rpc-rename-avoid-loop-20031201
authorDerrick Brashear <shadow@dementia.org>
Mon, 1 Dec 2003 20:16:02 +0000 (20:16 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 1 Dec 2003 20:16:02 +0000 (20:16 +0000)
enumerated solution (n vnodes cannot yield n+1 loop passes) suggested by
jhutz@cmu.edu. avoid looping forever on a corrupt parent.

src/viced/afsfileprocs.c

index 7da4edf..5171305 100644 (file)
@@ -3949,7 +3949,13 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
      * directory structure.  This is to prevent removing a subtree alltogether
      */
     if ((oldvptr != newvptr) && (fileptr->disk.type == vDirectory)) {
-       for (testnode = newvptr->disk.parent; testnode != 0;) {
+        afs_int32 forpass = 0, vnum = 0, top = 0;
+       for (testnode = newvptr->disk.parent; testnode != 0; forpass++) {
+           if (testnode > vnum) vnum = testnode;
+           if (forpass > vnum) {
+               errorCode = FSERR_ELOOP;
+               goto Bad_Rename;
+           }
            if (testnode == oldvptr->vnodeNumber) {
                testnode = oldvptr->disk.parent;
                continue;
@@ -3963,10 +3969,16 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
                errorCode = FSERR_ELOOP;
                goto Bad_Rename;
            }
+           if (testnode == 1) top = 1;
            testvptr = VGetVnode(&errorCode, volptr, testnode, READ_LOCK);
            assert(errorCode == 0);
            testnode = testvptr->disk.parent;
            VPutVnode(&errorCode, testvptr);
+           if ((top == 1) && (testnode != 0)) {
+               VTakeOffline(volptr);
+               errorCode = EIO;
+               goto Bad_Rename;
+           }
            assert(errorCode == 0);
        }
     }