Hello all.

Resending now, after unlock, a not-so-big patch implementing recursive
"nodump" flag handling in dump(8), for the case the flag is being set on
a directory. Tested successfully for many months on i386. Patch is
modelled after FreeBSD's dump(8) code.

-- 
  WBR,
  Vadim Zhukov

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?


Index: traverse.c
===================================================================
RCS file: /cvs/src/sbin/dump/traverse.c,v
retrieving revision 1.24
diff -u -p -r1.24 traverse.c
--- traverse.c  27 Oct 2009 23:59:32 -0000      1.24
+++ traverse.c  16 Feb 2012 11:02:26 -0000
@@ -60,9 +60,9 @@ union dinode {
 #define        HASDUMPEDFILE   0x1
 #define        HASSUBDIRS      0x2
 
-static int dirindir(ino_t ino, daddr64_t blkno, int level, off_t 
*size);
-static void dmpindir(ino_t ino, daddr64_t blk, int level, off_t *size);
-static int searchdir(ino_t ino, daddr64_t blkno, long size, off_t 
filesize);
+static int dirindir(ino_t, daddr64_t, int, off_t *, off_t *, int);
+static void dmpindir(ino_t, daddr64_t, int, off_t *);
+static int searchdir(ino_t, daddr64_t, long, off_t, off_t *, int);
 
 /*
  * This is an estimation of the number of TP_BSIZE blocks in the file.
@@ -103,18 +103,9 @@ blockest(union dinode *dp)
        return (blkest + 1);
 }
 
-/* Auxiliary macro to pick up files changed since previous dump. */
-#define        CHANGEDSINCE(dp, t) \
-       (DIP(dp, di_mtime) >= (t) || DIP(dp, di_ctime) >= (t))
-
-/* The WANTTODUMP macro decides whether a file should be dumped. */
-#ifdef UF_NODUMP
-#define        WANTTODUMP(dp) \
-       (CHANGEDSINCE(dp, spcl.c_ddate) && \
-        (nonodump || (DIP(dp, di_flags) & UF_NODUMP) != UF_NODUMP))
-#else
-#define        WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate)
-#endif
+/* true if "nodump" flag has no effect here, i.e. dumping allowed */
+#define CHECKNODUMP(dp) \
+       (nonodump || (DIP((dp), di_flags) & UF_NODUMP) != UF_NODUMP)
 
 /*
  * Determine if given inode should be dumped
@@ -131,7 +122,7 @@ mapfileino(ino_t ino, off_t *tapesize, i
        SETINO(ino, usedinomap);
        if (mode == IFDIR)
                SETINO(ino, dumpdirmap);
-       if (WANTTODUMP(dp)) {
+       if (CHECKNODUMP(dp) && DIP(dp, di_mtime) >= spcl.c_ddate) {
                SETINO(ino, dumpinomap);
                if (mode != IFREG && mode != IFDIR && mode != IFLNK)
                        *tapesize += 1;
@@ -139,8 +130,11 @@ mapfileino(ino_t ino, off_t *tapesize, i
                        *tapesize += blockest(dp);
                return;
        }
-       if (mode == IFDIR)
+       if (mode == IFDIR) {
+               if (!CHECKNODUMP(dp))
+                       CLRINO(ino, usedinomap);
                *dirskipped = 1;
+       }
 }
 
 void
@@ -307,7 +301,7 @@ int
 mapdirs(ino_t maxino, off_t *tapesize)
 {
        union dinode *dp;
-       int i, isdir;
+       int i, isdir, nodump;
        char *map;
        ino_t ino;
        union dinode di;
@@ -320,7 +314,15 @@ mapdirs(ino_t maxino, off_t *tapesize)
                        isdir = *map++;
                else
                        isdir >>= 1;
-               if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap))
+                /*
+                * If a directory has been removed from usedinomap, it
+                * either has the nodump flag set, or has inherited
+                * it.  Although a directory can't be in dumpinomap if
+                * it isn't in usedinomap, we have to go through it to
+                * propagate the nodump flag.
+                */
+               nodump = !nonodump && !TSTINO(ino, usedinomap);
+               if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap) && !nodump)
                        continue;
                dp = getino(ino, &i);
                /*
@@ -335,7 +337,7 @@ mapdirs(ino_t maxino, off_t *tapesize)
                        if (DIP(&di, di_db[i]) != 0)
                                ret |= searchdir(ino, DIP(&di, di_db[i]),
                                    sblksize(sblock, DIP(dp, di_size), i),
-                                   filesize);
+                                   filesize, tapesize, nodump);
                        if (ret & HASDUMPEDFILE)
                                filesize = 0;
                        else
@@ -344,7 +346,8 @@ mapdirs(ino_t maxino, off_t *tapesize)
                for (i = 0; filesize > 0 && i < NIADDR; i++) {
                        if (DIP(&di, di_ib[i]) == 0)
                                continue;
-                       ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize);
+                       ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize,
+                           tapesize, nodump);
                }
                if (ret & HASDUMPEDFILE) {
                        SETINO(ino, dumpinomap);
@@ -352,7 +355,11 @@ mapdirs(ino_t maxino, off_t *tapesize)
                        change = 1;
                        continue;
                }
-               if ((ret & HASSUBDIRS) == 0) {
+                if (nodump) {
+                        if (ret & HASSUBDIRS)
+                                change = 1;     /* subdirs inherit 
nodump */
+                        CLRINO(ino, dumpdirmap);
+                } else if ((ret & HASSUBDIRS) == 0) {
                        if (!TSTINO(ino, dumpinomap)) {
                                CLRINO(ino, dumpdirmap);
                                change = 1;
@@ -368,7 +375,8 @@ mapdirs(ino_t maxino, off_t *tapesize)
  * require the directory to be dumped.
  */
 static int
-dirindir(ino_t ino, daddr64_t blkno, int ind_level, off_t *filesize)
+dirindir(ino_t ino, daddr64_t blkno, int ind_level, off_t *filesize,
+    off_t *tapesize, int nodump)
 {
        int ret = 0;
        int i;
@@ -383,7 +391,7 @@ dirindir(ino_t ino, daddr64_t blkno, int
                                blkno = ((int64_t *)idblk)[i];
                        if (blkno != 0)
                                ret |= searchdir(ino, blkno, sblock->fs_bsize,
-                                       *filesize);
+                                       *filesize, tapesize, nodump);
                        if (ret & HASDUMPEDFILE)
                                *filesize = 0;
                        else
@@ -398,7 +406,8 @@ dirindir(ino_t ino, daddr64_t blkno, int
                else
                        blkno = ((int64_t *)idblk)[i];
                if (blkno != 0)
-                       ret |= dirindir(ino, blkno, ind_level, filesize);
+                       ret |= dirindir(ino, blkno, ind_level, filesize,
+                           tapesize, nodump);
        }
        return (ret);
 }
@@ -409,12 +418,14 @@ dirindir(ino_t ino, daddr64_t blkno, int
  * contains any subdirectories.
  */
 static int
-searchdir(ino_t ino, daddr64_t blkno, long size, off_t filesize)
+searchdir(ino_t ino, daddr64_t blkno, long size, off_t filesize,
+    off_t *tapesize, int nodump)
 {
        struct direct *dp;
+       union dinode *ip;
        long loc;
        static caddr_t dblk;
-       int ret = 0;
+       int mode, ret = 0;
 
        if (dblk == NULL && (dblk = malloc(sblock->fs_bsize)) == NULL)
                quit("searchdir: cannot allocate indirect memory.\n");
@@ -436,15 +447,32 @@ searchdir(ino_t ino, daddr64_t blkno, lo
                        if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
                                continue;
                }
-               if (TSTINO(dp->d_ino, dumpinomap)) {
-                       ret |= HASDUMPEDFILE;
-                       if (ret & HASSUBDIRS)
-                               break;
-               }
-               if (TSTINO(dp->d_ino, dumpdirmap)) {
-                       ret |= HASSUBDIRS;
-                       if (ret & HASDUMPEDFILE)
-                               break;
+               if (nodump) {
+                        ip = getino(dp->d_ino, &mode);
+                        if (TSTINO(dp->d_ino, dumpinomap)) {
+                                CLRINO(dp->d_ino, dumpinomap);
+                                *tapesize -= blockest(ip);
+                        }
+                        /*
+                         * Add back to dumpdirmap and remove from 
usedinomap
+                         * to propagate nodump.
+                         */
+                        if (mode == IFDIR) {
+                                SETINO(dp->d_ino, dumpdirmap);
+                                CLRINO(dp->d_ino, usedinomap);
+                                ret |= HASSUBDIRS;
+                        }
+               } else {
+                       if (TSTINO(dp->d_ino, dumpinomap)) {
+                               ret |= HASDUMPEDFILE;
+                               if (ret & HASSUBDIRS)
+                                       break;
+                       }
+                       if (TSTINO(dp->d_ino, dumpdirmap)) {
+                               ret |= HASSUBDIRS;
+                               if (ret & HASDUMPEDFILE)
+                                       break;
+                       }
                }
        }
        return (ret);

Reply via email to