mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
Merge branch 'svn-trunk'
This commit is contained in:
@@ -571,6 +571,21 @@ static inline long get_user_pages_backport(unsigned long start,
|
||||
#endif
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) */
|
||||
|
||||
/* See also commit f036be96dd9c ("printk: introduce printk_once()") */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
|
||||
#define printk_once(fmt, ...) \
|
||||
({ \
|
||||
static bool __print_once __read_mostly; \
|
||||
bool __ret_print_once = !__print_once; \
|
||||
\
|
||||
if (!__print_once) { \
|
||||
__print_once = true; \
|
||||
printk(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
unlikely(__ret_print_once); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
/*
|
||||
* See also patch "kernel.h: add pr_warn for symmetry to dev_warn,
|
||||
|
||||
@@ -443,6 +443,8 @@ static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_cluster_mode_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_cluster_mode_store(struct kobject *kobj,
|
||||
@@ -546,7 +548,8 @@ static struct kobj_attribute vdev_read_zero_attr =
|
||||
static struct kobj_attribute vdisk_removable_attr =
|
||||
__ATTR(removable, S_IRUGO, vdisk_sysfs_removable_show, NULL);
|
||||
static struct kobj_attribute vdisk_filename_attr =
|
||||
__ATTR(filename, S_IRUGO, vdev_sysfs_filename_show, NULL);
|
||||
__ATTR(filename, S_IWUSR|S_IRUGO, vdev_sysfs_filename_show,
|
||||
vdev_sysfs_filename_store);
|
||||
static struct kobj_attribute vdisk_cluster_mode_attr =
|
||||
__ATTR(cluster_mode, S_IWUSR|S_IRUGO, vdev_sysfs_cluster_mode_show,
|
||||
vdev_sysfs_cluster_mode_store);
|
||||
@@ -9490,6 +9493,107 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int vdev_sysfs_process_filename_store(struct scst_sysfs_work_item *work)
|
||||
{
|
||||
struct scst_device *dev = work->dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
int length = strlen(work->buf);
|
||||
char *p, *fn;
|
||||
const char *filename = NULL;
|
||||
int res;
|
||||
|
||||
res = mutex_lock_interruptible(&scst_mutex);
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
res = -EINVAL;
|
||||
|
||||
/* Serialize against vdisk_open_fd() and vdisk_close_fd() calls. */
|
||||
scst_alua_lock();
|
||||
|
||||
/*
|
||||
* This is safe since we hold a reference on dev_kobj and since
|
||||
* scst_assign_dev_handler() waits until all dev_kobj references
|
||||
* have been dropped before invoking .detach().
|
||||
*/
|
||||
virt_dev = dev->dh_priv;
|
||||
if (virt_dev->dev_active) {
|
||||
PRINT_ERROR("vdev %s: can't change the filename because the device is still active",
|
||||
dev->virt_name);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
p = work->buf;
|
||||
while (isspace(*p) && *p)
|
||||
p++;
|
||||
if (*p == '\0') {
|
||||
PRINT_ERROR("Filename is missing");
|
||||
goto unlock;
|
||||
}
|
||||
filename = p;
|
||||
p = &work->buf[length - 1];
|
||||
while (isspace(*p))
|
||||
p--;
|
||||
*(p + 1) = '\0';
|
||||
if (*filename != '/') {
|
||||
PRINT_ERROR("Path \"%s\" is not absolute", filename);
|
||||
goto unlock;
|
||||
}
|
||||
fn = kstrdup(filename, GFP_KERNEL);
|
||||
if (fn == NULL) {
|
||||
PRINT_ERROR("Filename allocation failed");
|
||||
goto unlock;
|
||||
}
|
||||
swap(virt_dev->filename, fn);
|
||||
kfree(fn);
|
||||
PRINT_INFO("vdev %s: changed filename into \"%s\"", virt_dev->name,
|
||||
virt_dev->filename);
|
||||
res = 0;
|
||||
|
||||
unlock:
|
||||
scst_alua_unlock();
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
out:
|
||||
kobject_put(&dev->dev_kobj);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev = container_of(kobj, struct scst_device,
|
||||
dev_kobj);
|
||||
struct scst_sysfs_work_item *work;
|
||||
char *arg;
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = -ENOMEM;
|
||||
arg = kasprintf(GFP_KERNEL, "%.*s", (int)count, buf);
|
||||
if (!arg)
|
||||
goto out;
|
||||
|
||||
res = scst_alloc_sysfs_work(vdev_sysfs_process_filename_store,
|
||||
false, &work);
|
||||
if (res)
|
||||
goto out;
|
||||
work->dev = dev;
|
||||
swap(work->buf, arg);
|
||||
kobject_get(&dev->dev_kobj);
|
||||
res = scst_sysfs_queue_wait_work(work);
|
||||
if (res)
|
||||
goto out;
|
||||
res = count;
|
||||
|
||||
out:
|
||||
kfree(arg);
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_cluster_mode_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
|
||||
@@ -13161,7 +13161,7 @@ void scst_dev_check_set_UA(struct scst_device *dev,
|
||||
scst_res_unlock(dev, &lksb);
|
||||
|
||||
if (rc)
|
||||
scst_unblock_aborted_cmds(NULL, NULL, dev, false);
|
||||
scst_unblock_aborted_cmds(NULL, NULL, dev);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -13835,7 +13835,7 @@ static void scst_process_qerr(struct scst_cmd *cmd)
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
if (unblock)
|
||||
scst_unblock_aborted_cmds(cmd->tgt, cmd->sess, dev, false);
|
||||
scst_unblock_aborted_cmds(cmd->tgt, cmd->sess, dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -14174,8 +14174,8 @@ EXPORT_SYMBOL(scst_reassign_retained_sess_states);
|
||||
* scst_get_next_lexem() - parse and return next lexem in the string
|
||||
*
|
||||
* Returns pointer to the next lexem from token_str skipping
|
||||
* spaces and '=' character and using them then as a delimeter. Content
|
||||
* of token_str is modified by setting '\0' at the delimeter's position.
|
||||
* spaces and '=' character and using them then as a delimiter. Content
|
||||
* of token_str is modified by setting '\0' at the delimiter's position.
|
||||
*/
|
||||
char *scst_get_next_lexem(char **token_str)
|
||||
{
|
||||
@@ -14218,8 +14218,8 @@ EXPORT_SYMBOL_GPL(scst_restore_token_str);
|
||||
* scst_get_next_token_str() - parse and return next token
|
||||
*
|
||||
* This function returns pointer to the next token strings from input_str
|
||||
* using '\n', ';' and '\0' as a delimeter. Content of input_str is
|
||||
* modified by setting '\0' at the delimeter's position.
|
||||
* using '\n', ';' and '\0' as a delimiter. Content of input_str is
|
||||
* modified by setting '\0' at the delimiter's position.
|
||||
*/
|
||||
char *scst_get_next_token_str(char **input_str)
|
||||
{
|
||||
|
||||
@@ -725,9 +725,10 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
|
||||
void scst_process_reset(struct scst_device *dev,
|
||||
struct scst_session *originator, struct scst_cmd *exclude_cmd,
|
||||
struct scst_mgmt_cmd *mcmd, bool setUA);
|
||||
void __scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
const struct scst_session *sess, const struct scst_device *device);
|
||||
void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
const struct scst_session *sess, const struct scst_device *device,
|
||||
bool scst_mutex_held);
|
||||
const struct scst_session *sess, const struct scst_device *device);
|
||||
void scst_clear_aca(struct scst_tgt_dev *tgt_dev, bool other_ini);
|
||||
|
||||
bool scst_is_ua_global(const uint8_t *sense, int len);
|
||||
|
||||
@@ -6376,18 +6376,14 @@ static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd,
|
||||
return res;
|
||||
}
|
||||
|
||||
void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
const struct scst_session *sess, const struct scst_device *device,
|
||||
bool scst_mutex_held)
|
||||
void __scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
const struct scst_session *sess, const struct scst_device *device)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (!scst_mutex_held)
|
||||
mutex_lock(&scst_mutex);
|
||||
else
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
|
||||
struct scst_cmd *cmd, *tcmd;
|
||||
@@ -6441,13 +6437,18 @@ void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
local_irq_enable_nort();
|
||||
}
|
||||
|
||||
if (!scst_mutex_held)
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
|
||||
const struct scst_session *sess, const struct scst_device *device)
|
||||
{
|
||||
mutex_lock(&scst_mutex);
|
||||
__scst_unblock_aborted_cmds(tgt, sess, device);
|
||||
mutex_unlock(&scst_mutex);
|
||||
}
|
||||
|
||||
static void __scst_abort_task_set(struct scst_mgmt_cmd *mcmd,
|
||||
struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
@@ -6526,7 +6527,8 @@ static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "ABORT TASK SET/PR ABORT", 0);
|
||||
|
||||
scst_unblock_aborted_cmds(tgt_dev->sess->tgt, tgt_dev->sess, tgt_dev->dev, false);
|
||||
scst_unblock_aborted_cmds(tgt_dev->sess->tgt, tgt_dev->sess,
|
||||
tgt_dev->dev);
|
||||
|
||||
scst_call_dev_task_mgmt_fn_received(mcmd, tgt_dev);
|
||||
|
||||
@@ -6616,7 +6618,7 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "CLEAR TASK SET", 0);
|
||||
|
||||
scst_unblock_aborted_cmds(NULL, NULL, dev, true);
|
||||
__scst_unblock_aborted_cmds(NULL, NULL, dev);
|
||||
|
||||
if (!dev->tas) {
|
||||
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
|
||||
@@ -6811,7 +6813,7 @@ static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
|
||||
list_add_tail(&dev->tm_dev_list_entry, &host_devs);
|
||||
}
|
||||
|
||||
scst_unblock_aborted_cmds(NULL, NULL, NULL, true);
|
||||
__scst_unblock_aborted_cmds(NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* We suppose here that for all commands that already on devices
|
||||
@@ -6917,7 +6919,7 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
|
||||
dev->scsi_dev->was_reset = 0;
|
||||
}
|
||||
|
||||
scst_unblock_aborted_cmds(NULL, NULL, dev, false);
|
||||
scst_unblock_aborted_cmds(NULL, NULL, dev);
|
||||
|
||||
tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "LUN RESET", 0);
|
||||
|
||||
@@ -6997,7 +6999,7 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
scst_unblock_aborted_cmds(NULL, sess, NULL, false);
|
||||
scst_unblock_aborted_cmds(NULL, sess, NULL);
|
||||
|
||||
res = scst_set_mcmd_next_state(mcmd);
|
||||
|
||||
@@ -7082,7 +7084,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
scst_unblock_aborted_cmds(tgt, NULL, NULL, true);
|
||||
__scst_unblock_aborted_cmds(tgt, NULL, NULL);
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
@@ -7122,7 +7124,7 @@ static int scst_abort_task(struct scst_mgmt_cmd *mcmd)
|
||||
scst_abort_cmd(cmd, mcmd, 0, 1);
|
||||
spin_unlock_irq(&cmd->sess->sess_list_lock);
|
||||
|
||||
scst_unblock_aborted_cmds(cmd->tgt, cmd->sess, cmd->dev, false);
|
||||
scst_unblock_aborted_cmds(cmd->tgt, cmd->sess, cmd->dev);
|
||||
}
|
||||
|
||||
res = scst_set_mcmd_next_state(mcmd);
|
||||
@@ -7231,7 +7233,7 @@ static int scst_clear_aca_mcmd(struct scst_mgmt_cmd *mcmd)
|
||||
scst_make_deferred_commands_active(order_data);
|
||||
|
||||
scst_unblock_aborted_cmds(mcmd_tgt_dev->sess->tgt, mcmd_tgt_dev->sess,
|
||||
mcmd_tgt_dev->dev, false);
|
||||
mcmd_tgt_dev->dev);
|
||||
|
||||
out_state:
|
||||
res = scst_set_mcmd_next_state(mcmd);
|
||||
|
||||
Reference in New Issue
Block a user