]> git.hungrycats.org Git - linux/commitdiff
[PATCH] IS_SYNC diretory handling
authorAndrew Morton <akpm@zip.com.au>
Mon, 18 Feb 2002 01:01:48 +0000 (17:01 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Mon, 18 Feb 2002 01:01:48 +0000 (17:01 -0800)
A forward-port.  ext2, minix and sysv aren't handling directories
correctly when IS_SYNC is in place.  They call waitfor_one_page(),
but forgot to start the I/O.

The patch also moves waitfor_one_page and writeout_one_page
into fs/buffer.c, so mm/filemap.c now does not mention buffer_head
at all.

fs/buffer.c
fs/ext2/dir.c
fs/minix/dir.c
fs/sysv/ChangeLog
fs/sysv/dir.c
include/linux/fs.h
kernel/ksyms.c
mm/filemap.c

index 216490fb8b70507152a7c2c2a22635f735f1ef17..04dc1d0c7da113b64021d872cf1f2bf66e3fb241 100644 (file)
@@ -1954,6 +1954,48 @@ done:
        goto done;
 }
 
+/*
+ * Commence writeout of all the buffers against a page.  The
+ * page must be locked.   Returns zero on success or a negative
+ * errno.
+ */
+int writeout_one_page(struct page *page)
+{
+       struct buffer_head *bh, *head = page->buffers;
+
+       if (!PageLocked(page))
+               BUG();
+       bh = head;
+       do {
+               if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
+                       continue;
+
+               bh->b_flushtime = jiffies;
+               ll_rw_block(WRITE, 1, &bh);     
+       } while ((bh = bh->b_this_page) != head);
+       return 0;
+}
+EXPORT_SYMBOL(writeout_one_page);
+
+/*
+ * Wait for completion of I/O of all buffers against a page.  The page
+ * must be locked.  Returns zero on success or a negative errno.
+ */
+int waitfor_one_page(struct page *page)
+{
+       int error = 0;
+       struct buffer_head *bh, *head = page->buffers;
+
+       bh = head;
+       do {
+               wait_on_buffer(bh);
+               if (buffer_req(bh) && !buffer_uptodate(bh))
+                       error = -EIO;
+       } while ((bh = bh->b_this_page) != head);
+       return error;
+}
+EXPORT_SYMBOL(waitfor_one_page);
+
 sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
                            get_block_t *get_block)
 {
index d6416b9484f3e2cf13c54b673a09d39735c9e478..c11482c94ed5ceac6a5f5ce30f25d74b68144ad6 100644 (file)
@@ -52,8 +52,13 @@ static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
        int err = 0;
        dir->i_version = ++event;
        page->mapping->a_ops->commit_write(NULL, page, from, to);
-       if (IS_SYNC(dir))
-               err = waitfor_one_page(page);
+       if (IS_SYNC(dir)) {
+               int err2;
+               err = writeout_one_page(page);
+               err2 = waitfor_one_page(page);
+               if (err == 0)
+                       err = err2;
+       }
        return err;
 }
 
index d8b5f8469c1057ee60482b1cf1ca4da84df84f4d..c363a6d009250c76278f3d56b10136455b0e3adf 100644 (file)
@@ -36,8 +36,13 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
        struct inode *dir = (struct inode *)page->mapping->host;
        int err = 0;
        page->mapping->a_ops->commit_write(NULL, page, from, to);
-       if (IS_SYNC(dir))
-               err = waitfor_one_page(page);
+       if (IS_SYNC(dir)) {
+               int err2;
+               err = writeout_one_page(page);
+               err2 = waitfor_one_page(page);
+               if (err == 0)
+                       err = err2;
+       }
        return err;
 }
 
@@ -236,10 +241,10 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
 
        lock_page(page);
        err = mapping->a_ops->prepare_write(NULL, page, from, to);
