From 1437175df5c8c799d11c92eaeaf3470534cbcb9b Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Fri, 30 Aug 2013 14:21:16 -0500 Subject: [PATCH] namei: Ignore misplaced files The namei salvaging/ListViceInodes code currently ignores files where we cannot derive an inode number from a given filename. However, if a file is a valid inode filename, but is in the wrong directory, we still record it. This can cause the salvager to abort, since it assumes inode e.g. 12345 is present, but when it tries to open 12345, namei translates the inode to a nonexistant path, and we bail out. It is unknown how a namei directory structure can reach this state, but try to handle it. To be on the safe side, just ignore the files, and log a message about them. That way, if the files are required for reconstructing the volume or contain important data, they are still available if needed. And if they contain incorrect or old data, we don't screw up the volume by trying to use them. Thanks to Sabah S. Salih for reporting a related issue. Reviewed-on: http://gerrit.openafs.org/10214 Reviewed-by: D Brashear Tested-by: BuildBot (cherry picked from commit 1096582bde6156bb469f2e397cbc40d13a8f2822) Change-Id: I9252877fbfe01328ac4a8692ebe28a86913b9713 Reviewed-on: http://gerrit.openafs.org/10810 Reviewed-by: D Brashear Reviewed-by: Andrew Deason Reviewed-by: Stephan Wiesand Tested-by: BuildBot --- src/vol/namei_ops.c | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/vol/namei_ops.c b/src/vol/namei_ops.c index 6e79a5cee..de6dc889a 100644 --- a/src/vol/namei_ops.c +++ b/src/vol/namei_ops.c @@ -1770,7 +1770,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, - unsigned int volid); + IHandle_t *myIH); static int DecodeVolumeName(char *name, unsigned int *vid); static int namei_ListAFSSubDirs(IHandle_t * dirIH, int (*write_fun) (FILE *, @@ -2042,7 +2042,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; } @@ -2133,7 +2133,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; } @@ -2791,7 +2791,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; @@ -2801,6 +2801,7 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info, char stmp[16]; FdHandle_t linkHandle; char dirl; + VolumeId volid = myIH->ih_vid; afs_snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name); @@ -2867,12 +2868,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 status; + struct afs_stat checkstatus; int parm, tag; lb64_string_t check; + VolumeId volid = myIH->ih_vid; + IHandle_t tmpih; + namei_t nameiname; afs_snprintf(fpath, sizeof(fpath), "%s" OS_DIRSEP "%s", dpath, name); @@ -2887,6 +2892,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); @@ -3075,7 +3110,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); -- 2.39.5