mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
Merge branch 'nvme-4.19' of git://git.infradead.org/nvme into for-4.19/block
Pull NVMe updates from Christoph: "This should be the last round of NVMe updates before the 4.19 merge window opens. It conatins support for write protected (aka read-only) namespaces from Chaitanya, two ANA fixes from Hannes and a fabrics fix from Tal Shorer." * 'nvme-4.19' of git://git.infradead.org/nvme: nvme-fabrics: fix ctrl_loss_tmo < 0 to reconnect forever nvmet: add ns write protect support nvme: set gendisk read only based on nsattr nvme.h: add support for ns write protect definitions nvme.h: fixup ANA group descriptor format nvme: fixup crash on failed discovery
This commit is contained in:
commit
4884f8bf87
@ -1484,6 +1484,12 @@ static void nvme_update_disk_info(struct gendisk *disk,
|
||||
|
||||
set_capacity(disk, capacity);
|
||||
nvme_config_discard(ns);
|
||||
|
||||
if (id->nsattr & (1 << 0))
|
||||
set_disk_ro(disk, true);
|
||||
else
|
||||
set_disk_ro(disk, false);
|
||||
|
||||
blk_mq_unfreeze_queue(disk->queue);
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,7 @@ EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
|
||||
|
||||
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl)
|
||||
{
|
||||
if (ctrl->opts->max_reconnects != -1 &&
|
||||
if (ctrl->opts->max_reconnects == -1 ||
|
||||
ctrl->nr_reconnects < ctrl->opts->max_reconnects)
|
||||
return true;
|
||||
|
||||
|
@ -22,7 +22,7 @@ MODULE_PARM_DESC(multipath,
|
||||
|
||||
inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
|
||||
{
|
||||
return multipath && (ctrl->subsys->cmic & (1 << 3));
|
||||
return multipath && ctrl->subsys && (ctrl->subsys->cmic & (1 << 3));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -372,6 +372,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
|
||||
id->psd[0].entry_lat = cpu_to_le32(0x10);
|
||||
id->psd[0].exit_lat = cpu_to_le32(0x4);
|
||||
|
||||
id->nwpc = 1 << 0; /* write protect and no write protect */
|
||||
|
||||
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
|
||||
|
||||
kfree(id);
|
||||
@ -433,6 +435,8 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req)
|
||||
|
||||
id->lbaf[0].ds = ns->blksize_shift;
|
||||
|
||||
if (ns->readonly)
|
||||
id->nsattr |= (1 << 0);
|
||||
nvmet_put_namespace(ns);
|
||||
done:
|
||||
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
|
||||
@ -545,6 +549,52 @@ static void nvmet_execute_abort(struct nvmet_req *req)
|
||||
nvmet_req_complete(req, 0);
|
||||
}
|
||||
|
||||
static u16 nvmet_write_protect_flush_sync(struct nvmet_req *req)
|
||||
{
|
||||
u16 status;
|
||||
|
||||
if (req->ns->file)
|
||||
status = nvmet_file_flush(req);
|
||||
else
|
||||
status = nvmet_bdev_flush(req);
|
||||
|
||||
if (status)
|
||||
pr_err("write protect flush failed nsid: %u\n", req->ns->nsid);
|
||||
return status;
|
||||
}
|
||||
|
||||
static u16 nvmet_set_feat_write_protect(struct nvmet_req *req)
|
||||
{
|
||||
u32 write_protect = le32_to_cpu(req->cmd->common.cdw10[1]);
|
||||
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
|
||||
u16 status = NVME_SC_FEATURE_NOT_CHANGEABLE;
|
||||
|
||||
req->ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->rw.nsid);
|
||||
if (unlikely(!req->ns))
|
||||
return status;
|
||||
|
||||
mutex_lock(&subsys->lock);
|
||||
switch (write_protect) {
|
||||
case NVME_NS_WRITE_PROTECT:
|
||||
req->ns->readonly = true;
|
||||
status = nvmet_write_protect_flush_sync(req);
|
||||
if (status)
|
||||
req->ns->readonly = false;
|
||||
break;
|
||||
case NVME_NS_NO_WRITE_PROTECT:
|
||||
req->ns->readonly = false;
|
||||
status = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
nvmet_ns_changed(subsys, req->ns->nsid);
|
||||
mutex_unlock(&subsys->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void nvmet_execute_set_features(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
|
||||
@ -575,6 +625,9 @@ static void nvmet_execute_set_features(struct nvmet_req *req)
|
||||
case NVME_FEAT_HOST_ID:
|
||||
status = NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
|
||||
break;
|
||||
case NVME_FEAT_WRITE_PROTECT:
|
||||
status = nvmet_set_feat_write_protect(req);
|
||||
break;
|
||||
default:
|
||||
status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
|
||||
break;
|
||||
@ -583,6 +636,26 @@ static void nvmet_execute_set_features(struct nvmet_req *req)
|
||||
nvmet_req_complete(req, status);
|
||||
}
|
||||
|
||||
static u16 nvmet_get_feat_write_protect(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
|
||||
u32 result;
|
||||
|
||||
req->ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->common.nsid);
|
||||
if (!req->ns)
|
||||
return NVME_SC_INVALID_NS | NVME_SC_DNR;
|
||||
|
||||
mutex_lock(&subsys->lock);
|
||||
if (req->ns->readonly == true)
|
||||
result = NVME_NS_WRITE_PROTECT;
|
||||
else
|
||||
result = NVME_NS_NO_WRITE_PROTECT;
|
||||
nvmet_set_result(req, result);
|
||||
mutex_unlock(&subsys->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvmet_execute_get_features(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_subsys *subsys = req->sq->ctrl->subsys;
|
||||
@ -634,6 +707,9 @@ static void nvmet_execute_get_features(struct nvmet_req *req)
|
||||
status = nvmet_copy_to_sgl(req, 0, &req->sq->ctrl->hostid,
|
||||
sizeof(req->sq->ctrl->hostid));
|
||||
break;
|
||||
case NVME_FEAT_WRITE_PROTECT:
|
||||
status = nvmet_get_feat_write_protect(req);
|
||||
break;
|
||||
default:
|
||||
status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
|
||||
break;
|
||||
|
@ -180,7 +180,7 @@ out_unlock:
|
||||
mutex_unlock(&ctrl->lock);
|
||||
}
|
||||
|
||||
static void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid)
|
||||
void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl;
|
||||
|
||||
@ -609,6 +609,21 @@ static inline u16 nvmet_check_ana_state(struct nvmet_port *port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u16 nvmet_io_cmd_check_access(struct nvmet_req *req)
|
||||
{
|
||||
if (unlikely(req->ns->readonly)) {
|
||||
switch (req->cmd->common.opcode) {
|
||||
case nvme_cmd_read:
|
||||
case nvme_cmd_flush:
|
||||
break;
|
||||
default:
|
||||
return NVME_SC_NS_WRITE_PROTECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
|
||||
{
|
||||
struct nvme_command *cmd = req->cmd;
|
||||
@ -622,6 +637,9 @@ static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
|
||||
if (unlikely(!req->ns))
|
||||
return NVME_SC_INVALID_NS | NVME_SC_DNR;
|
||||
ret = nvmet_check_ana_state(req->port, req->ns);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
ret = nvmet_io_cmd_check_access(req);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
|
@ -124,6 +124,13 @@ static void nvmet_bdev_execute_flush(struct nvmet_req *req)
|
||||
submit_bio(bio);
|
||||
}
|
||||
|
||||
u16 nvmet_bdev_flush(struct nvmet_req *req)
|
||||
{
|
||||
if (blkdev_issue_flush(req->ns->bdev, GFP_KERNEL, NULL))
|
||||
return NVME_SC_INTERNAL | NVME_SC_DNR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 nvmet_bdev_discard_range(struct nvmet_ns *ns,
|
||||
struct nvme_dsm_range *range, struct bio **bio)
|
||||
{
|
||||
|
@ -211,14 +211,18 @@ static void nvmet_file_execute_rw_buffered_io(struct nvmet_req *req)
|
||||
queue_work(buffered_io_wq, &req->f.work);
|
||||
}
|
||||
|
||||
u16 nvmet_file_flush(struct nvmet_req *req)
|
||||
{
|
||||
if (vfs_fsync(req->ns->file, 1) < 0)
|
||||
return NVME_SC_INTERNAL | NVME_SC_DNR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvmet_file_flush_work(struct work_struct *w)
|
||||
{
|
||||
struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
|
||||
int ret;
|
||||
|
||||
ret = vfs_fsync(req->ns->file, 1);
|
||||
|
||||
nvmet_req_complete(req, ret < 0 ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);
|
||||
nvmet_req_complete(req, nvmet_file_flush(req));
|
||||
}
|
||||
|
||||
static void nvmet_file_execute_flush(struct nvmet_req *req)
|
||||
|
@ -58,6 +58,7 @@ struct nvmet_ns {
|
||||
struct percpu_ref ref;
|
||||
struct block_device *bdev;
|
||||
struct file *file;
|
||||
bool readonly;
|
||||
u32 nsid;
|
||||
u32 blksize_shift;
|
||||
loff_t size;
|
||||
@ -429,6 +430,9 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns);
|
||||
int nvmet_file_ns_enable(struct nvmet_ns *ns);
|
||||
void nvmet_bdev_ns_disable(struct nvmet_ns *ns);
|
||||
void nvmet_file_ns_disable(struct nvmet_ns *ns);
|
||||
u16 nvmet_bdev_flush(struct nvmet_req *req);
|
||||
u16 nvmet_file_flush(struct nvmet_req *req);
|
||||
void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid);
|
||||
|
||||
static inline u32 nvmet_rw_len(struct nvmet_req *req)
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ struct nvme_id_ctrl {
|
||||
__le16 awun;
|
||||
__le16 awupf;
|
||||
__u8 nvscc;
|
||||
__u8 rsvd531;
|
||||
__u8 nwpc;
|
||||
__le16 acwu;
|
||||
__u8 rsvd534[2];
|
||||
__le32 sgls;
|
||||
@ -320,7 +320,9 @@ struct nvme_id_ns {
|
||||
__u8 nvmcap[16];
|
||||
__u8 rsvd64[28];
|
||||
__le32 anagrpid;
|
||||
__u8 rsvd96[8];
|
||||
__u8 rsvd96[3];
|
||||
__u8 nsattr;
|
||||
__u8 rsvd100[4];
|
||||
__u8 nguid[16];
|
||||
__u8 eui64[8];
|
||||
struct nvme_lbaf lbaf[16];
|
||||
@ -446,7 +448,7 @@ struct nvme_ana_group_desc {
|
||||
__le32 nnsids;
|
||||
__le64 chgcnt;
|
||||
__u8 state;
|
||||
__u8 rsvd17[7];
|
||||
__u8 rsvd17[15];
|
||||
__le32 nsids[];
|
||||
};
|
||||
|
||||
@ -794,6 +796,7 @@ enum {
|
||||
NVME_FEAT_HOST_ID = 0x81,
|
||||
NVME_FEAT_RESV_MASK = 0x82,
|
||||
NVME_FEAT_RESV_PERSIST = 0x83,
|
||||
NVME_FEAT_WRITE_PROTECT = 0x84,
|
||||
NVME_LOG_ERROR = 0x01,
|
||||
NVME_LOG_SMART = 0x02,
|
||||
NVME_LOG_FW_SLOT = 0x03,
|
||||
@ -807,6 +810,14 @@ enum {
|
||||
NVME_FWACT_ACTV = (2 << 3),
|
||||
};
|
||||
|
||||
/* NVMe Namespace Write Protect State */
|
||||
enum {
|
||||
NVME_NS_NO_WRITE_PROTECT = 0,
|
||||
NVME_NS_WRITE_PROTECT,
|
||||
NVME_NS_WRITE_PROTECT_POWER_CYCLE,
|
||||
NVME_NS_WRITE_PROTECT_PERMANENT,
|
||||
};
|
||||
|
||||
#define NVME_MAX_CHANGED_NAMESPACES 1024
|
||||
|
||||
struct nvme_identify {
|
||||
@ -1153,6 +1164,8 @@ enum {
|
||||
NVME_SC_SGL_INVALID_OFFSET = 0x16,
|
||||
NVME_SC_SGL_INVALID_SUBTYPE = 0x17,
|
||||
|
||||
NVME_SC_NS_WRITE_PROTECTED = 0x20,
|
||||
|
||||
NVME_SC_LBA_RANGE = 0x80,
|
||||
NVME_SC_CAP_EXCEEDED = 0x81,
|
||||
NVME_SC_NS_NOT_READY = 0x82,
|
||||
|
Loading…
Reference in New Issue
Block a user