#include <roken.h>
+
#ifdef AFS_NAMEI_ENV
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef AFS_NT40_ENV
-#include <unistd.h>
-#else
+
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
+#ifdef AFS_NT40_ENV
#define DELETE_ZLC
-#include <io.h>
#include <windows.h>
#include <winnt.h>
#include <winbase.h>
-#include <winsock2.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#ifdef AFS_NT40_ENV
#include <direct.h>
-#else
-#include <sys/file.h>
-#include <sys/param.h>
#endif
-#include <dirent.h>
-#include <afs/afs_assert.h>
-#include <string.h>
+
+#include <afs/opr.h>
+#include <rx/rx_queue.h>
+#ifdef AFS_PTHREAD_ENV
+# include <opr/lock.h>
+#endif
#include <lock.h>
#include <afs/afsutil.h>
#include <lwp.h>
#include "volume_inline.h"
#include "common.h"
#include <afs/errors.h>
+
#ifdef AFS_NT40_ENV
#include <afs/errmap_nt.h>
#endif
#include <vol/vol-salvage.h>
#endif
-#if !defined(HAVE_FLOCK) && !defined(AFS_NT40_ENV)
-#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
-
int Testing=0;
+static void namei_UnlockLinkCount(FdHandle_t * fdP, Inode ino);
afs_sfsize_t
namei_iread(IHandle_t * h, afs_foff_t offset, char *buf, afs_fsize_t size)
return -1;
nBytes = FDH_PREAD(fdP, buf, size, offset);
- FDH_CLOSE(fdP);
+ if (nBytes < 0)
+ FDH_REALLYCLOSE(fdP);
+ else
+ FDH_CLOSE(fdP);
return nBytes;
}
return -1;
nBytes = FDH_PWRITE(fdP, buf, size, offset);
- FDH_CLOSE(fdP);
+ if (nBytes < 0)
+ FDH_REALLYCLOSE(fdP);
+ else
+ FDH_CLOSE(fdP);
return nBytes;
}
namei_ViceREADME(char *partition)
{
char filename[32];
- int fd;
+ int fd, len, e = 0;
/* Create the inode directory if we're starting for the first time */
- (void)afs_snprintf(filename, sizeof filename, "%s" OS_DIRSEP "%s", partition,
- INODEDIR);
+ snprintf(filename, sizeof filename, "%s" OS_DIRSEP "%s", partition,
+ INODEDIR);
mkdir(filename, 0700);
- (void)afs_snprintf(filename, sizeof filename, "%s" OS_DIRSEP "%s" OS_DIRSEP "README",
- partition, INODEDIR);
+ snprintf(filename, sizeof filename,
+ "%s" OS_DIRSEP "%s" OS_DIRSEP "README",
+ partition, INODEDIR);
fd = OS_OPEN(filename, O_WRONLY | O_CREAT | O_TRUNC, 0444);
if (fd != INVALID_FD) {
- (void)OS_WRITE(fd, VICE_README, strlen(VICE_README));
+ len = strlen(VICE_README);
+ if (OS_WRITE(fd, VICE_README, len) != len)
+ e = errno;
OS_CLOSE(fd);
+ if (e)
+ errno = e;
}
return (errno);
}
int i;
*created = 0;
- afs_snprintf(tmp, 256, "%s" OS_DIRSEP "%s", name->n_drive, name->n_voldir);
+ snprintf(tmp, 256, "%s" OS_DIRSEP "%s", name->n_drive, name->n_voldir);
if (mkdir(tmp) < 0) {
if (errno != EEXIST)
cp = tree + strlen(tree); /* move cp to the end of string tree */
/* now delete all entries in this dir */
- if ((ds = opendir(root)) != (DIR *) NULL) {
+ if ((ds = opendir(root)) != NULL) {
errno = 0;
while ((dirp = readdir(ds))) {
/* ignore . and .. */
char tmp[256];
int i;
- afs_snprintf(tmp, 256, "%s" OS_DIRSEP "%s", name->n_drive, name->n_voldir);
+ snprintf(tmp, 256, "%s" OS_DIRSEP "%s", name->n_drive, name->n_voldir);
path = tmp;
path += strlen(path);
* types, but if we get that far, this could should be dead by then.
*/
Inode
-namei_MakeSpecIno(int volid, int type)
+namei_MakeSpecIno(VolumeId volid, int type)
{
Inode ino;
ino = NAMEI_INODESPECIAL;
}
static int
-CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
+SetWinOGM(FD_t fd, int p1, int p2)
{
- WIN32_FIND_DATA info;
- HANDLE dirH;
+ BOOL code;
+ FILETIME ftime;
+
+ ftime.dwHighDateTime = p1;
+ ftime.dwLowDateTime = p2;
+
+ code = SetFileTime(fd, &ftime, NULL /*access*/, NULL /*write*/);
+ if (!code)
+ return -1;
+ return 0;
+}
+
+static int
+GetWinOGM(FD_t fd, int *p1, int *p2)
+{
+ BOOL code;
+ FILETIME ftime;
+
+ code = GetFileTime(fd, &ftime, NULL /*access*/, NULL /*write*/);
+ if (!code)
+ return -1;
+
+ *p1 = ftime.dwHighDateTime;
+ *p2 = ftime.dwLowDateTime;
+
+ return 0;
+}
- dirH =
- FindFirstFileEx(name->n_path, FindExInfoStandard, &info,
- FindExSearchNameMatch, NULL,
- FIND_FIRST_EX_CASE_SENSITIVE);
+static int
+CheckOGM(FdHandle_t *fdP, int p1)
+{
+ int ogm_p1, ogm_p2;
- if (!dirH)
- return -1; /* Can't get info, leave alone */
+ if (GetWinOGM(fdP->fd_fd, &ogm_p1, &ogm_p2)) {
+ return -1;
+ }
+
+ if (ogm_p1 != p1) {
+ return -1;
+ }
+
+ return 0;
+}
- FindClose(dirH);
+static int
+FixSpecialOGM(FdHandle_t *fdP, int check)
+{
+ Inode ino = fdP->fd_ih->ih_ino;
+ VnodeId vno = NAMEI_VNODESPECIAL, ogm_vno;
+ int ogm_volid;
- if (info.ftCreationTime.dwHighDateTime != (unsigned int)p1)
+ if (GetWinOGM(fdP->fd_fd, &ogm_volid, &ogm_vno)) {
return -1;
+ }
+ /* the only thing we can check is the vnode number; for the volid we have
+ * nothing else to compare against */
+ if (vno != ogm_vno) {
+ if (check) {
+ return -1;
+ }
+ if (SetWinOGM(fdP->fd_fd, ogm_volid, vno)) {
+ return -1;
+ }
+ }
return 0;
}
+
#else /* AFS_NT40_ENV */
/* SetOGM - set owner group and mode bits from parm and tag */
static int
/* GetOGM - get parm and tag from owner, group and mode bits. */
static void
-GetOGMFromStat(struct afs_stat *status, int *parm, int *tag)
+GetOGMFromStat(struct afs_stat_st *status, int *parm, int *tag)
{
*parm = status->st_uid | (status->st_gid << 15);
*parm |= (status->st_mode & 0x18) << 27;
}
static int
-CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
+GetOGM(FdHandle_t *fdP, int *parm, int *tag)
{
- struct afs_stat status;
- int parm, tag;
+ struct afs_stat_st status;
if (afs_fstat(fdP->fd_fd, &status) < 0)
return -1;
+ GetOGMFromStat(&status, parm, tag);
+ return 0;
+}
+
+static int
+CheckOGM(FdHandle_t *fdP, int p1)
+{
+ int parm, tag;
- GetOGMFromStat(&status, &parm, &tag);
+ if (GetOGM(fdP, &parm, &tag) < 0)
+ return -1;
if (parm != p1)
return -1;
return 0;
}
+
+static int
+FixSpecialOGM(FdHandle_t *fdP, int check)
+{
+ int inode_volid, ogm_volid;
+ int inode_type, ogm_type;
+ Inode ino = fdP->fd_ih->ih_ino;
+
+ inode_volid = ((ino >> NAMEI_UNIQSHIFT) & NAMEI_UNIQMASK);
+ inode_type = (int)((ino >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
+
+ if (GetOGM(fdP, &ogm_volid, &ogm_type) < 0) {
+ Log("Error retrieving OGM info\n");
+ return -1;
+ }
+
+ if (inode_volid != ogm_volid || inode_type != ogm_type) {
+ Log("%sIncorrect OGM data (ino: vol %u type %d) (ogm: vol %u type %d)\n",
+ check?"":"Fixing ", inode_volid, inode_type, ogm_volid, ogm_type);
+
+ if (check) {
+ return -1;
+ }
+
+ if (SetOGM(fdP->fd_fd, inode_volid, inode_type) < 0) {
+ Log("Error setting OGM data\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
#endif /* !AFS_NT40_ENV */
+/**
+ * Check/fix the OGM data for an inode
+ *
+ * @param[in] fdP Open file handle for the inode to check
+ * @param[in] check 1 to just check the OGM data, and return an error if it
+ * is incorrect. 0 to fix the OGM data if it is incorrect.
+ *
+ * @pre fdP must be for a special inode
+ *
+ * @return status
+ * @retval 0 success
+ * @retval -1 error
+ */
+int
+namei_FixSpecialOGM(FdHandle_t *fdP, int check)
+{
+ int vnode;
+ Inode ino = fdP->fd_ih->ih_ino;
+
+ vnode = (int)(ino & NAMEI_VNODEMASK);
+ if (vnode != NAMEI_VNODESPECIAL) {
+ Log("FixSpecialOGM: non-special vnode %u\n", vnode);
+ return -1;
+ }
+
+ return FixSpecialOGM(fdP, check);
+}
+
int big_vno = 0; /* Just in case we ever do 64 bit vnodes. */
/* Derive the name and create it O_EXCL. If that fails we have an error.
FdHandle_t *fdP;
FdHandle_t tfd;
int type, tag;
- FILETIME ftime;
+ int ogm_p1, ogm_p2;
char *p;
b32_string_t str1;
* p3 - type
* p4 - parent volume id
*/
- ftime.dwHighDateTime = p1;
- ftime.dwLowDateTime = p2;
+ ogm_p1 = p1;
+ ogm_p2 = p2;
type = p3;
tmp.ih_vid = p4; /* Use parent volume id, where this file will be. */
tmp.ih_ino = namei_MakeSpecIno(p1, p3);
tmp.ih_vid = p1;
tmp.ih_ino = (Inode) p2;
- ftime.dwHighDateTime = p3;
- ftime.dwLowDateTime = p4;
+ ogm_p1 = p3;
+ ogm_p2 = p4;
}
namei_HandleToName(&name, &tmp);
p++;
for (tag = 0; tag < NAMEI_MAXVOLS; tag++) {
*p = *int_to_base32(str1, tag);
- fd = OS_OPEN((char *)&name.n_path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
+ fd = OS_OPEN((char *)&name.n_path, O_CREAT | O_RDWR | O_EXCL, 0666);
if (fd == INVALID_FD) {
if (errno == ENOTDIR || errno == ENOENT) {
if (namei_CreateDataDirectories(&name, &created_dir) == 0)
- fd = OS_OPEN((char *)&name.n_path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
+ fd = OS_OPEN((char *)&name.n_path, O_CREAT | O_RDWR | O_EXCL, 0666);
}
}
tmp.ih_ino |= (((Inode) tag) << NAMEI_TAGSHIFT);
if (!code) {
- if (!SetFileTime((HANDLE) fd, &ftime, NULL, NULL)) {
+ if (SetWinOGM(fd, ogm_p1, ogm_p2)) {
errno = OS_ERROR(EBADF);
code = -1;
}
}
#else /* !AFS_NT40_ENV */
Inode
-namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
+ IHandle_t **a_ih)
{
namei_t name;
int fd = INVALID_FD;
int code = 0;
int created_dir = 0;
IHandle_t tmp;
+ IHandle_t *realh = NULL;
FdHandle_t *fdP;
- FdHandle_t tfd;
int tag;
int ogm_parm;
memset((void *)&tmp, 0, sizeof(IHandle_t));
- memset(&tfd, 0, sizeof(FdHandle_t));
tmp.ih_dev = volutil_GetPartitionID(part);
if (tmp.ih_dev == -1) {
}
namei_HandleToName(&name, &tmp);
- fd = OS_OPEN(name.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
+ fd = OS_OPEN(name.n_path, O_CREAT | O_EXCL | O_RDWR, 0);
if (fd == INVALID_FD) {
if (errno == ENOTDIR || errno == ENOENT) {
if (namei_CreateDataDirectories(&name, &created_dir) < 0)
goto bad;
- fd = OS_OPEN(name.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR,
+ fd = OS_OPEN(name.n_path, O_CREAT | O_EXCL | O_RDWR,
0);
if (fd == INVALID_FD)
goto bad;
goto bad;
}
+ IH_INIT(realh, tmp.ih_dev, tmp.ih_vid, tmp.ih_ino);
+ fdP = ih_attachfd(realh, fd);
+
+ /* ih_attachfd can only return NULL if we give it an invalid fd; our fd
+ * must be valid by this point. */
+ opr_Assert(fdP);
+
if (p2 == (afs_uint32)-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);
+ code = namei_SetLinkCount(fdP, (Inode) 0, 1, 0);
}
- bad:
- if (fd != INVALID_FD)
- OS_CLOSE(fd);
-
+ FDH_CLOSE(fdP);
+ bad:
if (code || (fd == INVALID_FD)) {
if (p2 != -1) {
fdP = IH_OPEN(lh);
FDH_CLOSE(fdP);
}
}
+ IH_RELEASE(realh);
}
- return (code || (fd == INVALID_FD)) ? (Inode) - 1 : tmp.ih_ino;
+
+ *a_ih = realh;
+
+ return code;
+}
+
+Inode
+namei_icreate(IHandle_t * lh, char *part,
+ afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+{
+ Inode ino;
+ IHandle_t *ihP = NULL;
+ int code;
+
+ code = icreate(lh, part, p1, p2, p3, p4, &ihP);
+ if (code || !ihP) {
+ opr_Assert(!ihP);
+ ino = -1;
+ } else {
+ ino = ihP->ih_ino;
+ IH_RELEASE(ihP);
+ }
+ return ino;
+}
+
+IHandle_t *
+namei_icreate_init(IHandle_t * lh, int dev, char *part,
+ afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+{
+ int code;
+ IHandle_t *ihP = NULL;
+
+ code = icreate(lh, part, p1, p2, p3, p4, &ihP);
+ if (code) {
+ opr_Assert(!ihP);
+ }
+ return ihP;
}
#endif
return -1;
}
- if (CheckOGM(&name, fdP, p1) < 0) {
+ if (CheckOGM(fdP, p1) < 0) {
FDH_REALLYCLOSE(fdP);
IH_RELEASE(tmp);
errno = OS_ERROR(EINVAL);
}
count--;
- if (namei_SetLinkCount(fdP, (Inode) 0, count < 0 ? 0 : count, 1) <
- 0) {
- FDH_REALLYCLOSE(fdP);
- IH_RELEASE(tmp);
- return -1;
- }
-
if (count > 0) {
- FDH_REALLYCLOSE(fdP);
+ /* if our count is non-zero, we just set our new linkcount and
+ * return. But if our count is 0, don't bother updating the
+ * linktable, since we're about to delete the link table,
+ * below. */
+ if (namei_SetLinkCount(fdP, (Inode) 0, count < 0 ? 0 : count, 1) < 0) {
+ FDH_REALLYCLOSE(fdP);
+ IH_RELEASE(tmp);
+ return -1;
+ }
+
+ FDH_CLOSE(fdP);
IH_RELEASE(tmp);
return 0;
}
+
+ namei_UnlockLinkCount(fdP, (Inode) 0);
}
+ /* We should IH_REALLYCLOSE right before deleting the special file from
+ * disk, to ensure that somebody else cannot create a special inode,
+ * then IH_OPEN that special inode and get back a cached fd for the
+ * file we are deleting here (instead of an fd for the file they just
+ * created). */
+ IH_REALLYCLOSE(tmp);
+ FDH_REALLYCLOSE(fdP);
+ IH_RELEASE(tmp);
+
if ((code = OS_UNLINK(name.n_path)) == 0) {
if (type == VI_LINKTABLE) {
/* Try to remove directory. If it fails, that's ok.
* Salvage will clean up.
*/
+ char *slash = strrchr(name.n_path, OS_DIRSEPC);
+ if (slash) {
+ /* avoid an rmdir() on the file we just unlinked */
+ *slash = '\0';
+ }
(void)namei_RemoveDataDirectories(&name);
}
}
- FDH_REALLYCLOSE(fdP);
- IH_RELEASE(tmp);
} else {
/* Get a file descriptor handle for this Inode */
fdP = IH_OPEN(ih);
} 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, (afs_int64)th->ih_ino);
+ Log("Warning: Lost ref on ihandle dev %d vid %" AFS_VOLID_FMT " ino %lld\n",
+ th->ih_dev, afs_printable_VolumeId_lu(th->ih_vid), (afs_int64)th->ih_ino);
IH_RELEASE(th);
/* If we're less than 0, someone presumably unlinked;
FD_t fd;
namei_t name;
FdHandle_t *fdP;
- struct afs_stat tstat;
+ struct afs_stat_st tstat;
afs_foff_t offset;
namei_HandleToName(&name, h);
if (afs_stat(name.n_path, &tstat) < 0)
return EIO;
if (tstat.st_nlink > 1) { /* do a copy on write */
- char path[259];
+ char path[NAMEI_PATH_LEN + 4];
char *buf;
afs_size_t size;
ssize_t tlen;
fdP = IH_OPEN(h);
if (!fdP)
return EIO;
- afs_snprintf(path, sizeof(path), "%s-tmp", name.n_path);
- fd = OS_OPEN(path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
+ snprintf(path, sizeof(path), "%s-tmp", name.n_path);
+ fd = OS_OPEN(path, O_CREAT | O_EXCL | O_RDWR, 0);
if (fd == INVALID_FD) {
FDH_CLOSE(fdP);
return EIO;
#ifdef AFS_PTHREAD_ENV
/* XXX do static initializers work for WINNT/pthread? */
pthread_mutex_t _namei_glc_lock = PTHREAD_MUTEX_INITIALIZER;
-#define NAMEI_GLC_LOCK MUTEX_ENTER(&_namei_glc_lock)
-#define NAMEI_GLC_UNLOCK MUTEX_EXIT(&_namei_glc_lock)
+#define NAMEI_GLC_LOCK opr_mutex_enter(&_namei_glc_lock)
+#define NAMEI_GLC_UNLOCK opr_mutex_exit(&_namei_glc_lock)
#else /* !AFS_PTHREAD_ENV */
#define NAMEI_GLC_LOCK
#define NAMEI_GLC_UNLOCK
}
rc = FDH_PREAD(h, (char*)&row, sizeof(row), offset);
+ if (rc == -1)
+ goto bad_getLinkByte;
+
if ((rc == 0 || !((row >> index) & NAMEI_TAGMASK)) && fixup && nowrite)
return 1;
if (rc == 0 && fixup) {
NAMEI_GLC_UNLOCK;
goto bad_getLinkByte;
}
- FDH_TRUNC(h, offset+sizeof(row));
+ if (FDH_TRUNC(h, offset+sizeof(row))) {
+ NAMEI_GLC_UNLOCK;
+ goto bad_getLinkByte;
+ }
row = 1 << index;
rc = FDH_PWRITE(h, (char *)&row, sizeof(row), offset);
NAMEI_GLC_UNLOCK;
return -1;
}
-int
-namei_SetNonZLC(FdHandle_t * h, Inode ino)
-{
- return namei_GetLinkCount(h, ino, 0, 1, 0);
-}
-
/* Return a free column index for this vnode. */
static int
GetFreeTag(IHandle_t * ih, int vno)
if (FDH_PWRITE(fdP, (char *)&row, sizeof(row), offset) != sizeof(row)) {
goto badGetFreeTag;
}
- FDH_SYNC(fdP);
+ (void)FDH_SYNC(fdP);
FDH_UNLOCKFILE(fdP, offset);
- FDH_REALLYCLOSE(fdP);
+ FDH_CLOSE(fdP);
return col;
badGetFreeTag:
errno = OS_ERROR(EBADF);
goto bad_SetLinkCount;
}
- FDH_SYNC(fdP);
+ (void)FDH_SYNC(fdP);
nBytes = 0;
return (int)nBytes;
}
+static void
+namei_UnlockLinkCount(FdHandle_t * fdP, Inode ino)
+{
+ afs_foff_t offset;
+ int index;
+
+ namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
+
+ FDH_UNLOCKFILE(fdP, offset);
+}
+
/* ListViceInodes - write inode data to a results file. */
static int DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
- unsigned int volid);
-static int DecodeVolumeName(char *name, unsigned int *vid);
+ IHandle_t *myIH);
+static int DecodeVolumeName(char *name, VolumeId *vid);
static int namei_ListAFSSubDirs(IHandle_t * dirIH,
- int (*write_fun) (FILE *,
+ int (*write_fun) (FD_t,
struct ViceInodeInfo *,
- char *, char *), FILE * fp,
+ char *, char *), FD_t fp,
int (*judgeFun) (struct ViceInodeInfo *,
- afs_uint32 vid, void *),
- afs_uint32 singleVolumeNumber, void *rock);
+ VolumeId vid, void *),
+ VolumeId singleVolumeNumber, void *rock);
/* WriteInodeInfo
* can use the same inode reading code.
*/
static int
-WriteInodeInfo(FILE * fp, struct ViceInodeInfo *info, char *dir, char *name)
+WriteInodeInfo(FD_t fp, struct ViceInodeInfo *info, char *dir, char *name)
{
size_t n;
- n = fwrite(info, sizeof(*info), 1, fp);
- return (n == 1) ? 0 : -2;
+ n = OS_WRITE(fp, info, sizeof(*info));
+ return (n == sizeof(*info)) ? 0 : -2;
}
void
VerifyDirPerms(char *path)
{
- struct afs_stat status;
+ struct afs_stat_st status;
if (afs_stat(path, &status) < 0) {
Log("Unable to stat %s. Please manually verify mode bits for this"
* for this.
*/
int
-ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
- int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
- afs_uint32 singleVolumeNumber, int *forcep, int forceR, char *wpath,
+ListViceInodes(char *devname, char *mountedOn, FD_t inodeFile,
+ int (*judgeInode) (struct ViceInodeInfo * info, VolumeId vid, void *rock),
+ VolumeId singleVolumeNumber, int *forcep, int forceR, char *wpath,
void *rock)
{
int ninodes;
- struct afs_stat status;
*forcep = 0; /* no need to salvage until further notice */
namei_ListAFSFiles(mountedOn, WriteInodeInfo, inodeFile, judgeInode,
singleVolumeNumber, rock);
- if (!inodeFile)
+ if (inodeFile == INVALID_FD)
return ninodes;
if (ninodes < 0) {
return ninodes;
}
- if (fflush(inodeFile) == EOF) {
- Log("Unable to successfully flush inode file for %s\n", mountedOn);
- return -2;
- }
- if (fsync(fileno(inodeFile)) == -1) {
+ if (OS_SYNC(inodeFile) == -1) {
Log("Unable to successfully fsync inode file for %s\n", mountedOn);
return -2;
}
/*
* Paranoia: check that the file is really the right size
*/
- if (afs_fstat(fileno(inodeFile), &status) == -1) {
- Log("Unable to successfully stat inode file for %s\n", mountedOn);
- return -2;
- }
- if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
+ if (OS_SIZE(inodeFile) != ninodes * sizeof(struct ViceInodeInfo)) {
Log("Wrong size (%d instead of %lu) in inode file for %s\n",
- (int) status.st_size,
+ (int) OS_SIZE(inodeFile),
(long unsigned int) ninodes * sizeof(struct ViceInodeInfo),
mountedOn);
return -2;
*/
int
namei_ListAFSFiles(char *dev,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
+ int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
char *),
- FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- afs_uint32 singleVolumeNumber, void *rock)
+ FD_t fp,
+ int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+ VolumeId singleVolumeNumber, void *rock)
{
IHandle_t ih;
namei_t name;
#else
if (*dp1->d_name == '.')
continue;
- afs_snprintf(path2, sizeof(path2), "%s" OS_DIRSEP "%s", name.n_path,
- dp1->d_name);
+ snprintf(path2, sizeof(path2), "%s" OS_DIRSEP "%s", name.n_path,
+ dp1->d_name);
dirp2 = opendir(path2);
if (dirp2) {
while ((dp2 = readdir(dirp2))) {
char * dname,
IHandle_t * myIH,
FdHandle_t * linkHandle,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
+ int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
char *),
- FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- int singleVolumeNumber,
+ FD_t fp,
+ int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+ VolumeId singleVolumeNumber,
void *rock)
{
int ret = 0;
struct ViceInodeInfo info;
- afs_uint32 inode_vgid;
- if (DecodeInode(path1, dname, &info, myIH->ih_vid) < 0) {
+ if (DecodeInode(path1, dname, &info, myIH) < 0) {
ret = 0;
goto error;
}
-#ifdef AFS_NT40_ENV
- inode_vgid = myIH->ih_vid;
-#else
- inode_vgid = (info.inodeNumber >> NAMEI_UNIQSHIFT) & NAMEI_UNIQMASK;
-#endif
-
if (info.u.param[2] != VI_LINKTABLE) {
info.linkCount = 1;
- } else if ((info.u.param[0] != myIH->ih_vid) ||
- (inode_vgid != myIH->ih_vid)) {
+ } else if (info.u.param[0] != myIH->ih_vid) {
/* VGID encoded in linktable filename and/or OGM data isn't
* consistent with VGID encoded in namei path */
Log("namei_ListAFSSubDirs: warning: inconsistent linktable "
"filename \"%s" OS_DIRSEP "%s\"; salvager will delete it "
- "(dir_vgid=%u, inode_vgid=%u, ogm_vgid=%u)\n",
- path1, dname, myIH->ih_vid,
- (unsigned int)inode_vgid,
- info.u.param[0]);
+ "(dir_vgid=%" AFS_VOLID_FMT ", inode_vgid=%" AFS_VOLID_FMT ")\n",
+ path1, dname, afs_printable_VolumeId_lu(myIH->ih_vid),
+ afs_printable_VolumeId_lu(info.u.param[0]));
+ /* We need to set the linkCount to _something_, so linkCount
+ * doesn't just contain stack garbage. Set it to 0, so in case
+ * the salvager or whatever our caller is does try to process
+ * this like a normal file, we won't try to INC or DEC it. */
+ info.linkCount = 0;
} else {
char path2[512];
/* Open this handle */
- (void)afs_snprintf(path2, sizeof(path2),
- "%s" OS_DIRSEP "%s", path1, dname);
+ snprintf(path2, sizeof(path2),
+ "%s" OS_DIRSEP "%s", path1, dname);
linkHandle->fd_fd = OS_OPEN(path2, Testing ? O_RDONLY : O_RDWR, 0666);
info.linkCount =
namei_GetLinkCount(linkHandle, (Inode) 0, 1, 1, Testing);
if (!judgeFun ||
(*judgeFun) (&info, singleVolumeNumber, rock)) {
- ret = 1;
- if ((*writeFun) (fp, &info, path1, dname) < 0) {
+ ret = (*writeFun) (fp, &info, path1, dname);
+ if (ret < 0) {
+ Log("_namei_examine_special: writeFun returned %d\n", ret);
ret = -1;
+ } else {
+ ret = 1;
}
}
char * dname,
IHandle_t * myIH,
FdHandle_t * linkHandle,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
+ int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
char *),
- FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- int singleVolumeNumber,
+ FD_t fp,
+ int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+ VolumeId singleVolumeNumber,
void *rock)
{
int ret = 0;
int dirl; /* Windows-only (one level hash dir) */
#endif
- if (DecodeInode(path3, dname, &info, myIH->ih_vid) < 0) {
+ if (DecodeInode(path3, dname, &info, myIH) < 0) {
goto error;
}
if (!judgeFun ||
(*judgeFun) (&info, singleVolumeNumber, rock)) {
- ret = 1;
- if ((*writeFun) (fp, &info, path3, dname) < 0) {
+ ret = (*writeFun) (fp, &info, path3, dname);
+ if (ret < 0) {
+ Log("_namei_examine_reg: writeFun returned %d\n", ret);
ret = -1;
+ } else {
+ ret = 1;
}
}
* inode, this will be pointed at the
* link table
*/
- FILE * fp; /**< file pointer for writeFun */
+ FD_t fp; /**< file pointer for writeFun */
/** function which will write inode metadata to fp */
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *, char *);
+ int (*writeFun) (FD_t, struct ViceInodeInfo *, char *, char *);
/** inode filter function */
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *);
- int singleVolumeNumber; /**< volume id filter */
+ int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *);
+ VolumeId singleVolumeNumber; /**< volume id filter */
void * rock; /**< pointer passed to writeFun and judgeFun */
int code; /**< return code from examine function */
int special; /**< asserted when this is a volume
static void
_namei_wq_keycreate(void)
{
- osi_Assert(pthread_key_create(&wq_key, NULL) == 0);
+ opr_Verify(pthread_key_create(&wq_key, NULL) == 0);
}
/**
void
namei_SetWorkQueue(struct afs_work_queue *wq)
{
- osi_Assert(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
+ opr_Verify(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
- osi_Assert(pthread_setspecific(wq_key, wq) == 0);
+ opr_Verify(pthread_setspecific(wq_key, wq) == 0);
}
/**
*/
static int
namei_ListAFSSubDirs(IHandle_t * dirIH,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
+ int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
char *),
- FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- afs_uint32 singleVolumeNumber, void *rock)
+ FD_t fp,
+ int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+ VolumeId singleVolumeNumber, void *rock)
{
int code = 0, ret = 0;
IHandle_t myIH = *dirIH;
linkHandle.fd_fd = INVALID_FD;
#ifdef AFS_SALSRV_ENV
- osi_Assert(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
+ opr_Verify(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
wq = pthread_getspecific(wq_key);
if (!wq) {
#endif
if (linkHandle.fd_fd == INVALID_FD) {
- Log("namei_ListAFSSubDirs: warning: VG %u does not have a link table; "
- "salvager will recreate it.\n", dirIH->ih_vid);
+ Log("namei_ListAFSSubDirs: warning: VG %" AFS_VOLID_FMT " does not have a link table; "
+ "salvager will recreate it.\n", afs_printable_VolumeId_lu(dirIH->ih_vid));
}
/* Now run through all the other subdirs */
#ifndef AFS_NT40_ENV /* This level missing on Windows */
/* Now we've got a next level subdir. */
- afs_snprintf(path2, sizeof(path2), "%s" OS_DIRSEP "%s", path1, dp1->d_name);
+ code = snprintf(path2, sizeof(path2), "%s" OS_DIRSEP "%s",
+ path1, dp1->d_name);
+ if (code < 0 || code >= sizeof(path2)) {
+ /* error, or truncated */
+ closedir(dirp1);
+ ret = -1;
+ goto error;
+ }
dirp2 = opendir(path2);
if (dirp2) {
while ((dp2 = readdir(dirp2))) {
continue;
/* Now we've got to the actual data */
- afs_snprintf(path3, sizeof(path3), "%s" OS_DIRSEP "%s", path2,
- dp2->d_name);
+ code = snprintf(path3, sizeof(path3), "%s" OS_DIRSEP "%s",
+ path2, dp2->d_name);
#else
/* Now we've got to the actual data */
- afs_snprintf(path3, sizeof(path3), "%s" OS_DIRSEP "%s", path1,
- dp1->d_name);
+ code = snprintf(path3, sizeof(path3), "%s" OS_DIRSEP "%s",
+ path1, dp1->d_name);
+#endif
+ if (code < 0 || code >= sizeof(path3)) {
+ /* error, or truncated */
+#ifndef AFS_NT40_ENV
+ closedir(dirp2);
#endif
+ closedir(dirp1);
+ ret = -1;
+ goto error;
+ }
dirp3 = opendir(path3);
if (dirp3) {
while ((dp3 = readdir(dirp3))) {
#ifdef AFS_NT40_ENV
static int
-DecodeVolumeName(char *name, unsigned int *vid)
+DecodeVolumeName(char *name, VolumeId *vid)
{
/* Name begins with "Vol_" and ends with .data. See nt_HandleToVolDir() */
char stmp[32];
}
#else
static int
-DecodeVolumeName(char *name, unsigned int *vid)
+DecodeVolumeName(char *name, VolumeId *vid)
{
if (strlen(name) < 1)
return -1;
#ifdef AFS_NT40_ENV
static int
DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
- unsigned int volid)
+ IHandle_t *myIH)
{
char fpath[512];
int tag, vno;
char stmp[16];
FdHandle_t linkHandle;
char dirl;
+ VolumeId volid = myIH->ih_vid;
- afs_snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
+ snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
dirH = FindFirstFileEx(fpath, FindExInfoStandard, &data,
FindExSearchNameMatch, NULL,
#else
static int
DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
- unsigned int volid)
+ IHandle_t *myIH)
{
char fpath[512];
- struct afs_stat status;
+ struct afs_stat_st status;
+ struct afs_stat_st checkstatus;
int parm, tag;
lb64_string_t check;
+ VolumeId volid = myIH->ih_vid;
+ IHandle_t tmpih;
+ namei_t nameiname;
- afs_snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
+ snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
if (afs_stat(fpath, &status) < 0) {
return -1;
if (strcmp(name, check))
return -1;
- GetOGMFromStat(&status, &parm, &tag);
+ /* Check if the _full_ path is correct, to ensure we can actually open this
+ * file later. Otherwise, the salvager can choke. */
+ memset(&tmpih, 0, sizeof(tmpih));
+ tmpih.ih_dev = myIH->ih_dev;
+ tmpih.ih_vid = myIH->ih_vid;
+ tmpih.ih_ino = info->inodeNumber;
+ namei_HandleToName(&nameiname, &tmpih);
+ if ((afs_stat(nameiname.n_path, &checkstatus) < 0) ||
+ checkstatus.st_ino != status.st_ino ||
+ checkstatus.st_size != status.st_size) {
+ static int logged;
+ /* log something for this case, since this means the filename looks
+ * like a valid inode, but it's just in the wrong place. That's pretty
+ * strange. */
+ if (!logged) {
+ logged = 1;
+ Log("Note:\n");
+ Log(" Seemingly-misplaced files have been found, which I am\n");
+ Log(" ignoring for now. If you cannot salvage the relevant volume,\n");
+ Log(" you may try manually moving them to their correct location.\n");
+ Log(" If the relevant volume seems fine, and these files do not\n");
+ Log(" appear to contain important data, you can probably manually\n");
+ Log(" delete them, or leave them alone. Contact your local OpenAFS\n");
+ Log(" expert if you are unsure.\n");
+ }
+ Log("Ignoring misplaced file in volume group %u: %s (should be %s)\n",
+ (unsigned)myIH->ih_vid, fpath, nameiname.n_path);
+ return -1;
+ }
+
if ((info->inodeNumber & NAMEI_INODESPECIAL) == NAMEI_INODESPECIAL) {
+ parm = ((info->inodeNumber >> NAMEI_UNIQSHIFT) & NAMEI_UNIQMASK);
+ tag = (int)((info->inodeNumber >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
+
/* p1 - vid, p2 - -1, p3 - type, p4 - rwvid */
info->u.param[0] = parm;
info->u.param[1] = -1;
info->u.param[2] = tag;
info->u.param[3] = volid;
} else {
+ GetOGMFromStat(&status, &parm, &tag);
/* p1 - vid, p2 - vno, p3 - uniq, p4 - dv */
info->u.param[0] = volid;
info->u.param[1] = (int)(info->inodeNumber & NAMEI_VNODEMASK);
#ifdef FSSYNC_BUILD_CLIENT
static afs_int32
-convertVolumeInfo(FD_t fdr, FD_t fdw, afs_uint32 vid)
+convertVolumeInfo(FD_t fdr, FD_t fdw, VolumeId vid)
{
struct VolumeDiskData vd;
char *p;
if (OS_READ(fdr, &vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
- Log("1 convertVolumeInfo: read failed for %lu with code %d\n",
- afs_printable_uint32_lu(vid),
+ Log("1 convertVolumeInfo: read failed for %" AFS_VOLID_FMT " with code %d\n",
+ afs_printable_VolumeId_lu(vid),
errno);
return -1;
}
*/
int
-namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
+namei_ConvertROtoRWvolume(char *pname, VolumeId volumeId)
{
int code = 0;
#ifdef FSSYNC_BUILD_CLIENT
struct DiskPartition64 *partP;
struct ViceInodeInfo info;
struct VolumeDiskHeader h;
+ char *rwpart, *rwname;
+ Error ec;
# ifdef AFS_DEMAND_ATTACH_FS
int locktype = 0;
# endif /* AFS_DEMAND_ATTACH_FS */
goto done;
}
+ /* check for existing RW on any partition on this server; */
+ /* if found, return EXDEV - invalid cross-device link */
+ VOL_LOCK;
+ VGetVolumePath(&ec, h.parent, &rwpart, &rwname);
+ if (ec == 0) {
+ Log("1 namei_ConvertROtoRWvolume: RW volume %lu already exists on server partition %s.\n",
+ afs_printable_uint32_lu(h.parent), rwpart);
+ code = EXDEV;
+ VOL_UNLOCK;
+ goto done;
+ }
+ VOL_UNLOCK;
+
FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
if (*dp->d_name == '.')
continue;
#endif
- if (DecodeInode(dir_name, dp->d_name, &info, ih->ih_vid) < 0) {
+ if (DecodeInode(dir_name, dp->d_name, &info, ih) < 0) {
Log("1 namei_ConvertROtoRWvolume: DecodeInode failed for %s" OS_DIRSEP "%s\n",
dir_name, dp->d_name);
closedir(dirp);
largeSeen = 1;
} else {
closedir(dirp);
- Log("1 namei_ConvertROtoRWvolume: unknown type %d of special file found : %s" OS_DIRSEP "%s\n", info.u.param[2], dir_name, dp->d_name);
+ Log("1 namei_ConvertROtoRWvolume: unknown type %u of special file found : %s" OS_DIRSEP "%s\n", info.u.param[2], dir_name, dp->d_name);
code = -1;
goto done;
}
t_ih.ih_dev = ih->ih_dev;
t_ih.ih_vid = ih->ih_vid;
- (void)afs_snprintf(oldpath, sizeof oldpath, "%s" OS_DIRSEP "%s", dir_name,
- infoName);
+ code = snprintf(oldpath, sizeof oldpath, "%s" OS_DIRSEP "%s", dir_name,
+ infoName);
+ if (code < 0 || code >= sizeof(oldpath)) {
+ /* error, or truncated */
+ code = -1;
+ goto done;
+ }
fd = OS_OPEN(oldpath, O_RDWR, 0);
if (fd == INVALID_FD) {
Log("1 namei_ConvertROtoRWvolume: could not open RO info file: %s\n",
}
t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_VOLINFO);
namei_HandleToName(&n, &t_ih);
- fd2 = OS_OPEN(n.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
+ fd2 = OS_OPEN(n.n_path, O_CREAT | O_EXCL | O_RDWR, 0);
if (fd2 == INVALID_FD) {
Log("1 namei_ConvertROtoRWvolume: could not create RW info file: %s\n", n.n_path);
OS_CLOSE(fd);
t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_SMALLINDEX);
namei_HandleToName(&n, &t_ih);
- (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
- smallName);
+ code = snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+ smallName);
+ if (code < 0 || code >= sizeof(newpath)) {
+ /* error, or truncated */
+ code = -1;
+ goto done;
+ }
fd = OS_OPEN(newpath, O_RDWR, 0);
if (fd == INVALID_FD) {
Log("1 namei_ConvertROtoRWvolume: could not open SmallIndex file: %s\n", newpath);
#ifdef AFS_NT40_ENV
MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
#else
- link(newpath, n.n_path);
+ if (link(newpath, n.n_path)) {
+ Log("1 namei_ConvertROtoRWvolume: could not move SmallIndex file: %s\n", n.n_path);
+ code = -1;
+ goto done;
+ }
OS_UNLINK(newpath);
#endif
t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_LARGEINDEX);
namei_HandleToName(&n, &t_ih);
- (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
- largeName);
+ code = snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+ largeName);
+ if (code < 0 || code >= sizeof(newpath)) {
+ /* error, or truncated */
+ code = -1;
+ goto done;
+ }
fd = OS_OPEN(newpath, O_RDWR, 0);
if (fd == INVALID_FD) {
Log("1 namei_ConvertROtoRWvolume: could not open LargeIndex file: %s\n", newpath);
#ifdef AFS_NT40_ENV
MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
#else
- link(newpath, n.n_path);
+ if (link(newpath, n.n_path)) {
+ Log("1 namei_ConvertROtoRWvolume: could not move LargeIndex file: %s\n", n.n_path);
+ code = -1;
+ goto done;
+ }
OS_UNLINK(newpath);
#endif
if (!s)
s = result;
- (void)afs_snprintf(s, sizeof(afs_ino_str_t), "%" AFS_UINT64_FMT, (afs_uintmax_t) ino);
+ snprintf(s, sizeof(afs_ino_str_t), "%llu", (afs_uintmax_t) ino);
return s;
}
static void
AddToZLCDeleteList(char dir, char *name)
{
- osi_Assert(strlen(name) <= MAX_ZLC_NAMELEN - 3);
+ opr_Assert(strlen(name) <= MAX_ZLC_NAMELEN - 3);
if (!zlcCur || zlcCur->zlc_n >= MAX_ZLC_NAMES) {
if (zlcCur && zlcCur->zlc_next)
zlcCur = zlcCur->zlc_next;
else {
- zlcList_t *tmp = (zlcList_t *) malloc(sizeof(zlcList_t));
+ zlcList_t *tmp = malloc(sizeof(zlcList_t));
if (!tmp)
return;
if (!zlcAnchor) {
}
#endif
+/**
+ * Remove empty directories associated with the volume received
+ * as an argument.
+ *
+ * @param[in] pname vice partition path
+ * @param[in] vid volume id
+ *
+ * @return 0 on success
+ */
+int
+namei_RemoveDirectories(char *pname, afs_int32 vid)
+{
+ IHandle_t dirIH;
+ namei_t name;
+
+ memset(&dirIH, 0, sizeof(dirIH));
+
+ dirIH.ih_vid = vid;
+
+#ifdef AFS_NT40_ENV
+ dirIH.ih_dev = nt_DriveToDev(pname);
+#else
+ dirIH.ih_dev = volutil_GetPartitionID(pname);
+#endif
+ if (dirIH.ih_dev == -1) {
+ return -1;
+ }
+
+ namei_HandleToVolDir(&name, &dirIH);
+
+ return namei_RemoveDataDirectories(&name);
+}
+
#endif /* AFS_NAMEI_ENV */