-       if (err)
-               BUG();
-       de->inode = 0;
-       err = dir_commit_chunk(page, from, to);
+       if (err == 0) {
+               de->inode = 0;
+               err = dir_commit_chunk(page, from, to);
+       }
        UnlockPage(page);
        dir_put_page(page);
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
@@ -336,10 +341,10 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
 
        lock_page(page);
        err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
-       if (err)
-               BUG();
-       de->inode = inode->i_ino;
-       err = dir_commit_chunk(page, from, to);
+       if (err == 0) {
+               de->inode = inode->i_ino;
+               err = dir_commit_chunk(page, from, to);
+       }
        UnlockPage(page);
        dir_put_page(page);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
index adda370673202693bf6c812629f0357b04a46e33..1776aae9bd7879c072dcb2b02bc2be1009925312 100644 (file)
@@ -1,3 +1,9 @@
+Thu Feb 14 2002  Andrew Morton  <akpm@zip.com.au>
+
+       * dir_commit_chunk(): call writeout_one_page() as well as
+         waitfor_one_page() for IS_SYNC directories, so that we
+         actually do sync the directory. (forward-port from 2.4).
+
 Thu Feb  7 2002  Alexander Viro  <viro@math.psu.edu>
 
        * super.c: switched to ->get_sb()
@@ -97,3 +103,4 @@ Fri Oct 26 2001  Christoph Hellwig  <hch@caldera.de>
        Remove symlink faking.  Noone really wants to use these as
        linux filesystems and native OSes don't support it anyway.
 
+
index 99cd284659afd4ce8cdd9d39a50fe459106a0b8b..41e13fe81c8bc6ab2a3618caca7dde71c53054a7 100644 (file)
@@ -42,8 +42,13 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
        int err = 0;
 
        page->mapping->a_ops->commit_write(NULL, page, from, to);
-       if (IS_SYNC(dir))
-               err = waitfor_one_page(page);
+       if (IS_SYNC(dir)) {
+               int err2;
+               err = writeout_one_page(page);
+               err2 = waitfor_one_page(page);
+               if (err == 0)
+                       err = err2;
+       }
        return err;
 }
 
index ff3057143aae7ec28442806537d83f522005abe2..731ac8d2ca945ea3a26176d2ea1482caffe2bd69 100644 (file)
@@ -1440,8 +1440,9 @@ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 extern int generic_direct_IO(int, struct inode *, struct kiobuf *, unsigned long, int, get_block_t *);
+extern int waitfor_one_page(struct page *);
+extern int writeout_one_page(struct page *);
 
-extern int waitfor_one_page(struct page*);
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
index 0d8d867bbd66d7ff5889b0c02a2b26bbd96cf546..7b9510813a5185a0f713e03542325e19b702aeb3 100644 (file)
@@ -213,7 +213,6 @@ EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
-EXPORT_SYMBOL(waitfor_one_page);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
index 16b924b0c5ba14646f83b19e261358fb0547ddcf..3315b4e7237800d19fcb4f6bc09d1294fb54af4d 100644 (file)
@@ -449,41 +449,6 @@ not_found:
        return page;
 }
 
-/*
- * By the time this is called, the page is locked and
- * we don't have to worry about any races any more.
- *
- * Start the IO..
- */
-static int writeout_one_page(struct page *page)
-{
-       struct buffer_head *bh, *head = page->buffers;
-
-       bh = head;
-       do {
-               if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
-                       continue;
-
-               bh->b_flushtime = jiffies;
-               ll_rw_block(WRITE, 1, &bh);     
-       } while ((bh = bh->b_this_page) != head);
-       return 0;
-}
-
-int waitfor_one_page(struct page *page)
-{
-       int error = 0;
-       struct buffer_head *bh, *head = page->buffers;
-
-       bh = head;
-       do {
-               wait_on_buffer(bh);
-               if (buffer_req(bh) && !buffer_uptodate(bh))
-                       error = -EIO;
-       } while ((bh = bh->b_this_page) != head);
-       return error;
-}
-
 static int do_buffer_fdatasync(struct list_head *head, unsigned long start, unsigned long end, int (*fn)(struct page *))
 {
        struct list_head *curr;