mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-20 11:11:24 +00:00
Add LUN resizing to CTL. Also make it possible to explicitly set
size when creating file-backed or device-backed LUN. Reviewed by: ken (earlier version) Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
7dfd88318b
commit
811772950f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232604
@ -1,7 +1,11 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2009 Silicon Graphics International Corp.
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by Edward Tomasz Napierala
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -4797,6 +4801,25 @@ ctl_lun_power_lock(struct ctl_be_lun *be_lun, struct ctl_nexus *nexus,
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ctl_lun_capacity_changed(struct ctl_be_lun *be_lun)
|
||||
{
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *softc;
|
||||
int i;
|
||||
|
||||
softc = control_softc;
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
|
||||
lun = (struct ctl_lun *)be_lun->ctl_lun;
|
||||
|
||||
for (i = 0; i < CTL_MAX_INITIATORS; i++)
|
||||
lun->pending_sense[i].ua_pending |= CTL_UA_CAPACITY_CHANGED;
|
||||
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Backend "memory move is complete" callback for requests that never
|
||||
* make it down to say RAIDCore's configuration code.
|
||||
|
@ -120,7 +120,8 @@ typedef enum {
|
||||
CTL_UA_RES_PREEMPT = 0x0200,
|
||||
CTL_UA_RES_RELEASE = 0x0400,
|
||||
CTL_UA_REG_PREEMPT = 0x0800,
|
||||
CTL_UA_ASYM_ACC_CHANGE = 0x1000
|
||||
CTL_UA_ASYM_ACC_CHANGE = 0x1000,
|
||||
CTL_UA_CAPACITY_CHANGED = 0x2000
|
||||
} ctl_ua_type;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
@ -280,6 +280,11 @@ int ctl_lun_power_lock(struct ctl_be_lun *be_lun, struct ctl_nexus *nexus,
|
||||
int ctl_lun_offline(struct ctl_be_lun *be_lun);
|
||||
int ctl_lun_online(struct ctl_be_lun *be_lun);
|
||||
|
||||
/*
|
||||
* Let the backend notify the initiator about changed capacity.
|
||||
*/
|
||||
void ctl_lun_capacity_changed(struct ctl_be_lun *be_lun);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _CTL_BACKEND_H_ */
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Silicon Graphics International Corp.
|
||||
* Copyright (c) 2009-2011 Spectra Logic Corporation
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by Edward Tomasz Napierala
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -250,6 +254,12 @@ static int ctl_be_block_create(struct ctl_be_block_softc *softc,
|
||||
struct ctl_lun_req *req);
|
||||
static int ctl_be_block_rm(struct ctl_be_block_softc *softc,
|
||||
struct ctl_lun_req *req);
|
||||
static int ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
|
||||
struct ctl_lun_req *req);
|
||||
static int ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
|
||||
struct ctl_lun_req *req);
|
||||
static int ctl_be_block_modify(struct ctl_be_block_softc *softc,
|
||||
struct ctl_lun_req *req);
|
||||
static void ctl_be_block_lun_shutdown(void *be_lun);
|
||||
static void ctl_be_block_lun_config_status(void *be_lun,
|
||||
ctl_lun_config_status status);
|
||||
@ -1263,6 +1273,9 @@ ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
|
||||
case CTL_LUNREQ_RM:
|
||||
error = ctl_be_block_rm(softc, lun_req);
|
||||
break;
|
||||
case CTL_LUNREQ_MODIFY:
|
||||
error = ctl_be_block_modify(softc, lun_req);
|
||||
break;
|
||||
default:
|
||||
lun_req->status = CTL_LUN_ERROR;
|
||||
snprintf(lun_req->error_str, sizeof(lun_req->error_str),
|
||||
@ -1321,7 +1334,10 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
|
||||
|
||||
file_data->cred = crhold(curthread->td_ucred);
|
||||
be_lun->size_bytes = vattr.va_size;
|
||||
if (params->lun_size_bytes != 0)
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
else
|
||||
be_lun->size_bytes = vattr.va_size;
|
||||
/*
|
||||
* We set the multi thread flag for file operations because all
|
||||
* filesystems (in theory) are capable of allowing multiple readers
|
||||
@ -1446,16 +1462,28 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
curthread);
|
||||
if (error) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: error %d returned for DIOCGMEDIASIZE ioctl "
|
||||
"on %s!", __func__, error, be_lun->dev_path);
|
||||
"%s: error %d returned for DIOCGMEDIASIZE "
|
||||
" ioctl on %s!", __func__, error,
|
||||
be_lun->dev_path);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (params->lun_size_bytes != 0) {
|
||||
if (params->lun_size_bytes > be_lun->size_bytes) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: requested LUN size %ju > backing device "
|
||||
"size %ju", __func__,
|
||||
(uintmax_t)params->lun_size_bytes,
|
||||
(uintmax_t)be_lun->size_bytes);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ctl_be_block_close(struct ctl_be_block_lun *be_lun)
|
||||
{
|
||||
@ -1599,7 +1627,6 @@ ctl_be_block_open(struct ctl_be_block_softc *softc,
|
||||
be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2007,6 +2034,155 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
|
||||
struct ctl_lun_req *req)
|
||||
{
|
||||
struct vattr vattr;
|
||||
int error;
|
||||
struct ctl_lun_modify_params *params;
|
||||
|
||||
params = &req->reqdata.modify;
|
||||
|
||||
if (params->lun_size_bytes != 0) {
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
} else {
|
||||
error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
|
||||
if (error != 0) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"error calling VOP_GETATTR() for file %s",
|
||||
be_lun->dev_path);
|
||||
return (error);
|
||||
}
|
||||
|
||||
be_lun->size_bytes = vattr.va_size;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
|
||||
struct ctl_lun_req *req)
|
||||
{
|
||||
struct cdev *dev;
|
||||
struct cdevsw *devsw;
|
||||
int error;
|
||||
struct ctl_lun_modify_params *params;
|
||||
uint64_t size_bytes;
|
||||
|
||||
params = &req->reqdata.modify;
|
||||
|
||||
dev = be_lun->vn->v_rdev;
|
||||
devsw = dev->si_devsw;
|
||||
if (!devsw->d_ioctl) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: no d_ioctl for device %s!", __func__,
|
||||
be_lun->dev_path);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
|
||||
(caddr_t)&size_bytes, FREAD,
|
||||
curthread);
|
||||
if (error) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: error %d returned for DIOCGMEDIASIZE ioctl "
|
||||
"on %s!", __func__, error, be_lun->dev_path);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (params->lun_size_bytes != 0) {
|
||||
if (params->lun_size_bytes > size_bytes) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: requested LUN size %ju > backing device "
|
||||
"size %ju", __func__,
|
||||
(uintmax_t)params->lun_size_bytes,
|
||||
(uintmax_t)size_bytes);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
} else {
|
||||
be_lun->size_bytes = size_bytes;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
{
|
||||
struct ctl_lun_modify_params *params;
|
||||
struct ctl_be_block_lun *be_lun;
|
||||
int vfs_is_locked, error;
|
||||
|
||||
params = &req->reqdata.modify;
|
||||
|
||||
mtx_lock(&softc->lock);
|
||||
|
||||
be_lun = NULL;
|
||||
|
||||
STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
|
||||
if (be_lun->ctl_be_lun.lun_id == params->lun_id)
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&softc->lock);
|
||||
|
||||
if (be_lun == NULL) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: LUN %u is not managed by the block backend",
|
||||
__func__, params->lun_id);
|
||||
goto bailout_error;
|
||||
}
|
||||
|
||||
if (params->lun_size_bytes != 0) {
|
||||
if (params->lun_size_bytes < be_lun->blocksize) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: LUN size %ju < blocksize %u", __func__,
|
||||
params->lun_size_bytes, be_lun->blocksize);
|
||||
goto bailout_error;
|
||||
}
|
||||
}
|
||||
|
||||
vfs_is_locked = VFS_LOCK_GIANT(be_lun->vn->v_mount);
|
||||
vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
|
||||
|
||||
if (be_lun->vn->v_type == VREG)
|
||||
error = ctl_be_block_modify_file(be_lun, req);
|
||||
else
|
||||
error = ctl_be_block_modify_dev(be_lun, req);
|
||||
|
||||
VOP_UNLOCK(be_lun->vn, 0);
|
||||
VFS_UNLOCK_GIANT(vfs_is_locked);
|
||||
|
||||
if (error != 0)
|
||||
goto bailout_error;
|
||||
|
||||
be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
|
||||
|
||||
/*
|
||||
* The maximum LBA is the size - 1.
|
||||
*
|
||||
* XXX: Note that this field is being updated without locking,
|
||||
* which might cause problems on 32-bit architectures.
|
||||
*/
|
||||
be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
|
||||
ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
|
||||
|
||||
/* Tell the user the exact size we ended up using */
|
||||
params->lun_size_bytes = be_lun->size_bytes;
|
||||
|
||||
req->status = CTL_LUN_OK;
|
||||
|
||||
return (0);
|
||||
|
||||
bailout_error:
|
||||
req->status = CTL_LUN_ERROR;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_be_block_lun_shutdown(void *be_lun)
|
||||
{
|
||||
|
@ -1,7 +1,11 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2008 Silicon Graphics International Corp.
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by Edward Tomasz Napierala
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -102,6 +106,8 @@ static int ctl_backend_ramdisk_rm(struct ctl_be_ramdisk_softc *softc,
|
||||
struct ctl_lun_req *req);
|
||||
static int ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
struct ctl_lun_req *req, int do_wait);
|
||||
static int ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
|
||||
struct ctl_lun_req *req);
|
||||
static void ctl_backend_ramdisk_lun_shutdown(void *be_lun);
|
||||
static void ctl_backend_ramdisk_lun_config_status(void *be_lun,
|
||||
ctl_lun_config_status status);
|
||||
@ -376,6 +382,9 @@ ctl_backend_ramdisk_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
|
||||
case CTL_LUNREQ_RM:
|
||||
retval = ctl_backend_ramdisk_rm(softc, lun_req);
|
||||
break;
|
||||
case CTL_LUNREQ_MODIFY:
|
||||
retval = ctl_backend_ramdisk_modify(softc, lun_req);
|
||||
break;
|
||||
default:
|
||||
lun_req->status = CTL_LUN_ERROR;
|
||||
snprintf(lun_req->error_str, sizeof(lun_req->error_str),
|
||||
@ -666,6 +675,73 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
|
||||
struct ctl_lun_req *req)
|
||||
{
|
||||
struct ctl_be_ramdisk_lun *be_lun;
|
||||
struct ctl_lun_modify_params *params;
|
||||
uint32_t blocksize;
|
||||
|
||||
params = &req->reqdata.modify;
|
||||
|
||||
be_lun = NULL;
|
||||
|
||||
mtx_lock(&softc->lock);
|
||||
STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
|
||||
if (be_lun->ctl_be_lun.lun_id == params->lun_id)
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&softc->lock);
|
||||
|
||||
if (be_lun == NULL) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: LUN %u is not managed by the ramdisk backend",
|
||||
__func__, params->lun_id);
|
||||
goto bailout_error;
|
||||
}
|
||||
|
||||
if (params->lun_size_bytes == 0) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: LUN size \"auto\" not supported "
|
||||
"by the ramdisk backend", __func__);
|
||||
goto bailout_error;
|
||||
}
|
||||
|
||||
blocksize = be_lun->ctl_be_lun.blocksize;
|
||||
|
||||
if (params->lun_size_bytes < blocksize) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"%s: LUN size %ju < blocksize %u", __func__,
|
||||
params->lun_size_bytes, blocksize);
|
||||
goto bailout_error;
|
||||
}
|
||||
|
||||
be_lun->size_blocks = params->lun_size_bytes / blocksize;
|
||||
be_lun->size_bytes = be_lun->size_blocks * blocksize;
|
||||
|
||||
/*
|
||||
* The maximum LBA is the size - 1.
|
||||
*
|
||||
* XXX: Note that this field is being updated without locking,
|
||||
* which might cause problems on 32-bit architectures.
|
||||
*/
|
||||
be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
|
||||
ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
|
||||
|
||||
/* Tell the user the exact size we ended up using */
|
||||
params->lun_size_bytes = be_lun->size_bytes;
|
||||
|
||||
req->status = CTL_LUN_OK;
|
||||
|
||||
return (0);
|
||||
|
||||
bailout_error:
|
||||
req->status = CTL_LUN_ERROR;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_backend_ramdisk_lun_shutdown(void *be_lun)
|
||||
{
|
||||
|
@ -454,6 +454,11 @@ ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
|
||||
asc = 0x2A;
|
||||
ascq = 0x06;
|
||||
break;
|
||||
case CTL_UA_CAPACITY_CHANGED:
|
||||
/* 2Ah/09n CAPACITY DATA HAS CHANGED */
|
||||
asc = 0x2A;
|
||||
ascq = 0x09;
|
||||
break;
|
||||
default:
|
||||
ua_to_build = CTL_UA_NONE;
|
||||
return (ua_to_build);
|
||||
|
@ -397,7 +397,8 @@ struct ctl_be_arg {
|
||||
|
||||
typedef enum {
|
||||
CTL_LUNREQ_CREATE,
|
||||
CTL_LUNREQ_RM
|
||||
CTL_LUNREQ_RM,
|
||||
CTL_LUNREQ_MODIFY,
|
||||
} ctl_lunreq_type;
|
||||
|
||||
|
||||
@ -470,6 +471,20 @@ struct ctl_lun_rm_params {
|
||||
uint32_t lun_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* LUN modification parameters:
|
||||
*
|
||||
* lun_id: The number of the LUN to modify. This must be set.
|
||||
* The LUN must be backed by the given backend.
|
||||
*
|
||||
* lun_size_bytes: The size of the LUN in bytes. If zero, update
|
||||
* the size using the backing file size, if possible.
|
||||
*/
|
||||
struct ctl_lun_modify_params {
|
||||
uint32_t lun_id;
|
||||
uint64_t lun_size_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
* Union of request type data. Fill in the appropriate union member for
|
||||
* the request type.
|
||||
@ -477,6 +492,7 @@ struct ctl_lun_rm_params {
|
||||
union ctl_lunreq_data {
|
||||
struct ctl_lun_create_params create;
|
||||
struct ctl_lun_rm_params rm;
|
||||
struct ctl_lun_modify_params modify;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -14,8 +14,8 @@ CFLAGS+= -I${SDIR}
|
||||
WARNS?= 3
|
||||
.endif
|
||||
|
||||
DPADD= ${LIBCAM} ${LIBSBUF}
|
||||
LDADD= -lcam -lsbuf -lbsdxml
|
||||
DPADD= ${LIBCAM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL}
|
||||
LDADD= -lcam -lsbuf -lbsdxml -lutil
|
||||
MAN= ctladm.8
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -34,7 +34,7 @@
|
||||
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 8, 2011
|
||||
.Dd March 6, 2012
|
||||
.Dt CTLADM 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -173,6 +173,11 @@
|
||||
.Aq Fl l Ar lun_id
|
||||
.Op Fl o Ar name=value
|
||||
.Nm
|
||||
.Ic modify
|
||||
.Aq Fl b Ar backend
|
||||
.Aq Fl l Ar lun_id
|
||||
.Aq Fl s Ar size_bytes
|
||||
.Nm
|
||||
.Ic devlist
|
||||
.Op Fl b Ar backend
|
||||
.Op Fl v
|
||||
@ -830,6 +835,27 @@ Multiple
|
||||
arguments may be specified.
|
||||
Refer to the backend documentation for arguments that may be used.
|
||||
.El
|
||||
.It Ic modify
|
||||
Modify a LUN size.
|
||||
The backend, the LUN number, and the size must be specified.
|
||||
.Bl -tag -width 14n
|
||||
.It Fl b Ar backend
|
||||
Specify the backend that owns the LUN to be removed.
|
||||
Examples are
|
||||
.Dq ramdisk
|
||||
and
|
||||
.Dq block .
|
||||
.It Fl l Ar lun_id
|
||||
Specify the LUN number to remove.
|
||||
.It Fl s Ar size_bytes
|
||||
Specify the size of the LUN in bytes.
|
||||
For the
|
||||
.Dq block
|
||||
backend, an
|
||||
.Dq auto
|
||||
keyword may be passed instead; this will make CTL use the size of backing
|
||||
file or device.
|
||||
.El
|
||||
.It Ic devlist
|
||||
Get a list of all configured LUNs.
|
||||
This also includes the LUN size and blocksize, serial number and device ID.
|
||||
|
@ -1,8 +1,12 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Silicon Graphics International Corp.
|
||||
* Copyright (c) 1997-2007 Kenneth D. Merry
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by Edward Tomasz Napierala
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -68,6 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_scsi_all.h>
|
||||
#include <camlib.h>
|
||||
#include <libutil.h>
|
||||
#include "ctladm.h"
|
||||
|
||||
#ifdef min
|
||||
@ -110,7 +115,8 @@ typedef enum {
|
||||
CTLADM_CMD_PRES_IN,
|
||||
CTLADM_CMD_PRES_OUT,
|
||||
CTLADM_CMD_INQ_VPD_DEVID,
|
||||
CTLADM_CMD_RTPG
|
||||
CTLADM_CMD_RTPG,
|
||||
CTLADM_CMD_MODIFY
|
||||
} ctladm_cmdfunction;
|
||||
|
||||
typedef enum {
|
||||
@ -175,6 +181,7 @@ struct ctladm_opts option_table[] = {
|
||||
{"inquiry", CTLADM_CMD_INQUIRY, CTLADM_ARG_NEED_TL, NULL},
|
||||
{"lunlist", CTLADM_CMD_LUNLIST, CTLADM_ARG_NONE, NULL},
|
||||
{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
|
||||
{"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:s:"},
|
||||
{"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:p:qt:w:W:x"},
|
||||
{"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"},
|
||||
{"prout", CTLADM_CMD_PRES_OUT, CTLADM_ARG_NEED_TL, "a:k:r:s:"},
|
||||
@ -249,6 +256,7 @@ static int cctl_create_lun(int fd, int argc, char **argv, char *combinedopt);
|
||||
static int cctl_inquiry_vpd_devid(int fd, int target, int lun, int initiator);
|
||||
static int cctl_report_target_port_group(int fd, int target, int lun,
|
||||
int initiator);
|
||||
static int cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt);
|
||||
|
||||
ctladm_optret
|
||||
getoption(struct ctladm_opts *table, char *arg, uint32_t *cmdnum,
|
||||
@ -3045,7 +3053,15 @@ cctl_create_lun(int fd, int argc, char **argv, char *combinedopt)
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
lun_size = strtoull(optarg, NULL, 0);
|
||||
if (strcasecmp(optarg, "auto") != 0) {
|
||||
retval = expand_number(optarg, &lun_size);
|
||||
if (retval != 0) {
|
||||
warn("%s: invalid -s argument",
|
||||
__func__);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
lun_size_set = 1;
|
||||
break;
|
||||
case 'S':
|
||||
@ -3289,12 +3305,12 @@ cctl_rm_lun(int fd, int argc, char **argv, char *combinedopt)
|
||||
}
|
||||
|
||||
if (req.status == CTL_LUN_ERROR) {
|
||||
warnx("%s: error returned from LUN creation request:\n%s",
|
||||
warnx("%s: error returned from LUN removal request:\n%s",
|
||||
__func__, req.error_str);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
} else if (req.status != CTL_LUN_OK) {
|
||||
warnx("%s: unknown LUN creation request status %d",
|
||||
warnx("%s: unknown LUN removal request status %d",
|
||||
__func__, req.status);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
@ -3306,6 +3322,84 @@ cctl_rm_lun(int fd, int argc, char **argv, char *combinedopt)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt)
|
||||
{
|
||||
struct ctl_lun_req req;
|
||||
uint64_t lun_size = 0;
|
||||
uint32_t lun_id = 0;
|
||||
int lun_id_set = 0, lun_size_set = 0;
|
||||
char *backend_name = NULL;
|
||||
int retval = 0, c;
|
||||
|
||||
while ((c = getopt(argc, argv, combinedopt)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
backend_name = strdup(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
lun_id = strtoul(optarg, NULL, 0);
|
||||
lun_id_set = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (strcasecmp(optarg, "auto") != 0) {
|
||||
retval = expand_number(optarg, &lun_size);
|
||||
if (retval != 0) {
|
||||
warn("%s: invalid -s argument",
|
||||
__func__);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
lun_size_set = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (backend_name == NULL)
|
||||
errx(1, "%s: backend name (-b) must be specified", __func__);
|
||||
|
||||
if (lun_id_set == 0)
|
||||
errx(1, "%s: LUN id (-l) must be specified", __func__);
|
||||
|
||||
if (lun_size_set == 0)
|
||||
errx(1, "%s: size (-s) must be specified", __func__);
|
||||
|
||||
bzero(&req, sizeof(req));
|
||||
|
||||
strlcpy(req.backend, backend_name, sizeof(req.backend));
|
||||
req.reqtype = CTL_LUNREQ_MODIFY;
|
||||
|
||||
req.reqdata.modify.lun_id = lun_id;
|
||||
req.reqdata.modify.lun_size_bytes = lun_size;
|
||||
|
||||
if (ioctl(fd, CTL_LUN_REQ, &req) == -1) {
|
||||
warn("%s: error issuing CTL_LUN_REQ ioctl", __func__);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
if (req.status == CTL_LUN_ERROR) {
|
||||
warnx("%s: error returned from LUN modification request:\n%s",
|
||||
__func__, req.error_str);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
} else if (req.status != CTL_LUN_OK) {
|
||||
warnx("%s: unknown LUN modification request status %d",
|
||||
__func__, req.status);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
printf("LUN %d modified successfully\n", lun_id);
|
||||
|
||||
bailout:
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Name/value pair used for per-LUN attributes.
|
||||
*/
|
||||
@ -3601,6 +3695,7 @@ usage(int error)
|
||||
" [-l lun_id] [-o name=value] [-s size_bytes]\n"
|
||||
" [-S serial_num] [-t dev_type]\n"
|
||||
" ctladm remove <-b backend> <-l lun_id> [-o name=value]\n"
|
||||
" ctladm modify <-b backend> <-l lun_id> <-s size_bytes>\n"
|
||||
" ctladm devlist [-b][-v][-x]\n"
|
||||
" ctladm shutdown\n"
|
||||
" ctladm startup\n"
|
||||
@ -3987,6 +4082,9 @@ main(int argc, char **argv)
|
||||
case CTLADM_CMD_RTPG:
|
||||
retval = cctl_report_target_port_group(fd, target, lun, initid);
|
||||
break;
|
||||
case CTLADM_CMD_MODIFY:
|
||||
retval = cctl_modify_lun(fd, argc, argv, combinedopt);
|
||||
break;
|
||||
case CTLADM_CMD_HELP:
|
||||
default:
|
||||
usage(retval);
|
||||
|
Loading…
Reference in New Issue
Block a user