target: Fix reading of data length fields for UNMAP commands
[pandora-kernel.git] / drivers / target / target_core_file.c
index b4864fb..455a251 100644 (file)
@@ -134,21 +134,11 @@ static struct se_device *fd_create_virtdevice(
                ret = PTR_ERR(dev_p);
                goto fail;
        }
-#if 0
-       if (di->no_create_file)
-               flags = O_RDWR | O_LARGEFILE;
-       else
-               flags = O_RDWR | O_CREAT | O_LARGEFILE;
-#else
-       flags = O_RDWR | O_CREAT | O_LARGEFILE;
-#endif
-/*     flags |= O_DIRECT; */
        /*
-        * If fd_buffered_io=1 has not been set explicitly (the default),
-        * use O_SYNC to force FILEIO writes to disk.
+        * Use O_DSYNC by default instead of O_SYNC to forgo syncing
+        * of pure timestamp updates.
         */
-       if (!(fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO))
-               flags |= O_SYNC;
+       flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
 
        file = filp_open(dev_p, flags, 0600);
        if (IS_ERR(file)) {
@@ -170,6 +160,7 @@ static struct se_device *fd_create_virtdevice(
        inode = file->f_mapping->host;
        if (S_ISBLK(inode->i_mode)) {
                struct request_queue *q;
+               unsigned long long dev_size;
                /*
                 * Setup the local scope queue_limits from struct request_queue->limits
                 * to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
@@ -184,13 +175,12 @@ static struct se_device *fd_create_virtdevice(
                 * one (1) logical sector from underlying struct block_device
                 */
                fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
-               fd_dev->fd_dev_size = (i_size_read(file->f_mapping->host) -
+               dev_size = (i_size_read(file->f_mapping->host) -
                                       fd_dev->fd_block_size);
 
                pr_debug("FILEIO: Using size: %llu bytes from struct"
                        " block_device blocks: %llu logical_block_size: %d\n",
-                       fd_dev->fd_dev_size,
-                       div_u64(fd_dev->fd_dev_size, fd_dev->fd_block_size),
+                       dev_size, div_u64(dev_size, fd_dev->fd_block_size),
                        fd_dev->fd_block_size);
        } else {
                if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
@@ -400,26 +390,6 @@ static void fd_emulate_sync_cache(struct se_task *task)
                transport_complete_sync_cache(cmd, ret == 0);
 }
 
-/*
- * WRITE Force Unit Access (FUA) emulation on a per struct se_task
- * LBA range basis..
- */
-static void fd_emulate_write_fua(struct se_cmd *cmd, struct se_task *task)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct fd_dev *fd_dev = dev->dev_ptr;
-       loff_t start = task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
-       loff_t end = start + task->task_size;
-       int ret;
-
-       pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
-                       task->task_lba, task->task_size);
-
-       ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
-       if (ret != 0)
-               pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
-}
-
 static int fd_do_task(struct se_task *task)
 {
        struct se_cmd *cmd = task->task_se_cmd;
@@ -434,19 +404,21 @@ static int fd_do_task(struct se_task *task)
                ret = fd_do_readv(task);
        } else {
                ret = fd_do_writev(task);
-
+               /*
+                * Perform implict vfs_fsync_range() for fd_do_writev() ops
+                * for SCSI WRITEs with Forced Unit Access (FUA) set.
+                * Allow this to happen independent of WCE=0 setting.
+                */
                if (ret > 0 &&
-                   dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 &&
                    dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
                    (cmd->se_cmd_flags & SCF_FUA)) {
-                       /*
-                        * We might need to be a bit smarter here
-                        * and return some sense data to let the initiator
-                        * know the FUA WRITE cache sync failed..?
-                        */
-                       fd_emulate_write_fua(cmd, task);
-               }
+                       struct fd_dev *fd_dev = dev->dev_ptr;
+                       loff_t start = task->task_lba *
+                               dev->se_sub_dev->se_dev_attrib.block_size;
+                       loff_t end = start + task->task_size;
 
+                       vfs_fsync_range(fd_dev->fd_file, start, end, 1);
+               }
        }
 
        if (ret < 0) {
@@ -478,7 +450,6 @@ 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}
 };
 
@@ -490,7 +461,7 @@ static ssize_t fd_set_configfs_dev_params(
        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, arg, token;
+       int ret = 0, token;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -534,19 +505,6 @@ static ssize_t fd_set_configfs_dev_params(
                                        " 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_USE_BUFFERED_IO;
-                       break;
                default:
                        break;
                }
@@ -578,10 +536,8 @@ static ssize_t fd_show_configfs_dev_params(
        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: %s\n",
-               fd_dev->fd_dev_name, fd_dev->fd_dev_size,
-               (fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO) ?
-               "Buffered" : "Synchronous");
+       bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: O_DSYNC\n",
+               fd_dev->fd_dev_name, fd_dev->fd_dev_size);
        return bl;
 }
 
@@ -606,10 +562,20 @@ static u32 fd_get_device_type(struct se_device *dev)
 static sector_t fd_get_blocks(struct se_device *dev)
 {
        struct fd_dev *fd_dev = dev->dev_ptr;
-       unsigned long long blocks_long = div_u64(fd_dev->fd_dev_size,
-                       dev->se_sub_dev->se_dev_attrib.block_size);
+       struct file *f = fd_dev->fd_file;
+       struct inode *i = f->f_mapping->host;
+       unsigned long long dev_size;
+       /*
+        * When using a file that references an underlying struct block_device,
+        * ensure dev_size is always based on the current inode size in order
+        * to handle underlying block_device resize operations.
+        */
+       if (S_ISBLK(i->i_mode))
+               dev_size = (i_size_read(i) - fd_dev->fd_block_size);
+       else
+               dev_size = fd_dev->fd_dev_size;
 
-       return blocks_long;
+       return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size);
 }
 
 static struct se_subsystem_api fileio_template = {