mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-19 22:42:38 +00:00
Merge branch 'svn-trunk'
This commit is contained in:
@@ -10,7 +10,7 @@ SCST user space device handler interface description
|
||||
<name>Vladislav Bolkhovitin</name>
|
||||
</author>
|
||||
|
||||
<date>Version 3.5.0</date>
|
||||
<date>Version 3.6.0-pre</date>
|
||||
|
||||
<toc>
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
#define NEW_LIBFC_API
|
||||
#endif
|
||||
|
||||
#define FT_VERSION "3.5.0"
|
||||
#define FT_VERSION "3.6.0-pre"
|
||||
#define FT_MODULE "fcst"
|
||||
|
||||
#define FT_MAX_HW_PENDING_TIME 20 /* max I/O time in seconds */
|
||||
|
||||
@@ -14,10 +14,16 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <scsi/libfc.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
#include <scsi/fc_encode.h>
|
||||
#else
|
||||
#include <scsi/fc/fc_ms.h>
|
||||
#endif
|
||||
#include "fcst.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,10 +19,16 @@
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <scsi/libfc.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
#include <scsi/fc_encode.h>
|
||||
#else
|
||||
#include <scsi/fc/fc_ms.h>
|
||||
#endif
|
||||
#include "fcst.h"
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
iSCSI SCST target driver
|
||||
========================
|
||||
|
||||
Version 3.5.0, 21 December 2020
|
||||
Version 3.6.0-pre, 02 January 2021
|
||||
----------------------------
|
||||
|
||||
ISCSI-SCST is a deeply reworked fork of iSCSI Enterprise Target (IET)
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
|
||||
#define ISCSI_VERSION_STRING_SUFFIX
|
||||
|
||||
#define ISCSI_VERSION_STRING "3.5.0" ISCSI_VERSION_STRING_SUFFIX
|
||||
#define ISCSI_VERSION_STRING "3.6.0-pre" ISCSI_VERSION_STRING_SUFFIX
|
||||
|
||||
@@ -515,8 +515,8 @@ out:
|
||||
MODULE_AUTHOR("Yan Burman");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(SCST);
|
||||
#define DRV_VERSION "3.5.0" "#" __stringify(OFED_FLAVOR)
|
||||
#define DRV_RELDATE "21 December 2020"
|
||||
#define DRV_VERSION "3.6.0-pre" "#" __stringify(OFED_FLAVOR)
|
||||
#define DRV_RELDATE "02 January 2021"
|
||||
MODULE_DESCRIPTION("iSER target transport driver "
|
||||
"v" DRV_VERSION " (" DRV_RELDATE ")");
|
||||
module_init(isert_init_module);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
/* Driver version number */
|
||||
#define Q2T_VERSION(a, b, c, d) (((a) << 030) + ((b) << 020) + (c) << 010 + (d))
|
||||
#define Q2T_VERSION_CODE Q2T_VERSION(3, 5, 0, 0)
|
||||
#define Q2T_VERSION_CODE Q2T_VERSION(3, 6, 0, 0)
|
||||
#define Q2T_VERSION_STRING "3.5.0"
|
||||
|
||||
#define SQA_DEFAULT_TAGS 2048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Target driver for QLogic 2[2-6]xx/8[1-3]xx Fibre Channel cards
|
||||
==============================================================
|
||||
|
||||
Version 3.5.0, 21 December 2020
|
||||
Version 3.6.0-pre, 02 January 2021
|
||||
----------------------------
|
||||
|
||||
This is target driver for QLogic 2[2-6]xx/8[1-3]xx Fibre Channel cards.
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
|
||||
/* Version numbers, the same as for the kernel */
|
||||
#define Q2T_VERSION(a, b, c, d) (((a) << 030) + ((b) << 020) + (c) << 010 + (d))
|
||||
#define Q2T_VERSION_CODE Q2T_VERSION(3, 5, 0, 0)
|
||||
#define Q2T_VERSION_STRING "3.5.0"
|
||||
#define Q2T_VERSION_CODE Q2T_VERSION(3, 6, 0, 0)
|
||||
#define Q2T_VERSION_STRING "3.6.0-pre"
|
||||
#define Q2T_PROC_VERSION_NAME "version"
|
||||
|
||||
#define Q2T_MAX_CDB_LEN 16
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
Generic SCSI target mid-level for Linux (SCST)
|
||||
==============================================
|
||||
|
||||
Version 3.5.0, 21 December 2020
|
||||
Version 3.6.0-pre, 02 January 2021
|
||||
----------------------------
|
||||
|
||||
SCST is designed to provide unified, consistent interface between SCSI
|
||||
|
||||
@@ -161,6 +161,29 @@ static inline int bdev_io_opt(struct block_device *bdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See also commit d4d77629953e ("block: clean up blkdev_get() wrappers and
|
||||
* their users") # v2.6.38.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
|
||||
static inline struct block_device *
|
||||
blkdev_get_by_path(const char *path, fmode_t mode, void *holder)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
int err;
|
||||
|
||||
bdev = lookup_bdev(path);
|
||||
if (IS_ERR(bdev))
|
||||
return bdev;
|
||||
|
||||
err = blkdev_get(bdev, mode);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
return bdev;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* <linux/bsg-lib.h> */
|
||||
|
||||
/*
|
||||
@@ -1206,12 +1229,14 @@ static inline int pcie_capability_read_dword(struct pci_dev *dev, int pos,
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)
|
||||
#if !defined(RHEL_MAJOR) || RHEL_MAJOR -0 < 8
|
||||
/*
|
||||
* See also commit 09ed79d6d75f ("percpu_ref: introduce PERCPU_REF_ALLOW_REINIT
|
||||
* flag") # v5.3.
|
||||
*/
|
||||
#define PERCPU_REF_ALLOW_REINIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
#define PERCPU_COUNT_BIAS (1U << 31)
|
||||
|
||||
+5
-2
@@ -2081,7 +2081,7 @@ struct scst_cmd {
|
||||
|
||||
struct scst_session *sess; /* corresponding session */
|
||||
|
||||
atomic_t *cpu_cmd_counter;
|
||||
bool counted;
|
||||
|
||||
atomic_t cmd_ref;
|
||||
|
||||
@@ -2571,7 +2571,7 @@ struct scst_mgmt_cmd {
|
||||
|
||||
struct scst_session *sess;
|
||||
|
||||
atomic_t *cpu_cmd_counter;
|
||||
bool counted;
|
||||
|
||||
/* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
|
||||
int state;
|
||||
@@ -5543,6 +5543,9 @@ struct scst_data_descriptor {
|
||||
uint64_t sdd_blocks;
|
||||
};
|
||||
|
||||
loff_t scst_file_size(const char *path, umode_t *mode);
|
||||
loff_t scst_bdev_size(const char *path);
|
||||
loff_t scst_file_or_bdev_size(const char *path);
|
||||
ssize_t scst_readv(struct file *file, const struct kvec *vec,
|
||||
unsigned long vlen, loff_t *pos);
|
||||
ssize_t scst_writev(struct file *file, const struct kvec *vec,
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#define SCST_VERSION(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + d)
|
||||
#define SCST_VERSION_CODE SCST_VERSION(3, 4, 0, 0)
|
||||
#define SCST_VERSION_STRING_SUFFIX
|
||||
#define SCST_VERSION_NAME "3.5.0"
|
||||
#define SCST_VERSION_NAME "3.6.0-pre"
|
||||
#define SCST_VERSION_STRING SCST_VERSION_NAME SCST_VERSION_STRING_SUFFIX
|
||||
|
||||
#define SCST_CONST_VERSION SCST_CONST_INTF_VER
|
||||
|
||||
+139
-173
@@ -6,7 +6,7 @@
|
||||
* Copyright (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
|
||||
* Copyright (C) 2007 Ross Walker <rswwalker at hotmail dot com>
|
||||
* Copyright (C) 2007 - 2018 Western Digital Corporation
|
||||
* Copyright (C) 2008 - 2018 Bart Van Assche <bvanassche@acm.org>
|
||||
* Copyright (C) 2008 - 2020 Bart Van Assche <bvanassche@acm.org>
|
||||
*
|
||||
* SCSI disk (type 0) and CDROM (type 5) dev handler using files
|
||||
* on file systems or block devices (VDISK)
|
||||
@@ -76,7 +76,7 @@
|
||||
#define SCST_FIO_VENDOR "SCST_FIO"
|
||||
#define SCST_BIO_VENDOR "SCST_BIO"
|
||||
/* 4 byte ASCII Product Revision Level - left aligned */
|
||||
#define SCST_FIO_REV "350 "
|
||||
#define SCST_FIO_REV "360 "
|
||||
|
||||
#define MAX_USN_LEN (20+1) /* For '\0' */
|
||||
#define MAX_INQ_VEND_SPECIFIC_LEN (INQ_BUF_SZ - 96)
|
||||
@@ -191,6 +191,7 @@ struct scst_vdisk_dev {
|
||||
struct file *fd;
|
||||
struct file *dif_fd;
|
||||
struct block_device *bdev;
|
||||
fmode_t bdev_mode;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
struct bio_set *vdisk_bioset;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
|
||||
@@ -514,41 +515,34 @@ out:
|
||||
|
||||
static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct file *fd;
|
||||
struct block_device *bdev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache || virt_dev->wt_flag || !virt_dev->dev_active)
|
||||
if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache ||
|
||||
virt_dev->wt_flag || !virt_dev->dev_active)
|
||||
goto out;
|
||||
|
||||
fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
|
||||
if (IS_ERR(fd)) {
|
||||
if ((PTR_ERR(fd) == -EMEDIUMTYPE) && virt_dev->blockio)
|
||||
bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ,
|
||||
(void *)__func__);
|
||||
if (IS_ERR(bdev)) {
|
||||
if (PTR_ERR(bdev) == -EMEDIUMTYPE)
|
||||
TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, "
|
||||
"DRBD passive?", virt_dev->filename);
|
||||
else
|
||||
PRINT_ERROR("filp_open(%s) failed: %ld",
|
||||
virt_dev->filename, PTR_ERR(fd));
|
||||
PRINT_ERROR("blkdev_get_by_path(%s) failed: %ld",
|
||||
virt_dev->filename, PTR_ERR(bdev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = file_inode(fd);
|
||||
|
||||
if (!S_ISBLK(inode->i_mode)) {
|
||||
PRINT_ERROR("%s is NOT a block device", virt_dev->filename);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (vdisk_blockio_flush(inode->i_bdev, GFP_KERNEL, false, NULL, false) != 0) {
|
||||
if (vdisk_blockio_flush(bdev, GFP_KERNEL, false, NULL, false) != 0) {
|
||||
PRINT_WARNING("Device %s doesn't support barriers, switching "
|
||||
"to NV_CACHE mode. Read README for more details.",
|
||||
virt_dev->filename);
|
||||
virt_dev->nv_cache = 1;
|
||||
}
|
||||
|
||||
out_close:
|
||||
filp_close(fd, NULL);
|
||||
blkdev_put(bdev, FMODE_READ);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
@@ -557,39 +551,44 @@ out:
|
||||
|
||||
static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
struct block_device *bdev = NULL;
|
||||
struct file *fd = NULL;
|
||||
bool fd_open = false;
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
virt_dev->dev_thin_provisioned = 0;
|
||||
|
||||
if (virt_dev->rd_only || (virt_dev->filename == NULL) || !virt_dev->dev_active)
|
||||
if (virt_dev->rd_only || !virt_dev->filename || !virt_dev->dev_active)
|
||||
goto check;
|
||||
|
||||
fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
|
||||
if (IS_ERR(fd)) {
|
||||
if ((PTR_ERR(fd) == -EMEDIUMTYPE) && virt_dev->blockio)
|
||||
TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, "
|
||||
"DRBD passive?", virt_dev->filename);
|
||||
if (virt_dev->blockio) {
|
||||
bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ,
|
||||
(void *)__func__);
|
||||
res = IS_ERR(bdev) ? PTR_ERR(bdev) : 0;
|
||||
} else {
|
||||
fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
|
||||
res = IS_ERR(fd) ? PTR_ERR(fd) : 0;
|
||||
}
|
||||
if (res) {
|
||||
if (res == -EMEDIUMTYPE && virt_dev->blockio)
|
||||
TRACE(TRACE_MINOR,
|
||||
"Unable to open %s with EMEDIUMTYPE, DRBD passive?",
|
||||
virt_dev->filename);
|
||||
else
|
||||
PRINT_ERROR("filp_open(%s) failed: %ld",
|
||||
virt_dev->filename, PTR_ERR(fd));
|
||||
PRINT_ERROR("opening %s failed: %d",
|
||||
virt_dev->filename, res);
|
||||
goto check;
|
||||
}
|
||||
|
||||
fd_open = true;
|
||||
|
||||
if (virt_dev->blockio) {
|
||||
struct inode *inode = file_inode(fd);
|
||||
|
||||
if (!S_ISBLK(inode->i_mode)) {
|
||||
PRINT_ERROR("%s is NOT a block device",
|
||||
virt_dev->filename);
|
||||
goto check;
|
||||
}
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) || (defined(RHEL_MAJOR) && RHEL_MAJOR -0 >= 6)
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) || \
|
||||
(defined(RHEL_MAJOR) && RHEL_MAJOR -0 >= 6)
|
||||
virt_dev->dev_thin_provisioned =
|
||||
blk_queue_discard(bdev_get_queue(inode->i_bdev));
|
||||
blk_queue_discard(bdev_get_queue(bdev));
|
||||
#endif
|
||||
} else {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
|
||||
@@ -633,7 +632,7 @@ check:
|
||||
struct request_queue *q;
|
||||
|
||||
sBUG_ON(!fd_open);
|
||||
q = bdev_get_queue(file_inode(fd)->i_bdev);
|
||||
q = bdev_get_queue(bdev);
|
||||
virt_dev->unmap_opt_gran = q->limits.discard_granularity >> block_shift;
|
||||
virt_dev->unmap_align = q->limits.discard_alignment >> block_shift;
|
||||
if (virt_dev->unmap_opt_gran == virt_dev->unmap_align)
|
||||
@@ -666,8 +665,12 @@ check:
|
||||
virt_dev->discard_zeroes_data);
|
||||
}
|
||||
|
||||
if (fd_open)
|
||||
filp_close(fd, NULL);
|
||||
if (fd_open) {
|
||||
if (virt_dev->blockio)
|
||||
blkdev_put(bdev, FMODE_READ);
|
||||
else
|
||||
filp_close(fd, NULL);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -677,56 +680,31 @@ check:
|
||||
static int vdisk_get_file_size(const struct scst_vdisk_dev *virt_dev,
|
||||
loff_t *file_size)
|
||||
{
|
||||
struct inode *inode;
|
||||
int res = 0;
|
||||
struct file *fd;
|
||||
loff_t res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
sBUG_ON(!virt_dev->filename);
|
||||
|
||||
if (!virt_dev->dev_active) {
|
||||
TRACE_DBG("Not active dev %s, skip reexaming", virt_dev->dev->virt_name);
|
||||
TRACE_DBG("Not active dev %s, skip reexaming",
|
||||
virt_dev->dev->virt_name);
|
||||
res = -EMEDIUMTYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*file_size = 0;
|
||||
|
||||
fd = filp_open(virt_dev->filename, O_LARGEFILE | O_RDONLY, 0600);
|
||||
if (IS_ERR(fd)) {
|
||||
res = PTR_ERR(fd);
|
||||
if ((res == -EMEDIUMTYPE) && virt_dev->blockio)
|
||||
TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, "
|
||||
"DRBD passive?", virt_dev->filename);
|
||||
else
|
||||
PRINT_ERROR("filp_open(%s) failed: %d", virt_dev->filename, res);
|
||||
res = scst_file_or_bdev_size(virt_dev->filename);
|
||||
if (res == -EMEDIUMTYPE && virt_dev->blockio) {
|
||||
TRACE(TRACE_MINOR,
|
||||
"Unable to open %s with EMEDIUMTYPE, DRBD passive?",
|
||||
virt_dev->filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = file_inode(fd);
|
||||
|
||||
if (virt_dev->blockio && !S_ISBLK(inode->i_mode)) {
|
||||
PRINT_ERROR("File %s is NOT a block device", virt_dev->filename);
|
||||
res = -EINVAL;
|
||||
goto out_close;
|
||||
if (res < 0) {
|
||||
PRINT_ERROR("opening %s failed: %lld", virt_dev->filename, res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
/* Nothing to do */
|
||||
} else if (S_ISBLK(inode->i_mode)) {
|
||||
inode = inode->i_bdev->bd_inode;
|
||||
} else {
|
||||
PRINT_ERROR("File %s unsupported mode: mode=0%o\n",
|
||||
virt_dev->filename, inode->i_mode);
|
||||
res = -EINVAL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
*file_size = inode->i_size;
|
||||
|
||||
out_close:
|
||||
filp_close(fd, NULL);
|
||||
*file_size = res;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -1006,28 +984,20 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
int res;
|
||||
struct scst_device *dev = virt_dev->dev;
|
||||
struct inode *inode;
|
||||
struct file *fd;
|
||||
struct block_device *bdev;
|
||||
struct blk_integrity *bi;
|
||||
const char *bi_profile_name;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
fd = vdev_open_fd(virt_dev, virt_dev->filename, virt_dev->rd_only);
|
||||
if (IS_ERR(fd)) {
|
||||
res = -EINVAL;
|
||||
bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ,
|
||||
(void *)__func__);
|
||||
if (IS_ERR(bdev)) {
|
||||
res = PTR_ERR(bdev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = file_inode(fd);
|
||||
|
||||
if (!S_ISBLK(inode->i_mode)) {
|
||||
PRINT_ERROR("%s is NOT a block device!", virt_dev->filename);
|
||||
res = -EINVAL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
bi = bdev_get_integrity(inode->i_bdev);
|
||||
bi = bdev_get_integrity(bdev);
|
||||
if (bi == NULL) {
|
||||
TRACE_DBG("Block integrity not supported");
|
||||
goto out_no_bi;
|
||||
@@ -1099,7 +1069,7 @@ out_no_bi:
|
||||
res = 0;
|
||||
|
||||
out_close:
|
||||
filp_close(fd, NULL);
|
||||
blkdev_put(bdev, FMODE_READ);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -1352,21 +1322,35 @@ static void vdisk_detach(struct scst_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
static bool vdisk_is_open(const struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
return virt_dev->fd || virt_dev->bdev;
|
||||
}
|
||||
|
||||
static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
|
||||
{
|
||||
int res;
|
||||
|
||||
sBUG_ON(!virt_dev->filename);
|
||||
sBUG_ON(virt_dev->fd);
|
||||
sBUG_ON(vdisk_is_open(virt_dev));
|
||||
|
||||
virt_dev->fd = vdev_open_fd(virt_dev, virt_dev->filename, read_only);
|
||||
if (IS_ERR(virt_dev->fd)) {
|
||||
res = PTR_ERR(virt_dev->fd);
|
||||
if (virt_dev->blockio) {
|
||||
virt_dev->bdev_mode = FMODE_READ;
|
||||
if (!read_only)
|
||||
virt_dev->bdev_mode |= FMODE_WRITE;
|
||||
virt_dev->bdev = blkdev_get_by_path(virt_dev->filename,
|
||||
virt_dev->bdev_mode, (void *)__func__);
|
||||
res = IS_ERR(virt_dev->bdev) ? PTR_ERR(virt_dev->bdev) : 0;
|
||||
} else {
|
||||
virt_dev->fd = vdev_open_fd(virt_dev, virt_dev->filename,
|
||||
read_only);
|
||||
res = IS_ERR(virt_dev->fd) ? PTR_ERR(virt_dev->fd) : 0;
|
||||
}
|
||||
if (res) {
|
||||
virt_dev->bdev = NULL;
|
||||
virt_dev->fd = NULL;
|
||||
goto out;
|
||||
}
|
||||
virt_dev->bdev = virt_dev->blockio ? file_inode(virt_dev->fd)->i_bdev : NULL;
|
||||
res = 0;
|
||||
|
||||
/*
|
||||
* For block devices, get the optimal I/O size from the block device
|
||||
@@ -1386,27 +1370,34 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_DBG("virt_dev %s: fd %p open (dif_fd %p)", virt_dev->name,
|
||||
virt_dev->fd, virt_dev->dif_fd);
|
||||
TRACE_DBG("virt_dev %s: fd %p %p open (dif_fd %p)", virt_dev->name,
|
||||
virt_dev->fd, virt_dev->bdev, virt_dev->dif_fd);
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
out_close_fd:
|
||||
filp_close(virt_dev->fd, NULL);
|
||||
virt_dev->fd = NULL;
|
||||
if (virt_dev->blockio) {
|
||||
blkdev_put(virt_dev->bdev, virt_dev->bdev_mode);
|
||||
virt_dev->bdev = NULL;
|
||||
} else {
|
||||
filp_close(virt_dev->fd, NULL);
|
||||
virt_dev->fd = NULL;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void vdisk_close_fd(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
TRACE_DBG("virt_dev %s: closing fd %p (dif_fd %p)", virt_dev->name,
|
||||
virt_dev->fd, virt_dev->dif_fd);
|
||||
TRACE_DBG("virt_dev %s: closing fd %p %p (dif_fd %p)", virt_dev->name,
|
||||
virt_dev->fd, virt_dev->bdev, virt_dev->dif_fd);
|
||||
|
||||
if (virt_dev->fd) {
|
||||
if (virt_dev->bdev) {
|
||||
blkdev_put(virt_dev->bdev, virt_dev->bdev_mode);
|
||||
virt_dev->bdev = NULL;
|
||||
} else if (virt_dev->fd) {
|
||||
filp_close(virt_dev->fd, NULL);
|
||||
virt_dev->fd = NULL;
|
||||
virt_dev->bdev = NULL;
|
||||
}
|
||||
if (virt_dev->dif_fd) {
|
||||
filp_close(virt_dev->dif_fd, NULL);
|
||||
@@ -1414,6 +1405,16 @@ static void vdisk_close_fd(struct scst_vdisk_dev *virt_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static int vdisk_reopen_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
|
||||
{
|
||||
/*
|
||||
* To do: make this function transactional. That means that it either
|
||||
* succeeds or does not modify the state of @virt_dev.
|
||||
*/
|
||||
vdisk_close_fd(virt_dev);
|
||||
return vdisk_open_fd(virt_dev, read_only);
|
||||
}
|
||||
|
||||
/* Invoked with scst_mutex held, so no further locking is necessary here. */
|
||||
static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
@@ -1426,7 +1427,7 @@ static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
virt_dev->tgt_dev_cnt++;
|
||||
|
||||
if (virt_dev->fd != NULL)
|
||||
if (vdisk_is_open(virt_dev))
|
||||
goto out;
|
||||
|
||||
if (!virt_dev->nullio && !virt_dev->cdrom_empty) {
|
||||
@@ -1442,6 +1443,7 @@ static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
|
||||
}
|
||||
} else {
|
||||
virt_dev->fd = NULL;
|
||||
virt_dev->bdev = NULL;
|
||||
virt_dev->dif_fd = NULL;
|
||||
}
|
||||
|
||||
@@ -1831,7 +1833,6 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
|
||||
#else
|
||||
int res;
|
||||
#endif
|
||||
struct file *fd = virt_dev->fd;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -1852,24 +1853,25 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
|
||||
(unsigned long long)start_lba, blocks);
|
||||
|
||||
if (virt_dev->blockio) {
|
||||
struct block_device *bdev = virt_dev->bdev;
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)
|
||||
sector_t start_sector = start_lba << (cmd->dev->block_shift - 9);
|
||||
sector_t nr_sects = blocks << (cmd->dev->block_shift - 9);
|
||||
struct inode *inode = file_inode(fd);
|
||||
gfp_t gfp = cmd->cmd_gfp_mask;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)
|
||||
err = blkdev_issue_discard(inode->i_bdev, start_sector, nr_sects, gfp);
|
||||
err = blkdev_issue_discard(bdev, start_sector, nr_sects, gfp);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) \
|
||||
&& !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 34) \
|
||||
&& defined(CONFIG_SUSE_KERNEL))
|
||||
err = blkdev_issue_discard(inode->i_bdev, start_sector, nr_sects,
|
||||
gfp, DISCARD_FL_WAIT);
|
||||
err = blkdev_issue_discard(bdev, start_sector, nr_sects, gfp,
|
||||
DISCARD_FL_WAIT);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
|
||||
err = blkdev_issue_discard(inode->i_bdev, start_sector, nr_sects,
|
||||
gfp, BLKDEV_IFL_WAIT);
|
||||
err = blkdev_issue_discard(bdev, start_sector, nr_sects, gfp,
|
||||
BLKDEV_IFL_WAIT);
|
||||
#else
|
||||
err = blkdev_issue_discard(inode->i_bdev, start_sector, nr_sects, gfp, 0);
|
||||
err = blkdev_issue_discard(bdev, start_sector, nr_sects, gfp,
|
||||
0);
|
||||
#endif
|
||||
if (unlikely(err != 0)) {
|
||||
PRINT_ERROR("blkdev_issue_discard() for "
|
||||
@@ -1888,6 +1890,7 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
|
||||
} else {
|
||||
loff_t off = start_lba << cmd->dev->block_shift;
|
||||
loff_t len = blocks << cmd->dev->block_shift;
|
||||
struct file *fd = virt_dev->fd;
|
||||
|
||||
res = vdisk_unmap_file_range(cmd, virt_dev, off, len, fd);
|
||||
if (unlikely(res != 0))
|
||||
@@ -3410,7 +3413,7 @@ static enum scst_exec_res blockio_exec(struct scst_cmd *cmd)
|
||||
if (unlikely(!vdisk_parse_offset(&p, cmd)))
|
||||
goto err;
|
||||
|
||||
if (unlikely(virt_dev->fd == NULL)) {
|
||||
if (unlikely(virt_dev->bdev == NULL)) {
|
||||
if (!vdisk_no_fd_allowed_commands(cmd)) {
|
||||
/*
|
||||
* We should not get here, unless the user space
|
||||
@@ -4538,7 +4541,6 @@ out_not_sup:
|
||||
static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt, bool read_only)
|
||||
{
|
||||
int res = 0;
|
||||
struct file *fd, *dif_fd = NULL;
|
||||
bool old_wt = virt_dev->wt_flag;
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -4550,42 +4552,20 @@ static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt, bool read_only)
|
||||
virt_dev->wt_flag = wt;
|
||||
spin_unlock(&virt_dev->flags_lock);
|
||||
|
||||
if (virt_dev->fd == NULL)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* MODE SELECT is strictly serialized command, so it's safe here
|
||||
* to reopen fd.
|
||||
* MODE SELECT is a strictly serialized command so it's safe to reopen
|
||||
* the fd.
|
||||
*/
|
||||
|
||||
fd = vdev_open_fd(virt_dev, virt_dev->filename, read_only);
|
||||
if (IS_ERR(fd)) {
|
||||
res = PTR_ERR(fd);
|
||||
goto out_err;
|
||||
if (vdisk_is_open(virt_dev)) {
|
||||
res = vdisk_reopen_fd(virt_dev, read_only);
|
||||
if (res < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (virt_dev->dif_filename != NULL) {
|
||||
dif_fd = vdev_open_fd(virt_dev, virt_dev->dif_filename, read_only);
|
||||
if (IS_ERR(dif_fd)) {
|
||||
res = PTR_ERR(dif_fd);
|
||||
goto out_err_close_fd;
|
||||
}
|
||||
}
|
||||
|
||||
filp_close(virt_dev->fd, NULL);
|
||||
if (virt_dev->dif_fd)
|
||||
filp_close(virt_dev->dif_fd, NULL);
|
||||
|
||||
virt_dev->fd = fd;
|
||||
virt_dev->dif_fd = dif_fd;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_err_close_fd:
|
||||
filp_close(fd, NULL);
|
||||
|
||||
out_err:
|
||||
spin_lock(&virt_dev->flags_lock);
|
||||
virt_dev->wt_flag = old_wt;
|
||||
@@ -7660,24 +7640,20 @@ out:
|
||||
}
|
||||
|
||||
|
||||
static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
char *buffer)
|
||||
static int vcdrom_change(struct scst_vdisk_dev *virt_dev, char *buffer)
|
||||
{
|
||||
loff_t err;
|
||||
char *old_fn, *p, *pp;
|
||||
char *old_fn, *p;
|
||||
bool old_empty;
|
||||
struct file *old_fd;
|
||||
struct file *old_dif_fd;
|
||||
const char *filename = NULL;
|
||||
int length = strlen(buffer);
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("virt_dev %s, empty %d, fd %p (dif_fd %p), filename %p", virt_dev->name,
|
||||
virt_dev->cdrom_empty, virt_dev->fd, virt_dev->dif_fd, virt_dev->filename);
|
||||
|
||||
sBUG_ON(virt_dev->dif_fd); /* DIF is not supported for CDROMs */
|
||||
TRACE_DBG("virt_dev %s, empty %d, fd %p (dif_fd %p), filename %p",
|
||||
virt_dev->name, virt_dev->cdrom_empty, virt_dev->fd,
|
||||
virt_dev->dif_fd, virt_dev->filename);
|
||||
|
||||
if (virt_dev->prevent_allow_medium_removal) {
|
||||
PRINT_ERROR("Prevent medium removal for "
|
||||
@@ -7688,16 +7664,16 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
|
||||
p = buffer;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
filename = p;
|
||||
/* Strip trailing whitespace */
|
||||
WARN_ON_ONCE(length == 0);
|
||||
p = &buffer[length-1];
|
||||
pp = &buffer[length];
|
||||
while (isspace(*p) && (*p != '\0')) {
|
||||
pp = p;
|
||||
while (p > buffer && isspace(*p))
|
||||
p--;
|
||||
}
|
||||
*pp = '\0';
|
||||
p[1] = '\0';
|
||||
|
||||
res = scst_suspend_activity(SCST_SUSPEND_TIMEOUT_USER);
|
||||
if (res != 0)
|
||||
@@ -7707,8 +7683,6 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
old_empty = virt_dev->cdrom_empty;
|
||||
old_fd = virt_dev->fd;
|
||||
old_dif_fd = virt_dev->dif_fd;
|
||||
old_fn = virt_dev->filename;
|
||||
|
||||
if (*filename == '\0') {
|
||||
@@ -7735,24 +7709,17 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
res = vdisk_get_file_size(virt_dev, &err);
|
||||
if (res != 0)
|
||||
goto out_free_fn;
|
||||
if (virt_dev->fd == NULL) {
|
||||
res = vdisk_open_fd(virt_dev, true);
|
||||
if (!vdisk_is_open(virt_dev)) {
|
||||
res = vdisk_reopen_fd(virt_dev, true);
|
||||
if (res != 0)
|
||||
goto out_free_fn;
|
||||
sBUG_ON(!virt_dev->fd);
|
||||
|
||||
TRACE_DBG("Closing old_fd %p", old_fd);
|
||||
if (old_fd != NULL)
|
||||
filp_close(old_fd, NULL);
|
||||
if (old_dif_fd != NULL)
|
||||
filp_close(old_dif_fd, NULL);
|
||||
old_fd = NULL;
|
||||
old_dif_fd = NULL;
|
||||
}
|
||||
} else {
|
||||
err = 0;
|
||||
virt_dev->filename = NULL;
|
||||
virt_dev->fd = NULL;
|
||||
virt_dev->bdev = NULL;
|
||||
}
|
||||
|
||||
virt_dev->file_size = err;
|
||||
@@ -7790,7 +7757,6 @@ out:
|
||||
return res;
|
||||
|
||||
out_free_fn:
|
||||
virt_dev->fd = old_fd;
|
||||
kfree(virt_dev->filename);
|
||||
virt_dev->filename = old_fn;
|
||||
|
||||
@@ -7910,7 +7876,7 @@ static int vdev_size_process_store(struct scst_sysfs_work_item *work)
|
||||
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
queue_ua = (virt_dev->fd != NULL);
|
||||
queue_ua = vdisk_is_open(virt_dev);
|
||||
|
||||
if ((new_size & ((1 << virt_dev->blk_shift) - 1)) == 0) {
|
||||
virt_dev->file_size = new_size;
|
||||
|
||||
+80
-39
@@ -16,6 +16,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/aio.h> /* struct kiocb for kernel v4.0 */
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -31,7 +32,9 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
|
||||
#include <asm/kmap_types.h>
|
||||
#endif
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/checksum.h>
|
||||
#ifndef INSIDE_KERNEL_TREE
|
||||
@@ -5821,7 +5824,7 @@ struct scst_cmd *__scst_create_prepare_internal_cmd(const uint8_t *cdb,
|
||||
}
|
||||
|
||||
scst_sess_get(res->sess);
|
||||
res->cpu_cmd_counter = scst_get();
|
||||
scst_get_icmd(res);
|
||||
|
||||
TRACE(TRACE_SCSI, "New internal cmd %p (op %s)", res,
|
||||
scst_get_opcode_name(res));
|
||||
@@ -6012,6 +6015,66 @@ ssize_t kernel_write(struct file *file, const void *buf, size_t count,
|
||||
EXPORT_SYMBOL(kernel_write);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* scst_file_size - returns the size of a regular file
|
||||
* @path: Path of the file.
|
||||
* @mode: If not NULL, the file mode will be stored in *@mode.
|
||||
*
|
||||
* Returns the file size or an error code.
|
||||
*/
|
||||
loff_t scst_file_size(const char *path, umode_t *mode)
|
||||
{
|
||||
struct file *filp;
|
||||
struct inode *inode;
|
||||
loff_t res;
|
||||
|
||||
filp = filp_open(path, O_LARGEFILE | O_RDONLY, 0600);
|
||||
if (IS_ERR(filp))
|
||||
return PTR_ERR(filp);
|
||||
inode = file_inode(filp);
|
||||
if (mode)
|
||||
*mode = inode->i_mode;
|
||||
res = S_ISREG(inode->i_mode) ? i_size_read(file_inode(filp)) : -ENOTTY;
|
||||
filp_close(filp, NULL);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_file_size);
|
||||
|
||||
/**
|
||||
* scst_bdev_size - returns the size of a block device
|
||||
* @path: Path of the block device.
|
||||
*
|
||||
* Returns the block device size or an error code.
|
||||
*/
|
||||
loff_t scst_bdev_size(const char *path)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
loff_t res;
|
||||
|
||||
bdev = blkdev_get_by_path(path, FMODE_READ, (void *)__func__);
|
||||
if (IS_ERR(bdev))
|
||||
return PTR_ERR(bdev);
|
||||
res = i_size_read(bdev->bd_inode);
|
||||
blkdev_put(bdev, FMODE_READ);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_bdev_size);
|
||||
|
||||
loff_t scst_file_or_bdev_size(const char *path)
|
||||
{
|
||||
enum { INVALID_FILE_MODE = 0 };
|
||||
umode_t mode = INVALID_FILE_MODE;
|
||||
loff_t res;
|
||||
|
||||
res = scst_file_size(path, &mode);
|
||||
if (S_ISREG(mode))
|
||||
return res;
|
||||
if (mode != INVALID_FILE_MODE && !S_ISBLK(mode))
|
||||
return -EINVAL;
|
||||
return scst_bdev_size(path);
|
||||
}
|
||||
EXPORT_SYMBOL(scst_file_or_bdev_size);
|
||||
|
||||
/**
|
||||
* scst_readv - read data from a file into a kernel buffer
|
||||
* @file: File to read from.
|
||||
@@ -7471,10 +7534,8 @@ static void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
|
||||
scst_sess_put(cmd->sess);
|
||||
|
||||
if (likely(cmd->cpu_cmd_counter)) {
|
||||
scst_put(cmd->cpu_cmd_counter);
|
||||
cmd->cpu_cmd_counter = NULL;
|
||||
}
|
||||
if (likely(cmd->counted))
|
||||
scst_put_cmd(cmd);
|
||||
|
||||
EXTRACHECKS_BUG_ON(cmd->pre_alloced && cmd->internal);
|
||||
|
||||
@@ -7714,10 +7775,8 @@ void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
scst_sess_put(mcmd->sess);
|
||||
|
||||
if (mcmd->cpu_cmd_counter) {
|
||||
scst_put(mcmd->cpu_cmd_counter);
|
||||
mcmd->cpu_cmd_counter = NULL;
|
||||
}
|
||||
if (mcmd->counted)
|
||||
scst_put_mcmd(mcmd);
|
||||
|
||||
mempool_free(mcmd, scst_mgmt_mempool);
|
||||
|
||||
@@ -15130,7 +15189,6 @@ EXPORT_SYMBOL(scst_path_put);
|
||||
int scst_copy_file(const char *src, const char *dest)
|
||||
{
|
||||
int res = 0;
|
||||
struct inode *inode;
|
||||
loff_t file_size, pos;
|
||||
uint8_t *buf = NULL;
|
||||
struct file *file_src = NULL, *file_dest = NULL;
|
||||
@@ -15146,6 +15204,12 @@ int scst_copy_file(const char *src, const char *dest)
|
||||
|
||||
TRACE_DBG("Copying '%s' into '%s'", src, dest);
|
||||
|
||||
file_size = scst_file_or_bdev_size(src);
|
||||
if (file_size < 0) {
|
||||
res = file_size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file_src = filp_open(src, O_RDONLY, 0);
|
||||
if (IS_ERR(file_src)) {
|
||||
res = PTR_ERR(file_src);
|
||||
@@ -15161,20 +15225,6 @@ int scst_copy_file(const char *src, const char *dest)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
inode = file_inode(file_src);
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
/* Nothing to do */
|
||||
} else if (S_ISBLK(inode->i_mode)) {
|
||||
inode = inode->i_bdev->bd_inode;
|
||||
} else {
|
||||
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
|
||||
res = -EINVAL;
|
||||
goto out_skip;
|
||||
}
|
||||
|
||||
file_size = inode->i_size;
|
||||
|
||||
buf = vmalloc(file_size);
|
||||
if (buf == NULL) {
|
||||
res = -ENOMEM;
|
||||
@@ -15329,13 +15379,18 @@ static int __scst_read_file_transactional(const char *file_name,
|
||||
{
|
||||
int res;
|
||||
struct file *file = NULL;
|
||||
struct inode *inode;
|
||||
loff_t file_size, pos;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Loading file '%s'", file_name);
|
||||
|
||||
file_size = scst_file_or_bdev_size(file_name);
|
||||
if (file_size < 0) {
|
||||
res = file_size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = filp_open(file_name, O_RDONLY, 0);
|
||||
if (IS_ERR(file)) {
|
||||
res = PTR_ERR(file);
|
||||
@@ -15343,20 +15398,6 @@ static int __scst_read_file_transactional(const char *file_name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = file_inode(file);
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
/* Nothing to do */
|
||||
} else if (S_ISBLK(inode->i_mode)) {
|
||||
inode = inode->i_bdev->bd_inode;
|
||||
} else {
|
||||
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
|
||||
res = -EINVAL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
file_size = inode->i_size;
|
||||
|
||||
if (file_size > size) {
|
||||
PRINT_ERROR("Supplied buffer (%d) too small (need %d)", size,
|
||||
(int)file_size);
|
||||
|
||||
+59
-40
@@ -112,8 +112,6 @@ struct kmem_cache *scst_cmd_cachep;
|
||||
unsigned long scst_trace_flag;
|
||||
#endif
|
||||
|
||||
unsigned long scst_flags;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
|
||||
unsigned long scst_poll_ns = SCST_DEF_POLL_NS;
|
||||
#endif
|
||||
@@ -122,6 +120,9 @@ int scst_max_tasklet_cmd = SCST_DEF_MAX_TASKLET_CMD;
|
||||
|
||||
struct scst_cmd_threads scst_main_cmd_threads;
|
||||
|
||||
static bool percpu_ref_killed;
|
||||
struct percpu_ref scst_cmd_count;
|
||||
struct percpu_ref scst_mcmd_count;
|
||||
struct scst_percpu_info scst_percpu_infos[NR_CPUS];
|
||||
|
||||
spinlock_t scst_mcmd_lock;
|
||||
@@ -796,13 +797,15 @@ static void __printf(2, 3) scst_to_syslog(void *arg, const char *fmt, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Number of SCST non-management commands, management commands and activities
|
||||
* that are in progress. Must only be called if both scst_cmd_count and
|
||||
* scst_mcmd_count are in atomic mode.
|
||||
*/
|
||||
int scst_get_cmd_counter(void)
|
||||
{
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(scst_percpu_infos); i++)
|
||||
res += atomic_read(&scst_percpu_infos[i].cpu_cmd_count);
|
||||
return res;
|
||||
return percpu_ref_read(&scst_cmd_count) +
|
||||
percpu_ref_read(&scst_mcmd_count);
|
||||
}
|
||||
|
||||
static int scst_susp_wait(unsigned long timeout)
|
||||
@@ -820,7 +823,7 @@ static int scst_susp_wait(unsigned long timeout)
|
||||
t = min(timeout, SCST_SUSP_WAIT_REPORT_TIMEOUT);
|
||||
|
||||
res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ,
|
||||
(scst_get_cmd_counter() == 0), t);
|
||||
percpu_ref_killed, t);
|
||||
if (res > 0) {
|
||||
res = 0;
|
||||
goto out;
|
||||
@@ -836,13 +839,13 @@ static int scst_susp_wait(unsigned long timeout)
|
||||
|
||||
if (timeout != SCST_SUSPEND_TIMEOUT_UNLIMITED) {
|
||||
res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ,
|
||||
(scst_get_cmd_counter() == 0), timeout - t);
|
||||
percpu_ref_killed, timeout - t);
|
||||
if (res == 0)
|
||||
res = -EBUSY;
|
||||
else if (res > 0)
|
||||
res = 0;
|
||||
} else {
|
||||
wait_event(scst_dev_cmd_waitQ, scst_get_cmd_counter() == 0);
|
||||
wait_event(scst_dev_cmd_waitQ, percpu_ref_killed);
|
||||
res = 0;
|
||||
}
|
||||
|
||||
@@ -855,17 +858,18 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* scst_suspend_activity() - globally suspend any activity
|
||||
* scst_suspend_activity() - globally suspend activity
|
||||
*
|
||||
* Description:
|
||||
* Globally suspends any activity and doesn't return, until there are any
|
||||
* active commands (state after SCST_CMD_STATE_INIT). Timeout parameter sets
|
||||
* max time this function will wait for suspending or interrupted by a
|
||||
* signal with the corresponding error status < 0. If timeout is
|
||||
* SCST_SUSPEND_TIMEOUT_UNLIMITED, then it will wait virtually forever.
|
||||
* On success returns 0.
|
||||
* Globally suspends SCSI command and SCSI management command processing and
|
||||
* waits until all active commands have finished (state after
|
||||
* SCST_CMD_STATE_INIT). The timeout parameter defines the maximum time this
|
||||
* function will wait until activity has been suspended. If this function is
|
||||
* interrupted by a signal, it returns a negative value. If the timeout value
|
||||
* is SCST_SUSPEND_TIMEOUT_UNLIMITED, then it will wait virtually forever.
|
||||
* Returns 0 upon success.
|
||||
*
|
||||
* New arriving commands stay in the suspended state until
|
||||
* Newly arriving commands remain in the suspended state until
|
||||
* scst_resume_activity() is called.
|
||||
*/
|
||||
int scst_suspend_activity(unsigned long timeout)
|
||||
@@ -892,14 +896,9 @@ int scst_suspend_activity(unsigned long timeout)
|
||||
if (suspend_count > 1)
|
||||
goto out_up;
|
||||
|
||||
set_bit(SCST_FLAG_SUSPENDING, &scst_flags);
|
||||
set_bit(SCST_FLAG_SUSPENDED, &scst_flags);
|
||||
/*
|
||||
* Assignment of SCST_FLAG_SUSPENDING and SCST_FLAG_SUSPENDED must be
|
||||
* ordered with cpu_cmd_count in scst_get(). Otherwise, lockless logic
|
||||
* of scst_get() users won't work.
|
||||
*/
|
||||
smp_mb__after_set_bit();
|
||||
/* Cause scst_get_cmd() to fail. */
|
||||
percpu_ref_killed = false;
|
||||
percpu_ref_kill(&scst_cmd_count);
|
||||
|
||||
/*
|
||||
* See comment in scst_user.c::dev_user_task_mgmt_fn() for more
|
||||
@@ -921,12 +920,13 @@ int scst_suspend_activity(unsigned long timeout)
|
||||
}
|
||||
|
||||
res = scst_susp_wait(timeout);
|
||||
if (res != 0)
|
||||
goto out_clear;
|
||||
|
||||
clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
|
||||
/* See comment about smp_mb() above */
|
||||
smp_mb__after_clear_bit();
|
||||
/* Cause scst_get_mcmd() to fail. */
|
||||
percpu_ref_killed = false;
|
||||
percpu_ref_kill(&scst_mcmd_count);
|
||||
|
||||
if (res != 0)
|
||||
goto out_resume;
|
||||
|
||||
if (scst_get_cmd_counter() != 0)
|
||||
TRACE_MGMT_DBG("Waiting for %d active commands finally to "
|
||||
@@ -964,11 +964,6 @@ out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_clear:
|
||||
clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
|
||||
/* See comment about smp_mb() above */
|
||||
smp_mb__after_clear_bit();
|
||||
|
||||
out_resume:
|
||||
__scst_resume_activity();
|
||||
EXTRACHECKS_BUG_ON(suspend_count != 0);
|
||||
@@ -994,7 +989,8 @@ static void __scst_resume_activity(void)
|
||||
if (suspend_count > 0)
|
||||
goto out;
|
||||
|
||||
clear_bit(SCST_FLAG_SUSPENDED, &scst_flags);
|
||||
percpu_ref_resurrect(&scst_mcmd_count);
|
||||
percpu_ref_resurrect(&scst_cmd_count);
|
||||
|
||||
mutex_lock(&scst_cmd_threads_mutex);
|
||||
list_for_each_entry(l, &scst_cmd_threads_list, lists_list_entry) {
|
||||
@@ -1004,7 +1000,7 @@ static void __scst_resume_activity(void)
|
||||
|
||||
/*
|
||||
* Wait until scst_init_thread() either is waiting or has reexamined
|
||||
* scst_flags.
|
||||
* scst_cmd_count.
|
||||
*/
|
||||
spin_lock_irq(&scst_init_lock);
|
||||
spin_unlock_irq(&scst_init_lock);
|
||||
@@ -2318,6 +2314,13 @@ static void __init scst_print_config(void)
|
||||
PRINT_INFO("%s", buf);
|
||||
}
|
||||
|
||||
static void scst_suspended(struct percpu_ref *ref)
|
||||
{
|
||||
WARN_ON_ONCE(ref != &scst_cmd_count && ref != &scst_mcmd_count);
|
||||
percpu_ref_killed = true;
|
||||
wake_up_all(&scst_dev_cmd_waitQ);
|
||||
}
|
||||
|
||||
static int __init init_scst(void)
|
||||
{
|
||||
int res, i;
|
||||
@@ -2526,8 +2529,17 @@ static int __init init_scst(void)
|
||||
if (res != 0)
|
||||
goto out_destroy_sgv_pool;
|
||||
|
||||
res = percpu_ref_init(&scst_cmd_count, scst_suspended,
|
||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL);
|
||||
if (res != 0)
|
||||
goto out_unreg_interface;
|
||||
|
||||
res = percpu_ref_init(&scst_mcmd_count, scst_suspended,
|
||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL);
|
||||
if (res != 0)
|
||||
goto out_cmd_count;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(scst_percpu_infos); i++) {
|
||||
atomic_set(&scst_percpu_infos[i].cpu_cmd_count, 0);
|
||||
spin_lock_init(&scst_percpu_infos[i].tasklet_lock);
|
||||
INIT_LIST_HEAD(&scst_percpu_infos[i].tasklet_cmd_list);
|
||||
tasklet_init(&scst_percpu_infos[i].tasklet,
|
||||
@@ -2565,10 +2577,14 @@ out:
|
||||
|
||||
out_thread_free:
|
||||
scst_stop_global_threads();
|
||||
percpu_ref_exit(&scst_mcmd_count);
|
||||
|
||||
out_cmd_count:
|
||||
percpu_ref_exit(&scst_cmd_count);
|
||||
|
||||
out_unreg_interface:
|
||||
scsi_unregister_interface(&scst_interface);
|
||||
|
||||
|
||||
out_destroy_sgv_pool:
|
||||
scst_sgv_pools_deinit();
|
||||
scst_tg_cleanup();
|
||||
@@ -2651,6 +2667,9 @@ static void __exit exit_scst(void)
|
||||
|
||||
scst_deinit_threads(&scst_main_cmd_threads);
|
||||
|
||||
percpu_ref_exit(&scst_mcmd_count);
|
||||
percpu_ref_exit(&scst_cmd_count);
|
||||
|
||||
scsi_unregister_interface(&scst_interface);
|
||||
|
||||
|
||||
|
||||
+6
-14
@@ -660,7 +660,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
|
||||
{
|
||||
int res = 0, rc;
|
||||
struct file *file = NULL;
|
||||
struct inode *inode;
|
||||
char *buf = NULL;
|
||||
loff_t file_size, pos, data_size;
|
||||
uint64_t sign, version;
|
||||
@@ -676,6 +675,12 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
|
||||
|
||||
TRACE_PR("Loading persistent file '%s'", file_name);
|
||||
|
||||
file_size = scst_file_or_bdev_size(file_name);
|
||||
if (file_size < 0) {
|
||||
res = file_size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = filp_open(file_name, O_RDONLY, 0);
|
||||
if (IS_ERR(file)) {
|
||||
res = PTR_ERR(file);
|
||||
@@ -683,19 +688,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = file_inode(file);
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
/* Nothing to do */
|
||||
} else if (S_ISBLK(inode->i_mode)) {
|
||||
inode = inode->i_bdev->bd_inode;
|
||||
} else {
|
||||
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
file_size = inode->i_size;
|
||||
|
||||
/* Let's limit the file size by some reasonable number */
|
||||
if ((file_size == 0) || (file_size >= 15*1024*1024)) {
|
||||
PRINT_ERROR("Invalid PR file size %d", (int)file_size);
|
||||
|
||||
+52
-53
@@ -74,20 +74,6 @@ extern unsigned long scst_trace_flag;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Bits for scst_flags
|
||||
**/
|
||||
|
||||
/*
|
||||
* Set if new commands initialization is being suspended for a while.
|
||||
* Used to let TM commands execute while preparing the suspend, since
|
||||
* RESET or ABORT could be necessary to free SCSI commands.
|
||||
*/
|
||||
#define SCST_FLAG_SUSPENDING 0
|
||||
|
||||
/* Set if new commands initialization is suspended for a while */
|
||||
#define SCST_FLAG_SUSPENDED 1
|
||||
|
||||
extern spinlock_t scst_measure_latency_lock;
|
||||
extern atomic_t scst_measure_latency;
|
||||
void scst_update_latency_stats(struct scst_cmd *cmd, int new_state);
|
||||
@@ -184,7 +170,6 @@ extern struct kmem_cache *scst_tgt_cachep;
|
||||
extern struct kmem_cache *scst_tgtd_cachep;
|
||||
extern struct kmem_cache *scst_acgd_cachep;
|
||||
|
||||
extern unsigned long scst_flags;
|
||||
extern struct list_head scst_template_list;
|
||||
extern struct list_head scst_dev_list;
|
||||
extern struct list_head scst_dev_type_list;
|
||||
@@ -217,8 +202,9 @@ extern struct list_head scst_active_mgmt_cmd_list;
|
||||
extern struct list_head scst_delayed_mgmt_cmd_list;
|
||||
extern wait_queue_head_t scst_mgmt_cmd_list_waitQ;
|
||||
|
||||
extern struct percpu_ref scst_cmd_count;
|
||||
extern struct percpu_ref scst_mcmd_count;
|
||||
struct scst_percpu_info {
|
||||
atomic_t cpu_cmd_count;
|
||||
spinlock_t tasklet_lock;
|
||||
struct list_head tasklet_cmd_list;
|
||||
struct tasklet_struct tasklet;
|
||||
@@ -671,51 +657,64 @@ void scst_ext_blocking_done(struct scst_device *dev);
|
||||
int scst_get_suspend_count(void);
|
||||
|
||||
/*
|
||||
* Increases global SCST ref counters which prevent from entering into suspended
|
||||
* activities stage, so protects from any global management operations.
|
||||
* Increase the global command count if it has not been 'killed'. Use this
|
||||
* function to protect regular commands.
|
||||
*/
|
||||
static inline atomic_t *scst_get(void)
|
||||
static inline bool __must_check scst_get_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
atomic_t *a;
|
||||
|
||||
/*
|
||||
* Avoid that a high I/O load prevents activity to be suspended. See
|
||||
* also http://sourceforge.net/p/scst/mailman/message/34074831/.
|
||||
*/
|
||||
if (unlikely(test_bit(SCST_FLAG_SUSPENDING, &scst_flags)))
|
||||
mdelay(100);
|
||||
|
||||
/*
|
||||
* We don't mind if we because of preemption inc counter from another
|
||||
* CPU as soon in the majority cases we will the correct one.
|
||||
*/
|
||||
a = &scst_percpu_infos[raw_smp_processor_id()].cpu_cmd_count;
|
||||
atomic_inc(a);
|
||||
TRACE_DBG("Incrementing cpu_cmd_count %p (new value %d)",
|
||||
a, atomic_read(a));
|
||||
/* See comment about smp_mb() in scst_suspend_activity() */
|
||||
smp_mb__after_atomic_inc();
|
||||
|
||||
return a;
|
||||
if (!percpu_ref_tryget_live(&scst_cmd_count))
|
||||
return false;
|
||||
cmd->counted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decreases global SCST ref counters which prevent from entering into suspended
|
||||
* activities stage, so protects from any global management operations. On
|
||||
* all them zero, if suspending activities is waiting, it will be proceed.
|
||||
* Increase the global management command count if it is not zero. Use this
|
||||
* function to protect management commands.
|
||||
*/
|
||||
static inline void scst_put(atomic_t *a)
|
||||
static inline bool __must_check scst_get_mcmd(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
int f;
|
||||
if (!percpu_ref_tryget_live(&scst_mcmd_count))
|
||||
return false;
|
||||
mcmd->counted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
f = atomic_dec_and_test(a);
|
||||
/* See comment about smp_mb() in scst_suspend_activity() */
|
||||
if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) && f) {
|
||||
TRACE_MGMT_DBG("%s", "Waking up scst_dev_cmd_waitQ");
|
||||
wake_up_all(&scst_dev_cmd_waitQ);
|
||||
}
|
||||
TRACE_DBG("Decrementing cpu_cmd_count %p (new value %d)",
|
||||
a, atomic_read(a));
|
||||
/*
|
||||
* Increase the global command count. Use this function to protect internal
|
||||
* commands.
|
||||
*/
|
||||
static inline void scst_get_icmd(struct scst_cmd *cmd)
|
||||
{
|
||||
percpu_ref_get(&scst_cmd_count);
|
||||
cmd->counted = true;
|
||||
}
|
||||
|
||||
/* Decrease the global SCST refcount which prevents suspending activity. */
|
||||
static inline void scst_put_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
WARN_ON_ONCE(!cmd->counted);
|
||||
cmd->counted = false;
|
||||
percpu_ref_put(&scst_cmd_count);
|
||||
}
|
||||
|
||||
static inline void scst_put_mcmd(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
WARN_ON_ONCE(!mcmd->counted);
|
||||
mcmd->counted = false;
|
||||
percpu_ref_put(&scst_mcmd_count);
|
||||
}
|
||||
|
||||
/* Whether or not activities are being suspended or have been suspended. */
|
||||
static inline bool scst_activity_suspended(void)
|
||||
{
|
||||
return percpu_ref_is_dying(&scst_cmd_count);
|
||||
}
|
||||
|
||||
/* Returns true if and only if regular commands have already been suspended. */
|
||||
static inline bool scst_mcmd_suspended(void)
|
||||
{
|
||||
return percpu_ref_is_dying(&scst_mcmd_count);
|
||||
}
|
||||
|
||||
int scst_get_cmd_counter(void);
|
||||
|
||||
+39
-39
@@ -59,7 +59,16 @@ static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
|
||||
|
||||
i = &scst_percpu_infos[smp_processor_id()];
|
||||
|
||||
if (atomic_read(&i->cpu_cmd_count) <= scst_max_tasklet_cmd) {
|
||||
/*
|
||||
* Commands are removed from the list they are on before being
|
||||
* processed. If both lists are empty that means that at most two
|
||||
* commands are being processed and hence that processing a
|
||||
* command in tasklet context is possible without making a CPU core
|
||||
* spend all its time in interrupt and tasklet context and thereby
|
||||
* starving threads scheduled on the same CPU core.
|
||||
*/
|
||||
if (list_empty_careful(&i->tasklet_cmd_list) &&
|
||||
list_empty_careful(&cmd->cmd_threads->active_cmd_list)) {
|
||||
spin_lock_irqsave(&i->tasklet_lock, flags);
|
||||
TRACE_DBG("Adding cmd %p to tasklet %d cmd list", cmd,
|
||||
smp_processor_id());
|
||||
@@ -69,8 +78,8 @@ static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
|
||||
tasklet_schedule(&i->tasklet);
|
||||
} else {
|
||||
spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
|
||||
TRACE_DBG("Too many tasklet commands (%d), adding cmd %p to "
|
||||
"active cmd list", atomic_read(&i->cpu_cmd_count), cmd);
|
||||
TRACE_DBG("Too many tasklet commands, adding cmd %p to active cmd list",
|
||||
cmd);
|
||||
list_add_tail(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_threads->active_cmd_list);
|
||||
wake_up(&cmd->cmd_threads->cmd_list_waitQ);
|
||||
@@ -565,7 +574,7 @@ static void __scst_rx_cmd(struct scst_cmd *cmd, struct scst_session *sess,
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
WARN_ON_ONCE(cmd->cpu_cmd_counter);
|
||||
WARN_ON_ONCE(cmd->counted);
|
||||
|
||||
cmd->sess = sess;
|
||||
scst_sess_get(sess);
|
||||
@@ -4150,7 +4159,7 @@ struct scst_tgt_dev *scst_lookup_tgt_dev(struct scst_session *sess, u64 lun)
|
||||
* scst_translate_lun() - Translate @cmd->lun into a tgt_dev pointer.
|
||||
* @cmd: SCSI command for which to translate the LUN number.
|
||||
*
|
||||
* Initialize the following @cmd members: cpu_cmd_counter, cmd_threads,
|
||||
* Initialize the following @cmd members: counted, cmd_threads,
|
||||
* tgt_dev, cur_order_data, dev and devt.
|
||||
*
|
||||
* The caller must not hold any locks. May be called from IRQ context. The data
|
||||
@@ -4168,9 +4177,7 @@ static int scst_translate_lun(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd->cpu_cmd_counter = scst_get();
|
||||
|
||||
if (likely(!test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) {
|
||||
if (likely(scst_get_cmd(cmd))) {
|
||||
TRACE_DBG("Finding tgt_dev for cmd %p (lun %lld)", cmd,
|
||||
(unsigned long long)cmd->lun);
|
||||
res = -1;
|
||||
@@ -4213,12 +4220,9 @@ static int scst_translate_lun(struct scst_cmd *cmd)
|
||||
cmd->sess->initiator_name, cmd->tgt->tgt_name);
|
||||
scst_event_queue_lun_not_found(cmd);
|
||||
}
|
||||
scst_put(cmd->cpu_cmd_counter);
|
||||
cmd->cpu_cmd_counter = NULL;
|
||||
scst_put_cmd(cmd);
|
||||
}
|
||||
} else {
|
||||
scst_put(cmd->cpu_cmd_counter);
|
||||
cmd->cpu_cmd_counter = NULL;
|
||||
TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
|
||||
res = 1;
|
||||
}
|
||||
@@ -4427,7 +4431,8 @@ restart:
|
||||
* There is no need for read barrier here, because we don't care where
|
||||
* this check will be done.
|
||||
*/
|
||||
susp = test_bit(SCST_FLAG_SUSPENDED, &scst_flags);
|
||||
susp = scst_activity_suspended();
|
||||
|
||||
if (scst_init_poll_cnt > 0)
|
||||
scst_init_poll_cnt--;
|
||||
|
||||
@@ -4488,13 +4493,13 @@ restart:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int test_init_cmd_list(void)
|
||||
/* Whether or not scst_init_thread() should stop waiting. */
|
||||
static inline bool test_init_cmd_list(void)
|
||||
{
|
||||
int res = (!list_empty(&scst_init_cmd_list) &&
|
||||
!test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) ||
|
||||
unlikely(kthread_should_stop()) ||
|
||||
(scst_init_poll_cnt > 0);
|
||||
return res;
|
||||
return (!list_empty(&scst_init_cmd_list) &&
|
||||
!scst_activity_suspended()) ||
|
||||
unlikely(kthread_should_stop()) ||
|
||||
(scst_init_poll_cnt > 0);
|
||||
}
|
||||
|
||||
int scst_init_thread(void *arg)
|
||||
@@ -5015,9 +5020,8 @@ void scst_cmd_tasklet(long p)
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success, or > 0 if SCST_FLAG_SUSPENDED set and
|
||||
* SCST_FLAG_SUSPENDING - not. No locks, protection is done by the
|
||||
* suspended activity.
|
||||
* Returns 0 on success, or > 0 upon failure. No locks, protection is done by
|
||||
* suspending activity.
|
||||
*/
|
||||
static int scst_get_mgmt(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
@@ -5025,12 +5029,7 @@ static int scst_get_mgmt(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mcmd->cpu_cmd_counter = scst_get();
|
||||
|
||||
if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
|
||||
!test_bit(SCST_FLAG_SUSPENDING, &scst_flags))) {
|
||||
scst_put(mcmd->cpu_cmd_counter);
|
||||
mcmd->cpu_cmd_counter = NULL;
|
||||
if (unlikely(!scst_get_mcmd(mcmd))) {
|
||||
TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
|
||||
res = 1;
|
||||
goto out;
|
||||
@@ -5042,9 +5041,8 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success, < 0 if there is no device handler or
|
||||
* > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not.
|
||||
* No locks, protection is done by the suspended activity.
|
||||
* Returns 0 on success, < 0 if there is no device handler or > 0 if activity
|
||||
* has been suspended. No locks, protection is done by the suspended activity.
|
||||
*/
|
||||
static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
@@ -5069,8 +5067,7 @@ static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
|
||||
mcmd->mcmd_tgt_dev = tgt_dev;
|
||||
res = 0;
|
||||
} else {
|
||||
scst_put(mcmd->cpu_cmd_counter);
|
||||
mcmd->cpu_cmd_counter = NULL;
|
||||
scst_put_mcmd(mcmd);
|
||||
res = -1;
|
||||
}
|
||||
|
||||
@@ -5902,10 +5899,14 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
res = scst_set_mcmd_next_state(mcmd);
|
||||
goto out;
|
||||
}
|
||||
__scst_cmd_get(cmd);
|
||||
tgt_dev = cmd->tgt_dev;
|
||||
if (tgt_dev != NULL)
|
||||
mcmd->cpu_cmd_counter = scst_get();
|
||||
if (tgt_dev && !scst_get_mcmd(mcmd)) {
|
||||
TRACE_MGMT_DBG("Suspended; skipping mcmd");
|
||||
spin_unlock_irq(&sess->sess_list_lock);
|
||||
res = 1;
|
||||
goto ret;
|
||||
}
|
||||
__scst_cmd_get(cmd);
|
||||
spin_unlock_irq(&sess->sess_list_lock);
|
||||
TRACE_DBG("Cmd to abort %p for tag %llu found (tgt_dev %p)",
|
||||
cmd, (unsigned long long)mcmd->tag, tgt_dev);
|
||||
@@ -5963,6 +5964,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
out:
|
||||
scst_event_queue_tm_fn_received(mcmd);
|
||||
|
||||
ret:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -6842,9 +6844,7 @@ int scst_tm_thread(void *arg)
|
||||
rc = scst_process_mgmt_cmd(mcmd);
|
||||
spin_lock_irq(&scst_mcmd_lock);
|
||||
if (rc > 0) {
|
||||
if (test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
|
||||
!test_bit(SCST_FLAG_SUSPENDING,
|
||||
&scst_flags)) {
|
||||
if (scst_mcmd_suspended()) {
|
||||
TRACE_MGMT_DBG("Adding mgmt cmd %p to "
|
||||
"head of delayed mgmt cmd list",
|
||||
mcmd);
|
||||
|
||||
@@ -89,7 +89,7 @@ static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
|
||||
#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
|
||||
#endif
|
||||
|
||||
#define SCST_LOCAL_VERSION "3.5.0"
|
||||
#define SCST_LOCAL_VERSION "3.6.0-pre"
|
||||
static const char *scst_local_version_date = "20110901";
|
||||
|
||||
/* Some statistics */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $Version = 'SCST Configurator v3.5.0';
|
||||
my $Version = 'SCST Configurator v3.6.0-pre';
|
||||
|
||||
# Configures SCST
|
||||
#
|
||||
|
||||
+2
-2
@@ -63,8 +63,8 @@
|
||||
|
||||
/* Name of this kernel module. */
|
||||
#define DRV_NAME "ib_srpt"
|
||||
#define DRV_VERSION "3.5.0" "#" __stringify(OFED_FLAVOR)
|
||||
#define DRV_RELDATE "21 December 2020"
|
||||
#define DRV_VERSION "3.6.0-pre" "#" __stringify(OFED_FLAVOR)
|
||||
#define DRV_RELDATE "02 January 2021"
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
/* Flags to be used in SCST debug tracing statements. */
|
||||
#define DEFAULT_SRPT_TRACE_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR \
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
User space FILEIO handler
|
||||
=========================
|
||||
|
||||
Version 3.5.0, 21 December 2020
|
||||
Version 3.6.0-pre, 02 January 2021
|
||||
----------------------------
|
||||
|
||||
User space program fileio_tgt uses interface of SCST's scst_user dev
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
/* 8 byte ASCII Vendor */
|
||||
#define VENDOR "SCST_USR"
|
||||
/* 4 byte ASCII Product Revision Level - left aligned */
|
||||
#define FIO_REV "350 "
|
||||
#define FIO_REV "360 "
|
||||
|
||||
#define MAX_USN_LEN (20+1) /* For '\0' */
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
#ifndef __VERSION_H
|
||||
#define __VERSION_H
|
||||
|
||||
#define VERSION_STR "3.5.0"
|
||||
#define VERSION_STR "3.6.0-pre"
|
||||
|
||||
#endif /* __VERSION_H */
|
||||
|
||||
Reference in New Issue
Block a user