Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/udf Rework VAT searching on recordable media. It is n...



details:   https://anonhg.NetBSD.org/src/rev/f3374bf1b0cf
branches:  trunk
changeset: 345153:f3374bf1b0cf
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Tue May 10 15:23:39 2016 +0000

description:
Rework VAT searching on recordable media. It is now a lot more resilliant to
errors and it allows for VAT searching on crashed writeouts.

While here, make sure the node pointer is always initialised in
udf_get_node().

diffstat:

 sys/fs/udf/udf.h      |    5 +-
 sys/fs/udf/udf_subr.c |  124 ++++++++++++++++++++++++++++++++++---------------
 2 files changed, 88 insertions(+), 41 deletions(-)

diffs (210 lines):

diff -r 477d562d24f1 -r f3374bf1b0cf sys/fs/udf/udf.h
--- a/sys/fs/udf/udf.h  Tue May 10 15:14:30 2016 +0000
+++ b/sys/fs/udf/udf.h  Tue May 10 15:23:39 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf.h,v 1.50 2015/08/24 08:31:56 hannken Exp $ */
+/* $NetBSD: udf.h,v 1.51 2016/05/10 15:23:39 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -417,11 +417,12 @@
 #define        IN_SYNCED               0x0200  /* node is being used by sync */
 #define        IN_CALLBACK_ULK         0x0400  /* node will be unlocked by callback */
 #define        IN_NODE_REBUILD         0x0800  /* node is rebuild */
+#define IN_NO_DELETE           0x1000  /* node is not to be deleted */
 
 
 #define IN_FLAGBITS \
        "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFY\5IN_MODIFIED" \
        "\6IN_ACCESSED\7IN_RENAME\10IN_DELETED\11IN_LOCKED\12IN_SYNCED" \
-       "\13IN_CALLBACK_ULK\14IN_NODE_REBUILD"
+       "\13IN_CALLBACK_ULK\14IN_NODE_REBUILD\15IN_NO_DELETE"
 
 #endif /* !_FS_UDF_UDF_H_ */
diff -r 477d562d24f1 -r f3374bf1b0cf sys/fs/udf/udf_subr.c
--- a/sys/fs/udf/udf_subr.c     Tue May 10 15:14:30 2016 +0000
+++ b/sys/fs/udf/udf_subr.c     Tue May 10 15:23:39 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.136 2016/01/27 00:06:49 reinoud Exp $ */
+/* $NetBSD: udf_subr.c,v 1.137 2016/05/10 15:23:39 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.136 2016/01/27 00:06:49 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.137 2016/05/10 15:23:39 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -946,7 +946,7 @@
 
        /* VATs are only recorded on sequential media, but initialise */
        ump->first_possible_vat_location = track_start + 2;
-       ump->last_possible_vat_location  = track_end + last_track.packet_size;
+       ump->last_possible_vat_location  = track_end;
 
        return ok;
 }
@@ -2995,6 +2995,10 @@
        ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
        ump->logvol_integrity->time           = *mtime;
 
+       /* if we're updating, free old allocated space */
+       if (ump->vat_table)
+               free(ump->vat_table, M_UDFVOLD);
+
        ump->vat_table_len = vat_length;
        ump->vat_table_alloc_len = vat_table_alloc_len;
        ump->vat_table   = vat_table;
