From e7b792f99c71f9cde625978d45cee2147ecd16d8 Mon Sep 17 00:00:00 2001 From: zam Date: Wed, 4 Mar 2009 18:43:19 +0000 Subject: [PATCH] Branch b_release_1_8_0 b=17397 i=alexey.zhuravlev i=andrew.perepechko To avoid a deadlock in case of concurrent punch/write requests from one client, filter writes and filter truncates are serialized by i_alloc_sem, allowing multiple writes or single truncate. --- lustre/obdfilter/filter.c | 21 ++++++++++----------- lustre/obdfilter/filter_io.c | 9 +++++++++ lustre/obdfilter/filter_io_26.c | 2 ++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index facf13a..4e235a1 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -2720,7 +2720,7 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, unsigned int orig_ids[MAXQUOTAS] = {0, 0}; struct llog_cookie *fcc = NULL; struct filter_obd *filter; - int rc, err, locked = 0, sync = 0; + int rc, err, sync = 0; loff_t old_size = 0; unsigned int ia_valid; struct inode *inode; @@ -2743,12 +2743,15 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, if (fcc != NULL) *fcc = oa->o_lcookie; } - - if (ia_valid & ATTR_SIZE || ia_valid & (ATTR_UID | ATTR_GID)) { + if (ia_valid & (ATTR_SIZE | ATTR_UID | ATTR_GID)) { DQUOT_INIT(inode); + /* Filter truncates and writes are serialized by + * i_alloc_sem, see the comment in + * filter_preprw_write.*/ + if (ia_valid & ATTR_SIZE) + down_write(&inode->i_alloc_sem); LOCK_INODE_MUTEX(inode); old_size = i_size_read(inode); - locked = 1; } /* VBR: version recovery check */ @@ -2845,16 +2848,12 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, rc = err; } - if (locked) { - UNLOCK_INODE_MUTEX(inode); - locked = 0; - } - EXIT; out_unlock: - if (locked) + if (ia_valid & (ATTR_SIZE | ATTR_UID | ATTR_GID)) UNLOCK_INODE_MUTEX(inode); - + if (ia_valid & ATTR_SIZE) + up_write(&inode->i_alloc_sem); if (fcc) OBD_FREE(fcc, sizeof(*fcc)); diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c index c61f100..eeb8c7c 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -707,6 +707,14 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa, GOTO(cleanup, rc); cleanup_phase = 4; + /* Filter truncate first locks i_mutex then partally truncated + * page, filter write code first locks pages then take + * i_mutex. To avoid a deadlock in case of concurrent + * punch/write requests from one client, filter writes and + * filter truncates are serialized by i_alloc_sem, allowing + * multiple writes or single truncate. */ + down_read(&dentry->d_inode->i_alloc_sem); + do_gettimeofday(&start); for (i = 0, lnb = res; i < *pages; i++, lnb++) { @@ -797,6 +805,7 @@ cleanup: } } filter_grant_commit(exp, *pages, res); + up_read(&dentry->d_inode->i_alloc_sem); } case 3: filter_iobuf_put(&exp->exp_obd->u.filter, iobuf, oti); diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index 2689ae7..aad4451 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -767,5 +767,7 @@ cleanup: i_size_read(inode) > fo->fo_readcache_max_filesize)) filter_invalidate_cache(obd, obj, nb, inode); + up_read(&inode->i_alloc_sem); + RETURN(rc); } -- 1.8.3.1