[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
resuming writing an unclosed DVD+R track
From: |
Ivan Shmakov |
Subject: |
resuming writing an unclosed DVD+R track |
Date: |
Thu, 26 May 2022 02:48:15 +0000 |
Recently I’ve stumbled on my DVD drive failing mid-write of
a pre-mastered image. Noticing that the track is marked as
‘incomplete’ in the dvd+rw-mediainfo(1) output, and recalling
that one of the features of the DVD+R specification was
‘easy resumption’ of recording, I did a Web search and
followed the suggestion to use the -use-the-force-luke=seek=
option to growisofs(1) to resume writing from [1].
[1] http://unix.stackexchange.com/questions/313840/
The resulting medium had only two 2 KiB sectors (= 4 KiB)
worth of lost data. Given the availability of some 13 MiB
of spare space left on disk, I’ve copied there (as a second
track / session) a range of blocks covering the lost
portion, as well as a chunk from the beginning for a good
measure, and an ad-hoc text file describing the resulting
layout of the medium.
A cursory reading of xorriso(1) / xorrecord(1) didn’t reveal
any feature similar to the growisofs(1) seek= option, though,
making me wonder if there’s one?
A more detailed description follows.
(Portability note: I’ve relied on GNU/Linux tools and facilities
below, such as losetup(8), GNU Awk, as well as the -i, -n
options that seem to be specific to GNU cmp.)
The growisofs(1) invocation failed as follows:
+ /usr/bin/time -- growisofs -dvd-compat -speed=6 -Z /dev/sr0=IMAGE.FILE
Executing 'builtin_dd if=IMAGE.FILE of=/dev/sr0 obs=32k seek=0'
/dev/sr0: "Current Write Speed" is 6.1x1352KBps.
0/4700372992 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/4700372992 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/4700372992 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
4980736/4700372992 ( 0.1%) @1.1x, remaining 251:23 RBU 100.0% UBU -12.5%
32768000/4700372992 ( 0.7%) @6.0x, remaining 45:06 RBU 100.0% UBU 98.4%
…
484114432/4700372992 (10.3%) @5.4x, remaining 11:01 RBU 100.0% UBU 98.4%
:-[ WRITE@LBA=39b60h failed with SK=4h/LOGICAL UNIT COMMUNICATION TIMEOUT]:
Input/output error
:-( write failed: Input/output error
/dev/sr0: flushing cache
:-[ FLUSH CACHE failed with SK=2h/LOGICAL UNIT NOT READY, LONG WRITE IN
PROGRESS]: Resource temporarily unavailable
:-[ SYNCHRONOUS FLUSH CACHE failed with SK=2h/LOGICAL UNIT NOT READY, LONG
WRITE IN PROGRESS]: Resource temporarily unavailable
Command exited with non-zero status 11
0.06user 2.31system 1:16.95elapsed 3%CPU (0avgtext+0avgdata 35836maxresident)k
1011312inputs+0outputs (1major+8500minor)pagefaults 0swaps
(The reasons are as yet unidentified, but it wasn’t the only
failure to happen that day; OTOH, I don’t recall such failures
over the prior months of somewhat occasional use of the drive.)
As par the course, I’ve checked the dvd+rw-mediainfo(1) output
immediately; notable portion being:
READ DISC INFORMATION:
Disc status: appendable
Number of Sessions: 1
State of Last Session: incomplete
"Next" Track: 1
Number of Tracks: 1
READ TRACK INFORMATION[#1]:
Track State: invisible
Track Start Address: 0*2KB
Next Writable Address: 236400*2KB
Free Blocks: 2058704*2KB
Track Size: 2295104*2KB
ROM Compatibility LBA: 270336
READ CAPACITY: 0*2048=0
(Note that LBA 236400 refers to the DVD sector immediately
after 0x39b60 = 236384 reported in the error above.)
In order to write the latter part of IMAGE.FILE (i. e., to skip
the already written part), I’ve created a loop device (no idea
if growisofs(1) can be instructed to do such a skip by itself):
# chacl u::rw-,g::rw-,u:USERNAME:r--,m::rw-,o::--- \
"$(losetup --show --find -r -o $((236400*2))K -- IMAGE.FILE)"
Then resumed writing (below, 14775 = 236400 / 16, for there’re
16 2 KiB blocks in one 32 KiB DVD sector):
+ /usr/bin/time -- growisofs -dvd-compat -speed=6
-use-the-force-luke=seek=236400 -Z /dev/sr0=/dev/loopXX
Executing 'builtin_dd if=/dev/loopXX of=/dev/sr0 obs=32k seek=14775'
/dev/sr0: "Current Write Speed" is 6.1x1352KBps.
:-? resuming track#1 from LBA#236400
503087104/4700372992 ( 0.4%) @4.0x, remaining 22:09 RBU 100.0% UBU -12.5%
528515072/4700372992 ( 1.1%) @5.5x, remaining 14:06 RBU 100.0% UBU 97.7%
…
4616650752/4700372992 (98.0%) @6.0x, remaining 0:10 RBU 100.0% UBU 98.4%
4644405248/4700372992 (98.7%) @6.0x, remaining 0:06 RBU 100.0% UBU 98.4%
4672159744/4700372992 (99.3%) @6.0x, remaining 0:03 RBU 29.8% UBU 98.4%
builtin_dd: 2049808*2KB out @ average 5.9x1352KBps
/dev/sr0: flushing cache
/dev/sr0: closing track
/dev/sr0: closing session
/dev/sr0: reloading tray
0.60user 18.40system 9:03.17elapsed 3%CPU (0avgtext+0avgdata 35768maxresident)k
8199680inputs+0outputs (4major+8609minor)pagefaults 0swaps
The relevant portion of the dvd+rw-mediainfo(1) output after
the write:
READ DISC INFORMATION:
Disc status: appendable
Number of Sessions: 2
State of Last Session: empty
"Next" Track: 2
Number of Tracks: 2
READ TRACK INFORMATION[#1]:
Track State: invisible
Track Start Address: 0*2KB
Free Blocks: 0*2KB
Track Size: 2286208*2KB
ROM Compatibility LBA: 270336
READ TRACK INFORMATION[#2]:
Track State: blank
Track Start Address: 2288256*2KB
Next Writable Address: 2288256*2KB
Free Blocks: 6848*2KB
Track Size: 6848*2KB
ROM Compatibility LBA: 270336
FABRICATED TOC:
Track#1 : 17@0
Track#AA : 17@2286208
Multi-session Info: #1@0
READ CAPACITY: 2286208*2048=4682153984
Comparing the data on disk with the source IMAGE.FILE
revealed two sectors of lost data:
$ (/usr/bin/time ionice -c 3 -- cmp -l -- IMAGE.FILE /dev/sr0 \
| gawk '! /^ *[0-9]+\s/ { print $0; next; }
(c = rshift($1, 11)) > 1 + b { print a "-" b; a = c; }
1 { b = c; } END { print a "-" b; }') \
2>&1 | less -UF
Command exited with non-zero status 1
1.84user 17.56system 5:31.47elapsed 5%CPU (0avgtext+0avgdata 1740maxresident)k
18289736inputs+0outputs (2major+165minor)pagefaults 0swaps
-
236398-236400
$
(The expression above should’ve been c = rshift(-1 + $1, 11),
for cmp -l counts bytes from 1, not 0; and the output should’ve
been 236398-236399.)
At this point I’ve decided to make use of the space still
available and prepared the following map file:
## block-size: 2048
0 236398 payload+0
236398 2 bad
236400 2049808 payload+236400
## copies
2288256 384 payload+236160
2288640 6400 payload+0
2295040 64 map
The file to write was created with shell code along the lines of:
#!/bin/sh
## Ivan Shmakov, 2022
## License: CC0-1.0
set -e
set -C -u
## Hard-coded arguments:
set -- IMAGE.FILE MAP.FILE -2288256
f=${1} ; m=${2} ; adj=${3:-0} ; shift 3
exec < "$m" > "$(mktemp -- /tmp/pieces.XXXXXXXX)"
if test -t 1 ; then
printf %s\\n "Refusing to write to a tty" >&2
## .
exit 1
fi
pos=0
sed -e 1,/copies/d | while read -r -- o z src ; do
o=$((adj + o))
test "$o" = "$pos" \
|| exit 1
case "$src" in
(payload+*) dd bs=2048 count="$z" skip="${src##*+}" < "$f" ;;
(map)
sz=$(wc -c < "$m")
sz=$((1 + (-1 + sz) / 2048))
rz=${z}
while test "$rz" -gt "$sz" ; do
rz=$((rz - sz))
dd bs=2048 count="$sz" conv=sync < "$m"
done
dd bs=2048 count="$rz" conv=sync < "$m"
;;
esac
pos=$((z + o))
done
(Note that MAP.FILE is written over and over to fill up the
allocated 64 2 KiB sectors.)
The resulting pieces.-file was checked to contain the
intended data, in particular:
$ /usr/bin/time -- sh -Cexuc '
cmp -n $((384 * 2))K -i $((236160 * 2))K:$(((2288256 - 2288256) * 2))K -- "$@"
cmp -n $((6400 * 2))K -i $((0 * 2))K:$(((2288640 - 2288256) * 2))K -- "$@"
' dummy.sh IMAGE.FILE /tmp/pieces.Vm3nMUcT
Then written to the disk:
+ /usr/bin/time -- growisofs -dvd-compat -speed=6 -overburn
-use-the-force-luke=seek=2288256 -Z /dev/sr0=/tmp/pieces.Vm3nMUcT
Executing 'builtin_dd if=/tmp/pieces.Vm3nMUcT of=/dev/sr0 obs=32k seek=143016'
/dev/sr0: "Current Write Speed" is 6.1x1352KBps.
4695326720/4700372992 (64.0%) @1.9x, remaining 0:03 RBU 15.0% UBU 37.5%
builtin_dd: 6848*2KB out @ average 1.4x1352KBps
/dev/sr0: flushing cache
/dev/sr0: closing track
:-[ CLOSE TRACK failed with SK=5h/INVALID FIELD IN CDB]: Input/output error
/dev/sr0: closing session
/dev/sr0: reloading tray
0.00user 0.12system 0:24.28elapsed 0%CPU (0avgtext+0avgdata 35752maxresident)k
0inputs+0outputs (0major+8603minor)pagefaults 0swaps
Bringing the dvd+rw-mediainfo(1) output to the following
state. (The CLOSE TRACK failure above being apparently benign.)
READ DISC INFORMATION:
Disc status: complete
Number of Sessions: 2
State of Last Session: complete
Number of Tracks: 2
READ TRACK INFORMATION[#1]:
…
READ TRACK INFORMATION[#2]:
Track State: invisible
Track Start Address: 2288256*2KB
Free Blocks: 0*2KB
Track Size: 6848*2KB
ROM Compatibility LBA: 270336
FABRICATED TOC:
Track#1 : 17@0
Track#2 : 17@2288256
Track#AA : 17@2295104
Multi-session Info: #2@2288256
READ CAPACITY: 2295104*2048=4700372992
Finally, I’ve used dmsetup(1) to create a block device that
maps the copy of the data from the tail of the medium over
the miswritten portion:
bash# dmsetup create -- sr0.fixed \
<(printf %s\\n "0 944640 linear /dev/sr0 0" \
"944640 1536 linear /dev/sr0 9153024" \
"946176 8198656 linear /dev/sr0 946176")
Comparing the resulting device to the original IMAGE.FILE
revealed no differences.
--
FSF associate member #7257 http://am-1.org/~ivan/
- resuming writing an unclosed DVD+R track,
Ivan Shmakov <=