#ifdef AFS_NAMEI_ENV
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/param.h>
#include <lock.h>
-#ifdef AFS_AIX_ENV
-#include <sys/lockf.h>
-#endif
-#ifdef AFS_SUN5_ENV
+#if defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
#include <unistd.h>
#endif
#include <afs/afsutil.h>
#include "viceinode.h"
#include "voldefs.h"
#include "partition.h"
+#include "fssync.h"
#include <afs/errors.h>
/*@+fcnmacros +macrofcndecl@*/
/*@printflike@*/ extern void Log(const char *format, ...);
+#ifndef LOCK_SH
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* don't block when locking */
+#define LOCK_UN 8 /* unlock */
+#endif
+
+#ifndef HAVE_FLOCK
+#include <fcntl.h>
+
+/*
+ * This function emulates a subset of flock()
+ */
+int
+emul_flock(int fd, int cmd)
+{ struct flock f;
+
+ memset(&f, 0, sizeof (f));
+
+ if (cmd & LOCK_UN)
+ f.l_type = F_UNLCK;
+ if (cmd & LOCK_SH)
+ f.l_type = F_RDLCK;
+ if (cmd & LOCK_EX)
+ f.l_type = F_WRLCK;
+
+ return fcntl(fd, (cmd & LOCK_NB) ? F_SETLK : F_SETLKW, &f);
+}
+
+#define flock(f,c) emul_flock(f,c)
+#endif
+
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)
int ogm_mode;
} 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, int nowrite);
+
static int GetFreeTag(IHandle_t * ih, int vno);
/* namei_HandleToInodeDir
* name space.
*/
#define VICE_README "These files and directories are a part of the AFS \
-namespace. Modifying them\nin any way will result in loss of AFS data.\n"
+namespace. Modifying them\nin any way will result in loss of AFS data,\n\
+ownership and permissions included.\n"
int
namei_ViceREADME(char *partition)
{
if (p2 == -1 && p3 == VI_LINKTABLE) {
/* hack at tmp to setup for set link count call. */
+ memset((void *)&tfd, 0, sizeof(FdHandle_t)); /* minimalistic still, but a little cleaner */
+ tfd.fd_ih = &tmp;
tfd.fd_fd = fd;
code = namei_SetLinkCount(&tfd, (Inode) 0, 1, 0);
}
FDH_REALLYCLOSE(fdP);
return -1;
}
+ } else {
+ IHandle_t *th;
+ IH_INIT(th, ih->ih_dev, ih->ih_vid, ino);
+ Log("Warning: Lost ref on ihandle dev %d vid %d ino %" AFS_INT64_FMT "\n",
+ th->ih_dev, th->ih_vid, (int64_t) th->ih_ino);
+ IH_RELEASE(th);
+
+ /* If we're less than 0, someone presumably unlinked;
+ don't bother setting count to 0, but we need to drop a lock */
+ if (namei_SetLinkCount(fdP, ino, 0, 1) < 0) {
+ FDH_REALLYCLOSE(fdP);
+ return -1;
+ }
}
if (count == 0) {
IHandle_t *th;
IH_INIT(th, ih->ih_dev, ih->ih_vid, ino);
-#if 0
- /* This triggers in the fileserver on the volume index vnodes */
- if (th->ih_refcnt > 1)
- Log("Warning: Leaked ref on ihandle dev %d vid %d ino %lld\n",
- th->ih_dev, th->ih_vid, (int64_t) th->ih_ino);
-#endif
+
namei_HandleToName(&name, th);
IH_RELEASE(th);
code = unlink(name.n_path);
* 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, int nowrite)
{
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 defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- if (lockf(h->fd_fd, F_LOCK, 0) < 0)
-#else
if (flock(h->fd_fd, LOCK_EX) < 0)
-#endif
return -1;
}
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 || !((row >> index) & NAMEI_TAGMASK)) && fixup && nowrite)
+ return 1;
+ 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;
+ 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;
+ if (afs_lseek(h->fd_fd, offset, SEEK_SET) == -1)
+ goto bad_getLinkByte;
+ rc = write(h->fd_fd, (char *)&row, sizeof(row));
+ if (rc != sizeof(row))
+ goto bad_getLinkByte;
+ }
+
return (int)((row >> index) & NAMEI_TAGMASK);
bad_getLinkByte:
if (lockit)
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- lockf(h->fd_fd, F_ULOCK, 0);
-#else
flock(h->fd_fd, LOCK_UN);
-#endif
return -1;
}
+int
+namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
+{
+ return namei_GetLinkCount2(h, ino, lockit, 0, 1);
+}
+
/* Return a free column index for this vnode. */
static int
GetFreeTag(IHandle_t * ih, int vno)
return -1;
/* Only one manipulates at a time. */
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- if (lockf(fdP->fd_fd, F_LOCK, 0) < 0) {
-#else
if (flock(fdP->fd_fd, LOCK_EX) < 0) {
-#endif
FDH_REALLYCLOSE(fdP);
return -1;
}
if ((row & coldata) == 0)
break;
}
- if (col >= NAMEI_MAXVOLS)
+ if (col >= NAMEI_MAXVOLS) {
+ errno = ENOSPC;
goto badGetFreeTag;
+ }
coldata = 1 << (col * 3);
row |= coldata;
goto badGetFreeTag;
}
FDH_SYNC(fdP);
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- lockf(fdP->fd_fd, F_ULOCK, 0);
-#else
flock(fdP->fd_fd, LOCK_UN);
-#endif
FDH_REALLYCLOSE(fdP);
return col;;
badGetFreeTag:
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- lockf(fdP->fd_fd, F_ULOCK, 0);
-#else
flock(fdP->fd_fd, LOCK_UN);
-#endif
FDH_REALLYCLOSE(fdP);
return -1;
}
namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
if (!locked) {
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- if (lockf(fdP->fd_fd, F_LOCK, 0) < 0) {
-#else
if (flock(fdP->fd_fd, LOCK_EX) < 0) {
-#endif
return -1;
}
}
bad_SetLinkCount:
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
- lockf(fdP->fd_fd, F_ULOCK, 0);
-#else
flock(fdP->fd_fd, LOCK_UN);
-#endif
return code;
}
struct ViceInodeInfo *,
char *, char *), FILE * fp,
int (*judgeFun) (struct ViceInodeInfo *,
- int vid),
- int singleVolumeNumber);
+ int vid, void *),
+ int singleVolumeNumber, void *rock);
/* WriteInodeInfo
*/
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
- int (*judgeInode) (struct ViceInodeInfo * info, int vid),
- int singleVolumeNumber, int *forcep, int forceR, char *wpath)
+ int (*judgeInode) (struct ViceInodeInfo * info, int vid, void *rock),
+ int singleVolumeNumber, int *forcep, int forceR, char *wpath,
+ void *rock)
{
FILE *fp = (FILE *) - 1;
int ninodes;
struct afs_stat status;
+ *forcep = 0; /* no need to salvage until further notice */
+
if (resultFile) {
fp = afs_fopen(resultFile, "w");
if (!fp) {
ninodes =
namei_ListAFSFiles(mountedOn, WriteInodeInfo, fp, judgeInode,
- singleVolumeNumber);
+ singleVolumeNumber, rock);
if (!resultFile)
return ninodes;
namei_ListAFSFiles(char *dev,
int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, int),
- int singleVolumeNumber)
+ int (*judgeFun) (struct ViceInodeInfo *, int, void *),
+ int singleVolumeNumber, void *rock)
{
IHandle_t ih;
namei_t name;
namei_HandleToVolDir(&name, &ih);
ninodes =
namei_ListAFSSubDirs(&ih, writeFun, fp, judgeFun,
- singleVolumeNumber);
+ singleVolumeNumber, rock);
if (ninodes < 0)
return ninodes;
} else {
if (!DecodeVolumeName(dp2->d_name, &ih.ih_vid)) {
ninodes +=
namei_ListAFSSubDirs(&ih, writeFun, fp, judgeFun,
- 0);
+ 0, rock);
}
}
closedir(dirp2);
namei_ListAFSSubDirs(IHandle_t * dirIH,
int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, int),
- int singleVolumeNumber)
+ int (*judgeFun) (struct ViceInodeInfo *, int, void *),
+ int singleVolumeNumber, void *rock)
{
IHandle_t myIH = *dirIH;
namei_t name;
/* 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, 1, Testing);
}
- if (judgeFun && !(*judgeFun) (&info, singleVolumeNumber))
+ if (judgeFun && !(*judgeFun) (&info, singleVolumeNumber, rock))
continue;
if ((*writeFun) (fp, &info, path1, dp1->d_name) < 0) {
(path3, dp3->d_name, &info, myIH.ih_vid) < 0)
continue;
info.linkCount =
- namei_GetLinkCount(&linkHandle,
- info.inodeNumber, 0);
+ namei_GetLinkCount2(&linkHandle,
+ info.inodeNumber, 1, 1, Testing);
if (info.linkCount == 0) {
#ifdef DELETE_ZLC
Log("Found 0 link count file %s/%s, deleting it.\n", path3, dp3->d_name);
continue;
}
if (judgeFun
- && !(*judgeFun) (&info, singleVolumeNumber))
+ && !(*judgeFun) (&info, singleVolumeNumber, rock))
continue;
if ((*writeFun) (fp, &info, path3, dp3->d_name) <
char fpath[512];
struct afs_stat status;
int parm, tag;
+ lb64_string_t check;
(void)strcpy(fpath, dpath);
(void)strcat(fpath, "/");
info->byteCount = status.st_size;
info->inodeNumber = (Inode) flipbase64_to_int64(name);
+ int64_to_flipbase64(check, info->inodeNumber);
+ if (strcmp(name, check))
+ return -1;
+
GetOGMFromStat(&status, &parm, &tag);
if ((info->inodeNumber & NAMEI_INODESPECIAL) == NAMEI_INODESPECIAL) {
/* p1 - vid, p2 - -1, p3 - type, p4 - rwvid */
* the old RW volume around */
p = strrchr(vd.name, '.');
if (p && !strcmp(p, ".readonly")) {
- bzero(p, 8);
+ memset(p, 0, 9);
}
if (write(fdw, &vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
*/
int
-namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
+namei_ConvertROtoRWvolume(char *pname, afs_int32 volumeId)
{
+#ifdef FSSYNC_BUILD_CLIENT
namei_t n;
char dir_name[512], oldpath[512], newpath[512];
char smallName[64];
char largeName[64];
char infoName[64];
IHandle_t t_ih;
+ IHandle_t *ih;
char infoSeen = 0;
char smallSeen = 0;
char largeSeen = 0;
char linkSeen = 0;
- int code, fd, fd2;
+ int code, fd, fd2, found;
char *p;
DIR *dirp;
+ Inode ino;
struct dirent *dp;
+ struct DiskPartition64 *partP;
struct ViceInodeInfo info;
+ struct VolumeDiskHeader h;
+ char volname[20];
+ char headername[16];
+ afs_int32 error = 0;
+
+ (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
+ (void)afs_snprintf(oldpath, sizeof oldpath, "%s/%s", pname, headername);
+ fd = open(oldpath, O_RDONLY);
+ if (fd < 0) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
+ return ENOENT;
+ }
+ if (read(fd, &h, sizeof(h)) != sizeof(h)) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
+ close(fd);
+ return EIO;
+ }
+ close(fd);
+ FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
+
+ for (partP = DiskPartitionList; partP && strcmp(partP->name, pname);
+ partP = partP->next);
+ if (!partP) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
+ return EIO;
+ }
+ ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
+ IH_INIT(ih, partP->device, h.parent, ino);
- namei_HandleToName(&n, h);
+ namei_HandleToName(&n, ih);
strcpy(dir_name, n.n_path);
p = strrchr(dir_name, '/');
*p = 0;
if (*dp->d_name == '.')
continue;
- if (DecodeInode(dir_name, dp->d_name, &info, h->ih_vid) < 0) {
+ if (DecodeInode(dir_name, dp->d_name, &info, ih->ih_vid) < 0) {
Log("1 namei_ConvertROtoRWvolume: DecodeInode failed for %s/%s\n",
dir_name, dp->d_name);
closedir(dirp);
closedir(dirp);
return -1;
}
- if (info.u.param[0] != vid) {
- if (info.u.param[0] == h->ih_vid) {
+ if (info.u.param[0] != volumeId) {
+ if (info.u.param[0] == ih->ih_vid) {
if (info.u.param[2] == VI_LINKTABLE) { /* link table */
linkSeen = 1;
continue;
* proceed.
*/
- bzero(&t_ih, sizeof(t_ih));
- t_ih.ih_dev = h->ih_dev;
- t_ih.ih_vid = h->ih_vid;
+ memset(&t_ih, 0, sizeof(t_ih));
+ t_ih.ih_dev = ih->ih_dev;
+ t_ih.ih_vid = ih->ih_vid;
(void)afs_snprintf(oldpath, sizeof oldpath, "%s/%s", dir_name, infoName);
fd = afs_open(oldpath, O_RDWR, 0);
oldpath);
return -1;
}
- t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, VI_VOLINFO);
+ t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_VOLINFO);
namei_HandleToName(&n, &t_ih);
fd2 = afs_open(n.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
if (fd2 < 0) {
close(fd);
return -1;
}
- code = convertVolumeInfo(fd, fd2, h->ih_vid);
+ code = convertVolumeInfo(fd, fd2, ih->ih_vid);
close(fd);
if (code) {
close(fd2);
unlink(n.n_path);
return -1;
}
- SetOGM(fd2, h->ih_vid, 1);
+ SetOGM(fd2, ih->ih_vid, 1);
close(fd2);
- t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, VI_SMALLINDEX);
+ t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_SMALLINDEX);
namei_HandleToName(&n, &t_ih);
(void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, smallName);
fd = afs_open(newpath, O_RDWR, 0);
Log("1 namei_ConvertROtoRWvolume: could not open SmallIndex file: %s\n", newpath);
return -1;
}
- SetOGM(fd, h->ih_vid, 2);
+ SetOGM(fd, ih->ih_vid, 2);
close(fd);
link(newpath, n.n_path);
unlink(newpath);
- t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, VI_LARGEINDEX);
+ t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_LARGEINDEX);
namei_HandleToName(&n, &t_ih);
(void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, largeName);
fd = afs_open(newpath, O_RDWR, 0);
Log("1 namei_ConvertROtoRWvolume: could not open LargeIndex file: %s\n", newpath);
return -1;
}
- SetOGM(fd, h->ih_vid, 3);
+ SetOGM(fd, ih->ih_vid, 3);
close(fd);
link(newpath, n.n_path);
unlink(newpath);
unlink(oldpath);
+
+ h.id = h.parent;
+ h.volumeInfo_hi = h.id;
+ h.smallVnodeIndex_hi = h.id;
+ h.largeVnodeIndex_hi = h.id;
+ h.linkTable_hi = h.id;
+ (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
+ (void)afs_snprintf(newpath, sizeof newpath, "%s/%s", pname, headername);
+ fd = open(newpath, O_CREAT | O_EXCL | O_RDWR, 0644);
+ if (fd < 0) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
+ return EIO;
+ }
+ if (write(fd, &h, sizeof(h)) != sizeof(h)) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't write header for RW-volume\
+ %lu.\n", h.id);
+ close(fd);
+ return EIO;
+ }
+ close(fd);
+ if (unlink(oldpath) < 0) {
+ Log("1 namei_ConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
+ }
+ FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
+ FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
+#endif
return 0;
}