diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:26:52 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:26:52 (GMT) |
commit | 5f248c9c251c60af3403902b26e08de43964ea0b (patch) | |
tree | 6d3328e72a7e4015a64017eb30be18095c6a3c64 /fs/cifs/inode.c | |
parent | f6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff) | |
parent | dca332528bc69e05f67161e1ed59929633d5e63d (diff) | |
download | linux-5f248c9c251c60af3403902b26e08de43964ea0b.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (96 commits)
no need for list_for_each_entry_safe()/resetting with superblock list
Fix sget() race with failing mount
vfs: don't hold s_umount over close_bdev_exclusive() call
sysv: do not mark superblock dirty on remount
sysv: do not mark superblock dirty on mount
btrfs: remove junk sb_dirt change
BFS: clean up the superblock usage
AFFS: wait for sb synchronization when needed
AFFS: clean up dirty flag usage
cifs: truncate fallout
mbcache: fix shrinker function return value
mbcache: Remove unused features
add f_flags to struct statfs(64)
pass a struct path to vfs_statfs
update VFS documentation for method changes.
All filesystems that need invalidate_inode_buffers() are doing that explicitly
convert remaining ->clear_inode() to ->evict_inode()
Make ->drop_inode() just return whether inode needs to be dropped
fs/inode.c:clear_inode() is gone
fs/inode.c:evict() doesn't care about delete vs. non-delete paths now
...
Fix up trivial conflicts in fs/nilfs2/super.c
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 86 |
1 files changed, 44 insertions, 42 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index dc4c47a..4bc47e5 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1698,26 +1698,16 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) return rc; } -static int cifs_vmtruncate(struct inode *inode, loff_t offset) +static void cifs_setsize(struct inode *inode, loff_t offset) { loff_t oldsize; - int err; spin_lock(&inode->i_lock); - err = inode_newsize_ok(inode, offset); - if (err) { - spin_unlock(&inode->i_lock); - goto out; - } - oldsize = inode->i_size; i_size_write(inode, offset); spin_unlock(&inode->i_lock); + truncate_pagecache(inode, oldsize, offset); - if (inode->i_op->truncate) - inode->i_op->truncate(inode); -out: - return err; } static int @@ -1790,7 +1780,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, if (rc == 0) { cifsInode->server_eof = attrs->ia_size; - rc = cifs_vmtruncate(inode, attrs->ia_size); + cifs_setsize(inode, attrs->ia_size); cifs_truncate_page(inode->i_mapping, inode->i_size); } @@ -1815,14 +1805,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) xid = GetXid(); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { - /* check if we have permission to change attrs */ - rc = inode_change_ok(inode, attrs); - if (rc < 0) - goto out; - else - rc = 0; - } + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) + attrs->ia_valid |= ATTR_FORCE; + + rc = inode_change_ok(inode, attrs); + if (rc < 0) + goto out; full_path = build_path_from_dentry(direntry); if (full_path == NULL) { @@ -1908,18 +1896,24 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) CIFS_MOUNT_MAP_SPECIAL_CHR); } - if (!rc) { - rc = inode_setattr(inode, attrs); + if (rc) + goto out; - /* force revalidate when any of these times are set since some - of the fs types (eg ext3, fat) do not have fine enough - time granularity to match protocol, and we do not have a - a way (yet) to query the server fs's time granularity (and - whether it rounds times down). - */ - if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))) - cifsInode->time = 0; - } + if ((attrs->ia_valid & ATTR_SIZE) && + attrs->ia_size != i_size_read(inode)) + truncate_setsize(inode, attrs->ia_size); + + setattr_copy(inode, attrs); + mark_inode_dirty(inode); + + /* force revalidate when any of these times are set since some + of the fs types (eg ext3, fat) do not have fine enough + time granularity to match protocol, and we do not have a + a way (yet) to query the server fs's time granularity (and + whether it rounds times down). + */ + if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)) + cifsInode->time = 0; out: kfree(args); kfree(full_path); @@ -1944,14 +1938,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) cFYI(1, "setattr on file %s attrs->iavalid 0x%x", direntry->d_name.name, attrs->ia_valid); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { - /* check if we have permission to change attrs */ - rc = inode_change_ok(inode, attrs); - if (rc < 0) { - FreeXid(xid); - return rc; - } else - rc = 0; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) + attrs->ia_valid |= ATTR_FORCE; + + rc = inode_change_ok(inode, attrs); + if (rc < 0) { + FreeXid(xid); + return rc; } full_path = build_path_from_dentry(direntry); @@ -2059,8 +2052,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) /* do not need local check to inode_check_ok since the server does that */ - if (!rc) - rc = inode_setattr(inode, attrs); + if (rc) + goto cifs_setattr_exit; + + if ((attrs->ia_valid & ATTR_SIZE) && + attrs->ia_size != i_size_read(inode)) + truncate_setsize(inode, attrs->ia_size); + + setattr_copy(inode, attrs); + mark_inode_dirty(inode); + return 0; + cifs_setattr_exit: kfree(full_path); FreeXid(xid); |