From 29a41f00c50b1c85731e341a8d2c49120c36de22 Mon Sep 17 00:00:00 2001 From: anserper Date: Mon, 17 Aug 2009 18:43:23 +0000 Subject: [PATCH] b=20008 i=Oleg Drokin i=Alex Tomas pin the last page before starting transaction in setattr to avoid GFP_FS allocation under transaction --- lustre/obdfilter/filter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index a880872..11dcf00 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -3209,6 +3209,7 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, loff_t old_size = 0; unsigned int ia_valid; struct inode *inode; + struct page *page = NULL; struct iattr iattr; void *handle; ENTRY; @@ -3244,6 +3245,17 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, if (rc) GOTO(out_unlock, rc); + /* Let's pin the last page so that ldiskfs_truncate + * should not start GFP_FS allocation. */ + if (ia_valid & ATTR_SIZE) { + page = grab_cache_page(inode->i_mapping, + iattr.ia_size >> PAGE_CACHE_SHIFT); + if (page == NULL) + GOTO(out_unlock, rc = -ENOMEM); + + unlock_page(page); + } + /* If the inode still has SUID+SGID bits set (see filter_precreate()) * then we will accept the UID+GID sent by the client during write for * initializing the ownership of this inode. We only allow this to @@ -3332,7 +3344,11 @@ int filter_setattr_internal(struct obd_export *exp, struct dentry *dentry, } EXIT; + out_unlock: + if (page) + page_cache_release(page); + if (ia_valid & (ATTR_SIZE | ATTR_UID | ATTR_GID)) UNLOCK_INODE_MUTEX(inode); if (ia_valid & ATTR_SIZE) -- 1.8.3.1