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/xfs/linux-2.6/xfs_aops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/xfs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index d24e78f32f3e..7968d41e27ad 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1478,17 +1478,17 @@ xfs_vm_direct_IO( if (rw & WRITE) { iocb->private = xfs_alloc_ioend(inode, IO_NEW); - ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, - offset, nr_segs, - xfs_get_blocks_direct, - xfs_end_io_direct_write); + ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, + offset, nr_segs, + xfs_get_blocks_direct, + xfs_end_io_direct_write, NULL, 0); if (ret != -EIOCBQUEUED && iocb->private) xfs_destroy_ioend(iocb->private); } else { - ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, - offset, nr_segs, - xfs_get_blocks_direct, - NULL); + ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, + offset, nr_segs, + xfs_get_blocks_direct, + NULL, NULL, 0); } return ret; -- cgit v1.2.3 From 155130a4f7848b1aac439cab6bda1a175507c71c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:29:58 +0200 Subject: get rid of block_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 block_write_begin. While we're at it also remove several unused arguments to block_write_begin. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/bfs/file.c | 14 ++++++++--- fs/block_dev.c | 5 ++-- fs/buffer.c | 61 +++++++-------------------------------------- fs/ext2/inode.c | 5 ++-- fs/minix/inode.c | 12 +++++++-- fs/nilfs2/inode.c | 12 ++++++--- fs/nilfs2/recovery.c | 11 +++++--- fs/omfs/file.c | 14 ++++++++--- fs/sysv/itree.c | 13 +++++++--- fs/udf/inode.c | 13 +++++++--- fs/ufs/inode.c | 12 +++++++-- fs/xfs/linux-2.6/xfs_aops.c | 14 ++++++++--- include/linux/buffer_head.h | 8 ++---- 13 files changed, 103 insertions(+), 91 deletions(-) (limited to 'fs/xfs') diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 88b9a3ff44e4..8fc2e9c9739d 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -168,9 +168,17 @@ static int bfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, - pagep, fsdata, bfs_get_block); + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, + bfs_get_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t bfs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/block_dev.c b/fs/block_dev.c index 65a0c26508e5..63c9d6076205 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -308,9 +308,8 @@ static int blkdev_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin_newtrunc(file, mapping, pos, len, flags, - pagep, fsdata, blkdev_get_block); + return block_write_begin(mapping, pos, len, flags, pagep, + blkdev_get_block); } static int blkdev_write_end(struct file *file, struct address_space *mapping, diff --git a/fs/buffer.c b/fs/buffer.c index c319c49da511..50efa339e051 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1962,14 +1962,13 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, EXPORT_SYMBOL(__block_write_begin); /* - * Filesystems implementing the new truncate sequence should use the - * _newtrunc postfix variant which won't incorrectly call vmtruncate. + * block_write_begin takes care of the basic task of block allocation and + * bringing partial write blocks uptodate first. + * * The filesystem needs to handle block truncation upon failure. */ -int block_write_begin_newtrunc(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata, - get_block_t *get_block) +int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len, + unsigned flags, struct page **pagep, get_block_t *get_block) { pgoff_t index = pos >> PAGE_CACHE_SHIFT; struct page *page; @@ -1989,44 +1988,6 @@ int block_write_begin_newtrunc(struct file *file, struct address_space *mapping, *pagep = page; return status; } -EXPORT_SYMBOL(block_write_begin_newtrunc); - -/* - * block_write_begin takes care of the basic task of block allocation and - * bringing partial write blocks uptodate first. - * - * If *pagep is not NULL, then block_write_begin uses the locked page - * at *pagep rather than allocating its own. In this case, the page will - * not be unlocked or deallocated on failure. - */ -int block_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) -{ - int ret; - - ret = block_write_begin_newtrunc(file, mapping, pos, len, flags, - pagep, fsdata, get_block); - - /* - * prepare_write() may have instantiated a few blocks - * outside i_size. Trim these off again. Don't need - * i_size_read because we hold i_mutex. - * - * Filesystems which pass down their own page also cannot - * call into vmtruncate here because it would lead to lock - * inversion problems (*pagep is locked). This is a further - * example of where the old truncate sequence is inadequate. - */ - if (unlikely(ret) && *pagep == NULL) { - loff_t isize = mapping->host->i_size; - if (pos + len > isize) - vmtruncate(mapping->host, isize); - } - - return ret; -} EXPORT_SYMBOL(block_write_begin); int block_write_end(struct file *file, struct address_space *mapping, @@ -2357,7 +2318,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping, err = cont_expand_zero(file, mapping, pos, bytes); if (err) - goto out; + return err; zerofrom = *bytes & ~PAGE_CACHE_MASK; if (pos+len > *bytes && zerofrom & (blocksize-1)) { @@ -2365,11 +2326,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping, (*bytes)++; } - *pagep = NULL; - err = block_write_begin_newtrunc(file, mapping, pos, len, - flags, pagep, fsdata, get_block); -out: - return err; + return block_write_begin(mapping, pos, len, flags, pagep, get_block); } EXPORT_SYMBOL(cont_write_begin); @@ -2511,8 +2468,8 @@ int nobh_write_begin(struct address_space *mapping, unlock_page(page); page_cache_release(page); *pagep = NULL; - return block_write_begin_newtrunc(NULL, mapping, pos, len, - flags, pagep, fsdata, get_block); + return block_write_begin(mapping, pos, len, flags, pagep, + get_block); } if (PageMappedToDisk(page)) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 2f4dfbcd7696..74dfe5f73330 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -772,9 +772,8 @@ ext2_write_begin(struct file *file, struct address_space *mapping, { int ret; - *pagep = NULL; - ret = block_write_begin_newtrunc(file, mapping, pos, len, flags, - pagep, fsdata, ext2_get_block); + ret = block_write_begin(mapping, pos, len, flags, pagep, + ext2_get_block); if (ret < 0) ext2_write_failed(mapping, pos + len); return ret; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 6b29e73f0ca6..125062f55ef2 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -366,9 +366,17 @@ static int minix_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, minix_get_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t minix_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 1dd9e6a7d787..5c694ece172e 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -197,11 +197,15 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping, if (unlikely(err)) return err; - *pagep = NULL; - err = block_write_begin(file, mapping, pos, len, flags, pagep, - fsdata, nilfs_get_block); - if (unlikely(err)) + err = block_write_begin(mapping, pos, len, flags, pagep, + nilfs_get_block); + if (unlikely(err)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + nilfs_transaction_abort(inode->i_sb); + } return err; } diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index bae2a516b4ee..2f11f0868d87 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -505,11 +505,14 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, } pos = rb->blkoff << inode->i_blkbits; - page = NULL; - err = block_write_begin(NULL, inode->i_mapping, pos, blocksize, - 0, &page, NULL, nilfs_get_block); - if (unlikely(err)) + err = block_write_begin(inode->i_mapping, pos, blocksize, + 0, &page, nilfs_get_block); + if (unlikely(err)) { + loff_t isize = inode->i_size; + if (pos + blocksize > isize) + vmtruncate(inode, isize); goto failed_inode; + } err = nilfs_recovery_copy_block(sbi, rb, page); if (unlikely(err)) diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 6e7a3291bbe8..810cff346468 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -312,9 +312,17 @@ static int omfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, - pagep, fsdata, omfs_get_block); + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, + omfs_get_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t omfs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index 82a005c3d7eb..9ca66276315e 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c @@ -468,9 +468,16 @@ static int sysv_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, - get_block); + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, get_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t sysv_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 124852bcf6fe..ecddcc2ed746 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -127,9 +127,16 @@ static int udf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, - udf_get_block); + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t udf_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 45ce32391f8f..45cafa937a4b 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -567,9 +567,17 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, ufs_getfrag_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t ufs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7968d41e27ad..bf7aad0d78b8 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1504,9 +1504,17 @@ xfs_vm_write_begin( struct page **pagep, void **fsdata) { - *pagep = NULL; - return block_write_begin(file, mapping, pos, len, flags | AOP_FLAG_NOFS, - pagep, fsdata, xfs_get_blocks); + int ret; + + ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS, + pagep, xfs_get_blocks); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } STATIC sector_t diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index accc9f81bb63..3f69054f86d9 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -203,12 +203,8 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block, int block_read_full_page(struct page*, get_block_t*); int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, unsigned long from); -int block_write_begin_newtrunc(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page **, void **, get_block_t*); -int block_write_begin(struct file *, struct address_space *, - loff_t, unsigned, unsigned, - struct page **, void **, get_block_t*); +int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len, + unsigned flags, struct page **pagep, get_block_t *get_block); int __block_write_begin(struct page *page, loff_t pos, unsigned len, get_block_t *get_block); int block_write_end(struct file *, struct address_space *, -- cgit v1.2.3 From fa9b227e9019ebaeeb06224ba531a490f91144b3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Jun 2010 05:17:31 -0400 Subject: xfs: new truncate sequence Convert XFS to the new truncate sequence. We still can have errors after updating the file size in xfs_setattr, but these are real I/O errors and lead to a transaction abort and filesystem shutdown, so they are not an issue. Errors from ->write_begin and write_end can now be handled correctly because we can actually get rid of the delalloc extents while previous the buffer state was stipped in block_invalidatepage. There is still no error handling for ->direct_IO, because doing so will need some major restructuring given that we only have the iolock shared and do not hold i_mutex at all. Fortunately leaving the normally allocated blocks behind there is not a major issue and this will get cleaned up by xfs_free_eofblock later. Note: the patch is against Al's vfs.git tree as that contains the nessecary preparations. I'd prefer to get it applied there so that we can get some testing in linux-next. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/xfs/linux-2.6/xfs_aops.c | 42 ++++++++++++++++++++++++++++++++++++------ fs/xfs/linux-2.6/xfs_iops.c | 16 ---------------- fs/xfs/linux-2.6/xfs_linux.h | 2 -- fs/xfs/xfs_vnodeops.c | 38 ++++++++++++++++++++------------------ 4 files changed, 56 insertions(+), 42 deletions(-) (limited to 'fs/xfs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index bf7aad0d78b8..15412fe15c3a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1494,6 +1494,22 @@ xfs_vm_direct_IO( return ret; } +STATIC void +xfs_vm_write_failed( + struct address_space *mapping, + loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > inode->i_size) { + struct iattr ia = { + .ia_valid = ATTR_SIZE | ATTR_FORCE, + .ia_size = inode->i_size, + }; + xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK); + } +} + STATIC int xfs_vm_write_begin( struct file *file, @@ -1508,12 +1524,26 @@ xfs_vm_write_begin( ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS, pagep, xfs_get_blocks); - if (unlikely(ret)) { - loff_t isize = mapping->host->i_size; - if (pos + len > isize) - vmtruncate(mapping->host, isize); - } + if (unlikely(ret)) + xfs_vm_write_failed(mapping, pos + len); + return ret; +} + +STATIC int +xfs_vm_write_end( + struct file *file, + struct address_space *mapping, + loff_t pos, + unsigned len, + unsigned copied, + struct page *page, + void *fsdata) +{ + int ret; + ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); + if (unlikely(ret < len)) + xfs_vm_write_failed(mapping, pos + len); return ret; } @@ -1559,7 +1589,7 @@ const struct address_space_operations xfs_address_space_operations = { .releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, .write_begin = xfs_vm_write_begin, - .write_end = generic_write_end, + .write_end = xfs_vm_write_end, .bmap = xfs_vm_bmap, .direct_IO = xfs_vm_direct_IO, .migratepage = buffer_migrate_page, diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 536b81e63a3d..62dd349facee 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -540,21 +540,6 @@ xfs_vn_setattr( return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0); } -/* - * block_truncate_page can return an error, but we can't propagate it - * at all here. Leave a complaint + stack trace in the syslog because - * this could be bad. If it is bad, we need to propagate the error further. - */ -STATIC void -xfs_vn_truncate( - struct inode *inode) -{ - int error; - error = block_truncate_page(inode->i_mapping, inode->i_size, - xfs_get_blocks); - WARN_ON(error); -} - STATIC long xfs_vn_fallocate( struct inode *inode, @@ -694,7 +679,6 @@ xfs_vn_fiemap( static const struct inode_operations xfs_inode_operations = { .check_acl = xfs_check_acl, - .truncate = xfs_vn_truncate, .getattr = xfs_vn_getattr, .setattr = xfs_vn_setattr, .setxattr = generic_setxattr, diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 998a9d7fb9c8..2fa0bd9ebc7f 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -156,8 +156,6 @@ */ #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) #define xfs_stack_trace() dump_stack() -#define xfs_itruncate_data(ip, off) \ - (-vmtruncate(VFS_I(ip), (off))) /* Move the kernel do_div definition off to one side */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 3ac137dd531b..66d585c6917c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -221,8 +221,11 @@ xfs_setattr( * transaction to modify the i_size. */ code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size); + if (code) + goto error_return; } xfs_iunlock(ip, XFS_ILOCK_EXCL); + lock_flags &= ~XFS_ILOCK_EXCL; /* * We are going to log the inode size change in this @@ -236,36 +239,35 @@ xfs_setattr( * really care about here and prevents waiting for other data * not within the range we care about here. */ - if (!code && - ip->i_size != ip->i_d.di_size && + if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) { code = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, XBF_ASYNC, FI_NONE); + if (code) + goto error_return; } /* wait for all I/O to complete */ xfs_ioend_wait(ip); - if (!code) - code = xfs_itruncate_data(ip, iattr->ia_size); - if (code) { - ASSERT(tp == NULL); - lock_flags &= ~XFS_ILOCK_EXCL; - ASSERT(lock_flags == XFS_IOLOCK_EXCL || !need_iolock); + code = -block_truncate_page(inode->i_mapping, iattr->ia_size, + xfs_get_blocks); + if (code) goto error_return; - } + tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); - if ((code = xfs_trans_reserve(tp, 0, - XFS_ITRUNCATE_LOG_RES(mp), 0, - XFS_TRANS_PERM_LOG_RES, - XFS_ITRUNCATE_LOG_COUNT))) { - xfs_trans_cancel(tp, 0); - if (need_iolock) - xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return code; - } + code = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, + XFS_TRANS_PERM_LOG_RES, + XFS_ITRUNCATE_LOG_COUNT); + if (code) + goto error_return; + + truncate_setsize(inode, iattr->ia_size); + commit_flags = XFS_TRANS_RELEASE_LOG_RES; + lock_flags |= XFS_ILOCK_EXCL; + xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip); -- cgit v1.2.3 From a4ffdde6e56fdf8c34ddadc2674d6eb978083369 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 Jun 2010 17:38:30 -0400 Subject: simplify checks for I_CLEAR/I_FREEING add I_CLEAR instead of replacing I_FREEING with it. I_CLEAR is equivalent to I_FREEING for almost all code looking at either; it's there to keep track of having called clear_inode() exactly once per inode lifetime, at some point after having set I_FREEING. I_CLEAR and I_FREEING never get set at the same time with the current code, so we can switch to setting i_flags to I_FREEING | I_CLEAR instead of I_CLEAR without loss of information. As the result of such change, checks become simpler and the amount of code that needs to know about I_CLEAR shrinks a lot. Signed-off-by: Al Viro --- fs/btrfs/inode.c | 2 +- fs/drop_caches.c | 2 +- fs/fs-writeback.c | 8 ++++---- fs/gfs2/inode.c | 2 +- fs/inode.c | 16 ++++++++-------- fs/nilfs2/gcdat.c | 2 +- fs/notify/inode_mark.c | 6 +++--- fs/notify/inotify/inotify.c | 7 +++---- fs/quota/dquot.c | 2 +- fs/xfs/linux-2.6/xfs_iops.c | 4 ++-- include/linux/fs.h | 4 ++-- 11 files changed, 27 insertions(+), 28 deletions(-) (limited to 'fs/xfs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7f9e0536db1a..95eac0116963 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3860,7 +3860,7 @@ again: p = &parent->rb_right; else { WARN_ON(!(entry->vfs_inode.i_state & - (I_WILL_FREE | I_FREEING | I_CLEAR))); + (I_WILL_FREE | I_FREEING))); rb_erase(parent, &root->inode_tree); RB_CLEAR_NODE(parent); spin_unlock(&root->inode_lock); diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 83c4f600786a..2195c213ab2f 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; if (inode->i_mapping->nrpages == 0) continue; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index d5be1693ac93..7608880b5c58 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -352,7 +352,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) spin_lock(&inode_lock); inode->i_state &= ~I_SYNC; - if (!(inode->i_state & (I_FREEING | I_CLEAR))) { + if (!(inode->i_state & I_FREEING)) { if ((inode->i_state & I_DIRTY_PAGES) && wbc->for_kupdate) { /* * More pages get dirtied by a fast dirtier. @@ -499,7 +499,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, if (inode_dirtied_after(inode, wbc->wb_start)) return 1; - BUG_ON(inode->i_state & (I_FREEING | I_CLEAR)); + BUG_ON(inode->i_state & I_FREEING); __iget(inode); pages_skipped = wbc->pages_skipped; writeback_single_inode(inode, wbc); @@ -935,7 +935,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) if (hlist_unhashed(&inode->i_hash)) goto out; } - if (inode->i_state & (I_FREEING|I_CLEAR)) + if (inode->i_state & I_FREEING) goto out; /* @@ -1001,7 +1001,7 @@ static void wait_sb_inodes(struct super_block *sb) list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { struct address_space *mapping; - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; mapping = inode->i_mapping; if (mapping->nrpages == 0) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 6c023a3b5d25..08140f185a37 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -84,7 +84,7 @@ static int iget_skip_test(struct inode *inode, void *opaque) struct gfs2_skip_data *data = opaque; if (ip->i_no_addr == data->no_addr) { - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ + if (inode->i_state & (I_FREEING|I_WILL_FREE)){ data->skipped = 1; return 0; } diff --git a/fs/inode.c b/fs/inode.c index 722860b323a9..71fe079ca32a 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -317,7 +317,7 @@ void clear_inode(struct inode *inode) bd_forget(inode); if (S_ISCHR(inode->i_mode) && inode->i_cdev) cd_forget(inode); - inode->i_state = I_CLEAR; + inode->i_state = I_FREEING | I_CLEAR; } EXPORT_SYMBOL(clear_inode); @@ -553,7 +553,7 @@ repeat: continue; if (!test(inode, data)) continue; - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { + if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; } @@ -578,7 +578,7 @@ repeat: continue; if (inode->i_sb != sb) continue; - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { + if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; } @@ -840,7 +840,7 @@ EXPORT_SYMBOL(iunique); struct inode *igrab(struct inode *inode) { spin_lock(&inode_lock); - if (!(inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))) + if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) __iget(inode); else /* @@ -1089,7 +1089,7 @@ int insert_inode_locked(struct inode *inode) continue; if (old->i_sb != sb) continue; - if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) + if (old->i_state & (I_FREEING|I_WILL_FREE)) continue; break; } @@ -1128,7 +1128,7 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, continue; if (!test(old, data)) continue; - if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) + if (old->i_state & (I_FREEING|I_WILL_FREE)) continue; break; } @@ -1218,7 +1218,7 @@ void generic_delete_inode(struct inode *inode) hlist_del_init(&inode->i_hash); spin_unlock(&inode_lock); wake_up_inode(inode); - BUG_ON(inode->i_state != I_CLEAR); + BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); destroy_inode(inode); } EXPORT_SYMBOL(generic_delete_inode); @@ -1322,7 +1322,7 @@ static inline void iput_final(struct inode *inode) void iput(struct inode *inode) { if (inode) { - BUG_ON(inode->i_state == I_CLEAR); + BUG_ON(inode->i_state & I_CLEAR); if (atomic_dec_and_lock(&inode->i_count, &inode_lock)) iput_final(inode); diff --git a/fs/nilfs2/gcdat.c b/fs/nilfs2/gcdat.c index dd5f7e0a95f6..84a45d1d5464 100644 --- a/fs/nilfs2/gcdat.c +++ b/fs/nilfs2/gcdat.c @@ -78,7 +78,7 @@ void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs) struct inode *gcdat = nilfs->ns_gc_dat; struct nilfs_inode_info *gii = NILFS_I(gcdat); - gcdat->i_state = I_CLEAR; + gcdat->i_state = I_FREEING | I_CLEAR; gii->i_flags = 0; nilfs_palloc_clear_cache(gcdat); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 0399bcbe09c8..152b83ec005d 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -369,11 +369,11 @@ void fsnotify_unmount_inodes(struct list_head *list) struct inode *need_iput_tmp; /* - * We cannot __iget() an inode in state I_CLEAR, I_FREEING, + * We cannot __iget() an inode in state I_FREEING, * I_WILL_FREE, or I_NEW which is fine because by that point * the inode cannot have any associated watches. */ - if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; /* @@ -397,7 +397,7 @@ void fsnotify_unmount_inodes(struct list_head *list) /* In case the dropping of a reference would nuke next_i. */ if ((&next_i->i_sb_list != list) && atomic_read(&next_i->i_count) && - !(next_i->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE))) { + !(next_i->i_state & (I_FREEING | I_WILL_FREE))) { __iget(next_i); need_iput = next_i; } diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c index 27b75ebc7460..cf6b0429a257 100644 --- a/fs/notify/inotify/inotify.c +++ b/fs/notify/inotify/inotify.c @@ -377,11 +377,11 @@ void inotify_unmount_inodes(struct list_head *list) struct list_head *watches; /* - * We cannot __iget() an inode in state I_CLEAR, I_FREEING, + * We cannot __iget() an inode in state I_FREEING, * I_WILL_FREE, or I_NEW which is fine because by that point * the inode cannot have any associated watches. */ - if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; /* @@ -403,8 +403,7 @@ void inotify_unmount_inodes(struct list_head *list) /* In case the dropping of a reference would nuke next_i. */ if ((&next_i->i_sb_list != list) && atomic_read(&next_i->i_count) && - !(next_i->i_state & (I_CLEAR | I_FREEING | - I_WILL_FREE))) { + !(next_i->i_state & (I_FREEING|I_WILL_FREE))) { __iget(next_i); need_iput = next_i; } diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 437d2ca2de97..5cec3e2348f1 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -885,7 +885,7 @@ static void add_dquot_ref(struct super_block *sb, int type) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; #ifdef CONFIG_QUOTA_DEBUG if (unlikely(inode_get_rsv_space(inode) > 0)) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 62dd349facee..68be25dcd301 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -80,7 +80,7 @@ xfs_mark_inode_dirty_sync( { struct inode *inode = VFS_I(ip); - if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR))) + if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) mark_inode_dirty_sync(inode); } @@ -90,7 +90,7 @@ xfs_mark_inode_dirty( { struct inode *inode = VFS_I(ip); - if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR))) + if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) mark_inode_dirty(inode); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 5547b1b027db..218693d8d446 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1616,8 +1616,8 @@ 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 Set by clear_inode(). In this state the inode is clean - * and can be destroyed. + * I_CLEAR Added by clear_inode(). 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 * prohibited for many purposes. iget() must wait for -- 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/xfs') 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