DEVEL15-inode-convert-ro-to-rw-20071113
authorDerrick Brashear <shadow@dementia.org>
Tue, 13 Nov 2007 22:15:20 +0000 (22:15 +0000)
committerDerrick Brashear <shadow@dementia.org>
Tue, 13 Nov 2007 22:15:20 +0000 (22:15 +0000)
so this functionality works with inode fileserver, also. corrected abstraction from previous versions so vol and volser have correct bits.

(cherry picked from commit b98b51185dbd46ef6d9ef0249b032bbc49d13bfb)

src/vol/listinodes.c
src/vol/namei_ops.c
src/volser/volprocs.c

index b2789c8..1728824 100644 (file)
@@ -109,7 +109,13 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
 #if defined(AFS_HPUX101_ENV)
 #include <unistd.h>
 #endif
+#include "lock.h"
+#include "ihandle.h"
+#include "vnode.h"
+#include "volume.h"
+#include "volinodes.h"
 #include "partition.h"
+#include "fssync.h"
 
 /*@+fcnmacros +macrofcndecl@*/
 #ifdef O_LARGEFILE
@@ -278,10 +284,12 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        return -1;
     }
 
-    inodeFile = fopen(resultFile, "w");
-    if (inodeFile == NULL) {
-       Log("Unable to create inode description file %s\n", resultFile);
-       goto out;
+    if (resultFile) {
+       inodeFile = fopen(resultFile, "w");
+       if (inodeFile == NULL) {
+           Log("Unable to create inode description file %s\n", resultFile);
+           goto out;
+       }
     }
 
     /*
@@ -325,43 +333,47 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
            continue;
 
-       if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
-           Log("Error writing inode file for partition %s\n", partition);
-           goto out;
+       if (inodeFile) {
+           if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
+               Log("Error writing inode file for partition %s\n", partition);
+               goto out;
+           }
        }
        ++ninodes;
     }
 
-    if (fflush(inodeFile) == EOF) {
-       Log("Unable to successfully flush inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fsync(fileno(inodeFile)) == -1) {
-       Log("Unable to successfully fsync inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fclose(inodeFile) == EOF) {
-       Log("Unable to successfully close inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
+    if (inodeFile) {
+       if (fflush(inodeFile) == EOF) {
+           Log("Unable to successfully flush inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fsync(fileno(inodeFile)) == -1) {
+           Log("Unable to successfully fsync inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fclose(inodeFile) == EOF) {
+           Log("Unable to successfully close inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
 
-    /*
-     * Paranoia:  check that the file is really the right size
-     */
-    if (stat(resultFile, &status) == -1) {
-       Log("Unable to successfully stat inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
-       Log("Wrong size (%d instead of %d) in inode file for %s\n",
-           status.st_size, ninodes * sizeof(struct ViceInodeInfo),
-           partition);
-       err = -2;
-       goto out1;
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (stat(resultFile, &status) == -1) {
+           Log("Unable to successfully stat inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
+           Log("Wrong size (%d instead of %d) in inode file for %s\n",
+               status.st_size, ninodes * sizeof(struct ViceInodeInfo),
+               partition);
+           err = -2;
+           goto out1;
+       }
     }
     close(pfd);
     return 0;
@@ -524,10 +536,12 @@ efs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        return -1;
     }
 
-    inodeFile = fopen(resultFile, "w");
-    if (inodeFile == NULL) {
-       Log("Unable to create inode description file %s\n", resultFile);
-       goto out;
+    if (resultFile) {
+       inodeFile = fopen(resultFile, "w");
+       if (inodeFile == NULL) {
+           Log("Unable to create inode description file %s\n", resultFile);
+           goto out;
+       }
     }
 
     /* Allocate space for one cylinder group's worth of inodes. */
@@ -594,43 +608,47 @@ efs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
            continue;
 
-       if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
-           Log("Error writing inode file for partition %s\n", partition);
-           goto out;
+       if (inodeFile) {
+           if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
+               Log("Error writing inode file for partition %s\n", partition);
+               goto out;
+           }
        }
        ++ninodes;
     }
 
-    if (fflush(inodeFile) == EOF) {
-       Log("Unable to successfully flush inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fsync(fileno(inodeFile)) == -1) {
-       Log("Unable to successfully fsync inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fclose(inodeFile) == EOF) {
-       Log("Unable to successfully close inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
+    if (inodeFile) {
+       if (fflush(inodeFile) == EOF) {
+           Log("Unable to successfully flush inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fsync(fileno(inodeFile)) == -1) {
+           Log("Unable to successfully fsync inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fclose(inodeFile) == EOF) {
+           Log("Unable to successfully close inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
 
-    /*
-     * Paranoia:  check that the file is really the right size
-     */
-    if (stat(resultFile, &status) == -1) {
-       Log("Unable to successfully stat inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
-       Log("Wrong size (%d instead of %d) in inode file for %s\n",
-           status.st_size, ninodes * sizeof(struct ViceInodeInfo),
-           partition);
-       err = -2;
-       goto out1;
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (stat(resultFile, &status) == -1) {
+           Log("Unable to successfully stat inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
+           Log("Wrong size (%d instead of %d) in inode file for %s\n",
+               status.st_size, ninodes * sizeof(struct ViceInodeInfo),
+               partition);
+           err = -2;
+           goto out1;
+       }
     }
     efs_umount(mp);
     if (dinodeBuf) {
@@ -878,10 +896,12 @@ xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        return -1;
     }
 
-    inodeFile = fopen(resultFile, "w");
-    if (inodeFile == NULL) {
-       Log("Unable to create inode description file %s\n", resultFile);
-       return -1;
+    if (resultFile) {
+       inodeFile = fopen(resultFile, "w");
+       if (inodeFile == NULL) {
+           Log("Unable to create inode description file %s\n", resultFile);
+           return -1;
+       }
     }
 
     if ((top_dirp = opendir(mountedOn)) == NULL) {
@@ -985,11 +1005,11 @@ xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
                n_renames++;
            }
 
-           if (fwrite
-               (&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile)
-               != 1) {
-               Log("Error writing inode file for partition %s\n", mountedOn);
-               goto err1_exit;
+           if (inodeFile) {
+               if (fwrite(&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile) != 1) {
+                   Log("Error writing inode file for partition %s\n", mountedOn);
+                   goto err1_exit;
+               }
            }
            ninodes++;
 
@@ -1008,32 +1028,35 @@ xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     closedir(top_dirp);
     if (renames)
        free((char *)renames);
-    if (fflush(inodeFile) == EOF) {
-       ("Unable to successfully flush inode file for %s\n", mountedOn);
-       fclose(inodeFile);
-       return errors ? -1 : -2;
-    }
-    if (fsync(fileno(inodeFile)) == -1) {
-       Log("Unable to successfully fsync inode file for %s\n", mountedOn);
-       fclose(inodeFile);
-       return errors ? -1 : -2;
-    }
-    if (fclose(inodeFile) == EOF) {
-       Log("Unable to successfully close inode file for %s\n", mountedOn);
-       return errors ? -1 : -2;
-    }
-    /*
-     * Paranoia:  check that the file is really the right size
-     */
-    if (stat(resultFile, &status) == -1) {
-       Log("Unable to successfully stat inode file for %s\n", partition);
-       return errors ? -1 : -2;
-    }
-    if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
-       Log("Wrong size (%d instead of %d) in inode file for %s\n",
-           status.st_size, ninodes * sizeof(struct ViceInodeInfo),
-           partition);
-       return errors ? -1 : -2;
+
+    if (inodeFile) {
+       if (fflush(inodeFile) == EOF) {
+           ("Unable to successfully flush inode file for %s\n", mountedOn);
+           fclose(inodeFile);
+           return errors ? -1 : -2;
+       }
+       if (fsync(fileno(inodeFile)) == -1) {
+           Log("Unable to successfully fsync inode file for %s\n", mountedOn);
+           fclose(inodeFile);
+           return errors ? -1 : -2;
+       }
+       if (fclose(inodeFile) == EOF) {
+           Log("Unable to successfully close inode file for %s\n", mountedOn);
+           return errors ? -1 : -2;
+       }
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (stat(resultFile, &status) == -1) {
+           Log("Unable to successfully stat inode file for %s\n", partition);
+           return errors ? -1 : -2;
+       }
+       if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
+           Log("Wrong size (%d instead of %d) in inode file for %s\n",
+               status.st_size, ninodes * sizeof(struct ViceInodeInfo),
+               partition);
+           return errors ? -1 : -2;
+       }
     }
 
     if (errors) {
@@ -1188,10 +1211,12 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        goto out;
     }
 
-    inodeFile = fopen(resultFile, "w");
-    if (inodeFile == NULL) {
-       Log("Unable to create inode description file %s\n", resultFile);
-       goto out;
+    if (resultFile) {
+       inodeFile = fopen(resultFile, "w");
+       if (inodeFile == NULL) {
+           Log("Unable to create inode description file %s\n", resultFile);
+           goto out;
+       }
     }
 #ifdef AFS_AIX_ENV
     /*
@@ -1235,9 +1260,11 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        info.u.param[3] = auxp->aux_param4;
        if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
            continue;
-       if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
-           Log("Error writing inode file for partition %s\n", partition);
-           goto out;
+       if (inodeFile) {
+           if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
+               Log("Error writing inode file for partition %s\n", partition);
+               goto out;
+           }
        }
        ninodes++;
     }
@@ -1444,10 +1471,12 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
                    info.linkCount = p->di_nlink;
                    if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
                        continue;
-                   if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
-                       Log("Error writing inode file for partition %s\n",
-                           partition);
-                       goto out;
+                   if (inodeFile) {
+                       if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
+                           Log("Error writing inode file for partition %s\n",
+                               partition);
+                           goto out;
+                       }
                    }
                    ninodes++;
                }
@@ -1457,36 +1486,38 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     if (inodes)
        free(inodes);
 #endif
-    if (fflush(inodeFile) == EOF) {
-       Log("Unable to successfully flush inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fsync(fileno(inodeFile)) == -1) {
-       Log("Unable to successfully fsync inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (fclose(inodeFile) == EOF) {
-       Log("Unable to successfully close inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-
-    /*
-     * Paranoia:  check that the file is really the right size
-     */
-    if (stat(resultFile, &status) == -1) {
-       Log("Unable to successfully stat inode file for %s\n", partition);
-       err = -2;
-       goto out1;
-    }
-    if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
-       Log("Wrong size (%d instead of %d) in inode file for %s\n",
-           status.st_size, ninodes * sizeof(struct ViceInodeInfo),
-           partition);
-       err = -2;
-       goto out1;
+    if (inodeFile) {
+       if (fflush(inodeFile) == EOF) {
+           Log("Unable to successfully flush inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fsync(fileno(inodeFile)) == -1) {
+           Log("Unable to successfully fsync inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (fclose(inodeFile) == EOF) {
+           Log("Unable to successfully close inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (stat(resultFile, &status) == -1) {
+           Log("Unable to successfully stat inode file for %s\n", partition);
+           err = -2;
+           goto out1;
+       }
+       if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
+           Log("Wrong size (%d instead of %d) in inode file for %s\n",
+               status.st_size, ninodes * sizeof(struct ViceInodeInfo),
+               partition);
+           err = -2;
+           goto out1;
+       }
     }
     close(pfd);
     return 0;
@@ -1537,4 +1568,223 @@ bread(int fd, char *buf, daddr_t blk, afs_int32 size)
 }
 
 #endif /* AFS_LINUX20_ENV */
+static afs_int32
+convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
+{
+    struct VolumeDiskData vd;
+    char *p;
+
+    if (read(fdr, &vd, sizeof(struct VolumeDiskData)) !=
+        sizeof(struct VolumeDiskData)) {
+        Log("1 convertiVolumeInfo: read failed for %lu with code %d\n", vid,
+            errno);
+        return -1;
+    }
+    vd.restoredFromId = vd.id;  /* remember the RO volume here */
+    vd.cloneId = vd.id;
+    vd.id = vd.parentId;
+    vd.type = RWVOL;
+    vd.dontSalvage = 0;
+    vd.inUse = 0;
+    vd.uniquifier += 5000;      /* just in case there are still file copies 
+                                  from the old RW volume around */
+
+    p = strrchr(vd.name, '.');
+    if (p && !strcmp(p, ".readonly")) {
+        memset(p, 0, 9);
+    }
+
+    if (write(fdw, &vd, sizeof(struct VolumeDiskData)) !=
+        sizeof(struct VolumeDiskData)) {
+        Log("1 convertiVolumeInfo: write failed for %lu with code %d\n", vid,
+            errno);
+        return -1;
+    }
+    return 0;
+}
+
+struct specino {
+    afs_int32 inodeType;
+    Inode inodeNumber;
+    Inode ninodeNumber;
+};
+
+
+int
+UpdateThisVolume(struct ViceInodeInfo *inodeinfo, VolumeId singleVolumeNumber, 
+                struct specino *specinos)
+{
+    struct dinode *p;
+    if ((inodeinfo->u.vnode.vnodeNumber == INODESPECIAL) &&
+       (inodeinfo->u.vnode.volumeId == singleVolumeNumber)) {
+       specinos[inodeinfo->u.special.type].inodeNumber = 
+           inodeinfo->inodeNumber;
+    }
+    return 0; /* We aren't using a result file, we're caching */
+}
+
+static char *
+getDevName(char *pbuffer, char *wpath)
+{
+    char pbuf[128], *ptr;
+    strcpy(pbuf, pbuffer);
+    ptr = (char *)strrchr(pbuf, '/');
+    if (ptr) {
+        *ptr = '\0';
+        strcpy(wpath, pbuf);
+    } else
+        return NULL;
+    ptr = (char *)strrchr(pbuffer, '/');
+    if (ptr) {
+        strcpy(pbuffer, ptr + 1);
+        return pbuffer;
+    } else
+        return NULL;
+}
+
+int
+inode_ConvertROtoRWvolume(char *pname, afs_int32 volumeId)
+{
+    char dir_name[512], oldpath[512], newpath[512];
+    char volname[20];
+    char headername[16];
+    char *name;
+    int fd, err, forcep, len, j, code;
+    struct dirent *dp;
+    struct DiskPartition *partP;
+    struct ViceInodeInfo info;
+    struct VolumeDiskHeader h;
+    IHandle_t *ih, *ih2;
+    FdHandle_t *fdP, *fdP2;
+    char wpath[100];
+    char tmpDevName[100];
+    char buffer[128];
+    struct specino specinos[VI_LINKTABLE+1];
+    Inode nearInode = 0;
+
+    memset(&specinos, 0, sizeof(specinos));
+          
+    (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 inode_ConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
+        return ENOENT;
+    }
+    if (read(fd, &h, sizeof(h)) != sizeof(h)) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
+        close(fd);
+        return EIO;
+    }
+    close(fd);
+    FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
+
+    /* now do the work */
+          
+    for (partP = DiskPartitionList; partP && strcmp(partP->name, pname);
+         partP = partP->next);
+    if (!partP) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
+        return EIO;
+    }
+
+    strcpy(tmpDevName, partP->devName);
+    name = getDevName(tmpDevName, wpath);
+
+    if ((err = ListViceInodes(name, VPartitionPath(partP), 
+                             NULL, UpdateThisVolume, volumeId, 
+                             &forcep, 0, wpath, &specinos)) < 0)
+    {
+       Log("1 inode_ConvertROtoRWvolume: Couldn't get special inodes\n");
+       return EIO;
+    }
+          
+#if defined(NEARINODE_HINT)
+    nearInodeHash(volumeId, nearInode);
+    nearInode %= partP->f_files;
+#endif
+
+    for (j = VI_VOLINFO; j < VI_LINKTABLE+1; j++) {
+       if (specinos[j].inodeNumber > 0) {
+           specinos[j].ninodeNumber = 
+               IH_CREATE(NULL, partP->device, VPartitionPath(partP),
+                         nearInode, h.parent, INODESPECIAL, j, h.parent);
+           IH_INIT(ih, partP->device, volumeId, 
+                   specinos[j].inodeNumber);
+           fdP = IH_OPEN(ih);
+           if (!fdP) {
+               Log("1 inode_ConvertROtoRWvolume: Couldn't find special inode %d for %d\n", j, volumeId); 
+               return -1;
+           }
+           
+           IH_INIT(ih2, partP->device, h.parent, specinos[j].ninodeNumber);
+           fdP2 = IH_OPEN(ih2); 
+           if (!fdP2) { 
+               Log("1 inode_ConvertROtoRWvolume: Couldn't find special inode %d for %d\n", j, h.parent);  
+               return -1; 
+           } 
+           
+           if (j == VI_VOLINFO)
+               convertVolumeInfo(fdP->fd_fd, fdP2->fd_fd, ih2->ih_vid);
+           else {
+               while (1) {
+                   len = read(fdP->fd_fd, buffer, sizeof(buffer));
+                   if (len < 0)
+                       return errno;
+                   if (len == 0)
+                       break;
+                   code = write(fdP2->fd_fd, buffer, len);
+                   if (code != len)
+                       return -1;
+               }
+           }
+               
+           FDH_CLOSE(fdP);
+           FDH_CLOSE(fdP2);
+           IH_RELEASE(ih);
+           IH_RELEASE(ih2);
+       }
+    }
+   
+    h.id = h.parent;
+#ifdef AFS_64BIT_IOPS_ENV
+    h.volumeInfo_lo = (afs_int32)specinos[VI_VOLINFO].ninodeNumber & 0xffffffff;
+    h.volumeInfo_hi = (afs_int32)(specinos[VI_VOLINFO].ninodeNumber >> 32) && 0xffffffff;
+    h.smallVnodeIndex_lo = (afs_int32)specinos[VI_SMALLINDEX].ninodeNumber & 0xffffffff;
+    h.smallVnodeIndex_hi = (afs_int32)(specinos[VI_SMALLINDEX].ninodeNumber >> 32) & 0xffffffff;
+    h.largeVnodeIndex_lo = (afs_int32)specinos[VI_LARGEINDEX].ninodeNumber & 0xffffffff;
+    h.largeVnodeIndex_hi = (afs_int32)(specinos[VI_LARGEINDEX].ninodeNumber >> 32) & 0xffffffff;
+    if (specinos[VI_LINKTABLE].ninodeNumber) {
+       h.linkTable_lo = (afs_int32)specinos[VI_LINKTABLE].ninodeNumber & 0xffffffff;
+       h.linkTable_hi = (afs_int32)specinos[VI_LINKTABLE].ninodeNumber & 0xffffffff;
+    }
+#else
+    h.volumeInfo_lo = specinos[VI_VOLINFO].ninodeNumber;
+    h.smallVnodeIndex_lo = specinos[VI_SMALLINDEX].ninodeNumber;
+    h.largeVnodeIndex_lo = specinos[VI_LARGEINDEX].ninodeNumber;
+    if (specinos[VI_LINKTABLE].ninodeNumber) {
+       h.linkTable_lo = specinos[VI_LINKTABLE].ninodeNumber;
+    }
+#endif
+
+    (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 inode_ConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
+        return EIO;
+    }
+    if (write(fd, &h, sizeof(h)) != sizeof(h)) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
+        close(fd);
+        return EIO;
+    }
+    close(fd);
+    if (unlink(oldpath) < 0) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", errno);
+    }
+    FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
+    FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
+    return 0;
+}
 #endif /* AFS_NAMEI_ENV */
index 240e4be..509a7a3 100644 (file)
@@ -41,6 +41,7 @@ RCSID
 #include "voldefs.h"
 #include "partition.h"
 #include <afs/errors.h>
+#include <afs/fssync.h>
 
 /*@+fcnmacros +macrofcndecl@*/
 #ifdef O_LARGEFILE
@@ -1543,7 +1544,7 @@ convertVolumeInfo(fdr, fdw, vid)
  */
 
 int
-namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
+namei_ConvertROtoRWvolume(char *pname, afs_int32 volumeId)
 {
     namei_t n;
     char dir_name[512], oldpath[512], newpath[512];
@@ -1551,17 +1552,48 @@ namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid)
     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 DiskPartition *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_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
+
+    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;
@@ -1576,7 +1608,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);
@@ -1587,8 +1619,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;
@@ -1626,8 +1658,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);
@@ -1636,7 +1668,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) {
@@ -1644,17 +1676,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);
@@ -1662,12 +1694,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);
@@ -1675,12 +1707,37 @@ 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, 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_askfs(volumeId, pname, FSYNC_DONE, 0);
+    FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
     return 0;
 }
 
index 321bf38..a63b0f6 100644 (file)
@@ -191,7 +191,7 @@ XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
        *error = EINVAL;
        return NULL;
     }
-    tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
+    tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
     return tv;
 }
 
@@ -2758,116 +2758,65 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
     return error;
 }
 
-#ifdef AFS_NAMEI_ENV
-/* 
- * Inode number format  (from namei_ops.c): 
- * low 26 bits - vnode number - all 1's if volume special file.
- * next 3 bits - tag
- * next 3 bits spare (0's)
- * high 32 bits - uniquifier (regular) or type if spare
- */
-#define NAMEI_VNODEMASK    0x003ffffff
-#define NAMEI_TAGMASK      0x7
-#define NAMEI_TAGSHIFT     26
-#define NAMEI_UNIQMASK     0xffffffff
-#define NAMEI_UNIQSHIFT    32
-#define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
-#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
-#endif /* AFS_NAMEI_ENV */
-
 afs_int32
 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
                           afs_int32 volumeId)
 {
-#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
+#ifdef AFS_NT40_ENV
+    return EXDEV;
+#else
+    char caller[MAXKTCNAMELEN];
     DIR *dirp;
-    char pname[16];
-    char volname[20];
-    afs_int32 error = 0;
+    register struct volser_trans *ttc;
+    char pname[16], volname[20];
+    struct DiskPartition *partP;
+    afs_int32 ret = ENODEV;
     afs_int32 volid;
-    int found = 0;
-    char caller[MAXKTCNAMELEN];
-    char headername[16];
-    char opath[256];
-    char npath[256];
-    struct VolumeDiskHeader h;
-    int fd;
-    IHandle_t *ih;
-    Inode ino;
-    struct DiskPartition *dp;
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
     if (GetPartName(partId, pname))
-       return VOLSERILLEGAL_PARTITION;
-    dirp = opendir(pname);
+        return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+        return VOLSERILLEGAL_PARTITION;
+    dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
        return VOLSERILLEGAL_PARTITION;
     strcpy(volname, "");
+    ttc = (struct volser_trans *)0;
 
-    while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
-       GetNextVol(dirp, volname, &volid);
-       if (strcmp(volname, "")) {      /* its a volume */
-           if (volid == volumeId)
-               found = 1;
+    while (strcmp(volname, "EOD")) {
+       if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
+            GetNextVol(dirp, volname, &volid);
+            continue;           /*back to while loop */
+        }
+       
+       if (volid == volumeId) {        /*copy other things too */
+#ifndef AFS_PTHREAD_ENV
+            IOMGR_Poll();       /*make sure that the client doesnot time out */
+#endif
+            ttc = NewTrans(volumeId, partId);
+            if (!ttc) {
+               return VBUSY;
+            }
+#ifdef AFS_NAMEI_ENV
+           ret = namei_ConvertROtoRWvolume(pname, volumeId);
+#else
+           ret = inode_ConvertROtoRWvolume(pname, volumeId);
+#endif
+           break;
        }
+       GetNextVol(dirp, volname, &volid);
     }
-    if (!found)
-       return ENOENT;
-    (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
-    (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
-    fd = open(opath, O_RDONLY);
-    if (fd < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
-       return ENOENT;
-    }
-    if (read(fd, &h, sizeof(h)) != sizeof(h)) {
-       Log("1 SAFS_VolConvertROtoRWvolume: 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 (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
-        dp = dp->next);
-    if (!dp) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
-       return EIO;
-    }
-    ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
-    IH_INIT(ih, dp->device, h.parent, ino);
-
-    error = namei_ConvertROtoRWvolume(ih, volumeId);
-    if (error)
-       return error;
-    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(npath, sizeof npath, "%s/%s", pname, headername);
-    fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
-    if (fd < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
-       return EIO;
-    }
-    if (write(fd, &h, sizeof(h)) != sizeof(h)) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
-       close(fd);
-       return EIO;
-    }
-    close(fd);
-    if (unlink(opath) < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
+    
+    if (ttc) {
+        DeleteTrans(ttc, 1);
+        ttc = (struct volser_trans *)0;
     }
-    FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
-    FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
-    return 0;
-#else /* AFS_NAMEI_ENV */
-    return EINVAL;
-#endif /* AFS_NAMEI_ENV */
+    
+    closedir(dirp);
+    return ret;
+#endif
 }
 
 afs_int32