Home | History | Annotate | Line # | Download | only in udf
udf_readwrite.c revision 1.6
      1  1.6  reinoud /* $NetBSD: udf_readwrite.c,v 1.6 2008/07/28 19:41:13 reinoud Exp $ */
      2  1.1  reinoud 
      3  1.1  reinoud /*
      4  1.1  reinoud  * Copyright (c) 2007, 2008 Reinoud Zandijk
      5  1.1  reinoud  * All rights reserved.
      6  1.1  reinoud  *
      7  1.1  reinoud  * Redistribution and use in source and binary forms, with or without
      8  1.1  reinoud  * modification, are permitted provided that the following conditions
      9  1.1  reinoud  * are met:
     10  1.1  reinoud  * 1. Redistributions of source code must retain the above copyright
     11  1.1  reinoud  *    notice, this list of conditions and the following disclaimer.
     12  1.1  reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  reinoud  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  reinoud  *    documentation and/or other materials provided with the distribution.
     15  1.1  reinoud  *
     16  1.1  reinoud  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.1  reinoud  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  1.1  reinoud  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  1.1  reinoud  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  1.1  reinoud  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  1.1  reinoud  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  1.1  reinoud  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  1.1  reinoud  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  1.1  reinoud  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  1.1  reinoud  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  1.1  reinoud  *
     27  1.1  reinoud  */
     28  1.1  reinoud 
     29  1.1  reinoud #include <sys/cdefs.h>
     30  1.1  reinoud #ifndef lint
     31  1.6  reinoud __KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.6 2008/07/28 19:41:13 reinoud Exp $");
     32  1.1  reinoud #endif /* not lint */
     33  1.1  reinoud 
     34  1.1  reinoud 
     35  1.1  reinoud #if defined(_KERNEL_OPT)
     36  1.1  reinoud #include "opt_quota.h"
     37  1.1  reinoud #include "opt_compat_netbsd.h"
     38  1.1  reinoud #endif
     39  1.1  reinoud 
     40  1.1  reinoud #include <sys/param.h>
     41  1.1  reinoud #include <sys/systm.h>
     42  1.1  reinoud #include <sys/sysctl.h>
     43  1.1  reinoud #include <sys/namei.h>
     44  1.1  reinoud #include <sys/proc.h>
     45  1.1  reinoud #include <sys/kernel.h>
     46  1.1  reinoud #include <sys/vnode.h>
     47  1.1  reinoud #include <miscfs/genfs/genfs_node.h>
     48  1.1  reinoud #include <sys/mount.h>
     49  1.1  reinoud #include <sys/buf.h>
     50  1.1  reinoud #include <sys/file.h>
     51  1.1  reinoud #include <sys/device.h>
     52  1.1  reinoud #include <sys/disklabel.h>
     53  1.1  reinoud #include <sys/ioctl.h>
     54  1.1  reinoud #include <sys/malloc.h>
     55  1.1  reinoud #include <sys/dirent.h>
     56  1.1  reinoud #include <sys/stat.h>
     57  1.1  reinoud #include <sys/conf.h>
     58  1.1  reinoud #include <sys/kauth.h>
     59  1.1  reinoud #include <sys/kthread.h>
     60  1.1  reinoud #include <dev/clock_subr.h>
     61  1.1  reinoud 
     62  1.1  reinoud #include <fs/udf/ecma167-udf.h>
     63  1.1  reinoud #include <fs/udf/udf_mount.h>
     64  1.1  reinoud 
     65  1.1  reinoud #if defined(_KERNEL_OPT)
     66  1.1  reinoud #include "opt_udf.h"
     67  1.1  reinoud #endif
     68  1.1  reinoud 
     69  1.1  reinoud #include "udf.h"
     70  1.1  reinoud #include "udf_subr.h"
     71  1.1  reinoud #include "udf_bswap.h"
     72  1.1  reinoud 
     73  1.1  reinoud 
     74  1.1  reinoud #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
     75  1.1  reinoud 
     76  1.1  reinoud /* --------------------------------------------------------------------- */
     77  1.1  reinoud 
     78  1.1  reinoud void
     79  1.1  reinoud udf_fixup_fid_block(uint8_t *blob, int lb_size,
     80  1.1  reinoud 	int rfix_pos, int max_rfix_pos, uint32_t lb_num)
     81  1.1  reinoud {
     82  1.1  reinoud 	struct fileid_desc *fid;
     83  1.1  reinoud 	uint8_t *fid_pos;
     84  1.1  reinoud 	int fid_len, found;
     85  1.1  reinoud 
     86  1.1  reinoud 	/* needs to be word aligned */
     87  1.1  reinoud 	KASSERT(rfix_pos % 4 == 0);
     88  1.1  reinoud 
     89  1.1  reinoud 	/* first resync with the FID stream !!! */
     90  1.1  reinoud 	found = 0;
     91  1.1  reinoud 	while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
     92  1.1  reinoud 		fid_pos = blob + rfix_pos;
     93  1.1  reinoud 		fid = (struct fileid_desc *) fid_pos;
     94  1.1  reinoud 		if (udf_rw16(fid->tag.id) == TAGID_FID) {
     95  1.1  reinoud 			if (udf_check_tag((union dscrptr *) fid) == 0)
     96  1.1  reinoud 				found = 1;
     97  1.1  reinoud 		}
     98  1.1  reinoud 		if (found)
     99  1.1  reinoud 			break;
    100  1.1  reinoud 		/* try next location; can only be 4 bytes aligned */
    101  1.1  reinoud 		rfix_pos += 4;
    102  1.1  reinoud 	}
    103  1.1  reinoud 
    104  1.1  reinoud 	/* walk over the fids */
    105  1.1  reinoud 	fid_pos = blob + rfix_pos;
    106  1.1  reinoud 	while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
    107  1.1  reinoud 		fid = (struct fileid_desc *) fid_pos;
    108  1.1  reinoud 		if (udf_rw16(fid->tag.id) != TAGID_FID) {
    109  1.1  reinoud 			/* end of FID stream; end of directory or currupted */
    110  1.1  reinoud 			break;
    111  1.1  reinoud 		}
    112  1.1  reinoud 
    113  1.1  reinoud 		/* update sector number and recalculate checkum */
    114  1.1  reinoud 		fid->tag.tag_loc = udf_rw32(lb_num);
    115  1.1  reinoud 		udf_validate_tag_sum((union dscrptr *) fid);
    116  1.1  reinoud 
    117  1.1  reinoud 		/* if the FID crosses the memory, we're done! */
    118  1.1  reinoud 		if (rfix_pos + UDF_FID_SIZE >= max_rfix_pos)
    119  1.1  reinoud 			break;
    120  1.1  reinoud 
    121  1.1  reinoud 		fid_len = udf_fidsize(fid);
    122  1.1  reinoud 		fid_pos  += fid_len;
    123  1.1  reinoud 		rfix_pos += fid_len;
    124  1.1  reinoud 	}
    125  1.1  reinoud }
    126  1.1  reinoud 
    127  1.1  reinoud 
    128  1.1  reinoud void
    129  1.1  reinoud udf_fixup_internal_extattr(uint8_t *blob, uint32_t lb_num)
    130  1.1  reinoud {
    131  1.1  reinoud 	struct desc_tag        *tag;
    132  1.1  reinoud 	struct file_entry      *fe;
    133  1.1  reinoud 	struct extfile_entry   *efe;
    134  1.1  reinoud 	struct extattrhdr_desc *eahdr;
    135  1.2  reinoud 	int l_ea;
    136  1.1  reinoud 
    137  1.1  reinoud 	/* get information from fe/efe */
    138  1.1  reinoud 	tag = (struct desc_tag *) blob;
    139  1.1  reinoud 	switch (udf_rw16(tag->id)) {
    140  1.1  reinoud 	case TAGID_FENTRY :
    141  1.1  reinoud 		fe = (struct file_entry *) blob;
    142  1.1  reinoud 		l_ea  = udf_rw32(fe->l_ea);
    143  1.1  reinoud 		eahdr = (struct extattrhdr_desc *) fe->data;
    144  1.1  reinoud 		break;
    145  1.1  reinoud 	case TAGID_EXTFENTRY :
    146  1.1  reinoud 		efe = (struct extfile_entry *) blob;
    147  1.1  reinoud 		l_ea  = udf_rw32(efe->l_ea);
    148  1.1  reinoud 		eahdr = (struct extattrhdr_desc *) efe->data;
    149  1.1  reinoud 		break;
    150  1.1  reinoud 	case TAGID_INDIRECTENTRY :
    151  1.1  reinoud 	case TAGID_ALLOCEXTENT :
    152  1.1  reinoud 	case TAGID_EXTATTR_HDR :
    153  1.1  reinoud 		return;
    154  1.1  reinoud 	default:
    155  1.3    perry 		panic("%s: passed bad tag\n", __func__);
    156  1.1  reinoud 	}
    157  1.1  reinoud 
    158  1.1  reinoud 	/* something recorded here? (why am i called?) */
    159  1.1  reinoud 	if (l_ea == 0)
    160  1.1  reinoud 		return;
    161  1.1  reinoud 
    162  1.2  reinoud #if 0
    163  1.1  reinoud 	/* check extended attribute tag */
    164  1.1  reinoud 	/* TODO XXX what to do when we encounter an error here? */
    165  1.1  reinoud 	error = udf_check_tag(eahdr);
    166  1.1  reinoud 	if (error)
    167  1.1  reinoud 		return;	/* for now */
    168  1.1  reinoud 	if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
    169  1.1  reinoud 		return;	/* for now */
    170  1.1  reinoud 	error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
    171  1.1  reinoud 	if (error)
    172  1.1  reinoud 		return; /* for now */
    173  1.2  reinoud #endif
    174  1.1  reinoud 
    175  1.1  reinoud 	DPRINTF(EXTATTR, ("node fixup: found %d bytes of extended attributes\n",
    176  1.1  reinoud 		l_ea));
    177  1.1  reinoud 
    178  1.1  reinoud 	/* fixup eahdr tag */
    179  1.1  reinoud 	eahdr->tag.tag_loc = udf_rw32(lb_num);
    180  1.2  reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *) eahdr);
    181  1.1  reinoud }
    182  1.1  reinoud 
    183  1.1  reinoud 
    184  1.1  reinoud void
    185  1.1  reinoud udf_fixup_node_internals(struct udf_mount *ump, uint8_t *blob, int udf_c_type)
    186  1.1  reinoud {
    187  1.6  reinoud 	struct desc_tag *tag, *sbm_tag;
    188  1.1  reinoud 	struct file_entry *fe;
    189  1.1  reinoud 	struct extfile_entry *efe;
    190  1.5  reinoud 	struct alloc_ext_entry *ext;
    191  1.1  reinoud 	uint32_t lb_size, lb_num;
    192  1.1  reinoud 	uint32_t rfid_pos, max_rfid_pos;
    193  1.6  reinoud 	int icbflags, addr_type, file_type, has_fids, has_sbm, l_ea;
    194  1.1  reinoud 
    195  1.1  reinoud 	lb_size = udf_rw32(ump->logical_vol->lb_size);
    196  1.1  reinoud 	/* if its not a node we're done */
    197  1.1  reinoud 	if (udf_c_type != UDF_C_NODE)
    198  1.1  reinoud 		return;
    199  1.1  reinoud 
    200  1.1  reinoud 	/* NOTE this could also be done in write_internal */
    201  1.1  reinoud 	/* start of a descriptor */
    202  1.5  reinoud 	l_ea     = 0;
    203  1.1  reinoud 	has_fids = 0;
    204  1.6  reinoud 	has_sbm  = 0;
    205  1.1  reinoud 	max_rfid_pos = rfid_pos = lb_num = 0;	/* shut up gcc! */
    206  1.1  reinoud 
    207  1.1  reinoud 	tag = (struct desc_tag *) blob;
    208  1.1  reinoud 	switch (udf_rw16(tag->id)) {
    209  1.1  reinoud 	case TAGID_FENTRY :
    210  1.1  reinoud 		fe = (struct file_entry *) tag;
    211  1.1  reinoud 		l_ea = udf_rw32(fe->l_ea);
    212  1.1  reinoud 		icbflags  = udf_rw16(fe->icbtag.flags);
    213  1.1  reinoud 		addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
    214  1.6  reinoud 		file_type = fe->icbtag.file_type;
    215  1.1  reinoud 		has_fids  = (addr_type == UDF_ICB_INTERN_ALLOC);
    216  1.6  reinoud 		has_sbm   = (file_type == UDF_ICB_FILETYPE_META_BITMAP);
    217  1.1  reinoud 		rfid_pos  = UDF_FENTRY_SIZE + l_ea;
    218  1.1  reinoud 		max_rfid_pos = rfid_pos + udf_rw64(fe->inf_len);
    219  1.1  reinoud 		lb_num = udf_rw32(fe->tag.tag_loc);
    220  1.1  reinoud 		break;
    221  1.1  reinoud 	case TAGID_EXTFENTRY :
    222  1.1  reinoud 		efe = (struct extfile_entry *) tag;
    223  1.1  reinoud 		l_ea = udf_rw32(efe->l_ea);
    224  1.1  reinoud 		icbflags  = udf_rw16(efe->icbtag.flags);
    225  1.1  reinoud 		addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
    226  1.6  reinoud 		file_type = efe->icbtag.file_type;
    227  1.1  reinoud 		has_fids  = (addr_type == UDF_ICB_INTERN_ALLOC);
    228  1.6  reinoud 		has_sbm   = (file_type == UDF_ICB_FILETYPE_META_BITMAP);
    229  1.1  reinoud 		rfid_pos  = UDF_EXTFENTRY_SIZE + l_ea;
    230  1.1  reinoud 		max_rfid_pos = rfid_pos + udf_rw64(efe->inf_len);
    231  1.1  reinoud 		lb_num = udf_rw32(efe->tag.tag_loc);
    232  1.1  reinoud 		break;
    233  1.1  reinoud 	case TAGID_INDIRECTENTRY :
    234  1.5  reinoud 	case TAGID_EXTATTR_HDR :
    235  1.5  reinoud 		break;
    236  1.1  reinoud 	case TAGID_ALLOCEXTENT :
    237  1.5  reinoud 		/* force crclen to 8 for UDF version < 2.01 */
    238  1.5  reinoud 		ext = (struct alloc_ext_entry *) tag;
    239  1.5  reinoud 		if (udf_rw16(ump->logvol_info->min_udf_readver) <= 0x200)
    240  1.5  reinoud 			ext->tag.desc_crc_len = udf_rw16(8);
    241  1.1  reinoud 		break;
    242  1.1  reinoud 	default:
    243  1.3    perry 		panic("%s: passed bad tag\n", __func__);
    244  1.1  reinoud 		break;
    245  1.1  reinoud 	}
    246  1.1  reinoud 
    247  1.1  reinoud 	/* fixup internal extended attributes if present */
    248  1.1  reinoud 	if (l_ea)
    249  1.1  reinoud 		udf_fixup_internal_extattr(blob, lb_num);
    250  1.1  reinoud 
    251  1.6  reinoud 	if (has_fids)
    252  1.1  reinoud 		udf_fixup_fid_block(blob, lb_size, rfid_pos,
    253  1.1  reinoud 			max_rfid_pos, lb_num);
    254  1.6  reinoud 
    255  1.6  reinoud 	if (has_sbm) {
    256  1.6  reinoud 		sbm_tag = (struct desc_tag *) (blob + rfid_pos);
    257  1.6  reinoud 		sbm_tag->tag_loc = tag->tag_loc;
    258  1.6  reinoud 		udf_validate_tag_and_crc_sums((uint8_t *) sbm_tag);
    259  1.1  reinoud 	}
    260  1.6  reinoud 
    261  1.1  reinoud 	udf_validate_tag_and_crc_sums(blob);
    262  1.1  reinoud }
    263  1.1  reinoud 
    264  1.1  reinoud /* --------------------------------------------------------------------- */
    265  1.1  reinoud 
    266  1.1  reinoud /*
    267  1.1  reinoud  * Set of generic descriptor readers and writers and their helper functions.
    268  1.1  reinoud  * Descriptors inside `logical space' i.e. inside logically mapped partitions
    269  1.1  reinoud  * can never be longer than one logical sector.
    270  1.1  reinoud  *
    271  1.1  reinoud  * NOTE that these functions *can* be used by the sheduler backends to read
    272  1.1  reinoud  * node descriptors too.
    273  1.1  reinoud  *
    274  1.1  reinoud  * For reading, the size of allocated piece is returned in multiple of sector
    275  1.1  reinoud  * size due to udf_calc_udf_malloc_size().
    276  1.1  reinoud  */
    277  1.1  reinoud 
    278  1.1  reinoud 
    279  1.1  reinoud /* SYNC reading of n blocks from specified sector */
    280  1.1  reinoud /* NOTE only used by udf_read_phys_dscr */
    281  1.1  reinoud static int
    282  1.1  reinoud udf_read_phys_sectors(struct udf_mount *ump, int what, void *blob,
    283  1.1  reinoud 	uint32_t start, uint32_t sectors)
    284  1.1  reinoud {
    285  1.1  reinoud 	struct buf *buf, *nestbuf;
    286  1.1  reinoud 	uint32_t buf_offset;
    287  1.1  reinoud 	off_t lblkno, rblkno;
    288  1.1  reinoud 	int sector_size = ump->discinfo.sector_size;
    289  1.1  reinoud 	int blks = sector_size / DEV_BSIZE;
    290  1.1  reinoud 	int piece;
    291  1.1  reinoud 	int error;
    292  1.1  reinoud 
    293  1.1  reinoud 	DPRINTF(READ, ("udf_intbreadn() : sectors = %d, sector_size = %d\n",
    294  1.1  reinoud 		sectors, sector_size));
    295  1.1  reinoud 	buf = getiobuf(ump->devvp, true);
    296  1.1  reinoud 	buf->b_flags    = B_READ;
    297  1.1  reinoud 	buf->b_cflags   = BC_BUSY;	/* needed? */
    298  1.1  reinoud 	buf->b_iodone   = NULL;
    299  1.1  reinoud 	buf->b_data     = blob;
    300  1.1  reinoud 	buf->b_bcount   = sectors * sector_size;
    301  1.1  reinoud 	buf->b_resid    = buf->b_bcount;
    302  1.1  reinoud 	buf->b_bufsize  = buf->b_bcount;
    303  1.1  reinoud 	buf->b_private  = NULL;	/* not needed yet */
    304  1.1  reinoud 	BIO_SETPRIO(buf, BPRIO_DEFAULT);
    305  1.1  reinoud 	buf->b_lblkno   = buf->b_blkno = buf->b_rawblkno = start * blks;
    306  1.1  reinoud 	buf->b_proc     = NULL;
    307  1.1  reinoud 
    308  1.1  reinoud 	error = 0;
    309  1.1  reinoud 	buf_offset = 0;
    310  1.1  reinoud 	rblkno = start;
    311  1.1  reinoud 	lblkno = 0;
    312  1.1  reinoud 	while ((sectors > 0) && (error == 0)) {
    313  1.1  reinoud 		piece = MIN(MAXPHYS/sector_size, sectors);
    314  1.1  reinoud 		DPRINTF(READ, ("read in %d + %d\n", (uint32_t) rblkno, piece));
    315  1.1  reinoud 
    316  1.1  reinoud 		nestbuf = getiobuf(NULL, true);
    317  1.1  reinoud 		nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
    318  1.1  reinoud 		/* nestbuf is B_ASYNC */
    319  1.1  reinoud 
    320  1.1  reinoud 		/* identify this nestbuf */
    321  1.1  reinoud 		nestbuf->b_lblkno   = lblkno;
    322  1.1  reinoud 
    323  1.1  reinoud 		/* CD shedules on raw blkno */
    324  1.1  reinoud 		nestbuf->b_blkno      = rblkno * blks;
    325  1.1  reinoud 		nestbuf->b_proc       = NULL;
    326  1.1  reinoud 		nestbuf->b_rawblkno   = rblkno * blks;
    327  1.1  reinoud 		nestbuf->b_udf_c_type = what;
    328  1.1  reinoud 
    329  1.1  reinoud 		udf_discstrat_queuebuf(ump, nestbuf);
    330  1.1  reinoud 
    331  1.1  reinoud 		lblkno     += piece;
    332  1.1  reinoud 		rblkno     += piece;
    333  1.1  reinoud 		buf_offset += piece * sector_size;
    334  1.1  reinoud 		sectors    -= piece;
    335  1.1  reinoud 	}
    336  1.1  reinoud 	error = biowait(buf);
    337  1.1  reinoud 	putiobuf(buf);
    338  1.1  reinoud 
    339  1.1  reinoud 	return error;
    340  1.1  reinoud }
    341  1.1  reinoud 
    342  1.1  reinoud 
    343  1.1  reinoud /* synchronous generic descriptor read */
    344  1.1  reinoud int
    345  1.1  reinoud udf_read_phys_dscr(struct udf_mount *ump, uint32_t sector,
    346  1.1  reinoud 		    struct malloc_type *mtype, union dscrptr **dstp)
    347  1.1  reinoud {
    348  1.1  reinoud 	union dscrptr *dst, *new_dst;
    349  1.1  reinoud 	uint8_t *pos;
    350  1.1  reinoud 	int sectors, dscrlen;
    351  1.1  reinoud 	int i, error, sector_size;
    352  1.1  reinoud 
    353  1.1  reinoud 	sector_size = ump->discinfo.sector_size;
    354  1.1  reinoud 
    355  1.1  reinoud 	*dstp = dst = NULL;
    356  1.1  reinoud 	dscrlen = sector_size;
    357  1.1  reinoud 
    358  1.1  reinoud 	/* read initial piece */
    359  1.1  reinoud 	dst = malloc(sector_size, mtype, M_WAITOK);
    360  1.1  reinoud 	error = udf_read_phys_sectors(ump, UDF_C_DSCR, dst, sector, 1);
    361  1.1  reinoud 	DPRINTFIF(DESCRIPTOR, error, ("read error (%d)\n", error));
    362  1.1  reinoud 
    363  1.1  reinoud 	if (!error) {
    364  1.1  reinoud 		/* check if its a valid tag */
    365  1.1  reinoud 		error = udf_check_tag(dst);
    366  1.1  reinoud 		if (error) {
    367  1.1  reinoud 			/* check if its an empty block */
    368  1.1  reinoud 			pos = (uint8_t *) dst;
    369  1.1  reinoud 			for (i = 0; i < sector_size; i++, pos++) {
    370  1.1  reinoud 				if (*pos) break;
    371  1.1  reinoud 			}
    372  1.1  reinoud 			if (i == sector_size) {
    373  1.1  reinoud 				/* return no error but with no dscrptr */
    374  1.1  reinoud 				/* dispose first block */
    375  1.1  reinoud 				free(dst, mtype);
    376  1.1  reinoud 				return 0;
    377  1.1  reinoud 			}
    378  1.1  reinoud 		}
    379  1.1  reinoud 		/* calculate descriptor size */
    380  1.1  reinoud 		dscrlen = udf_tagsize(dst, sector_size);
    381  1.1  reinoud 	}
    382  1.1  reinoud 	DPRINTFIF(DESCRIPTOR, error, ("bad tag checksum\n"));
    383  1.1  reinoud 
    384  1.1  reinoud 	if (!error && (dscrlen > sector_size)) {
    385  1.1  reinoud 		DPRINTF(DESCRIPTOR, ("multi block descriptor read\n"));
    386  1.1  reinoud 		/*
    387  1.1  reinoud 		 * Read the rest of descriptor. Since it is only used at mount
    388  1.1  reinoud 		 * time its overdone to define and use a specific udf_intbreadn
    389  1.1  reinoud 		 * for this alone.
    390  1.1  reinoud 		 */
    391  1.1  reinoud 
    392  1.1  reinoud 		new_dst = realloc(dst, dscrlen, mtype, M_WAITOK);
    393  1.1  reinoud 		if (new_dst == NULL) {
    394  1.1  reinoud 			free(dst, mtype);
    395  1.1  reinoud 			return ENOMEM;
    396  1.1  reinoud 		}
    397  1.1  reinoud 		dst = new_dst;
    398  1.1  reinoud 
    399  1.1  reinoud 		sectors = (dscrlen + sector_size -1) / sector_size;
    400  1.1  reinoud 		DPRINTF(DESCRIPTOR, ("dscrlen = %d (%d blk)\n", dscrlen, sectors));
    401  1.1  reinoud 
    402  1.1  reinoud 		pos = (uint8_t *) dst + sector_size;
    403  1.1  reinoud 		error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos,
    404  1.1  reinoud 				sector + 1, sectors-1);
    405  1.1  reinoud 
    406  1.1  reinoud 		DPRINTFIF(DESCRIPTOR, error, ("read error on multi (%d)\n",
    407  1.1  reinoud 		    error));
    408  1.1  reinoud 	}
    409  1.1  reinoud 	if (!error) {
    410  1.1  reinoud 		error = udf_check_tag_payload(dst, dscrlen);
    411  1.1  reinoud 		DPRINTFIF(DESCRIPTOR, error, ("bad payload check sum\n"));
    412  1.1  reinoud 	}
    413  1.1  reinoud 	if (error && dst) {
    414  1.1  reinoud 		free(dst, mtype);
    415  1.1  reinoud 		dst = NULL;
    416  1.1  reinoud 	}
    417  1.1  reinoud 	*dstp = dst;
    418  1.1  reinoud 
    419  1.1  reinoud 	return error;
    420  1.1  reinoud }
    421  1.1  reinoud 
    422  1.1  reinoud 
    423  1.1  reinoud static void
    424  1.1  reinoud udf_write_phys_buf(struct udf_mount *ump, int what, struct buf *buf)
    425  1.1  reinoud {
    426  1.1  reinoud 	struct buf *nestbuf;
    427  1.1  reinoud 	uint32_t buf_offset;
    428  1.1  reinoud 	off_t lblkno, rblkno;
    429  1.1  reinoud 	int sector_size = ump->discinfo.sector_size;
    430  1.1  reinoud 	int blks = sector_size / DEV_BSIZE;
    431  1.1  reinoud 	uint32_t sectors;
    432  1.1  reinoud 	int piece;
    433  1.1  reinoud 	int error;
    434  1.1  reinoud 
    435  1.1  reinoud 	sectors = buf->b_bcount / sector_size;
    436  1.1  reinoud 	DPRINTF(WRITE, ("udf_intbwriten() : sectors = %d, sector_size = %d\n",
    437  1.1  reinoud 		sectors, sector_size));
    438  1.1  reinoud 
    439  1.1  reinoud 	/* don't forget to increase pending count for the bwrite itself */
    440  1.1  reinoud /* panic("NO WRITING\n"); */
    441  1.1  reinoud 	if (buf->b_vp) {
    442  1.1  reinoud 		mutex_enter(&buf->b_vp->v_interlock);
    443  1.1  reinoud 		buf->b_vp->v_numoutput++;
    444  1.1  reinoud 		mutex_exit(&buf->b_vp->v_interlock);
    445  1.1  reinoud 	}
    446  1.1  reinoud 
    447  1.1  reinoud 	error = 0;
    448  1.1  reinoud 	buf_offset = 0;
    449  1.1  reinoud 	rblkno = buf->b_blkno / blks;
    450  1.1  reinoud 	lblkno = 0;
    451  1.1  reinoud 	while ((sectors > 0) && (error == 0)) {
    452  1.1  reinoud 		piece = MIN(MAXPHYS/sector_size, sectors);
    453  1.1  reinoud 		DPRINTF(WRITE, ("write out %d + %d\n",
    454  1.1  reinoud 		    (uint32_t) rblkno, piece));
    455  1.1  reinoud 
    456  1.1  reinoud 		nestbuf = getiobuf(NULL, true);
    457  1.1  reinoud 		nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
    458  1.1  reinoud 		/* nestbuf is B_ASYNC */
    459  1.1  reinoud 
    460  1.1  reinoud 		/* identify this nestbuf */
    461  1.1  reinoud 		nestbuf->b_lblkno   = lblkno;
    462  1.1  reinoud 
    463  1.1  reinoud 		/* CD shedules on raw blkno */
    464  1.1  reinoud 		nestbuf->b_blkno      = rblkno * blks;
    465  1.1  reinoud 		nestbuf->b_proc       = NULL;
    466  1.1  reinoud 		nestbuf->b_rawblkno   = rblkno * blks;
    467  1.1  reinoud 		nestbuf->b_udf_c_type = what;
    468  1.1  reinoud 
    469  1.1  reinoud 		udf_discstrat_queuebuf(ump, nestbuf);
    470  1.1  reinoud 
    471  1.1  reinoud 		lblkno     += piece;
    472  1.1  reinoud 		rblkno     += piece;
    473  1.1  reinoud 		buf_offset += piece * sector_size;
    474  1.1  reinoud 		sectors    -= piece;
    475  1.1  reinoud 	}
    476  1.1  reinoud }
    477  1.1  reinoud 
    478  1.1  reinoud 
    479  1.1  reinoud /* synchronous generic descriptor write */
    480  1.1  reinoud int
    481  1.1  reinoud udf_write_phys_dscr_sync(struct udf_mount *ump, struct udf_node *udf_node, int what,
    482  1.1  reinoud 		     union dscrptr *dscr, uint32_t sector, uint32_t logsector)
    483  1.1  reinoud {
    484  1.1  reinoud 	struct vnode *vp;
    485  1.1  reinoud 	struct buf *buf;
    486  1.1  reinoud 	int sector_size = ump->discinfo.sector_size;
    487  1.1  reinoud 	int blks = sector_size / DEV_BSIZE;
    488  1.1  reinoud 	int dscrlen;
    489  1.1  reinoud 	int error;
    490  1.1  reinoud 
    491  1.1  reinoud 	/* set sector number in the descriptor and validate */
    492  1.1  reinoud 	dscr->tag.tag_loc = udf_rw32(logsector);
    493  1.1  reinoud 	udf_validate_tag_and_crc_sums(dscr);
    494  1.1  reinoud 
    495  1.1  reinoud 	/* calculate descriptor size */
    496  1.1  reinoud 	dscrlen = udf_tagsize(dscr, sector_size);
    497  1.1  reinoud 
    498  1.1  reinoud 	/* get transfer buffer */
    499  1.1  reinoud 	vp = udf_node ? udf_node->vnode : ump->devvp;
    500  1.1  reinoud 	buf = getiobuf(vp, true);
    501  1.1  reinoud 	buf->b_flags    = B_WRITE;
    502  1.1  reinoud 	buf->b_cflags   = BC_BUSY;	/* needed? */
    503  1.1  reinoud 	buf->b_iodone   = NULL;
    504  1.1  reinoud 	buf->b_data     = (void *) dscr;
    505  1.1  reinoud 	buf->b_bcount   = dscrlen;
    506  1.1  reinoud 	buf->b_resid    = buf->b_bcount;
    507  1.1  reinoud 	buf->b_bufsize  = buf->b_bcount;
    508  1.1  reinoud 	buf->b_private  = NULL;	/* not needed yet */
    509  1.1  reinoud 	BIO_SETPRIO(buf, BPRIO_DEFAULT);
    510  1.1  reinoud 	buf->b_lblkno   = buf->b_blkno = buf->b_rawblkno = sector * blks;
    511  1.1  reinoud 	buf->b_proc     = NULL;
    512  1.1  reinoud 
    513  1.1  reinoud 	/* do the write, wait and return error */
    514  1.1  reinoud 	udf_write_phys_buf(ump, what, buf);
    515  1.1  reinoud 	error = biowait(buf);
    516  1.1  reinoud 	putiobuf(buf);
    517  1.1  reinoud 
    518  1.1  reinoud 	return error;
    519  1.1  reinoud }
    520  1.1  reinoud 
    521  1.1  reinoud 
    522  1.1  reinoud /* asynchronous generic descriptor write */
    523  1.1  reinoud int
    524  1.1  reinoud udf_write_phys_dscr_async(struct udf_mount *ump, struct udf_node *udf_node,
    525  1.1  reinoud 		      int what, union dscrptr *dscr,
    526  1.1  reinoud 		      uint32_t sector, uint32_t logsector,
    527  1.1  reinoud 		      void (*dscrwr_callback)(struct buf *))
    528  1.1  reinoud {
    529  1.1  reinoud 	struct vnode *vp;
    530  1.1  reinoud 	struct buf *buf;
    531  1.1  reinoud 	int dscrlen;
    532  1.1  reinoud 	int sector_size = ump->discinfo.sector_size;
    533  1.1  reinoud 	int blks = sector_size / DEV_BSIZE;
    534  1.1  reinoud 
    535  1.1  reinoud 	KASSERT(dscrwr_callback);
    536  1.1  reinoud 	DPRINTF(NODE, ("udf_write_phys_dscr_async() called\n"));
    537  1.1  reinoud 
    538  1.1  reinoud 	/* set sector number in the descriptor and validate */
    539  1.1  reinoud 	dscr->tag.tag_loc = udf_rw32(logsector);
    540  1.1  reinoud 	udf_validate_tag_and_crc_sums(dscr);
    541  1.1  reinoud 
    542  1.1  reinoud 	/* calculate descriptor size */
    543  1.1  reinoud 	dscrlen = udf_tagsize(dscr, sector_size);
    544  1.1  reinoud 
    545  1.1  reinoud 	/* get transfer buffer */
    546  1.1  reinoud 	vp = udf_node ? udf_node->vnode : ump->devvp;
    547  1.1  reinoud 	buf = getiobuf(vp, true);
    548  1.1  reinoud 	buf->b_flags    = B_WRITE; // | B_ASYNC;
    549  1.1  reinoud 	buf->b_cflags   = BC_BUSY;
    550  1.1  reinoud 	buf->b_iodone	= dscrwr_callback;
    551  1.1  reinoud 	buf->b_data     = dscr;
    552  1.1  reinoud 	buf->b_bcount   = dscrlen;
    553  1.1  reinoud 	buf->b_resid    = buf->b_bcount;
    554  1.1  reinoud 	buf->b_bufsize  = buf->b_bcount;
    555  1.1  reinoud 	buf->b_private  = NULL;	/* not needed yet */
    556  1.1  reinoud 	BIO_SETPRIO(buf, BPRIO_DEFAULT);
    557  1.1  reinoud 	buf->b_lblkno   = buf->b_blkno = buf->b_rawblkno = sector * blks;
    558  1.1  reinoud 	buf->b_proc     = NULL;
    559  1.1  reinoud 
    560  1.1  reinoud 	/* do the write and return no error */
    561  1.1  reinoud 	udf_write_phys_buf(ump, what, buf);
    562  1.1  reinoud 	return 0;
    563  1.1  reinoud }
    564  1.1  reinoud 
    565  1.1  reinoud /* --------------------------------------------------------------------- */
    566  1.1  reinoud 
    567  1.1  reinoud /* disc strategy dispatchers */
    568  1.1  reinoud 
    569  1.1  reinoud int
    570  1.1  reinoud udf_create_logvol_dscr(struct udf_mount *ump, struct udf_node *udf_node, struct long_ad *icb,
    571  1.1  reinoud 	union dscrptr **dscrptr)
    572  1.1  reinoud {
    573  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    574  1.1  reinoud 	struct udf_strat_args args;
    575  1.1  reinoud 	int error;
    576  1.1  reinoud 
    577  1.4  reinoud 	KASSERT(strategy);
    578  1.1  reinoud 	args.ump  = ump;
    579  1.1  reinoud 	args.udf_node = udf_node;
    580  1.1  reinoud 	args.icb  = icb;
    581  1.1  reinoud 	args.dscr = NULL;
    582  1.1  reinoud 
    583  1.1  reinoud 	error = (strategy->create_logvol_dscr)(&args);
    584  1.1  reinoud 	*dscrptr = args.dscr;
    585  1.1  reinoud 
    586  1.1  reinoud 	return error;
    587  1.1  reinoud }
    588  1.1  reinoud 
    589  1.1  reinoud 
    590  1.1  reinoud void
    591  1.1  reinoud udf_free_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
    592  1.1  reinoud 	void *dscr)
    593  1.1  reinoud {
    594  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    595  1.1  reinoud 	struct udf_strat_args args;
    596  1.1  reinoud 
    597  1.4  reinoud 	KASSERT(strategy);
    598  1.1  reinoud 	args.ump  = ump;
    599  1.1  reinoud 	args.icb  = icb;
    600  1.1  reinoud 	args.dscr = dscr;
    601  1.1  reinoud 
    602  1.1  reinoud 	(strategy->free_logvol_dscr)(&args);
    603  1.1  reinoud }
    604  1.1  reinoud 
    605  1.1  reinoud 
    606  1.1  reinoud int
    607  1.1  reinoud udf_read_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
    608  1.1  reinoud 	union dscrptr **dscrptr)
    609  1.1  reinoud {
    610  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    611  1.1  reinoud 	struct udf_strat_args args;
    612  1.1  reinoud 	int error;
    613  1.1  reinoud 
    614  1.4  reinoud 	KASSERT(strategy);
    615  1.1  reinoud 	args.ump  = ump;
    616  1.1  reinoud 	args.icb  = icb;
    617  1.1  reinoud 	args.dscr = NULL;
    618  1.1  reinoud 
    619  1.1  reinoud 	error = (strategy->read_logvol_dscr)(&args);
    620  1.1  reinoud 	*dscrptr = args.dscr;
    621  1.1  reinoud 
    622  1.1  reinoud 	return error;
    623  1.1  reinoud }
    624  1.1  reinoud 
    625  1.1  reinoud 
    626  1.1  reinoud int
    627  1.1  reinoud udf_write_logvol_dscr(struct udf_node *udf_node, union dscrptr *dscr,
    628  1.1  reinoud 	struct long_ad *icb, int waitfor)
    629  1.1  reinoud {
    630  1.1  reinoud 	struct udf_strategy *strategy = udf_node->ump->strategy;
    631  1.1  reinoud 	struct udf_strat_args args;
    632  1.1  reinoud 	int error;
    633  1.1  reinoud 
    634  1.4  reinoud 	KASSERT(strategy);
    635  1.1  reinoud 	args.ump      = udf_node->ump;
    636  1.1  reinoud 	args.udf_node = udf_node;
    637  1.1  reinoud 	args.icb      = icb;
    638  1.1  reinoud 	args.dscr     = dscr;
    639  1.1  reinoud 	args.waitfor  = waitfor;
    640  1.1  reinoud 
    641  1.1  reinoud 	error = (strategy->write_logvol_dscr)(&args);
    642  1.1  reinoud 	return error;
    643  1.1  reinoud }
    644  1.1  reinoud 
    645  1.1  reinoud 
    646  1.1  reinoud void
    647  1.1  reinoud udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf)
    648  1.1  reinoud {
    649  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    650  1.1  reinoud 	struct udf_strat_args args;
    651  1.1  reinoud 
    652  1.4  reinoud 	KASSERT(strategy);
    653  1.1  reinoud 	args.ump = ump;
    654  1.1  reinoud 	args.nestbuf = nestbuf;
    655  1.1  reinoud 
    656  1.1  reinoud 	(strategy->queuebuf)(&args);
    657  1.1  reinoud }
    658  1.1  reinoud 
    659  1.1  reinoud 
    660  1.1  reinoud void
    661  1.1  reinoud udf_discstrat_init(struct udf_mount *ump)
    662  1.1  reinoud {
    663  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    664  1.1  reinoud 	struct udf_strat_args args;
    665  1.1  reinoud 
    666  1.4  reinoud 	KASSERT(strategy);
    667  1.1  reinoud 	args.ump = ump;
    668  1.1  reinoud 	(strategy->discstrat_init)(&args);
    669  1.1  reinoud }
    670  1.1  reinoud 
    671  1.1  reinoud 
    672  1.1  reinoud void udf_discstrat_finish(struct udf_mount *ump)
    673  1.1  reinoud {
    674  1.1  reinoud 	struct udf_strategy *strategy = ump->strategy;
    675  1.1  reinoud 	struct udf_strat_args args;
    676  1.1  reinoud 
    677  1.4  reinoud 	/* strategy might not have been set, so ignore if not set */
    678  1.4  reinoud 	if (strategy) {
    679  1.4  reinoud 		args.ump = ump;
    680  1.4  reinoud 		(strategy->discstrat_finish)(&args);
    681  1.4  reinoud 	}
    682  1.1  reinoud }
    683  1.1  reinoud 
    684  1.1  reinoud /* --------------------------------------------------------------------- */
    685  1.1  reinoud 
    686