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