Whamcloud - gitweb
Branch HEAD
authorbwzhou <bwzhou>
Mon, 17 Dec 2007 07:30:56 +0000 (07:30 +0000)
committerbwzhou <bwzhou>
Mon, 17 Dec 2007 07:30:56 +0000 (07:30 +0000)
b=14138
r=adilger, nikita

resolve deadlock on i_size_read() introduced by race condition of i_size_write();
Use old size assignment to avoid deadlock (bz14326).

lustre/llite/dir.c
lustre/llite/llite_lib.c
lustre/llite/llite_mmap.c

index 290ae72..ebea76c 100644 (file)
@@ -162,8 +162,11 @@ static int ll_dir_readpage(struct file *file, struct page *page)
                 /* Swabbed by mdc_readpage() */
                 LASSERT(lustre_rep_swabbed(request, REPLY_REC_OFF));
 
-                if (body->valid & OBD_MD_FLSIZE)
+                if (body->valid & OBD_MD_FLSIZE) {
+                        ll_inode_size_lock(inode, 0);
                         i_size_write(inode, body->size);
+                        ll_inode_size_unlock(inode, 0);
+                }
                 SetPageUptodate(page);
         }
         ptlrpc_req_finished(request);
index 77f615f..2f6fbab 100644 (file)
@@ -1696,13 +1696,17 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
                                                "the size got from MDS\n",
                                                inode->i_ino, lli->lli_flags);
                                 } else {
-                                        i_size_write(inode, body->size);
+                                        /* Use old size assignment to avoid
+                                         * deadlock bz14138 & bz14326 */
+                                        inode->i_size = body->size;
                                         lli->lli_flags |= LLIF_MDS_SIZE_LOCK;
                                 }
                                 ldlm_lock_decref(&lockh, mode);
                         }
                 } else {
-                        i_size_write(inode, body->size);
+                        /* Use old size assignment to avoid
+                         * deadlock bz14138 & bz14326 */
+                        inode->i_size = body->size;
                 }
 
                 if (body->valid & OBD_MD_FLBLOCKS)
index 025ad7b..7d2651b 100644 (file)
@@ -400,14 +400,20 @@ struct page *ll_nopage(struct vm_area_struct *vma, unsigned long address,
                 /* XXX change inode size without ll_inode_size_lock() held!
                  *     there is a race condition with truncate path. (see
                  *     ll_extent_lock) */
-               /* region is within kms and, hence, within real file size (A).
+                /* XXX i_size_write() is not used because it is not safe to
+                 *     take the ll_inode_size_lock() due to a potential lock
+                 *     inversion (bug 6077).  And since it's not safe to use
+                 *     i_size_write() without a covering mutex we do the
+                 *     assignment directly.  It is not critical that the
+                 *     size be correct. */
+                /* region is within kms and, hence, within real file size (A).
                  * We need to increase i_size to cover the read region so that
                  * generic_file_read() will do its job, but that doesn't mean
                  * the kms size is _correct_, it is only the _minimum_ size.
                  * If someone does a stat they will get the correct size which
                  * will always be >= the kms value here.  b=11081 */
                 if (i_size_read(inode) < kms) {
-                        i_size_write(inode, kms);
+                        inode->i_size = kms;
                         CDEBUG(D_INODE, "ino=%lu, updating i_size %llu\n",
                                inode->i_ino, i_size_read(inode));
                 }