All of lore.kernel.org
 help / color / mirror / Atom feed
From: Badari Pulavarty <pbadari@gmail.com>
To: Nick Piggin <npiggin@suse.de>
Cc: Linux Filesystems <linux-fsdevel@vger.kernel.org>,
	Mark Fasheh <mark.fasheh@oracle.com>,
	Steven Whitehouse <swhiteho@redhat.com>
Subject: Re: [ANNOUNCE] new new aops patchset
Date: Tue, 03 Apr 2007 10:35:19 -0700	[thread overview]
Message-ID: <1175621720.31817.4.camel@dyn9047017100.beaverton.ibm.com> (raw)
In-Reply-To: <20070402120934.GA19626@wotan.suse.de>

On Mon, 2007-04-02 at 14:09 +0200, Nick Piggin wrote:
> Updated aops patchset against 2.6.21-rc5.
> 
> http://www.kernel.org/pub/linux/kernel/people/npiggin/patches/new-aops/
> 
> Files/dirs are 2.6.21-rc5-new-aops*

Here is the ext4 support for it. This is a simple port from 
ext3 code. Ran fsx without any problems :)

BTW, I never clearly understood what exactly the problem these
new interfaces are solving and how :( I can dig through the
archives and try to figure out. Would you care to put a 
small description of the *actual* problem and how these
new aops are needed (vs hacking the existing methods).

Thanks,
Badari

---
 fs/ext4/inode.c |  171 +++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 113 insertions(+), 58 deletions(-)

Index: linux-2.6.21-rc5/fs/ext4/inode.c
===================================================================
--- linux-2.6.21-rc5.orig/fs/ext4/inode.c	2007-03-25 15:56:23.000000000 -0700
+++ linux-2.6.21-rc5/fs/ext4/inode.c	2007-04-03 10:01:34.000000000 -0700
@@ -1154,23 +1154,30 @@ static int do_journal_get_write_access(h
  * This content is expected to be set to zeroes by block_prepare_write().
  * 2006/10/14  SAW
  */
-static int ext4_prepare_failure(struct file *file, struct page *page,
-				unsigned from, unsigned to)
+static int ext4_write_failure(struct file *file, struct address_space *mapping,
+				loff_t pos, unsigned len,
+				struct page *page, void *fsdata)
 {
-	struct address_space *mapping;
 	struct buffer_head *bh, *head, *next;
 	unsigned block_start, block_end;
 	unsigned blocksize;
+	unsigned from, to;
 	int ret;
 	handle_t *handle = ext4_journal_current_handle();
 
-	mapping = page->mapping;
 	if (ext4_should_writeback_data(mapping->host)) {
 		/* optimization: no constraints about data */
+skip_and_stop:
+		ret = ext4_journal_stop(handle);
 skip:
-		return ext4_journal_stop(handle);
+		unlock_page(page);
+		page_cache_release(page);
+		return ret;
 	}
 
+	from = pos & (PAGE_CACHE_SIZE - 1);
+	to = from + len;
+
 	head = page_buffers(page);
 	blocksize = head->b_size;
 	for (	bh = head, block_start = 0;
@@ -1192,7 +1199,7 @@ skip:
 			ret = do_journal_get_write_access(handle, bh);
 			if (ret) {
 				ext4_journal_stop(handle);
-				return ret;
+				goto skip;
 			}
 		}
 	/*
@@ -1201,43 +1208,64 @@ skip:
 	 */
 	}
 	if (block_start <= from)
-		goto skip;
+		goto skip_and_stop;
 
 	/* commit allocated and zeroed buffers */
-	return mapping->a_ops->commit_write(file, page, from, block_start);
+	return mapping->a_ops->write_end(file, mapping, pos, len,
+					block_start - from, page, fsdata);
 }
 
-static int ext4_prepare_write(struct file *file, struct page *page,
-			      unsigned from, unsigned to)
+static int ext4_write_begin(struct file *file, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata)
 {
-	struct inode *inode = page->mapping->host;
-	int ret, ret2;
+	struct inode *inode = mapping->host;
 	int needed_blocks = ext4_writepage_trans_blocks(inode);
+	int ret, ret2;
 	handle_t *handle;
 	int retries = 0;
+	struct page *page;
+	pgoff_t index;
+	unsigned start, end;
+
+	index = pos >> PAGE_CACHE_SHIFT;
+	start = pos * (PAGE_CACHE_SIZE - 1);
+	end = start + len;
 
 retry:
+	page = __grab_cache_page(mapping, index);
+	if (!page)
+		return -ENOMEM;
+	*pagep = page;
+
 	handle = ext4_journal_start(inode, needed_blocks);
-	if (IS_ERR(handle))
+	if (IS_ERR(handle)) {
+		unlock_page(page);
+		page_cache_release(page);
 		return PTR_ERR(handle);
-	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
-		ret = nobh_prepare_write(page, from, to, ext4_get_block);
-	else
-		ret = block_prepare_write(page, from, to, ext4_get_block);
+	}
+	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+							ext4_get_block);
 	if (ret)
 		goto failure;
 
 	if (ext4_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
-				from, to, NULL, do_journal_get_write_access);
-		if (ret)
+				start, end, NULL, do_journal_get_write_access);
+		if (ret) {
 			/* fatal error, just put the handle and return */
 			ext4_journal_stop(handle);
+			unlock_page(page);
+			page_cache_release(page);
+		}
 	}
 	return ret;
 
 failure:
