Skip to contentSkip to conversation

fs: remove prepare_write/commit_write

PATCH In review Nick Piggin 5 participants 20 messages Sep 24, 2008 – Dec 26, 2008

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fs: remove prepare_write/commit_write

Just FYI (I'll resend for -mm after the last conversions get in), this shows how much cruft we shed after the old aops go away...

drivers/block/loop.c +2 -3
Index: linux-2.6/drivers/block/loop.c
===================================================================
@@ -40,8 +40,7 @@
  * Heinz Mauelshagen <[email protected]>, Feb 2002
  *
  * Support for falling back on the write file operation when the address space
- * operations prepare_write and/or commit_write are not available on the
- * backing filesystem.
+ * operations write_begin is not available on the backing filesystem.
  * Anton Altaparmakov, 16 Feb 2005
  *
  * Still To Fix:
@@ -766,7 +765,7 @@ static int loop_set_fd(struct loop_devic
 		 */
 		if (!file->f_op->splice_read)
 			goto out_putf;
-		if (aops->prepare_write || aops->write_begin)
+		if (aops->write_begin)
 			lo_flags |= LO_FLAGS_USE_AOPS;
 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
fs/fat/inode.c +1 -1
Index: linux-2.6/fs/fat/inode.c
===================================================================
@@ -175,7 +175,7 @@ static ssize_t fat_direct_IO(int rw, str
 
 	if (rw == WRITE) {
 		/*
-		 * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(),
+		 * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
 		 * so we need to update the ->mmu_private to block boundary.
 		 *
 		 * But we must fill the remaining area or hole by nul for
fs/ocfs2/file.c +1 -2
Index: linux-2.6/fs/ocfs2/file.c
===================================================================
@@ -837,8 +837,7 @@ leave:
 
 /* Some parts of this taken from generic_cont_expand, which turned out
  * to be too fragile to do exactly what we need without us having to
- * worry about recursive locking in ->prepare_write() and
- * ->commit_write(). */
+ * worry about recursive locking in ->write_begin() and ->write_end(). */
 static int ocfs2_write_zero_page(struct inode *inode,
 				 u64 size)
 {
fs/splice.c +2 -2
Index: linux-2.6/fs/splice.c
===================================================================
@@ -731,8 +731,8 @@ ssize_t splice_from_pipe(struct pipe_ino
 	};
 
 	/*
-	 * The actor worker might be calling ->prepare_write and
-	 * ->commit_write. Most of the time, these expect i_mutex to
+	 * The actor worker might be calling ->write_begin and
+	 * ->write_end. Most of the time, these expect i_mutex to
 	 * be held. Since this may result in an ABBA deadlock with
 	 * pipe->inode, we have to order lock acquiry here.
 	 */
include/linux/fs.h +0 -7
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -479,13 +479,6 @@ struct address_space_operations {
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
 
-	/*
-	 * ext3 requires that a successful prepare_write() call be followed
-	 * by a commit_write() call - they must be balanced
-	 */
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
-
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata);
mm/filemap.c +4 -235

264 lines not on this page · raw message

Documentation/filesystems/Locking +7 -5
Index: linux-2.6/Documentation/filesystems/Locking
===================================================================
@@ -161,8 +161,12 @@ prototypes:
 	int (*set_page_dirty)(struct page *page);
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+	int (*write_begin)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata);
+	int (*write_end)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata);
 	sector_t (*bmap)(struct address_space *, sector_t);
 	int (*invalidatepage) (struct page *, unsigned long);
 	int (*releasepage) (struct page *, int);
@@ -180,8 +184,6 @@ sync_page:		no	maybe
 writepages:		no
 set_page_dirty		no	no
 readpages:		no
-prepare_write:		no	yes			yes
-commit_write:		no	yes			yes
 write_begin:		no	locks the page		yes
 write_end:		no	yes, unlocks		yes
 perform_write:		no	n/a			yes
@@ -191,7 +193,7 @@ releasepage:		no	yes
 direct_IO:		no
 launder_page:		no	yes
 
-	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
+	->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
 
 	->readpage() unlocks the page, either synchronously or via I/O
Documentation/filesystems/vfs.txt +5 -34
Index: linux-2.6/Documentation/filesystems/vfs.txt
===================================================================
@@ -492,7 +492,7 @@ written-back to storage typically in who
 address_space has finer control of write sizes.
 
 The read process essentially only requires 'readpage'.  The write
-process is more complicated and uses prepare_write/commit_write or
+process is more complicated and uses write_begin/write_end or
 set_page_dirty to write data into the address_space, and writepage,
 sync_page, and writepages to writeback data to storage.
 
@@ -521,8 +521,6 @@ struct address_space_operations {
 	int (*set_page_dirty)(struct page *page);
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata);
@@ -598,37 +596,7 @@ struct address_space_operations {
 	readpages is only used for read-ahead, so read errors are
   	ignored.  If anything goes wrong, feel free to give up.
 
-  prepare_write: called by the generic write path in VM to set up a write
-  	request for a page.  This indicates to the address space that
-  	the given range of bytes is about to be written.  The
-  	address_space should check that the write will be able to
-  	complete, by allocating space if necessary and doing any other
-  	internal housekeeping.  If the write will update parts of
-  	any basic-blocks on storage, then those blocks should be
-  	pre-read (if they haven't been read already) so that the
-  	updated blocks can be written out properly.
-	The page will be locked.
-
-	Note: the page _must not_ be marked uptodate in this function
-	(or anywhere else) unless it actually is uptodate right now. As
-	soon as a page is marked uptodate, it is possible for a concurrent
-	read(2) to copy it to userspace.
-
-  commit_write: If prepare_write succeeds, new data will be copied
-        into the page and then commit_write will be called.  It will
-        typically update the size of the file (if appropriate) and
-        mark the inode as dirty, and do any other related housekeeping
-        operations.  It should avoid returning an error if possible -
-        errors should have been handled by prepare_write.
-
-  write_begin: This is intended as a replacement for prepare_write. The
-	key differences being that:
-		- it returns a locked page (in *pagep) rather than being
-		  given a pre locked page;
-		- it must be able to cope with short writes (where the
-		  length passed to write_begin is greater than the number
-		  of bytes copied into the page).
-
+  write_begin:
 	Called by the generic buffered write code to ask the filesystem to
 	prepare to write len bytes at the given offset in the file. The
 	address_space should check that the write will be able to complete,
@@ -640,6 +608,9 @@ struct address_space_operations {
         The filesystem must return the locked pagecache page for the specified
 	offset, in *pagep, for the caller to write into.
 
+	It must be able to cope with short writes (where the length passed to
+	write_begin is greater than the number of bytes copied into the page).
+
 	flags is a field for AOP_FLAG_xxx flags, described in
 	include/linux/fs.h.
 
#1 lore raw

mm/filemap.c int pagecache_write_begin(struct file *f · line 2022

Quoted 10 lines · Nick Piggin
mm/filemap.c +1 -0
@@ -2016,48 +2016,8 @@ int pagecache_write_begin(struct file *f
 {
 	const struct address_space_operations *aops = mapping->a_ops;
 
+	return aops->write_begin(file, mapping, pos, len, flags,
 							pagep, fsdata);
 }
 EXPORT_SYMBOL(pagecache_write_begin);

Please kill pagecache_write_begin/pagecache_write_end, too.

Quoted 5 lines
mm/filemap.c +0 -0
 static ssize_t generic_perform_write(struct file *file,
 				struct iov_iter *i, loff_t pos)
 {
@@ -2481,10 +2253,7 @@ generic_file_buffered_write(struct kiocb
 	struct iov_iter i;

mm/filemap.c generic_file_buffered_write(struct kiocb · line 2259

Quoted 10 lines
mm/filemap.c +1 -4
 
 	iov_iter_init(&i, iov, nr_segs, count, written);
-	if (a_ops->write_begin)
-		status = generic_perform_write(file, &i, pos);
-	else
-		status = generic_perform_write_2copy(file, &i, pos);
+	status = generic_perform_write(file, &i, pos);
 
 	if (likely(status >= 0)) {
 		written += status;

Can we merge generic_perform_write back into generic_file_buffered_write? generic_file_buffered_write is left as a rather useless wrapper after this.

mm/filemap.c

Quoted 3 lines
mm/filemap.c +1 -1
-	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
+	->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).

This comment can go away, all file I/O done by the loop device now is from a kthread.

#2 lore raw
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Nick Piggin
mm/filemap.c +0 -0
@@ -2016,48 +2016,8 @@ int pagecache_write_begin(struct file *f
 {
 	const struct address_space_operations *aops = mapping->a_ops;
 
Quoted 6 lines

mm/filemap.c int pagecache_write_begin(struct file *f · line 2022

Quoted 4 lines
mm/filemap.c +1 -0
+	return aops->write_begin(file, mapping, pos, len, flags,
 							pagep, fsdata);
 }
 EXPORT_SYMBOL(pagecache_write_begin);

Please kill pagecache_write_begin/pagecache_write_end, too.

Well.... we *could* have it handle writes for filesystems that don't implement write_begin/write_end, couldn't we?

Quoted 13 lines
Quoted 13 lines
mm/filemap.c +1 -4
 static ssize_t generic_perform_write(struct file *file,
 				struct iov_iter *i, loff_t pos)
 {
@@ -2481,10 +2253,7 @@ generic_file_buffered_write(struct kiocb
 	struct iov_iter i;
 
 	iov_iter_init(&i, iov, nr_segs, count, written);
-	if (a_ops->write_begin)
-		status = generic_perform_write(file, &i, pos);
-	else
-		status = generic_perform_write_2copy(file, &i, pos);
+	status = generic_perform_write(file, &i, pos);
 
Quoted 6 lines

mm/filemap.c generic_file_buffered_write(struct kiocb · line 2259

Quoted 2 lines
mm/filemap.c +0 -0
 	if (likely(status >= 0)) {
 		written += status;

Can we merge generic_perform_write back into generic_file_buffered_write? generic_file_buffered_write is left as a rather useless wrapper after this.

Yeah that makes sense.

Quoted 6 lines

mm/filemap.c

Quoted 3 lines
mm/filemap.c +1 -1
-	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
+	->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).

This comment can go away, all file I/O done by the loop device now is from a kthread.

Feel like sending a patch to kill that now?

Thanks,
Nick

#3 lore raw
In reply to Nick Piggin
Quoted 2 lines · Nick Piggin

Just FYI (I'll resend for -mm after the last conversions get in), this shows how much cruft we shed after the old aops go away...

All conversions are in mainline now, so can we get this patch in, too for 2.6.28?

#4 lore raw
Quoted 7 lines · Christoph Hellwig
Quoted 2 lines · Nick Piggin

Just FYI (I'll resend for -mm after the last conversions get in), this shows how much cruft we shed after the old aops go away...

All conversions are in mainline now, so can we get this patch in, too for 2.6.28?

This patch applied cleanly against 2.6.27-git7, compiled and booted fine.

FYI.

Thanks,
Badari

#5 lore raw

PATCH 1/1 fs: remove prepare_write/commit_write

Quoted 5 lines · Badari Pulavarty
Quoted 4 lines · Christoph Hellwig
Quoted 2 lines · Nick Piggin

Just FYI (I'll resend for -mm after the last conversions get in), this shows how much cruft we shed after the old aops go away...

Quoted 8 lines
Quoted 3 lines

All conversions are in mainline now, so can we get this patch in, too for 2.6.28?

This patch applied cleanly against 2.6.27-git7, compiled and booted fine.

FYI.

Hi Linus,

Please apply. Subsequent patch to fold generic_perform_write into generic_file_buffered_write is not completely trivial, so I'll send that one to -mm. This one is more obviously OK as prepare_write should always be NULL now.
--

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

---

drivers/block/loop.c +2 -3
Index: linux-2.6/drivers/block/loop.c
===================================================================
@@ -40,8 +40,7 @@
  * Heinz Mauelshagen <[email protected]>, Feb 2002
  *
  * Support for falling back on the write file operation when the address space
- * operations prepare_write and/or commit_write are not available on the
- * backing filesystem.
+ * operations write_begin is not available on the backing filesystem.
  * Anton Altaparmakov, 16 Feb 2005
  *
  * Still To Fix:
@@ -766,7 +765,7 @@ static int loop_set_fd(struct loop_devic
 		 */
 		if (!file->f_op->splice_read)
 			goto out_putf;
-		if (aops->prepare_write || aops->write_begin)
+		if (aops->write_begin)
 			lo_flags |= LO_FLAGS_USE_AOPS;
 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
fs/fat/inode.c +1 -1
Index: linux-2.6/fs/fat/inode.c
===================================================================
@@ -175,7 +175,7 @@ static ssize_t fat_direct_IO(int rw, str
 
 	if (rw == WRITE) {
 		/*
-		 * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(),
+		 * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
 		 * so we need to update the ->mmu_private to block boundary.
 		 *
 		 * But we must fill the remaining area or hole by nul for
fs/ocfs2/file.c +1 -2
Index: linux-2.6/fs/ocfs2/file.c
===================================================================
@@ -679,8 +679,7 @@ leave:
 
 /* Some parts of this taken from generic_cont_expand, which turned out
  * to be too fragile to do exactly what we need without us having to
- * worry about recursive locking in ->prepare_write() and
- * ->commit_write(). */
+ * worry about recursive locking in ->write_begin() and ->write_end(). */
 static int ocfs2_write_zero_page(struct inode *inode,
 				 u64 size)
 {
fs/splice.c +2 -2
Index: linux-2.6/fs/splice.c
===================================================================
@@ -731,8 +731,8 @@ ssize_t splice_from_pipe(struct pipe_ino
 	};
 
 	/*
-	 * The actor worker might be calling ->prepare_write and
-	 * ->commit_write. Most of the time, these expect i_mutex to
+	 * The actor worker might be calling ->write_begin and
+	 * ->write_end. Most of the time, these expect i_mutex to
 	 * be held. Since this may result in an ABBA deadlock with
 	 * pipe->inode, we have to order lock acquiry here.
 	 */
include/linux/fs.h +0 -7
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -484,13 +484,6 @@ struct address_space_operations {
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
 
-	/*
-	 * ext3 requires that a successful prepare_write() call be followed
-	 * by a commit_write() call - they must be balanced
-	 */
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
-
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata);
mm/filemap.c +4 -238

268 lines not on this page · raw message

Documentation/filesystems/Locking +7 -5
Index: linux-2.6/Documentation/filesystems/Locking
===================================================================
@@ -161,8 +161,12 @@ prototypes:
 	int (*set_page_dirty)(struct page *page);
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+	int (*write_begin)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata);
+	int (*write_end)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata);
 	sector_t (*bmap)(struct address_space *, sector_t);
 	int (*invalidatepage) (struct page *, unsigned long);
 	int (*releasepage) (struct page *, int);
@@ -180,8 +184,6 @@ sync_page:		no	maybe
 writepages:		no
 set_page_dirty		no	no
 readpages:		no
-prepare_write:		no	yes			yes
-commit_write:		no	yes			yes
 write_begin:		no	locks the page		yes
 write_end:		no	yes, unlocks		yes
 perform_write:		no	n/a			yes
@@ -191,7 +193,7 @@ releasepage:		no	yes
 direct_IO:		no
 launder_page:		no	yes
 
-	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
+	->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
 
 	->readpage() unlocks the page, either synchronously or via I/O
Documentation/filesystems/vfs.txt +5 -34
Index: linux-2.6/Documentation/filesystems/vfs.txt
===================================================================
@@ -492,7 +492,7 @@ written-back to storage typically in who
 address_space has finer control of write sizes.
 
 The read process essentially only requires 'readpage'.  The write
-process is more complicated and uses prepare_write/commit_write or
+process is more complicated and uses write_begin/write_end or
 set_page_dirty to write data into the address_space, and writepage,
 sync_page, and writepages to writeback data to storage.
 
@@ -521,8 +521,6 @@ struct address_space_operations {
 	int (*set_page_dirty)(struct page *page);
 	int (*readpages)(struct file *filp, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
-	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
-	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata);
@@ -598,37 +596,7 @@ struct address_space_operations {
 	readpages is only used for read-ahead, so read errors are
   	ignored.  If anything goes wrong, feel free to give up.
 
-  prepare_write: called by the generic write path in VM to set up a write
-  	request for a page.  This indicates to the address space that
-  	the given range of bytes is about to be written.  The
-  	address_space should check that the write will be able to
-  	complete, by allocating space if necessary and doing any other
-  	internal housekeeping.  If the write will update parts of
-  	any basic-blocks on storage, then those blocks should be
-  	pre-read (if they haven't been read already) so that the
-  	updated blocks can be written out properly.
-	The page will be locked.
-
-	Note: the page _must not_ be marked uptodate in this function
-	(or anywhere else) unless it actually is uptodate right now. As
-	soon as a page is marked uptodate, it is possible for a concurrent
-	read(2) to copy it to userspace.
-
-  commit_write: If prepare_write succeeds, new data will be copied
-        into the page and then commit_write will be called.  It will
-        typically update the size of the file (if appropriate) and
-        mark the inode as dirty, and do any other related housekeeping
-        operations.  It should avoid returning an error if possible -
-        errors should have been handled by prepare_write.
-
-  write_begin: This is intended as a replacement for prepare_write. The
-	key differences being that:
-		- it returns a locked page (in *pagep) rather than being
-		  given a pre locked page;
-		- it must be able to cope with short writes (where the
-		  length passed to write_begin is greater than the number
-		  of bytes copied into the page).
-
+  write_begin:
 	Called by the generic buffered write code to ask the filesystem to
 	prepare to write len bytes at the given offset in the file. The
 	address_space should check that the write will be able to complete,
@@ -640,6 +608,9 @@ struct address_space_operations {
         The filesystem must return the locked pagecache page for the specified
 	offset, in *pagep, for the caller to write into.
 
+	It must be able to cope with short writes (where the length passed to
+	write_begin is greater than the number of bytes copied into the page).
+
 	flags is a field for AOP_FLAG_xxx flags, described in
 	include/linux/fs.h.
 
maintainer
#6 lore raw
Quoted 2 lines · On Tue, 21 Oct 2008 08:20:20 +0200 Nick Piggin <[email protected]> wrote:

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

We could withdraw simple_prepare_write() too, I guess. But there's some risk that out-of-tree filesystems might be using it within their write_begin() implementations.

#7 lore raw
Quoted 9 lines · Andrew Morton
Quoted 2 lines · On Tue, 21 Oct 2008 08:20:20 +0200 Nick Piggin <[email protected]> wrote:

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

We could withdraw simple_prepare_write() too, I guess. But there's some risk that out-of-tree filesystems might be using it within their write_begin() implementations.

So? That's their risk for beeing out of tree. Nuke it.

maintainer
#8 lore raw
Quoted 4 lines · On Tue, 21 Oct 2008 17:36:35 -0400 Christoph Hellwig <[email protected]> wrote:
Quoted 3 lines · Andrew Morton

On Tue, 21 Oct 2008 08:20:20 +0200
Nick Piggin <[email protected]> wrote:

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

We could withdraw simple_prepare_write() too, I guess. But there's some risk that out-of-tree filesystems might be using it within their write_begin() implementations.

So? That's their risk for beeing out of tree. Nuke it.

Obviously, multiple repetition of the reasons why this is a poor idea didn't sink in, so I won't trouble you with another repetition.

#9 lore raw
Quoted 2 lines · Andrew Morton

Obviously, multiple repetition of the reasons why this is a poor idea didn't sink in, so I won't trouble you with another repetition.

Sorry, but there's absolutely no point of keeping dead code around for out of tree code. It just means we keep dead weight around, that we can't test and thus won't fix. It's not actually doing a service to anyone.

maintainer
#10 lore raw
Quoted 6 lines · On Tue, 21 Oct 2008 17:49:29 -0400 Christoph Hellwig <[email protected]> wrote:
Quoted 2 lines · Andrew Morton

Obviously, multiple repetition of the reasons why this is a poor idea didn't sink in, so I won't trouble you with another repetition.

Sorry, but there's absolutely no point of keeping dead code around for out of tree code.

yes, there _are_ reasons. Two of which are:

- we inconvenience the maintainers and the users of that out-of-tree code

- we drive away testers. People who are dependent upon out-of-tree code cannot test kernel.org kernels. This happens! People have reported it!

Quoted 3 lines

It just means we keep dead weight around, that we
can't test and thus won't fix. It's not actually doing a service to anyone.

We mark it EXPORT_UNUSED_SYMBOL() in 2.6.28.
We remove it from 2.6.29.

That solves the above problems and nothing could be simpler to do.

#11 lore raw
In reply to Andrew Morton
Quoted 9 lines · Andrew Morton
Quoted 2 lines · On Tue, 21 Oct 2008 08:20:20 +0200 Nick Piggin <[email protected]> wrote:

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

We could withdraw simple_prepare_write() too, I guess. But there's some risk that out-of-tree filesystems might be using it within their write_begin() implementations.

That's true. A number of the helper functions are still write_begin implemented by calling into prepare_write... Of course, after this patch, the bare prepare_write functions won't be any use to external modules anymore. At least the code still gets exercised and no hacks, though.

With the perform_write_2copy stuff, it almost becomes crazy for us to support given that very few in-kernel users (and now one) ever test it.

Anyway... this has taken long enough that I don't much care exactly how it gets merged. Whatever you think best.

maintainer
#12 lore raw
In reply to Nick Piggin
Quoted 2 lines · On Tue, 21 Oct 2008 08:20:20 +0200 Nick Piggin <[email protected]> wrote:

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

argh, reiser4 broke.

Edward, I'll disable it in config for now.

#13 lore raw
Quoted 4 lines · Andrew Morton

On Tue, 21 Oct 2008 08:20:20 +0200
Nick Piggin <[email protected]> wrote:

Quoted 9 lines
Quoted 3 lines

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

argh, reiser4 broke.

Edward, I'll disable it in config for now.

Ok, no probs.
Will be fixed up a bit later..

#14 lore raw

PATCH 1/2 reiser4: adjust to the new aops

In reply to Andrew Morton
Quoted 4 lines · Andrew Morton

On Tue, 21 Oct 2008 08:20:20 +0200
Nick Piggin <[email protected]> wrote:

Quoted 8 lines
Quoted 3 lines

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

argh, reiser4 broke.

Edward, I'll disable it in config for now.

Here is the fixup plus support of loop devices
over compressed files (an old to-do issue).
Andrew, please apply.

Thanks,
Edward.

. adjust reiser4 to the new aops (->write_begin, ->write_end) . add support of loop devices over cryptcompress files.

---
 linux-2.6.28-rc2-mm1/fs/reiser4/as_ops.c                      |   18 --
 linux-2.6.28-rc2-mm1/fs/reiser4/page_cache.c                  |    4 
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file/cryptcompress.c   |   56 +++++-
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file/file.c            |   61 +------
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file/file.h            |   31 ++-
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file/file_conversion.c |   83 ++++++++++
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file_ops.c             |   47 -----
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/object.c               |   16 -
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/object.h               |    3 
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/plugin.h               |    8 
 10 files changed, 175 insertions(+), 152 deletions(-)
fs/reiser4/as_ops.c renamed from fs/reiser4/as_ops.c.orig +0 -18
@@ -347,24 +347,6 @@ int reiser4_writepages(struct address_sp
 	return inode_file_plugin(mapping->host)->writepages(mapping, wbc);
 }
 
-int reiser4_prepare_write(struct file *file, struct page *page,
-			  unsigned from, unsigned to)
-{
-	return inode_file_plugin(file->f_dentry->d_inode)->prepare_write(file,
-									 page,
-									 from,
-									 to);
-}
-
-int reiser4_commit_write(struct file *file, struct page *page,
-			 unsigned from, unsigned to)
-{
-	return inode_file_plugin(file->f_dentry->d_inode)->commit_write(file,
-									page,
-									from,
-									to);
-}
-
 /* Make Linus happy.
    Local variables:
    c-indentation-style: "K&R"
fs/reiser4/page_cache.c renamed from fs/reiser4/page_cache.c.orig +2 -2
@@ -560,8 +560,8 @@ static struct address_space_operations f
 	.set_page_dirty = formatted_set_page_dirty,
 	/* used for read-ahead. Not applicable */
 	.readpages = NULL,
-	.prepare_write = NULL,
-	.commit_write = NULL,
+	.write_begin = NULL,
+	.write_end = NULL,
 	.bmap = NULL,
 	/* called just before page is being detached from inode mapping and
 	   removed from memory. Called on truncate, cut/squeeze, and
fs/reiser4/plugin/file/cryptcompress.c renamed from fs/reiser4/plugin/file/cryptcompress.c.orig +44 -12

86 lines not on this page · raw message

fs/reiser4/plugin/file/file.c renamed from fs/reiser4/plugin/file/file.c.orig +14 -47

82 lines not on this page · raw message

fs/reiser4/plugin/file/file.h renamed from fs/reiser4/plugin/file/file.h.orig +18 -13
@@ -59,10 +59,14 @@ int reiser4_readpage(struct file *, stru
 int reiser4_readpages(struct file*, struct address_space*, struct list_head*,
 		      unsigned);
 int reiser4_writepages(struct address_space *, struct writeback_control *);
-int reiser4_prepare_write(struct file *, struct page *, unsigned from,
-			  unsigned to);
-int reiser4_commit_write(struct file *, struct page *, unsigned from,
-			 unsigned to);
+int reiser4_write_begin_careful(struct file *file,
+				struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata);
+int reiser4_write_end_careful(struct file *file,
+			      struct address_space *mapping,
+			      loff_t pos, unsigned len, unsigned copied,
+			      struct page *page, void *fsdata);
 sector_t reiser4_bmap_careful(struct address_space *, sector_t lblock);
 
 /*
@@ -87,12 +91,13 @@ int release_unix_file(struct inode *, st
 
 /* private address space operations */
 int readpage_unix_file(struct file *, struct page *);
-int readpages_unix_file(struct file*, struct address_space*, struct list_head*, unsigned);
+int readpages_unix_file(struct file*, struct address_space*, struct list_head*,
+			unsigned);
 int writepages_unix_file(struct address_space *, struct writeback_control *);
-int prepare_write_unix_file(struct file *, struct page *, unsigned from,
-			    unsigned to);
-int commit_write_unix_file(struct file *, struct page *, unsigned from,
-			   unsigned to);
+int write_begin_unix_file(struct file *file, struct page *page,
+			  unsigned from, unsigned to);
+int write_end_unix_file(struct file *file, struct page *page,
+			unsigned from, unsigned to);
 sector_t bmap_unix_file(struct address_space *, sector_t lblock);
 
 /* other private methods */
@@ -129,10 +134,10 @@ int readpages_cryptcompress(struct file*
 			    struct list_head*, unsigned);
 int writepages_cryptcompress(struct address_space *,
 			     struct writeback_control *);
-int prepare_write_cryptcompress(struct file *, struct page *, unsigned from,
-				unsigned to);
-int commit_write_cryptcompress(struct file *, struct page *, unsigned from,
-			       unsigned to);
+int write_begin_cryptcompress(struct file *file, struct page *page,
+			      unsigned from, unsigned to);
+int write_end_cryptcompress(struct file *file, struct page *page,
+			    unsigned from, unsigned to);
 sector_t bmap_cryptcompress(struct address_space *, sector_t lblock);
 
 /* other private methods */
fs/reiser4/plugin/file/file_conversion.c renamed from fs/reiser4/plugin/file/file_conversion.c.orig +83 -0

89 lines not on this page · raw message

fs/reiser4/plugin/file_ops.c renamed from fs/reiser4/plugin/file_ops.c.orig +2 -45

57 lines not on this page · raw message

fs/reiser4/plugin/object.c renamed from fs/reiser4/plugin/object.c.orig +8 -8
@@ -114,8 +114,8 @@ static struct address_space_operations r
 	.writepages = reiser4_writepages,
 	.set_page_dirty = reiser4_set_page_dirty,
 	.readpages = reiser4_readpages,
-	.prepare_write = reiser4_prepare_write,
-	.commit_write =	reiser4_commit_write,
+	.write_begin = reiser4_write_begin_careful,
+	.write_end = reiser4_write_end_careful,
 	.bmap = reiser4_bmap_careful,
 	.invalidatepage = reiser4_invalidatepage,
 	.releasepage = reiser4_releasepage
@@ -165,8 +165,8 @@ static struct address_space_operations d
 	.writepages = dummyop,
 	.set_page_dirty = bugop,
 	.readpages = bugop,
-	.prepare_write = bugop,
-	.commit_write = bugop,
+	.write_begin = bugop,
+	.write_end = bugop,
 	.bmap = bugop,
 	.invalidatepage = bugop,
 	.releasepage = bugop
@@ -209,8 +209,8 @@ file_plugin file_plugins[LAST_FILE_PLUGI
 		.readpage = readpage_unix_file,
 		.readpages = readpages_unix_file,
 		.writepages = writepages_unix_file,
-		.prepare_write = prepare_write_unix_file,
-		.commit_write = commit_write_unix_file,
+		.write_begin = write_begin_unix_file,
+		.write_end = write_end_unix_file,
 		/*
 		 * private a_ops
 		 */
@@ -403,8 +403,8 @@ file_plugin file_plugins[LAST_FILE_PLUGI
 		.readpage = readpage_cryptcompress,
 		.readpages = readpages_cryptcompress,
 		.writepages = writepages_cryptcompress,
-		.prepare_write = prepare_write_cryptcompress,
-		.commit_write = commit_write_cryptcompress,
+		.write_begin = write_begin_cryptcompress,
+		.write_end = write_end_cryptcompress,
 
 		.bmap = bmap_cryptcompress,
 
fs/reiser4/plugin/object.h renamed from fs/reiser4/plugin/object.h.orig +0 -3
@@ -36,9 +36,6 @@ int reiser4_readdir_common(struct file *
 int reiser4_release_dir_common(struct inode *, struct file *);
 int reiser4_sync_common(struct file *, struct dentry *, int datasync);
 
-/* common implementations of address space operations */
-int prepare_write_common(struct file *, struct page *, unsigned from,
-			 unsigned to);
 
 /* file plugin operations: common implementations */
 int write_sd_by_inode_common(struct inode *);
fs/reiser4/plugin/plugin.h renamed from fs/reiser4/plugin/plugin.h.orig +4 -4
@@ -248,10 +248,10 @@ typedef struct file_plugin {
 			  struct list_head *pages, unsigned nr_pages);
 	int (*writepages)(struct address_space *mapping,
 			  struct writeback_control *wbc);
-	int (*prepare_write)(struct file *file, struct page *page,
-			     unsigned from, unsigned to);
-	int (*commit_write)(struct file *file, struct page *page,
-			    unsigned from, unsigned to);
+	int (*write_begin)(struct file *file, struct page *page,
+			  unsigned from, unsigned to);
+	int (*write_end)(struct file *file, struct page *page,
+			  unsigned from, unsigned to);
 	sector_t (*bmap) (struct address_space * mapping, sector_t lblock);
 	/* other private methods */
 	/* save inode cached stat-data onto disk. It was called
#15 lore raw

Re: [patch 1/2] reiser4: adjust to the new aops

Quoted 14 lines · Edward Shishkin
Quoted 4 lines · Andrew Morton

On Tue, 21 Oct 2008 08:20:20 +0200
Nick Piggin <[email protected]> wrote:

Quoted 8 lines
Quoted 3 lines

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

argh, reiser4 broke.

Edward, I'll disable it in config for now.

Quoted 7 lines

Here is the fixup plus support of loop devices
over compressed files (an old to-do issue).
Andrew, please apply.

Thanks,
Edward.

Thanks Edward, I appreciate your help with this. I don't know the reiser4 code at all, but just remember that you have to be able to tolerate a short-write in write_end (eg. the page may not actually have all or any of the memory initialized in the range (pos, pos+len), only the range (pos, pos+copied) (ie. copied may be < len).

One thing that many block based filesystems have to be careful of is to ensure that the uncopied range (which might contain garbage) doesn't get written back to the filesystem.

I can't immediately see whether you handle that or not, but you're not using 'copied' anywhere, so that might flag a problem.

Thanks,
Nick

Quoted 4 lines

. adjust reiser4 to the new aops (->write_begin, ->write_end) . add support of loop devices over cryptcompress files.

...

#16 lore raw

Re: [patch 1/2] reiser4: adjust to the new aops

Quoted 22 lines · Nick Piggin
Quoted 20 lines · Edward Shishkin
Quoted 5 lines · Andrew Morton

On Tue, 21 Oct 2008 08:20:20 +0200
Nick Piggin <[email protected]> wrote:

Quoted 9 lines
Quoted 4 lines

Nothing uses prepare_write or commit_write. Remove them from the tree completely.

argh, reiser4 broke.

Edward, I'll disable it in config for now.

Here is the fixup plus support of loop devices
over compressed files (an old to-do issue).
Andrew, please apply.

Quoted 6 lines
Quoted 4 lines

Thanks,
Edward.

Thanks Edward, I appreciate your help with this.

Hi Nick,
I am really happy that somebody looks at my patches..

Quoted 6 lines

I don't know the
reiser4 code at all, but just remember that you have to be able to tolerate a short-write in write_end (eg. the page may not actually have all or any of the memory initialized in the range (pos, pos+len), only the range (pos, pos+copied) (ie. copied may be < len).

Quoted 7 lines

One thing that many block based filesystems have to be careful of is to ensure that the uncopied range (which might contain garbage) doesn't get written back to the filesystem.

I can't immediately see whether you handle that or not, but you're not using 'copied' anywhere, so that might flag a problem.

reiser4_write_{begin,end} works only in splice.c (i.e. only for loopback functionality) in the chunk of code which looks like this:

pagecache_write_begin();
...
memcpy(.., to_page);
...
pagecache_write_end(.., to_page, ..);

i.e. there can not be short writes and everything is uptodate.

reiser4_write() has its own means to fight with short writes. Not everything is excellent here though, but this is another topic..

Thanks,
Edward.

#17 lore raw

Re: [patch 1/2] reiser4: adjust to the new aops

Quoted 10 lines · Edward Shishkin

reiser4_write_{begin,end} works only in splice.c (i.e. only for loopback functionality) in the chunk of code which looks like this:

pagecache_write_begin();
...
memcpy(.., to_page);
...
pagecache_write_end(.., to_page, ..);

i.e. there can not be short writes and everything is uptodate.

Ah OK, indeed you are right. Although that's not to say that some other kernel code may not be able to start doing interruptible copies, although it would be fairly unlikely. Maybe if you just have a BUG_ON(!(flags & AOP_FLAG_UNINTERRUPTIBLE)); or something to just make sure?

Quoted 2 lines

reiser4_write() has its own means to fight with short writes. Not everything is excellent here though, but this is another topic..

OK, well in that case, I don't see any problem with your patch.

Thanks,
Nick

#18 lore raw

PATCH 2/2 reiser4: adjust to the new aops fixup

Quoted 11 lines · Nick Piggin
Quoted 9 lines · Edward Shishkin

reiser4_write_{begin,end} works only in splice.c (i.e. only for loopback functionality) in the chunk of code which looks like this:

pagecache_write_begin();
...
memcpy(.., to_page);
...
pagecache_write_end(.., to_page, ..);

Quoted 8 lines
Quoted 2 lines

i.e. there can not be short writes and everything is uptodate.

Ah OK, indeed you are right. Although that's not to say that some other kernel code may not be able to start doing interruptible copies, although it would be fairly unlikely. Maybe if you just have a BUG_ON(!(flags & AOP_FLAG_UNINTERRUPTIBLE)); or something to just make sure?

Yup, I would say, it's a must..

Thanks,
Edward.

Make sure that reiser4_write_begin()
is not called for interruptible copies.

---
 linux-2.6.28-rc2-mm1/fs/reiser4/plugin/file/file_conversion.c |    6 ++++++
 1 file changed, 6 insertions(+)
fs/reiser4/plugin/file/file_conversion.c renamed from fs/reiser4/plugin/file/file_conversion.c.orig +6 -0
@@ -682,6 +682,12 @@ int reiser4_write_begin_careful(struct f
 	reiser4_context *ctx;
 	struct inode * inode = file->f_dentry->d_inode;
 
+	/**
+	 * reiser4_write_end() can not cope with
+	 * short writes for now
+	 */
+	BUG_ON(!(flags & AOP_FLAG_UNINTERRUPTIBLE));
+
 	index = pos >> PAGE_CACHE_SHIFT;
 	start = pos & (PAGE_CACHE_SIZE - 1);
 	end = start + len;
#19 lore raw
In reply to Christoph Hellwig
Quoted 6 lines · Christoph Hellwig
Quoted 2 lines · Nick Piggin

Just FYI (I'll resend for -mm after the last conversions get in), this shows how much cruft we shed after the old aops go away...

All conversions are in mainline now, so can we get this patch in, too for 2.6.28?

Ahh, good. Yes it should go upstream definitely. I'll update the patch and resend with your feedback incorporated.