/*@printflike@*/ extern void Log(const char *format, ...);
extern char *volutil_PartitionName_r(int volid, char *buf, int buflen);
+int Testing=0;
+
afs_sfsize_t
namei_iread(IHandle_t * h, afs_foff_t offset, char *buf, afs_fsize_t size)
} namei_ogm_t;
int namei_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
+static int namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup);
+
static int GetFreeTag(IHandle_t * ih, int vno);
/* namei_HandleToInodeDir
* If lockit is set, lock the file and leave it locked upon a successful
* return.
*/
-int
-namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
+static int
+namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup)
{
unsigned short row = 0;
afs_foff_t offset;
+ ssize_t rc;
int index;
+ /* there's no linktable yet. the salvager will create one later */
+ if (h->fd_fd == -1 && fixup)
+ return 1;
namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
if (lockit) {
if (afs_lseek(h->fd_fd, offset, SEEK_SET) == -1)
goto bad_getLinkByte;
- if (read(h->fd_fd, (char *)&row, sizeof(row)) != sizeof(row)) {
+ rc = read(h->fd_fd, (char *)&row, sizeof(row));
+ if (rc == 0 && fixup) {
+ struct stat st;
+ if (fstat(h->fd_fd, &st) || st.st_size >= offset+sizeof(row))
+ goto bad_getLinkByte;
+ FDH_TRUNC(h, offset+sizeof(row));
+ row = 1 << index;
+rewrite:
+ rc = write(h->fd_fd, (char *)&row, sizeof(row));
+ }
+ if (rc != sizeof(row)) {
goto bad_getLinkByte;
}
+ if (fixup && !((row >> index) & NAMEI_TAGMASK)) {
+ row |= 1<<index;
+ goto rewrite;
+ }
+
return (int)((row >> index) & NAMEI_TAGMASK);
bad_getLinkByte:
return -1;
}
+int
+namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
+{
+ return namei_GetLinkCount2(h, ino, lockit, 0);
+}
+
+void
+namei_SetNonZLC(FdHandle_t * h, Inode ino)
+{
+ (void)namei_GetLinkCount2(h, ino, 0, 1);
+}
+
/* Return a free column index for this vnode. */
static int
GetFreeTag(IHandle_t * ih, int vno)
/* Open this handle */
(void)afs_snprintf(path2, sizeof path2, "%s/%s", path1,
dp1->d_name);
- linkHandle.fd_fd = afs_open(path2, O_RDONLY, 0666);
+ linkHandle.fd_fd = afs_open(path2, Testing ? O_RDONLY : O_RDWR, 0666);
info.linkCount =
- namei_GetLinkCount(&linkHandle, (Inode) 0, 0);
+ namei_GetLinkCount2(&linkHandle, (Inode) 0, 1, !Testing);
}
if (judgeFun && !(*judgeFun) (&info, singleVolumeNumber, rock))
continue;
(path3, dp3->d_name, &info, myIH.ih_vid) < 0)
continue;
info.linkCount =
- namei_GetLinkCount(&linkHandle,
- info.inodeNumber, 0);
+ namei_GetLinkCount2(&linkHandle,
+ info.inodeNumber, 1, !Testing);
if (info.linkCount == 0) {
#ifdef DELETE_ZLC
Log("Found 0 link count file %s/%s, deleting it.\n", path3, dp3->d_name);
int debug; /* -d flag */
-int Testing = 0; /* -n flag */
+extern int Testing; /* -n flag */
int ListInodeOption; /* -i flag */
int ShowRootFiles; /* -r flag */
int RebuildDirs; /* -sal flag */
if (Testing) {
IH_INIT(VGLinkH, fileSysDevice, -1, -1);
} else {
+ int i, j;
+ struct ViceInodeInfo *ip;
CreateLinkTable(isp, ino);
+ fdP = IH_OPEN(VGLinkH);
+ /* Sync fake 1 link counts to the link table, now that it exists */
+ if (fdP) {
+ namei_SetNonZLC(fdP, ino);
+ for (i = 0; i < nVols; i++) {
+ ip = allInodes + isp[i].index;
+ for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++)
+ namei_SetNonZLC(fdP, ip[j].inodeNumber);
+ }
+ }
}
}
if (fdP)