[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [patch 4/6] xenblk: Add O_DIRECT and O_SYNC support -- generic support for O_SYNC.



[patch 4/6] xenblk: Add O_DIRECT and O_SYNC support -- generic support for 
O_SYNC.

Add new buffer_head flag BH_Sync_Write for sync write.
If the inode with sync flag(always is a mount options) or file open with
O_SYNC flag, mark the buffer_head(s) to Sync_Write flag. On buffer try 
to submit, check the flag, if the flag have setted, mark submit_bio()
rw flag to WRITE_SYNC, then frontend would pass the flag to backend.

diff -r 2fb13b8cbe13 include/linux/buffer_head.h
--- a/include/linux/buffer_head.h       Thu Oct 30 13:34:43 2008 +0000
+++ b/include/linux/buffer_head.h       Mon Nov 03 10:31:41 2008 +0800
@@ -27,6 +27,7 @@
        BH_New,         /* Disk mapping was newly created by get_block */
        BH_Async_Read,  /* Is under end_buffer_async_read I/O */
        BH_Async_Write, /* Is under end_buffer_async_write I/O */
+       BH_Sync_Write,  /* For xenblk O_SYNC write support */
        BH_Delay,       /* Buffer is not yet allocated on disk */
        BH_Boundary,    /* Block is followed by a discontiguity */
        BH_Write_EIO,   /* I/O error on write */
@@ -118,6 +119,7 @@
 BUFFER_FNS(Async_Read, async_read)
 BUFFER_FNS(Async_Write, async_write)
 BUFFER_FNS(Delay, delay)
+BUFFER_FNS(Sync_Write, sync_write)
 BUFFER_FNS(Boundary, boundary)
 BUFFER_FNS(Write_EIO, write_io_error)
 BUFFER_FNS(Ordered, ordered)
@@ -185,6 +187,25 @@
                        sector_t bblock, unsigned blocksize);
 
 extern int buffer_heads_over_limit;
+
+#if defined(CONFIG_XEN) && (defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE) || 
defined(CONFIG_XEN_BLKDEV_FRONTEND))
+#define mark_sync_write_bh(bh) set_buffer_sync_write(bh)
+static inline void mark_sync_write_bhs(struct page *page)
+{
+       struct buffer_head *bh, *head;
+
+       BUG_ON(!page_has_buffers(page));
+       bh = head = page_buffers(page);
+       do {
+               set_buffer_sync_write(bh);
+               bh = bh->b_this_page;
+       } while (bh != head);
+
+}
+#else
+#define mark_sync_write_bh(bh)  do { } while(0)
+#define mark_sync_write_bhs(struct page *page) do { } while(0)
+#endif
 
 /*
  * Generic address_space_operations implementations for buffer_head-backed
 /*
  * Recognised if "feature-flush-cache" is present in backend xenbus
  * info.  A flush will ask the underlying storage hardware to flush its
diff -r 2fb13b8cbe13 fs/buffer.c
--- a/fs/buffer.c       Thu Oct 30 13:34:43 2008 +0000
+++ b/fs/buffer.c       Mon Nov 03 10:31:41 2008 +0800
@@ -616,6 +616,38 @@
        bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
        local_irq_restore(flags);
        return;
+}
+
+static void end_buffer_sync_write(struct buffer_head *bh)
+{
+       unsigned long flags;
+
+       BUG_ON(!buffer_sync_write(bh));
+
+
+       local_irq_save(flags);
+       bit_spin_lock(BH_Uptodate_Lock, &bh->b_state);
+       clear_buffer_sync_write(bh);
+       bit_spin_unlock(BH_Uptodate_Lock, &bh->b_state);
+       local_irq_restore(flags);
+       return;
+}
+
+static int end_bio_bh_io_sync_write(struct bio *bio, unsigned int bytes_done, 
int err)
+{
+       struct buffer_head *bh = bio->bi_private;
+
+       if (bio->bi_size)
+               return 1;
+
+       if (err == -EOPNOTSUPP) {
+               set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+               set_bit(BH_Eopnotsupp, &bh->b_state);
+       }
+       end_buffer_sync_write(bh);
+       bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
+       bio_put(bio);
+       return 0;
 }
 
 /*
@@ -2840,6 +2872,13 @@
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
 
+       /* for xenblk O_SYNC support, let frontend mark it as SYNC io,
+        * then backend would submit it immedately */
+       if ((rw & WRITE) && buffer_sync_write(bh))  {
+               bio->bi_end_io = end_bio_bh_io_sync_write;
+               rw |= WRITE_SYNC;
+       }
+
        bio_get(bio);
        submit_bio(rw, bio);
 
@@ -2921,6 +2960,7 @@
        if (test_clear_buffer_dirty(bh)) {
                get_bh(bh);
                bh->b_end_io = end_buffer_write_sync;
+               mark_sync_write_bh(bh);
                ret = submit_bh(WRITE, bh);
                wait_on_buffer(bh);
                if (buffer_eopnotsupp(bh)) {

diff -r 2fb13b8cbe13 mm/filemap.c
--- a/mm/filemap.c      Thu Oct 30 13:34:43 2008 +0000
+++ b/mm/filemap.c      Mon Nov 03 10:31:41 2008 +0800
@@ -2145,6 +2145,8 @@
                                vmtruncate(inode, isize);
                        break;
                }
+               if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
+                       mark_sync_write_bhs(page);
                if (likely(nr_segs == 1))
                        copied = filemap_copy_from_user(page, offset,
                                                        buf, bytes);




_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.