From: johann Date: Wed, 2 Sep 2009 16:53:26 +0000 (+0000) Subject: Branch HEAD X-Git-Tag: v1_9_260~35 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=ba348dcdec078fdfda68e440023598355ebdd5f2;p=fs%2Flustre-release.git Branch HEAD b=20231 i=bzzz i=dmitry Take i_alloc_sem in filter_destroy() to prevent deadlock with writers. --- diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 11dcf00..13786ce 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -4090,18 +4090,28 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa, * down(i_zombie) down(i_zombie) * restart transaction * (see BUG 4180) -bzzz + * + * take i_alloc_sem too to prevent other threads from writing to the + * file while we are truncating it. This can cause lock ordering issue + * between page lock, i_mutex & starting new journal handle. + * (see bug 20321) -johann */ + down_write(&dchild->d_inode->i_alloc_sem); LOCK_INODE_MUTEX(dchild->d_inode); /* VBR: version recovery check */ rc = filter_version_get_check(exp, oti, dchild->d_inode); - if (rc) + if (rc) { + UNLOCK_INODE_MUTEX(dchild->d_inode); + up_write(&dchild->d_inode->i_alloc_sem); GOTO(cleanup, rc); + } handle = fsfilt_start_log(obd, dchild->d_inode, FSFILT_OP_SETATTR, NULL, 1); if (IS_ERR(handle)) { UNLOCK_INODE_MUTEX(dchild->d_inode); + up_write(&dchild->d_inode->i_alloc_sem); GOTO(cleanup, rc = PTR_ERR(handle)); } @@ -4110,6 +4120,7 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa, rc = fsfilt_setattr(obd, dchild, handle, &iattr, 1); rc2 = fsfilt_commit(obd, dchild->d_inode, handle, 0); UNLOCK_INODE_MUTEX(dchild->d_inode); + up_write(&dchild->d_inode->i_alloc_sem); if (rc) GOTO(cleanup, rc); if (rc2) diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index d546f5b..2621f3f 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -752,7 +752,7 @@ cleanup: * lnb->page automatically returns back into per-thread page * pool (bug 5137) */ - f_dput(res->dentry); + break; } /* trigger quota pre-acquire */ @@ -781,6 +781,7 @@ cleanup: page_cache_release(lnb->page); lnb->page = NULL; } + f_dput(res->dentry); if (inode && (fo->fo_writethrough_cache == 0 || i_size_read(inode) > fo->fo_readcache_max_filesize))