Module Name:    src
Committed By:   martin
Date:           Fri Jul 27 10:46:45 UTC 2018

Modified Files:
        src/sys/fs/udf [netbsd-7]: udf_subr.c

Log Message:
Pull up following revision(s) (requested by reinoud in ticket #1622):

        sys/fs/udf/udf_subr.c: revision 1.142

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


To generate a diff of this commit:
cvs rdiff -u -r1.125.2.1 -r1.125.2.2 src/sys/fs/udf/udf_subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/udf/udf_subr.c
diff -u src/sys/fs/udf/udf_subr.c:1.125.2.1 src/sys/fs/udf/udf_subr.c:1.125.2.2
--- src/sys/fs/udf/udf_subr.c:1.125.2.1	Mon Feb 16 21:25:35 2015
+++ src/sys/fs/udf/udf_subr.c	Fri Jul 27 10:46:45 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.125.2.1 2015/02/16 21:25:35 martin Exp $ */
+/* $NetBSD: udf_subr.c,v 1.125.2.2 2018/07/27 10:46:45 martin 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.125.2.1 2015/02/16 21:25:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.125.2.2 2018/07/27 10:46:45 martin Exp $");
 #endif /* not lint */
 
 
@@ -1235,7 +1235,7 @@ udf_retrieve_lvint(struct udf_mount *ump
 
 		/* 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) {
@@ -1281,7 +1281,7 @@ udf_loose_lvint_history(struct udf_mount
 	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;
 
@@ -1289,18 +1289,29 @@ udf_loose_lvint_history(struct udf_mount
 
 	/* 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);
+		sumext += extlen;
 	}
-	losing = MIN(minext, UDF_LVINT_LOSSAGE);
-	/* no sense wiping all */
-	if (losing == minext)
-		losing--;
+
+	/* 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));
 
@@ -1437,7 +1448,6 @@ udf_writeout_lvint(struct udf_mount *ump
 
 	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)) {
@@ -1465,11 +1475,20 @@ again:
 	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 */
@@ -1673,6 +1692,14 @@ udf_write_physical_partition_spacetables
 		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);
@@ -1699,6 +1726,14 @@ udf_write_physical_partition_spacetables
 		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);

Reply via email to