namei: Ignore misplaced files
[openafs.git] / src / vol / namei_ops.c
index 4e845b6..05d20e9 100644 (file)
@@ -1719,7 +1719,7 @@ 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,
-                      VolumeId volid);
+                      IHandle_t *myIH);
 static int DecodeVolumeName(char *name, VolumeId *vid);
 static int namei_ListAFSSubDirs(IHandle_t * dirIH,
                                int (*write_fun) (FD_t,
@@ -1982,7 +1982,7 @@ _namei_examine_special(char * path1,
     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;
     }
@@ -2073,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;
     }
 
@@ -2732,7 +2732,7 @@ DecodeVolumeName(char *name, VolumeId *vid)
 #ifdef AFS_NT40_ENV
 static int
 DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
-           VolumeId volid)
+           IHandle_t *myIH)
 {
     char fpath[512];
     int tag, vno;
@@ -2742,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);
 
@@ -2808,12 +2809,16 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
 #else
 static int
 DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
-           VolumeId 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);
 
@@ -2828,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);
@@ -3016,7 +3051,7 @@ namei_ConvertROtoRWvolume(char *pname, VolumeId 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);