[OpenAFS] Re: help, salvaged volume won't come back online, is it corrupt? [trimmed log]

Adam Megacz megacz@cs.berkeley.edu
Wed, 13 Sep 2006 20:39:03 -0700


John Koyle <jkoyle@koyle.org> writes:
>     ./afsdump_extract volume_name dest/ -v -i          <- dump the
> data to dest/
>     ./afsdump_scan -Pd -v volume > FileList.txt        <- Create a
> flat file with vnode/filename mappings for finding things from the
> above dump.

I ultimately patched together a solution using this and the code below
(which I'm attaching mainly for posterity via the mailing list
archives).  Apparently if you lose the root vnode, attach-orphans
won't give you anything back.

  - a


Grok.java:
______________________________________________________________________________
// It is my deep and sincere hope that nobody will ever
// need to use this program.
//
// Adam Megacz / public domain
//
// to use:
//   $ javac Grok.java
//   $ mkdir in
//   $ afsdump_extract dumpfile -v -i in
//   $ afsdump_scan -Pdvi | java -cp . Grok
//
// if you're lucky, stuff winds up in ./out/
//
// the top two levels of the directory hierarchy are the
// vnode number of the "missing" parent of each orphan
// and the vnode number of the orphan itself.  This way
// orphaned siblings wind up together.
//
// the code below is not pretty at all.

import java.util.*;
import java.io.*;

public class Grok {

    public static void main(String[] ss) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        while(true) {
            if (s==null) break;
            if (!s.startsWith("* VNODE  ")) throw new Error("expected *: " + s);
            s = s.substring(9);
            int a = Integer.parseInt(s.substring(0, s.indexOf('/')));
            int b = Integer.parseInt(s.substring(s.indexOf('/')+1, s.indexOf(' ')));
            VNode v = new VNode(a);
            while (s != null &&
                   !s.startsWith(" Parent:"))
                s = br.readLine();
            if (s!=null && s.startsWith(" Parent:"))
                v.setParent(Integer.parseInt(s.substring(8).trim()));
            while (s != null &&
                   !s.startsWith("  ========== ==========  =============================="))
                s = br.readLine();
            if (s==null) break;
            s = br.readLine();
            System.out.println("directory " + a+":"+b);
            while (s != null && !s.startsWith("*")) {
                int x = Integer.parseInt(s.substring(0, 12).trim());
                int y = Integer.parseInt(s.substring(12, 12+11).trim());
                String z = s.substring(25).trim();
                v.add(x,z);
                System.out.println("  "+x+":"+y+" = " + z);
                s = br.readLine();
            }
        }
        System.out.println("..........................................................");
        files = new File("out").list();
        for(VNode v : vnodes.values()) {
            if (!(v.parent == -1 || vnodes.get(v.parent)==null)) continue;
            System.out.println(v);
            new File("out/"+v.parent).mkdirs();
            v.creat("out/"+v.parent+"/"+v.a);
        }
    }


    public static HashMap<Integer,VNode> vnodes = new HashMap<Integer,VNode>();
    public static String[] files;

    public static class VNode {
        public int a;
        public int parent = -1;
        public HashMap<String,Integer> children = new HashMap<String,Integer>();
        public void creat(String path) throws IOException {
            new File(path).mkdirs();
            for(String c : children.keySet()) {
                VNode v = vnodes.get(children.get(c));
                if (v!=null) v.creat(path+"/"+c);
                else {
                    boolean good = false;
                    for(String s : files) {
                        if (s.indexOf(':')!=-1 &&
                            Integer.parseInt(s.substring(0,s.indexOf(':')))==children.get(c)) {
                            new File("in/"+s).renameTo(new File(path+"/"+c));
                            good = true;
                            break;
                        }
                    }
                    if (!good)
                        System.out.println("bad: " + children.get(c));
                }
            }
        }
        public void setParent(int a) {
            if (parent != -1 && parent != a)
                throw new Error("overwrite " + parent + " => " + a);
            parent = a;
        }
        public VNode(int a) {
            this.a = a;
            if (vnodes.get(a)!=null) throw new Error("dupe " + a);
            vnodes.put(a, this);
        }
        public void add(int a, String z) {
            if (z.equals(".")) return;
            if (z.equals("..")) {
                if (parent != -1 && parent != a)
                    throw new Error("overwrite " + parent + " => " + a);
                parent = a;
            } else
                children.put(z, a);
        }
        public String toString() {
            StringBuffer ret = new StringBuffer();
            ret.append("VNode " + a+" [parent="+parent+"]\n");
            for(String s: children.keySet())
                ret.append("  " + s+"\n");
            return ret.toString();
        }
    }

}