namei: Ignore misplaced files
[openafs.git] / src / vol / namei_ops.c
index 7274af5..05d20e9 100644 (file)
 #include <direct.h>
 #endif
 
+#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>
@@ -448,7 +453,7 @@ delTree(char *root, char *tree, int *errp)
            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 .. */
@@ -594,7 +599,7 @@ namei_RemoveDataDirectories(namei_t * name)
  * 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;
@@ -947,7 +952,8 @@ bad:
 }
 #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,
+        FD_t *afd, Inode *ainode)
 {
     namei_t name;
     int fd = INVALID_FD;
@@ -1037,10 +1043,6 @@ namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint
     }
 
   bad:
-    if (fd != INVALID_FD)
-       OS_CLOSE(fd);
-
-
     if (code || (fd == INVALID_FD)) {
        if (p2 != -1) {
            fdP = IH_OPEN(lh);
@@ -1050,7 +1052,56 @@ namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint
            }
        }
     }
-    return (code || (fd == INVALID_FD)) ? (Inode) - 1 : tmp.ih_ino;
+
+    *afd = fd;
+    *ainode = tmp.ih_ino;
+
+    return code;
+}
+
+Inode
+namei_icreate(IHandle_t * lh, char *part,
+              afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+{
+    Inode ino = 0;
+    int fd = INVALID_FD;
+    int code;
+
+    code = icreate(lh, part, p1, p2, p3, p4, &fd, &ino);
+    if (fd != INVALID_FD) {
+       close(fd);
+    }
+    return (code || (fd == INVALID_FD)) ? (Inode) - 1 : 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)
+{
+    Inode ino = 0;
+    int fd = INVALID_FD;
+    int code;
+    IHandle_t *ihP;
+    FdHandle_t *fdP;
+
+    code = icreate(lh, part, p1, p2, p3, p4, &fd, &ino);
+    if (fd == INVALID_FD) {
+       return NULL;
+    }
+    if (code) {
+       close(fd);
+       return NULL;
+    }
+
+    IH_INIT(ihP, dev, p1, ino);
+    fdP = ih_attachfd(ihP, fd);
+    if (!fdP) {
+       close(fd);
+    } else {
+       FDH_CLOSE(fdP);
+    }
+
+    return ihP;
 }
 #endif
 
@@ -1161,8 +1212,8 @@ 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",
-               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;
@@ -1451,8 +1502,8 @@ namei_GetLCOffsetAndIndexFromIno(Inode ino, afs_foff_t * offset, int *index)
 #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
@@ -1668,15 +1719,15 @@ namei_SetLinkCount(FdHandle_t * fdP, Inode ino, int count, int locked)
 
 /* 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) (FD_t,
                                                  struct ViceInodeInfo *,
                                                  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
@@ -1740,8 +1791,8 @@ VerifyDirPerms(char *path)
  */
 int
 ListViceInodes(char *devname, char *mountedOn, FD_t inodeFile,
-              int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
-              afs_uint32 singleVolumeNumber, int *forcep, int forceR, char *wpath,
+              int (*judgeInode) (struct ViceInodeInfo * info, VolumeId vid, void *rock),
+              VolumeId singleVolumeNumber, int *forcep, int forceR, char *wpath,
               void *rock)
 {
     int ninodes;
@@ -1807,8 +1858,8 @@ namei_ListAFSFiles(char *dev,
                   int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
                                    char *),
                   FD_t fp,
-                  int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-                  afs_uint32 singleVolumeNumber, void *rock)
+                  int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+                  VolumeId singleVolumeNumber, void *rock)
 {
     IHandle_t ih;
     namei_t name;
@@ -1924,14 +1975,14 @@ _namei_examine_special(char * path1,
                       int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
                                        char *),
                       FD_t fp,
-                      int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-                      int singleVolumeNumber,
+                      int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+                      VolumeId singleVolumeNumber,
                       void *rock)
 {
     int ret = 0;
     struct ViceInodeInfo info;
 
-    if (DecodeInode(path1, dname, &info, myIH->ih_vid) < 0) {
+    if (DecodeInode(path1, dname, &info, myIH) < 0) {
        ret = 0;
        goto error;
     }
@@ -1943,9 +1994,14 @@ _namei_examine_special(char * path1,
         * 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)\n",
-           path1, dname, myIH->ih_vid,
-           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 */
@@ -2007,8 +2063,8 @@ _namei_examine_reg(char * path3,
                   int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
                                    char *),
                   FD_t fp,
-                  int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-                  int singleVolumeNumber,
+                  int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+                  VolumeId singleVolumeNumber,
                   void *rock)
 {
     int ret = 0;
@@ -2017,7 +2073,7 @@ _namei_examine_reg(char * path3,
     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;
     }
 
@@ -2078,8 +2134,8 @@ struct listsubdirs_work_node {
     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
@@ -2248,7 +2304,7 @@ static pthread_key_t wq_key;
 static void
 _namei_wq_keycreate(void)
 {
-    osi_Assert(pthread_key_create(&wq_key, NULL) == 0);
+    opr_Verify(pthread_key_create(&wq_key, NULL) == 0);
 }
 
 /**
@@ -2262,9 +2318,9 @@ _namei_wq_keycreate(void)
 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);
 }
 
 /**
@@ -2405,8 +2461,8 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
                     int (*writeFun) (FD_t, struct ViceInodeInfo *, char *,
                                      char *),
                     FD_t fp,
-                    int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-                    afs_uint32 singleVolumeNumber, void *rock)
+                    int (*judgeFun) (struct ViceInodeInfo *, VolumeId, void *),
+                    VolumeId singleVolumeNumber, void *rock)
 {
     int code = 0, ret = 0;
     IHandle_t myIH = *dirIH;
@@ -2440,7 +2496,7 @@ namei_ListAFSSubDirs(IHandle_t * 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) {
@@ -2510,8 +2566,8 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
 #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 */
@@ -2638,7 +2694,7 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
 
 #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];
@@ -2658,7 +2714,7 @@ DecodeVolumeName(char *name, unsigned int *vid)
 }
 #else
 static int
-DecodeVolumeName(char *name, unsigned int *vid)
+DecodeVolumeName(char *name, VolumeId *vid)
 {
     if (strlen(name) < 1)
        return -1;
@@ -2676,7 +2732,7 @@ DecodeVolumeName(char *name, unsigned int *vid)
 #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;
@@ -2686,6 +2742,7 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
     char stmp[16];
     FdHandle_t linkHandle;
     char dirl;
+    VolumeId volid = myIH->ih_vid;
 
     snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
 
@@ -2752,12 +2809,16 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
 #else
 static int
 DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
-           unsigned int volid)
+           IHandle_t *myIH)
 {
     char fpath[512];
     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;
 
     snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name);
 
@@ -2772,6 +2833,36 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
     if (strcmp(name, check))
        return -1;
 
+    /* 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);
@@ -2801,15 +2892,15 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
 
 #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;
     }
@@ -2871,7 +2962,7 @@ convertVolumeInfo(FD_t fdr, FD_t fdw, afs_uint32 vid)
  */
 
 int
-namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
+namei_ConvertROtoRWvolume(char *pname, VolumeId volumeId)
 {
     int code = 0;
 #ifdef FSSYNC_BUILD_CLIENT
@@ -2960,7 +3051,7 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
        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);
@@ -2998,7 +3089,7 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
            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;
        }
@@ -3154,7 +3245,7 @@ static zlcList_t *zlcCur = NULL;
 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)