vol, volser, and viced type fixes
[openafs.git] / src / vol / listinodes.c
index 992e441..cf5578c 100644 (file)
@@ -20,8 +20,8 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <string.h>
+
 
 #ifndef AFS_NAMEI_ENV
 #if defined(AFS_LINUX20_ENV) || defined(AFS_SUN4_ENV)
@@ -33,8 +33,8 @@ RCSID
  * -2 - Unable to completely write temp file. Produces warning message in log.
  */
 int
-ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-              int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
+ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
+              afs_uint32 (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
               char *wpath, void *rock)
 {
     Log("ListViceInodes not implemented for this platform!\n");
@@ -80,9 +80,6 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
 #endif
 #endif
 #else /* AFS_VFSINCL_ENV */
-#ifdef AFS_DEC_ENV
-#include <sys/time.h>
-#endif /* AFS_DEC_ENV */
 #ifdef AFS_OSF_ENV
 #include <ufs/inode.h>
 #else /* AFS_OSF_ENV */
@@ -110,13 +107,41 @@ 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
+#ifdef S_SPLINT_S
+extern off64_t afs_lseek(int FD, off64_t O, int F);
+#endif /*S_SPLINT_S */
+#define afs_lseek(FD, O, F)   lseek64(FD, (off64_t) (O), F)
+#define afs_stat      stat64
+#define afs_fstat     fstat64
+#define afs_open      open64
+#define afs_fopen     fopen64
+#else /* !O_LARGEFILE */
+#ifdef S_SPLINT_S
+extern off_t afs_lseek(int FD, off_t O, int F);
+#endif /*S_SPLINT_S */
+#define afs_lseek(FD, O, F)   lseek(FD, (off_t) (O), F)
+#define afs_stat      stat
+#define afs_fstat     fstat
+#define afs_open      open
+#define afs_fopen     fopen
+#endif /* !O_LARGEFILE */
+/*@=fcnmacros =macrofcndecl@*/
 
 /* Notice:  parts of this module have been cribbed from vfsck.c */
 
 #define        ROOTINODE       2
 static char *partition;
-extern int Testing;
+int Testing=0;
 int pfd;
 
 #ifdef AFS_AIX32_ENV
@@ -165,11 +190,10 @@ struct dinode *ginode();
 
 
 int
-ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-              int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
+ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
+              int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
               char *wpath, void *rock)
 {
-    FILE *inodeFile = NULL;
     char dev[50], rdev[51];
     struct stat status;
     struct dinode *p;
@@ -251,18 +275,12 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
 
     fmax = fs.s_fsize / (FSBSIZE / 512);       /* first invalid blk num */
 
-    pfd = open(rdev, O_RDONLY);
+    pfd = afs_open(rdev, O_RDONLY);
     if (pfd < 0) {
        Log("Unable to open `%s' inode for reading\n", rdev);
        return -1;
     }
 
-    inodeFile = fopen(resultFile, "w");
-    if (inodeFile == NULL) {
-       Log("Unable to create inode description file %s\n", resultFile);
-       goto out;
-    }
-
     /*
      * calculate the maximum number of inodes possible
      */
@@ -304,43 +322,42 @@ 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;
+       }
 
-    /*
-     * 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 (fstat(fileno(inodeFile), &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;
@@ -350,8 +367,6 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
   out1:
     if (pfd >= 0)
        close(pfd);
-    if (inodeFile)
-       fclose(inodeFile);
 
     return err;
 }
@@ -362,7 +377,7 @@ ReadSuper(struct superblock *fs, char *devName)
 {
     int pfd;
 
-    pfd = open(devName, O_RDONLY);
+    pfd = afs_open(devName, O_RDONLY);
     if (pfd < 0) {
        Log("Unable to open inode on %s for reading superblock.\n", devName);
        return -1;
@@ -436,201 +451,6 @@ ginode(inum)
 /* libefs.h includes <assert.h>, which we don't want */
 #define        __ASSERT_H__
 
