Source-Changes-HG archive

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

[src/trunk]: src/sys/fs/udf Enhance logical volume integrity descriptor handl...



details:   https://anonhg.NetBSD.org/src/rev/4235182b8c69
branches:  trunk
changeset: 834047:4235182b8c69
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Wed Jul 25 11:09:22 2018 +0000

description:
Enhance logical volume integrity descriptor handling and provide
bug-compatibility for Linux mkudffs 1.3 images.

diffstat:

 sys/fs/udf/udf_subr.c |  61 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 48 insertions(+), 13 deletions(-)

diffs (133 lines):

diff -r 2e6dc36d4f41 -r 4235182b8c69 sys/fs/udf/udf_subr.c
--- a/sys/fs/udf/udf_subr.c     Wed Jul 25 07:55:44 2018 +0000
+++ b/sys/fs/udf/udf_subr.c     Wed Jul 25 11:09:22 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.141 2018/06/06 01:49:09 maya Exp $ */
+/* $NetBSD: udf_subr.c,v 1.142 2018/07/25 11:09:22 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.141 2018/06/06 01:49:09 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.142 2018/07/25 11:09:22 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -1233,7 +1233,7 @@
 
                /* are we linking to a new piece? */
                if (dscr && lvint->next_extent.len) {
-                       len    = udf_rw32(lvint->next_extent.len);
+                       len   = udf_rw32(lvint->next_extent.len);
                        lbnum = udf_rw32(lvint->next_extent.loc);
 
                        if (trace_len >= UDF_LVDINT_SEGMENTS-1) {
@@ -1279,7 +1279,7 @@
        uint32_t out_ext, out_wpos, out_len;
        uint32_t lb_num;
        uint32_t len, start;
-       int ext, minext, extlen, cnt, cpy_len, dscr_type;
+       int ext, sumext, extlen, cnt, cpy_len, dscr_type;
        int losing;
        int error;
 
@@ -1287,18 +1287,29 @@
 
        /* search smallest extent */
        trace = &ump->lvint_trace[0];
-       minext = trace->end - trace->start;
+       sumext = trace->end - trace->start;
        for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) {
                trace = &ump->lvint_trace[ext];
                extlen = trace->end - trace->start;
                if (extlen == 0)
                        break;
-               minext = MIN(minext, extlen);
-       }
-       losing = MIN(minext, UDF_LVINT_LOSSAGE);
-       /* no sense wiping all */
-       if (losing == minext)
-               losing--;
+               sumext += extlen;
+       }
+
+       /* just one element? its not legal but be bug compatible */
+       if (sumext == 1) {
+               /* overwrite the only entry */
+               DPRINTF(VOLUMES, ("\tLinux bugcompat overwriting sole entry\n"));
+               trace = &ump->lvint_trace[0];
+               trace->wpos = 0;
+               return 0;
+       }
+
+       losing = MIN(sumext, UDF_LVINT_LOSSAGE);
+
+       /* no sense wiping too much */
+       if (sumext == UDF_LVINT_LOSSAGE)
+               losing = UDF_LVINT_LOSSAGE/2;
 
        DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing));
 
@@ -1435,7 +1446,6 @@
 
        DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n"));
 
-again:
        /* get free space in last chunk */
        trace = ump->lvint_trace;
        while (trace->wpos > (trace->end - trace->start)) {
@@ -1463,11 +1473,20 @@
        if (space < 1) {
                if (lvflag & UDF_APPENDONLY_LVINT)
                        return EROFS;
+
                /* loose history by re-writing extents */
                error = udf_loose_lvint_history(ump);
                if (error)
                        return error;
-               goto again;
+
+               trace = ump->lvint_trace;
+               while (trace->wpos > (trace->end - trace->start))
+                       trace++;
+               space = (trace->end - trace->start) - trace->wpos;
+               DPRINTF(VOLUMES, ("new try: write start = %d, end = %d, "
+                                 "pos = %d, wpos = %d, "
+                                 "space = %d\n", trace->start, trace->end,
+                                 trace->pos, trace->wpos, space));
        }
 
        /* update our integrity descriptor to identify us and timestamp it */
@@ -1671,6 +1690,14 @@
                DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n",
                        lb_num + ptov));
                dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part];
+
+               /* force a sane minimum for descriptors CRC length */
+               /* see UDF 2.3.1.2 and 2.3.8.1 */
+               KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
+               if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
+                       dscr->sbd.tag.desc_crc_len = udf_rw16(8);
+
+               /* write out space bitmap */
                error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                                (union dscrptr *) dscr,
                                ptov + lb_num, lb_num);
@@ -1697,6 +1724,14 @@
                DPRINTF(VOLUMES, ("Write freed space bitmap %d\n",
                        lb_num + ptov));
                dscr = (union dscrptr *) ump->part_freed_dscr[phys_part];
+
+               /* force a sane minimum for descriptors CRC length */
+               /* see UDF 2.3.1.2 and 2.3.8.1 */
+               KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
+               if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
+                       dscr->sbd.tag.desc_crc_len = udf_rw16(8);
+
+               /* write out space bitmap */
                error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                                (union dscrptr *) dscr,
                                ptov + lb_num, lb_num);



Home | Main Index | Thread Index | Old Index