source: gpfs_3.1_ker2.6.20/lpp/mmfs/samples/util/tsgetusage.c @ 148

Last change on this file since 148 was 16, checked in by rock, 17 years ago
File size: 9.2 KB
Line 
1/* IBM_PROLOG_BEGIN_TAG                                                   */
2/* This is an automatically generated prolog.                             */
3/*                                                                        */
4/*                                                                        */
5/*                                                                        */
6/* Licensed Materials - Property of IBM                                   */
7/*                                                                        */
8/* (C) COPYRIGHT International Business Machines Corp. 2002,2006          */
9/* All Rights Reserved                                                    */
10/*                                                                        */
11/* US Government Users Restricted Rights - Use, duplication or            */
12/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
13/*                                                                        */
14/* IBM_PROLOG_END_TAG                                                     */
15
16/*====================================================================
17 *
18 * tsgetusage command: get a summary of each user's disk usage
19 *
20 * Syntax: tsgetusage [ options ] fsPath
21 *
22 *   fsPath: the directory where the root of the filesystem is found.
23 *
24 *==================================================================*/
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <unistd.h>
31#include <string.h>
32#include <pwd.h>
33#include <grp.h>
34#include <sys/types.h>
35#include <gpfs.h>
36
37
38/* Define globals */
39static int Verbose = 1;
40static int GroupStats = 0;
41static int DiskUsgFormat = 0;
42static char* ProgNameP = NULL;
43
44/* Define stat structure */
45typedef struct uStat_struct
46{
47  struct uStat_struct *nextP;
48  unsigned int         id;
49  gpfs_off64_t         blockCount;
50  gpfs_off64_t         inodeCount;
51} uStat;
52
53/* Define hash table for collecting stats */
54static uStat **HashPP = NULL;
55static int     HashSize = 1027;
56#define HASH(_id) (_id % HashSize)
57
58
59/* Print usage statement and exit. */
60static void Usage()
61{
62  fprintf(stderr, "Usage: %s [-g][-h][-q][-v][-u][-H hashTableSize] fsPath\n"
63            "\twhere:\tfsPath\tpath to file system\n"
64            "\t\t-u\toutputs data in diskusg format for acctdisk\n"
65            "\t\t-g\tcollect stats for groups\n"
66            "\t\t-H\tsets the hash table size (default %d)\n"
67            "\t\t-h\tprints this message\n"
68            "\t\t-q\toutputs only the resulting stats\n"
69            "\t\t-v\tprint information about each file\n",
70          ProgNameP, HashSize);
71  fflush(stderr);
72  exit(1);
73}
74
75/* Initialize hash table for collecting statistics */
76static int InitHash()
77{
78  int hashTableSize = HashSize * sizeof(uStat *);
79
80  HashPP = (uStat **)malloc(hashTableSize);
81  if (HashPP == NULL)
82  {
83    fprintf(stderr, "No space to allocate hash table (%d bytes)\n",
84            hashTableSize);
85    return ENOMEM;
86  }
87
88  memset(HashPP, '\0', hashTableSize);
89  return 0;
90}
91
92/* Find and increment an user/group's stat entry.
93   Create the entry, if it is not found. */
94static int IncStats(unsigned int id,
95                    gpfs_off64_t nBlocks, gpfs_off64_t nInodes)
96{
97  uStat *uP, *prevP;
98  int hashVal;
99
100  /* Locate stat entry in hash table */
101  prevP = NULL;
102  hashVal = HASH(id);
103  for (uP = HashPP[ hashVal ]; uP != NULL; uP = uP->nextP)
104  {
105    if (uP->id == id)
106    {
107      /* Entry found. Update its counters */
108      uP->blockCount += nBlocks;
109      uP->inodeCount += nInodes;
110
111      /* Move entry to head of hash list */
112      if (prevP != NULL)
113      {
114        prevP->nextP = uP->nextP;
115        uP->nextP = HashPP[ hashVal ];
116        HashPP[ hashVal ] = uP;
117      }
118      return 0;
119    }
120    prevP = uP;
121  }
122
123  /* Entry not found. Create a new one. */
124  uP = (uStat *)malloc(sizeof(*uP));
125  if (uP == NULL)
126  {
127    fprintf(stderr, "No space to allocate stat entry (%d bytes)\n",
128            sizeof(*uP));
129    return ENOMEM;
130  }
131
132  /* Initialize new entry & insert at head of hash list */
133  uP->id = id;
134  uP->blockCount = nBlocks;
135  uP->inodeCount = nInodes;
136  uP->nextP = HashPP[ hashVal ];
137  HashPP[ hashVal ] = uP;
138
139  return 0;
140}
141
142/* Traverse has table and print each entry */
143static int PrintStats(const char* fsPathP)
144{
145  int i;
146  uStat *uP;
147  char *nameP;
148  struct group *grpP;
149  struct passwd *usrP;
150
151  if (Verbose > 0)
152  {
153    printf("%s statistics for file system %s:\n",
154           (GroupStats != 0) ? "Group" : "User",
155           fsPathP);
156    printf("%10s %32s %12s %12s\n",
157           (GroupStats != 0) ? "gid" : "uid",
158           "name", "KB", "inodes");
159  }
160
161  /* Traverse the hash table */
162  for (i = 0; i < HashSize; i++)
163  {
164    /* Traverse each hash list */
165    for (uP = HashPP[i]; uP != NULL; uP = uP->nextP)
166    {
167      /* Convert ids into readable names */
168      if (GroupStats != 0)
169      {
170        grpP = getgrgid((gid_t) uP->id);
171        if (grpP == NULL)
172          nameP = "n/a";
173        else
174          nameP = grpP->gr_name;
175      }
176      else
177      {
178        usrP = getpwuid((uid_t) uP->id);
179        if (usrP == NULL)
180          nameP = "n/a";
181        else
182          nameP = usrP->pw_name;
183      }
184
185      /* Print stats on stdout */
186      if (DiskUsgFormat)
187        printf("%u\t%s\t%lld\n",
188               uP->id, nameP, (uP->blockCount+1)/2);
189      else
190        printf("%10u %32s %12lld %12lld\n",
191               uP->id, nameP, (uP->blockCount+1)/2, uP->inodeCount);
192    }
193  }
194  if (Verbose > 0)
195    printf("%s statistics for file system %s complete.\n",
196           (GroupStats != 0) ? "Group" : "User",
197           fsPathP);
198
199  return 0;
200}
201
202/* Scan the file system to collect the requested stats */
203int scanFileSystem(const char *fsPathP)
204{
205  int rc = 0;
206  gpfs_iscan_t *iscanP = NULL;
207  gpfs_fssnap_handle_t *fsP = NULL;
208  const gpfs_iattr_t *iattrP;
209  gpfs_ino_t lastInodeNum = 0;
210  gpfs_ino_t maxInodeNum;
211  char modeBuf[32];
212
213  if (Verbose > 1)
214    fprintf(stderr, "Scanning %s...\n", fsPathP);
215  else if (Verbose > 0)
216    printf("Scanning %s...\n", fsPathP);
217
218  /* Open inode scan */
219  fsP = gpfs_get_fssnaphandle_by_path(fsPathP);
220  if (fsP == NULL)
221  {
222    rc = errno;
223    fprintf(stderr, "%s: gpfs_get_fssnaphandle_by_path(%s): %s\n",
224            ProgNameP, fsPathP, strerror(rc));
225    goto done;
226  }
227
228  iscanP = gpfs_open_inodescan(fsP, NULL, &maxInodeNum);
229  if (iscanP == NULL)
230  {
231    rc = errno;
232    fprintf(stderr, "%s: gpfs_open_inodescan(%s): %s\n",
233            ProgNameP, fsPathP, strerror(rc));
234    goto done;
235  }
236
237  /* Loop over inodes in the file system */
238  while (1)
239  {
240    rc = gpfs_next_inode(iscanP, maxInodeNum, &iattrP);
241    if (rc != 0)
242    {
243      rc = errno;
244      fprintf(stderr, "%s: gpfs_next_inode(%s,%d): %s\n",
245              ProgNameP, fsPathP, lastInodeNum, strerror(rc));
246      goto done;
247    }
248
249    /* A null ptr indicates end of scan */
250    if (iattrP == NULL)
251      break;
252
253    /* Save inode number */
254    lastInodeNum = iattrP->ia_inode;
255
256    /* Skip over deleted files. */
257    if (iattrP->ia_nlink == 0)
258      continue;
259
260    if (Verbose > 1)
261      fprintf(stderr,
262              "inode %9d uid %6d gid %6d bytes %10lld blks %10lld\n",
263              iattrP->ia_inode, iattrP->ia_uid, iattrP->ia_gid,
264              iattrP->ia_size, iattrP->ia_blocks);
265
266    if (GroupStats != 0)
267      rc = IncStats((unsigned int) iattrP->ia_gid,
268                    iattrP->ia_blocks, 1);
269    else
270      rc = IncStats((unsigned int) iattrP->ia_uid,
271                    iattrP->ia_blocks, 1);
272    if (rc != 0)
273      goto done;
274  }
275
276done:
277  if (iscanP != NULL)
278    gpfs_close_inodescan(iscanP);
279  if (fsP != NULL)
280    gpfs_free_fssnaphandle(fsP);
281
282  if (Verbose > 1)
283    if (rc != 0)
284      fprintf(stderr, "Scan %s complete: %s\n", fsPathP, strerror(rc));
285    else
286      fprintf(stderr, "Scan %s complete\n", fsPathP);
287
288  return rc;
289}
290
291/* main */
292int main(int argc, char *argv[])
293{
294  int i, rc;
295  const char* fsPathP;
296
297  /* Save program name for usage statement */
298  ProgNameP = argv[0];
299  fsPathP = NULL;
300
301  /* parse options */
302  for (i = 1; i < argc; i++)
303  {
304    if (strcmp(argv[i], "-v") == 0)
305      Verbose = 2;
306    else if (strcmp(argv[i], "-q") == 0)
307      Verbose = 0;
308    else if (strcmp(argv[i], "-u") == 0)
309    {
310      DiskUsgFormat = 1;
311      Verbose = 0;
312    }
313    else if (strcmp(argv[i], "-g") == 0)
314      GroupStats = 1;
315    else if (strcmp(argv[i], "-H") == 0)
316    {
317      i++;
318      if (i < argc)
319      {
320        HashSize = atoi(argv[i]);
321        if (HashSize <= 0)
322        {
323          fprintf(stderr, "%s: Invalid value for -H (%d)\n",
324                  ProgNameP, HashSize);
325          exit(2);
326        }
327      }
328      else
329      {
330        fprintf(stderr, "%s: Missing arg for -H\n", ProgNameP);
331        Usage();
332      }
333    }
334    else if ((strcmp(argv[i], "-h") == 0) ||
335             (strcmp(argv[i], "-?") == 0))
336      Usage();
337    else if (fsPathP == NULL)
338      fsPathP = argv[i];
339    else
340    {
341      fprintf(stderr, "%s: Unknown arg \"%s\"\n", ProgNameP, argv[i]);
342      Usage();
343    }
344  }
345
346  if (fsPathP == NULL)
347  {
348    fprintf(stderr, "%s: Missing fsPath arg\n", ProgNameP);
349    Usage();
350  }
351
352  /* Initialize hash tables */
353  rc = InitHash();
354  if (rc != 0)
355    goto done;
356
357  /* Scan the file system to collect the requested stats */
358  rc = scanFileSystem(fsPathP);
359  if (rc != 0)
360    goto done;
361
362  /* Display results */
363  rc = PrintStats(fsPathP);
364
365done:
366  return rc;
367}
Note: See TracBrowser for help on using the repository browser.