diff options
35 files changed, 416 insertions, 194 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index e5e5f823d687..32625f366fb5 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -110,7 +110,9 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
110 | if ((attr->ia_valid & ATTR_SIZE) && | 110 | if ((attr->ia_valid & ATTR_SIZE) && |
111 | (attr->ia_size != inode->i_size)) | 111 | (attr->ia_size != inode->i_size)) |
112 | return -EINVAL; | 112 | return -EINVAL; |
113 | return inode_setattr(inode, attr); | 113 | setattr_copy(inode, attr); |
114 | mark_inode_dirty(inode); | ||
115 | return 0; | ||
114 | } | 116 | } |
115 | 117 | ||
116 | 118 | ||
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 643b413d9f0f..e818f53ccfd7 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c | |||
@@ -968,12 +968,18 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) | |||
968 | goto err_out_exit; | 968 | goto err_out_exit; |
969 | } | 969 | } |
970 | 970 | ||
971 | err = inode_setattr(inode, attr); | 971 | if ((attr->ia_valid & ATTR_SIZE) && |
972 | if (err) { | 972 | attr->ia_size != i_size_read(inode)) { |
973 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); | 973 | err = vmtruncate(inode, attr->ia_size); |
974 | goto err_out_exit; | 974 | if (err) { |
975 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); | ||
976 | goto err_out_exit; | ||
977 | } | ||
975 | } | 978 | } |
976 | 979 | ||
980 | setattr_copy(inode, attr); | ||
981 | mark_inode_dirty(inode); | ||
982 | |||
977 | dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", | 983 | dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", |
978 | __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, | 984 | __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, |
979 | inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); | 985 | inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); |
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); |
241 | out: | 250 | out: |
242 | return error; | 251 | return error; |
@@ -146,31 +146,6 @@ void setattr_copy(struct inode *inode, const struct iattr *attr) | |||
146 | } | 146 | } |
147 | EXPORT_SYMBOL(setattr_copy); | 147 | EXPORT_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 | */ | ||
153 | int 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 | } | ||
172 | EXPORT_SYMBOL(inode_setattr); | ||
173 | |||
174 | int notify_change(struct dentry * dentry, struct iattr * attr) | 149 | int 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; | ||
1904 | out: | 1913 | out: |
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 | |||
2045 | cifs_setattr_exit: | 2066 | cifs_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 | ||
894 | static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( | 904 | static 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 | ||
3216 | err_out: | 3224 | err_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 | ||
992 | static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | 992 | static 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 | ||
1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | 1297 | int 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 | |||
1343 | out_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 | ||
304 | static const struct inode_operations hfsplus_file_inode_operations = { | 314 | static 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 | ||
850 | int hostfs_setattr(struct dentry *dentry, struct iattr *attr) | 850 | int 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 | ||
911 | static const struct inode_operations hostfs_iops = { | 923 | static 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 | |
462 | out: | 462 | setattr_copy(inode, attr); |
463 | return error; | 463 | mark_inode_dirty(inode); |
464 | return 0; | ||
464 | } | 465 | } |
465 | 466 | ||
466 | static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, | 467 | static 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 | ||
246 | const struct inode_operations logfs_reg_iops = { | 250 | const 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 | ||
37 | const struct inode_operations minix_file_inode_operations = { | 47 | const 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 | |||
1007 | out: | 1007 | out: |
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 | ||
678 | out_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 | */ |
2886 | int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | 2883 | int 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 | ||
223 | static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait) | 225 | static 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 | ||
355 | const struct inode_operations omfs_file_inops = { | 365 | const 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 | ||
569 | static const struct inode_operations proc_def_inode_operations = { | 579 | static 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; |
270 | out: | 277 | return 0; |
271 | return error; | ||
272 | } | 278 | } |
273 | 279 | ||
274 | static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry, | 280 | static 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 | ||
338 | static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 347 | static 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 | ||
44 | const struct inode_operations sysv_file_inode_operations = { | 54 | const 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 | ||
242 | const struct inode_operations udf_file_inode_operations = { | 252 | const 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 | ||
531 | const struct inode_operations ufs_file_inode_operations = { | 534 | const struct inode_operations ufs_file_inode_operations = { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8ebb5f01a418..6ecb83c00a6d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2392,7 +2392,6 @@ extern int buffer_migrate_page(struct address_space *, | |||
2392 | 2392 | ||
2393 | extern int inode_change_ok(const struct inode *, struct iattr *); | 2393 | extern int inode_change_ok(const struct inode *, struct iattr *); |
2394 | extern int inode_newsize_ok(const struct inode *, loff_t offset); | 2394 | extern int inode_newsize_ok(const struct inode *, loff_t offset); |
2395 | extern int __must_check inode_setattr(struct inode *, const struct iattr *); | ||
2396 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); | 2395 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); |
2397 | 2396 | ||
2398 | extern void file_update_time(struct file *file); | 2397 | extern void file_update_time(struct file *file); |