From 9ddcab098af8846682e52b1e4fecfc55412946df Mon Sep 17 00:00:00 2001 From: johann Date: Fri, 21 Aug 2009 15:42:44 +0000 Subject: [PATCH] Branch b1_8 b=20321 i=bzzz i=dmitry Take i_alloc_sem in filter_destroy() when truncating the object & fix inode mutex leak --- lustre/ChangeLog | 9 +++++---- lustre/obdfilter/filter.c | 13 ++++++++++++- lustre/obdfilter/filter_io_26.c | 3 ++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index c62a402..3d46722 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -23,14 +23,14 @@ Severity : normal Bugzilla : 19934 Description: correctly send lsm on open replay Details : MDS is trust to LSM size on replay open, but client can set wrong size - to lsm buffer. + to lsm buffer. Severity : normal Bugzilla : 20008 Description: truncate starts GFP_FS allocation under transaction causing deadlock Details : ldiskfs_truncate calls grab_cache_page which may start page - allocation under an open transaction. This may lead to - calling prune_icache with consequent lustre reentrance. + allocation under an open transaction. This may lead to + calling prune_icache with consequent lustre reentrance. Severity : enhancement Bugzilla : 20200 @@ -49,7 +49,8 @@ Description: Deadlock between filter_destroy() and filter_commitrw_write(). Details : filter_destroy() does not hold the DLM lock over the whole operation. If the DLM lock is dropped, filter_commitrw() can go through, causing the deadlock between page lock and i_mutex. - + The i_alloc_sem should also be hold in filter_destroy() while + truncating the file. Severity : enhancement Bugzilla : 18539 diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 9cdcb40..735901d 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -3605,18 +3605,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)); } @@ -3625,6 +3635,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 05c7053..6cd82ef 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -778,7 +778,7 @@ cleanup: * lnb->page automatically returns back into per-thread page * pool (bug 5137) */ - f_dput(res->dentry); + break; } /* trigger quota pre-acquire */ @@ -812,6 +812,7 @@ cleanup: filter_release_cache(obd, obj, nb, inode); up_read(&inode->i_alloc_sem); } + f_dput(res->dentry); RETURN(rc); } -- 1.8.3.1