svn commit: r237821 - in stable/9: sys/cam/ctl usr.sbin/ctladm

Kenneth D. Merry ken at FreeBSD.org
Fri Jun 29 21:19:25 UTC 2012


Author: ken
Date: Fri Jun 29 21:19:24 2012
New Revision: 237821
URL: http://svn.freebsd.org/changeset/base/237821

Log:
  MFC r232604:
    r232604 | trasz | 2012-03-06 06:43:57 -0700 (Tue, 06 Mar 2012) | 6 lines
  
    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

Modified:
  stable/9/sys/cam/ctl/ctl.c
  stable/9/sys/cam/ctl/ctl.h
  stable/9/sys/cam/ctl/ctl_backend.h
  stable/9/sys/cam/ctl/ctl_backend_block.c
  stable/9/sys/cam/ctl/ctl_backend_ramdisk.c
  stable/9/sys/cam/ctl/ctl_error.c
  stable/9/sys/cam/ctl/ctl_ioctl.h
  stable/9/usr.sbin/ctladm/Makefile
  stable/9/usr.sbin/ctladm/ctladm.8
  stable/9/usr.sbin/ctladm/ctladm.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/usr.sbin/ctladm/   (props changed)

Modified: stable/9/sys/cam/ctl/ctl.c
==============================================================================
--- stable/9/sys/cam/ctl/ctl.c	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl.c	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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
 	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.

Modified: stable/9/sys/cam/ctl/ctl.h
==============================================================================
--- stable/9/sys/cam/ctl/ctl.h	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl.h	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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

Modified: stable/9/sys/cam/ctl/ctl_backend.h
==============================================================================
--- stable/9/sys/cam/ctl/ctl_backend.h	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl_backend.h	Fri Jun 29 21:19:24 2012	(r237821)
@@ -280,6 +280,11 @@ int ctl_lun_power_lock(struct ctl_be_lun
 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_ */
 

Modified: stable/9/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- stable/9/sys/cam/ctl/ctl_backend_block.c	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl_backend_block.c	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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 ct
 			       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_l
 		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_blo
 
 
 	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,15 +1462,27 @@ ctl_be_block_open_dev(struct ctl_be_bloc
 			       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);
 	}
 
-	return (0);
+	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_so
 	be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
 
 	return (0);
-
 }
 
 static int
@@ -2007,6 +2034,155 @@ bailout_error:
 	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)
 {

Modified: stable/9/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- stable/9/sys/cam/ctl/ctl_backend_ramdisk.c	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl_backend_ramdisk.c	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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
 				  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 *d
 		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 @@ bailout_error:
 	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)
 {

Modified: stable/9/sys/cam/ctl/ctl_error.c
==============================================================================
--- stable/9/sys/cam/ctl/ctl_error.c	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl_error.c	Fri Jun 29 21:19:24 2012	(r237821)
@@ -454,6 +454,11 @@ ctl_build_ua(ctl_ua_type ua_type, struct
 		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);

Modified: stable/9/sys/cam/ctl/ctl_ioctl.h
==============================================================================
--- stable/9/sys/cam/ctl/ctl_ioctl.h	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/sys/cam/ctl/ctl_ioctl.h	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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;
 
 
@@ -471,12 +472,27 @@ struct ctl_lun_rm_params {
 };
 
 /*
+ * 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.
  */
 union ctl_lunreq_data {
 	struct ctl_lun_create_params	create;
 	struct ctl_lun_rm_params	rm;
+	struct ctl_lun_modify_params	modify;
 };
 
 /*

Modified: stable/9/usr.sbin/ctladm/Makefile
==============================================================================
--- stable/9/usr.sbin/ctladm/Makefile	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/usr.sbin/ctladm/Makefile	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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>

Modified: stable/9/usr.sbin/ctladm/ctladm.8
==============================================================================
--- stable/9/usr.sbin/ctladm/ctladm.8	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/usr.sbin/ctladm/ctladm.8	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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.

Modified: stable/9/usr.sbin/ctladm/ctladm.c
==============================================================================
--- stable/9/usr.sbin/ctladm/ctladm.c	Fri Jun 29 20:15:00 2012	(r237820)
+++ stable/9/usr.sbin/ctladm/ctladm.c	Fri Jun 29 21:19:24 2012	(r237821)
@@ -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 a
 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,
@@ -3043,7 +3051,15 @@ cctl_create_lun(int fd, int argc, char *
 			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':
@@ -3287,12 +3303,12 @@ cctl_rm_lun(int fd, int argc, char **arg
 	}
 
 	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;
@@ -3304,6 +3320,84 @@ bailout:
 	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.
  */
@@ -3599,6 +3693,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"
@@ -3983,6 +4078,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);


More information about the svn-src-all mailing list