aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2010-06-04 05:30:02 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-09 16:47:37 -0400
commit1025774ce411f2bd4b059ad7b53f0003569b74fa (patch)
tree2be221c205cb5579652a6063e8ee27d1c72d1bbd /fs
parenteef2380c187890816b73b1a4cb89a09203759469 (diff)
remove inode_setattr
Replace inode_setattr with opencoded variants of it in all callers. This moves the remaining call to vmtruncate into the filesystem methods where it can be replaced with the proper truncate sequence. In a few cases it was obvious that we would never end up calling vmtruncate so it was left out in the opencoded variant: spufs: explicitly checks for ATTR_SIZE earlier btrfs,hugetlbfs,logfs,dlmfs: explicitly clears ATTR_SIZE earlier ufs: contains an opencoded simple_seattr + truncate that sets the filesize just above In addition to that ncpfs called inode_setattr with handcrafted iattrs, which allowed to trim down the opencoded variant. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_inode.c15
-rw-r--r--fs/affs/inode.c13
-rw-r--r--fs/attr.c25
-rw-r--r--fs/btrfs/inode.c12
-rw-r--r--fs/cifs/inode.c45
-rw-r--r--fs/exofs/inode.c14
-rw-r--r--fs/ext3/inode.c12
-rw-r--r--fs/ext4/inode.c16
-rw-r--r--fs/gfs2/inode.c25
-rw-r--r--fs/gfs2/ops_inode.c12
-rw-r--r--fs/gfs2/xattr.c24
-rw-r--r--fs/hfs/inode.c12
-rw-r--r--fs/hfsplus/inode.c12
-rw-r--r--fs/hostfs/hostfs_kern.c18
-rw-r--r--fs/hpfs/inode.c12
-rw-r--r--fs/hugetlbfs/inode.c17
-rw-r--r--fs/jfs/file.c14
-rw-r--r--fs/logfs/file.c18
-rw-r--r--fs/minix/file.c12
-rw-r--r--fs/ncpfs/inode.c24
-rw-r--r--fs/nilfs2/inode.c25
-rw-r--r--fs/ntfs/inode.c3
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c8
-rw-r--r--fs/ocfs2/file.c16
-rw-r--r--fs/omfs/file.c12
-rw-r--r--fs/proc/base.c16
-rw-r--r--fs/proc/generic.c18
-rw-r--r--fs/proc/proc_sysctl.c15
-rw-r--r--fs/reiserfs/inode.c97
-rw-r--r--fs/sysv/file.c12
-rw-r--r--fs/udf/file.c12
-rw-r--r--fs/ufs/truncate.c5
32 files changed, 403 insertions, 188 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 4331b3b5ee1c..4b3ad6ac9a41 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -896,10 +896,19 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
896 } 896 }
897 897
898 retval = p9_client_wstat(fid, &wstat); 898 retval = p9_client_wstat(fid, &wstat);
899 if (retval >= 0) 899 if (retval < 0)
900 retval = inode_setattr(dentry->d_inode, iattr); 900 return retval;
901
902 if ((iattr->ia_valid & ATTR_SIZE) &&
903 iattr->ia_size != i_size_read(dentry->d_inode)) {
904 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
905 if (retval)
906 return retval;
907 }
901 908
902 return retval; 909 setattr_copy(dentry->d_inode, iattr);
910 mark_inode_dirty(dentry->d_inode);
911 return 0;
903} 912}
904 913
905/** 914/**
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index f4b2a4ee4f91..6883d5fb84cf 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -235,8 +235,17 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
235 goto out; 235 goto out;
236 } 236 }
237 237
238 error = inode_setattr(inode, attr); 238 if ((attr->ia_valid & ATTR_SIZE) &&
239 if (!error && (attr->ia_valid & ATTR_MODE)) 239 attr->ia_size != i_size_read(inode)) {
240 error = vmtruncate(inode, attr->ia_size);
241 if (error)
242 return error;
243 }
244
245 setattr_copy(inode, attr);
246 mark_inode_dirty(inode);
247
248 if (attr->ia_valid & ATTR_MODE)
240 mode_to_prot(inode); 249 mode_to_prot(inode);
241out: 250out:
242 return error; 251 return error;
diff --git a/fs/attr.c b/fs/attr.c
index aeac826f4774..ed44d8ae8bf1 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -146,31 +146,6 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
146} 146}
147EXPORT_SYMBOL(setattr_copy); 147EXPORT_SYMBOL(setattr_copy);
148 148
149/*
150 * note this function is deprecated, the new truncate sequence should be
151 * used instead -- see eg. simple_setsize, setattr_copy.
152 */
153int inode_setattr(struct inode *inode, const struct iattr *attr)
154{
155 unsigned int ia_valid = attr->ia_valid;
156
157 if (ia_valid & ATTR_SIZE &&
158 attr->ia_size != i_size_read(inode)) {
159 int error;
160
161 error = vmtruncate(inode, attr->ia_size);
162 if (error)
163 return error;
164 }
165
166 setattr_copy(inode, attr);
167
168 mark_inode_dirty(inode);
169
170 return 0;
171}
172EXPORT_SYMBOL(inode_setattr);
173
174int notify_change(struct dentry * dentry, struct iattr * attr) 149int notify_change(struct dentry * dentry, struct iattr * attr)
175{ 150{
176 struct inode *inode = dentry->d_inode; 151 struct inode *inode = dentry->d_inode;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 1bff92ad4744..7f9e0536db1a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3656,13 +3656,15 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
3656 if (err) 3656 if (err)
3657 return err; 3657 return err;
3658 } 3658 }
3659 attr->ia_valid &= ~ATTR_SIZE;
3660 3659
3661 if (attr->ia_valid) 3660 if (attr->ia_valid) {
3662 err = inode_setattr(inode, attr); 3661 setattr_copy(inode, attr);
3662 mark_inode_dirty(inode);
3663
3664 if (attr->ia_valid & ATTR_MODE)
3665 err = btrfs_acl_chmod(inode);
3666 }
3663 3667
3664 if (!err && ((attr->ia_valid & ATTR_MODE)))
3665 err = btrfs_acl_chmod(inode);
3666 return err; 3668 return err;
3667} 3669}
3668 3670
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a15b3a9bbff4..9c6a40f5cc57 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1889,18 +1889,27 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1889 CIFS_MOUNT_MAP_SPECIAL_CHR); 1889 CIFS_MOUNT_MAP_SPECIAL_CHR);
1890 } 1890 }
1891 1891
1892 if (!rc) { 1892 if (rc)
1893 rc = inode_setattr(inode, attrs); 1893 goto out;
1894 1894
1895 /* force revalidate when any of these times are set since some 1895 if ((attrs->ia_valid & ATTR_SIZE) &&
1896 of the fs types (eg ext3, fat) do not have fine enough 1896 attrs->ia_size != i_size_read(inode)) {
1897 time granularity to match protocol, and we do not have a 1897 rc = vmtruncate(inode, attrs->ia_size);
1898 a way (yet) to query the server fs's time granularity (and 1898 if (rc)
1899 whether it rounds times down). 1899 goto out;
1900 */
1901 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
1902 cifsInode->time = 0;
1903 } 1900 }
1901
1902 setattr_copy(inode, attrs);
1903 mark_inode_dirty(inode);
1904
1905 /* force revalidate when any of these times are set since some
1906 of the fs types (eg ext3, fat) do not have fine enough
1907 time granularity to match protocol, and we do not have a
1908 a way (yet) to query the server fs's time granularity (and
1909 whether it rounds times down).
1910 */
1911 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
1912 cifsInode->time = 0;
1904out: 1913out:
1905 kfree(args); 1914 kfree(args);
1906 kfree(full_path); 1915 kfree(full_path);
@@ -2040,8 +2049,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
2040 2049
2041 /* do not need local check to inode_check_ok since the server does 2050 /* do not need local check to inode_check_ok since the server does
2042 that */ 2051 that */
2043 if (!rc) 2052 if (rc)
2044 rc = inode_setattr(inode, attrs); 2053 goto cifs_setattr_exit;
2054
2055 if ((attrs->ia_valid & ATTR_SIZE) &&
2056 attrs->ia_size != i_size_read(inode)) {
2057 rc = vmtruncate(inode, attrs->ia_size);
2058 if (rc)
2059 goto cifs_setattr_exit;
2060 }
2061
2062 setattr_copy(inode, attrs);
2063 mark_inode_dirty(inode);
2064 return 0;
2065
2045cifs_setattr_exit: 2066cifs_setattr_exit:
2046 kfree(full_path); 2067 kfree(full_path);
2047 FreeXid(xid); 2068 FreeXid(xid);
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 4bb6ef822e46..4bfc1f4fd013 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -887,8 +887,18 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
887 if (error) 887 if (error)
888 return error; 888 return error;
889 889
890 error = inode_setattr(inode, iattr); 890 if ((iattr->ia_valid & ATTR_SIZE) &&
891 return error; 891 iattr->ia_size != i_size_read(inode)) {
892 int error;
893
894 error = vmtruncate(inode, iattr->ia_size);
895 if (error)
896 return error;
897 }
898
899 setattr_copy(inode, iattr);
900 mark_inode_dirty(inode);
901 return 0;
892} 902}
893 903
894static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( 904static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF(
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 5c6f07eefa4a..b04d11936683 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -3208,9 +3208,17 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
3208 ext3_journal_stop(handle); 3208 ext3_journal_stop(handle);
3209 } 3209 }
3210 3210
3211 rc = inode_setattr(inode, attr); 3211 if ((attr->ia_valid & ATTR_SIZE) &&
3212 attr->ia_size != i_size_read(inode)) {
3213 rc = vmtruncate(inode, attr->ia_size);
3214 if (rc)
3215 goto err_out;
3216 }
3217
3218 setattr_copy(inode, attr);
3219 mark_inode_dirty(inode);
3212 3220
3213 if (!rc && (ia_valid & ATTR_MODE)) 3221 if (ia_valid & ATTR_MODE)
3214 rc = ext3_acl_chmod(inode); 3222 rc = ext3_acl_chmod(inode);
3215 3223
3216err_out: 3224err_out:
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3da3c9646e5e..1fb390359bc5 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5539,11 +5539,19 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
5539 ext4_truncate(inode); 5539 ext4_truncate(inode);
5540 } 5540 }
5541 5541
5542 rc = inode_setattr(inode, attr); 5542 if ((attr->ia_valid & ATTR_SIZE) &&
5543 attr->ia_size != i_size_read(inode))
5544 rc = vmtruncate(inode, attr->ia_size);
5543 5545
5544 /* If inode_setattr's call to ext4_truncate failed to get a 5546 if (!rc) {
5545 * transaction handle at all, we need to clean up the in-core 5547 setattr_copy(inode, attr);
5546 * orphan list manually. */ 5548 mark_inode_dirty(inode);
5549 }
5550
5551 /*
5552 * If the call to ext4_truncate failed to get a transaction handle at
5553 * all, we need to clean up the in-core orphan list manually.
5554 */
5547 if (inode->i_nlink) 5555 if (inode->i_nlink)
5548 ext4_orphan_del(NULL, inode); 5556 ext4_orphan_del(NULL, inode);
5549 5557
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index f03afd9c44bc..6c023a3b5d25 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -991,18 +991,29 @@ fail:
991 991
992static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) 992static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
993{ 993{
994 struct inode *inode = &ip->i_inode;
994 struct buffer_head *dibh; 995 struct buffer_head *dibh;
995 int error; 996 int error;
996 997
997 error = gfs2_meta_inode_buffer(ip, &dibh); 998 error = gfs2_meta_inode_buffer(ip, &dibh);
998 if (!error) { 999 if (error)
999 error = inode_setattr(&ip->i_inode, attr); 1000 return error;
1000 gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); 1001
1001 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 1002 if ((attr->ia_valid & ATTR_SIZE) &&
1002 gfs2_dinode_out(ip, dibh->b_data); 1003 attr->ia_size != i_size_read(inode)) {
1003 brelse(dibh); 1004 error = vmtruncate(inode, attr->ia_size);
1005 if (error)
1006 return error;
1004 } 1007 }
1005 return error; 1008
1009 setattr_copy(inode, attr);
1010 mark_inode_dirty(inode);
1011
1012 gfs2_assert_warn(GFS2_SB(inode), !error);
1013 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1014 gfs2_dinode_out(ip, dibh->b_data);
1015 brelse(dibh);
1016 return 0;
1006} 1017}
1007 1018
1008/** 1019/**
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 98cdd05f3316..d7d410a4ca42 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -1136,8 +1136,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
1136 if (error) 1136 if (error)
1137 goto out_end_trans; 1137 goto out_end_trans;
1138 1138
1139 error = inode_setattr(inode, attr); 1139 if ((attr->ia_valid & ATTR_SIZE) &&
1140 gfs2_assert_warn(sdp, !error); 1140 attr->ia_size != i_size_read(inode)) {
1141 int error;
1142
1143 error = vmtruncate(inode, attr->ia_size);
1144 gfs2_assert_warn(sdp, !error);
1145 }
1146
1147 setattr_copy(inode, attr);
1148 mark_inode_dirty(inode);
1141 1149
1142 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 1150 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1143 gfs2_dinode_out(ip, dibh->b_data); 1151 gfs2_dinode_out(ip, dibh->b_data);
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 82f93da00d1b..776af6eb4bcb 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -1296,6 +1296,7 @@ fail:
1296 1296
1297int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) 1297int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
1298{ 1298{
1299 struct inode *inode = &ip->i_inode;
1299 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1300 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1300 struct gfs2_ea_location el; 1301 struct gfs2_ea_location el;
1301 struct buffer_head *dibh; 1302 struct buffer_head *dibh;
@@ -1321,14 +1322,25 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
1321 return error; 1322 return error;
1322 1323
1323 error = gfs2_meta_inode_buffer(ip, &dibh); 1324 error = gfs2_meta_inode_buffer(ip, &dibh);
1324 if (!error) { 1325 if (error)
1325 error = inode_setattr(&ip->i_inode, attr); 1326 goto out_trans_end;
1326 gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); 1327
1327 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 1328 if ((attr->ia_valid & ATTR_SIZE) &&
1328 gfs2_dinode_out(ip, dibh->b_data); 1329 attr->ia_size != i_size_read(inode)) {
1329 brelse(dibh); 1330 int error;
1331
1332 error = vmtruncate(inode, attr->ia_size);
1333 gfs2_assert_warn(GFS2_SB(inode), !error);
1330 } 1334 }
1331 1335
1336 setattr_copy(inode, attr);
1337 mark_inode_dirty(inode);
1338
1339 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1340 gfs2_dinode_out(ip, dibh->b_data);
1341 brelse(dibh);
1342
1343out_trans_end:
1332 gfs2_trans_end(sdp); 1344 gfs2_trans_end(sdp);
1333 return error; 1345 return error;
1334} 1346}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 8df18e63eb6b..87de671baa83 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -612,10 +612,16 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
612 attr->ia_mode = inode->i_mode & ~S_IWUGO; 612 attr->ia_mode = inode->i_mode & ~S_IWUGO;
613 attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask; 613 attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask;
614 } 614 }
615 error = inode_setattr(inode, attr);
616 if (error)
617 return error;
618 615
616 if ((attr->ia_valid & ATTR_SIZE) &&
617 attr->ia_size != i_size_read(inode)) {
618 error = vmtruncate(inode, attr->ia_size);
619 if (error)
620 return error;
621 }
622
623 setattr_copy(inode, attr);
624 mark_inode_dirty(inode);
619 return 0; 625 return 0;
620} 626}
621 627
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index d6ebe53fbdbf..654c5a8ddf1c 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -298,7 +298,17 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
298 error = inode_change_ok(inode, attr); 298 error = inode_change_ok(inode, attr);
299 if (error) 299 if (error)
300 return error; 300 return error;
301 return inode_setattr(inode, attr); 301
302 if ((attr->ia_valid & ATTR_SIZE) &&
303 attr->ia_size != i_size_read(inode)) {
304 error = vmtruncate(inode, attr->ia_size);
305 if (error)
306 return error;
307 }
308
309 setattr_copy(inode, attr);
310 mark_inode_dirty(inode);
311 return 0;
302} 312}
303 313
304static const struct inode_operations hfsplus_file_inode_operations = { 314static const struct inode_operations hfsplus_file_inode_operations = {
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 87ac1891a185..7943ff11d489 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -849,13 +849,14 @@ int hostfs_permission(struct inode *ino, int desired)
849 849
850int hostfs_setattr(struct dentry *dentry, struct iattr *attr) 850int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
851{ 851{
852 struct inode *inode = dentry->d_inode;
852 struct hostfs_iattr attrs; 853 struct hostfs_iattr attrs;
853 char *name; 854 char *name;
854 int err; 855 int err;
855 856
856 int fd = HOSTFS_I(dentry->d_inode)->fd; 857 int fd = HOSTFS_I(inode)->fd;
857 858
858 err = inode_change_ok(dentry->d_inode, attr); 859 err = inode_change_ok(inode, attr);
859 if (err) 860 if (err)
860 return err; 861 return err;
861 862
@@ -905,7 +906,18 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
905 if (err) 906 if (err)
906 return err; 907 return err;
907 908
908 return inode_setattr(dentry->d_inode, attr); 909 if ((attr->ia_valid & ATTR_SIZE) &&
910 attr->ia_size != i_size_read(inode)) {
911 int error;
912
913 error = vmtruncate(inode, attr->ia_size);
914 if (err)
915 return err;
916 }
917
918 setattr_copy(inode, attr);
919 mark_inode_dirty(inode);
920 return 0;
909} 921}
910 922
911static const struct inode_operations hostfs_iops = { 923static const struct inode_operations hostfs_iops = {
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 1042a9bc97f3..3f3b397fd4e6 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -277,9 +277,15 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
277 if (error) 277 if (error)
278 goto out_unlock; 278 goto out_unlock;
279 279
280 error = inode_setattr(inode, attr); 280 if ((attr->ia_valid & ATTR_SIZE) &&
281 if (error) 281 attr->ia_size != i_size_read(inode)) {
282 goto out_unlock; 282 error = vmtruncate(inode, attr->ia_size);
283 if (error)
284 return error;
285 }
286
287 setattr_copy(inode, attr);
288 mark_inode_dirty(inode);
283 289
284 hpfs_write_inode(inode); 290 hpfs_write_inode(inode);
285 291
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index a4e9a7ec3691..d5f019d48b09 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -448,19 +448,20 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
448 448
449 error = inode_change_ok(inode, attr); 449 error = inode_change_ok(inode, attr);
450 if (error) 450 if (error)
451 goto out; 451 return error;
452 452
453 if (ia_valid & ATTR_SIZE) { 453 if (ia_valid & ATTR_SIZE) {
454 error = -EINVAL; 454 error = -EINVAL;
455 if (!(attr->ia_size & ~huge_page_mask(h))) 455 if (attr->ia_size & ~huge_page_mask(h))
456 error = hugetlb_vmtruncate(inode, attr->ia_size); 456 return -EINVAL;
457 error = hugetlb_vmtruncate(inode, attr->ia_size);
457 if (error) 458 if (error)
458 goto out; 459 return error;
459 attr->ia_valid &= ~ATTR_SIZE;
460 } 460 }
461 error = inode_setattr(inode, attr); 461
462out: 462 setattr_copy(inode, attr);
463 return error; 463 mark_inode_dirty(inode);
464 return 0;
464} 465}
465 466
466static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, 467static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index 127263cc8657..c5ce6c1d1ff4 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -17,6 +17,7 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#include <linux/mm.h>
20#include <linux/fs.h> 21#include <linux/fs.h>
21#include <linux/quotaops.h> 22#include <linux/quotaops.h>
22#include "jfs_incore.h" 23#include "jfs_incore.h"
@@ -107,11 +108,18 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
107 return rc; 108 return rc;
108 } 109 }
109 110
110 rc = inode_setattr(inode, iattr); 111 if ((iattr->ia_valid & ATTR_SIZE) &&
112 iattr->ia_size != i_size_read(inode)) {
113 rc = vmtruncate(inode, iattr->ia_size);
114 if (rc)
115 return rc;
116 }
111 117
112 if (!rc && (iattr->ia_valid & ATTR_MODE)) 118 setattr_copy(inode, iattr);
113 rc = jfs_acl_chmod(inode); 119 mark_inode_dirty(inode);
114 120
121 if (iattr->ia_valid & ATTR_MODE)
122 rc = jfs_acl_chmod(inode);
115 return rc; 123 return rc;
116} 124}
117 125
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index abe1cafbd4c2..23b4d03bbd26 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -232,15 +232,19 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
232 struct inode *inode = dentry->d_inode; 232 struct inode *inode = dentry->d_inode;
233 int err = 0; 233 int err = 0;
234 234
235 if (attr->ia_valid & ATTR_SIZE) 235 if (attr->ia_valid & ATTR_SIZE) {
236 err = logfs_truncate(inode, attr->ia_size); 236 err = logfs_truncate(inode, attr->ia_size);
237 attr->ia_valid &= ~ATTR_SIZE; 237 if (err)
238 return err;
239 }
238 240
239 if (!err) 241 err = inode_change_ok(inode, attr);
240 err = inode_change_ok(inode, attr); 242 if (err)
241 if (!err) 243 return err;
242 err = inode_setattr(inode, attr); 244
243 return err; 245 setattr_copy(inode, attr);
246 mark_inode_dirty(inode);
247 return 0;
244} 248}
245 249
246const struct inode_operations logfs_reg_iops = { 250const struct inode_operations logfs_reg_iops = {
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 7a45dd1fe2e5..4493ce695ab8 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -31,7 +31,17 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
31 error = inode_change_ok(inode, attr); 31 error = inode_change_ok(inode, attr);
32 if (error) 32 if (error)
33 return error; 33 return error;
34 return inode_setattr(inode, attr); 34
35 if ((attr->ia_valid & ATTR_SIZE) &&
36 attr->ia_size != i_size_read(inode)) {
37 error = vmtruncate(inode, attr->ia_size);
38 if (error)
39 return error;
40 }
41
42 setattr_copy(inode, attr);
43 mark_inode_dirty(inode);
44 return 0;
35} 45}
36 46
37const struct inode_operations minix_file_inode_operations = { 47const struct inode_operations minix_file_inode_operations = {
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index fa3385154023..b4e8aaae14be 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -924,9 +924,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
924 tmpattr.ia_valid = ATTR_MODE; 924 tmpattr.ia_valid = ATTR_MODE;
925 tmpattr.ia_mode = attr->ia_mode; 925 tmpattr.ia_mode = attr->ia_mode;
926 926
927 result = inode_setattr(inode, &tmpattr); 927 setattr_copy(inode, &tmpattr);
928 if (result) 928 mark_inode_dirty(inode);
929 goto out;
930 } 929 }
931 } 930 }
932#endif 931#endif
@@ -954,15 +953,12 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
954 result = ncp_make_closed(inode); 953 result = ncp_make_closed(inode);
955 if (result) 954 if (result)
956 goto out; 955 goto out;
957 { 956
958 struct iattr tmpattr; 957 if (attr->ia_size != i_size_read(inode)) {
959 958 result = vmtruncate(inode, attr->ia_size);
960 tmpattr.ia_valid = ATTR_SIZE;
961 tmpattr.ia_size = attr->ia_size;
962
963 result = inode_setattr(inode, &tmpattr);
964 if (result) 959 if (result)
965 goto out; 960 goto out;
961 mark_inode_dirty(inode);
966 } 962 }
967 } 963 }
968 if ((attr->ia_valid & ATTR_CTIME) != 0) { 964 if ((attr->ia_valid & ATTR_CTIME) != 0) {
@@ -1002,8 +998,12 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
1002 NCP_FINFO(inode)->nwattr = info.attributes; 998 NCP_FINFO(inode)->nwattr = info.attributes;
1003#endif 999#endif
1004 } 1000 }
1005 if (!result) 1001 if (result)
1006 result = inode_setattr(inode, attr); 1002 goto out;
1003
1004 setattr_copy(inode, attr);
1005 mark_inode_dirty(inode);
1006
1007out: 1007out:
1008 unlock_kernel(); 1008 unlock_kernel();
1009 return result; 1009 return result;
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 5c694ece172e..051d279abb37 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -656,14 +656,27 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
656 err = nilfs_transaction_begin(sb, &ti, 0); 656 err = nilfs_transaction_begin(sb, &ti, 0);
657 if (unlikely(err)) 657 if (unlikely(err))
658 return err; 658 return err;
659 err = inode_setattr(inode, iattr); 659
660 if (!err && (iattr->ia_valid & ATTR_MODE)) 660 if ((iattr->ia_valid & ATTR_SIZE) &&
661 iattr->ia_size != i_size_read(inode)) {
662 err = vmtruncate(inode, iattr->ia_size);
663 if (unlikely(err))
664 goto out_err;
665 }
666
667 setattr_copy(inode, iattr);
668 mark_inode_dirty(inode);
669
670 if (iattr->ia_valid & ATTR_MODE) {
661 err = nilfs_acl_chmod(inode); 671 err = nilfs_acl_chmod(inode);
662 if (likely(!err)) 672 if (unlikely(err))
663 err = nilfs_transaction_commit(sb); 673 goto out_err;
664 else 674 }
665 nilfs_transaction_abort(sb); 675
676 return nilfs_transaction_commit(sb);
666 677
678out_err:
679 nilfs_transaction_abort(sb);
667 return err; 680 return err;
668} 681}
669 682
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 4b57fb1eac2a..fdef8f729c3a 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2879,9 +2879,6 @@ void ntfs_truncate_vfs(struct inode *vi) {
2879 * 2879 *
2880 * Called with ->i_mutex held. For the ATTR_SIZE (i.e. ->truncate) case, also 2880 * Called with ->i_mutex held. For the ATTR_SIZE (i.e. ->truncate) case, also
2881 * called with ->i_alloc_sem held for writing. 2881 * called with ->i_alloc_sem held for writing.
2882 *
2883 * Basically this is a copy of generic notify_change() and inode_setattr()
2884 * functionality, except we intercept and abort changes in i_size.
2885 */ 2882 */
2886int ntfs_setattr(struct dentry *dentry, struct iattr *attr) 2883int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
2887{ 2884{
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index b83d6107a1f5..85e4ccaedd1f 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -214,10 +214,12 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
214 214
215 attr->ia_valid &= ~ATTR_SIZE; 215 attr->ia_valid &= ~ATTR_SIZE;
216 error = inode_change_ok(inode, attr); 216 error = inode_change_ok(inode, attr);
217 if (!error) 217 if (error)
218 error = inode_setattr(inode, attr); 218 return error;
219 219
220 return error; 220 setattr_copy(inode, attr);
221 mark_inode_dirty(inode);
222 return 0;
221} 223}
222 224
223static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait) 225static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 2b10b36d1577..584cf8ac167a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1238,13 +1238,21 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
1238 * Otherwise, we could get into problems with truncate as 1238 * Otherwise, we could get into problems with truncate as
1239 * ip_alloc_sem is used there to protect against i_size 1239 * ip_alloc_sem is used there to protect against i_size
1240 * changes. 1240 * changes.
1241 *
1242 * XXX: this means the conditional below can probably be removed.
1241 */ 1243 */
1242 status = inode_setattr(inode, attr); 1244 if ((attr->ia_valid & ATTR_SIZE) &&
1243 if (status < 0) { 1245 attr->ia_size != i_size_read(inode)) {
1244 mlog_errno(status); 1246 status = vmtruncate(inode, attr->ia_size);
1245 goto bail_commit; 1247 if (status) {
1248 mlog_errno(status);
1249 goto bail_commit;
1250 }
1246 } 1251 }
1247 1252
1253 setattr_copy(inode, attr);
1254 mark_inode_dirty(inode);
1255
1248 status = ocfs2_mark_inode_dirty(handle, inode, bh); 1256 status = ocfs2_mark_inode_dirty(handle, inode, bh);
1249 if (status < 0) 1257 if (status < 0)
1250 mlog_errno(status); 1258 mlog_errno(status);
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 78c9f0c1a2f3..5542c284dc1c 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -349,7 +349,17 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
349 error = inode_change_ok(inode, attr); 349 error = inode_change_ok(inode, attr);
350 if (error) 350 if (error)
351 return error; 351 return error;
352 return inode_setattr(inode, attr); 352
353 if ((attr->ia_valid & ATTR_SIZE) &&
354 attr->ia_size != i_size_read(inode)) {
355 error = vmtruncate(inode, attr->ia_size);
356 if (error)
357 return error;
358 }
359
360 setattr_copy(inode, attr);
361 mark_inode_dirty(inode);
362 return 0;
353} 363}
354 364
355const struct inode_operations omfs_file_inops = { 365const struct inode_operations omfs_file_inops = {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index acb7ef80ea4f..a49d9dd06d1d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -561,9 +561,19 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr)
561 return -EPERM; 561 return -EPERM;
562 562
563 error = inode_change_ok(inode, attr); 563 error = inode_change_ok(inode, attr);
564 if (!error) 564 if (error)
565 error = inode_setattr(inode, attr); 565 return error;
566 return error; 566
567 if ((attr->ia_valid & ATTR_SIZE) &&
568 attr->ia_size != i_size_read(inode)) {
569 error = vmtruncate(inode, attr->ia_size);
570 if (error)
571 return error;
572 }
573
574 setattr_copy(inode, attr);
575 mark_inode_dirty(inode);
576 return 0;
567} 577}
568 578
569static const struct inode_operations proc_def_inode_operations = { 579static const struct inode_operations proc_def_inode_operations = {
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 2791907744ed..dd29f0337661 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -12,6 +12,7 @@
12#include <linux/time.h> 12#include <linux/time.h>
13#include <linux/proc_fs.h> 13#include <linux/proc_fs.h>
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/mm.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/mount.h> 18#include <linux/mount.h>
@@ -258,17 +259,22 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
258 259
259 error = inode_change_ok(inode, iattr); 260 error = inode_change_ok(inode, iattr);
260 if (error) 261 if (error)
261 goto out; 262 return error;
262 263
263 error = inode_setattr(inode, iattr); 264 if ((iattr->ia_valid & ATTR_SIZE) &&
264 if (error) 265 iattr->ia_size != i_size_read(inode)) {
265 goto out; 266 error = vmtruncate(inode, iattr->ia_size);
267 if (error)
268 return error;
269 }
270
271 setattr_copy(inode, iattr);
272 mark_inode_dirty(inode);
266 273
267 de->uid = inode->i_uid; 274 de->uid = inode->i_uid;
268 de->gid = inode->i_gid; 275 de->gid = inode->i_gid;
269 de->mode = inode->i_mode; 276 de->mode = inode->i_mode;
270out: 277 return 0;
271 return error;
272} 278}
273 279
274static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry, 280static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 6ff9981f0a18..5be436ea088e 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -329,10 +329,19 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
329 return -EPERM; 329 return -EPERM;
330 330
331 error = inode_change_ok(inode, attr); 331 error = inode_change_ok(inode, attr);
332 if (!error) 332 if (error)
333 error = inode_setattr(inode, attr); 333 return error;
334
335 if ((attr->ia_valid & ATTR_SIZE) &&
336 attr->ia_size != i_size_read(inode)) {
337 error = vmtruncate(inode, attr->ia_size);
338 if (error)
339 return error;
340 }
334 341
335 return error; 342 setattr_copy(inode, attr);
343 mark_inode_dirty(inode);
344 return 0;
336} 345}
337 346
338static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 347static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 045729f5674a..2b8dc5c22867 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -3134,55 +3134,62 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
3134 } 3134 }
3135 3135
3136 error = inode_change_ok(inode, attr); 3136 error = inode_change_ok(inode, attr);
3137 if (!error) { 3137 if (error)
3138 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 3138 goto out;
3139 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
3140 error = reiserfs_chown_xattrs(inode, attr);
3141 3139
3142 if (!error) { 3140 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
3143 struct reiserfs_transaction_handle th; 3141 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
3144 int jbegin_count = 3142 struct reiserfs_transaction_handle th;
3145 2 * 3143 int jbegin_count =
3146 (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + 3144 2 *
3147 REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + 3145 (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) +
3148 2; 3146 REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) +
3149 3147 2;
3150 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ 3148
3151 error = 3149 error = reiserfs_chown_xattrs(inode, attr);
3152 journal_begin(&th, inode->i_sb, 3150
3153 jbegin_count); 3151 if (error)
3154 if (error) 3152 return error;
3155 goto out; 3153
3156 error = dquot_transfer(inode, attr); 3154 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
3157 if (error) { 3155 error = journal_begin(&th, inode->i_sb, jbegin_count);
3158 journal_end(&th, inode->i_sb, 3156 if (error)
3159 jbegin_count); 3157 goto out;
3160 goto out; 3158 error = dquot_transfer(inode, attr);
3161 } 3159 if (error) {
3162 /* Update corresponding info in inode so that everything is in 3160 journal_end(&th, inode->i_sb, jbegin_count);
3163 * one transaction */ 3161 goto out;
3164 if (attr->ia_valid & ATTR_UID)
3165 inode->i_uid = attr->ia_uid;
3166 if (attr->ia_valid & ATTR_GID)
3167 inode->i_gid = attr->ia_gid;
3168 mark_inode_dirty(inode);
3169 error =
3170 journal_end(&th, inode->i_sb, jbegin_count);
3171 }
3172 }
3173 if (!error) {
3174 /*
3175 * Relax the lock here, as it might truncate the
3176 * inode pages and wait for inode pages locks.
3177 * To release such page lock, the owner needs the
3178 * reiserfs lock
3179 */
3180 reiserfs_write_unlock_once(inode->i_sb, depth);
3181 error = inode_setattr(inode, attr);
3182 depth = reiserfs_write_lock_once(inode->i_sb);
3183 } 3162 }
3163
3164 /* Update corresponding info in inode so that everything is in
3165 * one transaction */
3166 if (attr->ia_valid & ATTR_UID)
3167 inode->i_uid = attr->ia_uid;
3168 if (attr->ia_valid & ATTR_GID)
3169 inode->i_gid = attr->ia_gid;
3170 mark_inode_dirty(inode);
3171 error = journal_end(&th, inode->i_sb, jbegin_count);
3172 if (error)
3173 goto out;
3184 } 3174 }
3185 3175
3176 /*
3177 * Relax the lock here, as it might truncate the
3178 * inode pages and wait for inode pages locks.
3179 * To release such page lock, the owner needs the
3180 * reiserfs lock
3181 */
3182 reiserfs_write_unlock_once(inode->i_sb, depth);
3183 if ((attr->ia_valid & ATTR_SIZE) &&
3184 attr->ia_size != i_size_read(inode))
3185 error = vmtruncate(inode, attr->ia_size);
3186
3187 if (!error) {
3188 setattr_copy(inode, attr);
3189 mark_inode_dirty(inode);
3190 }
3191 depth = reiserfs_write_lock_once(inode->i_sb);
3192
3186 if (!error && reiserfs_posixacl(inode->i_sb)) { 3193 if (!error && reiserfs_posixacl(inode->i_sb)) {
3187 if (attr->ia_valid & ATTR_MODE) 3194 if (attr->ia_valid & ATTR_MODE)
3188 error = reiserfs_acl_chmod(inode); 3195 error = reiserfs_acl_chmod(inode);
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 94f6319292a1..0a65939508e9 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -38,7 +38,17 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
38 error = inode_change_ok(inode, attr); 38 error = inode_change_ok(inode, attr);
39 if (error) 39 if (error)
40 return error; 40 return error;
41 return inode_setattr(inode, attr); 41
42 if ((attr->ia_valid & ATTR_SIZE) &&
43 attr->ia_size != i_size_read(inode)) {
44 error = vmtruncate(inode, attr->ia_size);
45 if (error)
46 return error;
47 }
48
49 setattr_copy(inode, attr);
50 mark_inode_dirty(inode);
51 return 0;
42} 52}
43 53
44const struct inode_operations sysv_file_inode_operations = { 54const struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 7376032c89ce..04bb5bf07630 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -236,7 +236,17 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
236 error = inode_change_ok(inode, attr); 236 error = inode_change_ok(inode, attr);
237 if (error) 237 if (error)
238 return error; 238 return error;
239 return inode_setattr(inode, attr); 239
240 if ((attr->ia_valid & ATTR_SIZE) &&
241 attr->ia_size != i_size_read(inode)) {
242 error = vmtruncate(inode, attr->ia_size);
243 if (error)
244 return error;
245 }
246
247 setattr_copy(inode, attr);
248 mark_inode_dirty(inode);
249 return 0;
240} 250}
241 251
242const struct inode_operations udf_file_inode_operations = { 252const struct inode_operations udf_file_inode_operations = {
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 589e01a465ba..085e11623b7b 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -525,7 +525,10 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
525 if (error) 525 if (error)
526 return error; 526 return error;
527 } 527 }
528 return inode_setattr(inode, attr); 528
529 setattr_copy(inode, attr);
530 mark_inode_dirty(inode);
531 return 0;
529} 532}
530 533
531const struct inode_operations ufs_file_inode_operations = { 534const struct inode_operations ufs_file_inode_operations = {