-#ifdef AFS_SGI_EFS_IOPS_ENV
-#include "sgiefs/libefs.h"
-extern int Log();
-
-/* afs_efs_figet() replaces the SGI library routine because we are malloc'ing
- * memory for all the inodes on all the cylinder groups without releasing
- * it when we're done. Using afs_efs_figet ensures more efficient use of
- * memory.
- */
-struct efs_dinode *
-afs_efs_figet(EFS_MOUNT * mp, struct efs_dinode *dinodeBuf, int *last_cgno,
-             ino_t inum)
-{
-    int cgno = EFS_ITOCG(mp->m_fs, inum);
-
-
-    if (cgno != *last_cgno) {
-       if (efs_readb
-           (mp->m_fd, (char *)dinodeBuf, EFS_CGIMIN(mp->m_fs, cgno),
-            mp->m_fs->fs_cgisize) != mp->m_fs->fs_cgisize) {
-           Log("Unable to read inodes for cylinder group %d.\n", cgno);
-           return NULL;
-       }
-       *last_cgno = cgno;
-    }
-
-    return dinodeBuf + (inum % (mp->m_fs->fs_cgisize * EFS_INOPBB));
-}
-
-
-int
-efs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-                  int (*judgeInode) (), int judgeParam, int *forcep,
-                  int forceR, char *wpath, void *rock)
-{
-    FILE *inodeFile = NULL;
-    char dev[50], rdev[51];
-    struct stat status;
-    struct efs_dinode *p;
-    struct ViceInodeInfo info;
-    int ninodes = 0, err = 0;
-    struct efs_dinode *dinodeBuf = NULL;
-    int last_cgno;
-    EFS_MOUNT *mp;
-    ino_t imax, inum;          /* total number of I-nodes in file system */
-
-    *forcep = 0;
-
-    partition = mountedOn;
-    sprintf(dev, "/dev/dsk/%s", devname);
-    sprintf(rdev, "/dev/rdsk/%s", devname);
-
-
-    /*
-     * open raw device
-     */
-    efs_init(Log);
-    if ((stat(rdev, &status) == -1)
-       || ((mp = efs_mount(rdev, O_RDONLY)) == NULL)) {
-       sprintf(rdev, "/dev/r%s", devname);
-       mp = efs_mount(rdev, O_RDONLY);
-    }
-    if (mp == NULL) {
-       Log("Unable to open `%s' inode for reading\n", rdev);
-       return -1;
-    }
-
-    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. */
-    dinodeBuf = (struct efs_dinode *)malloc(mp->m_fs->fs_cgisize * BBSIZE);
-    if (!dinodeBuf) {
-       Log("Unable to malloc %lu bytes for inode buffer.\n",
-           mp->m_fs->fs_cgisize * BBSIZE);
-       goto out;
-    }
-
-    /*
-     * calculate the maximum number of inodes possible
-     */
-    imax = mp->m_fs->fs_ncg * mp->m_fs->fs_ipcg;
-
-    last_cgno = -1;
-    for (inum = 2; inum < imax; ++inum) {
-       p = afs_efs_figet(mp, dinodeBuf, &last_cgno, inum);
-       if (!p) {
-           Log("Unable to read all inodes from partition.\n");
-           goto out;
-       }
-       if (!IS_DVICEMAGIC(p) || !((p->di_mode & IFMT) == IFREG)) {
-           continue;
-       }
-#if defined(AFS_SGI_EXMAG)
-       /* volume ID */
-       info.u.param[0] =
-           dmag(p, 0) << 24 | dmag(p, 1) << 16 | dmag(p, 2) << 8 | dmag(p,
-                                                                        3) <<
-           0;
-       if ((p)->di_version == EFS_IVER_AFSSPEC) {
-           info.u.param[1] = INODESPECIAL;
-           /* type */
-           info.u.param[2] = dmag(p, 8);
-           /* parentId */
-           info.u.param[3] =
-               dmag(p, 4) << 24 | dmag(p, 5) << 16 | dmag(p,
-                                                          6) << 8 | dmag(p,
-                                                                         7)
-               << 0;
-       } else {
-           /* vnode number */
-           info.u.param[1] =
-               dmag(p, 4) << 16 | dmag(p, 5) << 8 | dmag(p, 6) << 0;
-           /* disk uniqifier */
-           info.u.param[2] =
-               dmag(p, 7) << 16 | dmag(p, 8) << 8 | dmag(p, 9) << 0;
-           /* data version */
-           info.u.param[3] =
-               dmag(p, 10) << 16 | dmag(p, 11) << 8 | (p)->di_spare;
-       }
-#else
-       BOMB ! !
-#endif
-           info.inodeNumber = inum;
-       info.byteCount = p->di_size;
-       info.linkCount = p->di_nlink;
-#ifdef notdef
-       Log("Ino=%d, bytes=%d, linkCnt=%d, [%x,%x,%x,%x]\n", inum, p->di_size,
-           p->di_nlink, info.u.param[0], info.u.param[1], info.u.param[2],
-           info.u.param[3]);
-#endif
-       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;
-       }
-       ++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;
-    }
-
-    /*
-     * 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) {
-       free(dinodeBuf);
-    }
-    return 0;
-
-  out:
-    err = -1;
-  out1:
-    if (dinodeBuf) {
-       free(dinodeBuf);
-    }
-    efs_umount(mp);
-    if (inodeFile)
-       fclose(inodeFile);
-
-    return err;
-}
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
 #ifdef AFS_SGI_XFS_IOPS_ENV
 #include <dirent.h>
 #include <afs/xfsattrs.h>
@@ -800,7 +620,7 @@ xfs_RenameFiles(char *dir, xfs_Rename_t * renames, int n_renames)
                      int_to_base64(stmp, renames[i].uniq));
        for (tag = 2, j = 0; j < 64; tag++, j++) {
            (void)sprintf(npath, "%s.%s", nbase, int_to_base64(stmp, tag));
-           fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0);
+           fd = afs_open(npath, O_CREAT | O_EXCL | O_RDWR, 0);
            if (fd > 0) {
                close(fd);
                break;
@@ -821,11 +641,10 @@ xfs_RenameFiles(char *dir, xfs_Rename_t * renames, int n_renames)
 
 
 int
-xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-                  int (*judgeInode) (), int judgeParam, int *forcep,
+xfs_ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
+                  int (*judgeInode) (), afs_uint32 judgeParam, int *forcep,
                   int forceR, char *wpath, void *rock)
 {
-    FILE *inodeFile = NULL;
     i_list_inode_t info;
     int info_size = sizeof(i_list_inode_t);
     int fd;
@@ -857,12 +676,6 @@ 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 ((top_dirp = opendir(mountedOn)) == NULL) {
        Log("Can't open directory %s to read inodes.\n", mountedOn);
        return -1;
@@ -964,11 +777,13 @@ 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++;
 
@@ -987,32 +802,28 @@ 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);
+           return errors ? -1 : -2;
+       }
+       if (fsync(fileno(inodeFile)) == -1) {
+           Log("Unable to successfully fsync inode file for %s\n", mountedOn);
+           return errors ? -1 : -2;
+       }
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (fstat(fileno(inodeFile), &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) {
@@ -1029,19 +840,16 @@ xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        closedir(top_dirp);
     if (renames)
        free((char *)renames);
-    if (inodeFile)
-       fclose(inodeFile);
     return -1;
 }
 
 #endif
 
 int
-ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-              int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
+ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
+              int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
               char *wpath, void *rock)
 {
-    FILE *inodeFile = NULL;
     char dev[50], rdev[51];
     struct stat status;
     struct efs_dinode *p;
@@ -1050,9 +858,6 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     int ninodes = 0, err = 0;
     struct efs_dinode *dinodeBuf = NULL;
     int last_cgno;
-#ifdef AFS_SGI_EFS_IOPS_ENV
-    EFS_MOUNT *mp;
-#endif
     ino_t imax, inum;          /* total number of I-nodes in file system */
 
     *forcep = 0;
