bed512ca618bb10c173bc35f1b98a14a47bdfb1a
[openafs.git] / src / vol / xfs_size_check.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Verify that the size of the XFS inode is large enough to hold the XFS
11  * attribute for AFS inode parameters. Check all the mounted /vicep partitions.
12 #include <afsconfig.h>
13
14
15  */
16 #include <afs/param.h>
17 #ifdef AFS_SGI_XFS_IOPS_ENV
18 #include <errno.h>
19 #include <sys/stat.h>
20 #include <stdio.h>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <mntent.h>
24 #include "partition.h"
25 #include <afs/xfsattrs.h>
26
27 char *prog = "xfs_size_check";
28
29 /* Verify that the on disk XFS inodes on the partition are large enough to
30  * hold the AFS attribute. Returns -1 if the attribute can't be set or is
31  * too small to fit in the inode. Returns 0 if the attribute does fit in
32  * the XFS inode.
33  */
34 #define VERIFY_ERROR   -1
35 #define VERIFY_OK       0
36 #define VERIFY_FIX      1
37 static int
38 VerifyXFSInodeSize(char *part)
39 {
40     afs_xfs_attr_t junk;
41     int length = SIZEOF_XFS_ATTR_T;
42     int fd;
43     int code = VERIFY_ERROR;
44     struct fsxattr fsx;
45
46     if (attr_set(part, AFS_XFS_ATTR, &junk, length, ATTR_ROOT) < 0) {
47         if (errno == EPERM) {
48             printf("Must be root to run %s\n", prog);
49             exit(1);
50         }
51         return VERIFY_ERROR;
52     }
53
54     if ((fd = open(part, O_RDONLY, 0)) < 0)
55         goto done;
56
57     if (fcntl(fd, F_FSGETXATTRA, &fsx) < 0)
58         goto done;
59
60     if (fsx.fsx_nextents == 0)
61         code = VERIFY_OK;
62     else
63         code = VERIFY_FIX;
64
65   done:
66     if (fd >= 0)
67         close(fd);
68     (void)attr_remove(part, AFS_XFS_ATTR, ATTR_ROOT);
69
70     return code;
71 }
72
73 #define ALLOC_STEP 256
74 #define NAME_SIZE 64
75 typedef struct {
76     char partName[NAME_SIZE];
77     char devName[NAME_SIZE];
78 } partInfo;
79 partInfo *partList = NULL;
80 int nParts = 0;
81 int nAvail = 0;
82
83 int
84 CheckPartitions()
85 {
86     int i;
87     struct mntent *mntent;
88     FILE *mfd;
89     DIR *dirp;
90     struct dirent *dp;
91     struct stat status;
92     int code;
93
94     if ((mfd = setmntent(MOUNTED, "r")) == NULL) {
95         printf("Problems in getting mount entries(setmntent): %s\n",
96                strerror(errno));
97         exit(-1);
98     }
99     while (mntent = getmntent(mfd)) {
100         char *part = mntent->mnt_dir;
101
102         if (!hasmntopt(mntent, MNTOPT_RW))
103             continue;
104
105         if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
106             continue;           /* Non /vicepx; ignore */
107         }
108         if (stat(part, &status) == -1) {
109             printf("Couldn't find file system %s; ignored\n", part);
110             continue;
111         }
112         if (!strcmp("xfs", status.st_fstype)) {
113             code = VerifyXFSInodeSize(part);
114             switch (code) {
115             case VERIFY_OK:
116                 break;
117             case VERIFY_ERROR:
118                 printf("%s: Can't check XFS inode size: %s\n",
119                        strerror(errno));
120                 break;
121             case VERIFY_FIX:
122                 if (nAvail <= nParts) {
123                     nAvail += ALLOC_STEP;
124                     if (nAvail == ALLOC_STEP)
125                         partList =
126                             (partInfo *) malloc(nAvail * sizeof(partInfo));
127                     else
128                         partList =
129                             (partInfo *) realloc((char *)partList,
130                                                  nAvail * sizeof(partInfo));
131                     if (!partList) {
132                         printf
133                             ("Failed to %salloc %d bytes for partition list.\n",
134                              (nAvail == ALLOC_STEP) ? "m" : "re",
135                              nAvail * sizeof(partInfo));
136                         exit(1);
137                     }
138                 }
139                 (void)strcpy(partList[nParts].partName, part);
140                 (void)strcpy(partList[nParts].devName, mntent->mnt_fsname);
141                 nParts++;
142                 break;
143             default:
144                 printf("Unknown return code %d from VerifyXFSInodeSize.\n",
145                        code);
146                 abort();
147             }
148         }
149     }
150     return nParts;
151 }
152
153
154 main(int ac, char **av)
155 {
156     int i;
157     int code;
158
159     if (getuid()) {
160         printf("Must be root to run %s.\n", prog);
161         exit(1);
162     }
163
164     code = CheckPartitions();
165     if (code) {
166         printf("Need to remake the following partitions:\n");
167         for (i = 0; i < nParts; i++) {
168             printf("%s: mkfs -t xfs -i size=512 -l size=4000b %s\n",
169                    partList[i].partName, partList[i].devName);
170         }
171     }
172     exit(code ? 1 : 0);
173 }
174
175
176 #else /* AFS_SGI_XFS_IOPS_ENV */
177 main()
178 {
179     printf("%s only runs on XFS platforms.\n, prog");
180     exit(1);
181 }
182 #endif /* AFS_SGI_XFS_IOPS_ENV */