]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/target/target_core_file.c
target: break up free_device callback
[linux.git] / drivers / target / target_core_file.c
index 87aa376a1a1ae9f9119369725199d7bd5ba22a1e..50f2355805461755e43aa9d0854d02e85a876e02 100644 (file)
@@ -236,6 +236,11 @@ static void fd_dev_call_rcu(struct rcu_head *p)
 }
 
 static void fd_free_device(struct se_device *dev)
+{
+       call_rcu(&dev->rcu_head, fd_dev_call_rcu);
+}
+
+static void fd_destroy_device(struct se_device *dev)
 {
        struct fd_dev *fd_dev = FD_DEV(dev);
 
@@ -243,7 +248,6 @@ static void fd_free_device(struct se_device *dev)
                filp_close(fd_dev->fd_file, NULL);
                fd_dev->fd_file = NULL;
        }
-       call_rcu(&dev->rcu_head, fd_dev_call_rcu);
 }
 
 static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
@@ -277,12 +281,11 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
        else
                ret = vfs_iter_read(fd, &iter, &pos);
 
-       kfree(bvec);
-
        if (is_write) {
                if (ret < 0 || ret != data_length) {
                        pr_err("%s() write returned %d\n", __func__, ret);
-                       return (ret < 0 ? ret : -EINVAL);
+                       if (ret >= 0)
+                               ret = -EINVAL;
                }
        } else {
                /*
@@ -295,17 +298,29 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
                                pr_err("%s() returned %d, expecting %u for "
                                                "S_ISBLK\n", __func__, ret,
                                                data_length);
-                               return (ret < 0 ? ret : -EINVAL);
+                               if (ret >= 0)
+                                       ret = -EINVAL;
                        }
                } else {
                        if (ret < 0) {
                                pr_err("%s() returned %d for non S_ISBLK\n",
                                                __func__, ret);
-                               return ret;
+                       } else if (ret != data_length) {
+                               /*
+                                * Short read case:
+                                * Probably some one truncate file under us.
+                                * We must explicitly zero sg-pages to prevent
+                                * expose uninizialized pages to userspace.
+                                */
+                               if (ret < data_length)
+                                       ret += iov_iter_zero(data_length - ret, &iter);
+                               else
+                                       ret = -EINVAL;
                        }
                }
        }
-       return 1;
+       kfree(bvec);
+       return ret;
 }
 
 static sense_reason_t
@@ -543,7 +558,8 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
                               sgl, sgl_nents, cmd->data_length, 0);
 
-               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
+               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type &&
+                   dev->dev_attrib.pi_prot_verify) {
                        u32 sectors = cmd->data_length >>
                                        ilog2(dev->dev_attrib.block_size);
 
@@ -553,7 +569,8 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                return rc;
                }
        } else {
-               if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
+               if (cmd->prot_type && dev->dev_attrib.pi_prot_type &&
+                   dev->dev_attrib.pi_prot_verify) {
                        u32 sectors = cmd->data_length >>
                                        ilog2(dev->dev_attrib.block_size);
 
@@ -595,8 +612,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        if (ret < 0)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       if (ret)
-               target_complete_cmd(cmd, SAM_STAT_GOOD);
+       target_complete_cmd(cmd, SAM_STAT_GOOD);
        return 0;
 }
 
@@ -814,6 +830,7 @@ static const struct target_backend_ops fileio_ops = {
        .detach_hba             = fd_detach_hba,
        .alloc_device           = fd_alloc_device,
        .configure_device       = fd_configure_device,
+       .destroy_device         = fd_destroy_device,
        .free_device            = fd_free_device,
        .parse_cdb              = fd_parse_cdb,
        .set_configfs_dev_params = fd_set_configfs_dev_params,