-	ret2 = ext4_prepare_failure(file, page, from, to);
+	ret2 = ext4_write_failure(file, mapping, pos, len, page, *fsdata);
+	/* trim off blocks (XXX: need better helpers than vmtruncate) */
+	if (pos + len > inode->i_size)
+		vmtruncate(inode, inode->i_size);
 	if (ret2 < 0)
 		return ret2;
 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -1251,12 +1279,12 @@ int ext4_journal_dirty_data(handle_t *ha
 	int err = jbd2_journal_dirty_data(handle, bh);
 	if (err)
 		ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
-						bh, handle,err);
+						bh, handle, err);
 	return err;
 }
 
-/* For commit_write() in data=journal mode */
-static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
+/* For write_end() in data=journal mode */
+static int write_end_fn(handle_t *handle, struct buffer_head *bh)
 {
 	if (!buffer_mapped(bh) || buffer_freed(bh))
 		return 0;
@@ -1271,78 +1299,103 @@ static int commit_write_fn(handle_t *han
  * ext4 never places buffers on inode->i_mapping->private_list.  metadata
  * buffers are managed internally.
  */
-static int ext4_ordered_commit_write(struct file *file, struct page *page,
-			     unsigned from, unsigned to)
+static int ext4_ordered_write_end(struct file *file,
+				struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = file->f_mapping->host;
+	unsigned from, to;
 	int ret = 0, ret2;
 
+	from = pos & (PAGE_CACHE_SIZE - 1);
+	to = from + len;
+
 	ret = walk_page_buffers(handle, page_buffers(page),
 		from, to, NULL, ext4_journal_dirty_data);
 
 	if (ret == 0) {
 		/*
-		 * generic_commit_write() will run mark_inode_dirty() if i_size
+		 * block_write_end() will run mark_inode_dirty() if i_size
 		 * changes.  So let's piggyback the i_disksize mark_inode_dirty
 		 * into that.
 		 */
 		loff_t new_i_size;
 
-		new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+		new_i_size = pos + copied;
 		if (new_i_size > EXT4_I(inode)->i_disksize)
 			EXT4_I(inode)->i_disksize = new_i_size;
-		ret = generic_commit_write(file, page, from, to);
+		copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+		if (copied < 0)
+			ret = copied;
 	}
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	return ret;
+	return ret ? ret : copied;
 }
 
-static int ext4_writeback_commit_write(struct file *file, struct page *page,
-			     unsigned from, unsigned to)
+static int ext4_writeback_write_end(struct file *file,
+				struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = file->f_mapping->host;
 	int ret = 0, ret2;
 	loff_t new_i_size;
 
-	new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	new_i_size = pos + copied;
 	if (new_i_size > EXT4_I(inode)->i_disksize)
 		EXT4_I(inode)->i_disksize = new_i_size;
 
-	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
-		ret = nobh_commit_write(file, page, from, to);
-	else
-		ret = generic_commit_write(file, page, from, to);
+	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+	if (copied < 0)
+		ret = copied;
 
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	return ret;
+	return ret ? ret : copied;
 }
 
-static int ext4_journalled_commit_write(struct file *file,
-			struct page *page, unsigned from, unsigned to)
+static int ext4_journalled_write_end(struct file *file,
+				struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = mapping->host;
 	int ret = 0, ret2;
 	int partial = 0;
-	loff_t pos;
+	unsigned from, to;
 
-	/*
-	 * Here we duplicate the generic_commit_write() functionality
-	 */
-	pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	from = pos & (PAGE_CACHE_SIZE - 1);
+	to = from + len;
+
+	if (copied < len) {
+		if (PageUptodate(page))
+			copied = len;
+		else {
+			/* XXX: don't need to zero new buffers because we abort? */
+			copied = 0;
+			if (!is_handle_aborted(handle))
+				jbd2_journal_abort_handle(handle);
+			unlock_page(page);
+			page_cache_release(page);
+			goto out;
+		}
+	}
 
 	ret = walk_page_buffers(handle, page_buffers(page), from,
-				to, &partial, commit_write_fn);
+				to, &partial, write_end_fn);
 	if (!partial)
 		SetPageUptodate(page);
-	if (pos > inode->i_size)
-		i_size_write(inode, pos);
+	unlock_page(page);
+	page_cache_release(page);
+	if (pos+copied > inode->i_size)
+		i_size_write(inode, pos+copied);
 	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
 	if (inode->i_size > EXT4_I(inode)->i_disksize) {
 		EXT4_I(inode)->i_disksize = inode->i_size;
@@ -1350,10 +1403,12 @@ static int ext4_journalled_commit_write(
 		if (!ret)
 			ret = ret2;
 	}
+
+out:
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	return ret;
+	return ret ? ret : copied;
 }
 
 /*
@@ -1611,7 +1666,7 @@ static int ext4_journalled_writepage(str
 			PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
 
 		err = walk_page_buffers(handle, page_buffers(page), 0,
-				PAGE_CACHE_SIZE, NULL, commit_write_fn);
+				PAGE_CACHE_SIZE, NULL, write_end_fn);
 		if (ret == 0)
 			ret = err;
 		EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
@@ -1771,8 +1826,8 @@ static const struct address_space_operat
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_ordered_writepage,
 	.sync_page	= block_sync_page,
-	.prepare_write	= ext4_prepare_write,
-	.commit_write	= ext4_ordered_commit_write,
+	.write_begin	= ext4_write_begin,
+	.write_end	= ext4_ordered_write_end,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,
 	.releasepage	= ext4_releasepage,
@@ -1785,8 +1840,8 @@ static const struct address_space_operat
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_writeback_writepage,
 	.sync_page	= block_sync_page,
-	.prepare_write	= ext4_prepare_write,
-	.commit_write	= ext4_writeback_commit_write,
+	.write_begin	= ext4_write_begin,
+	.write_end	= ext4_writeback_write_end,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,
 	.releasepage	= ext4_releasepage,
@@ -1799,8 +1854,8 @@ static const struct address_space_operat
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_journalled_writepage,
 	.sync_page	= block_sync_page,
-	.prepare_write	= ext4_prepare_write,
-	.commit_write	= ext4_journalled_commit_write,
+	.write_begin	= ext4_write_begin,
+	.write_end	= ext4_journalled_write_end,
 	.set_page_dirty	= ext4_journalled_set_page_dirty,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,



  parent reply	other threads:[~2007-04-03 17:35 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-02 12:09 [ANNOUNCE] new new aops patchset Nick Piggin
2007-04-02 20:18 ` Badari Pulavarty
2007-04-03  0:45   ` Nick Piggin
2007-04-02 20:44 ` Badari Pulavarty
2007-04-02 23:58   ` Nick Piggin
2007-04-03 15:59     ` Badari Pulavarty
2007-04-04  2:33       ` Nick Piggin
2007-04-02 21:44 ` Badari Pulavarty
2007-04-02 23:08 ` Badari Pulavarty
2007-04-02 23:14 ` Badari Pulavarty
2007-04-02 23:49   ` Nick Piggin
2007-04-03 15:57     ` Badari Pulavarty
2007-04-04  2:31       ` Nick Piggin
2007-04-02 23:31 ` Badari Pulavarty
2007-04-02 23:35   ` Nick Piggin
2007-04-02 23:56 ` Badari Pulavarty
2007-04-03  0:02   ` Nick Piggin
2007-04-03  0:00 ` Badari Pulavarty
2007-04-03  0:08   ` Nick Piggin
2007-04-03  9:31     ` Nick Piggin
2007-04-03 16:03       ` Badari Pulavarty
2007-04-04  2:37         ` Nick Piggin
2007-04-03 17:35 ` Badari Pulavarty [this message]
2007-04-04  3:05   ` Nick Piggin
2007-04-04 22:10 ` Mark Fasheh
2007-04-04 22:39   ` Badari Pulavarty
2007-04-04 22:51     ` Mark Fasheh
2007-04-04 23:02       ` Badari Pulavarty
2007-04-04 23:05   ` Badari Pulavarty
2007-04-04 23:17     ` Mark Fasheh
2007-04-04 23:32       ` Badari Pulavarty
2007-04-05  2:08         ` Nick Piggin
2007-04-05 15:21           ` Badari Pulavarty
2007-04-06  1:38             ` Nick Piggin
2007-04-05  2:09   ` Nick Piggin
2007-04-05  0:10 ` David Chinner
2007-04-05  2:13   ` Nick Piggin
2007-04-05  7:45     ` Christoph Hellwig
2007-04-05  7:58       ` Nick Piggin
2007-04-05  2:43   ` David Chinner
2007-04-05  3:00     ` Nick Piggin
2007-04-05  6:18       ` David Chinner
2007-04-05  6:40         ` Nick Piggin

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=1175621720.31817.4.camel@dyn9047017100.beaverton.ibm.com \
    --to=pbadari@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=mark.fasheh@oracle.com \
    --cc=npiggin@suse.de \
    --cc=swhiteho@redhat.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 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.