1 /* $NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $ */
4 * Copyright (c) 2007, 2008 Reinoud Zandijk
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $");
35 #if defined(_KERNEL_OPT)
36 #include "opt_compat_netbsd.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sysctl.h>
42 #include <sys/namei.h>
44 #include <sys/kernel.h>
45 #include <sys/vnode.h>
46 #include <miscfs/genfs/genfs_node.h>
47 #include <sys/mount.h>
50 #include <sys/device.h>
51 #include <sys/disklabel.h>
52 #include <sys/ioctl.h>
53 #include <sys/malloc.h>
54 #include <sys/dirent.h>
57 #include <sys/kauth.h>
58 #include <sys/kthread.h>
59 #include <dev/clock_subr.h>
61 #include <fs/udf/ecma167-udf.h>
62 #include <fs/udf/udf_mount.h>
66 #include "udf_bswap.h"
69 #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
71 /* --------------------------------------------------------------------- */
74 udf_fixup_fid_block(uint8_t *blob
, int lb_size
,
75 int rfix_pos
, int max_rfix_pos
, uint32_t lb_num
)
77 struct fileid_desc
*fid
;
81 /* needs to be word aligned */
82 KASSERT(rfix_pos
% 4 == 0);
84 /* first resync with the FID stream !!! */
86 while (rfix_pos
+ sizeof(struct desc_tag
) <= max_rfix_pos
) {
87 fid_pos
= blob
+ rfix_pos
;
88 fid
= (struct fileid_desc
*) fid_pos
;
89 if (udf_rw16(fid
->tag
.id
) == TAGID_FID
) {
90 if (udf_check_tag((union dscrptr
*) fid
) == 0)
95 /* try next location; can only be 4 bytes aligned */
99 /* walk over the fids */
100 fid_pos
= blob
+ rfix_pos
;
101 while (rfix_pos
+ sizeof(struct desc_tag
) <= max_rfix_pos
) {
102 fid
= (struct fileid_desc
*) fid_pos
;
103 if (udf_rw16(fid
->tag
.id
) != TAGID_FID
) {
104 /* end of FID stream; end of directory or currupted */
108 /* update sector number and recalculate checkum */
109 fid
->tag
.tag_loc
= udf_rw32(lb_num
);
110 udf_validate_tag_sum((union dscrptr
*) fid
);
112 /* if the FID crosses the memory, we're done! */
113 if (rfix_pos
+ UDF_FID_SIZE
>= max_rfix_pos
)
116 fid_len
= udf_fidsize(fid
);
124 udf_fixup_internal_extattr(uint8_t *blob
, uint32_t lb_num
)
126 struct desc_tag
*tag
;
127 struct file_entry
*fe
;
128 struct extfile_entry
*efe
;
129 struct extattrhdr_desc
*eahdr
;
132 /* get information from fe/efe */
133 tag
= (struct desc_tag
*) blob
;
134 switch (udf_rw16(tag
->id
)) {
136 fe
= (struct file_entry
*) blob
;
137 l_ea
= udf_rw32(fe
->l_ea
);
138 eahdr
= (struct extattrhdr_desc
*) fe
->data
;
140 case TAGID_EXTFENTRY
:
141 efe
= (struct extfile_entry
*) blob
;
142 l_ea
= udf_rw32(efe
->l_ea
);
143 eahdr
= (struct extattrhdr_desc
*) efe
->data
;
145 case TAGID_INDIRECTENTRY
:
146 case TAGID_ALLOCEXTENT
:
147 case TAGID_EXTATTR_HDR
:
150 panic("%s: passed bad tag\n", __func__
);
153 /* something recorded here? (why am i called?) */
158 /* check extended attribute tag */
159 /* TODO XXX what to do when we encounter an error here? */
160 error
= udf_check_tag(eahdr
);
162 return; /* for now */
163 if (udf_rw16(eahdr
->tag
.id
) != TAGID_EXTATTR_HDR
)
164 return; /* for now */
165 error
= udf_check_tag_payload(eahdr
, sizeof(struct extattrhdr_desc
));
167 return; /* for now */
170 DPRINTF(EXTATTR
, ("node fixup: found %d bytes of extended attributes\n",
173 /* fixup eahdr tag */
174 eahdr
->tag
.tag_loc
= udf_rw32(lb_num
);
175 udf_validate_tag_and_crc_sums((union dscrptr
*) eahdr
);
180 udf_fixup_node_internals(struct udf_mount
*ump
, uint8_t *blob
, int udf_c_type
)
182 struct desc_tag
*tag
, *sbm_tag
;
183 struct file_entry
*fe
;
184 struct extfile_entry
*efe
;
185 struct alloc_ext_entry
*ext
;
186 uint32_t lb_size
, lb_num
;
187 uint32_t intern_pos
, max_intern_pos
;
188 int icbflags
, addr_type
, file_type
, intern
, has_fids
, has_sbm
, l_ea
;
190 lb_size
= udf_rw32(ump
->logical_vol
->lb_size
);
191 /* if its not a node we're done */
192 if (udf_c_type
!= UDF_C_NODE
)
195 /* NOTE this could also be done in write_internal */
196 /* start of a descriptor */
202 max_intern_pos
= intern_pos
= lb_num
= 0; /* shut up gcc! */
204 tag
= (struct desc_tag
*) blob
;
205 switch (udf_rw16(tag
->id
)) {
207 fe
= (struct file_entry
*) tag
;
208 l_ea
= udf_rw32(fe
->l_ea
);
209 icbflags
= udf_rw16(fe
->icbtag
.flags
);
210 addr_type
= (icbflags
& UDF_ICB_TAG_FLAGS_ALLOC_MASK
);
211 file_type
= fe
->icbtag
.file_type
;
212 intern
= (addr_type
== UDF_ICB_INTERN_ALLOC
);
213 intern_pos
= UDF_FENTRY_SIZE
+ l_ea
;
214 max_intern_pos
= intern_pos
+ udf_rw64(fe
->inf_len
);
215 lb_num
= udf_rw32(fe
->tag
.tag_loc
);
217 case TAGID_EXTFENTRY
:
218 efe
= (struct extfile_entry
*) tag
;
219 l_ea
= udf_rw32(efe
->l_ea
);
220 icbflags
= udf_rw16(efe
->icbtag
.flags
);
221 addr_type
= (icbflags
& UDF_ICB_TAG_FLAGS_ALLOC_MASK
);
222 file_type
= efe
->icbtag
.file_type
;
223 intern
= (addr_type
== UDF_ICB_INTERN_ALLOC
);
224 intern_pos
= UDF_EXTFENTRY_SIZE
+ l_ea
;
225 max_intern_pos
= intern_pos
+ udf_rw64(efe
->inf_len
);
226 lb_num
= udf_rw32(efe
->tag
.tag_loc
);
228 case TAGID_INDIRECTENTRY
:
229 case TAGID_EXTATTR_HDR
:
231 case TAGID_ALLOCEXTENT
:
232 /* force crclen to 8 for UDF version < 2.01 */
233 ext
= (struct alloc_ext_entry
*) tag
;
234 if (udf_rw16(ump
->logvol_info
->min_udf_readver
) <= 0x200)
235 ext
->tag
.desc_crc_len
= udf_rw16(8);
238 panic("%s: passed bad tag\n", __func__
);
242 /* determine what to fix if its internally recorded */
244 has_fids
= (file_type
== UDF_ICB_FILETYPE_DIRECTORY
) ||
245 (file_type
== UDF_ICB_FILETYPE_STREAMDIR
);
246 has_sbm
= (file_type
== UDF_ICB_FILETYPE_META_BITMAP
);
249 /* fixup internal extended attributes if present */
251 udf_fixup_internal_extattr(blob
, lb_num
);
253 /* fixup fids lb numbers */
255 udf_fixup_fid_block(blob
, lb_size
, intern_pos
,
256 max_intern_pos
, lb_num
);
258 /* fixup space bitmap descriptor */
260 sbm_tag
= (struct desc_tag
*) (blob
+ intern_pos
);
261 sbm_tag
->tag_loc
= tag
->tag_loc
;
262 udf_validate_tag_and_crc_sums((uint8_t *) sbm_tag
);
265 udf_validate_tag_and_crc_sums(blob
);
268 /* --------------------------------------------------------------------- */
271 * Set of generic descriptor readers and writers and their helper functions.
272 * Descriptors inside `logical space' i.e. inside logically mapped partitions
273 * can never be longer than one logical sector.
275 * NOTE that these functions *can* be used by the sheduler backends to read
276 * node descriptors too.
278 * For reading, the size of allocated piece is returned in multiple of sector
279 * size due to udf_calc_udf_malloc_size().
283 /* SYNC reading of n blocks from specified sector */
285 udf_read_phys_sectors(struct udf_mount
*ump
, int what
, void *blob
,
286 uint32_t start
, uint32_t sectors
)
288 struct buf
*buf
, *nestbuf
;
290 off_t lblkno
, rblkno
;
291 int sector_size
= ump
->discinfo
.sector_size
;
292 int blks
= sector_size
/ DEV_BSIZE
;
296 DPRINTF(READ
, ("udf_intbreadn() : sectors = %d, sector_size = %d\n",
297 sectors
, sector_size
));
298 buf
= getiobuf(ump
->devvp
, true);
299 buf
->b_flags
= B_READ
;
300 buf
->b_cflags
= BC_BUSY
; /* needed? */
301 buf
->b_iodone
= NULL
;
303 buf
->b_bcount
= sectors
* sector_size
;
304 buf
->b_resid
= buf
->b_bcount
;
305 buf
->b_bufsize
= buf
->b_bcount
;
306 buf
->b_private
= NULL
; /* not needed yet */
307 BIO_SETPRIO(buf
, BPRIO_DEFAULT
);
308 buf
->b_lblkno
= buf
->b_blkno
= buf
->b_rawblkno
= start
* blks
;
315 while ((sectors
> 0) && (error
== 0)) {
316 piece
= MIN(MAXPHYS
/sector_size
, sectors
);
317 DPRINTF(READ
, ("read in %d + %d\n", (uint32_t) rblkno
, piece
));
319 nestbuf
= getiobuf(NULL
, true);
320 nestiobuf_setup(buf
, nestbuf
, buf_offset
, piece
* sector_size
);
321 /* nestbuf is B_ASYNC */
323 /* identify this nestbuf */
324 nestbuf
->b_lblkno
= lblkno
;
326 /* CD shedules on raw blkno */
327 nestbuf
->b_blkno
= rblkno
* blks
;
328 nestbuf
->b_proc
= NULL
;
329 nestbuf
->b_rawblkno
= rblkno
* blks
;
330 nestbuf
->b_udf_c_type
= what
;
332 udf_discstrat_queuebuf(ump
, nestbuf
);
336 buf_offset
+= piece
* sector_size
;
339 error
= biowait(buf
);
346 /* synchronous generic descriptor read */
348 udf_read_phys_dscr(struct udf_mount
*ump
, uint32_t sector
,
349 struct malloc_type
*mtype
, union dscrptr
**dstp
)
351 union dscrptr
*dst
, *new_dst
;
353 int sectors
, dscrlen
;
354 int i
, error
, sector_size
;
356 sector_size
= ump
->discinfo
.sector_size
;
359 dscrlen
= sector_size
;
361 /* read initial piece */
362 dst
= malloc(sector_size
, mtype
, M_WAITOK
);
363 error
= udf_read_phys_sectors(ump
, UDF_C_DSCR
, dst
, sector
, 1);
364 DPRINTFIF(DESCRIPTOR
, error
, ("read error (%d)\n", error
));
367 /* check if its a valid tag */
368 error
= udf_check_tag(dst
);
370 /* check if its an empty block */
371 pos
= (uint8_t *) dst
;
372 for (i
= 0; i
< sector_size
; i
++, pos
++) {
375 if (i
== sector_size
) {
376 /* return no error but with no dscrptr */
377 /* dispose first block */
382 /* calculate descriptor size */
383 dscrlen
= udf_tagsize(dst
, sector_size
);
385 DPRINTFIF(DESCRIPTOR
, error
, ("bad tag checksum\n"));
387 if (!error
&& (dscrlen
> sector_size
)) {
388 DPRINTF(DESCRIPTOR
, ("multi block descriptor read\n"));
390 * Read the rest of descriptor. Since it is only used at mount
391 * time its overdone to define and use a specific udf_intbreadn
395 new_dst
= realloc(dst
, dscrlen
, mtype
, M_WAITOK
);
396 if (new_dst
== NULL
) {
402 sectors
= (dscrlen
+ sector_size
-1) / sector_size
;
403 DPRINTF(DESCRIPTOR
, ("dscrlen = %d (%d blk)\n", dscrlen
, sectors
));
405 pos
= (uint8_t *) dst
+ sector_size
;
406 error
= udf_read_phys_sectors(ump
, UDF_C_DSCR
, pos
,
407 sector
+ 1, sectors
-1);
409 DPRINTFIF(DESCRIPTOR
, error
, ("read error on multi (%d)\n",
413 error
= udf_check_tag_payload(dst
, dscrlen
);
414 DPRINTFIF(DESCRIPTOR
, error
, ("bad payload check sum\n"));
427 udf_write_phys_buf(struct udf_mount
*ump
, int what
, struct buf
*buf
)
431 off_t lblkno
, rblkno
;
432 int sector_size
= ump
->discinfo
.sector_size
;
433 int blks
= sector_size
/ DEV_BSIZE
;
438 sectors
= buf
->b_bcount
/ sector_size
;
439 DPRINTF(WRITE
, ("udf_intbwriten() : sectors = %d, sector_size = %d\n",
440 sectors
, sector_size
));
442 /* don't forget to increase pending count for the bwrite itself */
443 /* panic("NO WRITING\n"); */
445 mutex_enter(buf
->b_vp
->v_interlock
);
446 buf
->b_vp
->v_numoutput
++;
447 mutex_exit(buf
->b_vp
->v_interlock
);
452 rblkno
= buf
->b_blkno
/ blks
;
454 while ((sectors
> 0) && (error
== 0)) {
455 piece
= MIN(MAXPHYS
/sector_size
, sectors
);
456 DPRINTF(WRITE
, ("write out %d + %d\n",
457 (uint32_t) rblkno
, piece
));
459 nestbuf
= getiobuf(NULL
, true);
460 nestiobuf_setup(buf
, nestbuf
, buf_offset
, piece
* sector_size
);
461 /* nestbuf is B_ASYNC */
463 /* identify this nestbuf */
464 nestbuf
->b_lblkno
= lblkno
;
466 /* CD shedules on raw blkno */
467 nestbuf
->b_blkno
= rblkno
* blks
;
468 nestbuf
->b_proc
= NULL
;
469 nestbuf
->b_rawblkno
= rblkno
* blks
;
470 nestbuf
->b_udf_c_type
= what
;
472 udf_discstrat_queuebuf(ump
, nestbuf
);
476 buf_offset
+= piece
* sector_size
;
482 /* SYNC writing of n blocks from specified sector */
484 udf_write_phys_sectors(struct udf_mount
*ump
, int what
, void *blob
,
485 uint32_t start
, uint32_t sectors
)
489 int sector_size
= ump
->discinfo
.sector_size
;
490 int blks
= sector_size
/ DEV_BSIZE
;
493 /* get transfer buffer */
495 buf
= getiobuf(vp
, true);
496 buf
->b_flags
= B_WRITE
;
497 buf
->b_cflags
= BC_BUSY
; /* needed? */
498 buf
->b_iodone
= NULL
;
500 buf
->b_bcount
= sectors
* sector_size
;
501 buf
->b_resid
= buf
->b_bcount
;
502 buf
->b_bufsize
= buf
->b_bcount
;
503 buf
->b_private
= NULL
; /* not needed yet */
504 BIO_SETPRIO(buf
, BPRIO_DEFAULT
);
505 buf
->b_lblkno
= buf
->b_blkno
= buf
->b_rawblkno
= start
* blks
;
508 /* do the write, wait and return error */
509 udf_write_phys_buf(ump
, what
, buf
);
510 error
= biowait(buf
);
517 /* synchronous generic descriptor write */
519 udf_write_phys_dscr_sync(struct udf_mount
*ump
, struct udf_node
*udf_node
, int what
,
520 union dscrptr
*dscr
, uint32_t sector
, uint32_t logsector
)
524 int sector_size
= ump
->discinfo
.sector_size
;
525 int blks
= sector_size
/ DEV_BSIZE
;
529 /* set sector number in the descriptor and validate */
530 dscr
->tag
.tag_loc
= udf_rw32(logsector
);
531 udf_validate_tag_and_crc_sums(dscr
);
533 /* calculate descriptor size */
534 dscrlen
= udf_tagsize(dscr
, sector_size
);
536 /* get transfer buffer */
537 vp
= udf_node
? udf_node
->vnode
: ump
->devvp
;
538 buf
= getiobuf(vp
, true);
539 buf
->b_flags
= B_WRITE
;
540 buf
->b_cflags
= BC_BUSY
; /* needed? */
541 buf
->b_iodone
= NULL
;
542 buf
->b_data
= (void *) dscr
;
543 buf
->b_bcount
= dscrlen
;
544 buf
->b_resid
= buf
->b_bcount
;
545 buf
->b_bufsize
= buf
->b_bcount
;
546 buf
->b_private
= NULL
; /* not needed yet */
547 BIO_SETPRIO(buf
, BPRIO_DEFAULT
);
548 buf
->b_lblkno
= buf
->b_blkno
= buf
->b_rawblkno
= sector
* blks
;
551 /* do the write, wait and return error */
552 udf_write_phys_buf(ump
, what
, buf
);
553 error
= biowait(buf
);
560 /* asynchronous generic descriptor write */
562 udf_write_phys_dscr_async(struct udf_mount
*ump
, struct udf_node
*udf_node
,
563 int what
, union dscrptr
*dscr
,
564 uint32_t sector
, uint32_t logsector
,
565 void (*dscrwr_callback
)(struct buf
*))
570 int sector_size
= ump
->discinfo
.sector_size
;
571 int blks
= sector_size
/ DEV_BSIZE
;
573 KASSERT(dscrwr_callback
);
574 DPRINTF(NODE
, ("udf_write_phys_dscr_async() called\n"));
576 /* set sector number in the descriptor and validate */
577 dscr
->tag
.tag_loc
= udf_rw32(logsector
);
578 udf_validate_tag_and_crc_sums(dscr
);
580 /* calculate descriptor size */
581 dscrlen
= udf_tagsize(dscr
, sector_size
);
583 /* get transfer buffer */
584 vp
= udf_node
? udf_node
->vnode
: ump
->devvp
;
585 buf
= getiobuf(vp
, true);
586 buf
->b_flags
= B_WRITE
; // | B_ASYNC;
587 buf
->b_cflags
= BC_BUSY
;
588 buf
->b_iodone
= dscrwr_callback
;
590 buf
->b_bcount
= dscrlen
;
591 buf
->b_resid
= buf
->b_bcount
;
592 buf
->b_bufsize
= buf
->b_bcount
;
593 buf
->b_private
= NULL
; /* not needed yet */
594 BIO_SETPRIO(buf
, BPRIO_DEFAULT
);
595 buf
->b_lblkno
= buf
->b_blkno
= buf
->b_rawblkno
= sector
* blks
;
598 /* do the write and return no error */
599 udf_write_phys_buf(ump
, what
, buf
);
603 /* --------------------------------------------------------------------- */
605 /* disc strategy dispatchers */
608 udf_create_logvol_dscr(struct udf_mount
*ump
, struct udf_node
*udf_node
, struct long_ad
*icb
,
609 union dscrptr
**dscrptr
)
611 struct udf_strategy
*strategy
= ump
->strategy
;
612 struct udf_strat_args args
;
617 args
.udf_node
= udf_node
;
621 error
= (strategy
->create_logvol_dscr
)(&args
);
622 *dscrptr
= args
.dscr
;
629 udf_free_logvol_dscr(struct udf_mount
*ump
, struct long_ad
*icb
,
632 struct udf_strategy
*strategy
= ump
->strategy
;
633 struct udf_strat_args args
;
640 (strategy
->free_logvol_dscr
)(&args
);
645 udf_read_logvol_dscr(struct udf_mount
*ump
, struct long_ad
*icb
,
646 union dscrptr
**dscrptr
)
648 struct udf_strategy
*strategy
= ump
->strategy
;
649 struct udf_strat_args args
;
657 error
= (strategy
->read_logvol_dscr
)(&args
);
658 *dscrptr
= args
.dscr
;
665 udf_write_logvol_dscr(struct udf_node
*udf_node
, union dscrptr
*dscr
,
666 struct long_ad
*icb
, int waitfor
)
668 struct udf_strategy
*strategy
= udf_node
->ump
->strategy
;
669 struct udf_strat_args args
;
673 args
.ump
= udf_node
->ump
;
674 args
.udf_node
= udf_node
;
677 args
.waitfor
= waitfor
;
679 error
= (strategy
->write_logvol_dscr
)(&args
);
685 udf_discstrat_queuebuf(struct udf_mount
*ump
, struct buf
*nestbuf
)
687 struct udf_strategy
*strategy
= ump
->strategy
;
688 struct udf_strat_args args
;
692 args
.nestbuf
= nestbuf
;
694 (strategy
->queuebuf
)(&args
);
699 udf_discstrat_init(struct udf_mount
*ump
)
701 struct udf_strategy
*strategy
= ump
->strategy
;
702 struct udf_strat_args args
;
706 (strategy
->discstrat_init
)(&args
);
710 void udf_discstrat_finish(struct udf_mount
*ump
)
712 struct udf_strategy
*strategy
= ump
->strategy
;
713 struct udf_strat_args args
;
715 /* strategy might not have been set, so ignore if not set */
718 (strategy
->discstrat_finish
)(&args
);
722 /* --------------------------------------------------------------------- */