@@ -3017,49 +3021,70 @@
 static int
 udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping)
 {
-       struct udf_node *vat_node;
+       struct udf_node *vat_node, *accepted_vat_node;
        struct long_ad   icb_loc;
-       uint32_t early_vat_loc, vat_loc;
+       uint32_t early_vat_loc, late_vat_loc, vat_loc;
        int error;
 
        /* mapping info not needed */
        mapping = mapping;
 
-       vat_loc = ump->last_possible_vat_location;
-       early_vat_loc = vat_loc - 256;  /* 8 blocks of 32 sectors */
-
-       DPRINTF(VOLUMES, ("1) last possible %d, early_vat_loc %d \n",
-               vat_loc, early_vat_loc));
-       early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location);
-
-       DPRINTF(VOLUMES, ("2) last possible %d, early_vat_loc %d \n",
-               vat_loc, early_vat_loc));
-
-       /* start looking from the end of the range */
+       DPRINTF(VOLUMES, ("Searching VAT\n"));
+       
+       /*
+        * Start reading forward in blocks from the first possible vat
+        * location. If not found in this block, start again a bit before
+        * until we get a hit.
+        */
+       late_vat_loc = ump->last_possible_vat_location;
+       early_vat_loc = MAX(late_vat_loc - 64, ump->first_possible_vat_location);
+ 
+       DPRINTF(VOLUMES, ("\tfull range %d to %d\n", early_vat_loc, late_vat_loc));
+       accepted_vat_node = NULL;
        do {
-               DPRINTF(VOLUMES, ("Checking for VAT at sector %d\n", vat_loc));
-               icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART);
-               icb_loc.loc.lb_num   = udf_rw32(vat_loc);
-
-               error = udf_get_node(ump, &icb_loc, &vat_node);
-               if (!error) {
-                       error = udf_check_for_vat(vat_node);
-                       DPRINTFIF(VOLUMES, !error,
-                               ("VAT accepted at %d\n", vat_loc));
-                       if (!error)
-                               break;
-               }
-               if (vat_node) {
-                       vput(vat_node->vnode);
-                       vat_node = NULL;
-               }
-               vat_loc--;      /* walk backwards */
-       } while (vat_loc >= early_vat_loc);
-
-       /* keep our VAT node around */
-       if (vat_node) {
-               UDF_SET_SYSTEMFILE(vat_node->vnode);
-               ump->vat_node = vat_node;
+               vat_loc = early_vat_loc;
+               DPRINTF(VOLUMES, ("\tchecking range %d to %d\n",
+                       early_vat_loc, late_vat_loc));
+               do {
+                       DPRINTF(VOLUMES, ("\t\tChecking for VAT at sector %d\n",
+                               vat_loc));
+                       icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART);
+                       icb_loc.loc.lb_num   = udf_rw32(vat_loc);
+
+                       error = udf_get_node(ump, &icb_loc, &vat_node);
+                       if (!error) {
+                               error = udf_check_for_vat(vat_node);
+                               vat_node->i_flags = 0;  /* reset access */
+                       }
+                       if (!error) {
+                               DPRINTFIF(VOLUMES, !error,
+                                       ("VAT candidate accepted at %d\n",
+                                        vat_loc));
+                               if (accepted_vat_node)
+                                       vput(accepted_vat_node->vnode);
+                               accepted_vat_node = vat_node;
+                               accepted_vat_node->i_flags |= IN_NO_DELETE;
+                               vat_node = NULL;
+                       }
+                       if (vat_node)
+                               vput(vat_node->vnode);
+                       vat_loc++;      /* walk forward */
+               } while (vat_loc < late_vat_loc);
+               if (accepted_vat_node)
+                       break;
+
+               early_vat_loc = MAX(early_vat_loc - 64, ump->first_possible_vat_location);
+               late_vat_loc = MIN(early_vat_loc + 64, ump->last_possible_vat_location);
+       } while (late_vat_loc > ump->first_possible_vat_location);
+
+       /* keep our last accepted VAT node around */
+       if (accepted_vat_node) {
+               /* revert no delete flag again to avoid potential side effects */
+               accepted_vat_node->i_flags &= ~IN_NO_DELETE;
+
+               UDF_SET_SYSTEMFILE(accepted_vat_node->vnode);
+               ump->vat_node = accepted_vat_node;
+               return 0;
        }
 
        return error;
@@ -3674,6 +3699,22 @@
 
                /* determine data and metadata tracks again */
                error = udf_search_writing_tracks(ump);
+
+               if (ump->lvclose & UDF_WRITE_VAT) {
+                       /*
+                        * we writeout the VAT to get a self-sustained session
+                        * for fsck
+                        */
+                       DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n"));
+
+                       /* write out the VAT data and all its descriptors */
+                       DPRINTF(VOLUMES, ("writeout vat_node\n"));
+                       udf_writeout_vat(ump);
+                       vflushbuf(ump->vat_node->vnode, 1 /* sync */);
+
+                       (void) VOP_FSYNC(ump->vat_node->vnode,
+                                       FSCRED, FSYNC_WAIT, 0, 0);
+               }
        }
 
        /* mark it open */
@@ -5562,6 +5603,8 @@
        int error;
        struct vnode *vp;
 
+       *udf_noderes = NULL;
+
        error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc,
            sizeof(node_icb_loc->loc), &vp);
        if (error)
@@ -5927,6 +5970,9 @@
        struct long_ad *loc;
        int extnr, lvint, dummy;
 
+       if (udf_node->i_flags & IN_NO_DELETE)
+               return;
+
        /* paranoia check on integrity; should be open!; we could panic */
        lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type);
        if (lvint == UDF_INTEGRITY_CLOSED)



Home | Main Index | Thread Index | Old Index