]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_file.c
RDMA/iw_cxgb4: fix the calculation of ipv6 header size
[karo-tx-linux.git] / drivers / target / target_core_file.c
index 87aa376a1a1ae9f9119369725199d7bd5ba22a1e..73b8f93a5fefbf18dfe06f763ffc07ceaca059a3 100644 (file)
@@ -277,12 +277,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 +294,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 +554,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 +565,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 +608,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;
 }