| From 14b557c19dbe677059243246522da15800ca94f0 Mon Sep 17 00:00:00 2001 |
| From: Nicholas Bellinger <nab@linux-iscsi.org> |
| Date: Sat, 29 Sep 2012 17:15:37 -0700 |
| Subject: target/file: Re-enable optional fd_buffered_io=1 operation |
| |
| From: Nicholas Bellinger <nab@linux-iscsi.org> |
| |
| commit b32f4c7ed85c5cee2a21a55c9f59ebc9d57a2463 upstream. |
| |
| This patch re-adds the ability to optionally run in buffered FILEIO mode |
| (eg: w/o O_DSYNC) for device backends in order to once again use the |
| Linux buffered cache as a write-back storage mechanism. |
| |
| This logic was originally dropped with mainline v3.5-rc commit: |
| |
| commit a4dff3043c231d57f982af635c9d2192ee40e5ae |
| Author: Nicholas Bellinger <nab@linux-iscsi.org> |
| Date: Wed May 30 16:25:41 2012 -0700 |
| |
| target/file: Use O_DSYNC by default for FILEIO backends |
| |
| This difference with this patch is that fd_create_virtdevice() now |
| forces the explicit setting of emulate_write_cache=1 when buffered FILEIO |
| operation has been enabled. |
| |
| (v2: Switch to FDBD_HAS_BUFFERED_IO_WCE + add more detailed |
| comment as requested by hch) |
| |
| Reported-by: Ferry <iscsitmp@bananateam.nl> |
| Cc: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| Cc: Li Zefan <lizefan@huawei.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/target/target_core_file.c | 41 +++++++++++++++++++++++++++++++++++--- |
| drivers/target/target_core_file.h | 1 |
| 2 files changed, 39 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/target/target_core_file.c |
| +++ b/drivers/target/target_core_file.c |
| @@ -138,6 +138,19 @@ static struct se_device *fd_create_virtd |
| * of pure timestamp updates. |
| */ |
| flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; |
| + /* |
| + * Optionally allow fd_buffered_io=1 to be enabled for people |
| + * who want use the fs buffer cache as an WriteCache mechanism. |
| + * |
| + * This means that in event of a hard failure, there is a risk |
| + * of silent data-loss if the SCSI client has *not* performed a |
| + * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE |
| + * to write-out the entire device cache. |
| + */ |
| + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { |
| + pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); |
| + flags &= ~O_DSYNC; |
| + } |
| |
| file = filp_open(dev_p, flags, 0600); |
| if (IS_ERR(file)) { |
| @@ -205,6 +218,12 @@ static struct se_device *fd_create_virtd |
| if (!dev) |
| goto fail; |
| |
| + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { |
| + pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" |
| + " with FDBD_HAS_BUFFERED_IO_WCE\n"); |
| + dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1; |
| + } |
| + |
| fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; |
| fd_dev->fd_queue_depth = dev->queue_depth; |
| |
| @@ -449,6 +468,7 @@ enum { |
| static match_table_t tokens = { |
| {Opt_fd_dev_name, "fd_dev_name=%s"}, |
| {Opt_fd_dev_size, "fd_dev_size=%s"}, |
| + {Opt_fd_buffered_io, "fd_buffered_io=%d"}, |
| {Opt_err, NULL} |
| }; |
| |
| @@ -460,7 +480,7 @@ static ssize_t fd_set_configfs_dev_param |
| struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; |
| char *orig, *ptr, *arg_p, *opts; |
| substring_t args[MAX_OPT_ARGS]; |
| - int ret = 0, token; |
| + int ret = 0, arg, token; |
| |
| opts = kstrdup(page, GFP_KERNEL); |
| if (!opts) |
| @@ -504,6 +524,19 @@ static ssize_t fd_set_configfs_dev_param |
| " bytes\n", fd_dev->fd_dev_size); |
| fd_dev->fbd_flags |= FBDF_HAS_SIZE; |
| break; |
| + case Opt_fd_buffered_io: |
| + match_int(args, &arg); |
| + if (arg != 1) { |
| + pr_err("bogus fd_buffered_io=%d value\n", arg); |
| + ret = -EINVAL; |
| + goto out; |
| + } |
| + |
| + pr_debug("FILEIO: Using buffered I/O" |
| + " operations for struct fd_dev\n"); |
| + |
| + fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE; |
| + break; |
| default: |
| break; |
| } |
| @@ -535,8 +568,10 @@ static ssize_t fd_show_configfs_dev_para |
| ssize_t bl = 0; |
| |
| bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); |
| - bl += sprintf(b + bl, " File: %s Size: %llu Mode: O_DSYNC\n", |
| - fd_dev->fd_dev_name, fd_dev->fd_dev_size); |
| + bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s\n", |
| + fd_dev->fd_dev_name, fd_dev->fd_dev_size, |
| + (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ? |
| + "Buffered-WCE" : "O_DSYNC"); |
| return bl; |
| } |
| |
| --- a/drivers/target/target_core_file.h |
| +++ b/drivers/target/target_core_file.h |
| @@ -18,6 +18,7 @@ struct fd_request { |
| |
| #define FBDF_HAS_PATH 0x01 |
| #define FBDF_HAS_SIZE 0x02 |
| +#define FDBD_HAS_BUFFERED_IO_WCE 0x04 |
| |
| struct fd_dev { |
| u32 fbd_flags; |