From f8e0db25678089f367facf14845e319e5841d41c Mon Sep 17 00:00:00 2001 From: shadow <shadow> Date: Thu, 17 May 2007 16:41:49 +0000 Subject: [PATCH] size of struct ll_inode_info is to big for union inode.u and can be cause of random memory corruption with 2.4 kernel. b=12134 i=wangdi i=green --- lustre/ChangeLog | 7 +++++++ lustre/llite/file.c | 20 ++++++++++---------- lustre/llite/llite_close.c | 15 +++++++++++++-- lustre/llite/llite_internal.h | 24 ++++++++++++++++++------ lustre/llite/llite_lib.c | 9 +++++---- lustre/llite/rw.c | 4 ++-- lustre/llite/symlink.c | 8 ++++---- 7 files changed, 59 insertions(+), 28 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 5760b930c2..9f4148da1a 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -145,6 +145,13 @@ Bugzilla : 11647 Description: update patchless client Details : Add support for patchless client with 2.6.20, 2.6.21 and RHEL 5 +Severity : normal +Frequency : only with 2.4 kernel +Bugzilla : 12134 +Description: random memory corruption +Details : size of struct ll_inode_info is to big for union inode.u and this + can be cause of random memory corruption. + -------------------------------------------------------------------------------- 2007-05-03 Cluster File Systems, Inc. <info@clusterfs.com> diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 45a74f3771..d4a4e48cd5 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -81,7 +81,7 @@ static int ll_close_inode_openhandle(struct inode *inode, OBD_MD_FLSIZE | OBD_MD_FLBLOCKS | OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME); - if (0 /* ll_is_inode_dirty(inode) */) { + if (ll_is_inode_dirty(inode)) { oa->o_flags = MDS_BFLAG_UNCOMMITTED_WRITES; oa->o_valid |= OBD_MD_FLFLAGS; } @@ -90,7 +90,7 @@ static int ll_close_inode_openhandle(struct inode *inode, if (rc == EAGAIN) { /* We are the last writer, so the MDS has instructed us to get * the file size and any write cookies, then close again. */ - //ll_queue_done_writing(inode); + ll_queue_done_writing(inode); rc = 0; } else if (rc) { CERROR("inode %lu mdc close failed: rc = %d\n", @@ -812,7 +812,7 @@ static int ll_extent_lock_callback(struct ldlm_lock *lock, lsm->lsm_oinfo[stripe]->loi_kms = kms; unlock_res_and_lock(lock); lov_stripe_unlock(lsm); - //ll_try_done_writing(inode); + ll_try_done_writing(inode); iput: iput(inode); break; @@ -857,16 +857,16 @@ int ll_async_completion_ast(struct ldlm_lock *lock, int flags, void *data) lvb = lock->l_lvb_data; lsm->lsm_oinfo[stripe].loi_rss = lvb->lvb_size; - LOCK_INODE_MUTEX(inode); lock_res_and_lock(lock); + ll_inode_size_lock(inode, 1); kms = MAX(lsm->lsm_oinfo[stripe].loi_kms, lvb->lvb_size); kms = ldlm_extent_shift_kms(NULL, kms); if (lsm->lsm_oinfo[stripe].loi_kms != kms) LDLM_DEBUG(lock, "updating kms from "LPU64" to "LPU64, lsm->lsm_oinfo[stripe].loi_kms, kms); lsm->lsm_oinfo[stripe].loi_kms = kms; + ll_inode_size_unlock(inode, 1); unlock_res_and_lock(lock); - UNLOCK_INODE_MUTEX(inode); } iput: @@ -1534,7 +1534,7 @@ static int ll_lov_recreate_obj(struct inode *inode, struct file *file, if (oa == NULL) RETURN(-ENOMEM); - down(&lli->lli_open_sem); + down(&lli->lli_size_sem); lsm = lli->lli_smd; if (lsm == NULL) GOTO(out, rc = -ENOENT); @@ -1559,7 +1559,7 @@ static int ll_lov_recreate_obj(struct inode *inode, struct file *file, OBD_FREE(lsm2, lsm_size); GOTO(out, rc); out: - up(&lli->lli_open_sem); + up(&lli->lli_size_sem); obdo_free(oa); return rc; } @@ -1574,10 +1574,10 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, int rc = 0; ENTRY; - down(&lli->lli_open_sem); + down(&lli->lli_size_sem); lsm = lli->lli_smd; if (lsm) { - up(&lli->lli_open_sem); + up(&lli->lli_size_sem); CDEBUG(D_IOCTL, "stripe already exists for ino %lu\n", inode->i_ino); RETURN(-EEXIST); @@ -1595,7 +1595,7 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, ll_release_openhandle(file->f_dentry, &oit); out: - up(&lli->lli_open_sem); + up(&lli->lli_size_sem); ll_intent_release(&oit); RETURN(rc); out_req_free: diff --git a/lustre/llite/llite_close.c b/lustre/llite/llite_close.c index f310bf1362..aa392f3368 100644 --- a/lustre/llite/llite_close.c +++ b/lustre/llite/llite_close.c @@ -28,6 +28,7 @@ #include <lustre_lite.h> #include "llite_internal.h" +#ifdef HAVE_CLOSE_THREAD /* record that a write is in flight */ void llap_write_pending(struct inode *inode, struct ll_async_page *llap) { @@ -107,7 +108,6 @@ void ll_queue_done_writing(struct inode *inode) EXIT; } -#if 0 /* If we know the file size and have the cookies: * - send a DONE_WRITING rpc * @@ -169,7 +169,7 @@ static void ll_close_done_writing(struct inode *inode) rc = mdc_done_writing(ll_i2sbi(inode)->ll_mdc_exp, &obdo); out: } -#endif + static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) { @@ -188,6 +188,15 @@ static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) spin_unlock(&lcq->lcq_lock); return lli; } +#else +static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) +{ + if (lcq->lcq_list.next == NULL) + return ERR_PTR(-1); + + return NULL; +} +#endif static int ll_close_thread(void *arg) { @@ -255,3 +264,5 @@ void ll_close_thread_shutdown(struct ll_close_queue *lcq) wait_for_completion(&lcq->lcq_comp); OBD_FREE(lcq, sizeof(*lcq)); } + + diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 9303e96d44..07e5646c64 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -68,9 +68,8 @@ extern struct file_operations ll_pgcache_seq_fops; struct ll_inode_info { int lli_inode_magic; - struct semaphore lli_size_sem; + struct semaphore lli_size_sem; /* protect open and change size */ void *lli_size_sem_owner; - struct semaphore lli_open_sem; struct semaphore lli_write_sem; struct lov_stripe_md *lli_smd; char *lli_symlink_name; @@ -80,12 +79,13 @@ struct ll_inode_info { /* this lock protects s_d_w and p_w_ll and mmap_cnt */ spinlock_t lli_lock; +#ifdef HAVE_CLOSE_THREAD struct list_head lli_pending_write_llaps; + struct list_head lli_close_item; int lli_send_done_writing; +#endif atomic_t lli_mmap_cnt; - struct list_head lli_close_item; - /* for writepage() only to communicate to fsync */ int lli_async_rc; @@ -127,6 +127,7 @@ static inline struct ll_inode_info *ll_i2info(struct inode *inode) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) return container_of(inode, struct ll_inode_info, lli_vfs_inode); #else + CLASSERT(sizeof(inode->u) >= sizeof(struct ll_inode_info)); return (struct ll_inode_info *)&(inode->u.generic_ip); #endif } @@ -452,7 +453,6 @@ extern struct inode_operations ll_dir_inode_operations; int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir); struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *lic); -struct dentry *ll_find_alias(struct inode *, struct dentry *); int ll_mdc_cancel_unused(struct lustre_handle *, struct inode *, int flags, void *opaque); int ll_mdc_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, @@ -475,7 +475,6 @@ int llap_shrink_cache(struct ll_sb_info *sbi, int shrink_fraction); extern struct cache_definition ll_cache_definition; void ll_removepage(struct page *page); int ll_readpage(struct file *file, struct page *page); -struct ll_async_page *llap_from_cookie(void *cookie); struct ll_async_page *llap_cast_private(struct page *page); void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); void ll_ra_accounting(struct ll_async_page *llap,struct address_space *mapping); @@ -607,12 +606,25 @@ struct ll_close_queue { struct completion lcq_comp; }; +#ifdef HAVE_CLOSE_THREAD void llap_write_pending(struct inode *inode, struct ll_async_page *llap); void llap_write_complete(struct inode *inode, struct ll_async_page *llap); void ll_open_complete(struct inode *inode); int ll_is_inode_dirty(struct inode *inode); void ll_try_done_writing(struct inode *inode); void ll_queue_done_writing(struct inode *inode); +#else +static inline void llap_write_pending(struct inode *inode, + struct ll_async_page *llap) { return; }; +static inline void llap_write_complete(struct inode *inode, + struct ll_async_page *llap) { return; }; +static inline void ll_open_complete(struct inode *inode) { return; }; +static inline int ll_is_inode_dirty(struct inode *inode) { return 0; }; +static inline void ll_try_done_writing(struct inode *inode) { return; }; +static inline void ll_queue_done_writing(struct inode *inode) { return; }; +//static inline void ll_close_thread_shutdown(struct ll_close_queue *lcq) { return; }; +//static inline int ll_close_thread_start(struct ll_close_queue **lcq_ret) { return 0; }; +#endif void ll_close_thread_shutdown(struct ll_close_queue *lcq); int ll_close_thread_start(struct ll_close_queue **lcq_ret); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 0671d57207..70ac74853c 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -677,23 +677,24 @@ next: } RETURN(0); } - + void ll_lli_init(struct ll_inode_info *lli) { - sema_init(&lli->lli_open_sem, 1); + lli->lli_inode_magic = LLI_INODE_MAGIC; sema_init(&lli->lli_size_sem, 1); sema_init(&lli->lli_write_sem, 1); lli->lli_flags = 0; lli->lli_maxbytes = PAGE_CACHE_MAXBYTES; spin_lock_init(&lli->lli_lock); - INIT_LIST_HEAD(&lli->lli_pending_write_llaps); - lli->lli_inode_magic = LLI_INODE_MAGIC; sema_init(&lli->lli_och_sem, 1); lli->lli_mds_read_och = lli->lli_mds_write_och = NULL; lli->lli_mds_exec_och = NULL; lli->lli_open_fd_read_count = lli->lli_open_fd_write_count = 0; lli->lli_open_fd_exec_count = 0; INIT_LIST_HEAD(&lli->lli_dead_list); +#ifdef HAVE_CLOSE_THREAD + INIT_LIST_HEAD(&lli->lli_pending_write_llaps); +#endif } /* COMPAT_146 */ diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index aefff58c8b..ca8e6b3f04 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -665,7 +665,7 @@ static int queue_or_sync_write(struct obd_export *exp, struct inode *inode, 0, 0, 0, async_flags); if (rc == 0) { LL_CDEBUG_PAGE(D_PAGE, llap->llap_page, "write queued\n"); - //llap_write_pending(inode, llap); + llap_write_pending(inode, llap); GOTO(out, 0); } @@ -870,7 +870,7 @@ int ll_ap_completion(void *data, int cmd, struct obdo *oa, int rc) unlock_page(page); - if (0 && cmd & OBD_BRW_WRITE) { + if (cmd & OBD_BRW_WRITE) { llap_write_complete(page->mapping->host, llap); ll_try_done_writing(page->mapping->host); } diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 683f36f3ce..09a2471b2e 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -110,7 +110,7 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) CDEBUG(D_VFSTRACE, "VFS Op\n"); /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */ - down(&lli->lli_open_sem); + down(&lli->lli_size_sem); rc = ll_readlink_internal(inode, &request, &symname); if (rc) GOTO(out, rc); @@ -118,7 +118,7 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) rc = vfs_readlink(dentry, buffer, buflen, symname); ptlrpc_req_finished(request); out: - up(&lli->lli_open_sem); + up(&lli->lli_size_sem); RETURN(rc); } @@ -152,9 +152,9 @@ static LL_FOLLOW_LINK_RETURN_TYPE ll_follow_link(struct dentry *dentry, struct n #endif CDEBUG(D_VFSTRACE, "VFS Op\n"); - down(&lli->lli_open_sem); + down(&lli->lli_size_sem); rc = ll_readlink_internal(inode, &request, &symname); - up(&lli->lli_open_sem); + up(&lli->lli_size_sem); if (rc) { path_release(nd); /* Kernel assumes that ->follow_link() releases nameidata on error */ -- GitLab