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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to