[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |