Start of change

List Detailed File System Information

Purpose

Start of changeReturns detailed information for one or more file systems. It offers the ability to get information for file systems that have common names, common attributes, or that have encountered similar unexpected conditions.End of change

Start of changeIBM recommends that you use the List Detailed File System Information API instead of List Aggregate Status, List File System Status, List File System Names (Version 1) or List File System Names (Version 2).End of change

Format

syscall_parmlist
  opcode             int             153    AGOP_FSINFO_PARMDATA
                                     154    AGOP_FSINFO_RESET_PARMDATA
  parms[0]           int             offset to FSINFO_REQUEST
  parms[1]           int             0
  parms[2]           int             0
  parms[3]           int             0
  parms[4]           int             0
  parms[5]           int             0
  parms[6]           int             0
                                    
FSINFO_REQUEST                      
  fr_eye             char[4]         "FIRQ"
  fr_length          short           Length of Structure
  fr_sversion        char            Structure Version, must be 1
  fr_reqtype         char            SingleQuery=0, NameCursor=1
  fr_version         char            Version of input/output
                                      buffer, must be 1
  fr_output          char            Type of output/function selected, one of:
                                      0 - Local statistics only, use only local
                                          cache. Only allowed with
                                          fr_nameSelection=2.
                                      1 - Full sysplex-wide statistics
                                          (including owner statistics).
                                      2 - Reset statistics.
  fr_nameSelection   char            Selection of aggregates desired, one of:
                                      0 - When SingleQuery selected.
                                     Options for fr_reqtype=1 (NameCursor):
                                      1 - All aggregates. fr_output can be
                                          1 (full) or 2 (reset).
                                      2 - Aggregates known on the local system.
                                          This is only allowed with fr_output
                                          0 (local statistics).
                                      3 - All aggregates matching a specific
                                          pattern provided in fr_patternName.
                                          fr_output can be 1 (full) or
                                          2 (reset).
  fr_eol             char            Indicates if a multi-aggregate read has
                                      completed. 1 if yes, 0 if no.
  fr_selection       int             Selection mask for aggregates meeting
                                      certain state criteria. More than one bit
                                      can be set. Note zFS will use an OR-ing
                                      of the criteria so that aggregates that
                                      meet one or more criteria are returned.
                                      0 - all aggregates desired.
                                      x1 - Show aggregates that have sysplex
                                           thrashing objects.
                                      x2 - Show aggregates that contain v5
                                           directories with overflow pages.
                                      x4 - Show aggregates mounted R/W.
                                      x8 - Show aggregates mounted R/O.
                                      x10 - Show aggregates that are disabled.
                                      x20 - Show aggregates that are growing.
                                      x40 - Show aggregates that are quiesced.
                                      x80 - Show aggregates that had grow
                                            failures.
                                      x100 - Show aggregates that are low on
                                             space, as defined by the zFS
                                             bitmap manager.
                                      x200 - Show aggregates that are damaged.
                                      x400 - Show aggregates that are mounted
                                             RWSHARE.
                                      x800 - Show aggregates that are mounted
                                             NORWSHARE.
                                      x1000 - Show aggregates that had requests
                                      x2000 - Show aggregates that had write
                                              requests.
                                      x4000 - Show aggregates where applications
                                              saw ENOSPC errors.
                                      x8000 - Show aggregates that had disk I/O
                                              errors.
                                      x10000 - Show aggregates that had XCF
                                               timeouts between client systems
                                               and owning systems (for RWSHARE
                                               aggregates).
                                      x20000 - Show aggregates that are version
                                               1.4 aggregates.
                                      x40000 - Show aggregates that are version
                                               1.5 aggregates.
                                      x80000 - Show aggregates that are
                                               disabled for dynamic grow.
                                      x100000 - Show aggregates that are
                                                disabled for conversion to
                                                version 1.5.
                                      x80000000 - Tells zFS to use an AND-ing
                                                  method of examining criteria.
                                                  Hence only aggregates meeting
                                                  all criteria will be returned.
                                      x801FFFFF - Represents all valid bits.
  fr_entries         unsigned int    Number of aggregatess returned in output.
  fr_nonFatalRc      int             Non-fatal error code.
  fr_nonFatalRsn     int             Reason code if fr_nonFatalRc is non-zero.
  fr_resumeName      char[45]        Dataset name to resume with for NameCursor
                                      or the name of a single-aggregate query.
  fr_patternName     char[45]        The aggregate name to be used. This can
                                      contain wildcards.
  fr_future2         char[2]         For future use (reserved).
FSINFO_NAME
  fn_eye             char[4]         "FINA"
  fn_slength         short           Structure length.
  fn_sversion        short           Structure version, must be 1.
  fn_name            char[44]        Aggregate name.
  fn_connected       unsigned int    Number of connected systems if owner
                                      output is requested; 0 otherwise.
  fn_owner           char[8]         System name of the owner.
  fn_length          unsigned int    Total length of all information for this
                                     aggregate.
  fn_future          char[4]         For future use (reserved).
  fn_sysnames        char[8]         Names of connected systems (32 at most).

FSINFO_OWNER
  fo_eye             char[4]         "FIOW"
  fo_length          short           Length of structure
  fo_sversion        short           Structure version, must be 1.
  fo_size            unsigned int    Number of 8K blocks in the aggregate.
  fo_free            unsigned int    Number of unused 8K blocks in the
                                      aggregate.
  fo_frags           unsigned long long int  Number of free 1K fragments
                                              available in the aggregate.
  fo_logsize         unsigned int    Number of 8K blocks allocated to the log
                                      file for transaction logging, including
                                      indirect blocks.
  fo_bitmapsize      unsigned int    Number of 8K blocks allocated to the
                                      bitmap file, including indirect blocks.
  fo_anodesize       unsigned int    Number of 8K blocks allocated to the
                                      anode table.
  fo_objects         unsigned int    Number of objects in the file system.
  fo_version         char            Aggregate version number.
  fo_threshold       char            Space monitoring threshold.
  fo_increment       char            Space monitoring increment.
  reserved1          char            Reserved
  fo_flags           int             Flag bits:
                                      x01 - Mounted in R/W mode.
                                      x02 - Disabled for access.
                                      x04 - Grow failure occurred since
                                             last reset.
                                      x08 - Aggregate is low on space
                                             (zfs definition).
                                      x10 - Aggregate considered damaged by
                                             salvage verification and not
                                             repaired yet.
                                      x20 - Aggregage using zFS sysplex sharing
                                             (RWSHARE).
                                      x40 - Dynamic grow set at mount time.
                                      x80 - Aggregate is in the process of
                                             growing at time of query.
                                      x100 - converttov5 is set.
                                      x200 - Aggregate is not mounted.
                                      x400 - Aggregate is unowned.
                                      x800 - Dynamic grow allowed, no grow
                                              failures or since a grow failure
                                              an admin grow was done.
                                      x1000 - The quiesce is done for chgowner.
                                      x2000 - converttov5 disabled.
                                      x4000 - Aggregate version 1.4.
                                      x8000 - Aggregate version 1.5.
  
  fo_overflow        unsigned int    Number of overflow pages used in v5
                                      directories.
  fo_overflowhiwater unsigned int    Hi-water mark of fo_overflow for life of
                                      the file system.
  fo_thrashing       unsigned int    Current number of objects using the
                                      thrash-resolution protocol.
  reserved2          char[4]         Reserved.
  fo_thrash_resolution unsigned long long int  Number of thrash resolutions
                                                performed since last statistics
                                                reset.
  fo_revocations     unsigned long long int  Number of token revocations
                                              performed since last statistics
                                              reset.
  fo_revwait         unsigned long long int  Average revocation wait time in
                                              microseconds.
  fo_qsysname        char[8]         Name of system requesting quiesce, if the
                                      aggregate is quiesced, 0 otherwise.
  fo_jobname         char[8]         Name of job requesting the quiesce, if the
                                      aggregate is quiesced, 0 otherwise.
  fo_createtime      unsigned long long int  Creation time in seconds since
                                              last epoch.
  fo_ownership       unsigned long long int  Owership time in seconds since
                                              last epoch.
  fo_reset           unsigned long long int  Time statistic counters reset
                                              in seconds since last epoch.
  fo_quiesce         unsigned long long int  Quiesce time in seconds since
                                              epoch, 0 if not quiesced.
  fo_devno           unsigned int    z/OS UNIX device number.
  fo_auditfid        char[10]        Audit fid for file system.
  fo_qasid           unsigned short  ASID which issued the quiesce.
  fo_growcount       unsigned int    Number of grows since mount.
  reserved3          char[4]         Reserved.
  fo_growtime        unsigned long long int  Time of the last grow as known
                                              by the owner.

FSINFO_LOCAL
  fl_eye             char[4]                 "FILO"
  fl_length          short                   Structure Length.
  fl_sversion        short                   Structure version.
  fl_vnodes          unsigned long long int  Number of vnodes cached in
                                              memory on the local system.
  fl_ussheld         unsigned long long int  Number of vnodes held by USS.
  fl_sysname         char[8]                 System name stats are for.
  fl_open            unsigned long long int  Number of open objects in the
                                              file system.
  fl_tokens          unsigned long long int  Number of tokens held from the
                                              token manager.
  fl_usercache       unsigned int            Number of 4K pages held in the
                                              user cache for the file system.
  fl_metacache       unsigned int            Number of 8K pages held in the
                                              metadata cache.
  fl_appreads        unsigned long long int  Number of application reads
                                              done since last reset.
  fl_appreadresp     unsigned long long int  Average read response time,
                                              in microseconds.
  fl_appwrites       unsigned long long int  Number of application writes
                                              done since last reset.
  fl_appwriteresp    unsigned long long int  Average write response time,
                                              in microseconds.
 
  fl_xcfreads        unsigned long long int  Number of XCF read calls made
                                              to the owner since last reset.
  fl_xcfreadresp     unsigned long long int  Average XCF read call response
                                              time, in microseconds.
  fl_xcfwrites       unsigned long long int  Number of XCF write calls made
                                              to the server since last reset.
  fl_xcfwriteresp    unsigned long long int  Average XCF write call response
                                              time, in microseconds.
  fl_enospc          unsigned long long int  Number of ENOSPC errors
                                              returned to applications
                                              since last reset.
  fl_ioerrs          unsigned long long int  Number of disk I/O errors
                                              since last reset.
  fl_commerrs        unsigned long long int  Number of XCF communication
                                              timeouts or failures since last
                                              reset.
  fl_cancels         unsigned long long int  Number of cancelled operations
                                              since last reset by asynchronus
                                              abends, cancels, or forces.
  fl_ddname          char[8]                 DDNAME during allocation of
                                              aggregagte dataset.
  fl_mounttime       struct timeval64        Mount time in seconds since
                                              the last epoch.
  fl_numdasd         unsigned int            Number of DASD volumes listed
                                              for aggregate in FSINFO_DASD
                                              array.
  fl_flags           unsigned int            1 indicates this system has tasks
                                              waiting on a quiesced FS.

FSINFO_DASD
  fd_eye             char[4]                 "FIDA"
  fd_length          short                   Structure Length.
  fd_sversion        short                   Structure version, must be 1.
  fd_volser          char[6]                 Volume serial.
  fd_pavios          short                   Number of I/Os zFS will issue
                                              at one time for non-critical
                                              I/Os.
  fd_reads           unsigned long long int  Number of reads to this volume.
  fd_readbytes       unsigned long long int  Number of kilobytes read.
  fd_writes          unsigned long long int  Number of writes to this volume
  fd_writebytes      unsigned long long int  Number of kilobytes written.
  fd_waits           unsigned long long int  Number of times a zFS task had
                                              to wait for an I/O to this
                                              volume.
  fd_waitTime        unsigned long long int  (includes all time, queue wait,
                                             DASD response time etc.)
                                              since last reset.
  fd_resptime        unsigned long long int  Avg. wait time in microseconds.

Return_value      0 if request is successful, -1 if it is not successful

Return_code
  EINTR           zFS is shutting down
  EINVAL          Invalid parameter list
  EMVSERR         Internal error occurred
  E2BIG           Information too big for buffer supplied
  ENOENT          Specified data set is not found
  EPERM           Permission denied to perform request
Reason_code
  0xEFnnxxxx      See z/OS Distributed File Service Messages and Codes

Usage notes

  • Start of changeUsers of the API supply an input buffer that contains a syscall_parmlist followed by an FSINFO_REQUEST structure. Output will be placed in this buffer after the FSINFO_REQUEST.End of change
  • A minimum length output buffer for a single-aggregate query is 10 K, and a minimum length output buffer for a multi-aggregate query is 64 K.
  • A single specific aggregate can be queried by putting its name in fr_resumeName. The name must be null-terminated. Also specify fr_reqtype 0 (SingleQuery). This aggregate does not need to be attached. fr_selection and fr_nameSelection must also be 0.
  • Multiple aggregate names can be specified by entering a string in fr_patternName that can contain a wildcard character ('*'). A wildcard can be specified at the beginning, at the end, or both at the beginning and the end of the string. The string must be null-terminated. The input string is converted to uppercase before it is processed. Use a fr_nameSelection value of 3 when specifying a wildcard, and a fr_reqtype of NameCursor (1).
  • All attached aggregates can be specified by using fr_nameSelection value of 1 and a fr_reqtype value of NameCursor (1).
  • If the output buffer cannot hold all of the returned information, fr_eol will be 0 and fr_resumeName will contain a value to be returned to zFS on the next query. Keep querying zFS until fr_eol is 1 to indicate that all information has been returned.
  • Use fr_selection to return only aggregates that match the specified criteria in a multiple aggregate query. The options are defined in the Format section.
  • fr_output determines the output of the request. Options are defined in the Format section.
  • There is no file system information returned when a reset is requested (fr_output=2). A reset can only be requested when the opcode is 154 (AGOP_FSINFO_RESET_PARMDATA) and fr_selection is 0.
  • Reserved fields and undefined flags must be set to binary zeros.
  • Any names returned that are less than the full length of the field are null terminated. If the length of the name is equal to the length of the field that contains it, then it is not null terminated.
  • Output consists of various structures following the FSINFO_REQUEST area in the buffer. For each aggregate that has information returned, first will be an FSINFO_NAME structure. This contains the name of an aggregate and the systems that are connected to it. Then, if present, will be the FSINFO_OWNER structure. This contains aggregate statistics and attributes as known by the owner. There can be no FSINFO_OWNER in some cases when the aggregate is unowned (fn_owner is *UNOWNED). This is followed by FSINFO_LOCAL structures. There are fn_connected FSINFO_LOCAL structures (if it is unowned), otherwise there are fn_connected+1 FSINFO_LOCAL structures. Each FSINFO_LOCAL structure is followed by fl_numdasd FSINFO_DASD structures to describe the DASD volumes that contain the zFS aggregate data set.

Privilege required

Start of changeIf a reset of the statistics values is requested and the fr_output field of the FSINFO_REQUEST structure contains the value 2, the issuer must be UID 0 or have READ authority to the SUPERUSER.FILESYS.PFSCTL resource in the z/OS UNIXPRIV class. Otherwise, no privilege is required.End of change

Related services

  • List Aggregate Status (Version 1)
  • List Aggregate Status (Version 2)
  • List Attached Aggregate Names (Version 1)
  • List Attached Aggregate Names (Version 2)
  • List File System Names (Version 1)
  • List File System Names (Version 2)
  • List File System Status

Restrictions

None.

Examples

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

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

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>

#define ZFSCALL_FSINFO       0x40000013
#define ZFS_MAX_AGGRNAME     44
#define AGOP_FSINFO_PARMDATA 153 /* Get status on aggr & fs */
#define BUFFER_SIZE          1024 * 64

#define FSINFO_XCF_ERR       0x1
#define FSINFO_IO_ERR        0x2
#define FSINFO_SPC_ERR       0x4

typedef struct syscall_parmlist_t {
  int opcode;                  /* Operation code to perform */
  int parms[7];                /* Specific to type of operation, */
                               /* provides access to the parms */
                               /* parms[1]-parms[6] are currently unused*/
} syscall_parmlist;

struct timeval64 {
  uint64_t tv_sec;
  int32_t  tv_usec_pad;
  uint32_t tv_usec;
};

typedef struct FSINFO_REQUEST_t {
  char  fr_eye[4];
#define FR_EYE  "FIRQ"
  short fr_length;
  char  fr_sversion;             /* Structure version. must be 1 */
  char  fr_reqtype;              /*request type. BulkList=0, OffsetCursor=1*/
#define FR_REQTYPE_SINGLEQUERY 0
#define FR_REQTYPE_NAMECURSOR  1
  char  fr_version;              /* Version of input/output buffer; must be 1*/
  char  fr_output;               /* Type of output */
#define FR_OUT_LOCAL_STAT      0 /* Local stats from local system */
#define FR_OUT_FULL_STAT       1 /* Full stats from all systems*/
#define FR_OUT_RESET           2 /* reset statistics */
  char  fr_nameSelection;        /* Selection of aggregates desired, one of: */
#define FR_NM_ALLAGGR          1 /* All aggregates */
#define FR_NM_LOCAL            2 /* Local aggregates */
#define FR_NM_PATTERN          3 /* All aggregates matching pattern */
  char  fr_eol;                  /* Indicates if a multi-aggregate
                                    read has completed */
  int   fr_selection;            /* Selection criteria of aggregates desired */
  unsigned int   fr_entries;     /* Number of entries returned
                                    by zFS (for OffsetCusor) */
  int   fr_nonFatalRc;           /* Non-fatal error code */
  int   fr_nonFatalRsn;          /* Reason code if fr_nonFatalRc is non-0 */
  char  fr_resumeName[45];  /* Dataset name to resume with for NameCursor or */
                            /* the name for the single-aggregate query.*/
  char  fr_patternName[45]; /* The pattern name to be used. */
  char  fr_future2[2];
} FSINFO_REQUEST;

typedef struct FSINFO_NAME_t
{
  char  fn_eye[4];
#define FN_EYE "FINA"
  short fn_slength;           /* Structure length */
  short fn_sversion;
  char  fn_name[44];          /* aggregate name */
  unsigned int  fn_connected; /* number of conneceted systems if owner
                                 output is included; 0 otherwise*/
  char  fn_owner[8];          /* system name of the owner */
  unsigned int fn_length;     /* Total length of all information for this
                                 aggregate, so programs can quickly find the
                                 beginning of the next record
                                 in the output buffer. */
  char  fn_future[4];
  char  fn_sysnames[8];       /* Names of connected systems (32 at most).Actual
                                 number is defined fn_connected.*/
} FSINFO_NAME;

typedef struct FSINFO_OWNER_t {
  char           fo_eye[4];
#define          FSO_EYE "FIOW"
  short          fo_length;
  short          fo_sversion;
  unsigned int   fo_size;          /* Num of 8K blocks in the aggregate */
  unsigned int   fo_free;          /* Number of unused 8K blocks
                                      in the aggregate.*/
  unsigned long long int fo_frags; /* Num of free 1K fragments
                                      available in the aggregate.*/
  unsigned int   fo_logsize;       /* Num of 8K blocks allocated
                                      to the log file for
                                      transaction logging,
                                      including indirect blocks.*/
  unsigned int   fo_bitmapsize;    /* Number of 8K blocks allocated to the
                                      bitmap file including indirect blocks.*/
  unsigned int   fo_anodesize;     /* Number of 8K blocks allocated
                                      to the anode table.*/
  unsigned int   fo_objects;       /* Number of objects in the file system. */
  char           fo_version;       /* Aggregate version number */
  char           fo_threshold;     /* Space monitoring threshold */
  char           fo_increment;     /* Space monitoring increment*/
  char           reserved1;
  int            fo_flags;
#define FO_OWNER_MNTRW       0x1   /* Mounted in RW mode */
#define FO_OWNER_DISABLED    0x2   /* Disabled for access */
#define FO_OWNER_GROWFAIL    0x4   /* Grow failure since last reset */
#define FO_OWNER_LOW_ONSPC   0x8   /* Low on space (zfs definition)*/
#define FO_OWNER_DAMAGED     0x10  /* Aggregate is damaged by salvage
                                      verification & not repaired yet */
#define FO_OWNER_RWSHARE     0x20  /* Aggregate using zFS sysplex
                                      sharing (RWSHARE) */
#define FO_OWNER_GROWSET     0x40  /* Dynamic grow set at mount time */
#define FO_OWNER_GROWING     0x80  /* Aggregate is in the process
                                      of growing at the time of query */
#define FO_CONVERTOV5        0x100 /* CONVERTTOV5 parm is set on mount. */
#define FO_NOTMOUNT          0x200 /* Aggregate is not mounted */
#define FO_NO_OWNER          0x400 /* Aggregate is un-owned */
#define FO_OWNER_ALLOWGROW   0x800 /* Dynamic grow allowed , no
                                      grow failures or since a grow
                                      failure an admin grow was done. */
#define FO_OWNER_CHGOWNER    0x1000     /* The quiesce is done for a
                                           chgowner instead of a backup */
#define FO_CONVERTTOV5_DISABLED 0x2000  /* CONVERTTOV5 is disabled
                                           due to quiesce or failed convert */
#define FO_V4                0x4000     /* Aggregate with version 1.4 */
#define FO_V5                0x8000     /* Aggregate with version 1.5 */

  unsigned int fo_overflow; /* Num of overflow pages used for v5 directories */
  unsigned int fo_overflowhiwater; /* Hiwater mark of fo_overflow
                                      for life of file system.*/
  unsigned int fo_thrashing;       /* Current number of objects using
                                      the thrash-resolution protocol*/
  char         reserved2[4];
  unsigned long long int fo_thrash_resolution; /* Number of thrash resolutions
                                                  performed since last
                                                  statistics reset.*/
  unsigned long long int fo_revocations; /* Number of token revocations
                                            performed since last
                                            statistics reset*/
  unsigned long long int fo_revwait;     /* Average revocation wait time
                                            in microseconds.*/
  char                   fo_qsysname[8]; /* Name of system requesting quiesce,
                                            if the aggregate is quiesced,
                                            0 otherwise.*/
  char                   fo_jobname[8];  /* Name of job requesting quiesce,
                                            if the aggregate is quiesced,
                                            0 otherwise.*/
  unsigned long long int fo_createtime;  /* Creation time in
                                            seconds since epoch*/
  unsigned long long int fo_ownership;   /* Owership time in
                                            seconds since epoch*/
  unsigned long long int fo_reset;       /* Time statistic counters reset in
                                            seconds since last epoch*/
  unsigned long long int fo_quiesce;     /* Quiesce time in seconds since
                                            epoch, 0 if file system
                                            not quiesced.*/
  unsigned int           fo_devno;       /* Devno for the mount*/
  char                   fo_auditfid[10]; /* Audit fid for file system*/
  unsigned short         fo_qasid;       /* ASID which issued the quiesce */
  unsigned int           fo_growcount;   /* Number of grows since mount. */
  char                   reserved3[4];
  unsigned long long int fo_growtime;    /* Time of the last grow 
                                            as known by owner */
} FSINFO_OWNER;

typedef struct FSINFO_LOCAL_t {
  char                   fl_eye[4];
#define                  FL_EYE  "FILO"
  short                  fl_length;
  short                  fl_sversion;     /* Structure version */
  unsigned long long int fl_vnodes;       /* Number of vnodes cached in memory
                                             on the local system */
  unsigned long long int fl_ussheld;      /* Number of USS held vnodes*/
  char                   fl_sysname[8];   /* System name these stats are for */
  unsigned long long int fl_open;         /* Number of open objects in
                                             the file system */
  unsigned long long int fl_tokens;       /* Number of tokens held from
                                             the token manager */
  unsigned int           fl_usercache;    /* Number of 4K pages held in the
                                             user cache for the file system */
  unsigned int           fl_metacache;    /* Number of 8k pages held in
                                             the metadata cache */
  unsigned long long int fl_appreads;     /* Number of application reads made
                                             since last reset */
  unsigned long long int fl_appreadresp;  /* Average read response
                                             time in microseconds*/
  unsigned long long int fl_appwrites;    /* Number of application writes
                                             made since last reset */
  unsigned long long int fl_appwriteresp; /* Average write response
                                             time in microseconds*/
  unsigned long long int fl_xcfreads;     /* Number of xcf read calls made
                                             to the owner since last reset */
  unsigned long long int fl_xcfreadresp;  /* Average xcf read call response
                                             time in microseconds*/
  unsigned long long int fl_xcfwrites;    /* Number of xcf write calls made to
                                             the server since last reset */
  unsigned long long int fl_xcfwriteresp; /* Average xcf write call response
                                             time in microseconds*/
  unsigned long long int fl_enospc;       /* Number of ENOSPC errors returned
                                             to apps since last reset */
  unsigned long long int fl_ioerrs;       /* Number of disk IO errors 
                                             since last reset*/
  unsigned long long int fl_commerrs;     /* Number of XCF communication timeouts
                                             or failures since last reset*/
  unsigned long long int fl_cancels;      /* Number of cancelled operations
                                             since last reset by asynchronus
                                             abends, cancel, forces and EOMs */
  char                   fl_ddname[8];    /* DDNAME of allocation of dataset */
  struct timeval64       fl_mounttime;    /* Mount time, seconds since epoch */
  unsigned int           fl_numdasd;      /* Number of DASD volumes listed for
                                             aggregate in FSINFO_DASD array */
  unsigned int           fl_flags;        /* 1 indicates if this system has
                                             tasks waiting on a quiesced FS.*/
} FSINFO_LOCAL;

typedef struct FSINFO_DASD_t
{
  char  fd_eye[4];
#define FSD_EYE  "FIDA"
  short fd_length;
  short fd_sversion;
#define FSD_VER_INITIAL 1
  char  fd_volser[6];
  short fd_pavios;
  unsigned long long int fd_reads;
  unsigned long long int fd_readbytes;
  unsigned long long int fd_writes;
  unsigned long long int fd_writebytes;
  unsigned long long int fd_waits;
  unsigned long long int fd_waitTime;
  unsigned long long int fd_resptime;
} FSINFO_DASD;

void check_local_error(char *buffp, FSINFO_REQUEST *fs_req, int *lerr_stat);

int main(int argc, char **argv)
{
  char*             buffp          = NULL;
  syscall_parmlist* parmp          = NULL;
  FSINFO_REQUEST*   fs_req         = NULL;
  char              owner_sys[9];

  int               buff_fill_len  = 0;
  int               fs_ownerlen    = 0;
  int               fs_locallen    = 0;
  int               unowned        = 0;
  int               fr_nonFatalRc  = 0;
  int               fr_nonFatalRsn = 0;
  int               sperr          = 0;
  int               ioerr          = 0;
  int               xcferr         = 0;
  int               lerr_stat      = 0;
  int               bpxrv, bpxrc, bpxrs;
  int               i, j, k;
  unsigned long long int most_writes = 0;
  char              busiest_volume[7];
  int               locals         = 0;

  /* aggrname for fsinfo */
  char              aggrname[ZFS_MAX_AGGRNAME+1] = "PLEX.DCEIMGQY.FS";

  /* Output structure pointers */
  FSINFO_NAME*      fs_namep      = NULL;
  FSINFO_OWNER*     fs_ownerp     = NULL;
  FSINFO_LOCAL*     fs_localp     = NULL;
  FSINFO_DASD *     fs_dasdp      = NULL;
  char*             outputp       = NULL;

  /* Allocate buffer */
  buffp = (char*) malloc(BUFFER_SIZE);
  if( buffp == NULL )
  {
    printf("Malloc Error\n");
    return 0;
  }

  /* Set the parmdata */
  parmp = (syscall_parmlist*) &buffp[0];
  parmp->opcode   = AGOP_FSINFO_PARMDATA;
  parmp->parms[0] = buff_fill_len = sizeof(syscall_parmlist);
  parmp->parms[1] = 0;
  parmp->parms[2] = 0;
  parmp->parms[3] = 0;
  parmp->parms[4] = 0;
  parmp->parms[5] = 0;
  parmp->parms[6] = 0;

  fs_req = (FSINFO_REQUEST*) &buffp[buff_fill_len];
  memset( fs_req, 0x00, sizeof(FSINFO_REQUEST) );

  /* First obtain the statistics for all file systems. We will look       */
  /* through them to find the DASD volume with the most write operations. */
  memcpy( fs_req->fr_eye, FR_EYE, sizeof(fs_req->fr_eye) );
  fs_req->fr_length        = sizeof(FSINFO_REQUEST);
  fs_req->fr_sversion      = 1;
  fs_req->fr_version       = 1;
  fs_req->fr_reqtype       = FR_REQTYPE_NAMECURSOR;
  fs_req->fr_output        = FR_OUT_FULL_STAT;
  fs_req->fr_nameSelection = FR_NM_ALLAGGR;

  buff_fill_len += sizeof(FSINFO_REQUEST);

  /* Loop getting file system information from zFS until we have it all. */
  do
  {
      /* Call zFS. */
      printf("call zfs\n");
      BPX1PCT("ZFS     ",
              ZFSCALL_FSINFO,             /* Aggregate operation */
              BUFFER_SIZE,                /* Length of Argument */
              (char*) buffp,              /* Pointer to Argument */
              &bpxrv,                     /* Pointer to Return_value */
              &bpxrc,                     /* Pointer to Return_code */
              &bpxrs);                    /* Pointer to Reason_code */

      if( bpxrv )
      {
        printf("Error getting fsinfo for aggregate %s\n", aggrname);
        printf("Return Value: %d Return Code: %d Reason Code: %x\n",
               bpxrv, bpxrc, bpxrs);
        goto done;
      }
      if( fs_req->fr_nonFatalRc )
      {
        fr_nonFatalRc  = fs_req->fr_nonFatalRc;
        fr_nonFatalRsn = fs_req->fr_nonFatalRsn;
        goto print_non_fatals;
      }

      /* The first structure pointed by output buffer is FSINFO_NAME.*/
      fs_namep = (FSINFO_NAME *) &buffp[buff_fill_len];
      for (i=0; i<fs_req->fr_entries; i++)
      {
        fs_ownerp = (FSINFO_OWNER *)((char *)fs_namep+fs_namep->fn_slength);
        locals = fs_namep->fn_connected;

        /* If file system has an owner, there will be one more */
        /* FSINFO_LOCAL structure returned than this count.    */
        if (memcmp(fs_namep->fn_owner, "*UNOWNED") != 0)
          locals++;

        /* Determine if there is an FSINFO_OWNER or not.         */
        /* If not, then the structure should be an FSINFO_LOCAL. */
        if (memcmp(fs_ownerp->fo_eye, FSO_EYE, 4) == 0)
        { /* FSINFO_OWNER returned */
          fs_localp = (FSINFO_LOCAL *)((char *)fs_ownerp+fs_ownerp->fo_length);
        }
        else if (memcmp(fs_ownerp->fo_eye, FL_EYE, 4) == 0)
        {
          /* No FSINFO_OWNER returned. It's FSINFO_LOCAL */
          fs_localp = (FSINFO_LOCAL *)fs_ownerp;
          fs_ownerp = NULL;
        }
        else
        {
          /* Should not get here!! */
          printf("Error exit: Incorrect structure sequence!!\n");
          goto done;
        }

        /* Loop through each FSINFO_LOCAL structure returned. */
        for (j=0; j<locals; j++)
        {
          fs_dasdp = (FSINFO_DASD *)((char *)fs_localp + fs_localp->fl_length);
          for (k=0; k<fs_localp->fl_numdasd; k++)
          {
            /* Determine if this DASD volume has more writes than the  */
            /* previously higher one.  Yes, remember DASD volume name. */
            if (fs_dasdp->fd_writes > most_writes)
            {
              strncpy(busiest_volume, fs_dasdp->fd_volser, 6);
              busiest_volume[6] = 0;
              most_writes = fs_dasdp->fd_writes;
            }
            /* Set up for next iteration. */
            fs_dasdp = (FSINFO_DASD *)((char *)fs_dasdp + fs_dasdp->fd_length);
          }
          /* After looping through all FSINFO_DASD structures, fs_dasdp */
          /* should be pointing at the next FSINFO_LOCAL structure.     */
          fs_localp = (FSINFO_LOCAL *)fs_dasdp;
        }

        /* Get ready for next loop iteration. */
        fs_namep = (FSINFO_NAME *)((char *)fs_namep+fs_namep->fn_length);
      }
  }
  while (!fs_req->fr_eol);

  printf("DASD volume %s has the most writes (%llu)\n",
         busiest_volume, most_writes);

  /* Now do a single aggregate query for a specific file system. */
  memset( fs_req, 0x00, sizeof(FSINFO_REQUEST));
  memcpy( fs_req->fr_eye, FR_EYE, sizeof(fs_req->fr_eye) );
  fs_req->fr_length        = sizeof(FSINFO_REQUEST);
  fs_req->fr_sversion      = 1;
  fs_req->fr_version       = 1;
  fs_req->fr_output        = FR_OUT_FULL_STAT;
  fs_req->fr_reqtype       = FR_REQTYPE_SINGLEQUERY;
  memcpy( fs_req->fr_resumeName, aggrname, ZFS_MAX_AGGRNAME+1 );

  BPX1PCT("ZFS     ",
          ZFSCALL_FSINFO,             /* Aggregate operation */
          BUFFER_SIZE,                /* Length of Argument */
          (char*) buffp,              /* Pointer to Argument */
          &bpxrv,                     /* Pointer to Return_value */
          &bpxrc,                     /* Pointer to Return_code */
          &bpxrs);                    /* Pointer to Reason_code */

  if( bpxrv )
  {
    printf("Error getting fsinfo for aggregate %s\n", aggrname);
    printf("Return Value: %d Return Code: %d Reason Code: %x\n",
           bpxrv, bpxrc, bpxrs);
    goto done;
  }
  if( fs_req->fr_nonFatalRc )
  {
    fr_nonFatalRc  = fs_req->fr_nonFatalRc;
    fr_nonFatalRsn = fs_req->fr_nonFatalRsn;
    goto print_non_fatals;
  }

  buff_fill_len = sizeof(syscall_parmlist) + sizeof(FSINFO_REQUEST);
  outputp = buffp + buff_fill_len;
  check_local_error(outputp, fs_req, &lerr_stat);

  /* The first structure pointed by output buffer would be FSINFO_NAME. */
  fs_namep = (FSINFO_NAME *) &buffp[buff_fill_len];
  fs_ownerp = (FSINFO_OWNER *) ((char*) fs_namep + fs_namep->fn_slength);
  memcpy(owner_sys, fs_namep->fn_owner, 8);
  owner_sys[8] = '\0';

  if (memcmp(&owner_sys[0], "*UNOWNED", 8) == 0)
  {
     unowned = 1;
     if (memcmp(fs_ownerp->fo_eye, FSO_EYE, 4) == 0)
     {  /* FSINFO_OWNER returned */
        fs_localp = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);
     }
     else if (memcmp(fs_ownerp->fo_eye, FL_EYE, 4) == 0)
     {
        /* No FSINFO_OWNER returned. It's FSINFO_LOCAL */
        fs_localp = (FSINFO_LOCAL *)fs_ownerp;
        fs_ownerp = NULL;
     }
  } 
  else if (fs_ownerp->fo_flags & FO_NO_OWNER)
  {
     unowned = 1;
     fs_localp = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);
  }
  else
     fs_localp = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);

  if ((lerr_stat & FSINFO_SPC_ERR) == FSINFO_SPC_ERR)
  {
    fs_localp->fl_enospc = 1;
    sperr = 1;
  }
  if ((lerr_stat & FSINFO_IO_ERR) == FSINFO_IO_ERR)
  {
    fs_localp->fl_ioerrs = 1;
    ioerr = 1;
  }
  if ((lerr_stat & FSINFO_XCF_ERR) == FSINFO_XCF_ERR)
  {
    fs_localp->fl_commerrs = 1;
    xcferr = 1;
  }

  if( unowned && !fs_ownerp )
  {
    if (!xcferr && !ioerr && !sperr)
      printf("%-44.44s %-8.8s n/a \n\n",
             aggrname, "*UNOWNED");
    else
    {
      printf("%-44.44s %-8.8s %s%s%s \n\n",
             aggrname, "*UNOWNED",
             (sperr)? "SE" :"",
             (ioerr)?((sperr)?",IE":"IE"):"",
             (xcferr)?((sperr || ioerr)?",CE":"CE"):"");
      /* Define the flags in a legend */
      printf("Legend: %s%s%s\n\n",
             (sperr)? "SE = Space errors reported":"",
             (ioerr)?
               ((sperr)? ",IE = IO errors reported":
                         "IE = IO errors reported") : "",
             (xcferr)?
               ((sperr || ioerr)?
                         ",CE = Communication errors reported":
                         "CE = Communication errors reported") : "");
    }
  }
  else
  {
    /* Print the aggregate info with flags */
    printf("%-44.44s %-8.8s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s \n\n",
           aggrname, fs_namep->fn_owner,
           (fs_ownerp->fo_flags & FO_NOTMOUNT)         ? "NM" : "",
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) &&
            (fs_ownerp->fo_flags & FO_OWNER_MNTRW))    ? "RW" :
           ((fs_ownerp->fo_flags & FO_NOTMOUNT)        ? ""   : "RO"),
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) && 
            (fs_ownerp->fo_flags & FO_OWNER_RWSHARE))  ? ",RS" :
           ((fs_ownerp->fo_flags & FO_NOTMOUNT)        ? ""    : ",NS"),

           (fs_ownerp->fo_thrashing)                   ? ",TH" : "",
           (fs_ownerp->fo_qsysname[0] != '\0')         ? ",Q"  : "",
           (fs_ownerp->fo_flags & FO_OWNER_DISABLED)   ? ",DI" : "",
           (fs_ownerp->fo_flags & FO_OWNER_GROWING)    ? ",GR" : "",
           (fs_ownerp->fo_flags & FO_OWNER_GROWFAIL)   ? ",GF" : "",
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) &&
            !(fs_ownerp->fo_flags & FO_OWNER_ALLOWGROW)) ? ",GD" : "",

           (fs_ownerp->fo_flags & FO_OWNER_DAMAGED)    ? ",DA" : "",
           (fs_ownerp->fo_flags & FO_OWNER_LOW_ONSPC)  ? ",L"  : "",
           (sperr)                                     ? ",SE" : "",
           (fs_ownerp->fo_flags & FO_OWNER_DISABLED)   ? ",DI" : "",
           (ioerr)                                     ? ",IE" : "",
           (xcferr)                                    ? ",CE" : "");


    /* Define the flags in a legend */
    printf("Legend: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s \n\n",
           (fs_ownerp->fo_flags & FO_NOTMOUNT)    ? "NM = Not mounted" : "",
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) && 
            (fs_ownerp->fo_flags & FO_OWNER_MNTRW)) ? "RW = Read-write"  :
           ((fs_ownerp->fo_flags & FO_NOTMOUNT)     ? "" : "RO = Read-only"),
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) &&
            (fs_ownerp->fo_flags & FO_OWNER_RWSHARE)) ?
            ",RS = Mounted RWSHARE" : ((fs_ownerp->fo_flags & FO_NOTMOUNT) ?
            "" : ",NS = Mounted NORWSHARE"),
           (fs_ownerp->fo_thrashing)               ? ",TH = Thrashing"  : "",
           (fs_ownerp->fo_qsysname[0] != '\0')     ? ",Q = Queisced"    : "",
           (fs_ownerp->fo_flags & FO_OWNER_DISABLED) ?
            ",DI = Disabled"   : "",
           (fs_ownerp->fo_flags & FO_OWNER_GROWING)  ?
            ",GR = Growing"    : "",
           (fs_ownerp->fo_flags & FO_OWNER_GROWFAIL) ?
            ",GF = Grow Failed": "",
           /* Multiple Conditions */
           (!(fs_ownerp->fo_flags & FO_NOTMOUNT) &&
            !(fs_ownerp->fo_flags & FO_OWNER_ALLOWGROW)) ?
              ",GD = AGGRGROW disabled" : "",
           (fs_ownerp->fo_flags & FO_OWNER_DAMAGED)  ?
            ",DA = Damaged"    : "",
           (fs_ownerp->fo_flags & FO_OWNER_LOW_ONSPC)  ?
            ",L = Low on space": "",
           (sperr)   ? ",SE = Space errors reported":"",
           (fs_ownerp->fo_flags & FO_OWNER_DISABLED)   ?
            ",DI = Disabled"   : "",
           (ioerr)   ? ",IE = IO errors reported"  : "",
           (xcferr)  ? ",CE = Communication errors reported":"");
  }
  goto done;

print_non_fatals:
  if( fr_nonFatalRc )
  {
    printf("Non-Fatal errors:\n");
    printf("Return Code: %d Reason Code: %x\n\n",
           fr_nonFatalRc, fr_nonFatalRsn);
  }
done:
  free(buffp);
  return 0;
}

void check_local_error(char *buffptr, FSINFO_REQUEST *fs_req, int *lerr_stat)
{
  FSINFO_NAME * fs_namep;
  FSINFO_OWNER * fs_ownerp = NULL;
  FSINFO_LOCAL * fs_local;
  FSINFO_DASD  * dasdp;
  int dasd_space;
  int i, j;
  int total_sys = 0;
  int unowned = 0;  

  if ((*lerr_stat) == (FSINFO_XCF_ERR | FSINFO_IO_ERR | FSINFO_SPC_ERR))
  {
    printf("FSINFO_CheckLocalErr: all 3 bits are set in *lerr_stat=%X\n",
           *lerr_stat);
    return ;
  }

  /* The first structure pointed by output buffer would be FSINFO_NAME. */
  fs_namep = (FSINFO_NAME *)((char *)buffptr);
  fs_ownerp = (FSINFO_OWNER *)((char *)fs_namep + fs_namep->fn_slength);

  /* if UNOWNED, make sure we are processing the right stats. */
  if (memcmp(&fs_namep->fn_owner, "*UNOWNED", 8) == 0)
  {
    unowned = 1;
    if (memcmp(fs_ownerp->fo_eye, FSO_EYE, 4) == 0)
    { /* FSINFO_OWNER block */
      fs_local = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);
    }
    else if (memcmp(fs_ownerp->fo_eye, FL_EYE, 4) == 0)
    { /* FSINFO_LOCAL block */
      fs_local = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);
      fs_ownerp = NULL;
    }
    else
    {  /* We should not get here!! */
      return;
    }
  } 
  else
    fs_local = (FSINFO_LOCAL *)((char *)fs_ownerp + fs_ownerp->fo_length);

  /* If FSINFO_OWNER is not returned, we have 1 less FSINFO_LOCAL to process */
  if (unowned && (fs_ownerp == NULL))
    total_sys = fs_namep->fn_connected;
  else
    total_sys = fs_namep->fn_connected+1;

  for (i=0; i < total_sys; i++)
  {
    if (fs_local->fl_commerrs)
      (*lerr_stat) |= FSINFO_XCF_ERR;

    if (fs_local->fl_enospc)
      (*lerr_stat) |= FSINFO_SPC_ERR;

    if (fs_local->fl_ioerrs)
      (*lerr_stat) |= FSINFO_IO_ERR;

    if ((*lerr_stat) == (FSINFO_XCF_ERR | FSINFO_IO_ERR | FSINFO_SPC_ERR))
      return ;

    /* Find the next FSINFO_LOCAL structure, which is after any FSINFO_DASD */
    /* structures that might be present.                                    */
    if (fs_local->fl_numdasd > 0)
    {
        dasdp = (FSINFO_DASD *)((char *)fs_local + fs_local->fl_length);
        dasd_space = fs_local->fl_numdasd * dasdp->fd_length;
    }
    else
        dasd_space = 0;
    fs_local = (FSINFO_LOCAL *)((char *)fs_local + fs_local->fl_length +
                                dasd_space);
  }

  return;
}
End of change