2 * Copyright 2000, International Business Machines Corporation and others.
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
14 Institution: The Information Technology Center, Carnegie-Mellon University
18 #define ITC /* Required by inode.h */
20 #include <afsconfig.h>
21 #include <afs/param.h>
26 #if defined(AFS_LINUX20_ENV) || defined(AFS_SUN4_ENV)
31 * -1 - Unable to read the inodes.
32 * -2 - Unable to completely write temp file. Produces warning message in log.
34 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
35 char *devname, *mountedOn, *resultFile, *wpath;
39 Log("ListViceInodes not implemented for this platform!\n");
44 #include <sys/param.h>
45 #if defined(AFS_SGI_ENV)
49 #else /* AFS_OSF_ENV */
50 #ifdef AFS_VFSINCL_ENV
53 #include <sys/fs/ufs_fs.h>
55 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
56 #include <ufs/ufs/dinode.h>
57 #include <ufs/ffs/fs.h>
58 #define itod ino_to_fsba
63 #else /* AFS_VFSINCL_ENV */
65 #include <sys/filsys.h>
69 #endif /* AFS_VFSINCL_ENV */
70 #endif /* AFS_OSF_ENV */
72 #ifdef AFS_VFSINCL_ENV
73 #include <sys/vnode.h>
75 #include <sys/fs/ufs_inode.h>
77 #if !defined(AFS_DARWIN_ENV)
78 #include <ufs/inode.h>
81 #else /* AFS_VFSINCL_ENV */
84 #endif /* AFS_DEC_ENV */
86 #include <ufs/inode.h>
87 #else /* AFS_OSF_ENV */
88 #include <sys/inode.h>
90 #endif /* AFS_VFSINCL_ENV */
91 #endif /* AFS_SGI_ENV */
92 #include <afs/osi_inode.h>
96 #include <afs/afsint.h>
98 #include <afs/afssyscalls.h>
99 #include "viceinode.h"
100 #include <sys/stat.h>
101 #if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
104 #ifdef AFS_PTHREAD_ENV
106 #else /* AFS_PTHREAD_ENV */
107 #include <afs/assert.h>
108 #endif /* AFS_PTHREAD_ENV */
109 #if defined(AFS_HPUX101_ENV)
112 #include "partition.h"
114 /* Notice: parts of this module have been cribbed from vfsck.c */
117 static char *partition;
122 #include <jfs/filsys.h>
125 #define FSBSIZE (4096) /* filesystem block size */
126 #define FSBSHIFT (12) /* log2(FSBSIZE) */
127 #define FSBMASK (FSBSIZE - 1) /* FSBSIZE mask */
129 #define MIN_FSIZE DISKMAP_B /* minimum fs size (FSblocks) */
130 #define LAST_RSVD_I 15 /* last reserved inode */
135 * This will hopefully eventually make it into the system include files
137 #define INOPB (FSBSIZE / sizeof (struct dinode))
145 #endif /* AFS_AIX41_ENV */
148 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
149 XX This was lifted from some `com/cmd/fs/fshlpr_aix3/Fs.h', which indicated X
150 XX a longing to see it make it into a readily accessible include file. XXXXXX
151 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
153 * itoo - inode number to offset within disk block
156 #define itoo(x) (int) ((unsigned)(x) % INOPB)
158 int Bsize = FSBSIZE; /* block size for this system */
159 daddr_t fmax; /* total number of blocks n file system */
160 ino_t imax, inum; /* total number of I-nodes in file system */
162 static struct superblock fs;
163 struct dinode *ginode();
167 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
168 char *devname, *mountedOn, *resultFile, *wpath;
170 int *forcep, forceR; {
171 FILE *inodeFile = NULL;
172 char dev[50], rdev[51];
175 struct ViceInodeInfo info;
176 struct stat root_inode;
177 int ninodes = 0, err = 0;
179 pfd = -1; /* initialize so we don't close on error output below. */
181 sync(); sleep(1); /* simulate operator */
185 partition = mountedOn;
186 sprintf(dev, "/dev/%s", devname);
187 sprintf(rdev, "/dev/r%s", devname);
189 if (stat(mountedOn, &root_inode) < 0) {
190 Log("cannot stat: %s\n", mountedOn);
194 if (root_inode.st_ino != ROOTDIR_I) {
195 Log("%s is not root of a filesystem\n", mountedOn);
201 * done with the superblock, now try to read the raw device.
203 if(ReadSuper(&fs, dev)<0)
208 case FM_CLEAN: /* clean and unmounted */
209 Log("Most peculiar - Super blk in FM_CLEAN state!\n");
211 case FM_MOUNT: /* mounted cleanly */
214 case FM_MDIRTY: /* dirty when mounted or commit fail */
215 case FM_LOGREDO: /* log redo attempted but failed */
216 Log("File system %s is in a bad state.\n", rdev);
217 Log("Call your IBM representative.\n");
221 if (IsBigFilesFileSystem(&fs, (char*)0)) {
222 Log("%s is a big files filesystem, can't salvage.\n", mountedOn);
226 if (strncmp(fs.s_magic, fsv3magic, strlen(fsv3magic)) != 0) {
228 if ((strncmp(fs.s_magic, fsv3pmagic, strlen(fsv3pmagic)) != 0) ||
229 (fs.s_version != fsv3pvers)) {
230 Log("Super block doesn't have the problem magic (%s vs v3magic %s v3pmagic %s)\n",
231 fs.s_magic, fsv3magic, fsv3pmagic);
235 Log("Super block doesn't have the problem magic (%s vs v3magic %s)\n",
236 fs.s_magic, fsv3magic);
243 fragsize = (fs.s_fragsize)? fs.s_fragsize : FSBSIZE;
244 iagsize = (fs.s_iagsize)? fs.s_iagsize : fs.s_agsize;
245 ag512 = fragsize * fs.s_agsize / 512;
246 agblocks = fragsize * fs.s_agsize >> BSHIFT;
247 #endif /* AFS_AIX41_ENV */
249 fmax = fs.s_fsize / (FSBSIZE/512); /* first invalid blk num */
251 pfd = open(rdev, O_RDONLY);
253 Log("Unable to open `%s' inode for reading\n", rdev);
257 inodeFile = fopen(resultFile, "w");
258 if (inodeFile == NULL) {
259 Log("Unable to create inode description file %s\n"
265 * calculate the maximum number of inodes possible
268 imax = iagsize * (fs.s_fsize/ag512) - 1;
269 #else /* AFS_AIX41_ENV */
270 imax = ((fmax / fs.s_agsize +
271 ((fmax % fs.s_agsize) >= fs.s_agsize/INOPB ? 1 : 0))
273 #endif /* AFS_AIX41_ENV */
276 * check for "FORCESALVAGE" equivalent:
277 * LAST_RSVD_I is a vice inode, with dead beef, and
278 * di_nlink == 2 to indicate the FORCE.
280 assert(p = ginode(LAST_RSVD_I));
282 if (p->di_vicemagic == VICEMAGIC
283 && p->di_vicep1 == 0xdeadbeef
284 && p->di_nlink == 2) {
286 idec(root_inode.st_dev, LAST_RSVD_I, 0xdeadbeef);
289 for (inum = LAST_RSVD_I + 1; inum <= imax; ++inum) {
290 if ((p = ginode(inum)) == NULL
291 || p->di_vicemagic != VICEMAGIC
292 || (p->di_mode & IFMT) != IFREG)
295 info.inodeNumber = inum;
296 info.byteCount = p->di_size;
297 info.linkCount = p->di_nlink;
298 info.u.param[0] = p->di_vicep1;
299 info.u.param[1] = p->di_vicep2;
300 info.u.param[2] = p->di_vicep3;
301 info.u.param[3] = p->di_vicep4;
303 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
306 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
307 Log("Error writing inode file for partition %s\n"
314 if (fflush(inodeFile) == EOF) {
315 Log("Unable to successfully flush inode file for %s\n", partition);
319 if (fsync(fileno(inodeFile)) == -1) {
320 Log("Unable to successfully fsync inode file for %s\n", partition);
324 if (fclose(inodeFile) == EOF) {
325 Log("Unable to successfully close inode file for %s\n", partition);
331 * Paranoia: check that the file is really the right size
333 if (stat(resultFile, &status) == -1) {
334 Log("Unable to successfully stat inode file for %s\n", partition);
338 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
339 Log("Wrong size (%d instead of %d) in inode file for %s\n",
340 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
358 /* Read in the superblock for devName */
360 ReadSuper(struct superblock *fs, char *devName)
364 pfd = open(devName, O_RDONLY);
366 Log("Unable to open inode on %s for reading superblock.\n",
371 if (bread(pfd, fs, SUPER_B, sizeof(struct superblock)) < 0) {
372 Log("Unable to read superblock on %s.\n", devName);
380 /* IsBigFilesFileSystem returns 1 if it's a big files filesystem, 0 otherwise. */
382 IsBigFilesFileSystem(struct superblock *sb)
384 if((strncmp(sb->s_magic,fsv3pmagic,4) == 0)
385 && (sb->s_version == fsbigfile)
398 static char buf[FSBSIZE];
399 static daddr_t last_blk = -1;
403 pblk = (ag == 0) ? INODES_B + inum/INOPB
404 : ag*agblocks + (inum - ag*iagsize)/INOPB;
405 #else /* AFS_AIX41_ENV */
406 ag = inum/fs.s_agsize;
407 pblk = (ag == 0) ? INODES_B + inum/INOPB
408 : ag*fs.s_agsize + (inum - ag*fs.s_agsize)/INOPB;
409 #endif /* AFS_AIX41_ENV */
411 if (last_blk != pblk) {
412 if (bread(pfd, buf, pblk, sizeof(buf)) < 0) {
419 dp = (struct dinode *)buf;
424 #else /* !AFS_AIX31_ENV */
426 #if defined(AFS_SGI_ENV)
428 /* libefs.h includes <assert.h>, which we don't want */
431 #ifdef AFS_SGI_EFS_IOPS_ENV
432 #include "sgiefs/libefs.h"
435 /* afs_efs_figet() replaces the SGI library routine because we are malloc'ing
436 * memory for all the inodes on all the cylinder groups without releasing
437 * it when we're done. Using afs_efs_figet ensures more efficient use of
441 afs_efs_figet(EFS_MOUNT *mp, struct efs_dinode *dinodeBuf, int *last_cgno,
444 int cgno = EFS_ITOCG(mp->m_fs, inum);
447 if (cgno != *last_cgno) {
448 if (efs_readb(mp->m_fd, (char *)dinodeBuf, EFS_CGIMIN(mp->m_fs, cgno),
449 mp->m_fs->fs_cgisize) != mp->m_fs->fs_cgisize) {
450 Log("Unable to read inodes for cylinder group %d.\n", cgno);
456 return dinodeBuf + (inum % (mp->m_fs->fs_cgisize*EFS_INOPBB));
461 efs_ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam,
462 forcep, forceR, wpath)
463 char *devname, *mountedOn, *resultFile, *wpath;
467 FILE *inodeFile = NULL;
468 char dev[50], rdev[51];
470 struct efs_dinode *p;
471 struct ViceInodeInfo info;
472 int ninodes = 0, err = 0;
473 struct efs_dinode *dinodeBuf = NULL;
476 ino_t imax, inum; /* total number of I-nodes in file system */
480 partition = mountedOn;
481 sprintf(dev, "/dev/dsk/%s", devname);
482 sprintf(rdev, "/dev/rdsk/%s", devname);
489 if ((stat(rdev, &status) == -1) || ((mp = efs_mount(rdev, O_RDONLY)) == NULL)) {
490 sprintf(rdev, "/dev/r%s", devname);
491 mp = efs_mount(rdev, O_RDONLY);
494 Log("Unable to open `%s' inode for reading\n", rdev);
498 inodeFile = fopen(resultFile, "w");
499 if (inodeFile == NULL) {
500 Log("Unable to create inode description file %s\n"
505 /* Allocate space for one cylinder group's worth of inodes. */
506 dinodeBuf = (struct efs_dinode*)malloc(mp->m_fs->fs_cgisize * BBSIZE);
508 Log("Unable to malloc %lu bytes for inode buffer.\n",
509 mp->m_fs->fs_cgisize * BBSIZE);
514 * calculate the maximum number of inodes possible
516 imax = mp->m_fs->fs_ncg * mp->m_fs->fs_ipcg;
519 for (inum = 2; inum < imax; ++inum) {
520 p = afs_efs_figet(mp, dinodeBuf, &last_cgno, inum);
522 Log("Unable to read all inodes from partition.\n");
525 if (!IS_DVICEMAGIC(p) || !((p->di_mode&IFMT) == IFREG)) {
529 #if defined(AFS_SGI_EXMAG)
531 info.u.param[0] = dmag(p, 0) << 24 | dmag(p, 1) << 16 |
532 dmag(p, 2) << 8 | dmag(p, 3) << 0;
533 if ((p)->di_version == EFS_IVER_AFSSPEC) {
534 info.u.param[1] = INODESPECIAL;
536 info.u.param[2] = dmag(p, 8);
538 info.u.param[3] = dmag(p, 4) << 24 | dmag(p, 5) << 16 |
539 dmag(p, 6) << 8 | dmag(p, 7) << 0;
542 info.u.param[1] = dmag(p, 4) << 16 |
543 dmag(p, 5) << 8 | dmag(p, 6) << 0;
545 info.u.param[2] = dmag(p, 7) << 16 |
546 dmag(p, 8) << 8 | dmag(p, 9) << 0;
548 info.u.param[3] = dmag(p, 10) << 16 |
549 dmag(p, 11) << 8 | (p)->di_spare;
555 info.inodeNumber = inum;
556 info.byteCount = p->di_size;
557 info.linkCount = p->di_nlink;
559 Log("Ino=%d, bytes=%d, linkCnt=%d, [%x,%x,%x,%x]\n", inum, p->di_size, p->di_nlink,
560 info.u.param[0],info.u.param[1],info.u.param[2],info.u.param[3]);
562 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
565 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
566 Log("Error writing inode file for partition %s\n"
573 if (fflush(inodeFile) == EOF) {
574 Log("Unable to successfully flush inode file for %s\n", partition);
578 if (fsync(fileno(inodeFile)) == -1) {
579 Log("Unable to successfully fsync inode file for %s\n", partition);
583 if (fclose(inodeFile) == EOF) {
584 Log("Unable to successfully close inode file for %s\n", partition);
590 * Paranoia: check that the file is really the right size
592 if (stat(resultFile, &status) == -1) {
593 Log("Unable to successfully stat inode file for %s\n", partition);
597 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
598 Log("Wrong size (%d instead of %d) in inode file for %s\n",
599 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
621 #endif /* AFS_SGI_EFS_IOPS_ENV */
623 #ifdef AFS_SGI_XFS_IOPS_ENV
625 #include <afs/xfsattrs.h>
626 /* xfs_ListViceInodes
628 * xfs_ListViceInodes verifies and correct the XFS namespace as it collects
629 * the inode information. The name is required for the idec operation to work.
630 * Steps 2 and 3 below are for the AFS_XFS_NAME_VERS == 1. If the name space
631 * changes, the algorithm will need to change.
632 * 1) If the parent inode number does not match the directory's inod number,
633 * change it in the attribute.
634 * 2) If the unqifier in the attribute does not match the name, rename the
635 * file. This is done by doing an exclusive open, incrementing the tag
636 * number until a file can be created. If the tag changes, then the
637 * attribute will need updating.
638 * 3) If the tag in the attribute does not match the name, change the
640 * 4) Verify uid = RW volume id and gid = XFS_VICEMAGIC.
646 * Does the verifications listed above.
647 * We can't change the names until the readdir is complete, so we set the
648 * rename flag if the file needs renaming.
650 int xfs_VerifyInode(char *dir, uint64_t pino, char *name, i_list_inode_t *info,
657 int update_chown = 0;
664 (void) sprintf(path, "%s/%s", dir, name);
665 /* Verify uid and gid fields */
666 if (info->ili_magic != XFS_VICEMAGIC) {
667 Log("%s magic for %s/%s (inode %s) from %d to %d\n",
668 Testing ? "Would have changed" : "Changing",
669 dir, name, PrintInode(NULL, info->ili_info.inodeNumber),
670 info->ili_magic, XFS_VICEMAGIC);
675 vno = info->ili_info.param[0];
676 if (info->ili_vno != AFS_XFS_VNO_CLIP(vno)) {
677 Log("%s volume id for %s/%s (inode %s) from %d to %d\n",
678 Testing ? "Would have changed" : "Changing",
679 dir, name, PrintInode(NULL, info->ili_info.inodeNumber),
680 info->ili_vno , AFS_XFS_VNO_CLIP(vno));
686 if (chown(path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC)<0) {
687 Log("Can't chown %s to uid=%d, gid=0x%x\n",
688 path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC);
693 /* Check Parent inode number. */
694 if (info->ili_pino != pino) {
695 afs_ino_str_t sino, sipino, spino;
696 (void) PrintInode(sino, info->ili_info.inodeNumber);
697 (void) PrintInode(sipino, info->ili_pino);
698 (void) PrintInode(spino, pino);
699 Log("%s parent ino for %s (inode %s) from %s to %s.\n",
700 Testing ? "Would have changed" : "Changing",
701 path, sino, sipino, spino);
706 /* Verify the file name. */
707 (void) strcpy(tmpName, ".");
708 (void) strcat(tmpName, int_to_base64(stmp, info->ili_info.param[2]));
709 if (strncmp(name, tmpName, strlen(tmpName))) {
710 Log("%s name %s (inode %s) in directory %s, unique=%d, tag=%d\n",
711 Testing ? "Would have returned bad" : "Bad",
712 name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
713 info->ili_info.param[2], info->ili_tag);
719 /* update the tag? */
720 (void) strcat(tmpName, ".");
721 (void) strcat(tmpName, int_to_base64(stmp, info->ili_tag));
722 if (strcmp(name, tmpName)) {
724 (void) strcpy(tmpName, name);
725 p = strchr(tmpName+1, '.');
727 Log("No tag found on name %s (inode %s)in directory, %s.\n",
728 name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
729 Testing ? "would have renamed" : "will rename");
734 tag = base64_to_int(p+1);
735 Log("%s the tag for %s (inode %s) from %d to %d.\n",
736 Testing ? "Would have changed" : "Will change",
737 path, PrintInode(NULL, info->ili_info.inodeNumber), dir,
745 if (update_pino || update_tag) {
746 afs_xfs_attr_t attrs;
749 length = SIZEOF_XFS_ATTR_T;
750 if (attr_get(path, AFS_XFS_ATTR, (char*)&attrs, &length, ATTR_ROOT)<0) {
751 Log("Can't get AFS attribute for %s\n", path);
755 attrs.at_pino = pino;
758 if(attr_set(path, AFS_XFS_ATTR, (char*)&attrs, length,
759 ATTR_ROOT|ATTR_REPLACE)<0) {
760 Log("Can't set AFS attribute into %s\n", path);
773 int xfs_RenameFiles(char *dir, xfs_Rename_t *renames, int n_renames)
776 char opath[128], nbase[128], npath[128];
777 afs_xfs_attr_t attrs;
778 int length = SIZEOF_XFS_ATTR_T;
783 for (i=0; i<n_renames; i++) {
784 (void) sprintf(opath, "%s/%s", dir, renames[i].name);
785 (void) sprintf(nbase, "%s/.%s", dir, int_to_base64(stmp, renames[i].uniq));
786 for (tag=2, j=0; j<64; tag++, j++) {
787 (void) sprintf(npath, "%s.%s", nbase, int_to_base64(stmp, tag));
788 fd = open(npath, O_CREAT|O_EXCL|O_RDWR, 0);
795 Log("Can't find a new name for %s\n", opath);
798 if (rename(opath, npath)<0) {
799 Log("Can't rename %s to %s\n", opath, npath);
802 Log("Renamed %s to %s\n", opath, npath);
808 xfs_ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam,
809 forcep, forceR, wpath)
810 char *devname, *mountedOn, *resultFile, *wpath;
814 FILE *inodeFile = NULL;
816 int info_size = sizeof(i_list_inode_t);
819 dirent64_t *top_direntp;
821 dirent64_t *vol_direntp;
822 struct stat64 sdirbuf;
823 struct stat64 sfilebuf;
824 afs_xfs_attr_t attrs;
825 afs_xfs_dattr_t dattrs;
827 char vol_dirname[1024];
830 xfs_Rename_t *renames = (xfs_Rename_t*)0;
832 #define N_RENAME_STEP 64
841 if (stat64(mountedOn, &sdirbuf)<0) {
842 perror("xfs_ListViceInodes: stat64");
846 inodeFile = fopen(resultFile, "w");
847 if (inodeFile == NULL) {
848 Log("Unable to create inode description file %s\n", resultFile);
852 if ((top_dirp=opendir(mountedOn)) == NULL) {
853 Log("Can't open directory %s to read inodes.\n", mountedOn);
857 while (top_direntp=readdir64(top_dirp)) {
858 /* Only descend directories with the AFSDIR attribute set.
859 * Could also verify the contents of the atribute, but currently
861 * Performance could be improved for single volume salvages by
862 * only going through the directory containing the volume's inodes.
863 * But I'm being complete as a first pass.
865 (void) sprintf(vol_dirname, "%s/%s", mountedOn, top_direntp->d_name);
866 length = SIZEOF_XFS_DATTR_T;
867 if (attr_get(vol_dirname, AFS_XFS_DATTR, (char*)&dattrs, &length,
871 if ((vol_dirp=opendir(vol_dirname)) == NULL) {
872 if (errno == ENOTDIR)
874 Log("Can't open directory %s to read inodes.\n", vol_dirname);
878 pino = top_direntp->d_ino;
880 while (vol_direntp=readdir64(vol_dirp)) {
881 if (vol_direntp->d_name[1] == '\0'
882 || vol_direntp->d_name[1] == '.')
885 info.ili_version = AFS_XFS_ILI_VERSION;
886 info_size = sizeof(i_list_inode_t);
887 code = ilistinode64(sdirbuf.st_dev, vol_direntp->d_ino,
890 /* Where possible, give more explicit messages. */
894 Log("%s (device id %d) is not on an XFS filesystem.\n",
895 vol_dirname, sdirbuf.st_dev);
900 if (info_size != sizeof(i_list_inode_t) ||
901 info.ili_version != AFS_XFS_ILI_VERSION) {
902 Log("Version skew between kernel and salvager.\n");
907 /* Continue, so we collect all the errors in the first pass.*/
908 Log("Error listing inode named %s/%s: %s\n",
909 vol_dirname, vol_direntp->d_name, strerror(errno));
914 if (info.ili_attr_version != AFS_XFS_ATTR_VERS) {
915 Log("Unrecognized XFS attribute version %d in %s/%s. Upgrade salvager\n",
916 info.ili_attr_version, vol_dirname, vol_direntp->d_name);
920 if (judgeInode && (*judgeInode)(&info.ili_info, judgeParam) == 0)
924 if (xfs_VerifyInode(vol_dirname, pino, vol_direntp->d_name,
930 /* Add this name to the list of items to rename. */
931 if (n_renames >= n_avail) {
932 n_avail += N_RENAME_STEP;
933 if (n_avail == N_RENAME_STEP)
934 renames = (xfs_Rename_t*)
935 malloc(n_avail*sizeof(xfs_Rename_t));
937 renames = (xfs_Rename_t*)
938 realloc((char*)renames,
939 n_avail * sizeof(xfs_Rename_t));
941 Log("Can't %salloc %lu bytes for rename list.\n",
942 (n_avail == N_RENAME_STEP) ? "m" : "re",
943 n_avail * sizeof(xfs_Rename_t));
947 (void) strcpy(renames[n_renames].name, vol_direntp->d_name);
948 renames[n_renames].uniq = info.ili_info.param[2];
952 if (fwrite(&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile)
954 Log("Error writing inode file for partition %s\n", mountedOn);
959 } /* end while vol_direntp */
964 Log("Renaming files.\n");
965 if (xfs_RenameFiles(vol_dirname, renames, n_renames)<0) {
973 free((char*)renames);
974 if (fflush(inodeFile) == EOF) {
975 ("Unable to successfully flush inode file for %s\n", mountedOn);
977 return errors ? -1 : -2;
979 if (fsync(fileno(inodeFile)) == -1) {
980 Log("Unable to successfully fsync inode file for %s\n", mountedOn);
982 return errors ? -1 : -2;
984 if (fclose(inodeFile) == EOF) {
985 Log("Unable to successfully close inode file for %s\n", mountedOn);
986 return errors ? -1 : -2;
989 * Paranoia: check that the file is really the right size
991 if (stat(resultFile, &status) == -1) {
992 Log("Unable to successfully stat inode file for %s\n", partition);
993 return errors ? -1 : -2;
995 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
996 Log("Wrong size (%d instead of %d) in inode file for %s\n",
997 status.st_size, ninodes * sizeof (struct ViceInodeInfo),
999 return errors ? -1 : -2;
1003 Log("Errors encontered listing inodes, not salvaging partition.\n");
1015 free((char*)renames);
1023 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep,
1025 char *devname, *mountedOn, *resultFile, *wpath;
1026 int (*judgeInode)();
1027 int *forcep, forceR;
1029 FILE *inodeFile = NULL;
1030 char dev[50], rdev[51];
1032 struct efs_dinode *p;
1033 struct ViceInodeInfo info;
1034 struct stat root_inode;
1035 int ninodes = 0, err = 0;
1036 struct efs_dinode *dinodeBuf = NULL;
1038 #ifdef AFS_SGI_EFS_IOPS_ENV
1041 ino_t imax, inum; /* total number of I-nodes in file system */
1044 sync(); sleep(1); /* simulate operator */
1048 if (stat(mountedOn, &root_inode) < 0) {
1049 Log("cannot stat: %s\n", mountedOn);
1054 #ifdef AFS_SGI_XFS_IOPS_ENV
1055 if (!strcmp("xfs", root_inode.st_fstype)) {
1056 return xfs_ListViceInodes(devname, mountedOn, resultFile,
1057 judgeInode, judgeParam,
1058 forcep, forceR, wpath);
1062 #ifdef AFS_SGI_EFS_IOPS_ENV
1063 if (root_inode.st_ino == EFS_ROOTINO) {
1064 return efs_ListViceInodes(devname, mountedOn, resultFile,
1065 judgeInode, judgeParam,
1066 forcep, forceR, wpath);
1071 Log("%s is not root of a filesystem\n", mountedOn);
1076 #else /* AFS_SGI_ENV */
1079 #define SPERB (MAXBSIZE / sizeof(short))
1080 #define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
1083 struct bufarea *b_next; /* must be first */
1087 char b_buf[MAXBSIZE]; /* buffer space */
1088 short b_lnks[SPERB]; /* link counts */
1089 daddr_t b_indir[MAXNINDIR]; /* indirect block */
1090 struct fs b_fs; /* super block */
1091 struct cg b_cg; /* cylinder group */
1095 typedef struct bufarea BUFAREA;
1098 #define sblock sblk.b_un.b_fs
1099 #endif /* AFS_HPUX_ENV */
1101 extern char *afs_rawname();
1102 int ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
1103 char *devname, *mountedOn, *resultFile, *wpath;
1104 int (*judgeInode)(), *forcep, forceR;
1110 #else /* !AFS_AIX_ENV */
1115 int i, c, e, bufsize, code, err =0;
1116 FILE *inodeFile = NULL;
1117 char dev[50], rdev[100], err1[512], *ptr1;
1118 struct dinode *inodes = NULL, *einodes, *dptr;
1122 struct ViceInodeInfo info;
1125 partition = mountedOn;
1126 sprintf(rdev, "%s/%s", wpath, devname);
1127 ptr1 = afs_rawname(rdev);
1131 /* Bletch: this is terrible; is there a better way to do this? Does this work? vfsck doesn't even sleep!! */
1133 sleep(5); /* Trying a smaller one for aix */
1138 pfd = open(rdev, O_RDONLY);
1140 sprintf(err1, "Could not open device %s to get inode list\n", rdev);
1147 if (bread(pfd, (char *)&super.fs, SUPERB, sizeof super.fs) == -1) {
1150 if (bread(pfd, (char *)&sblock, SBLOCK, SBSIZE) == -1) {
1152 if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
1153 #endif /* AFS_HPUX_ENV */
1155 Log("Unable to read superblock, partition %s\n", partition);
1159 inodeFile = fopen(resultFile, "w");
1160 if (inodeFile == NULL) {
1161 Log("Unable to create inode description file %s\n", resultFile);
1167 char *FSlabel(), *fslabel=0;
1168 fslabel = FSlabel(&super.fs);
1170 if (super.fs.s_bsize == 0)
1171 super.fs.s_bsize = 512;
1172 if (super.fs.s_bsize != BSIZE ) {
1173 Log("SuperBlk: Cluster size not %d; run vfsck\n", BSIZE);
1176 fmax = super.fs.s_fsize; /* first invalid blk num */
1177 imax = ((ino_t)super.fs.s_isize - (SUPERB+1)) * INOPB;
1179 Log("Size check: imax==0!\n");
1182 if (GetAuxInodeFile(partition, &status) == 0) {
1183 Log("Can't access Aux inode file for partition %s, aborting\n", partition);
1186 for (inum=1; inum <= imax; inum++) {
1187 struct dauxinode *auxp;
1188 if ((auxp = IsAfsInode(inum)) == NULL){
1189 /* Not an afs inode, keep going */
1192 if ((p = ginode(inum)) == NULL)
1194 /* deleted/non-existent inode when di_mode == 0 */
1197 info.inodeNumber = (int)inum;
1198 info.byteCount = p->di_size;
1199 info.linkCount = p->di_nlink;
1200 info.u.param[0] = auxp->aux_param1;
1201 info.u.param[1] = auxp->aux_param2;
1202 info.u.param[2] = auxp->aux_param3;
1203 info.u.param[3] = auxp->aux_param4;
1204 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
1206 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1207 Log("Error writing inode file for partition %s\n", partition);
1214 * run a few consistency checks of the superblock
1215 * (Cribbed from vfsck)
1218 #if defined(FD_FSMAGIC)
1219 if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN) && (sblock.fs_magic != FD_FSMAGIC)
1220 #if defined(AFS_HPUX101_ENV)
1221 && ( sblock.fs_magic != FD_FSMAGIC_2)
1226 if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)) {
1228 Log("There's something wrong with the superblock for partition %s; bad magic (%d) run vfsck\n",
1229 partition, sblock.fs_magic);
1232 if (sblock.fs_ncg < 1 ) {
1233 Log("There's something wrong with the superblock for partition %s; NCG OUT OF RANGE (%d) run vfsck\n",
1234 partition, sblock.fs_ncg);
1237 if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG ) {
1238 Log("There's something wrong with the superblock for partition %s; CPG OUT OF RANGE (%d) run vfsck\n",
1239 partition, sblock.fs_cpg);
1242 if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
1243 (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) {
1244 Log("There's something wrong with the superblock for partition %s; NCYL LESS THAN NCG*CPG run vfsck\n", partition);
1247 if (sblock.fs_sbsize > SBSIZE ) {
1248 Log("There's something wrong with the superblock for partition %s; bsize too large (%d vs. %d) run vfsck\n",
1249 partition, sblock.fs_sbsize, sblock.fs_bsize);
1255 (super.fs.fs_magic != FS_MAGIC)
1256 || (super.fs.fs_ncg < 1)
1257 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1258 || (super.fs.fs_cpg < 1)
1260 || (super.fs.fs_cpg < 1 || super.fs.fs_cpg > MAXCPG)
1262 || (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl ||
1263 (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
1264 || (super.fs.fs_sbsize > SBSIZE)) {
1265 Log("There's something wrong with the superblock for partition %s; run vfsck\n", partition);
1268 #endif /* AFS_HPUX_ENV */
1271 bufsize = sblock.fs_ipg * sizeof(struct dinode);
1273 bufsize = super.fs.fs_ipg * sizeof(struct dinode);
1274 #endif /* AFS_HPUX_ENV */
1275 inodes = (struct dinode *) malloc(bufsize);
1276 einodes = (struct dinode *) (((char *)inodes) + bufsize);
1277 if (inodes == NULL) {
1278 Log("Unable to allocate enough memory to scan inodes; help!\n");
1281 Log("Scanning inodes on device %s...\n", rdev);
1283 for (c = 0; c < sblock.fs_ncg; c++) {
1284 i = c*sblock.fs_ipg; e = i+sblock.fs_ipg;
1285 #if defined(AFS_HPUX102_ENV)
1286 if (lseek(pfd, dbtoo(fsbtodb(&sblock,itod(&sblock,i))), L_SET) == -1) {
1288 if (lseek(pfd, dbtob(fsbtodb(&sblock,itod(&sblock,i))), L_SET) == -1) {
1291 for (c = 0; c < super.fs.fs_ncg; c++) {
1293 #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
1295 #if defined(AFS_DARWIN_ENV)
1296 #define offset_t off_t
1297 #define llseek lseek
1300 #endif /* AFS_SUN5_ENV */
1301 i = c*super.fs.fs_ipg; e = i+super.fs.fs_ipg;
1303 dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
1304 if (lseek(pfd, (off_t) ((off_t)dblk1 * DEV_BSIZE), L_SET) == -1) {
1306 #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
1307 f1 = fsbtodb(&super.fs,itod(&super.fs,i));
1308 off = (offset_t)f1 << DEV_BSHIFT;
1309 if (llseek(pfd, off, L_SET) == -1) {
1311 if (lseek(pfd, dbtob(fsbtodb(&super.fs,itod(&super.fs,i))), L_SET) == -1) {
1312 #endif /* AFS_SUN5_ENV */
1313 #endif /* AFS_OSF_ENV */
1314 #endif /* AFS_HPUX_ENV */
1315 Log("Error reading inodes for partition %s; run vfsck\n", partition);
1320 if (read(pfd, inodes, bufsize) != bufsize) {
1321 Log("Error reading inodes for partition %s; run vfsck\n", partition);
1325 register int bj, bk;
1327 for (bj=bk=0; bj < bufsize; bj=bj+512, bk++) {
1328 if ((code = read(pfd, dptr, 512)) != 512) {
1329 Log("Error reading inode %d? for partition %s (errno = %d); run vfsck\n", bk+i, partition, errno);
1330 if (lseek(pfd, 512, L_SET) == -1) {
1331 Log("Lseek failed\n");
1334 dptr->di_mode = 0; dptr++;
1335 dptr->di_mode = 0; dptr++;
1336 dptr->di_mode = 0; dptr++;
1337 dptr->di_mode = 0; dptr++;
1342 for (p=inodes; p<einodes && i<e; i++,p++) {
1344 Log("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n", i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode, p->di_size, p->di_nlink);
1345 printf("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n", i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode, p->di_size, p->di_nlink);
1348 #ifdef AFS_3DISPARES
1349 /* Check to see if this inode is a pre-"OSF1 4.0D" inode */
1350 if ((p->di_uid || p->di_gid)
1351 && !(p->di_flags & (IC_XUID|IC_XGID))) {
1352 Log("Found unconverted inode %d: Use 'fs_conv_dux40D convert' on partition %s\n",
1357 assert(0); /* define AFS_3DISPARES in param.h */
1360 #if defined(AFS_SUN56_ENV)
1361 /* if this is a pre-sol2.6 unconverted inode, bail out */
1363 afs_uint32 p1, p2, p3, p4;
1367 q = (quad *)&(p->di_ic.ic_lsize);
1369 p2 = p->di_ic.ic_flags;
1371 p4 = p->di_ic.ic_uid;
1372 p5 = p->di_ic.ic_gid;
1374 if ( (p2 || p3) && !p4 && (p5 == -2) )
1376 Log("Found unconverted inode %d\n", i);
1377 Log("You should run the AFS file conversion utility\n");
1382 if (IS_DVICEMAGIC(p) && (p->di_mode&IFMT) == IFREG) {
1383 afs_uint32 p2 = p->di_vicep2, p3 = DI_VICEP3(p);
1385 info.u.param[0] = p->di_vicep1;
1386 #ifdef AFS_3DISPARES
1387 if (((p2 >> 3) == INODESPECIAL) && (p2 & 0x3)) {
1388 info.u.param[1] = INODESPECIAL;
1389 info.u.param[2] = p3;
1390 info.u.param[3] = p2 & 0x3;
1392 info.u.param[1] = ((p2 >> 27) << 16) + (p3 & 0xffff);
1393 info.u.param[2] = (p2 & 0x3fffff);
1394 info.u.param[3] = (((p2 >> 22) & 0x1f) << 16) + (p3 >> 16);
1397 info.u.param[1] = p->di_vicep2;
1398 info.u.param[2] = DI_VICEP3(p);
1399 info.u.param[3] = p->di_vicep4;
1401 info.inodeNumber = i;
1402 info.byteCount = p->di_size;
1403 info.linkCount = p->di_nlink;
1404 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
1406 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1407 Log("Error writing inode file for partition %s\n", partition);
1415 if (inodes) free(inodes);
1417 if (fflush(inodeFile) == EOF) {
1418 Log("Unable to successfully flush inode file for %s\n", partition);
1422 if (fsync(fileno(inodeFile)) == -1) {
1423 Log("Unable to successfully fsync inode file for %s\n", partition);
1427 if (fclose(inodeFile) == EOF) {
1428 Log("Unable to successfully close inode file for %s\n", partition);
1434 * Paranoia: check that the file is really the right size
1436 if (stat(resultFile, &status) == -1) {
1437 Log("Unable to successfully stat inode file for %s\n", partition);
1441 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
1442 Log("Wrong size (%d instead of %d) in inode file for %s\n",
1443 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
1460 #endif /* !AFS_SGI_ENV */
1461 #endif /* !AFS_AIX31_ENV */
1463 #ifdef AFS_DARWIN_ENV
1465 #define dbtob(db) ((unsigned)(db) << DEV_BSHIFT)
1468 int bread(fd, buf, blk, size)
1475 #ifdef AFS_AIX41_ENV
1476 offset_t off = (offset_t)blk << FSBSHIFT;
1477 if (llseek(fd, off, 0) < 0) {
1478 Log("Unable to seek to offset %llu for block %u\n", off, blk);
1481 #else /* AFS_AIX41_ENV */
1482 if (lseek(fd, blk * Bsize, 0) < 0) {
1483 Log("Unable to seek to offset %u for block %u\n",
1486 #endif /* AFS_AIX41_ENV */
1488 if (lseek(fd, (off_t)dbtob(blk), L_SET) < 0) {
1489 Log("Unable to seek to offset %u for block %u\n",
1493 if (read(fd, buf, size) != size) {
1494 Log("Unable to read block %d, partition %s\n", blk, partition);
1500 #endif /* AFS_LINUX20_ENV */
1501 #endif /* AFS_NAMEI_ENV */