From: Christoph Hellwig <hch@infradead.org>
To: npiggin@suse.de
Cc: Andrew Morton <akpm@linux-foundation.org>,
linux-fsdevel@vger.kernel.org, xfs@oss.sgi.com
Subject: [PATCH 13/n] xfs: new truncate sequence
Date: Tue, 22 Sep 2009 16:54:47 -0400 [thread overview]
Message-ID: <20090922205447.GB12224@infradead.org> (raw)
In-Reply-To: <20090820163504.131529718@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: vfs-2.6.git/fs/xfs/linux-2.6/xfs_aops.c
===================================================================
--- vfs-2.6.git.orig/fs/xfs/linux-2.6/xfs_aops.c 2009-09-22 11:28:48.581004129 -0300
+++ vfs-2.6.git/fs/xfs/linux-2.6/xfs_aops.c 2009-09-22 12:11:08.625765641 -0300
@@ -1563,6 +1563,45 @@ xfs_vm_direct_IO(
return ret;
}
+STATIC void
+xfs_truncate_excess_blocks(
+ struct address_space *mapping,
+ loff_t pos,
+ unsigned len)
+{
+ struct inode *inode = mapping->host;
+ loff_t isize = inode->i_size;
+
+ if (pos + len > isize) {
+ struct iattr ia;
+ int error;
+
+ ia.ia_valid = ATTR_SIZE | ATTR_FORCE,
+ ia.ia_size = isize,
+
+ error = xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK);
+ WARN_ON(error); /* not much we can do here. */
+ }
+}
+
+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 (ret < len)
+ xfs_truncate_excess_blocks(mapping, pos, len);
+ return ret;
+}
+
STATIC int
xfs_vm_write_begin(
struct file *file,
@@ -1573,9 +1612,14 @@ xfs_vm_write_begin(
struct page **pagep,
void **fsdata)
{
+ int ret;
+
*pagep = NULL;
- return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
xfs_get_blocks);
+ if (ret < 0)
+ xfs_truncate_excess_blocks(mapping, pos, len);
+ return ret;
}
STATIC sector_t
@@ -1630,7 +1674,7 @@ const struct address_space_operations xf
.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,
Index: vfs-2.6.git/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- vfs-2.6.git.orig/fs/xfs/linux-2.6/xfs_iops.c 2009-09-22 11:28:48.585004290 -0300
+++ vfs-2.6.git/fs/xfs/linux-2.6/xfs_iops.c 2009-09-22 12:11:47.725937790 -0300
@@ -547,21 +547,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,
@@ -688,7 +673,7 @@ xfs_vn_fiemap(
static const struct inode_operations xfs_inode_operations = {
.check_acl = xfs_check_acl,
- .truncate = xfs_vn_truncate,
+ .truncate_kludge_to_be_killed = 1,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
Index: vfs-2.6.git/fs/xfs/linux-2.6/xfs_linux.h
===================================================================
--- vfs-2.6.git.orig/fs/xfs/linux-2.6/xfs_linux.h 2009-09-22 11:28:48.585004290 -0300
+++ vfs-2.6.git/fs/xfs/linux-2.6/xfs_linux.h 2009-09-22 12:11:08.637764444 -0300
@@ -159,9 +159,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 */
Index: vfs-2.6.git/fs/xfs/xfs_vnodeops.c
===================================================================
--- vfs-2.6.git.orig/fs/xfs/xfs_vnodeops.c 2009-09-22 12:10:45.977765610 -0300
+++ vfs-2.6.git/fs/xfs/xfs_vnodeops.c 2009-09-22 12:12:54.586307127 -0300
@@ -197,9 +197,11 @@ xfs_setattr(
* Truncate file. Must have write permission and not be a directory.
*/
if (mask & ATTR_SIZE) {
+ loff_t oldsize = ip->i_size;
+ loff_t newsize = iattr->ia_size;
+
/* Short circuit the truncate case for zero length files */
- if (iattr->ia_size == 0 &&
- ip->i_size == 0 && ip->i_d.di_nextents == 0) {
+ if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
xfs_iunlock(ip, XFS_ILOCK_EXCL);
lock_flags &= ~XFS_ILOCK_EXCL;
if (mask & ATTR_CTIME)
@@ -231,16 +233,19 @@ xfs_setattr(
* to the transaction, because the inode cannot be unlocked
* once it is a part of the transaction.
*/
- if (iattr->ia_size > ip->i_size) {
+ if (newsize > oldsize) {
/*
* Do the first part of growing a file: zero any data
* in the last block that is beyond the old EOF. We
* need to do this before the inode is joined to the
* transaction to modify the i_size.
*/
- code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
+ code = xfs_zero_eof(ip, newsize, oldsize);
+ 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
@@ -254,25 +259,28 @@ 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 &&
- iattr->ia_size > ip->i_d.di_size) {
- code = xfs_flush_pages(ip,
- ip->i_d.di_size, iattr->ia_size,
- XFS_B_ASYNC, FI_NONE);
+ if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) {
+ code = xfs_flush_pages(ip, ip->i_d.di_size, newsize,
+ XFS_B_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);
+ code = -inode_newsize_ok(inode, newsize);
+ if (code)
goto error_return;
- }
+
+ code = -block_truncate_page(inode->i_mapping, newsize,
+ xfs_get_blocks);
+ if (code)
+ goto error_return;
+
+ i_size_write(inode, newsize);
+ truncate_pagecache(inode, oldsize, newsize);
+
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
if ((code = xfs_trans_reserve(tp, 0,
XFS_ITRUNCATE_LOG_RES(mp), 0,
@@ -284,6 +292,7 @@ xfs_setattr(
return code;
}
commit_flags = XFS_TRANS_RELEASE_LOG_RES;
+ lock_flags |= XFS_ILOCK_EXCL;
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, lock_flags);
@@ -295,23 +304,23 @@ xfs_setattr(
* the semantic difference between truncate() and ftruncate()
* as implemented in the VFS.
*/
- if (iattr->ia_size != ip->i_size || (mask & ATTR_CTIME))
+ if (newsize != ip->i_size || (mask & ATTR_CTIME))
timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
- if (iattr->ia_size > ip->i_size) {
- ip->i_d.di_size = iattr->ia_size;
- ip->i_size = iattr->ia_size;
+ if (newsize > ip->i_size) {
+ ip->i_d.di_size = newsize;
+ ip->i_size = newsize;
if (!(flags & XFS_ATTR_DMI))
xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- } else if (iattr->ia_size <= ip->i_size ||
- (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
+ } else if (newsize <= ip->i_size ||
+ (newsize == 0 && ip->i_d.di_nextents)) {
/*
* signal a sync transaction unless
* we're truncating an already unlinked
* file on a wsync filesystem
*/
- code = xfs_itruncate_finish(&tp, ip, iattr->ia_size,
+ code = xfs_itruncate_finish(&tp, ip, newsize,
XFS_DATA_FORK,
((ip->i_d.di_nlink != 0 ||
!(mp->m_flags & XFS_MOUNT_WSYNC))
next prev parent reply other threads:[~2009-09-22 20:54 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-20 16:35 [patch 00/11] new truncate sequence npiggin
2009-08-20 16:35 ` [patch 01/11] fs: new truncate helpers npiggin
2009-08-26 7:38 ` Artem Bityutskiy
2009-09-07 7:33 ` Nick Piggin
2009-09-07 7:48 ` Artem Bityutskiy
2009-08-20 16:35 ` [patch 02/11] fs: use " npiggin-l3A5Bk7waGM
2009-08-20 16:35 ` [patch 03/11] fs: introduce new truncate sequence npiggin
2009-08-26 7:40 ` Artem Bityutskiy
2009-08-20 16:35 ` [patch 04/11] fs: convert simple fs to new truncate npiggin
2009-08-20 16:35 ` [patch 05/11] tmpfs: convert to use the new truncate convention npiggin
2009-08-20 16:35 ` [patch 06/11] ext2: " npiggin
2009-08-21 13:42 ` Jan Kara
2009-08-21 14:06 ` Jan Kara
2009-08-24 5:30 ` [patch] ext2: convert to use the new truncate convention fix Nick Piggin
2009-08-20 16:35 ` [patch 07/11] fat: convert to use the new truncate convention npiggin
2009-08-20 16:35 ` [patch 08/11] btrfs: " npiggin
2009-08-20 16:35 ` [patch 09/11] jfs: " npiggin
2009-08-20 16:35 ` [patch 10/11] udf: " npiggin
2009-08-21 14:22 ` Jan Kara
2009-08-24 5:33 ` Nick Piggin
2009-08-20 16:35 ` [patch 11/11] minix: " npiggin
2009-09-09 7:11 ` [patch 00/11] new truncate sequence Artem Bityutskiy
2009-09-22 15:04 ` Al Viro
2009-09-22 20:00 ` Christoph Hellwig
2009-09-22 21:51 ` Al Viro
2009-09-22 23:27 ` Al Viro
2009-09-22 23:58 ` Al Viro
2009-09-23 2:29 ` Al Viro
2009-09-27 19:50 ` Nick Piggin
2009-12-07 12:49 ` Nick Piggin
2009-12-07 22:46 ` Tyler Hicks
2009-09-22 20:53 ` [PATCH 12/n] kill spurious reference to vmtruncate Christoph Hellwig
2009-09-22 20:54 ` Christoph Hellwig [this message]
2009-09-22 20:55 ` [PATCH 14/n] sysv: new truncate sequence Christoph Hellwig
2009-09-22 20:56 ` [PATCH 15/n] ntfs: " Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090922205447.GB12224@infradead.org \
--to=hch@infradead.org \
--cc=akpm@linux-foundation.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=npiggin@suse.de \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).