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