@@ -1069,13 +874,7 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     }
 #ifdef AFS_SGI_XFS_IOPS_ENV
     if (!strcmp("xfs", root_inode.st_fstype)) {
-       return xfs_ListViceInodes(devname, mountedOn, resultFile, judgeInode,
-                                 judgeParam, forcep, forceR, wpath, rock);
-    } else
-#endif
-#ifdef AFS_SGI_EFS_IOPS_ENV
-    if (root_inode.st_ino == EFS_ROOTINO) {
-       return efs_ListViceInodes(devname, mountedOn, resultFile, judgeInode,
+       return xfs_ListViceInodes(devname, mountedOn, inodeFile, judgeInode,
                                  judgeParam, forcep, forceR, wpath, rock);
     } else
 #endif
@@ -1112,8 +911,8 @@ BUFAREA sblk;
 
 extern char *afs_rawname();
 int
-ListViceInodes(char *devname, char *mountedOn, char *resultFile,
-              int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
+ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
+              int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
               char *wpath, void *rock)
 {
     union {
@@ -1126,7 +925,6 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
 #endif
     } super;
     int i, c, e, bufsize, code, err = 0;
-    FILE *inodeFile = NULL;
     char dev[50], rdev[100], err1[512], *ptr1;
     struct dinode *inodes = NULL, *einodes, *dptr;
     struct stat status;
@@ -1148,7 +946,7 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     sleep(10);
 #endif
 
-    pfd = open(rdev, O_RDONLY);
+    pfd = afs_open(rdev, O_RDONLY);
     if (pfd <= 0) {
        sprintf(err1, "Could not open device %s to get inode list\n", rdev);
        perror(err1);
@@ -1167,11 +965,6 @@ 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;
-    }
 #ifdef AFS_AIX_ENV
     /*
      * char *FSlabel(), *fslabel=0;
@@ -1214,9 +1007,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++;
     }
@@ -1289,10 +1084,10 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        i = c * sblock.fs_ipg;
        e = i + sblock.fs_ipg;
 #if    defined(AFS_HPUX102_ENV)
-       if (lseek(pfd, dbtoo(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
+       if (afs_lseek(pfd, dbtoo(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
            -1) {
 #else
-       if (lseek(pfd, dbtob(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
+       if (afs_lseek(pfd, dbtob(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
            -1) {
 #endif
 #else
@@ -1310,14 +1105,14 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
        e = i + super.fs.fs_ipg;
 #ifdef AFS_OSF_ENV
        dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
-       if (lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET) == -1) {
+       if (afs_lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET) == -1) {
 #else
 #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
        f1 = fsbtodb(&super.fs, itod(&super.fs, i));
        off = (offset_t) f1 << DEV_BSHIFT;
        if (llseek(pfd, off, L_SET) == -1) {
 #else
-       if (lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET)
+       if (afs_lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET)
            == -1) {
 #endif /* AFS_SUN5_ENV */
 #endif /* AFS_OSF_ENV */
@@ -1339,7 +1134,7 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
                for (bj = bk = 0; bj < bufsize; bj = bj + 512, bk++) {
                    if ((code = read(pfd, dptr, 512)) != 512) {
                        Log("Error reading inode %d? for partition %s (errno = %d); run vfsck\n", bk + i, partition, errno);
-                       if (lseek(pfd, 512, L_SET) == -1) {
+                       if (afs_lseek(pfd, 512, L_SET) == -1) {
                            Log("Lseek failed\n");
                            goto out;
                        }
@@ -1423,10 +1218,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++;
                }
@@ -1436,36 +1233,33 @@ 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;
+       }
+       
+       /*
+        * Paranoia:  check that the file is really the right size
+        */
+       if (fstat(fileno(inodeFile), &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;
@@ -1474,8 +1268,6 @@ ListViceInodes(char *devname, char *mountedOn, char *resultFile,
     err = -1;
   out1:
     close(pfd);
-    if (inodeFile)
-       fclose(inodeFile);
     if (inodes)
        free(inodes);
     return err;
@@ -1499,12 +1291,12 @@ bread(int fd, char *buf, daddr_t blk, afs_int32 size)
        return -1;
     }
 #else /* AFS_AIX41_ENV */
-    if (lseek(fd, blk * Bsize, 0) < 0) {
+    if (afs_lseek(fd, blk * Bsize, 0) < 0) {
        Log("Unable to seek to offset %u for block %u\n", blk * Bsize, blk);
     }
 #endif /* AFS_AIX41_ENV */
 #else
-    if (lseek(fd, (off_t) dbtob(blk), L_SET) < 0) {
+    if (afs_lseek(fd, (off_t) dbtob(blk), L_SET) < 0) {
        Log("Unable to seek to offset %u for block %u\n", dbtob(blk), blk);
     }
 #endif
@@ -1516,4 +1308,233 @@ 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;
+}
+
+#ifdef FSSYNC_BUILD_CLIENT
+int
+inode_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
+{
+    char dir_name[512], oldpath[512], newpath[512];
+    char volname[20];
+    char headername[16];
+    char *name;
+    int fd, err, forcep, j;
+    ssize_t len, nBytes;
+    struct dirent *dp;
+    struct DiskPartition64 *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));
+
+#ifdef AFS_DEMAND_ATTACH_FS
+/* DAFS currently doesn't really work with inode, so don't bother putting the
+ * locking code here right now. But in case someday someone makes DAFS work
+ * with the inode backend, make sure they remember to add the volume locking
+ * code here (make the build fail until that happens). If that is what you're
+ * trying to do, take a look at VLockVolumeByIdNB, and
+ * namei_ConvertROtoRWvolume.
+ */
+# error must lock volumes before ConvertROtoRW is usable on DAFS inode
+#endif
+          
+    /* 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;
+    }
+
+    if (VReadVolumeDiskHeader(volumeId, partP, &h)) {
+       Log("1 inode_ConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n",
+           afs_printable_uint32_lu(volumeId));
+       return EIO;
+    }
+
+    FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
+
+    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;
+                   nBytes = write(fdP2->fd_fd, buffer, len);
+                   if (nBytes != len)
+                       return -1;
+               }
+           }
+               
+           FDH_CLOSE(fdP);
+           FDH_CLOSE(fdP2);
+
+           /* Unlink the old special inode; otherwise we will get duplicate
+            * special inodes if we recreate the RO again */
+           if (IH_DEC(ih, specinos[j].inodeNumber, volumeId) == -1) {
+               Log("IH_DEC failed: %x, %s, %u errno %d\n", ih,
+                   PrintInode(NULL, specinos[j].inodeNumber), volumeId, errno);
+           }
+
+           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
+
+    if (VCreateVolumeDiskHeader(&h, partP)) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't write header for RW-volume %lu\n",
+           afs_printable_uint32_lu(h.id));
+        return EIO;
+    }
+
+    if (VDestroyVolumeDiskHeader(partP, volumeId, h.parent)) {
+        Log("1 inode_ConvertROtoRWvolume: Couldn't unlink header for RO-volume %lu\n",
+           afs_printable_uint32_lu(volumeId));
+    }
+
+    FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
+    FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
+    return 0;
+}
+#endif /* FSSYNC_BUILD_CLIENT */
 #endif /* AFS_NAMEI_ENV */