From: zam Date: Wed, 4 Mar 2009 18:11:29 +0000 (+0000) Subject: Branch b1_8 X-Git-Tag: v1_8_0_110~218 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=1241d35e697068f83348c8cbaefe20e52d712abf;p=fs%2Flustre-release.git Branch b1_8 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. --- diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 6d4e6cc..851f1ba 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -2728,7 +2728,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; @@ -2751,12 +2751,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 */ @@ -2853,16 +2856,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 1e6d8ac..901e60e 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -727,6 +727,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++) { @@ -817,6 +825,7 @@ cleanup: } } filter_grant_commit(exp, *pages, res); + up_read(&dentry->d_inode->i_alloc_sem); } case 3: filter_iobuf_put(&obd->u.filter, iobuf, oti); diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index 776e43f..243610e 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -782,5 +782,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); }