Whamcloud - gitweb
b=20008
[fs/lustre-release.git] / lustre / obdfilter / filter.c
index a880872..11dcf00 100644 (file)
@@ -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)