#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
#ifdef AFS_NAMEI_ENV
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "viceinode.h"
#include "voldefs.h"
#include "partition.h"
+#include "fssync.h"
#include <afs/errors.h>
/*@+fcnmacros +macrofcndecl@*/
#define flock(f,c) emul_flock(f,c)
#endif
-extern char *volutil_PartitionName_r(int volid, char *buf, int buflen);
int Testing=0;
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);
}
} 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 %lld\n",
+ 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);
return code;
}
+int
+namei_replace_file_by_hardlink(IHandle_t *hLink, IHandle_t *hTarget)
+{
+ afs_int32 code;
+ namei_t nameLink;
+ namei_t nameTarget;
+
+ /* Convert handle to file name. */
+ namei_HandleToName(&nameLink, hLink);
+ namei_HandleToName(&nameTarget, hTarget);
+
+ unlink(nameLink.n_path);
+ code = link(nameTarget.n_path, nameLink.n_path);
+ return code;
+}
+
+int
+namei_copy_on_write(IHandle_t *h)
+{
+ afs_int32 fd, code = 0;
+ namei_t name;
+ FdHandle_t *fdP;
+ struct afs_stat tstat;
+
+ 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 *buf;
+ afs_size_t size;
+ afs_int32 tlen;
+
+ fdP = IH_OPEN(h);
+ if (!fdP)
+ return EIO;
+ strcpy(path, name.n_path);
+ strcat(path, "-tmp");
+ fd = afs_open(path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
+ if (fd < 0) {
+ FDH_CLOSE(fdP);
+ return EIO;
+ }
+ buf = malloc(8192);
+ if (!buf) {
+ close(fd);
+ unlink(path);
+ FDH_CLOSE(fdP);
+ return ENOMEM;
+ }
+ size = tstat.st_size;
+ FDH_SEEK(fdP, 0, 0);
+ while (size) {
+ tlen = size > 8192 ? 8192 : size;
+ if (FDH_READ(fdP, buf, tlen) != tlen)
+ break;
+ if (write(fd, buf, tlen) != tlen)
+ break;
+ size -= tlen;
+ }
+ close(fd);
+ FDH_REALLYCLOSE(fdP);
+ free(buf);
+ if (size)
+ code = EIO;
+ else {
+ unlink(name.n_path);
+ code = rename(path, name.n_path);
+ }
+ }
+ return code;
+}
+
/************************************************************************
* File Name Structure
************************************************************************
if ((row & coldata) == 0)
break;
}
- if (col >= NAMEI_MAXVOLS)
+ if (col >= NAMEI_MAXVOLS) {
+ errno = ENOSPC;
goto badGetFreeTag;
+ }
coldata = 1 << (col * 3);
row |= coldata;
struct ViceInodeInfo *,
char *, char *), FILE * fp,
int (*judgeFun) (struct ViceInodeInfo *,
- int vid, void *),
- int singleVolumeNumber, void *rock);
+ afs_uint32 vid, void *),
+ afs_uint32 singleVolumeNumber, void *rock);
/* WriteInodeInfo
*/
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
- int (*judgeInode) (struct ViceInodeInfo * info, int vid, void *rock),
- int singleVolumeNumber, int *forcep, int forceR, char *wpath,
+ int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
+ afs_uint32 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) {
namei_ListAFSFiles(char *dev,
int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, int, void *),
- int singleVolumeNumber, void *rock)
+ int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
+ afs_uint32 singleVolumeNumber, void *rock)
{
IHandle_t ih;
namei_t name;
namei_ListAFSSubDirs(IHandle_t * dirIH,
int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, int, void *),
- int singleVolumeNumber, void *rock)
+ int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
+ afs_uint32 singleVolumeNumber, void *rock)
{
IHandle_t myIH = *dirIH;
namei_t 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 */
*/
static afs_int32
-convertVolumeInfo(fdr, fdw, vid)
- int fdr;
- int fdw;
- afs_uint32 vid;
+convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
{
struct VolumeDiskData vd;
char *p;
*/
int
-namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
+namei_ConvertROtoRWvolume(char *pname, afs_uint32 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;
int code, fd, fd2;
char *p;
DIR *dirp;
+ Inode ino;
struct dirent *dp;
+ struct DiskPartition64 *partP;
struct ViceInodeInfo info;
+ struct VolumeDiskHeader h;
+ char headername[16];
+ afs_int32 error = 0;
- namei_HandleToName(&n, h);
+ (void)afs_snprintf(headername, sizeof headername, VFORMAT, afs_cast_uint32(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, 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;
*/
memset(&t_ih, 0, sizeof(t_ih));
- t_ih.ih_dev = h->ih_dev;
- t_ih.ih_vid = h->ih_vid;
+ 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, afs_cast_uint32(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;
}