From eafdc7d190a944c755a9fe68573c193e6e0217e7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:29:53 +0200 Subject: sort out blockdev_direct_IO variants Move the call to vmtruncate to get rid of accessive blocks to the callers in prepearation of the new truncate calling sequence. This was only done for DIO_LOCKING filesystems, so the __blockdev_direct_IO_newtrunc variant was not needed anyway. Get rid of blockdev_direct_IO_no_locking and its _newtrunc variant while at it as just opencoding the two additional paramters is shorted than the name suffix. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/hfsplus/inode.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'fs/hfsplus') diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9bbb82924a22..486021773911 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -105,9 +105,24 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; + ssize_t ret; - return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, hfsplus_get_block, NULL); + + /* + * In case of error extending write may have instantiated a few + * blocks outside i_size. Trim these off again. + */ + if (unlikely((rw & WRITE) && ret < 0)) { + loff_t isize = i_size_read(inode); + loff_t end = offset + iov_length(iov, nr_segs); + + if (end > isize) + vmtruncate(inode, isize); + } + + return ret; } static int hfsplus_writepages(struct address_space *mapping, -- cgit v1.2.3 From 282dc178849882289d30e58b54be6b2799b351aa Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:29:55 +0200 Subject: get rid of cont_write_begin_newtrunc Move the call to vmtruncate to get rid of accessive blocks to the callers in preparation of the new truncate sequence and rename the non-truncating version to cont_write_begin. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/adfs/inode.c | 11 ++++++++++- fs/affs/file.c | 11 ++++++++++- fs/buffer.c | 21 +-------------------- fs/fat/inode.c | 2 +- fs/hfs/inode.c | 11 ++++++++++- fs/hfsplus/inode.c | 11 ++++++++++- fs/hpfs/file.c | 11 ++++++++++- fs/qnx4/inode.c | 11 ++++++++++- include/linux/buffer_head.h | 3 --- 9 files changed, 62 insertions(+), 30 deletions(-) (limited to 'fs/hfsplus') diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 6f850b06ab62..b3dec193036b 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -50,10 +50,19 @@ static int adfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, adfs_get_block, &ADFS_I(mapping->host)->mmu_private); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t _adfs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/affs/file.c b/fs/affs/file.c index 322710c3eedf..c4a9875bd1a6 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -406,10 +406,19 @@ static int affs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, affs_get_block, &AFFS_I(mapping->host)->mmu_private); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t _affs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/buffer.c b/fs/buffer.c index 559daf76bca4..14529ec759b9 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2351,7 +2351,7 @@ out: * For moronic filesystems that do not allow holes in file. * We may have to extend the file. */ -int cont_write_begin_newtrunc(struct file *file, struct address_space *mapping, +int cont_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata, get_block_t *get_block, loff_t *bytes) @@ -2377,25 +2377,6 @@ int cont_write_begin_newtrunc(struct file *file, struct address_space *mapping, out: return err; } -EXPORT_SYMBOL(cont_write_begin_newtrunc); - -int cont_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata, - get_block_t *get_block, loff_t *bytes) -{ - int ret; - - ret = cont_write_begin_newtrunc(file, mapping, pos, len, flags, - pagep, fsdata, get_block, bytes); - if (unlikely(ret)) { - loff_t isize = mapping->host->i_size; - if (pos + len > isize) - vmtruncate(mapping->host, isize); - } - - return ret; -} EXPORT_SYMBOL(cont_write_begin); int block_prepare_write(struct page *page, unsigned from, unsigned to, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ffe7c6fdc1ec..ec6a699a4023 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -159,7 +159,7 @@ static int fat_write_begin(struct file *file, struct address_space *mapping, int err; *pagep = NULL; - err = cont_write_begin_newtrunc(file, mapping, pos, len, flags, + err = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, fat_get_block, &MSDOS_I(mapping->host)->mmu_private); if (err < 0) diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 07b2464b5716..8df18e63eb6b 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -39,10 +39,19 @@ static int hfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, hfs_get_block, &HFS_I(mapping->host)->phys_size); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t hfs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 486021773911..88bf1b562641 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -31,10 +31,19 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, hfsplus_get_block, &HFSPLUS_I(mapping->host).phys_size); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index a9ae9bfa752f..c0340887c7ea 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -97,10 +97,19 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, hpfs_get_block, &hpfs_i(mapping->host)->mmu_private); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 277575ddc05c..16829722be93 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -320,10 +320,19 @@ static int qnx4_write_begin(struct file *file, struct address_space *mapping, struct page **pagep, void **fsdata) { struct qnx4_inode_info *qnx4_inode = qnx4_i(mapping->host); + int ret; + *pagep = NULL; - return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, qnx4_get_block, &qnx4_inode->mmu_private); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t qnx4_bmap(struct address_space *mapping, sector_t block) { diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index cfda5f0b2a4b..7638647f0424 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -217,9 +217,6 @@ int generic_write_end(struct file *, struct address_space *, struct page *, void *); void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); -int cont_write_begin_newtrunc(struct file *, struct address_space *, loff_t, - unsigned, unsigned, struct page **, void **, - get_block_t *, loff_t *); int cont_write_begin(struct file *, struct address_space *, loff_t, unsigned, unsigned, struct page **, void **, get_block_t *, loff_t *); -- cgit v1.2.3 From d39aae9ec447dda84d9a2850743a78a535a71c90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:29:59 +0200 Subject: add missing setattr methods For the new truncate sequence every filesystem that wants to truncate on-disk state needs a seattr method. Convert the remaining filesystems that implement the truncate inode operation to have its own setattr method. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/hfsplus/inode.c | 12 ++++++++++++ fs/minix/file.c | 12 ++++++++++++ fs/omfs/file.c | 12 ++++++++++++ fs/sysv/file.c | 12 ++++++++++++ fs/udf/file.c | 12 ++++++++++++ 5 files changed, 60 insertions(+) (limited to 'fs/hfsplus') diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 88bf1b562641..d6ebe53fbdbf 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -290,9 +290,21 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) return 0; } +static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + int error; + + error = inode_change_ok(inode, attr); + if (error) + return error; + return inode_setattr(inode, attr); +} + static const struct inode_operations hfsplus_file_inode_operations = { .lookup = hfsplus_file_lookup, .truncate = hfsplus_file_truncate, + .setattr = hfsplus_setattr, .setxattr = hfsplus_setxattr, .getxattr = hfsplus_getxattr, .listxattr = hfsplus_listxattr, diff --git a/fs/minix/file.c b/fs/minix/file.c index d5320ff23faf..7a45dd1fe2e5 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -23,7 +23,19 @@ const struct file_operations minix_file_operations = { .splice_read = generic_file_splice_read, }; +static int minix_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + int error; + + error = inode_change_ok(inode, attr); + if (error) + return error; + return inode_setattr(inode, attr); +} + const struct inode_operations minix_file_inode_operations = { .truncate = minix_truncate, + .setattr = minix_setattr, .getattr = minix_getattr, }; diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 810cff346468..78c9f0c1a2f3 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -341,7 +341,19 @@ const struct file_operations omfs_file_operations = { .splice_read = generic_file_splice_read, }; +static int omfs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + int error; + + error = inode_change_ok(inode, attr); + if (error) + return error; + return inode_setattr(inode, attr); +} + const struct inode_operations omfs_file_inops = { + .setattr = omfs_setattr, .truncate = omfs_truncate }; diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 750cc22349bd..94f6319292a1 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -30,7 +30,19 @@ const struct file_operations sysv_file_operations = { .splice_read = generic_file_splice_read, }; +static int sysv_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + int error; + + error = inode_change_ok(inode, attr); + if (error) + return error; + return inode_setattr(inode, attr); +} + const struct inode_operations sysv_file_inode_operations = { .truncate = sysv_truncate, + .setattr = sysv_setattr, .getattr = sysv_getattr, }; diff --git a/fs/udf/file.c b/fs/udf/file.c index 94e06d6bddbd..7376032c89ce 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -228,6 +228,18 @@ const struct file_operations udf_file_operations = { .llseek = generic_file_llseek, }; +static int udf_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + int error; + + error = inode_change_ok(inode, attr); + if (error) + return error; + return inode_setattr(inode, attr); +} + const struct inode_operations udf_file_inode_operations = { + .setattr = udf_setattr, .truncate = udf_truncate, }; -- cgit v1.2.3 From 1025774ce411f2bd4b059ad7b53f0003569b74fa Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:30:02 +0200 Subject: 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 Signed-off-by: Al Viro --- arch/powerpc/platforms/cell/spufs/inode.c | 4 +- drivers/staging/pohmelfs/inode.c | 14 +++-- fs/9p/vfs_inode.c | 15 ++++- fs/affs/inode.c | 13 ++++- fs/attr.c | 25 -------- fs/btrfs/inode.c | 12 ++-- fs/cifs/inode.c | 45 ++++++++++---- fs/exofs/inode.c | 14 ++++- fs/ext3/inode.c | 12 +++- fs/ext4/inode.c | 16 +++-- fs/gfs2/inode.c | 25 +++++--- fs/gfs2/ops_inode.c | 12 +++- fs/gfs2/xattr.c | 24 ++++++-- fs/hfs/inode.c | 12 +++- fs/hfsplus/inode.c | 12 +++- fs/hostfs/hostfs_kern.c | 18 +++++- fs/hpfs/inode.c | 12 +++- fs/hugetlbfs/inode.c | 17 +++--- fs/jfs/file.c | 14 ++++- fs/logfs/file.c | 18 +++--- fs/minix/file.c | 12 +++- fs/ncpfs/inode.c | 24 ++++---- fs/nilfs2/inode.c | 25 ++++++-- fs/ntfs/inode.c | 3 - fs/ocfs2/dlmfs/dlmfs.c | 8 ++- fs/ocfs2/file.c | 16 +++-- fs/omfs/file.c | 12 +++- fs/proc/base.c | 16 ++++- fs/proc/generic.c | 18 ++++-- fs/proc/proc_sysctl.c | 15 ++++- fs/reiserfs/inode.c | 97 +++++++++++++++++-------------- fs/sysv/file.c | 12 +++- fs/udf/file.c | 12 +++- fs/ufs/truncate.c | 5 +- include/linux/fs.h | 1 - 35 files changed, 416 insertions(+), 194 deletions(-) (limited to 'fs/hfsplus') 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) if ((attr->ia_valid & ATTR_SIZE) && (attr->ia_size != inode->i_size)) return -EINVAL; - return inode_setattr(inode, attr); + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) goto err_out_exit; } - err = inode_setattr(inode, attr); - if (err) { - dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); - goto err_out_exit; + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + err = vmtruncate(inode, attr->ia_size); + if (err) { + dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); + goto err_out_exit; + } } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, 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) } retval = p9_client_wstat(fid, &wstat); - if (retval >= 0) - retval = inode_setattr(dentry->d_inode, iattr); + if (retval < 0) + return retval; + + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(dentry->d_inode)) { + retval = vmtruncate(dentry->d_inode, iattr->ia_size); + if (retval) + return retval; + } - return retval; + setattr_copy(dentry->d_inode, iattr); + mark_inode_dirty(dentry->d_inode); + return 0; } /** 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) goto out; } - error = inode_setattr(inode, attr); - if (!error && (attr->ia_valid & ATTR_MODE)) + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + if (attr->ia_valid & ATTR_MODE) mode_to_prot(inode); out: 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) } EXPORT_SYMBOL(setattr_copy); -/* - * note this function is deprecated, the new truncate sequence should be - * used instead -- see eg. simple_setsize, setattr_copy. - */ -int inode_setattr(struct inode *inode, const struct iattr *attr) -{ - unsigned int ia_valid = attr->ia_valid; - - if (ia_valid & ATTR_SIZE && - attr->ia_size != i_size_read(inode)) { - int error; - - error = vmtruncate(inode, attr->ia_size); - if (error) - return error; - } - - setattr_copy(inode, attr); - - mark_inode_dirty(inode); - - return 0; -} -EXPORT_SYMBOL(inode_setattr); - int notify_change(struct dentry * dentry, struct iattr * attr) { 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) if (err) return err; } - attr->ia_valid &= ~ATTR_SIZE; - if (attr->ia_valid) - err = inode_setattr(inode, attr); + if (attr->ia_valid) { + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + if (attr->ia_valid & ATTR_MODE) + err = btrfs_acl_chmod(inode); + } - if (!err && ((attr->ia_valid & ATTR_MODE))) - err = btrfs_acl_chmod(inode); return err; } 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) 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)) { + rc = vmtruncate(inode, attrs->ia_size); + if (rc) + goto out; } + + 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); @@ -2040,8 +2049,20 @@ 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)) { + rc = vmtruncate(inode, attrs->ia_size); + if (rc) + goto cifs_setattr_exit; + } + + setattr_copy(inode, attrs); + mark_inode_dirty(inode); + return 0; + cifs_setattr_exit: kfree(full_path); 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) if (error) return error; - error = inode_setattr(inode, iattr); - return error; + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, iattr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, iattr); + mark_inode_dirty(inode); + return 0; } 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) ext3_journal_stop(handle); } - rc = inode_setattr(inode, attr); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + rc = vmtruncate(inode, attr->ia_size); + if (rc) + goto err_out; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); - if (!rc && (ia_valid & ATTR_MODE)) + if (ia_valid & ATTR_MODE) rc = ext3_acl_chmod(inode); 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) ext4_truncate(inode); } - rc = inode_setattr(inode, attr); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) + rc = vmtruncate(inode, attr->ia_size); - /* If inode_setattr's call to ext4_truncate failed to get a - * transaction handle at all, we need to clean up the in-core - * orphan list manually. */ + if (!rc) { + setattr_copy(inode, attr); + mark_inode_dirty(inode); + } + + /* + * If the call to ext4_truncate failed to get a transaction handle at + * all, we need to clean up the in-core orphan list manually. + */ if (inode->i_nlink) ext4_orphan_del(NULL, inode); 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: static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { + struct inode *inode = &ip->i_inode; struct buffer_head *dibh; int error; error = gfs2_meta_inode_buffer(ip, &dibh); - if (!error) { - error = inode_setattr(&ip->i_inode, attr); - gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); + if (error) + return error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; } - return error; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + gfs2_assert_warn(GFS2_SB(inode), !error); + gfs2_trans_add_bh(ip->i_gl, dibh, 1); + gfs2_dinode_out(ip, dibh->b_data); + brelse(dibh); + return 0; } /** 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) if (error) goto out_end_trans; - error = inode_setattr(inode, attr); - gfs2_assert_warn(sdp, !error); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, attr->ia_size); + gfs2_assert_warn(sdp, !error); + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); gfs2_trans_add_bh(ip->i_gl, dibh, 1); 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: int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) { + struct inode *inode = &ip->i_inode; struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_ea_location el; struct buffer_head *dibh; @@ -1321,14 +1322,25 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) return error; error = gfs2_meta_inode_buffer(ip, &dibh); - if (!error) { - error = inode_setattr(&ip->i_inode, attr); - gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); + if (error) + goto out_trans_end; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, attr->ia_size); + gfs2_assert_warn(GFS2_SB(inode), !error); } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + gfs2_trans_add_bh(ip->i_gl, dibh, 1); + gfs2_dinode_out(ip, dibh->b_data); + brelse(dibh); + +out_trans_end: gfs2_trans_end(sdp); return error; } 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) attr->ia_mode = inode->i_mode & ~S_IWUGO; attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask; } - error = inode_setattr(inode, attr); - if (error) - return error; + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); return 0; } 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) error = inode_change_ok(inode, attr); if (error) return error; - return inode_setattr(inode, attr); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) int hostfs_setattr(struct dentry *dentry, struct iattr *attr) { + struct inode *inode = dentry->d_inode; struct hostfs_iattr attrs; char *name; int err; - int fd = HOSTFS_I(dentry->d_inode)->fd; + int fd = HOSTFS_I(inode)->fd; - err = inode_change_ok(dentry->d_inode, attr); + err = inode_change_ok(inode, attr); if (err) return err; @@ -905,7 +906,18 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) if (err) return err; - return inode_setattr(dentry->d_inode, attr); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, attr->ia_size); + if (err) + return err; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) if (error) goto out_unlock; - error = inode_setattr(inode, attr); - if (error) - goto out_unlock; + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); hpfs_write_inode(inode); 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) error = inode_change_ok(inode, attr); if (error) - goto out; + return error; if (ia_valid & ATTR_SIZE) { error = -EINVAL; - if (!(attr->ia_size & ~huge_page_mask(h))) - error = hugetlb_vmtruncate(inode, attr->ia_size); + if (attr->ia_size & ~huge_page_mask(h)) + return -EINVAL; + error = hugetlb_vmtruncate(inode, attr->ia_size); if (error) - goto out; - attr->ia_valid &= ~ATTR_SIZE; + return error; } - error = inode_setattr(inode, attr); -out: - return error; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include "jfs_incore.h" @@ -107,11 +108,18 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) return rc; } - rc = inode_setattr(inode, iattr); + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(inode)) { + rc = vmtruncate(inode, iattr->ia_size); + if (rc) + return rc; + } - if (!rc && (iattr->ia_valid & ATTR_MODE)) - rc = jfs_acl_chmod(inode); + setattr_copy(inode, iattr); + mark_inode_dirty(inode); + if (iattr->ia_valid & ATTR_MODE) + rc = jfs_acl_chmod(inode); return rc; } 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) struct inode *inode = dentry->d_inode; int err = 0; - if (attr->ia_valid & ATTR_SIZE) + if (attr->ia_valid & ATTR_SIZE) { err = logfs_truncate(inode, attr->ia_size); - attr->ia_valid &= ~ATTR_SIZE; + if (err) + return err; + } - if (!err) - err = inode_change_ok(inode, attr); - if (!err) - err = inode_setattr(inode, attr); - return err; + err = inode_change_ok(inode, attr); + if (err) + return err; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) error = inode_change_ok(inode, attr); if (error) return error; - return inode_setattr(inode, attr); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) tmpattr.ia_valid = ATTR_MODE; tmpattr.ia_mode = attr->ia_mode; - result = inode_setattr(inode, &tmpattr); - if (result) - goto out; + setattr_copy(inode, &tmpattr); + mark_inode_dirty(inode); } } #endif @@ -954,15 +953,12 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) result = ncp_make_closed(inode); if (result) goto out; - { - struct iattr tmpattr; - - tmpattr.ia_valid = ATTR_SIZE; - tmpattr.ia_size = attr->ia_size; - - result = inode_setattr(inode, &tmpattr); + + if (attr->ia_size != i_size_read(inode)) { + result = vmtruncate(inode, attr->ia_size); if (result) goto out; + mark_inode_dirty(inode); } } if ((attr->ia_valid & ATTR_CTIME) != 0) { @@ -1002,8 +998,12 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) NCP_FINFO(inode)->nwattr = info.attributes; #endif } - if (!result) - result = inode_setattr(inode, attr); + if (result) + goto out; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + out: unlock_kernel(); 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) err = nilfs_transaction_begin(sb, &ti, 0); if (unlikely(err)) return err; - err = inode_setattr(inode, iattr); - if (!err && (iattr->ia_valid & ATTR_MODE)) + + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(inode)) { + err = vmtruncate(inode, iattr->ia_size); + if (unlikely(err)) + goto out_err; + } + + setattr_copy(inode, iattr); + mark_inode_dirty(inode); + + if (iattr->ia_valid & ATTR_MODE) { err = nilfs_acl_chmod(inode); - if (likely(!err)) - err = nilfs_transaction_commit(sb); - else - nilfs_transaction_abort(sb); + if (unlikely(err)) + goto out_err; + } + + return nilfs_transaction_commit(sb); +out_err: + nilfs_transaction_abort(sb); return err; } 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) { * * Called with ->i_mutex held. For the ATTR_SIZE (i.e. ->truncate) case, also * called with ->i_alloc_sem held for writing. - * - * Basically this is a copy of generic notify_change() and inode_setattr() - * functionality, except we intercept and abort changes in i_size. */ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) { 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) attr->ia_valid &= ~ATTR_SIZE; error = inode_change_ok(inode, attr); - if (!error) - error = inode_setattr(inode, attr); + if (error) + return error; - return error; + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) * Otherwise, we could get into problems with truncate as * ip_alloc_sem is used there to protect against i_size * changes. + * + * XXX: this means the conditional below can probably be removed. */ - status = inode_setattr(inode, attr); - if (status < 0) { - mlog_errno(status); - goto bail_commit; + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + status = vmtruncate(inode, attr->ia_size); + if (status) { + mlog_errno(status); + goto bail_commit; + } } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + status = ocfs2_mark_inode_dirty(handle, inode, bh); if (status < 0) 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) error = inode_change_ok(inode, attr); if (error) return error; - return inode_setattr(inode, attr); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) return -EPERM; error = inode_change_ok(inode, attr); - if (!error) - error = inode_setattr(inode, attr); - return error; + if (error) + return error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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 @@ #include #include #include +#include #include #include #include @@ -258,17 +259,22 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) error = inode_change_ok(inode, iattr); if (error) - goto out; + return error; - error = inode_setattr(inode, iattr); - if (error) - goto out; + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, iattr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, iattr); + mark_inode_dirty(inode); de->uid = inode->i_uid; de->gid = inode->i_gid; de->mode = inode->i_mode; -out: - return error; + return 0; } 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) return -EPERM; error = inode_change_ok(inode, attr); - if (!error) - error = inode_setattr(inode, attr); + if (error) + return error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } - return error; + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) } error = inode_change_ok(inode, attr); - if (!error) { - if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || - (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { - error = reiserfs_chown_xattrs(inode, attr); + if (error) + goto out; - if (!error) { - struct reiserfs_transaction_handle th; - int jbegin_count = - 2 * - (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + - REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + - 2; - - /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ - error = - journal_begin(&th, inode->i_sb, - jbegin_count); - if (error) - goto out; - error = dquot_transfer(inode, attr); - if (error) { - journal_end(&th, inode->i_sb, - jbegin_count); - goto out; - } - /* Update corresponding info in inode so that everything is in - * one transaction */ - if (attr->ia_valid & ATTR_UID) - inode->i_uid = attr->ia_uid; - if (attr->ia_valid & ATTR_GID) - inode->i_gid = attr->ia_gid; - mark_inode_dirty(inode); - error = - journal_end(&th, inode->i_sb, jbegin_count); - } - } - if (!error) { - /* - * Relax the lock here, as it might truncate the - * inode pages and wait for inode pages locks. - * To release such page lock, the owner needs the - * reiserfs lock - */ - reiserfs_write_unlock_once(inode->i_sb, depth); - error = inode_setattr(inode, attr); - depth = reiserfs_write_lock_once(inode->i_sb); + if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { + struct reiserfs_transaction_handle th; + int jbegin_count = + 2 * + (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + + REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + + 2; + + error = reiserfs_chown_xattrs(inode, attr); + + if (error) + return error; + + /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ + error = journal_begin(&th, inode->i_sb, jbegin_count); + if (error) + goto out; + error = dquot_transfer(inode, attr); + if (error) { + journal_end(&th, inode->i_sb, jbegin_count); + goto out; } + + /* Update corresponding info in inode so that everything is in + * one transaction */ + if (attr->ia_valid & ATTR_UID) + inode->i_uid = attr->ia_uid; + if (attr->ia_valid & ATTR_GID) + inode->i_gid = attr->ia_gid; + mark_inode_dirty(inode); + error = journal_end(&th, inode->i_sb, jbegin_count); + if (error) + goto out; } + /* + * Relax the lock here, as it might truncate the + * inode pages and wait for inode pages locks. + * To release such page lock, the owner needs the + * reiserfs lock + */ + reiserfs_write_unlock_once(inode->i_sb, depth); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) + error = vmtruncate(inode, attr->ia_size); + + if (!error) { + setattr_copy(inode, attr); + mark_inode_dirty(inode); + } + depth = reiserfs_write_lock_once(inode->i_sb); + if (!error && reiserfs_posixacl(inode->i_sb)) { if (attr->ia_valid & ATTR_MODE) 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) error = inode_change_ok(inode, attr); if (error) return error; - return inode_setattr(inode, attr); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) error = inode_change_ok(inode, attr); if (error) return error; - return inode_setattr(inode, attr); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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) if (error) return error; } - return inode_setattr(inode, attr); + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } 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 *, extern int inode_change_ok(const struct inode *, struct iattr *); extern int inode_newsize_ok(const struct inode *, loff_t offset); -extern int __must_check inode_setattr(struct inode *, const struct iattr *); extern void setattr_copy(struct inode *inode, const struct iattr *attr); extern void file_update_time(struct file *file); -- cgit v1.2.3 From b5fc510c48f631882ccec3c0f02a25d5b67de09f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 4 Jul 2010 12:24:09 +0400 Subject: get rid of file_fsync() Copy and simplify in the only two users remaining. Signed-off-by: Al Viro --- fs/hfs/inode.c | 26 +++++++++++++++++++++++++- fs/hfsplus/hfsplus_fs.h | 1 + fs/hfsplus/inode.c | 27 ++++++++++++++++++++++++++- fs/hfsplus/super.c | 2 +- fs/sync.c | 25 ------------------------- include/linux/buffer_head.h | 1 - 6 files changed, 53 insertions(+), 29 deletions(-) (limited to 'fs/hfsplus') diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 87de671baa83..93ceec8fbb8f 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -625,6 +625,30 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) return 0; } +static int hfs_file_fsync(struct file *filp, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block * sb; + int ret, err; + + /* sync the inode to buffers */ + ret = write_inode_now(inode, 0); + + /* sync the superblock to buffers */ + sb = inode->i_sb; + if (sb->s_dirt) { + lock_super(sb); + sb->s_dirt = 0; + if (!(sb->s_flags & MS_RDONLY)) + hfs_mdb_commit(sb); + unlock_super(sb); + } + /* .. finally sync the buffers to disk */ + err = sync_blockdev(sb->s_bdev); + if (!ret) + ret = err; + return ret; +} static const struct file_operations hfs_file_operations = { .llseek = generic_file_llseek, @@ -634,7 +658,7 @@ static const struct file_operations hfs_file_operations = { .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .splice_read = generic_file_splice_read, - .fsync = file_fsync, + .fsync = hfs_file_fsync, .open = hfs_file_open, .release = hfs_file_release, }; diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 6505c30ad965..dc856be3c2b0 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -351,6 +351,7 @@ int hfsplus_show_options(struct seq_file *, struct vfsmount *); /* super.c */ struct inode *hfsplus_iget(struct super_block *, unsigned long); +int hfsplus_sync_fs(struct super_block *sb, int wait); /* tables.c */ extern u16 hfsplus_case_fold_table[]; diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 654c5a8ddf1c..c5a979d62c65 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -311,6 +311,31 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) return 0; } +static int hfsplus_file_fsync(struct file *filp, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block * sb; + int ret, err; + + /* sync the inode to buffers */ + ret = write_inode_now(inode, 0); + + /* sync the superblock to buffers */ + sb = inode->i_sb; + if (sb->s_dirt) { + if (!(sb->s_flags & MS_RDONLY)) + hfsplus_sync_fs(sb, 1); + else + sb->s_dirt = 0; + } + + /* .. finally sync the buffers to disk */ + err = sync_blockdev(sb->s_bdev); + if (!ret) + ret = err; + return ret; +} + static const struct inode_operations hfsplus_file_inode_operations = { .lookup = hfsplus_file_lookup, .truncate = hfsplus_file_truncate, @@ -328,7 +353,7 @@ static const struct file_operations hfsplus_file_operations = { .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .splice_read = generic_file_splice_read, - .fsync = file_fsync, + .fsync = hfsplus_file_fsync, .open = hfsplus_file_open, .release = hfsplus_file_release, .unlocked_ioctl = hfsplus_ioctl, diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 74b473a8ef92..a32c241e4e45 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -154,7 +154,7 @@ static void hfsplus_clear_inode(struct inode *inode) } } -static int hfsplus_sync_fs(struct super_block *sb, int wait) +int hfsplus_sync_fs(struct super_block *sb, int wait) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; diff --git a/fs/sync.c b/fs/sync.c index 15aa6f03b2da..ba76b9623e7e 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -128,31 +128,6 @@ void emergency_sync(void) } } -/* - * Generic function to fsync a file. - */ -int file_fsync(struct file *filp, int datasync) -{ - struct inode *inode = filp->f_mapping->host; - struct super_block * sb; - int ret, err; - - /* sync the inode to buffers */ - ret = write_inode_now(inode, 0); - - /* sync the superblock to buffers */ - sb = inode->i_sb; - if (sb->s_dirt && sb->s_op->write_super) - sb->s_op->write_super(sb); - - /* .. finally sync the buffers to disk */ - err = sync_blockdev(sb->s_bdev); - if (!ret) - ret = err; - return ret; -} -EXPORT_SYMBOL(file_fsync); - /** * vfs_fsync_range - helper to sync a range of data & metadata to disk * @file: file to sync diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 3f69054f86d9..620f1d1088cb 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -225,7 +225,6 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, void block_sync_page(struct page *); sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); int block_truncate_page(struct address_space *, loff_t, get_block_t *); -int file_fsync(struct file *, int); int nobh_write_begin(struct address_space *, loff_t, unsigned, unsigned, struct page **, void **, get_block_t*); int nobh_write_end(struct file *, struct address_space *, -- cgit v1.2.3 From b57922d97fd6f79b6dbe6db0c4fd30d219fa08c1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Jun 2010 14:34:48 -0400 Subject: convert remaining ->clear_inode() to ->evict_inode() Signed-off-by: Al Viro --- fs/9p/v9fs_vfs.h | 2 +- fs/9p/vfs_inode.c | 4 +++- fs/9p/vfs_super.c | 4 ++-- fs/afs/inode.c | 5 ++++- fs/afs/internal.h | 2 +- fs/afs/super.c | 2 +- fs/binfmt_misc.c | 5 +++-- fs/block_dev.c | 7 +++++-- fs/cifs/cifsfs.c | 6 ++++-- fs/coda/inode.c | 8 +++++--- fs/ecryptfs/super.c | 8 +++++--- fs/freevxfs/vxfs_extern.h | 2 +- fs/freevxfs/vxfs_inode.c | 8 +++++--- fs/freevxfs/vxfs_super.c | 2 +- fs/fuse/inode.c | 6 ++++-- fs/hfs/hfs_fs.h | 2 +- fs/hfs/inode.c | 4 +++- fs/hfs/super.c | 2 +- fs/hfsplus/super.c | 8 +++++--- fs/inode.c | 2 -- fs/jffs2/fs.c | 6 ++++-- fs/jffs2/os-linux.h | 2 +- fs/jffs2/super.c | 2 +- fs/jffs2/xattr.c | 2 +- fs/nfs/inode.c | 13 +++++++++++-- fs/nfs/internal.h | 4 ++-- fs/nfs/super.c | 4 ++-- fs/ntfs/inode.c | 7 +++++-- fs/ntfs/inode.h | 2 +- fs/ntfs/super.c | 2 +- fs/ocfs2/dlmfs/dlmfs.c | 7 +++---- fs/xfs/linux-2.6/xfs_super.c | 8 +++++--- fs/xfs/linux-2.6/xfs_trace.h | 2 +- include/linux/fs.h | 3 +-- 34 files changed, 94 insertions(+), 59 deletions(-) (limited to 'fs/hfsplus') diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 32ef4009d030..3d056fe01b50 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -52,7 +52,7 @@ void v9fs_destroy_inode(struct inode *inode); #endif struct inode *v9fs_get_inode(struct super_block *sb, int mode); -void v9fs_clear_inode(struct inode *inode); +void v9fs_evict_inode(struct inode *inode); ino_t v9fs_qid2ino(struct p9_qid *qid); void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); int v9fs_dir_release(struct inode *inode, struct file *filp); diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 4b3ad6ac9a41..b81ce206508d 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -387,8 +387,10 @@ error: * @inode: inode to release * */ -void v9fs_clear_inode(struct inode *inode) +void v9fs_evict_inode(struct inode *inode) { + truncate_inode_pages(inode->i_mapping, 0); + end_writeback(inode); filemap_fdatawrite(inode->i_mapping); #ifdef CONFIG_9P_FSCACHE diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index be74d020436e..c6122bf547df 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -257,7 +257,7 @@ static const struct super_operations v9fs_super_ops = { .destroy_inode = v9fs_destroy_inode, #endif .statfs = simple_statfs, - .clear_inode = v9fs_clear_inode, + .evict_inode = v9fs_evict_inode, .show_options = generic_show_options, .umount_begin = v9fs_umount_begin, }; @@ -268,7 +268,7 @@ static const struct super_operations v9fs_super_ops_dotl = { .destroy_inode = v9fs_destroy_inode, #endif .statfs = v9fs_statfs, - .clear_inode = v9fs_clear_inode, + .evict_inode = v9fs_evict_inode, .show_options = generic_show_options, .umount_begin = v9fs_umount_begin, }; diff --git a/fs/afs/inode.c b/fs/afs/inode.c index d00b312e3110..320ffef11574 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -316,7 +316,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, /* * clear an AFS inode */ -void afs_clear_inode(struct inode *inode) +void afs_evict_inode(struct inode *inode) { struct afs_permits *permits; struct afs_vnode *vnode; @@ -335,6 +335,9 @@ void afs_clear_inode(struct inode *inode) ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode); + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); + afs_give_up_callback(vnode); if (vnode->server) { diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 5f679b77ce24..8679089ce9a1 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -565,7 +565,7 @@ extern void afs_zap_data(struct afs_vnode *); extern int afs_validate(struct afs_vnode *, struct key *); extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int afs_setattr(struct dentry *, struct iattr *); -extern void afs_clear_inode(struct inode *); +extern void afs_evict_inode(struct inode *); /* * main.c diff --git a/fs/afs/super.c b/fs/afs/super.c index e932e5a3a0c1..9cf80f02da16 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -49,7 +49,7 @@ static const struct super_operations afs_super_ops = { .statfs = afs_statfs, .alloc_inode = afs_alloc_inode, .destroy_inode = afs_destroy_inode, - .clear_inode = afs_clear_inode, + .evict_inode = afs_evict_inode, .put_super = afs_put_super, .show_options = generic_show_options, }; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c4e83537ead7..9e60fd201716 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -502,8 +502,9 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode) return inode; } -static void bm_clear_inode(struct inode *inode) +static void bm_evict_inode(struct inode *inode) { + end_writeback(inode); kfree(inode->i_private); } @@ -685,7 +686,7 @@ static const struct file_operations bm_status_operations = { static const struct super_operations s_ops = { .statfs = simple_statfs, - .clear_inode = bm_clear_inode, + .evict_inode = bm_evict_inode, }; static int bm_fill_super(struct super_block * sb, void * data, int silent) diff --git a/fs/block_dev.c b/fs/block_dev.c index 63c9d6076205..de7b4d0c7e30 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -426,10 +426,13 @@ static inline void __bd_forget(struct inode *inode) inode->i_mapping = &inode->i_data; } -static void bdev_clear_inode(struct inode *inode) +static void bdev_evict_inode(struct inode *inode) { struct block_device *bdev = &BDEV_I(inode)->bdev; struct list_head *p; + truncate_inode_pages(&inode->i_data, 0); + invalidate_inode_buffers(inode); /* is it needed here? */ + end_writeback(inode); spin_lock(&bdev_lock); while ( (p = bdev->bd_inodes.next) != &bdev->bd_inodes ) { __bd_forget(list_entry(p, struct inode, i_devices)); @@ -443,7 +446,7 @@ static const struct super_operations bdev_sops = { .alloc_inode = bdev_alloc_inode, .destroy_inode = bdev_destroy_inode, .drop_inode = generic_delete_inode, - .clear_inode = bdev_clear_inode, + .evict_inode = bdev_evict_inode, }; static int bd_get_sb(struct file_system_type *fs_type, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 20914f5627dd..5574a42b7bb6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -330,8 +330,10 @@ cifs_destroy_inode(struct inode *inode) } static void -cifs_clear_inode(struct inode *inode) +cifs_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); cifs_fscache_release_inode_cookie(inode); } @@ -495,7 +497,7 @@ static const struct super_operations cifs_super_ops = { .alloc_inode = cifs_alloc_inode, .destroy_inode = cifs_destroy_inode, .drop_inode = cifs_drop_inode, - .clear_inode = cifs_clear_inode, + .evict_inode = cifs_evict_inode, /* .delete_inode = cifs_delete_inode, */ /* Do not need above function unless later we add lazy close of inodes or unless the kernel forgets to call us with the same number of releases (closes) diff --git a/fs/coda/inode.c b/fs/coda/inode.c index d97f9935a028..6526e6f21ecf 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -35,7 +35,7 @@ #include "coda_int.h" /* VFS super_block ops */ -static void coda_clear_inode(struct inode *); +static void coda_evict_inode(struct inode *); static void coda_put_super(struct super_block *); static int coda_statfs(struct dentry *dentry, struct kstatfs *buf); @@ -93,7 +93,7 @@ static const struct super_operations coda_super_operations = { .alloc_inode = coda_alloc_inode, .destroy_inode = coda_destroy_inode, - .clear_inode = coda_clear_inode, + .evict_inode = coda_evict_inode, .put_super = coda_put_super, .statfs = coda_statfs, .remount_fs = coda_remount, @@ -224,8 +224,10 @@ static void coda_put_super(struct super_block *sb) printk("Coda: Bye bye.\n"); } -static void coda_clear_inode(struct inode *inode) +static void coda_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); coda_cache_clear_inode(inode); } diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 0435886e4a9f..4b5de6c6e0fa 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -122,7 +122,7 @@ static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) } /** - * ecryptfs_clear_inode + * ecryptfs_evict_inode * @inode - The ecryptfs inode * * Called by iput() when the inode reference count reached zero @@ -131,8 +131,10 @@ static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) * on the inode free list. We use this to drop out reference to the * lower inode. */ -static void ecryptfs_clear_inode(struct inode *inode) +static void ecryptfs_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); iput(ecryptfs_inode_to_lower(inode)); } @@ -184,6 +186,6 @@ const struct super_operations ecryptfs_sops = { .drop_inode = generic_delete_inode, .statfs = ecryptfs_statfs, .remount_fs = NULL, - .clear_inode = ecryptfs_clear_inode, + .evict_inode = ecryptfs_evict_inode, .show_options = ecryptfs_show_options }; diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 50ab5eecb99b..881aa3d217f0 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -63,7 +63,7 @@ extern void vxfs_put_fake_inode(struct inode *); extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); extern struct inode * vxfs_iget(struct super_block *, ino_t); -extern void vxfs_clear_inode(struct inode *); +extern void vxfs_evict_inode(struct inode *); /* vxfs_lookup.c */ extern const struct inode_operations vxfs_dir_inode_ops; diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 03a6ea5e99f7..79d1b4ea13e7 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -337,15 +337,17 @@ vxfs_iget(struct super_block *sbp, ino_t ino) } /** - * vxfs_clear_inode - remove inode from main memory + * vxfs_evict_inode - remove inode from main memory * @ip: inode to discard. * * Description: - * vxfs_clear_inode() is called on the final iput and frees the private + * vxfs_evict_inode() is called on the final iput and frees the private * inode area. */ void -vxfs_clear_inode(struct inode *ip) +vxfs_evict_inode(struct inode *ip) { + truncate_inode_pages(&ip->i_data, 0); + end_writeback(ip); kmem_cache_free(vxfs_inode_cachep, ip->i_private); } diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1e8af939b3e4..1f3ffd93b357 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -61,7 +61,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *); static int vxfs_remount(struct super_block *, int *, char *); static const struct super_operations vxfs_super_ops = { - .clear_inode = vxfs_clear_inode, + .evict_inode = vxfs_evict_inode, .put_super = vxfs_put_super, .statfs = vxfs_statfs, .remount_fs = vxfs_remount, diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index ec14d19ce501..da9e6e11374c 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -122,8 +122,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, fuse_request_send_noreply(fc, req); } -static void fuse_clear_inode(struct inode *inode) +static void fuse_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); if (inode->i_sb->s_flags & MS_ACTIVE) { struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); @@ -736,7 +738,7 @@ static const struct export_operations fuse_export_operations = { static const struct super_operations fuse_super_operations = { .alloc_inode = fuse_alloc_inode, .destroy_inode = fuse_destroy_inode, - .clear_inode = fuse_clear_inode, + .evict_inode = fuse_evict_inode, .drop_inode = generic_delete_inode, .remount_fs = fuse_remount_fs, .put_super = fuse_put_super, diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index fe35e3b626c4..4f55651aaa51 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -193,7 +193,7 @@ extern int hfs_inode_setattr(struct dentry *, struct iattr *); extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, __be32 log_size, __be32 phys_size, u32 clump_size); extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *); -extern void hfs_clear_inode(struct inode *); +extern void hfs_evict_inode(struct inode *); extern void hfs_delete_inode(struct inode *); /* attr.c */ diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 93ceec8fbb8f..397b7adc7ce6 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -531,8 +531,10 @@ out: return NULL; } -void hfs_clear_inode(struct inode *inode) +void hfs_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) { HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL; iput(HFS_I(inode)->rsrc_inode); diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 0a81eb7111f3..34235d4bf08b 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -181,7 +181,7 @@ static const struct super_operations hfs_super_operations = { .alloc_inode = hfs_alloc_inode, .destroy_inode = hfs_destroy_inode, .write_inode = hfs_write_inode, - .clear_inode = hfs_clear_inode, + .evict_inode = hfs_evict_inode, .put_super = hfs_put_super, .write_super = hfs_write_super, .sync_fs = hfs_sync_fs, diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index a32c241e4e45..3b55c050c742 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -145,9 +145,11 @@ static int hfsplus_write_inode(struct inode *inode, return ret; } -static void hfsplus_clear_inode(struct inode *inode) +static void hfsplus_evict_inode(struct inode *inode) { - dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); + dprint(DBG_INODE, "hfsplus_evict_inode: %lu\n", inode->i_ino); + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); if (HFSPLUS_IS_RSRC(inode)) { HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; iput(HFSPLUS_I(inode).rsrc_inode); @@ -293,7 +295,7 @@ static const struct super_operations hfsplus_sops = { .alloc_inode = hfsplus_alloc_inode, .destroy_inode = hfsplus_destroy_inode, .write_inode = hfsplus_write_inode, - .clear_inode = hfsplus_clear_inode, + .evict_inode = hfsplus_evict_inode, .put_super = hfsplus_put_super, .write_super = hfsplus_write_super, .sync_fs = hfsplus_sync_fs, diff --git a/fs/inode.c b/fs/inode.c index 0e077619cbf6..5daeb0b8fb59 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -317,8 +317,6 @@ static void evict(struct inode *inode) truncate_inode_pages(&inode->i_data, 0); invalidate_inode_buffers(inode); end_writeback(inode); - if (op->clear_inode) - op->clear_inode(inode); } if (S_ISBLK(inode->i_mode) && inode->i_bdev) bd_forget(inode); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 1b2426604fe3..ac0638f04969 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -225,7 +225,7 @@ int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf) } -void jffs2_clear_inode (struct inode *inode) +void jffs2_evict_inode (struct inode *inode) { /* We can forget about this inode for now - drop all * the nodelists associated with it, etc. @@ -233,7 +233,9 @@ void jffs2_clear_inode (struct inode *inode) struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); + D1(printk(KERN_DEBUG "jffs2_evict_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); jffs2_do_clear_inode(c, f); } diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 4791aacf3084..00bae7cc2e48 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -171,7 +171,7 @@ extern const struct inode_operations jffs2_symlink_inode_operations; int jffs2_setattr (struct dentry *, struct iattr *); int jffs2_do_setattr (struct inode *, struct iattr *); struct inode *jffs2_iget(struct super_block *, unsigned long); -void jffs2_clear_inode (struct inode *); +void jffs2_evict_inode (struct inode *); void jffs2_dirty_inode(struct inode *inode); struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri); diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 511e2d609d12..662bba099501 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -135,7 +135,7 @@ static const struct super_operations jffs2_super_operations = .write_super = jffs2_write_super, .statfs = jffs2_statfs, .remount_fs = jffs2_remount_fs, - .clear_inode = jffs2_clear_inode, + .evict_inode = jffs2_evict_inode, .dirty_inode = jffs2_dirty_inode, .sync_fs = jffs2_sync_fs, }; diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index d258e261bdc7..9b572ca40a49 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -588,7 +588,7 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { - /* It's called from jffs2_clear_inode() on inode removing. + /* It's called from jffs2_evict_inode() on inode removing. When an inode with XATTR is removed, those XATTRs must be removed. */ struct jffs2_xattr_ref *ref, *_ref; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 099b3518feea..c211b8168e5b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -98,7 +98,7 @@ u64 nfs_compat_user_ino64(u64 fileid) return ino; } -void nfs_clear_inode(struct inode *inode) +static void nfs_clear_inode(struct inode *inode) { /* * The following should never happen... @@ -110,6 +110,13 @@ void nfs_clear_inode(struct inode *inode) nfs_fscache_release_inode_cookie(inode); } +void nfs_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); + nfs_clear_inode(inode); +} + /** * nfs_sync_mapping - helper to flush all mmapped dirty data to disk */ @@ -1338,8 +1345,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) * to open() calls that passed nfs_atomic_lookup, but failed to call * nfs_open(). */ -void nfs4_clear_inode(struct inode *inode) +void nfs4_evict_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); /* If we are holding a delegation, return it! */ nfs_inode_return_delegation_noreclaim(inode); /* First call standard NFS clear_inode() code */ diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e70f44b9b3f4..f168ebdf7c6d 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -213,9 +213,9 @@ extern struct workqueue_struct *nfsiod_workqueue; extern struct inode *nfs_alloc_inode(struct super_block *sb); extern void nfs_destroy_inode(struct inode *); extern int nfs_write_inode(struct inode *, struct writeback_control *); -extern void nfs_clear_inode(struct inode *); +extern void nfs_evict_inode(struct inode *); #ifdef CONFIG_NFS_V4 -extern void nfs4_clear_inode(struct inode *); +extern void nfs4_evict_inode(struct inode *); #endif void nfs_zap_acl_cache(struct inode *inode); extern int nfs_wait_bit_killable(void *word); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index f9df16de4a56..ef2b7e468a7e 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -270,7 +270,7 @@ static const struct super_operations nfs_sops = { .write_inode = nfs_write_inode, .put_super = nfs_put_super, .statfs = nfs_statfs, - .clear_inode = nfs_clear_inode, + .evict_inode = nfs_evict_inode, .umount_begin = nfs_umount_begin, .show_options = nfs_show_options, .show_stats = nfs_show_stats, @@ -340,7 +340,7 @@ static const struct super_operations nfs4_sops = { .write_inode = nfs_write_inode, .put_super = nfs_put_super, .statfs = nfs_statfs, - .clear_inode = nfs4_clear_inode, + .evict_inode = nfs4_evict_inode, .umount_begin = nfs_umount_begin, .show_options = nfs_show_options, .show_stats = nfs_show_stats, diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index fdef8f729c3a..93622b175fc7 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -2238,7 +2238,7 @@ void ntfs_clear_extent_inode(ntfs_inode *ni) } /** - * ntfs_clear_big_inode - clean up the ntfs specific part of an inode + * ntfs_evict_big_inode - clean up the ntfs specific part of an inode * @vi: vfs inode pending annihilation * * When the VFS is going to remove an inode from memory, ntfs_clear_big_inode() @@ -2247,10 +2247,13 @@ void ntfs_clear_extent_inode(ntfs_inode *ni) * * If the MFT record is dirty, we commit it before doing anything else. */ -void ntfs_clear_big_inode(struct inode *vi) +void ntfs_evict_big_inode(struct inode *vi) { ntfs_inode *ni = NTFS_I(vi); + truncate_inode_pages(&vi->i_data, 0); + end_writeback(vi); + #ifdef NTFS_RW if (NInoDirty(ni)) { bool was_bad = (is_bad_inode(vi)); diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 9a113544605d..2dabf813456c 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -279,7 +279,7 @@ extern struct inode *ntfs_index_iget(struct inode *base_vi, ntfschar *name, extern struct inode *ntfs_alloc_big_inode(struct super_block *sb); extern void ntfs_destroy_big_inode(struct inode *inode); -extern void ntfs_clear_big_inode(struct inode *vi); +extern void ntfs_evict_big_inode(struct inode *vi); extern void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni); diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 0de1db6cddbf..512806171bfa 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2700,7 +2700,7 @@ static const struct super_operations ntfs_sops = { .put_super = ntfs_put_super, /* Syscall: umount. */ .statfs = ntfs_statfs, /* Syscall: statfs */ .remount_fs = ntfs_remount, /* Syscall: mount -o remount. */ - .clear_inode = ntfs_clear_big_inode, /* VFS: Called when an inode is + .evict_inode = ntfs_evict_big_inode, /* VFS: Called when an inode is removed from memory. */ //.umount_begin = NULL, /* Forced umount. */ .show_options = ntfs_show_options, /* Show mount options in diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index 85e4ccaedd1f..a43ebb11ad3b 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c @@ -357,13 +357,12 @@ static void dlmfs_destroy_inode(struct inode *inode) kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode)); } -static void dlmfs_clear_inode(struct inode *inode) +static void dlmfs_evict_inode(struct inode *inode) { int status; struct dlmfs_inode_private *ip; - if (!inode) - return; + end_writeback(inode); mlog(0, "inode %lu\n", inode->i_ino); @@ -633,7 +632,7 @@ static const struct super_operations dlmfs_ops = { .statfs = simple_statfs, .alloc_inode = dlmfs_alloc_inode, .destroy_inode = dlmfs_destroy_inode, - .clear_inode = dlmfs_clear_inode, + .evict_inode = dlmfs_evict_inode, .drop_inode = generic_delete_inode, }; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 758df94690ed..15c35b62ff14 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1100,13 +1100,15 @@ xfs_fs_write_inode( } STATIC void -xfs_fs_clear_inode( +xfs_fs_evict_inode( struct inode *inode) { xfs_inode_t *ip = XFS_I(inode); - trace_xfs_clear_inode(ip); + trace_xfs_evict_inode(ip); + truncate_inode_pages(&inode->i_data, 0); + end_writeback(inode); XFS_STATS_INC(vn_rele); XFS_STATS_INC(vn_remove); XFS_STATS_DEC(vn_active); @@ -1622,7 +1624,7 @@ static const struct super_operations xfs_super_operations = { .destroy_inode = xfs_fs_destroy_inode, .dirty_inode = xfs_fs_dirty_inode, .write_inode = xfs_fs_write_inode, - .clear_inode = xfs_fs_clear_inode, + .evict_inode = xfs_fs_evict_inode, .put_super = xfs_fs_put_super, .sync_fs = xfs_fs_sync_fs, .freeze_fs = xfs_fs_freeze, diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h index c657cdca2cd2..be5dffd282a1 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/linux-2.6/xfs_trace.h @@ -581,7 +581,7 @@ DEFINE_INODE_EVENT(xfs_ioctl_setattr); DEFINE_INODE_EVENT(xfs_file_fsync); DEFINE_INODE_EVENT(xfs_destroy_inode); DEFINE_INODE_EVENT(xfs_write_inode); -DEFINE_INODE_EVENT(xfs_clear_inode); +DEFINE_INODE_EVENT(xfs_evict_inode); DEFINE_INODE_EVENT(xfs_dquot_dqalloc); DEFINE_INODE_EVENT(xfs_dquot_dqdetach); diff --git a/include/linux/fs.h b/include/linux/fs.h index 8553adbda57b..dec9ac598859 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1571,7 +1571,6 @@ struct super_operations { int (*unfreeze_fs) (struct super_block *); int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); - void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); int (*show_options)(struct seq_file *, struct vfsmount *); @@ -1616,7 +1615,7 @@ struct super_operations { * I_FREEING Set when inode is about to be freed but still has dirty * pages or buffers attached or the inode itself is still * dirty. - * I_CLEAR Added by clear_inode(). In this state the inode is clean + * I_CLEAR Added by end_writeback(). In this state the inode is clean * and can be destroyed. Inode keeps I_FREEING. * * Inodes that are I_WILL_FREE, I_FREEING or I_CLEAR are -- cgit v1.2.3