Whamcloud - gitweb
b=19928
authorjxiong <jxiong>
Wed, 25 Nov 2009 01:05:36 +0000 (01:05 +0000)
committerjxiong <jxiong>
Wed, 25 Nov 2009 01:05:36 +0000 (01:05 +0000)
r=wangdi,ericm

A workaround fix for 19928 where we found that sometimes MDS takes much long time to finish setattr, which then causes clients can't take inode mutex on time after holding extent lock.

I just added ->lli_trunc_sem to make the above process atomic.

lustre/llite/llite_internal.h
lustre/llite/llite_lib.c

index 099c62c..543eff8 100644 (file)
@@ -121,6 +121,7 @@ struct ll_inode_info {
         struct semaphore        lli_size_sem;           /* protect open and change size */
         void                   *lli_size_sem_owner;
         struct semaphore        lli_write_sem;
+        struct semaphore        lli_trunc_sem;
         char                   *lli_symlink_name;
         __u64                   lli_maxbytes;
         __u64                   lli_ioepoch;
index 2ea9d2e..9b244da 100644 (file)
@@ -862,6 +862,7 @@ void ll_lli_init(struct ll_inode_info *lli)
         lli->lli_inode_magic = LLI_INODE_MAGIC;
         sema_init(&lli->lli_size_sem, 1);
         sema_init(&lli->lli_write_sem, 1);
+        sema_init(&lli->lli_trunc_sem, 1);
         lli->lli_flags = 0;
         lli->lli_maxbytes = PAGE_CACHE_MAXBYTES;
         spin_lock_init(&lli->lli_lock);
@@ -1324,6 +1325,14 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
         if (op_data == NULL)
                 RETURN(-ENOMEM);
 
+        UNLOCK_INODE_MUTEX(inode);
+        if (ia_valid & ATTR_SIZE)
+                UP_WRITE_I_ALLOC_SEM(inode);
+        down(&lli->lli_trunc_sem);
+        LOCK_INODE_MUTEX(inode);
+        if (ia_valid & ATTR_SIZE)
+                DOWN_WRITE_I_ALLOC_SEM(inode);
+
         memcpy(&op_data->op_attr, attr, sizeof(*attr));
 
         /* Open epoch for truncate. */
@@ -1355,6 +1364,7 @@ out:
                         rc1 = ll_setattr_done_writing(inode, op_data, mod);
                 ll_finish_md_op_data(op_data);
         }
+        up(&lli->lli_trunc_sem);
         return rc ? rc : rc1;
 }