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>
23
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/vol/listinodes.c,v 1.1.1.10 2002/09/26 19:09:23 hartmans Exp $");
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 */