951 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*******************************************************************************3 * Filename: target_core_file.c4 *5 * This file contains the Storage Engine <-> FILEIO transport specific functions6 *7 * (c) Copyright 2005-2013 Datera, Inc.8 *9 * Nicholas A. Bellinger <nab@kernel.org>10 *11 ******************************************************************************/12 13#include <linux/string.h>14#include <linux/parser.h>15#include <linux/timer.h>16#include <linux/blkdev.h>17#include <linux/slab.h>18#include <linux/spinlock.h>19#include <linux/module.h>20#include <linux/vmalloc.h>21#include <linux/falloc.h>22#include <linux/uio.h>23#include <linux/scatterlist.h>24#include <scsi/scsi_proto.h>25#include <linux/unaligned.h>26 27#include <target/target_core_base.h>28#include <target/target_core_backend.h>29 30#include "target_core_file.h"31 32static inline struct fd_dev *FD_DEV(struct se_device *dev)33{34 return container_of(dev, struct fd_dev, dev);35}36 37static int fd_attach_hba(struct se_hba *hba, u32 host_id)38{39 struct fd_host *fd_host;40 41 fd_host = kzalloc(sizeof(struct fd_host), GFP_KERNEL);42 if (!fd_host) {43 pr_err("Unable to allocate memory for struct fd_host\n");44 return -ENOMEM;45 }46 47 fd_host->fd_host_id = host_id;48 49 hba->hba_ptr = fd_host;50 51 pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"52 " Target Core Stack %s\n", hba->hba_id, FD_VERSION,53 TARGET_CORE_VERSION);54 pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",55 hba->hba_id, fd_host->fd_host_id);56 57 return 0;58}59 60static void fd_detach_hba(struct se_hba *hba)61{62 struct fd_host *fd_host = hba->hba_ptr;63 64 pr_debug("CORE_HBA[%d] - Detached FILEIO HBA: %u from Generic"65 " Target Core\n", hba->hba_id, fd_host->fd_host_id);66 67 kfree(fd_host);68 hba->hba_ptr = NULL;69}70 71static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name)72{73 struct fd_dev *fd_dev;74 struct fd_host *fd_host = hba->hba_ptr;75 76 fd_dev = kzalloc(sizeof(struct fd_dev), GFP_KERNEL);77 if (!fd_dev) {78 pr_err("Unable to allocate memory for struct fd_dev\n");79 return NULL;80 }81 82 fd_dev->fd_host = fd_host;83 84 pr_debug("FILEIO: Allocated fd_dev for %p\n", name);85 86 return &fd_dev->dev;87}88 89static bool fd_configure_unmap(struct se_device *dev)90{91 struct file *file = FD_DEV(dev)->fd_file;92 struct inode *inode = file->f_mapping->host;93 94 if (S_ISBLK(inode->i_mode))95 return target_configure_unmap_from_queue(&dev->dev_attrib,96 I_BDEV(inode));97 98 /* Limit UNMAP emulation to 8k Number of LBAs (NoLB) */99 dev->dev_attrib.max_unmap_lba_count = 0x2000;100 /* Currently hardcoded to 1 in Linux/SCSI code. */101 dev->dev_attrib.max_unmap_block_desc_count = 1;102 dev->dev_attrib.unmap_granularity = 1;103 dev->dev_attrib.unmap_granularity_alignment = 0;104 return true;105}106 107static int fd_configure_device(struct se_device *dev)108{109 struct fd_dev *fd_dev = FD_DEV(dev);110 struct fd_host *fd_host = dev->se_hba->hba_ptr;111 struct file *file;112 struct inode *inode = NULL;113 int flags, ret = -EINVAL;114 115 if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {116 pr_err("Missing fd_dev_name=\n");117 return -EINVAL;118 }119 120 /*121 * Use O_DSYNC by default instead of O_SYNC to forgo syncing122 * of pure timestamp updates.123 */124 flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;125 126 /*127 * Optionally allow fd_buffered_io=1 to be enabled for people128 * who want use the fs buffer cache as an WriteCache mechanism.129 *130 * This means that in event of a hard failure, there is a risk131 * of silent data-loss if the SCSI client has *not* performed a132 * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE133 * to write-out the entire device cache.134 */135 if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {136 pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n");137 flags &= ~O_DSYNC;138 }139 140 file = filp_open(fd_dev->fd_dev_name, flags, 0600);141 if (IS_ERR(file)) {142 pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name);143 ret = PTR_ERR(file);144 goto fail;145 }146 fd_dev->fd_file = file;147 /*148 * If using a block backend with this struct file, we extract149 * fd_dev->fd_[block,dev]_size from struct block_device.150 *151 * Otherwise, we use the passed fd_size= from configfs152 */153 inode = file->f_mapping->host;154 if (S_ISBLK(inode->i_mode)) {155 struct block_device *bdev = I_BDEV(inode);156 unsigned long long dev_size;157 158 fd_dev->fd_block_size = bdev_logical_block_size(bdev);159 /*160 * Determine the number of bytes from i_size_read() minus161 * one (1) logical sector from underlying struct block_device162 */163 dev_size = (i_size_read(file->f_mapping->host) -164 fd_dev->fd_block_size);165 166 pr_debug("FILEIO: Using size: %llu bytes from struct"167 " block_device blocks: %llu logical_block_size: %d\n",168 dev_size, div_u64(dev_size, fd_dev->fd_block_size),169 fd_dev->fd_block_size);170 /*171 * Enable write same emulation for IBLOCK and use 0xFFFF as172 * the smaller WRITE_SAME(10) only has a two-byte block count.173 */174 dev->dev_attrib.max_write_same_len = 0xFFFF;175 176 if (bdev_nonrot(bdev))177 dev->dev_attrib.is_nonrot = 1;178 } else {179 if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {180 pr_err("FILEIO: Missing fd_dev_size="181 " parameter, and no backing struct"182 " block_device\n");183 goto fail;184 }185 186 fd_dev->fd_block_size = FD_BLOCKSIZE;187 188 /*189 * Limit WRITE_SAME w/ UNMAP=0 emulation to 8k Number of LBAs (NoLB)190 * based upon struct iovec limit for vfs_writev()191 */192 dev->dev_attrib.max_write_same_len = 0x1000;193 }194 195 dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;196 dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;197 dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;198 199 if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {200 pr_debug("FILEIO: Forcing setting of emulate_write_cache=1"201 " with FDBD_HAS_BUFFERED_IO_WCE\n");202 dev->dev_attrib.emulate_write_cache = 1;203 }204 205 fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;206 fd_dev->fd_queue_depth = dev->queue_depth;207 208 pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s,"209 " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id,210 fd_dev->fd_dev_name, fd_dev->fd_dev_size);211 212 return 0;213fail:214 if (fd_dev->fd_file) {215 filp_close(fd_dev->fd_file, NULL);216 fd_dev->fd_file = NULL;217 }218 return ret;219}220 221static void fd_dev_call_rcu(struct rcu_head *p)222{223 struct se_device *dev = container_of(p, struct se_device, rcu_head);224 struct fd_dev *fd_dev = FD_DEV(dev);225 226 kfree(fd_dev);227}228 229static void fd_free_device(struct se_device *dev)230{231 call_rcu(&dev->rcu_head, fd_dev_call_rcu);232}233 234static void fd_destroy_device(struct se_device *dev)235{236 struct fd_dev *fd_dev = FD_DEV(dev);237 238 if (fd_dev->fd_file) {239 filp_close(fd_dev->fd_file, NULL);240 fd_dev->fd_file = NULL;241 }242}243 244struct target_core_file_cmd {245 unsigned long len;246 struct se_cmd *cmd;247 struct kiocb iocb;248 struct bio_vec bvecs[];249};250 251static void cmd_rw_aio_complete(struct kiocb *iocb, long ret)252{253 struct target_core_file_cmd *cmd;254 255 cmd = container_of(iocb, struct target_core_file_cmd, iocb);256 257 if (ret != cmd->len)258 target_complete_cmd(cmd->cmd, SAM_STAT_CHECK_CONDITION);259 else260 target_complete_cmd(cmd->cmd, SAM_STAT_GOOD);261 262 kfree(cmd);263}264 265static sense_reason_t266fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,267 enum dma_data_direction data_direction)268{269 int is_write = !(data_direction == DMA_FROM_DEVICE);270 struct se_device *dev = cmd->se_dev;271 struct fd_dev *fd_dev = FD_DEV(dev);272 struct file *file = fd_dev->fd_file;273 struct target_core_file_cmd *aio_cmd;274 struct iov_iter iter;275 struct scatterlist *sg;276 ssize_t len = 0;277 int ret = 0, i;278 279 aio_cmd = kmalloc(struct_size(aio_cmd, bvecs, sgl_nents), GFP_KERNEL);280 if (!aio_cmd)281 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;282 283 for_each_sg(sgl, sg, sgl_nents, i) {284 bvec_set_page(&aio_cmd->bvecs[i], sg_page(sg), sg->length,285 sg->offset);286 len += sg->length;287 }288 289 iov_iter_bvec(&iter, is_write, aio_cmd->bvecs, sgl_nents, len);290 291 aio_cmd->cmd = cmd;292 aio_cmd->len = len;293 aio_cmd->iocb.ki_pos = cmd->t_task_lba * dev->dev_attrib.block_size;294 aio_cmd->iocb.ki_filp = file;295 aio_cmd->iocb.ki_complete = cmd_rw_aio_complete;296 aio_cmd->iocb.ki_flags = IOCB_DIRECT;297 298 if (is_write && (cmd->se_cmd_flags & SCF_FUA))299 aio_cmd->iocb.ki_flags |= IOCB_DSYNC;300 301 if (is_write)302 ret = file->f_op->write_iter(&aio_cmd->iocb, &iter);303 else304 ret = file->f_op->read_iter(&aio_cmd->iocb, &iter);305 306 if (ret != -EIOCBQUEUED)307 cmd_rw_aio_complete(&aio_cmd->iocb, ret);308 309 return 0;310}311 312static int fd_do_rw(struct se_cmd *cmd, struct file *fd,313 u32 block_size, struct scatterlist *sgl,314 u32 sgl_nents, u32 data_length, int is_write)315{316 struct scatterlist *sg;317 struct iov_iter iter;318 struct bio_vec *bvec;319 ssize_t len = 0;320 loff_t pos = (cmd->t_task_lba * block_size);321 int ret = 0, i;322 323 bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL);324 if (!bvec) {325 pr_err("Unable to allocate fd_do_readv iov[]\n");326 return -ENOMEM;327 }328 329 for_each_sg(sgl, sg, sgl_nents, i) {330 bvec_set_page(&bvec[i], sg_page(sg), sg->length, sg->offset);331 len += sg->length;332 }333 334 iov_iter_bvec(&iter, is_write, bvec, sgl_nents, len);335 if (is_write)336 ret = vfs_iter_write(fd, &iter, &pos, 0);337 else338 ret = vfs_iter_read(fd, &iter, &pos, 0);339 340 if (is_write) {341 if (ret < 0 || ret != data_length) {342 pr_err("%s() write returned %d\n", __func__, ret);343 if (ret >= 0)344 ret = -EINVAL;345 }346 } else {347 /*348 * Return zeros and GOOD status even if the READ did not return349 * the expected virt_size for struct file w/o a backing struct350 * block_device.351 */352 if (S_ISBLK(file_inode(fd)->i_mode)) {353 if (ret < 0 || ret != data_length) {354 pr_err("%s() returned %d, expecting %u for "355 "S_ISBLK\n", __func__, ret,356 data_length);357 if (ret >= 0)358 ret = -EINVAL;359 }360 } else {361 if (ret < 0) {362 pr_err("%s() returned %d for non S_ISBLK\n",363 __func__, ret);364 } else if (ret != data_length) {365 /*366 * Short read case:367 * Probably some one truncate file under us.368 * We must explicitly zero sg-pages to prevent369 * expose uninizialized pages to userspace.370 */371 if (ret < data_length)372 ret += iov_iter_zero(data_length - ret, &iter);373 else374 ret = -EINVAL;375 }376 }377 }378 kfree(bvec);379 return ret;380}381 382static sense_reason_t383fd_execute_sync_cache(struct se_cmd *cmd)384{385 struct se_device *dev = cmd->se_dev;386 struct fd_dev *fd_dev = FD_DEV(dev);387 int immed = (cmd->t_task_cdb[1] & 0x2);388 loff_t start, end;389 int ret;390 391 /*392 * If the Immediate bit is set, queue up the GOOD response393 * for this SYNCHRONIZE_CACHE op394 */395 if (immed)396 target_complete_cmd(cmd, SAM_STAT_GOOD);397 398 /*399 * Determine if we will be flushing the entire device.400 */401 if (cmd->t_task_lba == 0 && cmd->data_length == 0) {402 start = 0;403 end = LLONG_MAX;404 } else {405 start = cmd->t_task_lba * dev->dev_attrib.block_size;406 if (cmd->data_length)407 end = start + cmd->data_length - 1;408 else409 end = LLONG_MAX;410 }411 412 ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);413 if (ret != 0)414 pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);415 416 if (immed)417 return 0;418 419 if (ret)420 target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);421 else422 target_complete_cmd(cmd, SAM_STAT_GOOD);423 424 return 0;425}426 427static sense_reason_t428fd_execute_write_same(struct se_cmd *cmd)429{430 struct se_device *se_dev = cmd->se_dev;431 struct fd_dev *fd_dev = FD_DEV(se_dev);432 loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;433 sector_t nolb = sbc_get_write_same_sectors(cmd);434 struct iov_iter iter;435 struct bio_vec *bvec;436 unsigned int len = 0, i;437 ssize_t ret;438 439 if (cmd->prot_op) {440 pr_err("WRITE_SAME: Protection information with FILEIO"441 " backends not supported\n");442 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;443 }444 445 if (!cmd->t_data_nents)446 return TCM_INVALID_CDB_FIELD;447 448 if (cmd->t_data_nents > 1 ||449 cmd->t_data_sg[0].length != cmd->se_dev->dev_attrib.block_size) {450 pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"451 " block_size: %u\n",452 cmd->t_data_nents,453 cmd->t_data_sg[0].length,454 cmd->se_dev->dev_attrib.block_size);455 return TCM_INVALID_CDB_FIELD;456 }457 458 bvec = kcalloc(nolb, sizeof(struct bio_vec), GFP_KERNEL);459 if (!bvec)460 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;461 462 for (i = 0; i < nolb; i++) {463 bvec_set_page(&bvec[i], sg_page(&cmd->t_data_sg[0]),464 cmd->t_data_sg[0].length,465 cmd->t_data_sg[0].offset);466 len += se_dev->dev_attrib.block_size;467 }468 469 iov_iter_bvec(&iter, ITER_SOURCE, bvec, nolb, len);470 ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos, 0);471 472 kfree(bvec);473 if (ret < 0 || ret != len) {474 pr_err("vfs_iter_write() returned %zd for write same\n", ret);475 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;476 }477 478 target_complete_cmd(cmd, SAM_STAT_GOOD);479 return 0;480}481 482static int483fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb,484 void *buf, size_t bufsize)485{486 struct fd_dev *fd_dev = FD_DEV(se_dev);487 struct file *prot_fd = fd_dev->fd_prot_file;488 sector_t prot_length, prot;489 loff_t pos = lba * se_dev->prot_length;490 491 if (!prot_fd) {492 pr_err("Unable to locate fd_dev->fd_prot_file\n");493 return -ENODEV;494 }495 496 prot_length = nolb * se_dev->prot_length;497 498 memset(buf, 0xff, bufsize);499 for (prot = 0; prot < prot_length;) {500 sector_t len = min_t(sector_t, bufsize, prot_length - prot);501 ssize_t ret = kernel_write(prot_fd, buf, len, &pos);502 503 if (ret != len) {504 pr_err("vfs_write to prot file failed: %zd\n", ret);505 return ret < 0 ? ret : -ENODEV;506 }507 prot += ret;508 }509 510 return 0;511}512 513static int514fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)515{516 void *buf;517 int rc;518 519 buf = (void *)__get_free_page(GFP_KERNEL);520 if (!buf) {521 pr_err("Unable to allocate FILEIO prot buf\n");522 return -ENOMEM;523 }524 525 rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);526 527 free_page((unsigned long)buf);528 529 return rc;530}531 532static sense_reason_t533fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)534{535 struct file *file = FD_DEV(cmd->se_dev)->fd_file;536 struct inode *inode = file->f_mapping->host;537 int ret;538 539 if (!nolb) {540 return 0;541 }542 543 if (cmd->se_dev->dev_attrib.pi_prot_type) {544 ret = fd_do_prot_unmap(cmd, lba, nolb);545 if (ret)546 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;547 }548 549 if (S_ISBLK(inode->i_mode)) {550 /* The backend is block device, use discard */551 struct block_device *bdev = I_BDEV(inode);552 struct se_device *dev = cmd->se_dev;553 554 ret = blkdev_issue_discard(bdev,555 target_to_linux_sector(dev, lba),556 target_to_linux_sector(dev, nolb),557 GFP_KERNEL);558 if (ret < 0) {559 pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",560 ret);561 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;562 }563 } else {564 /* The backend is normal file, use fallocate */565 struct se_device *se_dev = cmd->se_dev;566 loff_t pos = lba * se_dev->dev_attrib.block_size;567 unsigned int len = nolb * se_dev->dev_attrib.block_size;568 int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;569 570 if (!file->f_op->fallocate)571 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;572 573 ret = file->f_op->fallocate(file, mode, pos, len);574 if (ret < 0) {575 pr_warn("FILEIO: fallocate() failed: %d\n", ret);576 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;577 }578 }579 580 return 0;581}582 583static sense_reason_t584fd_execute_rw_buffered(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,585 enum dma_data_direction data_direction)586{587 struct se_device *dev = cmd->se_dev;588 struct fd_dev *fd_dev = FD_DEV(dev);589 struct file *file = fd_dev->fd_file;590 struct file *pfile = fd_dev->fd_prot_file;591 sense_reason_t rc;592 int ret = 0;593 /*594 * Call vectorized fileio functions to map struct scatterlist595 * physical memory addresses to struct iovec virtual memory.596 */597 if (data_direction == DMA_FROM_DEVICE) {598 if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {599 ret = fd_do_rw(cmd, pfile, dev->prot_length,600 cmd->t_prot_sg, cmd->t_prot_nents,601 cmd->prot_length, 0);602 if (ret < 0)603 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;604 }605 606 ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,607 sgl, sgl_nents, cmd->data_length, 0);608 609 if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type &&610 dev->dev_attrib.pi_prot_verify) {611 u32 sectors = cmd->data_length >>612 ilog2(dev->dev_attrib.block_size);613 614 rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,615 0, cmd->t_prot_sg, 0);616 if (rc)617 return rc;618 }619 } else {620 if (cmd->prot_type && dev->dev_attrib.pi_prot_type &&621 dev->dev_attrib.pi_prot_verify) {622 u32 sectors = cmd->data_length >>623 ilog2(dev->dev_attrib.block_size);624 625 rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,626 0, cmd->t_prot_sg, 0);627 if (rc)628 return rc;629 }630 631 ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,632 sgl, sgl_nents, cmd->data_length, 1);633 /*634 * Perform implicit vfs_fsync_range() for fd_do_writev() ops635 * for SCSI WRITEs with Forced Unit Access (FUA) set.636 * Allow this to happen independent of WCE=0 setting.637 */638 if (ret > 0 && (cmd->se_cmd_flags & SCF_FUA)) {639 loff_t start = cmd->t_task_lba *640 dev->dev_attrib.block_size;641 loff_t end;642 643 if (cmd->data_length)644 end = start + cmd->data_length - 1;645 else646 end = LLONG_MAX;647 648 vfs_fsync_range(fd_dev->fd_file, start, end, 1);649 }650 651 if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {652 ret = fd_do_rw(cmd, pfile, dev->prot_length,653 cmd->t_prot_sg, cmd->t_prot_nents,654 cmd->prot_length, 1);655 if (ret < 0)656 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;657 }658 }659 660 if (ret < 0)661 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;662 663 target_complete_cmd(cmd, SAM_STAT_GOOD);664 return 0;665}666 667static sense_reason_t668fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,669 enum dma_data_direction data_direction)670{671 struct se_device *dev = cmd->se_dev;672 struct fd_dev *fd_dev = FD_DEV(dev);673 674 /*675 * We are currently limited by the number of iovecs (2048) per676 * single vfs_[writev,readv] call.677 */678 if (cmd->data_length > FD_MAX_BYTES) {679 pr_err("FILEIO: Not able to process I/O of %u bytes due to"680 "FD_MAX_BYTES: %u iovec count limitation\n",681 cmd->data_length, FD_MAX_BYTES);682 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;683 }684 685 if (fd_dev->fbd_flags & FDBD_HAS_ASYNC_IO)686 return fd_execute_rw_aio(cmd, sgl, sgl_nents, data_direction);687 return fd_execute_rw_buffered(cmd, sgl, sgl_nents, data_direction);688}689 690enum {691 Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io,692 Opt_fd_async_io, Opt_err693};694 695static match_table_t tokens = {696 {Opt_fd_dev_name, "fd_dev_name=%s"},697 {Opt_fd_dev_size, "fd_dev_size=%s"},698 {Opt_fd_buffered_io, "fd_buffered_io=%d"},699 {Opt_fd_async_io, "fd_async_io=%d"},700 {Opt_err, NULL}701};702 703static ssize_t fd_set_configfs_dev_params(struct se_device *dev,704 const char *page, ssize_t count)705{706 struct fd_dev *fd_dev = FD_DEV(dev);707 char *orig, *ptr, *arg_p, *opts;708 substring_t args[MAX_OPT_ARGS];709 int ret = 0, arg, token;710 711 opts = kstrdup(page, GFP_KERNEL);712 if (!opts)713 return -ENOMEM;714 715 orig = opts;716 717 while ((ptr = strsep(&opts, ",\n")) != NULL) {718 if (!*ptr)719 continue;720 721 token = match_token(ptr, tokens, args);722 switch (token) {723 case Opt_fd_dev_name:724 if (match_strlcpy(fd_dev->fd_dev_name, &args[0],725 FD_MAX_DEV_NAME) == 0) {726 ret = -EINVAL;727 break;728 }729 pr_debug("FILEIO: Referencing Path: %s\n",730 fd_dev->fd_dev_name);731 fd_dev->fbd_flags |= FBDF_HAS_PATH;732 break;733 case Opt_fd_dev_size:734 arg_p = match_strdup(&args[0]);735 if (!arg_p) {736 ret = -ENOMEM;737 break;738 }739 ret = kstrtoull(arg_p, 0, &fd_dev->fd_dev_size);740 kfree(arg_p);741 if (ret < 0) {742 pr_err("kstrtoull() failed for"743 " fd_dev_size=\n");744 goto out;745 }746 pr_debug("FILEIO: Referencing Size: %llu"747 " bytes\n", fd_dev->fd_dev_size);748 fd_dev->fbd_flags |= FBDF_HAS_SIZE;749 break;750 case Opt_fd_buffered_io:751 ret = match_int(args, &arg);752 if (ret)753 goto out;754 if (arg != 1) {755 pr_err("bogus fd_buffered_io=%d value\n", arg);756 ret = -EINVAL;757 goto out;758 }759 760 pr_debug("FILEIO: Using buffered I/O"761 " operations for struct fd_dev\n");762 763 fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE;764 break;765 case Opt_fd_async_io:766 ret = match_int(args, &arg);767 if (ret)768 goto out;769 if (arg != 1) {770 pr_err("bogus fd_async_io=%d value\n", arg);771 ret = -EINVAL;772 goto out;773 }774 775 pr_debug("FILEIO: Using async I/O"776 " operations for struct fd_dev\n");777 778 fd_dev->fbd_flags |= FDBD_HAS_ASYNC_IO;779 break;780 default:781 break;782 }783 }784 785out:786 kfree(orig);787 return (!ret) ? count : ret;788}789 790static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b)791{792 struct fd_dev *fd_dev = FD_DEV(dev);793 ssize_t bl = 0;794 795 bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);796 bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s Async: %d\n",797 fd_dev->fd_dev_name, fd_dev->fd_dev_size,798 (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ?799 "Buffered-WCE" : "O_DSYNC",800 !!(fd_dev->fbd_flags & FDBD_HAS_ASYNC_IO));801 return bl;802}803 804static sector_t fd_get_blocks(struct se_device *dev)805{806 struct fd_dev *fd_dev = FD_DEV(dev);807 struct file *f = fd_dev->fd_file;808 struct inode *i = f->f_mapping->host;809 unsigned long long dev_size;810 /*811 * When using a file that references an underlying struct block_device,812 * ensure dev_size is always based on the current inode size in order813 * to handle underlying block_device resize operations.814 */815 if (S_ISBLK(i->i_mode))816 dev_size = i_size_read(i);817 else818 dev_size = fd_dev->fd_dev_size;819 820 return div_u64(dev_size - dev->dev_attrib.block_size,821 dev->dev_attrib.block_size);822}823 824static int fd_init_prot(struct se_device *dev)825{826 struct fd_dev *fd_dev = FD_DEV(dev);827 struct file *prot_file, *file = fd_dev->fd_file;828 struct inode *inode;829 int ret, flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;830 char buf[FD_MAX_DEV_PROT_NAME];831 832 if (!file) {833 pr_err("Unable to locate fd_dev->fd_file\n");834 return -ENODEV;835 }836 837 inode = file->f_mapping->host;838 if (S_ISBLK(inode->i_mode)) {839 pr_err("FILEIO Protection emulation only supported on"840 " !S_ISBLK\n");841 return -ENOSYS;842 }843 844 if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE)845 flags &= ~O_DSYNC;846 847 snprintf(buf, FD_MAX_DEV_PROT_NAME, "%s.protection",848 fd_dev->fd_dev_name);849 850 prot_file = filp_open(buf, flags, 0600);851 if (IS_ERR(prot_file)) {852 pr_err("filp_open(%s) failed\n", buf);853 ret = PTR_ERR(prot_file);854 return ret;855 }856 fd_dev->fd_prot_file = prot_file;857 858 return 0;859}860 861static int fd_format_prot(struct se_device *dev)862{863 unsigned char *buf;864 int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size;865 int ret;866 867 if (!dev->dev_attrib.pi_prot_type) {868 pr_err("Unable to format_prot while pi_prot_type == 0\n");869 return -ENODEV;870 }871 872 buf = vzalloc(unit_size);873 if (!buf) {874 pr_err("Unable to allocate FILEIO prot buf\n");875 return -ENOMEM;876 }877 878 pr_debug("Using FILEIO prot_length: %llu\n",879 (unsigned long long)(dev->transport->get_blocks(dev) + 1) *880 dev->prot_length);881 882 ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1,883 buf, unit_size);884 vfree(buf);885 return ret;886}887 888static void fd_free_prot(struct se_device *dev)889{890 struct fd_dev *fd_dev = FD_DEV(dev);891 892 if (!fd_dev->fd_prot_file)893 return;894 895 filp_close(fd_dev->fd_prot_file, NULL);896 fd_dev->fd_prot_file = NULL;897}898 899static struct exec_cmd_ops fd_exec_cmd_ops = {900 .execute_rw = fd_execute_rw,901 .execute_sync_cache = fd_execute_sync_cache,902 .execute_write_same = fd_execute_write_same,903 .execute_unmap = fd_execute_unmap,904};905 906static sense_reason_t907fd_parse_cdb(struct se_cmd *cmd)908{909 return sbc_parse_cdb(cmd, &fd_exec_cmd_ops);910}911 912static const struct target_backend_ops fileio_ops = {913 .name = "fileio",914 .inquiry_prod = "FILEIO",915 .inquiry_rev = FD_VERSION,916 .owner = THIS_MODULE,917 .attach_hba = fd_attach_hba,918 .detach_hba = fd_detach_hba,919 .alloc_device = fd_alloc_device,920 .configure_device = fd_configure_device,921 .destroy_device = fd_destroy_device,922 .free_device = fd_free_device,923 .configure_unmap = fd_configure_unmap,924 .parse_cdb = fd_parse_cdb,925 .set_configfs_dev_params = fd_set_configfs_dev_params,926 .show_configfs_dev_params = fd_show_configfs_dev_params,927 .get_device_type = sbc_get_device_type,928 .get_blocks = fd_get_blocks,929 .init_prot = fd_init_prot,930 .format_prot = fd_format_prot,931 .free_prot = fd_free_prot,932 .tb_dev_attrib_attrs = sbc_attrib_attrs,933};934 935static int __init fileio_module_init(void)936{937 return transport_backend_register(&fileio_ops);938}939 940static void __exit fileio_module_exit(void)941{942 target_backend_unregister(&fileio_ops);943}944 945MODULE_DESCRIPTION("TCM FILEIO subsystem plugin");946MODULE_AUTHOR("nab@Linux-iSCSI.org");947MODULE_LICENSE("GPL");948 949module_init(fileio_module_init);950module_exit(fileio_module_exit);951