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