6 * (C) COPYRIGHT IBM CORPORATION 1987
7 * LICENSED MATERIALS - PROPERTY OF IBM
13 Institution: The Information Technology Center, Carnegie-Mellon University
17 #define ITC /* Required by inode.h */
19 #include <afs/param.h>
21 #ifdef AFS_LINUX20_ENV
26 * -1 - Unable to read the inodes.
27 * -2 - Unable to completely write temp file. Produces warning message in log.
29 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
30 char *devname, *mountedOn, *resultFile, *wpath;
34 Log("ListViceInodes not implemented for Linux\n");
39 #include <sys/param.h>
40 #if defined(AFS_SGI_ENV)
44 #else /* AFS_OSF_ENV */
45 #ifdef AFS_VFSINCL_ENV
48 #include <sys/fs/ufs_fs.h>
52 #else /* AFS_VFSINCL_ENV */
54 #include <sys/filsys.h>
58 #endif /* AFS_VFSINCL_ENV */
59 #endif /* AFS_OSF_ENV */
61 #ifdef AFS_VFSINCL_ENV
62 #include <sys/vnode.h>
64 #include <sys/fs/ufs_inode.h>
66 #include <ufs/inode.h>
68 #else /* AFS_VFSINCL_ENV */
71 #endif /* AFS_DEC_ENV */
73 #include <ufs/inode.h>
74 #else /* AFS_OSF_ENV */
75 #include <sys/inode.h>
77 #endif /* AFS_VFSINCL_ENV */
78 #endif /* AFS_SGI_ENV */
79 #include <afs/osi_inode.h>
83 #include <afs/afsint.h>
85 #include <afs/afssyscalls.h>
86 #include "viceinode.h"
88 #if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
91 #ifdef AFS_PTHREAD_ENV
93 #else /* AFS_PTHREAD_ENV */
94 #include <afs/assert.h>
95 #endif /* AFS_PTHREAD_ENV */
96 #if defined(AFS_HPUX101_ENV)
99 #include "partition.h"
101 /* Notice: parts of this module have been cribbed from vfsck.c */
104 static char *partition;
109 #include <jfs/filsys.h>
112 #define FSBSIZE (4096) /* filesystem block size */
113 #define FSBSHIFT (12) /* log2(FSBSIZE) */
114 #define FSBMASK (FSBSIZE - 1) /* FSBSIZE mask */
116 #define MIN_FSIZE DISKMAP_B /* minimum fs size (FSblocks) */
117 #define LAST_RSVD_I 15 /* last reserved inode */
122 * This will hopefully eventually make it into the system include files
124 #define INOPB (FSBSIZE / sizeof (struct dinode))
132 #endif /* AFS_AIX41_ENV */
135 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
136 XX This was lifted from some `com/cmd/fs/fshlpr_aix3/Fs.h', which indicated X
137 XX a longing to see it make it into a readily accessible include file. XXXXXX
138 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
140 * itoo - inode number to offset within disk block
143 #define itoo(x) (int) ((unsigned)(x) % INOPB)
145 int Bsize = FSBSIZE; /* block size for this system */
146 daddr_t fmax; /* total number of blocks n file system */
147 ino_t imax, inum; /* total number of I-nodes in file system */
149 static struct superblock fs;
150 struct dinode *ginode();
154 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
155 char *devname, *mountedOn, *resultFile, *wpath;
157 int *forcep, forceR; {
158 FILE *inodeFile = NULL;
159 char dev[50], rdev[51];
162 struct ViceInodeInfo info;
163 struct stat root_inode;
164 int ninodes = 0, err = 0;
166 pfd = -1; /* initialize so we don't close on error output below. */
168 sync(); sleep(1); /* simulate operator */
172 partition = mountedOn;
173 sprintf(dev, "/dev/%s", devname);
174 sprintf(rdev, "/dev/r%s", devname);
176 if (stat(mountedOn, &root_inode) < 0) {
177 Log("cannot stat: %s\n", mountedOn);
181 if (root_inode.st_ino != ROOTDIR_I) {
182 Log("%s is not root of a filesystem\n", mountedOn);
188 * done with the superblock, now try to read the raw device.
190 if(ReadSuper(&fs, dev)<0)
195 case FM_CLEAN: /* clean and unmounted */
196 Log("Most peculiar - Super blk in FM_CLEAN state!\n");
198 case FM_MOUNT: /* mounted cleanly */
201 case FM_MDIRTY: /* dirty when mounted or commit fail */
202 case FM_LOGREDO: /* log redo attempted but failed */
203 Log("File system %s is in a bad state.\n", rdev);
204 Log("Call your IBM representative.\n");
208 if (IsBigFilesFileSystem(&fs, (char*)0)) {
209 Log("%s is a big files filesystem, can't salvage.\n", mountedOn);
213 if (strncmp(fs.s_magic, fsv3magic, strlen(fsv3magic)) != 0) {
215 if ((strncmp(fs.s_magic, fsv3pmagic, strlen(fsv3pmagic)) != 0) ||
216 (fs.s_version != fsv3pvers)) {
217 Log("Super block doesn't have the problem magic (%s vs v3magic %s v3pmagic %s)\n",
218 fs.s_magic, fsv3magic, fsv3pmagic);
222 Log("Super block doesn't have the problem magic (%s vs v3magic %s)\n",
223 fs.s_magic, fsv3magic);
230 fragsize = (fs.s_fragsize)? fs.s_fragsize : FSBSIZE;
231 iagsize = (fs.s_iagsize)? fs.s_iagsize : fs.s_agsize;
232 ag512 = fragsize * fs.s_agsize / 512;
233 agblocks = fragsize * fs.s_agsize >> BSHIFT;
234 #endif /* AFS_AIX41_ENV */
236 fmax = fs.s_fsize / (FSBSIZE/512); /* first invalid blk num */
238 pfd = open(rdev, O_RDONLY);
240 Log("Unable to open `%s' inode for reading\n", rdev);
244 inodeFile = fopen(resultFile, "w");
245 if (inodeFile == NULL) {
246 Log("Unable to create inode description file %s\n"
252 * calculate the maximum number of inodes possible
255 imax = iagsize * (fs.s_fsize/ag512) - 1;
256 #else /* AFS_AIX41_ENV */
257 imax = ((fmax / fs.s_agsize +
258 ((fmax % fs.s_agsize) >= fs.s_agsize/INOPB ? 1 : 0))
260 #endif /* AFS_AIX41_ENV */
263 * check for "FORCESALVAGE" equivalent:
264 * LAST_RSVD_I is a vice inode, with dead beef, and
265 * di_nlink == 2 to indicate the FORCE.
267 assert(p = ginode(LAST_RSVD_I));
269 if (p->di_vicemagic == VICEMAGIC
270 && p->di_vicep1 == 0xdeadbeef
271 && p->di_nlink == 2) {
273 idec(root_inode.st_dev, LAST_RSVD_I, 0xdeadbeef);
276 for (inum = LAST_RSVD_I + 1; inum <= imax; ++inum) {
277 if ((p = ginode(inum)) == NULL
278 || p->di_vicemagic != VICEMAGIC
279 || (p->di_mode & IFMT) != IFREG)
282 info.inodeNumber = inum;
283 info.byteCount = p->di_size;
284 info.linkCount = p->di_nlink;
285 info.u.param[0] = p->di_vicep1;
286 info.u.param[1] = p->di_vicep2;
287 info.u.param[2] = p->di_vicep3;
288 info.u.param[3] = p->di_vicep4;
290 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
293 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
294 Log("Error writing inode file for partition %s\n"
301 if (fflush(inodeFile) == EOF) {
302 Log("Unable to successfully flush inode file for %s\n", partition);
306 if (fsync(fileno(inodeFile)) == -1) {
307 Log("Unable to successfully fsync inode file for %s\n", partition);
311 if (fclose(inodeFile) == EOF) {
312 Log("Unable to successfully close inode file for %s\n", partition);
318 * Paranoia: check that the file is really the right size
320 if (stat(resultFile, &status) == -1) {
321 Log("Unable to successfully stat inode file for %s\n", partition);
325 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
326 Log("Wrong size (%d instead of %d) in inode file for %s\n",
327 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
345 /* Read in the superblock for devName */
347 ReadSuper(struct superblock *fs, char *devName)
351 pfd = open(devName, O_RDONLY);
353 Log("Unable to open inode on %s for reading superblock.\n",
358 if (bread(pfd, fs, SUPER_B, sizeof(struct superblock)) < 0) {
359 Log("Unable to read superblock on %s.\n", devName);
367 /* IsBigFilesFileSystem returns 1 if it's a big files filesystem, 0 otherwise. */
369 IsBigFilesFileSystem(struct superblock *sb)
371 if((strncmp(sb->s_magic,fsv3pmagic,4) == 0)
372 && (sb->s_version == fsbigfile)
385 static char buf[FSBSIZE];
386 static daddr_t last_blk = -1;
390 pblk = (ag == 0) ? INODES_B + inum/INOPB
391 : ag*agblocks + (inum - ag*iagsize)/INOPB;
392 #else /* AFS_AIX41_ENV */
393 ag = inum/fs.s_agsize;
394 pblk = (ag == 0) ? INODES_B + inum/INOPB
395 : ag*fs.s_agsize + (inum - ag*fs.s_agsize)/INOPB;
396 #endif /* AFS_AIX41_ENV */
398 if (last_blk != pblk) {
399 if (bread(pfd, buf, pblk, sizeof(buf)) < 0) {
406 dp = (struct dinode *)buf;
411 #else /* !AFS_AIX31_ENV */
413 #if defined(AFS_SGI_ENV)
415 /* libefs.h includes <assert.h>, which we don't want */
418 #include "../sgiefs/libefs.h"
421 /* afs_efs_figet() replaces the SGI library routine because we are malloc'ing
422 * memory for all the inodes on all the cylinder groups without releasing
423 * it when we're done. Using afs_efs_figet ensures more efficient use of
427 afs_efs_figet(EFS_MOUNT *mp, struct efs_dinode *dinodeBuf, int *last_cgno,
430 int cgno = EFS_ITOCG(mp->m_fs, inum);
433 if (cgno != *last_cgno) {
434 if (efs_readb(mp->m_fd, (char *)dinodeBuf, EFS_CGIMIN(mp->m_fs, cgno),
435 mp->m_fs->fs_cgisize) != mp->m_fs->fs_cgisize) {
436 Log("Unable to read inodes for cylinder group %d.\n", cgno);
442 return dinodeBuf + (inum % (mp->m_fs->fs_cgisize*EFS_INOPBB));
447 efs_ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam,
448 forcep, forceR, wpath)
449 char *devname, *mountedOn, *resultFile, *wpath;
453 FILE *inodeFile = NULL;
454 char dev[50], rdev[51];
456 struct efs_dinode *p;
457 struct ViceInodeInfo info;
458 int ninodes = 0, err = 0;
459 struct efs_dinode *dinodeBuf = NULL;
462 ino_t imax, inum; /* total number of I-nodes in file system */
466 partition = mountedOn;
467 sprintf(dev, "/dev/dsk/%s", devname);
468 sprintf(rdev, "/dev/rdsk/%s", devname);
475 if ((stat(rdev, &status) == -1) || ((mp = efs_mount(rdev, O_RDONLY)) == NULL)) {
476 sprintf(rdev, "/dev/r%s", devname);
477 mp = efs_mount(rdev, O_RDONLY);
480 Log("Unable to open `%s' inode for reading\n", rdev);
484 inodeFile = fopen(resultFile, "w");
485 if (inodeFile == NULL) {
486 Log("Unable to create inode description file %s\n"
491 /* Allocate space for one cylinder group's worth of inodes. */
492 dinodeBuf = (struct efs_dinode*)malloc(mp->m_fs->fs_cgisize * BBSIZE);
494 Log("Unable to malloc %lu bytes for inode buffer.\n",
495 mp->m_fs->fs_cgisize * BBSIZE);
500 * calculate the maximum number of inodes possible
502 imax = mp->m_fs->fs_ncg * mp->m_fs->fs_ipcg;
505 for (inum = 2; inum < imax; ++inum) {
506 p = afs_efs_figet(mp, dinodeBuf, &last_cgno, inum);
508 Log("Unable to read all inodes from partition.\n");
511 if (!IS_DVICEMAGIC(p) || !((p->di_mode&IFMT) == IFREG)) {
515 #if defined(AFS_SGI_EXMAG)
517 info.u.param[0] = dmag(p, 0) << 24 | dmag(p, 1) << 16 |
518 dmag(p, 2) << 8 | dmag(p, 3) << 0;
519 if ((p)->di_version == EFS_IVER_AFSSPEC) {
520 info.u.param[1] = INODESPECIAL;
522 info.u.param[2] = dmag(p, 8);
524 info.u.param[3] = dmag(p, 4) << 24 | dmag(p, 5) << 16 |
525 dmag(p, 6) << 8 | dmag(p, 7) << 0;
528 info.u.param[1] = dmag(p, 4) << 16 |
529 dmag(p, 5) << 8 | dmag(p, 6) << 0;
531 info.u.param[2] = dmag(p, 7) << 16 |
532 dmag(p, 8) << 8 | dmag(p, 9) << 0;
534 info.u.param[3] = dmag(p, 10) << 16 |
535 dmag(p, 11) << 8 | (p)->di_spare;
541 info.inodeNumber = inum;
542 info.byteCount = p->di_size;
543 info.linkCount = p->di_nlink;
545 Log("Ino=%d, bytes=%d, linkCnt=%d, [%x,%x,%x,%x]\n", inum, p->di_size, p->di_nlink,
546 info.u.param[0],info.u.param[1],info.u.param[2],info.u.param[3]);
548 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
551 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
552 Log("Error writing inode file for partition %s\n"
559 if (fflush(inodeFile) == EOF) {
560 Log("Unable to successfully flush inode file for %s\n", partition);
564 if (fsync(fileno(inodeFile)) == -1) {
565 Log("Unable to successfully fsync inode file for %s\n", partition);
569 if (fclose(inodeFile) == EOF) {
570 Log("Unable to successfully close inode file for %s\n", partition);
576 * Paranoia: check that the file is really the right size
578 if (stat(resultFile, &status) == -1) {
579 Log("Unable to successfully stat inode file for %s\n", partition);
583 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
584 Log("Wrong size (%d instead of %d) in inode file for %s\n",
585 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
608 #ifdef AFS_SGI_XFS_IOPS_ENV
610 #include <afs/xfsattrs.h>
611 /* xfs_ListViceInodes
613 * xfs_ListViceInodes verifies and correct the XFS namespace as it collects
614 * the inode information. The name is required for the idec operation to work.
615 * Steps 2 and 3 below are for the AFS_XFS_NAME_VERS == 1. If the name space
616 * changes, the algorithm will need to change.
617 * 1) If the parent inode number does not match the directory's inod number,
618 * change it in the attribute.
619 * 2) If the unqifier in the attribute does not match the name, rename the
620 * file. This is done by doing an exclusive open, incrementing the tag
621 * number until a file can be created. If the tag changes, then the
622 * attribute will need updating.
623 * 3) If the tag in the attribute does not match the name, change the
625 * 4) Verify uid = RW volume id and gid = XFS_VICEMAGIC.
631 * Does the verifications listed above.
632 * We can't change the names until the readdir is complete, so we set the
633 * rename flag if the file needs renaming.
635 int xfs_VerifyInode(char *dir, uint64_t pino, char *name, i_list_inode_t *info,
642 int update_chown = 0;
649 (void) sprintf(path, "%s/%s", dir, name);
650 /* Verify uid and gid fields */
651 if (info->ili_magic != XFS_VICEMAGIC) {
652 Log("%s magic for %s/%s (inode %s) from %d to %d\n",
653 Testing ? "Would have changed" : "Changing",
654 dir, name, PrintInode(NULL, info->ili_info.inodeNumber),
655 info->ili_magic, XFS_VICEMAGIC);
660 vno = info->ili_info.param[0];
661 if (info->ili_vno != AFS_XFS_VNO_CLIP(vno)) {
662 Log("%s volume id for %s/%s (inode %s) from %d to %d\n",
663 Testing ? "Would have changed" : "Changing",
664 dir, name, PrintInode(NULL, info->ili_info.inodeNumber),
665 info->ili_vno , AFS_XFS_VNO_CLIP(vno));
671 if (chown(path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC)<0) {
672 Log("Can't chown %s to uid=%d, gid=0x%x\n",
673 path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC);
678 /* Check Parent inode number. */
679 if (info->ili_pino != pino) {
680 afs_ino_str_t sino, sipino, spino;
681 (void) PrintInode(sino, info->ili_info.inodeNumber);
682 (void) PrintInode(sipino, info->ili_pino);
683 (void) PrintInode(spino, pino);
684 Log("%s parent ino for %s (inode %s) from %s to %s.\n",
685 Testing ? "Would have changed" : "Changing",
686 path, sino, sipino, spino);
691 /* Verify the file name. */
692 (void) strcpy(tmpName, ".");
693 (void) strcat(tmpName, int_to_base64(stmp, info->ili_info.param[2]));
694 if (strncmp(name, tmpName, strlen(tmpName))) {
695 Log("%s name %s (inode %s) in directory %s, unique=%d, tag=%d\n",
696 Testing ? "Would have returned bad" : "Bad",
697 name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
698 info->ili_info.param[2], info->ili_tag);
704 /* update the tag? */
705 (void) strcat(tmpName, ".");
706 (void) strcat(tmpName, int_to_base64(stmp, info->ili_tag));
707 if (strcmp(name, tmpName)) {
709 (void) strcpy(tmpName, name);
710 p = strchr(tmpName+1, '.');
712 Log("No tag found on name %s (inode %s)in directory, %s.\n",
713 name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
714 Testing ? "would have renamed" : "will rename");
719 tag = base64_to_int(p+1);
720 Log("%s the tag for %s (inode %s) from %d to %d.\n",
721 Testing ? "Would have changed" : "Will change",
722 path, PrintInode(NULL, info->ili_info.inodeNumber), dir,
730 if (update_pino || update_tag) {
731 afs_xfs_attr_t attrs;
734 length = SIZEOF_XFS_ATTR_T;
735 if (attr_get(path, AFS_XFS_ATTR, (char*)&attrs, &length, ATTR_ROOT)<0) {
736 Log("Can't get AFS attribute for %s\n", path);
740 attrs.at_pino = pino;
743 if(attr_set(path, AFS_XFS_ATTR, (char*)&attrs, length,
744 ATTR_ROOT|ATTR_REPLACE)<0) {
745 Log("Can't set AFS attribute into %s\n", path);
758 int xfs_RenameFiles(char *dir, xfs_Rename_t *renames, int n_renames)
761 char opath[128], nbase[128], npath[128];
762 afs_xfs_attr_t attrs;
763 int length = SIZEOF_XFS_ATTR_T;
768 for (i=0; i<n_renames; i++) {
769 (void) sprintf(opath, "%s/%s", dir, renames[i].name);
770 (void) sprintf(nbase, "%s/.%s", dir, int_to_base64(stmp, renames[i].uniq));
771 for (tag=2, j=0; j<64; tag++, j++) {
772 (void) sprintf(npath, "%s.%s", nbase, int_to_base64(stmp, tag));
773 fd = open(npath, O_CREAT|O_EXCL|O_RDWR, 0);
780 Log("Can't find a new name for %s\n", opath);
783 if (rename(opath, npath)<0) {
784 Log("Can't rename %s to %s\n", opath, npath);
787 Log("Renamed %s to %s\n", opath, npath);
793 xfs_ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam,
794 forcep, forceR, wpath)
795 char *devname, *mountedOn, *resultFile, *wpath;
799 FILE *inodeFile = NULL;
801 int info_size = sizeof(i_list_inode_t);
804 dirent64_t *top_direntp;
806 dirent64_t *vol_direntp;
807 struct stat64 sdirbuf;
808 struct stat64 sfilebuf;
809 afs_xfs_attr_t attrs;
810 afs_xfs_dattr_t dattrs;
812 char vol_dirname[1024];
815 xfs_Rename_t *renames = (xfs_Rename_t*)0;
817 #define N_RENAME_STEP 64
826 if (stat64(mountedOn, &sdirbuf)<0) {
827 perror("xfs_ListViceInodes: stat64");
831 inodeFile = fopen(resultFile, "w");
832 if (inodeFile == NULL) {
833 Log("Unable to create inode description file %s\n", resultFile);
837 if ((top_dirp=opendir(mountedOn)) == NULL) {
838 Log("Can't open directory %s to read inodes.\n", mountedOn);
842 while (top_direntp=readdir64(top_dirp)) {
843 /* Only descend directories with the AFSDIR attribute set.
844 * Could also verify the contents of the atribute, but currently
846 * Performance could be improved for single volume salvages by
847 * only going through the directory containing the volume's inodes.
848 * But I'm being complete as a first pass.
850 (void) sprintf(vol_dirname, "%s/%s", mountedOn, top_direntp->d_name);
851 length = SIZEOF_XFS_DATTR_T;
852 if (attr_get(vol_dirname, AFS_XFS_DATTR, (char*)&dattrs, &length,
856 if ((vol_dirp=opendir(vol_dirname)) == NULL) {
857 if (errno == ENOTDIR)
859 Log("Can't open directory %s to read inodes.\n", vol_dirname);
863 pino = top_direntp->d_ino;
865 while (vol_direntp=readdir64(vol_dirp)) {
866 if (vol_direntp->d_name[1] == '\0'
867 || vol_direntp->d_name[1] == '.')
870 info.ili_version = AFS_XFS_ILI_VERSION;
871 info_size = sizeof(i_list_inode_t);
872 code = ilistinode64(sdirbuf.st_dev, vol_direntp->d_ino,
875 /* Where possible, give more explicit messages. */
879 Log("%s (device id %d) is not on an XFS filesystem.\n",
880 vol_dirname, sdirbuf.st_dev);
885 if (info_size != sizeof(i_list_inode_t) ||
886 info.ili_version != AFS_XFS_ILI_VERSION) {
887 Log("Version skew between kernel and salvager.\n");
892 /* Continue, so we collect all the errors in the first pass.*/
893 Log("Error listing inode named %s/%s: %s\n",
894 vol_dirname, vol_direntp->d_name, strerror(errno));
899 if (info.ili_attr_version != AFS_XFS_ATTR_VERS) {
900 Log("Unrecognized XFS attribute version %d in %s/%s. Upgrade salvager\n",
901 info.ili_attr_version, vol_dirname, vol_direntp->d_name);
905 if (judgeInode && (*judgeInode)(&info.ili_info, judgeParam) == 0)
909 if (xfs_VerifyInode(vol_dirname, pino, vol_direntp->d_name,
915 /* Add this name to the list of items to rename. */
916 if (n_renames >= n_avail) {
917 n_avail += N_RENAME_STEP;
918 if (n_avail == N_RENAME_STEP)
919 renames = (xfs_Rename_t*)
920 malloc(n_avail*sizeof(xfs_Rename_t));
922 renames = (xfs_Rename_t*)
923 realloc((char*)renames,
924 n_avail * sizeof(xfs_Rename_t));
926 Log("Can't %salloc %lu bytes for rename list.\n",
927 (n_avail == N_RENAME_STEP) ? "m" : "re",
928 n_avail * sizeof(xfs_Rename_t));
932 (void) strcpy(renames[n_renames].name, vol_direntp->d_name);
933 renames[n_renames].uniq = info.ili_info.param[2];
937 if (fwrite(&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile)
939 Log("Error writing inode file for partition %s\n", mountedOn);
944 } /* end while vol_direntp */
949 Log("Renaming files.\n");
950 if (xfs_RenameFiles(vol_dirname, renames, n_renames)<0) {
958 free((char*)renames);
959 if (fflush(inodeFile) == EOF) {
960 ("Unable to successfully flush inode file for %s\n", mountedOn);
962 return errors ? -1 : -2;
964 if (fsync(fileno(inodeFile)) == -1) {
965 Log("Unable to successfully fsync inode file for %s\n", mountedOn);
967 return errors ? -1 : -2;
969 if (fclose(inodeFile) == EOF) {
970 Log("Unable to successfully close inode file for %s\n", mountedOn);
971 return errors ? -1 : -2;
974 * Paranoia: check that the file is really the right size
976 if (stat(resultFile, &status) == -1) {
977 Log("Unable to successfully stat inode file for %s\n", partition);
978 return errors ? -1 : -2;
980 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
981 Log("Wrong size (%d instead of %d) in inode file for %s\n",
982 status.st_size, ninodes * sizeof (struct ViceInodeInfo),
984 return errors ? -1 : -2;
988 Log("Errors encontered listing inodes, not salvaging partition.\n");
1000 free((char*)renames);
1008 ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep,
1010 char *devname, *mountedOn, *resultFile, *wpath;
1011 int (*judgeInode)();
1012 int *forcep, forceR;
1014 FILE *inodeFile = NULL;
1015 char dev[50], rdev[51];
1017 struct efs_dinode *p;
1018 struct ViceInodeInfo info;
1019 struct stat root_inode;
1020 int ninodes = 0, err = 0;
1021 struct efs_dinode *dinodeBuf = NULL;
1024 ino_t imax, inum; /* total number of I-nodes in file system */
1027 sync(); sleep(1); /* simulate operator */
1031 if (stat(mountedOn, &root_inode) < 0) {
1032 Log("cannot stat: %s\n", mountedOn);
1037 #ifdef AFS_SGI_XFS_IOPS_ENV
1038 if (!strcmp("xfs", root_inode.st_fstype)) {
1039 return xfs_ListViceInodes(devname, mountedOn, resultFile,
1040 judgeInode, judgeParam,
1041 forcep, forceR, wpath);
1046 if (root_inode.st_ino != EFS_ROOTINO) {
1047 Log("%s is not root of a filesystem\n", mountedOn);
1050 return efs_ListViceInodes(devname, mountedOn, resultFile,
1051 judgeInode, judgeParam,
1052 forcep, forceR, wpath);
1056 #else /* AFS_SGI_ENV */
1059 #define SPERB (MAXBSIZE / sizeof(short))
1060 #define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
1063 struct bufarea *b_next; /* must be first */
1067 char b_buf[MAXBSIZE]; /* buffer space */
1068 short b_lnks[SPERB]; /* link counts */
1069 daddr_t b_indir[MAXNINDIR]; /* indirect block */
1070 struct fs b_fs; /* super block */
1071 struct cg b_cg; /* cylinder group */
1075 typedef struct bufarea BUFAREA;
1078 #define sblock sblk.b_un.b_fs
1079 #endif /* AFS_HPUX_ENV */
1081 extern char *afs_rawname();
1082 int ListViceInodes(devname, mountedOn, resultFile, judgeInode, judgeParam, forcep, forceR, wpath)
1083 char *devname, *mountedOn, *resultFile, *wpath;
1084 int (*judgeInode)(), *forcep, forceR;
1090 #else /* !AFS_AIX_ENV */
1095 int i, c, e, bufsize, code, err =0;
1096 FILE *inodeFile = NULL;
1097 char dev[50], rdev[100], err1[512], *ptr1;
1098 struct dinode *inodes = NULL, *einodes, *dptr;
1102 struct ViceInodeInfo info;
1105 partition = mountedOn;
1106 sprintf(rdev, "%s/%s", wpath, devname);
1107 ptr1 = afs_rawname(rdev);
1111 /* Bletch: this is terrible; is there a better way to do this? Does this work? vfsck doesn't even sleep!! */
1113 sleep(5); /* Trying a smaller one for aix */
1118 pfd = open(rdev, O_RDONLY);
1120 sprintf(err1, "Could not open device %s to get inode list\n", rdev);
1127 if (bread(pfd, (char *)&super.fs, SUPERB, sizeof super.fs) == -1) {
1130 if (bread(pfd, (char *)&sblock, SBLOCK, SBSIZE) == -1) {
1132 if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
1133 #endif /* AFS_HPUX_ENV */
1135 Log("Unable to read superblock, partition %s\n", partition);
1139 inodeFile = fopen(resultFile, "w");
1140 if (inodeFile == NULL) {
1141 Log("Unable to create inode description file %s\n", resultFile);
1147 char *FSlabel(), *fslabel=0;
1148 fslabel = FSlabel(&super.fs);
1150 if (super.fs.s_bsize == 0)
1151 super.fs.s_bsize = 512;
1152 if (super.fs.s_bsize != BSIZE ) {
1153 Log("SuperBlk: Cluster size not %d; run vfsck\n", BSIZE);
1156 fmax = super.fs.s_fsize; /* first invalid blk num */
1157 imax = ((ino_t)super.fs.s_isize - (SUPERB+1)) * INOPB;
1159 Log("Size check: imax==0!\n");
1162 if (GetAuxInodeFile(partition, &status) == 0) {
1163 Log("Can't access Aux inode file for partition %s, aborting\n", partition);
1166 for (inum=1; inum <= imax; inum++) {
1167 struct dauxinode *auxp;
1168 if ((auxp = IsAfsInode(inum)) == NULL){
1169 /* Not an afs inode, keep going */
1172 if ((p = ginode(inum)) == NULL)
1174 /* deleted/non-existent inode when di_mode == 0 */
1177 info.inodeNumber = (int)inum;
1178 info.byteCount = p->di_size;
1179 info.linkCount = p->di_nlink;
1180 info.u.param[0] = auxp->aux_param1;
1181 info.u.param[1] = auxp->aux_param2;
1182 info.u.param[2] = auxp->aux_param3;
1183 info.u.param[3] = auxp->aux_param4;
1184 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
1186 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1187 Log("Error writing inode file for partition %s\n", partition);
1194 * run a few consistency checks of the superblock
1195 * (Cribbed from vfsck)
1198 #if defined(FD_FSMAGIC)
1199 if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN) && (sblock.fs_magic != FD_FSMAGIC)
1200 #if defined(AFS_HPUX101_ENV)
1201 && ( sblock.fs_magic != FD_FSMAGIC_2)
1206 if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)) {
1208 Log("There's something wrong with the superblock for partition %s; bad magic (%d) run vfsck\n",
1209 partition, sblock.fs_magic);
1212 if (sblock.fs_ncg < 1 ) {
1213 Log("There's something wrong with the superblock for partition %s; NCG OUT OF RANGE (%d) run vfsck\n",
1214 partition, sblock.fs_ncg);
1217 if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG ) {
1218 Log("There's something wrong with the superblock for partition %s; CPG OUT OF RANGE (%d) run vfsck\n",
1219 partition, sblock.fs_cpg);
1222 if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
1223 (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) {
1224 Log("There's something wrong with the superblock for partition %s; NCYL LESS THAN NCG*CPG run vfsck\n", partition);
1227 if (sblock.fs_sbsize > SBSIZE ) {
1228 Log("There's something wrong with the superblock for partition %s; bsize too large (%d vs. %d) run vfsck\n",
1229 partition, sblock.fs_sbsize, sblock.fs_bsize);
1235 (super.fs.fs_magic != FS_MAGIC)
1236 || (super.fs.fs_ncg < 1)
1237 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV)
1238 || (super.fs.fs_cpg < 1)
1240 || (super.fs.fs_cpg < 1 || super.fs.fs_cpg > MAXCPG)
1242 || (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl ||
1243 (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
1244 || (super.fs.fs_sbsize > SBSIZE)) {
1245 Log("There's something wrong with the superblock for partition %s; run vfsck\n", partition);
1248 #endif /* AFS_HPUX_ENV */
1251 bufsize = sblock.fs_ipg * sizeof(struct dinode);
1253 bufsize = super.fs.fs_ipg * sizeof(struct dinode);
1254 #endif /* AFS_HPUX_ENV */
1255 inodes = (struct dinode *) malloc(bufsize);
1256 einodes = (struct dinode *) (((char *)inodes) + bufsize);
1257 if (inodes == NULL) {
1258 Log("Unable to allocate enough memory to scan inodes; help!\n");
1261 Log("Scanning inodes on device %s...\n", rdev);
1263 for (c = 0; c < sblock.fs_ncg; c++) {
1264 i = c*sblock.fs_ipg; e = i+sblock.fs_ipg;
1265 #if defined(AFS_HPUX102_ENV)
1266 if (lseek(pfd, dbtoo(fsbtodb(&sblock,itod(&sblock,i))), L_SET) == -1) {
1268 if (lseek(pfd, dbtob(fsbtodb(&sblock,itod(&sblock,i))), L_SET) == -1) {
1271 for (c = 0; c < super.fs.fs_ncg; c++) {
1276 #endif /* AFS_SUN5_ENV */
1277 i = c*super.fs.fs_ipg; e = i+super.fs.fs_ipg;
1279 dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
1280 if (lseek(pfd, (off_t) ((off_t)dblk1 * DEV_BSIZE), L_SET) == -1) {
1283 f1 = fsbtodb(&super.fs,itod(&super.fs,i));
1284 off = (offset_t)f1 << DEV_BSHIFT;
1285 if (llseek(pfd, off, L_SET) == -1) {
1287 if (lseek(pfd, dbtob(fsbtodb(&super.fs,itod(&super.fs,i))), L_SET) == -1) {
1288 #endif /* AFS_SUN5_ENV */
1289 #endif /* AFS_OSF_ENV */
1290 #endif /* AFS_HPUX_ENV */
1291 Log("Error reading inodes for partition %s; run vfsck\n", partition);
1296 if (read(pfd, inodes, bufsize) != bufsize) {
1297 Log("Error reading inodes for partition %s; run vfsck\n", partition);
1301 register int bj, bk;
1303 for (bj=bk=0; bj < bufsize; bj=bj+512, bk++) {
1304 if ((code = read(pfd, dptr, 512)) != 512) {
1305 Log("Error reading inode %d? for partition %s (errno = %d); run vfsck\n", bk+i, partition, errno);
1306 if (lseek(pfd, 512, L_SET) == -1) {
1307 Log("Lseek failed\n");
1310 dptr->di_mode = 0; dptr++;
1311 dptr->di_mode = 0; dptr++;
1312 dptr->di_mode = 0; dptr++;
1313 dptr->di_mode = 0; dptr++;
1318 for (p=inodes; p<einodes && i<e; i++,p++) {
1320 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);
1321 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);
1324 #ifdef AFS_3DISPARES
1325 /* Check to see if this inode is a pre-"OSF1 4.0D" inode */
1326 if ((p->di_uid || p->di_gid)
1327 && !(p->di_flags & (IC_XUID|IC_XGID))) {
1328 Log("Found unconverted inode %d: Use 'fs_conv_dux40D convert' on partition %s\n",
1333 assert(0); /* define AFS_3DISPARES in param.h */
1336 #if defined(AFS_SUN56_ENV)
1337 /* if this is a pre-sol2.6 unconverted inode, bail out */
1339 afs_uint32 p1, p2, p3, p4;
1343 q = (quad *)&(p->di_ic.ic_lsize);
1345 p2 = p->di_ic.ic_flags;
1347 p4 = p->di_ic.ic_uid;
1348 p5 = p->di_ic.ic_gid;
1350 if ( (p2 || p3) && !p4 && (p5 == -2) )
1352 Log("Found unconverted inode %d\n", i);
1353 Log("You should run the AFS file conversion utility\n");
1358 if (IS_DVICEMAGIC(p) && (p->di_mode&IFMT) == IFREG) {
1359 afs_uint32 p2 = p->di_vicep2, p3 = DI_VICEP3(p);
1361 info.u.param[0] = p->di_vicep1;
1362 #ifdef AFS_3DISPARES
1363 if (((p2 >> 3) == INODESPECIAL) && (p2 & 0x3)) {
1364 info.u.param[1] = INODESPECIAL;
1365 info.u.param[2] = p3;
1366 info.u.param[3] = p2 & 0x3;
1368 info.u.param[1] = ((p2 >> 27) << 16) + (p3 & 0xffff);
1369 info.u.param[2] = (p2 & 0x3fffff);
1370 info.u.param[3] = (((p2 >> 22) & 0x1f) << 16) + (p3 >> 16);
1373 info.u.param[1] = p->di_vicep2;
1374 info.u.param[2] = DI_VICEP3(p);
1375 info.u.param[3] = p->di_vicep4;
1377 info.inodeNumber = i;
1378 info.byteCount = p->di_size;
1379 info.linkCount = p->di_nlink;
1380 if (judgeInode && (*judgeInode)(&info, judgeParam) == 0)
1382 if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1383 Log("Error writing inode file for partition %s\n", partition);
1391 if (inodes) free(inodes);
1393 if (fflush(inodeFile) == EOF) {
1394 Log("Unable to successfully flush inode file for %s\n", partition);
1398 if (fsync(fileno(inodeFile)) == -1) {
1399 Log("Unable to successfully fsync inode file for %s\n", partition);
1403 if (fclose(inodeFile) == EOF) {
1404 Log("Unable to successfully close inode file for %s\n", partition);
1410 * Paranoia: check that the file is really the right size
1412 if (stat(resultFile, &status) == -1) {
1413 Log("Unable to successfully stat inode file for %s\n", partition);
1417 if (status.st_size != ninodes * sizeof (struct ViceInodeInfo)) {
1418 Log("Wrong size (%d instead of %d) in inode file for %s\n",
1419 status.st_size, ninodes * sizeof (struct ViceInodeInfo), partition);
1436 #endif /* !AFS_SGI_ENV */
1437 #endif /* !AFS_AIX31_ENV */
1439 int bread(fd, buf, blk, size)
1446 #ifdef AFS_AIX41_ENV
1447 offset_t off = (offset_t)blk << FSBSHIFT;
1448 if (llseek(fd, off, 0) < 0) {
1449 Log("Unable to seek to offset %llu for block %u\n", off, blk);
1452 #else /* AFS_AIX41_ENV */
1453 if (lseek(fd, blk * Bsize, 0) < 0) {
1454 Log("Unable to seek to offset %u for block %u\n",
1457 #endif /* AFS_AIX41_ENV */
1459 if (lseek(fd, (off_t)dbtob(blk), L_SET) < 0) {
1460 Log("Unable to seek to offset %u for block %u\n",
1464 if (read(fd, buf, size) != size) {
1465 Log("Unable to read block %d, partition %s\n", blk, partition);
1471 #endif /* AFS_LINUX20_ENV */
1472 #endif /* AFS_NAMEI_ENV */