All of lore.kernel.org
 help / color / mirror / Atom feed
From: npiggin@suse.de
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-fsdevel@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
	Chris Mason <chris.mason@oracle.com>,
	linux-btrfs@vger.kernel.org
Subject: [patch 08/11] btrfs: convert to use the new truncate convention.
Date: Fri, 21 Aug 2009 02:35:12 +1000	[thread overview]
Message-ID: <20090820164051.564931048@suse.de> (raw)
In-Reply-To: 20090820163504.131529718@suse.de

Cc: Chris Mason <chris.mason@oracle.com>
Cc: linux-btrfs@vger.kernel.org
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nick Piggin <npiggin@suse.de>
---
 fs/btrfs/ctree.h |    1 
 fs/btrfs/inode.c |  132 +++++++++++++++++++++++++++++++++++--------------------
 fs/btrfs/ioctl.c |    2 
 3 files changed, 86 insertions(+), 49 deletions(-)

Index: linux-2.6/fs/btrfs/inode.c
===================================================================
--- linux-2.6.orig/fs/btrfs/inode.c
+++ linux-2.6/fs/btrfs/inode.c
@@ -81,7 +81,6 @@ static unsigned char btrfs_type_by_mode[
 	[S_IFLNK >> S_SHIFT]	= BTRFS_FT_SYMLINK,
 };
 
-static void btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
 static noinline int cow_file_range(struct inode *inode,
 				   struct page *locked_page,
@@ -1990,7 +1989,7 @@ void btrfs_orphan_cleanup(struct btrfs_r
 		/* if we have links, this was a truncate, lets do that */
 		if (inode->i_nlink) {
 			nr_truncate++;
-			btrfs_truncate(inode);
+			btrfs_truncate_blocks(inode, inode->i_size);
 		} else {
 			nr_unlink++;
 		}
@@ -2956,39 +2955,6 @@ int btrfs_cont_expand(struct inode *inod
 	return err;
 }
 
-static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
-	struct inode *inode = dentry->d_inode;
-	int err;
-
-	err = inode_change_ok(inode, attr);
-	if (err)
-		return err;
-
-	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-		if (attr->ia_size > inode->i_size) {
-			err = btrfs_cont_expand(inode, attr->ia_size);
-			if (err)
-				return err;
-		} else if (inode->i_size > 0 &&
-			   attr->ia_size == 0) {
-
-			/* we're truncating a file that used to have good
-			 * data down to zero.  Make sure it gets into
-			 * the ordered flush list so that any new writes
-			 * get down to disk quickly.
-			 */
-			BTRFS_I(inode)->ordered_data_close = 1;
-		}
-	}
-
-	err = inode_setattr(inode, attr);
-
-	if (!err && ((attr->ia_valid & ATTR_MODE)))
-		err = btrfs_acl_chmod(inode);
-	return err;
-}
-
 void btrfs_delete_inode(struct inode *inode)
 {
 	struct btrfs_trans_handle *trans;
@@ -4438,7 +4404,7 @@ static void btrfs_invalidatepage(struct
  *
  * We are not allowed to take the i_mutex here so we have to play games to
  * protect against truncate races as the page could now be beyond EOF.  Because
- * vmtruncate() writes the inode size before removing pages, once we have the
+ * btrfs_setsize() writes the inode size before removing pages, once we have the
  * page lock we can determine safely if the page is beyond EOF. If it is not
  * beyond EOF, then the page is guaranteed safe against truncation until we
  * unlock the page.
@@ -4524,7 +4490,7 @@ out:
 	return ret;
 }
 
-static void btrfs_truncate(struct inode *inode)
+static void __btrfs_truncate_blocks(struct inode *inode, loff_t offset)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	int ret;
@@ -4532,13 +4498,8 @@ static void btrfs_truncate(struct inode
 	unsigned long nr;
 	u64 mask = root->sectorsize - 1;
 
-	if (!S_ISREG(inode->i_mode))
-		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
-
-	btrfs_truncate_page(inode->i_mapping, inode->i_size);
-	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
+	btrfs_truncate_page(inode->i_mapping, offset);
+	btrfs_wait_ordered_range(inode, offset & (~mask), (u64)-1);
 
 	trans = btrfs_start_transaction(root, 1);
 
@@ -4559,17 +4520,17 @@ static void btrfs_truncate(struct inode
 	 * using truncate to replace the contents of the file will
 	 * end up with a zero length file after a crash.
 	 */
-	if (inode->i_size == 0 && BTRFS_I(inode)->ordered_data_close)
+	if (offset == 0 && BTRFS_I(inode)->ordered_data_close)
 		btrfs_add_ordered_operation(trans, root, inode);
 
 	btrfs_set_trans_block_group(trans, inode);
-	btrfs_i_size_write(inode, inode->i_size);
+	btrfs_i_size_write(inode, offset);
 
 	ret = btrfs_orphan_add(trans, inode);
 	if (ret)
 		goto out;
 	/* FIXME, add redo link to tree so we don't leak on crash */
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
+	ret = btrfs_truncate_inode_items(trans, root, inode, offset,
 				      BTRFS_EXTENT_DATA_KEY);
 	btrfs_update_inode(trans, root, inode);
 
@@ -4583,6 +4544,81 @@ out:
 	btrfs_btree_balance_dirty(root, nr);
 }
 
+void btrfs_truncate_blocks(struct inode *inode, loff_t offset)
+{
+	if (!S_ISREG(inode->i_mode))
+		return;
+	/* XXX: should allow IS_APPEND and IS_IMMUTABLE files to have
+	 * blocks trimmed past i_size */
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return;
+
+	__btrfs_truncate_blocks(inode, offset);
+	mark_inode_dirty(inode);
+}
+
+static int btrfs_setsize(struct inode *inode, loff_t newsize)
+{
+	int error;
+	loff_t oldsize;
+
+	if (!S_ISREG(inode->i_mode))
+		return -EINVAL;
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return -EPERM;
+
+	error = inode_newsize_ok(inode, newsize);
+	if (error)
+		return error;
+
+	oldsize = inode->i_size;
+	__btrfs_truncate_blocks(inode, newsize);
+	truncate_pagecache(inode, oldsize, newsize);
+
+	return error;
+}
+
+static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int err;
+
+	err = inode_change_ok(inode, attr);
+	if (err)
+		return err;
+
+	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
+		loff_t newsize = attr->ia_size;
+
+		if (newsize > inode->i_size) {
+			err = btrfs_cont_expand(inode, newsize);
+			if (err)
+				return err;
+		} else if (inode->i_size > 0 &&
+			   newsize == 0) {
+
+			/* we're truncating a file that used to have good
+			 * data down to zero.  Make sure it gets into
+			 * the ordered flush list so that any new writes
+			 * get down to disk quickly.
+			 */
+			BTRFS_I(inode)->ordered_data_close = 1;
+		}
+
+		err = btrfs_setsize(inode, newsize);
+		if (err)
+			return err;
+	}
+
+	generic_setattr(inode, attr);
+
+	if ((attr->ia_valid & ATTR_MODE))
+		err = btrfs_acl_chmod(inode);
+	mark_inode_dirty(inode);
+
+	return err;
+}
+
 /*
  * create a new subvolume directory/inode (helper for the ioctl).
  */
