From 66488cebc779518874605f6335e40af66a1fb1ba Mon Sep 17 00:00:00 2001 From: bwzhou <bwzhou> Date: Mon, 17 Dec 2007 07:30:56 +0000 Subject: [PATCH] Branch HEAD 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 | 5 ++++- lustre/llite/llite_lib.c | 8 ++++++-- lustre/llite/llite_mmap.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 290ae72e3e..ebea76c099 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 77f615f5e1..2f6fbabe1e 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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) diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 025ad7b8cc..7d2651b223 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -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)); } -- GitLab