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