DEVEL15-volserver-split-volume-functionality-20090324
[openafs.git] / src / vol / namei_ops.c
index 824a8a6..f530a31 100644 (file)
@@ -18,6 +18,7 @@ RCSID
 #ifdef AFS_NAMEI_ENV
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -40,6 +41,7 @@ RCSID
 #include "viceinode.h"
 #include "voldefs.h"
 #include "partition.h"
+#include "fssync.h"
 #include <afs/errors.h>
 
 /*@+fcnmacros +macrofcndecl@*/
@@ -604,6 +606,8 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
 
     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);
     }
@@ -728,7 +732,7 @@ namei_dec(IHandle_t * ih, Inode ino, int p1)
        } 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);
          
@@ -793,6 +797,79 @@ namei_inc(IHandle_t * h, Inode ino, int p1)
     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
  ************************************************************************
@@ -989,8 +1066,10 @@ GetFreeTag(IHandle_t * ih, int vno)
        if ((row & coldata) == 0)
            break;
     }
-    if (col >= NAMEI_MAXVOLS)
+    if (col >= NAMEI_MAXVOLS) {
+       errno = ENOSPC;
        goto badGetFreeTag;
+    }
 
     coldata = 1 << (col * 3);
     row |= coldata;
@@ -1084,8 +1163,8 @@ static int namei_ListAFSSubDirs(IHandle_t * dirIH,
                                                  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
@@ -1136,8 +1215,8 @@ VerifyDirPerms(char *path)
  */
 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;
@@ -1213,8 +1292,8 @@ int
 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;
@@ -1285,8 +1364,8 @@ static int
 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;
@@ -1445,6 +1524,7 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info, int volid)
     char fpath[512];
     struct afs_stat status;
     int parm, tag;
+    lb64_string_t check;
 
     (void)strcpy(fpath, dpath);
     (void)strcat(fpath, "/");
@@ -1457,6 +1537,10 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info, int volid)
     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 */
@@ -1481,10 +1565,7 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info, int volid)
  */
 
 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;
@@ -1536,14 +1617,16 @@ convertVolumeInfo(fdr, fdw, vid)
  */
 
 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;
@@ -1551,10 +1634,39 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
     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;
+
+    (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, h);
+    namei_HandleToName(&n, ih);
     strcpy(dir_name, n.n_path);
     p = strrchr(dir_name, '/');
     *p = 0;
@@ -1569,7 +1681,7 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
 
        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);
@@ -1580,8 +1692,8 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
            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;
@@ -1619,8 +1731,8 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
      */
 
     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);
@@ -1629,7 +1741,7 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
            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) {
@@ -1637,17 +1749,17 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
        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);
@@ -1655,12 +1767,12 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
        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);
@@ -1668,12 +1780,38 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
        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;
 }