[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
|