Shrink Aggregate

Purpose

Reduces the physical size of a zFS aggregate.

Format

syscall_parmlist
   opcode            int                     266   AGOP_SHRINK_PARMDATA
   parms[0]          int                     offset to SH_REQ
   parms[1]          int                     0
   parms[2]          int                     0
   parms[3]          int                     0
   parms[4]          int                     0
   parms[5]          int                     0
   parms[6]          int                     0

SH_REQ
   sh_eye            char[4]                 "SHRQ"
   sh_len            short                   sizeof(SH_REQ)
   sh_ver            char                    1
   sh_flags          char                    Shrink flags with values:
                                               0 - No options specified.
                                               1 - Active increase not allowed.
                                               2 - Do not wait for shrink
                                                   completion.
   sh_length         unsigned long long int  New total size (in 1K units)
   sh_name           char[45]                Name of aggregate to shrink.
   sh_command        char                    Shrink operation to perform:
                                               1 - Start a shrink.
                                               2 - Cancel an active shrink.
   sh_reserved       char[66]                Reserved.

Shrink API return codes:

   EPERM   User does not have permission to perform shrink
   ENOENT  No aggregate by this name is found
   EROFS   Aggregate is mounted readonly
   EIO     General errors processing the shrink operation
   EFBIG   Aggregate size request does not make sense (bigger
           than existing aggregate or active increase gets back to original
           aggregate size)
   EMVSERR Internal error
   EBUSY   Aggregate is busy or otherwise unavailable, or no
           long running threads available
   EINVAL  Invalid parameters
   ENFILE  Error releasing space from the data set
   ENOSYS  zFS owner goes down before a shrink command completes
   EINTR   Shrink command canceled

Usage notes for Shrink Aggregate

  1. The aggregate must be mounted.
  2. Reserved fields and undefined flags must be set to binary zeros.
  3. A long-running command foreground thread must be available.
  4. A shrink operation can be interrupted by a shutdown, unmount with the force option, or a zfsadm shrink command with the -cancel option specified.
  5. The difference between the new total size of the aggregate and the current size of the aggregate cannot be larger than the free space in the aggregate.
  6. Most of the shrink operation will allow other applications to access file and directory blocks during the shrink operation, which might cause additional blocks to be allocated. If this allocation causes more space to be needed in the aggregate than the new total size specified in -size, zFS will actively increase the new total size by adding 1 M to the new total size. The shrink command will end with an error if the size is actively increased back to the original size of the aggregate. You can prevent active increase by specifying -noai. If -noai is specified, and an active increase is needed, the shrink command will end with an error.
  7. Both the FSINFO command and the List Detailed File System Information service have progress indicators that show the current step of the shrink operation. The progress indicators can be seen when owner information is requested.

Privilege required

The user must have UPDATE authority to the VSAM linear data set.

Related services

  • Grow Aggregate
  • List Detailed File System Information

Restrictions

None.

Examples

#pragma linkage(BPX1PCT, OS)
#pragma LANGLVL(EXTENDED)

extern void BPX1PCT(char *, int, int, char *, int *, int *, int *);

#include <stdio.h>

#define ZFSCALL_AGGR 0x40000005
#define AGOP_SHRINK_PARMDATA 266    /* shrink specified aggregate */

typedef struct syscall_parmlist_
{
  int opcode;   /* Operation code to perform */
  int parms[7]; /* Specific to type of operation, */
                /* provides access to the parms */
} syscall_parmlist;

#define ZFS_MAX_AGGRNAME 44
#define SHR_EYE "SHRQ"
#define SHR_VER_INITIAL 1
#define SHR_NO_ACTIVE_INCREASE 0x01   /* active increase should not be used */
#define SHR_ASYNC              0x02   /* do not wait for shrink to complete */
#define SHR_START_SHRINK       1      /* start a shrink operation if one    */
                                      /*  not already in progress           */
#define SHR_STOP_SHRINK        2      /* stop a shrink operation that is    */
                                      /*  already in progress               */
#define SHR_RESERVED_LEN       66

typedef struct shrink_req_t
{
  char    sh_eye[4];                      /* eyecatcher "SHRQ"              */
  short   sh_len;                         /* sizeof SH_REQ                  */
  char    sh_ver;                         /* 1                              */
  char    sh_flags;                       /* 1=no active increase, 2=async  */
  unsigned long long int sh_length;       /* New length of aggregate        */
                                          /*   (in 1K units)                */
  char    sh_name[ZFS_MAX_AGGRNAME+1];    /* NULL terminated aggregate name */
  char    sh_command;                     /* 1=start shrink 2=stop shrink   */
  char    sh_reserved[SHR_RESERVED_LEN];  /* reserved must be 0             */
} SH_REQ;

struct parmstruct {
  syscall_parmlist myparms;
  SH_REQ shreq;
};

int main(int argc, char **argv)
{
  int bpxrv;
  int bpxrc;
  int bpxrs;
  struct parmstruct myparmstruct;
  char aggrname[45] = "ZFSAGGR.BIGZFS.DHH.FS1.EXTATTR";
  SH_REQ *reqp = &(myparmstruct.shreq);
  myparmstruct.myparms.opcode = AGOP_SHRINK_PARMDATA;
  myparmstruct.myparms.parms[0] = sizeof(syscall_parmlist);
  myparmstruct.myparms.parms[1] = 0;
  myparmstruct.myparms.parms[2] = 0;
  myparmstruct.myparms.parms[3] = 0;
  myparmstruct.myparms.parms[4] = 0;
  myparmstruct.myparms.parms[5] = 0;
  myparmstruct.myparms.parms[6] = 0;

  /* Ensure reserved fields are 0 */
  memset(&myparmstruct.shreq, 0, sizeof(SH_REQ));

  /* Set fields to shrink aggregate, and not wait for it to complete.   */
  /* Since the aggregate is being used, we will allow active increase   */
  /* so that running tasks will not run out of space if they need more  */
  /* than originally anticipated.                                       */
  memcpy(&myparmstruct.shreq.sh_eye, SHR_EYE, 4);
  myparmstruct.shreq.sh_len = sizeof(SH_REQ);
  myparmstruct.shreq.sh_ver = SHR_VER_INITIAL;
  strcpy(myparmstruct.shreq.sh_name, aggrname);
  myparmstruct.shreq.sh_flags = SHR_ASYNC;
  myparmstruct.shreq.sh_command = SHR_START_SHRINK;
  /* Using 1K units, 8388704 is just over an 8G aggregate as a new length. */
  myparmstruct.shreq.sh_length = 8388704;

  BPX1PCT("ZFS     ",            /* must be blank padded to length 8 */
          ZFSCALL_AGGR,          /* Aggregate operation */
          sizeof(myparmstruct),  /* Length of Argument */
          (char *)&myparmstruct, /* Pointer to Argument */
          &bpxrv,                /* Pointer to Return_value */
          &bpxrc,                /* Pointer to Return_code */
          &bpxrs);               /* Pointer to Reason_code */
  if (bpxrv < 0)
  {
    printf("Error trying to shrink aggregate %s\n", aggrname);
    printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", bpxrv, bpxrc, bpxrs);
    return bpxrc;
  }
  else /* Return from change aggregate attributes was successful */
    printf("Shrink of aggregate %s started.\n", aggrname);

  return 0;
}