@@ -5272,7 +5308,7 @@ static struct address_space_operations b
 };
 
 static struct inode_operations btrfs_file_inode_operations = {
-	.truncate	= btrfs_truncate,
+	.new_truncate	= 1,
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,
 	.setxattr	= btrfs_setxattr,
Index: linux-2.6/fs/btrfs/ioctl.c
===================================================================
--- linux-2.6.orig/fs/btrfs/ioctl.c
+++ linux-2.6/fs/btrfs/ioctl.c
@@ -1148,7 +1148,7 @@ out:
 	btrfs_end_transaction(trans, root);
 	unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
 	if (ret)
-		vmtruncate(inode, 0);
+		btrfs_truncate_blocks(inode, 0);
 out_unlock:
 	mutex_unlock(&src->i_mutex);
 	mutex_unlock(&inode->i_mutex);
Index: linux-2.6/fs/btrfs/ctree.h
===================================================================
--- linux-2.6.orig/fs/btrfs/ctree.h
+++ linux-2.6/fs/btrfs/ctree.h
@@ -2275,6 +2275,7 @@ int btrfs_orphan_add(struct btrfs_trans_
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
+void btrfs_truncate_blocks(struct inode *inode, loff_t offset);
 
 /* ioctl.c */
 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);



WARNING: multiple messages have this Message-ID (diff)
From: npiggin@suse.de
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-fsdevel@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
	Chris Mason <chris.mason@oracle.com>,
	linux-btrfs@vger.kernel.org
Subject: [patch 08/11] btrfs: convert to use the new truncate convention.
Date: Fri, 21 Aug 2009 02:35:12 +1000	[thread overview]
Message-ID: <20090820164051.564931048@suse.de> (raw)
In-Reply-To: 20090820163504.131529718@suse.de

[-- Attachment #1: btrfs-new-truncate.patch --]
[-- Type: text/plain, Size: 7395 bytes --]

Cc: Chris Mason <chris.mason@oracle.com>
Cc: linux-btrfs@vger.kernel.org
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nick Piggin <npiggin@suse.de>
---
 fs/btrfs/ctree.h |    1 
 fs/btrfs/inode.c |  132 +++++++++++++++++++++++++++++++++++--------------------
 fs/btrfs/ioctl.c |    2 
 3 files changed, 86 insertions(+), 49 deletions(-)

Index: linux-2.6/fs/btrfs/inode.c
===================================================================
--- linux-2.6.orig/fs/btrfs/inode.c
+++ linux-2.6/fs/btrfs/inode.c
@@ -81,7 +81,6 @@ static unsigned char btrfs_type_by_mode[
 	[S_IFLNK >> S_SHIFT]	= BTRFS_FT_SYMLINK,
 };
 
-static void btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
 static noinline int cow_file_range(struct inode *inode,
 				   struct page *locked_page,
@@ -1990,7 +1989,7 @@ void btrfs_orphan_cleanup(struct btrfs_r
 		/* if we have links, this was a truncate, lets do that */
 		if (inode->i_nlink) {
 			nr_truncate++;
-			btrfs_truncate(inode);
+			btrfs_truncate_blocks(inode, inode->i_size);
 		} else {
 			nr_unlink++;
 		}
@@ -2956,39 +2955,6 @@ int btrfs_cont_expand(struct inode *inod
 	return err;
 }
 
-static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
-	struct inode *inode = dentry->d_inode;
-	int err;
-
-	err = inode_change_ok(inode, attr);
-	if (err)
-		return err;
-
-	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-		if (attr->ia_size > inode->i_size) {
-			err = btrfs_cont_expand(inode, attr->ia_size);
-			if (err)
-				return err;
-		} else if (inode->i_size > 0 &&
-			   attr->ia_size == 0) {
-
-			/* we're truncating a file that used to have good
-			 * data down to zero.  Make sure it gets into
-			 * the ordered flush list so that any new writes
-			 * get down to disk quickly.
-			 */
-			BTRFS_I(inode)->ordered_data_close = 1;
-		}
-	}
-
-	err = inode_setattr(inode, attr);
-
-	if (!err && ((attr->ia_valid & ATTR_MODE)))
-		err = btrfs_acl_chmod(inode);
-	return err;
-}
-
 void btrfs_delete_inode(struct inode *inode)
 {
 	struct btrfs_trans_handle *trans;
@@ -4438,7 +4404,7 @@ static void btrfs_invalidatepage(struct
  *
  * We are not allowed to take the i_mutex here so we have to play games to
  * protect against truncate races as the page could now be beyond EOF.  Because
- * vmtruncate() writes the inode size before removing pages, once we have the
+ * btrfs_setsize() writes the inode size before removing pages, once we have the
  * page lock we can determine safely if the page is beyond EOF. If it is not
  * beyond EOF, then the page is guaranteed safe against truncation until we
  * unlock the page.
@@ -4524,7 +4490,7 @@ out:
 	return ret;
 }
 
-static void btrfs_truncate(struct inode *inode)
+static void __btrfs_truncate_blocks(struct inode *inode, loff_t offset)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	int ret;
@@ -4532,13 +4498,8 @@ static void btrfs_truncate(struct inode
 	unsigned long nr;
 	u64 mask = root->sectorsize - 1;
 
-	if (!S_ISREG(inode->i_mode))
-		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
-
-	btrfs_truncate_page(inode->i_mapping, inode->i_size);
-	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
+	btrfs_truncate_page(inode->i_mapping, offset);
+	btrfs_wait_ordered_range(inode, offset & (~mask), (u64)-1);
 
 	trans = btrfs_start_transaction(root, 1);
 
@@ -4559,17 +4520,17 @@ static void btrfs_truncate(struct inode
 	 * using truncate to replace the contents of the file will
 	 * end up with a zero length file after a crash.
 	 */
-	if (inode->i_size == 0 && BTRFS_I(inode)->ordered_data_close)
+	if (offset == 0 && BTRFS_I(inode)->ordered_data_close)
 		btrfs_add_ordered_operation(trans, root, inode);
 
 	btrfs_set_trans_block_group(trans, inode);
-	btrfs_i_size_write(inode, inode->i_size);
+	btrfs_i_size_write(inode, offset);
 
 	ret = btrfs_orphan_add(trans, inode);
 	if (ret)
 		goto out;
 	/* FIXME, add redo link to tree so we don't leak on crash */
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
+	ret = btrfs_truncate_inode_items(trans, root, inode, offset,
 				      BTRFS_EXTENT_DATA_KEY);
 	btrfs_update_inode(trans, root, inode);
 
@@ -4583,6 +4544,81 @@ out:
 	btrfs_btree_balance_dirty(root, nr);
 }
 
+void btrfs_truncate_blocks(struct inode *inode, loff_t offset)
+{
+	if (!S_ISREG(inode->i_mode))
+		return;
+	/* XXX: should allow IS_APPEND and IS_IMMUTABLE files to have
+	 * blocks trimmed past i_size */
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return;
+
+	__btrfs_truncate_blocks(inode, offset);
+	mark_inode_dirty(inode);
+}
+
+static int btrfs_setsize(struct inode *inode, loff_t newsize)
+{
+	int error;
+	loff_t oldsize;
+
+	if (!S_ISREG(inode->i_mode))
+		return -EINVAL;
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return -EPERM;
+
+	error = inode_newsize_ok(inode, newsize);
+	if (error)
+		return error;
+
+	oldsize = inode->i_size;
+	__btrfs_truncate_blocks(inode, newsize);
+	truncate_pagecache(inode, oldsize, newsize);
+
+	return error;
+}
+
+static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int err;
+
+	err = inode_change_ok(inode, attr);
+	if (err)
+		return err;
+
+	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
+		loff_t newsize = attr->ia_size;
+
+		if (newsize > inode->i_size) {
+			err = btrfs_cont_expand(inode, newsize);
+			if (err)
+				return err;
+		} else if (inode->i_size > 0 &&
+			   newsize == 0) {
+
+			/* we're truncating a file that used to have good
+			 * data down to zero.  Make sure it gets into
+			 * the ordered flush list so that any new writes
+			 * get down to disk quickly.
+			 */
+			BTRFS_I(inode)->ordered_data_close = 1;
+		}
+
+		err = btrfs_setsize(inode, newsize);
+		if (err)
+			return err;
+	}
+
+	generic_setattr(inode, attr);
+
+	if ((attr->ia_valid & ATTR_MODE))
+		err = btrfs_acl_chmod(inode);
+	mark_inode_dirty(inode);
+
+	return err;
+}
+
 /*
  * create a new subvolume directory/inode (helper for the ioctl).
  */
@@ -5272,7 +5308,7 @@ static struct address_space_operations b
 };
 
 static struct inode_operations btrfs_file_inode_operations = {
-	.truncate	= btrfs_truncate,
+	.new_truncate	= 1,
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,
 	.setxattr	= btrfs_setxattr,
Index: linux-2.6/fs/btrfs/ioctl.c
===================================================================
--- linux-2.6.orig/fs/btrfs/ioctl.c
+++ linux-2.6/fs/btrfs/ioctl.c
@@ -1148,7 +1148,7 @@ out:
 	btrfs_end_transaction(trans, root);
 	unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
 	if (ret)
-		vmtruncate(inode, 0);
+		btrfs_truncate_blocks(inode, 0);
 out_unlock:
 	mutex_unlock(&src->i_mutex);
 	mutex_unlock(&inode->i_mutex);
Index: linux-2.6/fs/btrfs/ctree.h
===================================================================
--- linux-2.6.orig/fs/btrfs/ctree.h
+++ linux-2.6/fs/btrfs/ctree.h
@@ -2275,6 +2275,7 @@ int btrfs_orphan_add(struct btrfs_trans_
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
+void btrfs_truncate_blocks(struct inode *inode, loff_t offset);
 
 /* ioctl.c */
 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);



  parent reply	other threads:[~2009-08-20 16:35 UTC|newest]

Thread overview: 38+ 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
2009-08-20 16:35   ` 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 ` npiggin [this message]
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 ` [PATCH 13/n] xfs: new truncate sequence Christoph Hellwig
2009-09-22 20:54   ` Christoph Hellwig
2009-09-22 20:55 ` [PATCH 14/n] sysv: " 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=20090820164051.564931048@suse.de \
    --to=npiggin@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=chris.mason@oracle.com \
    --cc=hch@lst.de \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.