Print this page
8115 parallel zfs mount
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/udfs/udf_vfsops.c
+++ new/usr/src/uts/common/fs/udfs/udf_vfsops.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25 + * Copyright (c) 2017 by Delphix. All rights reserved.
25 26 */
26 27
27 28 #include <sys/types.h>
28 29 #include <sys/t_lock.h>
29 30 #include <sys/param.h>
30 31 #include <sys/time.h>
31 32 #include <sys/systm.h>
32 33 #include <sys/sysmacros.h>
33 34 #include <sys/resource.h>
34 35 #include <sys/signal.h>
35 36 #include <sys/cred.h>
36 37 #include <sys/user.h>
37 38 #include <sys/buf.h>
38 39 #include <sys/vfs.h>
39 40 #include <sys/vfs_opreg.h>
40 41 #include <sys/stat.h>
41 42 #include <sys/vnode.h>
42 43 #include <sys/mode.h>
43 44 #include <sys/proc.h>
44 45 #include <sys/disp.h>
45 46 #include <sys/file.h>
46 47 #include <sys/fcntl.h>
47 48 #include <sys/flock.h>
48 49 #include <sys/kmem.h>
49 50 #include <sys/uio.h>
50 51 #include <sys/dnlc.h>
51 52 #include <sys/conf.h>
52 53 #include <sys/errno.h>
53 54 #include <sys/mman.h>
54 55 #include <sys/fbuf.h>
55 56 #include <sys/pathname.h>
56 57 #include <sys/debug.h>
57 58 #include <sys/vmsystm.h>
58 59 #include <sys/cmn_err.h>
59 60 #include <sys/dirent.h>
60 61 #include <sys/errno.h>
61 62 #include <sys/modctl.h>
62 63 #include <sys/statvfs.h>
63 64 #include <sys/mount.h>
64 65 #include <sys/sunddi.h>
65 66 #include <sys/bootconf.h>
66 67 #include <sys/policy.h>
67 68
68 69 #include <vm/hat.h>
69 70 #include <vm/page.h>
70 71 #include <vm/pvn.h>
71 72 #include <vm/as.h>
72 73 #include <vm/seg.h>
73 74 #include <vm/seg_map.h>
74 75 #include <vm/seg_kmem.h>
75 76 #include <vm/seg_vn.h>
76 77 #include <vm/rm.h>
77 78 #include <vm/page.h>
78 79 #include <sys/swap.h>
79 80 #include <sys/mntent.h>
80 81
81 82
82 83 #include <fs/fs_subr.h>
83 84
84 85
85 86 #include <sys/fs/udf_volume.h>
86 87 #include <sys/fs/udf_inode.h>
87 88
88 89
89 90 extern struct vnode *common_specvp(struct vnode *vp);
90 91
91 92 extern kmutex_t ud_sync_busy;
92 93 static int32_t ud_mountfs(struct vfs *,
93 94 enum whymountroot, dev_t, char *, struct cred *, int32_t);
94 95 static struct udf_vfs *ud_validate_and_fill_superblock(dev_t,
95 96 int32_t, uint32_t);
96 97 void ud_destroy_fsp(struct udf_vfs *);
97 98 void ud_convert_to_superblock(struct udf_vfs *,
98 99 struct log_vol_int_desc *);
99 100 void ud_update_superblock(struct vfs *);
100 101 int32_t ud_get_last_block(dev_t, daddr_t *);
101 102 static int32_t ud_val_get_vat(struct udf_vfs *,
102 103 dev_t, daddr_t, struct ud_map *);
103 104 int32_t ud_read_sparing_tbls(struct udf_vfs *,
104 105 dev_t, struct ud_map *, struct pmap_typ2 *);
105 106 uint32_t ud_get_lbsize(dev_t, uint32_t *);
106 107
107 108 static int32_t udf_mount(struct vfs *,
108 109 struct vnode *, struct mounta *, struct cred *);
109 110 static int32_t udf_unmount(struct vfs *, int, struct cred *);
110 111 static int32_t udf_root(struct vfs *, struct vnode **);
111 112 static int32_t udf_statvfs(struct vfs *, struct statvfs64 *);
112 113 static int32_t udf_sync(struct vfs *, int16_t, struct cred *);
113 114 static int32_t udf_vget(struct vfs *, struct vnode **, struct fid *);
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
114 115 static int32_t udf_mountroot(struct vfs *vfsp, enum whymountroot);
115 116
116 117 static int udfinit(int, char *);
117 118
118 119 static mntopts_t udfs_mntopts;
119 120
120 121 static vfsdef_t vfw = {
121 122 VFSDEF_VERSION,
122 123 "udfs",
123 124 udfinit,
124 - VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_CANLOFI,
125 + VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_CANLOFI|VSW_MOUNTDEV,
125 126 &udfs_mntopts
126 127 };
127 128
128 129 static mntopts_t udfs_mntopts = {
129 130 0,
130 131 NULL
131 132 };
132 133
133 134 /*
134 135 * Module linkage information for the kernel.
135 136 */
136 137 extern struct mod_ops mod_fsops;
137 138
138 139 static struct modlfs modlfs = {
139 140 &mod_fsops, "filesystem for UDFS", &vfw
140 141 };
141 142
142 143 static struct modlinkage modlinkage = {
143 144 MODREV_1, (void *)&modlfs, NULL
144 145 };
145 146
146 147 int32_t udf_fstype = -1;
147 148
148 149 int
149 150 _init()
150 151 {
151 152 return (mod_install(&modlinkage));
152 153 }
153 154
154 155 int
155 156 _fini()
156 157 {
157 158 return (EBUSY);
158 159 }
159 160
160 161 int
161 162 _info(struct modinfo *modinfop)
162 163 {
163 164 return (mod_info(&modlinkage, modinfop));
164 165 }
165 166
166 167
167 168 /* -------------------- vfs routines -------------------- */
168 169
169 170 /*
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
170 171 * XXX - this appears only to be used by the VM code to handle the case where
171 172 * UNIX is running off the mini-root. That probably wants to be done
172 173 * differently.
173 174 */
174 175 struct vnode *rootvp;
175 176 #ifndef __lint
176 177 _NOTE(SCHEME_PROTECTS_DATA("safe sharing", rootvp))
177 178 #endif
178 179 static int32_t
179 180 udf_mount(struct vfs *vfsp, struct vnode *mvp,
180 - struct mounta *uap, struct cred *cr)
181 + struct mounta *uap, struct cred *cr)
181 182 {
182 183 dev_t dev;
183 184 struct vnode *lvp = NULL;
184 185 struct vnode *svp = NULL;
185 186 struct pathname dpn;
186 187 int32_t error;
187 188 enum whymountroot why;
188 189 int oflag, aflag;
189 190
190 191 ud_printf("udf_mount\n");
191 192
192 193 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) {
193 194 return (error);
194 195 }
195 196
196 197 if (mvp->v_type != VDIR) {
197 198 return (ENOTDIR);
198 199 }
199 200
200 201 mutex_enter(&mvp->v_lock);
201 202 if ((uap->flags & MS_REMOUNT) == 0 &&
202 203 (uap->flags & MS_OVERLAY) == 0 &&
203 204 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
204 205 mutex_exit(&mvp->v_lock);
205 206 return (EBUSY);
206 207 }
207 208 mutex_exit(&mvp->v_lock);
208 209
209 210 if (error = pn_get(uap->dir, UIO_USERSPACE, &dpn)) {
210 211 return (error);
211 212 }
212 213
213 214 /*
214 215 * Resolve path name of the file being mounted.
215 216 */
216 217 if (error = lookupname(uap->spec, UIO_USERSPACE, FOLLOW, NULLVPP,
217 218 &svp)) {
218 219 pn_free(&dpn);
219 220 return (error);
220 221 }
221 222
222 223 error = vfs_get_lofi(vfsp, &lvp);
223 224
224 225 if (error > 0) {
225 226 if (error == ENOENT)
226 227 error = ENODEV;
227 228 goto out;
228 229 } else if (error == 0) {
229 230 dev = lvp->v_rdev;
230 231 } else {
231 232 dev = svp->v_rdev;
232 233
233 234 if (svp->v_type != VBLK) {
234 235 error = ENOTBLK;
235 236 goto out;
236 237 }
237 238 }
238 239
239 240 /*
240 241 * Ensure that this device isn't already mounted,
241 242 * unless this is a REMOUNT request
242 243 */
243 244 if (vfs_devmounting(dev, vfsp)) {
244 245 error = EBUSY;
245 246 goto out;
246 247 }
247 248 if (vfs_devismounted(dev)) {
248 249 if (uap->flags & MS_REMOUNT) {
249 250 why = ROOT_REMOUNT;
250 251 } else {
251 252 error = EBUSY;
252 253 goto out;
253 254 }
254 255 } else {
255 256 why = ROOT_INIT;
256 257 }
257 258 if (getmajor(dev) >= devcnt) {
258 259 error = ENXIO;
259 260 goto out;
260 261 }
261 262
262 263 /*
263 264 * If the device is a tape, mount it read only
264 265 */
265 266 if (devopsp[getmajor(dev)]->devo_cb_ops->cb_flag & D_TAPE) {
266 267 vfsp->vfs_flag |= VFS_RDONLY;
267 268 }
268 269
269 270 if (uap->flags & MS_RDONLY) {
270 271 vfsp->vfs_flag |= VFS_RDONLY;
271 272 }
272 273
273 274 /*
274 275 * Set mount options.
275 276 */
276 277 if (uap->flags & MS_RDONLY) {
277 278 vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
278 279 }
279 280 if (uap->flags & MS_NOSUID) {
280 281 vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0);
281 282 }
282 283
283 284 /*
284 285 * Verify that the caller can open the device special file as
285 286 * required. It is not until this moment that we know whether
286 287 * we're mounting "ro" or not.
287 288 */
288 289 if ((vfsp->vfs_flag & VFS_RDONLY) != 0) {
289 290 oflag = FREAD;
290 291 aflag = VREAD;
291 292 } else {
292 293 oflag = FREAD | FWRITE;
293 294 aflag = VREAD | VWRITE;
294 295 }
295 296
296 297 if (lvp == NULL &&
297 298 (error = secpolicy_spec_open(cr, svp, oflag)) != 0)
298 299 goto out;
299 300
300 301 if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0)
301 302 goto out;
302 303
303 304 /*
304 305 * Mount the filesystem.
305 306 */
306 307 error = ud_mountfs(vfsp, why, dev, dpn.pn_path, cr, 0);
307 308 out:
308 309 VN_RELE(svp);
309 310 if (lvp != NULL)
310 311 VN_RELE(lvp);
311 312 pn_free(&dpn);
312 313 return (error);
313 314 }
314 315
315 316
316 317
317 318 /*
318 319 * unmount the file system pointed
319 320 * by vfsp
320 321 */
321 322 /* ARGSUSED */
322 323 static int32_t
323 324 udf_unmount(struct vfs *vfsp, int fflag, struct cred *cr)
324 325 {
325 326 struct udf_vfs *udf_vfsp;
326 327 struct vnode *bvp, *rvp;
327 328 struct ud_inode *rip;
328 329 int32_t flag;
329 330
330 331 ud_printf("udf_unmount\n");
331 332
332 333 if (secpolicy_fs_unmount(cr, vfsp) != 0) {
333 334 return (EPERM);
334 335 }
335 336
336 337 /*
337 338 * forced unmount is not supported by this file system
338 339 * and thus, ENOTSUP, is being returned.
339 340 */
340 341 if (fflag & MS_FORCE)
341 342 return (ENOTSUP);
342 343
343 344 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
344 345 flag = !(udf_vfsp->udf_flags & UDF_FL_RDONLY);
345 346 bvp = udf_vfsp->udf_devvp;
346 347
347 348 rvp = udf_vfsp->udf_root;
348 349 ASSERT(rvp != NULL);
349 350 rip = VTOI(rvp);
350 351
351 352 (void) ud_release_cache(udf_vfsp);
352 353
353 354
354 355 /* Flush all inodes except root */
355 356 if (ud_iflush(vfsp) < 0) {
356 357 return (EBUSY);
357 358 }
358 359
359 360 rw_enter(&rip->i_contents, RW_WRITER);
360 361 (void) ud_syncip(rip, B_INVAL, I_SYNC);
361 362 rw_exit(&rip->i_contents);
362 363
363 364 mutex_enter(&ud_sync_busy);
364 365 if ((udf_vfsp->udf_flags & UDF_FL_RDONLY) == 0) {
365 366 bflush(vfsp->vfs_dev);
366 367 mutex_enter(&udf_vfsp->udf_lock);
367 368 udf_vfsp->udf_clean = UDF_CLEAN;
368 369 mutex_exit(&udf_vfsp->udf_lock);
369 370 ud_update_superblock(vfsp);
370 371 }
371 372 mutex_exit(&ud_sync_busy);
372 373
373 374 mutex_destroy(&udf_vfsp->udf_lock);
374 375 mutex_destroy(&udf_vfsp->udf_rename_lck);
375 376
376 377 ud_delcache(rip);
377 378 ITIMES(rip);
378 379 VN_RELE(rvp);
379 380
380 381 ud_destroy_fsp(udf_vfsp);
381 382
382 383 (void) VOP_PUTPAGE(bvp, (offset_t)0, (uint32_t)0, B_INVAL, cr, NULL);
383 384 (void) VOP_CLOSE(bvp, flag, 1, (offset_t)0, cr, NULL);
384 385
385 386 (void) bfinval(vfsp->vfs_dev, 1);
386 387 VN_RELE(bvp);
387 388
388 389
389 390 return (0);
390 391 }
391 392
392 393
393 394 /*
394 395 * Get the root vp for the
395 396 * file system
396 397 */
397 398 static int32_t
398 399 udf_root(struct vfs *vfsp, struct vnode **vpp)
399 400 {
400 401 struct udf_vfs *udf_vfsp;
401 402 struct vnode *vp;
402 403
403 404 ud_printf("udf_root\n");
404 405
405 406 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
406 407
407 408 ASSERT(udf_vfsp != NULL);
408 409 ASSERT(udf_vfsp->udf_root != NULL);
409 410
410 411 vp = udf_vfsp->udf_root;
411 412 VN_HOLD(vp);
412 413 *vpp = vp;
413 414 return (0);
414 415 }
415 416
416 417
417 418 /*
418 419 * Get file system statistics.
419 420 */
420 421 static int32_t
421 422 udf_statvfs(struct vfs *vfsp, struct statvfs64 *sp)
422 423 {
423 424 struct udf_vfs *udf_vfsp;
424 425 struct ud_part *parts;
425 426 dev32_t d32;
426 427 int32_t index;
427 428
428 429 ud_printf("udf_statvfs\n");
429 430
430 431 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
431 432 (void) bzero(sp, sizeof (struct statvfs64));
432 433
433 434 mutex_enter(&udf_vfsp->udf_lock);
434 435 sp->f_bsize = udf_vfsp->udf_lbsize;
435 436 sp->f_frsize = udf_vfsp->udf_lbsize;
436 437 sp->f_blocks = 0;
437 438 sp->f_bfree = 0;
438 439 parts = udf_vfsp->udf_parts;
439 440 for (index = 0; index < udf_vfsp->udf_npart; index++) {
440 441 sp->f_blocks += parts->udp_nblocks;
441 442 sp->f_bfree += parts->udp_nfree;
442 443 parts++;
443 444 }
444 445 sp->f_bavail = sp->f_bfree;
445 446
446 447 /*
447 448 * Since there are no real inodes allocated
448 449 * we will approximate
449 450 * each new file will occupy :
450 451 * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size)
451 452 */
452 453 sp->f_ffree = sp->f_favail =
453 454 (sp->f_bavail * sp->f_bsize) / (146 + sp->f_bsize);
454 455
455 456 /*
456 457 * The total number of inodes is
457 458 * the sum of files + directories + free inodes
458 459 */
459 460 sp->f_files = sp->f_ffree + udf_vfsp->udf_nfiles + udf_vfsp->udf_ndirs;
460 461 (void) cmpldev(&d32, vfsp->vfs_dev);
461 462 sp->f_fsid = d32;
462 463 (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
463 464 sp->f_flag = vf_to_stf(vfsp->vfs_flag);
464 465 sp->f_namemax = MAXNAMLEN;
465 466 (void) strcpy(sp->f_fstr, udf_vfsp->udf_volid);
466 467
467 468 mutex_exit(&udf_vfsp->udf_lock);
468 469
469 470 return (0);
470 471 }
471 472
472 473
473 474 /*
474 475 * Flush any pending I/O to file system vfsp.
475 476 * The ud_update() routine will only flush *all* udf files.
476 477 */
477 478 /*ARGSUSED*/
478 479 /* ARGSUSED */
479 480 static int32_t
480 481 udf_sync(struct vfs *vfsp, int16_t flag, struct cred *cr)
481 482 {
↓ open down ↓ |
291 lines elided |
↑ open up ↑ |
482 483 ud_printf("udf_sync\n");
483 484
484 485 ud_update(flag);
485 486 return (0);
486 487 }
487 488
488 489
489 490
490 491 /* ARGSUSED */
491 492 static int32_t
492 -udf_vget(struct vfs *vfsp,
493 - struct vnode **vpp, struct fid *fidp)
493 +udf_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp)
494 494 {
495 495 int32_t error = 0;
496 496 struct udf_fid *udfid;
497 497 struct udf_vfs *udf_vfsp;
498 498 struct ud_inode *ip;
499 499
500 500 ud_printf("udf_vget\n");
501 501
502 502 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
503 503 if (udf_vfsp == NULL) {
504 504 *vpp = NULL;
505 505 return (0);
506 506 }
507 507
508 508 udfid = (struct udf_fid *)fidp;
509 509 if ((error = ud_iget(vfsp, udfid->udfid_prn,
510 510 udfid->udfid_icb_lbn, &ip, NULL, CRED())) != 0) {
511 511 *vpp = NULL;
512 512 return (error);
513 513 }
514 514
515 515 rw_enter(&ip->i_contents, RW_READER);
516 516 if ((udfid->udfid_uinq_lo != (ip->i_uniqid & 0xffffffff)) ||
517 517 (udfid->udfid_prn != ip->i_icb_prn)) {
518 518 rw_exit(&ip->i_contents);
519 519 VN_RELE(ITOV(ip));
520 520 *vpp = NULL;
521 521 return (EINVAL);
522 522 }
523 523 rw_exit(&ip->i_contents);
524 524
525 525 *vpp = ITOV(ip);
526 526 return (0);
527 527 }
528 528
529 529
530 530 /*
531 531 * Mount root file system.
532 532 * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
533 533 * remount the root file system, and ROOT_UNMOUNT if called to
534 534 * unmount the root (e.g., as part of a system shutdown).
535 535 *
536 536 * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
537 537 * operation, goes along with auto-configuration. A mechanism should be
538 538 * provided by which machine-INdependent code in the kernel can say "get me the
539 539 * right root file system" and "get me the right initial swap area", and have
540 540 * that done in what may well be a machine-dependent fashion.
541 541 * Unfortunately, it is also file-system-type dependent (NFS gets it via
542 542 * bootparams calls, UFS gets it from various and sundry machine-dependent
543 543 * mechanisms, as SPECFS does for swap).
544 544 */
545 545 /* ARGSUSED */
546 546 static int32_t
547 547 udf_mountroot(struct vfs *vfsp, enum whymountroot why)
548 548 {
549 549 dev_t rootdev;
550 550 static int32_t udf_rootdone = 0;
551 551 struct vnode *vp = NULL;
552 552 int32_t ovflags, error;
553 553 ud_printf("udf_mountroot\n");
554 554
555 555 if (why == ROOT_INIT) {
556 556 if (udf_rootdone++) {
557 557 return (EBUSY);
558 558 }
559 559 rootdev = getrootdev();
560 560 if (rootdev == (dev_t)NODEV) {
561 561 return (ENODEV);
562 562 }
563 563 vfsp->vfs_dev = rootdev;
564 564 vfsp->vfs_flag |= VFS_RDONLY;
565 565 } else if (why == ROOT_REMOUNT) {
566 566 vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
567 567 (void) dnlc_purge_vfsp(vfsp, 0);
568 568 vp = common_specvp(vp);
569 569 (void) VOP_PUTPAGE(vp, (offset_t)0,
570 570 (uint32_t)0, B_INVAL, CRED(), NULL);
571 571 binval(vfsp->vfs_dev);
572 572
573 573 ovflags = vfsp->vfs_flag;
574 574 vfsp->vfs_flag &= ~VFS_RDONLY;
575 575 vfsp->vfs_flag |= VFS_REMOUNT;
576 576 rootdev = vfsp->vfs_dev;
577 577 } else if (why == ROOT_UNMOUNT) {
578 578 ud_update(0);
579 579 vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
580 580 (void) VOP_CLOSE(vp, FREAD|FWRITE, 1,
581 581 (offset_t)0, CRED(), NULL);
582 582 return (0);
583 583 }
584 584
585 585 if ((error = vfs_lock(vfsp)) != 0) {
586 586 return (error);
587 587 }
588 588
589 589 error = ud_mountfs(vfsp, why, rootdev, "/", CRED(), 1);
590 590 if (error) {
591 591 vfs_unlock(vfsp);
592 592 if (why == ROOT_REMOUNT) {
593 593 vfsp->vfs_flag = ovflags;
594 594 }
595 595 if (rootvp) {
596 596 VN_RELE(rootvp);
597 597 rootvp = (struct vnode *)0;
598 598 }
599 599 return (error);
600 600 }
601 601
602 602 if (why == ROOT_INIT) {
603 603 vfs_add((struct vnode *)0, vfsp,
604 604 (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
↓ open down ↓ |
101 lines elided |
↑ open up ↑ |
605 605 }
606 606 vfs_unlock(vfsp);
607 607 return (0);
608 608 }
609 609
610 610
611 611 /* ------------------------- local routines ------------------------- */
612 612
613 613
614 614 static int32_t
615 -ud_mountfs(struct vfs *vfsp,
616 - enum whymountroot why, dev_t dev, char *name,
617 - struct cred *cr, int32_t isroot)
615 +ud_mountfs(struct vfs *vfsp, enum whymountroot why, dev_t dev, char *name,
616 + struct cred *cr, int32_t isroot)
618 617 {
619 618 struct vnode *devvp = NULL;
620 619 int32_t error = 0;
621 620 int32_t needclose = 0;
622 621 struct udf_vfs *udf_vfsp = NULL;
623 622 struct log_vol_int_desc *lvid;
624 623 struct ud_inode *rip = NULL;
625 624 struct vnode *rvp = NULL;
626 625 int32_t i, lbsize;
627 626 uint32_t avd_loc;
628 627 struct ud_map *map;
629 628 int32_t desc_len;
630 629
631 630 ud_printf("ud_mountfs\n");
632 631
633 632 if (why == ROOT_INIT) {
634 633 /*
635 634 * Open the device.
636 635 */
637 636 devvp = makespecvp(dev, VBLK);
638 637
639 638 /*
640 639 * Open block device mounted on.
641 640 * When bio is fixed for vnodes this can all be vnode
642 641 * operations.
643 642 */
644 643 error = VOP_OPEN(&devvp,
645 644 (vfsp->vfs_flag & VFS_RDONLY) ? FREAD : FREAD|FWRITE,
646 645 cr, NULL);
647 646 if (error) {
648 647 goto out;
649 648 }
650 649 needclose = 1;
651 650
652 651 /*
653 652 * Refuse to go any further if this
654 653 * device is being used for swapping.
655 654 */
656 655 if (IS_SWAPVP(devvp)) {
657 656 error = EBUSY;
658 657 goto out;
659 658 }
660 659 }
661 660
662 661 /*
663 662 * check for dev already mounted on
664 663 */
665 664 if (vfsp->vfs_flag & VFS_REMOUNT) {
666 665 struct tag *ttag;
667 666 int32_t index, count;
668 667 struct buf *tpt = 0;
669 668 caddr_t addr;
670 669
671 670
672 671 /* cannot remount to RDONLY */
673 672 if (vfsp->vfs_flag & VFS_RDONLY) {
674 673 return (EINVAL);
675 674 }
676 675
677 676 if (vfsp->vfs_dev != dev) {
678 677 return (EINVAL);
679 678 }
680 679
681 680 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
682 681 devvp = udf_vfsp->udf_devvp;
683 682
684 683 /*
685 684 * fsck may have altered the file system; discard
686 685 * as much incore data as possible. Don't flush
687 686 * if this is a rw to rw remount; it's just resetting
688 687 * the options.
689 688 */
690 689 if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
691 690 (void) dnlc_purge_vfsp(vfsp, 0);
692 691 (void) VOP_PUTPAGE(devvp, (offset_t)0, (uint_t)0,
693 692 B_INVAL, CRED(), NULL);
694 693 (void) ud_iflush(vfsp);
695 694 bflush(dev);
696 695 binval(dev);
697 696 }
698 697
699 698 /*
700 699 * We could read UDF1.50 and write UDF1.50 only
701 700 * disallow mount of any highier version
702 701 */
703 702 if ((udf_vfsp->udf_miread > UDF_150) ||
704 703 (udf_vfsp->udf_miwrite > UDF_150)) {
705 704 error = EINVAL;
706 705 goto remountout;
707 706 }
708 707
709 708 /*
710 709 * read/write to read/write; all done
711 710 */
712 711 if (udf_vfsp->udf_flags & UDF_FL_RW) {
713 712 goto remountout;
714 713 }
715 714
716 715 /*
717 716 * Does the media type allow a writable mount
718 717 */
719 718 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
720 719 error = EINVAL;
721 720 goto remountout;
722 721 }
723 722
724 723 /*
725 724 * Read the metadata
726 725 * and check if it is possible to
727 726 * mount in rw mode
728 727 */
729 728 tpt = ud_bread(vfsp->vfs_dev,
730 729 udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift,
731 730 udf_vfsp->udf_iseq_len);
732 731 if (tpt->b_flags & B_ERROR) {
733 732 error = EIO;
734 733 goto remountout;
735 734 }
736 735 count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
737 736 addr = tpt->b_un.b_addr;
738 737 for (index = 0; index < count; index ++) {
739 738 ttag = (struct tag *)(addr + index * DEV_BSIZE);
740 739 desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
741 740 if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
742 741 udf_vfsp->udf_iseq_loc +
743 742 (index >> udf_vfsp->udf_l2d_shift),
744 743 1, desc_len) == 0) {
745 744 struct log_vol_int_desc *lvid;
746 745
747 746 lvid = (struct log_vol_int_desc *)ttag;
748 747
749 748 if (SWAP_32(lvid->lvid_int_type) !=
750 749 LOG_VOL_CLOSE_INT) {
751 750 error = EINVAL;
752 751 goto remountout;
753 752 }
754 753
755 754 /*
756 755 * Copy new data to old data
757 756 */
758 757 bcopy(udf_vfsp->udf_iseq->b_un.b_addr,
759 758 tpt->b_un.b_addr, udf_vfsp->udf_iseq_len);
760 759 break;
761 760 }
762 761 }
763 762
764 763 udf_vfsp->udf_flags = UDF_FL_RW;
765 764
766 765 mutex_enter(&udf_vfsp->udf_lock);
767 766 ud_sbwrite(udf_vfsp);
768 767 mutex_exit(&udf_vfsp->udf_lock);
769 768 remountout:
770 769 if (tpt != NULL) {
771 770 tpt->b_flags = B_AGE | B_STALE;
772 771 brelse(tpt);
773 772 }
774 773 return (error);
775 774 }
776 775
777 776 ASSERT(devvp != 0);
778 777 /*
779 778 * Flush back any dirty pages on the block device to
780 779 * try and keep the buffer cache in sync with the page
781 780 * cache if someone is trying to use block devices when
782 781 * they really should be using the raw device.
783 782 */
784 783 (void) VOP_PUTPAGE(common_specvp(devvp), (offset_t)0,
785 784 (uint32_t)0, B_INVAL, cr, NULL);
786 785
787 786
788 787 /*
789 788 * Check if the file system
790 789 * is a valid udfs and fill
791 790 * the required fields in udf_vfs
792 791 */
793 792 #ifndef __lint
794 793 _NOTE(NO_COMPETING_THREADS_NOW);
795 794 #endif
796 795
797 796 if ((lbsize = ud_get_lbsize(dev, &avd_loc)) == 0) {
798 797 error = EINVAL;
799 798 goto out;
800 799 }
801 800
802 801 udf_vfsp = ud_validate_and_fill_superblock(dev, lbsize, avd_loc);
803 802 if (udf_vfsp == NULL) {
804 803 error = EINVAL;
805 804 goto out;
806 805 }
807 806
808 807 /*
809 808 * Fill in vfs private data
810 809 */
811 810 vfsp->vfs_fstype = udf_fstype;
812 811 vfs_make_fsid(&vfsp->vfs_fsid, dev, udf_fstype);
813 812 vfsp->vfs_data = (caddr_t)udf_vfsp;
814 813 vfsp->vfs_dev = dev;
815 814 vfsp->vfs_flag |= VFS_NOTRUNC;
816 815 udf_vfsp->udf_devvp = devvp;
817 816
818 817 udf_vfsp->udf_fsmnt = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
819 818 (void) strcpy(udf_vfsp->udf_fsmnt, name);
820 819
821 820 udf_vfsp->udf_vfs = vfsp;
822 821 udf_vfsp->udf_rdclustsz = udf_vfsp->udf_wrclustsz = maxphys;
823 822
824 823 udf_vfsp->udf_mod = 0;
825 824
826 825
827 826 lvid = udf_vfsp->udf_lvid;
828 827 if (vfsp->vfs_flag & VFS_RDONLY) {
829 828 /*
830 829 * We could read only UDF1.50
831 830 * disallow mount of any highier version
832 831 */
833 832 if (udf_vfsp->udf_miread > UDF_150) {
834 833 error = EINVAL;
835 834 goto out;
836 835 }
837 836 udf_vfsp->udf_flags = UDF_FL_RDONLY;
838 837 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
839 838 udf_vfsp->udf_clean = UDF_CLEAN;
840 839 } else {
841 840 /* Do we have a VAT at the end of the recorded media */
842 841 map = udf_vfsp->udf_maps;
843 842 for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
844 843 if (map->udm_flags & UDM_MAP_VPM) {
845 844 break;
846 845 }
847 846 map++;
848 847 }
849 848 if (i == udf_vfsp->udf_nmaps) {
850 849 error = ENOSPC;
851 850 goto out;
852 851 }
853 852 udf_vfsp->udf_clean = UDF_CLEAN;
854 853 }
855 854 } else {
856 855 /*
857 856 * We could read UDF1.50 and write UDF1.50 only
858 857 * disallow mount of any highier version
859 858 */
860 859 if ((udf_vfsp->udf_miread > UDF_150) ||
861 860 (udf_vfsp->udf_miwrite > UDF_150)) {
862 861 error = EINVAL;
863 862 goto out;
864 863 }
865 864 /*
866 865 * Check if the media allows
867 866 * us to mount read/write
868 867 */
869 868 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
870 869 error = EACCES;
871 870 goto out;
872 871 }
873 872
874 873 /*
875 874 * Check if we have VAT on a writable media
876 875 * we cannot use the media in presence of VAT
877 876 * Dent RW mount.
878 877 */
879 878 map = udf_vfsp->udf_maps;
880 879 ASSERT(map != NULL);
881 880 for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
882 881 if (map->udm_flags & UDM_MAP_VPM) {
883 882 error = EACCES;
884 883 goto out;
885 884 }
886 885 map++;
887 886 }
888 887
889 888 /*
890 889 * Check if the domain Id allows
891 890 * us to write
892 891 */
893 892 if (udf_vfsp->udf_lvd->lvd_dom_id.reg_ids[2] & 0x3) {
894 893 error = EACCES;
895 894 goto out;
896 895 }
897 896 udf_vfsp->udf_flags = UDF_FL_RW;
898 897
899 898 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
900 899 udf_vfsp->udf_clean = UDF_CLEAN;
901 900 } else {
902 901 if (isroot) {
903 902 udf_vfsp->udf_clean = UDF_DIRTY;
904 903 } else {
905 904 error = ENOSPC;
906 905 goto out;
907 906 }
908 907 }
909 908 }
910 909
911 910 mutex_init(&udf_vfsp->udf_lock, NULL, MUTEX_DEFAULT, NULL);
912 911
913 912 mutex_init(&udf_vfsp->udf_rename_lck, NULL, MUTEX_DEFAULT, NULL);
914 913
915 914 #ifndef __lint
916 915 _NOTE(COMPETING_THREADS_NOW);
917 916 #endif
918 917 if (error = ud_iget(vfsp, udf_vfsp->udf_ricb_prn,
919 918 udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) {
920 919 mutex_destroy(&udf_vfsp->udf_lock);
921 920 goto out;
922 921 }
923 922
924 923
925 924 /*
926 925 * Get the root inode and
927 926 * initialize the root vnode
928 927 */
929 928 rvp = ITOV(rip);
930 929 mutex_enter(&rvp->v_lock);
931 930 rvp->v_flag |= VROOT;
932 931 mutex_exit(&rvp->v_lock);
933 932 udf_vfsp->udf_root = rvp;
934 933
935 934
936 935 if (why == ROOT_INIT && isroot)
937 936 rootvp = devvp;
938 937
939 938 ud_vfs_add(udf_vfsp);
940 939
941 940 if (udf_vfsp->udf_flags == UDF_FL_RW) {
942 941 udf_vfsp->udf_clean = UDF_DIRTY;
943 942 ud_update_superblock(vfsp);
944 943 }
945 944
946 945 return (0);
947 946
948 947 out:
949 948 ud_destroy_fsp(udf_vfsp);
950 949 if (needclose) {
951 950 (void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ?
952 951 FREAD : FREAD|FWRITE, 1, (offset_t)0, cr, NULL);
953 952 bflush(dev);
954 953 binval(dev);
955 954 }
956 955 VN_RELE(devvp);
957 956
958 957 return (error);
959 958 }
960 959
961 960
962 961 static struct udf_vfs *
963 962 ud_validate_and_fill_superblock(dev_t dev, int32_t bsize, uint32_t avd_loc)
964 963 {
965 964 int32_t error, count, index, shift;
966 965 uint32_t dummy, vds_loc;
967 966 caddr_t addr;
968 967 daddr_t blkno, lblkno;
969 968 struct buf *secbp, *bp;
970 969 struct tag *ttag;
971 970 struct anch_vol_desc_ptr *avdp;
972 971 struct file_set_desc *fsd;
973 972 struct udf_vfs *udf_vfsp = NULL;
974 973 struct pmap_hdr *hdr;
975 974 struct pmap_typ1 *typ1;
976 975 struct pmap_typ2 *typ2;
977 976 struct ud_map *map;
978 977 int32_t desc_len;
979 978
980 979 ud_printf("ud_validate_and_fill_superblock\n");
981 980
982 981 if (bsize < DEV_BSIZE) {
983 982 return (NULL);
984 983 }
985 984 shift = 0;
986 985 while ((bsize >> shift) > DEV_BSIZE) {
987 986 shift++;
988 987 }
989 988
990 989 /*
991 990 * Read Anchor Volume Descriptor
992 991 * Verify it and get the location of
993 992 * Main Volume Descriptor Sequence
994 993 */
995 994 secbp = ud_bread(dev, avd_loc << shift, ANCHOR_VOL_DESC_LEN);
996 995 if ((error = geterror(secbp)) != 0) {
997 996 cmn_err(CE_NOTE, "udfs : Could not read Anchor Volume Desc %x",
998 997 error);
999 998 brelse(secbp);
1000 999 return (NULL);
1001 1000 }
1002 1001 avdp = (struct anch_vol_desc_ptr *)secbp->b_un.b_addr;
1003 1002 if (ud_verify_tag_and_desc(&avdp->avd_tag, UD_ANCH_VOL_DESC,
1004 1003 avd_loc, 1, ANCHOR_VOL_DESC_LEN) != 0) {
1005 1004 brelse(secbp);
1006 1005 return (NULL);
1007 1006 }
1008 1007 udf_vfsp = (struct udf_vfs *)
1009 1008 kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP);
1010 1009 udf_vfsp->udf_mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc);
1011 1010 udf_vfsp->udf_mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len);
1012 1011 udf_vfsp->udf_rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc);
1013 1012 udf_vfsp->udf_rvds_len = SWAP_32(avdp->avd_res_vdse.ext_len);
1014 1013 secbp->b_flags = B_AGE | B_STALE;
1015 1014 brelse(secbp);
1016 1015
1017 1016 /*
1018 1017 * Read Main Volume Descriptor Sequence
1019 1018 * and process it
1020 1019 */
1021 1020 vds_loc = udf_vfsp->udf_mvds_loc;
1022 1021 secbp = ud_bread(dev, vds_loc << shift,
1023 1022 udf_vfsp->udf_mvds_len);
1024 1023 if ((error = geterror(secbp)) != 0) {
1025 1024 brelse(secbp);
1026 1025 cmn_err(CE_NOTE, "udfs : Could not read Main Volume Desc %x",
1027 1026 error);
1028 1027
1029 1028 vds_loc = udf_vfsp->udf_rvds_loc;
1030 1029 secbp = ud_bread(dev, vds_loc << shift,
1031 1030 udf_vfsp->udf_rvds_len);
1032 1031 if ((error = geterror(secbp)) != 0) {
1033 1032 brelse(secbp);
1034 1033 cmn_err(CE_NOTE,
1035 1034 "udfs : Could not read Res Volume Desc %x", error);
1036 1035 return (NULL);
1037 1036 }
1038 1037 }
1039 1038
1040 1039 udf_vfsp->udf_vds = ngeteblk(udf_vfsp->udf_mvds_len);
1041 1040 bp = udf_vfsp->udf_vds;
1042 1041 bp->b_edev = dev;
1043 1042 bp->b_dev = cmpdev(dev);
1044 1043 bp->b_blkno = vds_loc << shift;
1045 1044 bp->b_bcount = udf_vfsp->udf_mvds_len;
1046 1045 bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_mvds_len);
1047 1046 secbp->b_flags |= B_STALE | B_AGE;
1048 1047 brelse(secbp);
1049 1048
1050 1049
1051 1050 count = udf_vfsp->udf_mvds_len / DEV_BSIZE;
1052 1051 addr = bp->b_un.b_addr;
1053 1052 for (index = 0; index < count; index ++) {
1054 1053 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1055 1054 desc_len = udf_vfsp->udf_mvds_len - (index * DEV_BSIZE);
1056 1055 if (ud_verify_tag_and_desc(ttag, UD_PRI_VOL_DESC,
1057 1056 vds_loc + (index >> shift),
1058 1057 1, desc_len) == 0) {
1059 1058 if (udf_vfsp->udf_pvd == NULL) {
1060 1059 udf_vfsp->udf_pvd =
1061 1060 (struct pri_vol_desc *)ttag;
1062 1061 } else {
1063 1062 struct pri_vol_desc *opvd, *npvd;
1064 1063
1065 1064 opvd = udf_vfsp->udf_pvd;
1066 1065 npvd = (struct pri_vol_desc *)ttag;
1067 1066
1068 1067 if ((strncmp(opvd->pvd_vsi,
1069 1068 npvd->pvd_vsi, 128) == 0) &&
1070 1069 (strncmp(opvd->pvd_vol_id,
1071 1070 npvd->pvd_vol_id, 32) == 0) &&
1072 1071 (strncmp((caddr_t)&opvd->pvd_desc_cs,
1073 1072 (caddr_t)&npvd->pvd_desc_cs,
1074 1073 sizeof (charspec_t)) == 0)) {
1075 1074
1076 1075 if (SWAP_32(opvd->pvd_vdsn) <
1077 1076 SWAP_32(npvd->pvd_vdsn)) {
1078 1077 udf_vfsp->udf_pvd = npvd;
1079 1078 }
1080 1079 } else {
1081 1080 goto out;
1082 1081 }
1083 1082 }
1084 1083 } else if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_DESC,
1085 1084 vds_loc + (index >> shift),
1086 1085 1, desc_len) == 0) {
1087 1086 struct log_vol_desc *lvd;
1088 1087
1089 1088 lvd = (struct log_vol_desc *)ttag;
1090 1089 if (strncmp(lvd->lvd_dom_id.reg_id,
1091 1090 UDF_DOMAIN_NAME, 23) != 0) {
1092 1091 printf("Domain ID in lvd is not valid\n");
1093 1092 goto out;
1094 1093 }
1095 1094
1096 1095 if (udf_vfsp->udf_lvd == NULL) {
1097 1096 udf_vfsp->udf_lvd = lvd;
1098 1097 } else {
1099 1098 struct log_vol_desc *olvd;
1100 1099
1101 1100 olvd = udf_vfsp->udf_lvd;
1102 1101 if ((strncmp((caddr_t)&olvd->lvd_desc_cs,
1103 1102 (caddr_t)&lvd->lvd_desc_cs,
1104 1103 sizeof (charspec_t)) == 0) &&
1105 1104 (strncmp(olvd->lvd_lvid,
1106 1105 lvd->lvd_lvid, 128) == 0)) {
1107 1106 if (SWAP_32(olvd->lvd_vdsn) <
1108 1107 SWAP_32(lvd->lvd_vdsn)) {
1109 1108 udf_vfsp->udf_lvd = lvd;
1110 1109 }
1111 1110 } else {
1112 1111 goto out;
1113 1112 }
1114 1113 }
1115 1114 } else if (ud_verify_tag_and_desc(ttag, UD_PART_DESC,
1116 1115 vds_loc + (index >> shift),
1117 1116 1, desc_len) == 0) {
1118 1117 int32_t i;
1119 1118 struct phdr_desc *hdr;
1120 1119 struct part_desc *pdesc;
1121 1120 struct ud_part *pnew, *pold, *part;
1122 1121
1123 1122 pdesc = (struct part_desc *)ttag;
1124 1123 pold = udf_vfsp->udf_parts;
1125 1124 for (i = 0; i < udf_vfsp->udf_npart; i++) {
1126 1125 if (pold->udp_number !=
1127 1126 SWAP_16(pdesc->pd_pnum)) {
1128 1127 pold++;
1129 1128 continue;
1130 1129 }
1131 1130
1132 1131 if (SWAP_32(pdesc->pd_vdsn) >
1133 1132 pold->udp_seqno) {
1134 1133 pold->udp_seqno =
1135 1134 SWAP_32(pdesc->pd_vdsn);
1136 1135 pold->udp_access =
1137 1136 SWAP_32(pdesc->pd_acc_type);
1138 1137 pold->udp_start =
1139 1138 SWAP_32(pdesc->pd_part_start);
1140 1139 pold->udp_length =
1141 1140 SWAP_32(pdesc->pd_part_length);
1142 1141 }
1143 1142 goto loop_end;
1144 1143 }
1145 1144 pold = udf_vfsp->udf_parts;
1146 1145 udf_vfsp->udf_npart++;
1147 1146 pnew = kmem_zalloc(udf_vfsp->udf_npart *
1148 1147 sizeof (struct ud_part), KM_SLEEP);
1149 1148 udf_vfsp->udf_parts = pnew;
1150 1149 if (pold) {
1151 1150 bcopy(pold, pnew,
1152 1151 sizeof (struct ud_part) *
1153 1152 (udf_vfsp->udf_npart - 1));
1154 1153 kmem_free(pold,
1155 1154 sizeof (struct ud_part) *
1156 1155 (udf_vfsp->udf_npart - 1));
1157 1156 }
1158 1157 part = pnew + (udf_vfsp->udf_npart - 1);
1159 1158 part->udp_number = SWAP_16(pdesc->pd_pnum);
1160 1159 part->udp_seqno = SWAP_32(pdesc->pd_vdsn);
1161 1160 part->udp_access = SWAP_32(pdesc->pd_acc_type);
1162 1161 part->udp_start = SWAP_32(pdesc->pd_part_start);
1163 1162 part->udp_length = SWAP_32(pdesc->pd_part_length);
1164 1163 part->udp_last_alloc = 0;
1165 1164
1166 1165 /*
1167 1166 * Figure out space bitmaps
1168 1167 * or space tables
1169 1168 */
1170 1169 hdr = (struct phdr_desc *)pdesc->pd_pc_use;
1171 1170 if (hdr->phdr_ust.sad_ext_len) {
1172 1171 part->udp_flags = UDP_SPACETBLS;
1173 1172 part->udp_unall_loc =
1174 1173 SWAP_32(hdr->phdr_ust.sad_ext_loc);
1175 1174 part->udp_unall_len =
1176 1175 SWAP_32(hdr->phdr_ust.sad_ext_len);
1177 1176 part->udp_freed_loc =
1178 1177 SWAP_32(hdr->phdr_fst.sad_ext_loc);
1179 1178 part->udp_freed_len =
1180 1179 SWAP_32(hdr->phdr_fst.sad_ext_len);
1181 1180 } else {
1182 1181 part->udp_flags = UDP_BITMAPS;
1183 1182 part->udp_unall_loc =
1184 1183 SWAP_32(hdr->phdr_usb.sad_ext_loc);
1185 1184 part->udp_unall_len =
1186 1185 SWAP_32(hdr->phdr_usb.sad_ext_len);
1187 1186 part->udp_freed_loc =
1188 1187 SWAP_32(hdr->phdr_fsb.sad_ext_loc);
1189 1188 part->udp_freed_len =
1190 1189 SWAP_32(hdr->phdr_fsb.sad_ext_len);
1191 1190 }
1192 1191 } else if (ud_verify_tag_and_desc(ttag, UD_TERM_DESC,
1193 1192 vds_loc + (index >> shift),
1194 1193 1, desc_len) == 0) {
1195 1194
1196 1195 break;
1197 1196 }
1198 1197 loop_end:
1199 1198 ;
1200 1199 }
1201 1200 if ((udf_vfsp->udf_pvd == NULL) ||
1202 1201 (udf_vfsp->udf_lvd == NULL) ||
1203 1202 (udf_vfsp->udf_parts == NULL)) {
1204 1203 goto out;
1205 1204 }
1206 1205
1207 1206 /*
1208 1207 * Process Primary Volume Descriptor
1209 1208 */
1210 1209 (void) strncpy(udf_vfsp->udf_volid, udf_vfsp->udf_pvd->pvd_vol_id, 32);
1211 1210 udf_vfsp->udf_volid[31] = '\0';
1212 1211 udf_vfsp->udf_tsno = SWAP_16(udf_vfsp->udf_pvd->pvd_tag.tag_sno);
1213 1212
1214 1213 /*
1215 1214 * Process Logical Volume Descriptor
1216 1215 */
1217 1216 udf_vfsp->udf_lbsize =
1218 1217 SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize);
1219 1218 udf_vfsp->udf_lbmask = udf_vfsp->udf_lbsize - 1;
1220 1219 udf_vfsp->udf_l2d_shift = shift;
1221 1220 udf_vfsp->udf_l2b_shift = shift + DEV_BSHIFT;
1222 1221
1223 1222 /*
1224 1223 * Check if the media is in
1225 1224 * proper domain.
1226 1225 */
1227 1226 if (strcmp(udf_vfsp->udf_lvd->lvd_dom_id.reg_id,
1228 1227 UDF_DOMAIN_NAME) != 0) {
1229 1228 goto out;
1230 1229 }
1231 1230
1232 1231 /*
1233 1232 * AVDS offset does not match with the lbsize
1234 1233 * in the lvd
1235 1234 */
1236 1235 if (udf_vfsp->udf_lbsize != bsize) {
1237 1236 goto out;
1238 1237 }
1239 1238
1240 1239 udf_vfsp->udf_iseq_loc =
1241 1240 SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc);
1242 1241 udf_vfsp->udf_iseq_len =
1243 1242 SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len);
1244 1243
1245 1244 udf_vfsp->udf_fsd_prn =
1246 1245 SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn);
1247 1246 udf_vfsp->udf_fsd_loc =
1248 1247 SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc);
1249 1248 udf_vfsp->udf_fsd_len =
1250 1249 SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len);
1251 1250
1252 1251
1253 1252 /*
1254 1253 * process paritions
1255 1254 */
1256 1255 udf_vfsp->udf_mtype = udf_vfsp->udf_parts[0].udp_access;
1257 1256 for (index = 0; index < udf_vfsp->udf_npart; index ++) {
1258 1257 if (udf_vfsp->udf_parts[index].udp_access <
1259 1258 udf_vfsp->udf_mtype) {
1260 1259 udf_vfsp->udf_mtype =
1261 1260 udf_vfsp->udf_parts[index].udp_access;
1262 1261 }
1263 1262 }
1264 1263 if ((udf_vfsp->udf_mtype < UDF_MT_RO) ||
1265 1264 (udf_vfsp->udf_mtype > UDF_MT_OW)) {
1266 1265 udf_vfsp->udf_mtype = UDF_MT_RO;
1267 1266 }
1268 1267
1269 1268 udf_vfsp->udf_nmaps = 0;
1270 1269 hdr = (struct pmap_hdr *)udf_vfsp->udf_lvd->lvd_pmaps;
1271 1270 count = SWAP_32(udf_vfsp->udf_lvd->lvd_num_pmaps);
1272 1271 for (index = 0; index < count; index++) {
1273 1272
1274 1273 if ((hdr->maph_type == MAP_TYPE1) &&
1275 1274 (hdr->maph_length == MAP_TYPE1_LEN)) {
1276 1275 typ1 = (struct pmap_typ1 *)hdr;
1277 1276
1278 1277 map = udf_vfsp->udf_maps;
1279 1278 udf_vfsp->udf_maps =
1280 1279 kmem_zalloc(sizeof (struct ud_map) *
1281 1280 (udf_vfsp->udf_nmaps + 1), KM_SLEEP);
1282 1281 if (map != NULL) {
1283 1282 bcopy(map, udf_vfsp->udf_maps,
1284 1283 sizeof (struct ud_map) *
1285 1284 udf_vfsp->udf_nmaps);
1286 1285 kmem_free(map, sizeof (struct ud_map) *
1287 1286 udf_vfsp->udf_nmaps);
1288 1287 }
1289 1288 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1290 1289 map->udm_flags = UDM_MAP_NORM;
1291 1290 map->udm_vsn = SWAP_16(typ1->map1_vsn);
1292 1291 map->udm_pn = SWAP_16(typ1->map1_pn);
1293 1292 udf_vfsp->udf_nmaps ++;
1294 1293 } else if ((hdr->maph_type == MAP_TYPE2) &&
1295 1294 (hdr->maph_length == MAP_TYPE2_LEN)) {
1296 1295 typ2 = (struct pmap_typ2 *)hdr;
1297 1296
1298 1297 if (strncmp(typ2->map2_pti.reg_id,
1299 1298 UDF_VIRT_PART, 23) == 0) {
1300 1299 /*
1301 1300 * Add this to the normal
1302 1301 * partition table so that
1303 1302 * we donot
1304 1303 */
1305 1304 map = udf_vfsp->udf_maps;
1306 1305 udf_vfsp->udf_maps =
1307 1306 kmem_zalloc(sizeof (struct ud_map) *
1308 1307 (udf_vfsp->udf_nmaps + 1), KM_SLEEP);
1309 1308 if (map != NULL) {
1310 1309 bcopy(map, udf_vfsp->udf_maps,
1311 1310 sizeof (struct ud_map) *
1312 1311 udf_vfsp->udf_nmaps);
1313 1312 kmem_free(map,
1314 1313 sizeof (struct ud_map) *
1315 1314 udf_vfsp->udf_nmaps);
1316 1315 }
1317 1316 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1318 1317 map->udm_flags = UDM_MAP_VPM;
1319 1318 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1320 1319 map->udm_pn = SWAP_16(typ2->map2_pn);
1321 1320 udf_vfsp->udf_nmaps ++;
1322 1321 if (error = ud_get_last_block(dev, &lblkno)) {
1323 1322 goto out;
1324 1323 }
1325 1324 if (error = ud_val_get_vat(udf_vfsp, dev,
1326 1325 lblkno, map)) {
1327 1326 goto out;
1328 1327 }
1329 1328 } else if (strncmp(typ2->map2_pti.reg_id,
1330 1329 UDF_SPAR_PART, 23) == 0) {
1331 1330
1332 1331 if (SWAP_16(typ2->map2_pl) != 32) {
1333 1332 printf(
1334 1333 "Packet Length is not valid %x\n",
1335 1334 SWAP_16(typ2->map2_pl));
1336 1335 goto out;
1337 1336 }
1338 1337 if ((typ2->map2_nst < 1) ||
1339 1338 (typ2->map2_nst > 4)) {
1340 1339 goto out;
1341 1340 }
1342 1341 map = udf_vfsp->udf_maps;
1343 1342 udf_vfsp->udf_maps =
1344 1343 kmem_zalloc(sizeof (struct ud_map) *
1345 1344 (udf_vfsp->udf_nmaps + 1),
1346 1345 KM_SLEEP);
1347 1346 if (map != NULL) {
1348 1347 bcopy(map, udf_vfsp->udf_maps,
1349 1348 sizeof (struct ud_map) *
1350 1349 udf_vfsp->udf_nmaps);
1351 1350 kmem_free(map,
1352 1351 sizeof (struct ud_map) *
1353 1352 udf_vfsp->udf_nmaps);
1354 1353 }
1355 1354 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1356 1355 map->udm_flags = UDM_MAP_SPM;
1357 1356 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1358 1357 map->udm_pn = SWAP_16(typ2->map2_pn);
1359 1358
1360 1359 udf_vfsp->udf_nmaps ++;
1361 1360
1362 1361 if (error = ud_read_sparing_tbls(udf_vfsp,
1363 1362 dev, map, typ2)) {
1364 1363 goto out;
1365 1364 }
1366 1365 } else {
1367 1366 /*
1368 1367 * Unknown type of partition
1369 1368 * Bail out
1370 1369 */
1371 1370 goto out;
1372 1371 }
1373 1372 } else {
1374 1373 /*
1375 1374 * Unknown type of partition
1376 1375 * Bail out
1377 1376 */
1378 1377 goto out;
1379 1378 }
1380 1379 hdr = (struct pmap_hdr *)(((uint8_t *)hdr) + hdr->maph_length);
1381 1380 }
1382 1381
1383 1382
1384 1383 /*
1385 1384 * Read Logical Volume Integrity Sequence
1386 1385 * and process it
1387 1386 */
1388 1387 secbp = ud_bread(dev, udf_vfsp->udf_iseq_loc << shift,
1389 1388 udf_vfsp->udf_iseq_len);
1390 1389 if ((error = geterror(secbp)) != 0) {
1391 1390 cmn_err(CE_NOTE,
1392 1391 "udfs : Could not read Logical Volume Integrity Sequence %x",
1393 1392 error);
1394 1393 brelse(secbp);
1395 1394 goto out;
1396 1395 }
1397 1396 udf_vfsp->udf_iseq = ngeteblk(udf_vfsp->udf_iseq_len);
1398 1397 bp = udf_vfsp->udf_iseq;
1399 1398 bp->b_edev = dev;
1400 1399 bp->b_dev = cmpdev(dev);
1401 1400 bp->b_blkno = udf_vfsp->udf_iseq_loc << shift;
1402 1401 bp->b_bcount = udf_vfsp->udf_iseq_len;
1403 1402 bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_iseq_len);
1404 1403 secbp->b_flags |= B_STALE | B_AGE;
1405 1404 brelse(secbp);
1406 1405
1407 1406 count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
1408 1407 addr = bp->b_un.b_addr;
1409 1408 for (index = 0; index < count; index ++) {
1410 1409 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1411 1410 desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
1412 1411 if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
1413 1412 udf_vfsp->udf_iseq_loc + (index >> shift),
1414 1413 1, desc_len) == 0) {
1415 1414
1416 1415 struct log_vol_int_desc *lvid;
1417 1416
1418 1417 lvid = (struct log_vol_int_desc *)ttag;
1419 1418 udf_vfsp->udf_lvid = lvid;
1420 1419
1421 1420 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
1422 1421 udf_vfsp->udf_clean = UDF_CLEAN;
1423 1422 } else {
1424 1423 udf_vfsp->udf_clean = UDF_DIRTY;
1425 1424 }
1426 1425
1427 1426 /*
1428 1427 * update superblock with the metadata
1429 1428 */
1430 1429 ud_convert_to_superblock(udf_vfsp, lvid);
1431 1430 break;
1432 1431 }
1433 1432 }
1434 1433
1435 1434 if (udf_vfsp->udf_lvid == NULL) {
1436 1435 goto out;
1437 1436 }
1438 1437
1439 1438 if ((blkno = ud_xlate_to_daddr(udf_vfsp,
1440 1439 udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc,
1441 1440 1, &dummy)) == 0) {
1442 1441 goto out;
1443 1442 }
1444 1443 secbp = ud_bread(dev, blkno << shift, udf_vfsp->udf_fsd_len);
1445 1444 if ((error = geterror(secbp)) != 0) {
1446 1445 cmn_err(CE_NOTE,
1447 1446 "udfs : Could not read File Set Descriptor %x", error);
1448 1447 brelse(secbp);
1449 1448 goto out;
1450 1449 }
1451 1450 fsd = (struct file_set_desc *)secbp->b_un.b_addr;
1452 1451 if (ud_verify_tag_and_desc(&fsd->fsd_tag, UD_FILE_SET_DESC,
1453 1452 udf_vfsp->udf_fsd_loc,
1454 1453 1, udf_vfsp->udf_fsd_len) != 0) {
1455 1454 secbp->b_flags = B_AGE | B_STALE;
1456 1455 brelse(secbp);
1457 1456 goto out;
1458 1457 }
1459 1458 udf_vfsp->udf_ricb_prn = SWAP_16(fsd->fsd_root_icb.lad_ext_prn);
1460 1459 udf_vfsp->udf_ricb_loc = SWAP_32(fsd->fsd_root_icb.lad_ext_loc);
1461 1460 udf_vfsp->udf_ricb_len = SWAP_32(fsd->fsd_root_icb.lad_ext_len);
1462 1461 secbp->b_flags = B_AGE | B_STALE;
1463 1462 brelse(secbp);
1464 1463 udf_vfsp->udf_root_blkno = ud_xlate_to_daddr(udf_vfsp,
1465 1464 udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc,
1466 1465 1, &dummy);
1467 1466
1468 1467 return (udf_vfsp);
1469 1468 out:
1470 1469 ud_destroy_fsp(udf_vfsp);
1471 1470
1472 1471 return (NULL);
1473 1472 }
1474 1473
1475 1474 /*
1476 1475 * release/free resources from one ud_map; map data was zalloc'd in
1477 1476 * ud_validate_and_fill_superblock() and fields may later point to
1478 1477 * valid data
1479 1478 */
1480 1479 static void
1481 1480 ud_free_map(struct ud_map *map)
1482 1481 {
1483 1482 uint32_t n;
1484 1483
1485 1484 if (map->udm_flags & UDM_MAP_VPM) {
1486 1485 if (map->udm_count) {
1487 1486 kmem_free(map->udm_count,
1488 1487 map->udm_nent * sizeof (*map->udm_count));
1489 1488 map->udm_count = NULL;
1490 1489 }
1491 1490 if (map->udm_bp) {
1492 1491 for (n = 0; n < map->udm_nent; n++) {
1493 1492 if (map->udm_bp[n])
1494 1493 brelse(map->udm_bp[n]);
1495 1494 }
1496 1495 kmem_free(map->udm_bp,
1497 1496 map->udm_nent * sizeof (*map->udm_bp));
1498 1497 map->udm_bp = NULL;
1499 1498 }
1500 1499 if (map->udm_addr) {
1501 1500 kmem_free(map->udm_addr,
1502 1501 map->udm_nent * sizeof (*map->udm_addr));
1503 1502 map->udm_addr = NULL;
1504 1503 }
1505 1504 }
1506 1505 if (map->udm_flags & UDM_MAP_SPM) {
1507 1506 for (n = 0; n < MAX_SPM; n++) {
1508 1507 if (map->udm_sbp[n]) {
1509 1508 brelse(map->udm_sbp[n]);
1510 1509 map->udm_sbp[n] = NULL;
1511 1510 map->udm_spaddr[n] = NULL;
1512 1511 }
1513 1512 }
1514 1513 }
1515 1514 }
1516 1515
1517 1516 void
1518 1517 ud_destroy_fsp(struct udf_vfs *udf_vfsp)
1519 1518 {
1520 1519 int32_t i;
1521 1520
1522 1521 ud_printf("ud_destroy_fsp\n");
1523 1522 if (udf_vfsp == NULL)
1524 1523 return;
1525 1524
1526 1525 if (udf_vfsp->udf_maps) {
1527 1526 for (i = 0; i < udf_vfsp->udf_nmaps; i++)
1528 1527 ud_free_map(&udf_vfsp->udf_maps[i]);
1529 1528
1530 1529 kmem_free(udf_vfsp->udf_maps,
1531 1530 udf_vfsp->udf_nmaps * sizeof (*udf_vfsp->udf_maps));
1532 1531 }
1533 1532
1534 1533 if (udf_vfsp->udf_parts) {
1535 1534 kmem_free(udf_vfsp->udf_parts,
1536 1535 udf_vfsp->udf_npart * sizeof (*udf_vfsp->udf_parts));
1537 1536 }
1538 1537 if (udf_vfsp->udf_iseq) {
1539 1538 udf_vfsp->udf_iseq->b_flags |= (B_STALE|B_AGE);
1540 1539 brelse(udf_vfsp->udf_iseq);
1541 1540 }
1542 1541 if (udf_vfsp->udf_vds) {
1543 1542 udf_vfsp->udf_vds->b_flags |= (B_STALE|B_AGE);
1544 1543 brelse(udf_vfsp->udf_vds);
1545 1544 }
1546 1545 if (udf_vfsp->udf_vfs)
↓ open down ↓ |
919 lines elided |
↑ open up ↑ |
1547 1546 ud_vfs_remove(udf_vfsp);
1548 1547 if (udf_vfsp->udf_fsmnt) {
1549 1548 kmem_free(udf_vfsp->udf_fsmnt,
1550 1549 strlen(udf_vfsp->udf_fsmnt) + 1);
1551 1550 }
1552 1551 kmem_free(udf_vfsp, sizeof (*udf_vfsp));
1553 1552 }
1554 1553
1555 1554 void
1556 1555 ud_convert_to_superblock(struct udf_vfs *udf_vfsp,
1557 - struct log_vol_int_desc *lvid)
1556 + struct log_vol_int_desc *lvid)
1558 1557 {
1559 1558 int32_t i, c;
1560 1559 uint32_t *temp;
1561 1560 struct ud_part *ud_part;
1562 1561 struct lvid_iu *iu;
1563 1562
1564 1563 udf_vfsp->udf_maxuniq = SWAP_64(lvid->lvid_uniqid);
1565 1564 temp = lvid->lvid_fst;
1566 1565 c = SWAP_32(lvid->lvid_npart);
1567 1566 ud_part = udf_vfsp->udf_parts;
1568 1567 for (i = 0; i < c; i++) {
1569 1568 if (i >= udf_vfsp->udf_npart) {
1570 1569 continue;
1571 1570 }
1572 1571 ud_part->udp_nfree = SWAP_32(temp[i]);
1573 1572 ud_part->udp_nblocks = SWAP_32(temp[c + i]);
1574 1573 udf_vfsp->udf_freeblks += SWAP_32(temp[i]);
1575 1574 udf_vfsp->udf_totalblks += SWAP_32(temp[c + i]);
1576 1575 ud_part++;
1577 1576 }
1578 1577
1579 1578 iu = (struct lvid_iu *)(temp + c * 2);
1580 1579 udf_vfsp->udf_nfiles = SWAP_32(iu->lvidiu_nfiles);
1581 1580 udf_vfsp->udf_ndirs = SWAP_32(iu->lvidiu_ndirs);
1582 1581 udf_vfsp->udf_miread = BCD2HEX_16(SWAP_16(iu->lvidiu_mread));
1583 1582 udf_vfsp->udf_miwrite = BCD2HEX_16(SWAP_16(iu->lvidiu_mwrite));
1584 1583 udf_vfsp->udf_mawrite = BCD2HEX_16(SWAP_16(iu->lvidiu_maxwr));
1585 1584 }
1586 1585
1587 1586 void
1588 1587 ud_update_superblock(struct vfs *vfsp)
1589 1588 {
1590 1589 struct udf_vfs *udf_vfsp;
1591 1590
1592 1591 ud_printf("ud_update_superblock\n");
1593 1592
1594 1593 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1595 1594
1596 1595 mutex_enter(&udf_vfsp->udf_lock);
1597 1596 ud_sbwrite(udf_vfsp);
1598 1597 mutex_exit(&udf_vfsp->udf_lock);
1599 1598 }
1600 1599
1601 1600
1602 1601 #include <sys/dkio.h>
1603 1602 #include <sys/cdio.h>
1604 1603 #include <sys/vtoc.h>
1605 1604
1606 1605 /*
1607 1606 * This part of the code is known
1608 1607 * to work with only sparc. It needs
1609 1608 * to be evluated before using it with x86
1610 1609 */
1611 1610 int32_t
1612 1611 ud_get_last_block(dev_t dev, daddr_t *blkno)
1613 1612 {
1614 1613 struct vtoc vtoc;
1615 1614 struct dk_cinfo dki_info;
1616 1615 int32_t rval, error;
1617 1616
1618 1617 if ((error = cdev_ioctl(dev, DKIOCGVTOC, (intptr_t)&vtoc,
1619 1618 FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1620 1619 cmn_err(CE_NOTE, "Could not get the vtoc information");
1621 1620 return (error);
1622 1621 }
1623 1622
1624 1623 if (vtoc.v_sanity != VTOC_SANE) {
1625 1624 return (EINVAL);
1626 1625 }
1627 1626 if ((error = cdev_ioctl(dev, DKIOCINFO, (intptr_t)&dki_info,
1628 1627 FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1629 1628 cmn_err(CE_NOTE, "Could not get the slice information");
1630 1629 return (error);
1631 1630 }
1632 1631
1633 1632 if (dki_info.dki_partition > V_NUMPAR) {
1634 1633 return (EINVAL);
1635 1634 }
1636 1635
1637 1636
1638 1637 *blkno = vtoc.v_part[dki_info.dki_partition].p_size;
1639 1638
1640 1639 return (0);
1641 1640 }
1642 1641
1643 1642 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1644 1643 /*
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
1645 1644 * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1646 1645 */
1647 1646 int32_t ud_sub_blks[] = {152, 150, 2, 0};
1648 1647 int32_t ud_sub_count = 4;
1649 1648
1650 1649 /*
1651 1650 * Validate the VAT ICB
1652 1651 */
1653 1652 static int32_t
1654 1653 ud_val_get_vat(struct udf_vfs *udf_vfsp, dev_t dev,
1655 - daddr_t blkno, struct ud_map *udm)
1654 + daddr_t blkno, struct ud_map *udm)
1656 1655 {
1657 1656 struct buf *secbp;
1658 1657 struct file_entry *fe;
1659 1658 int32_t end_loc, i, j, ad_type;
1660 1659 struct short_ad *sad;
1661 1660 struct long_ad *lad;
1662 1661 uint32_t count, blk;
1663 1662 struct ud_part *ud_part;
1664 1663 int err = 0;
1665 1664
1666 1665 end_loc = (blkno >> udf_vfsp->udf_l2d_shift) - 1;
1667 1666
1668 1667 for (i = 0; i < ud_sub_count; i++) {
1669 1668 udm->udm_vat_icb = end_loc - ud_sub_blks[i];
1670 1669
1671 1670 secbp = ud_bread(dev,
1672 1671 udm->udm_vat_icb << udf_vfsp->udf_l2d_shift,
1673 1672 udf_vfsp->udf_lbsize);
1674 1673 ASSERT(secbp->b_un.b_addr);
1675 1674
1676 1675 fe = (struct file_entry *)secbp->b_un.b_addr;
1677 1676 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 0,
1678 1677 0, 0) == 0) {
1679 1678 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
1680 1679 SWAP_32(fe->fe_tag.tag_loc),
1681 1680 1, udf_vfsp->udf_lbsize) == 0) {
1682 1681 if (fe->fe_icb_tag.itag_ftype == 0) {
1683 1682 break;
1684 1683 }
1685 1684 }
1686 1685 }
1687 1686 secbp->b_flags |= B_AGE | B_STALE;
1688 1687 brelse(secbp);
1689 1688 }
1690 1689 if (i == ud_sub_count) {
1691 1690 return (EINVAL);
1692 1691 }
1693 1692
1694 1693 ad_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x3;
1695 1694 if (ad_type == ICB_FLAG_ONE_AD) {
1696 1695 udm->udm_nent = 1;
1697 1696 } else if (ad_type == ICB_FLAG_SHORT_AD) {
1698 1697 udm->udm_nent =
1699 1698 SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
1700 1699 } else if (ad_type == ICB_FLAG_LONG_AD) {
1701 1700 udm->udm_nent =
1702 1701 SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
1703 1702 } else {
1704 1703 err = EINVAL;
1705 1704 goto end;
1706 1705 }
1707 1706
1708 1707 udm->udm_count = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_count),
1709 1708 KM_SLEEP);
1710 1709 udm->udm_bp = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_bp),
1711 1710 KM_SLEEP);
1712 1711 udm->udm_addr = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_addr),
1713 1712 KM_SLEEP);
1714 1713
1715 1714 if (ad_type == ICB_FLAG_ONE_AD) {
1716 1715 udm->udm_count[0] = (SWAP_64(fe->fe_info_len) - 36) /
1717 1716 sizeof (uint32_t);
1718 1717 udm->udm_bp[0] = secbp;
1719 1718 udm->udm_addr[0] = (uint32_t *)
1720 1719 &fe->fe_spec[SWAP_32(fe->fe_len_ear)];
1721 1720 return (0);
1722 1721 }
1723 1722 for (i = 0; i < udm->udm_nent; i++) {
1724 1723 if (ad_type == ICB_FLAG_SHORT_AD) {
1725 1724 sad = (struct short_ad *)
1726 1725 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1727 1726 sad += i;
1728 1727 count = SWAP_32(sad->sad_ext_len);
1729 1728 blk = SWAP_32(sad->sad_ext_loc);
1730 1729 } else {
1731 1730 lad = (struct long_ad *)
1732 1731 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1733 1732 lad += i;
1734 1733 count = SWAP_32(lad->lad_ext_len);
1735 1734 blk = SWAP_32(lad->lad_ext_loc);
1736 1735 ASSERT(SWAP_16(lad->lad_ext_prn) == udm->udm_pn);
1737 1736 }
1738 1737 if ((count & 0x3FFFFFFF) == 0) {
1739 1738 break;
1740 1739 }
1741 1740 if (i < udm->udm_nent - 1) {
1742 1741 udm->udm_count[i] = count / 4;
1743 1742 } else {
1744 1743 udm->udm_count[i] = (count - 36) / 4;
1745 1744 }
1746 1745 ud_part = udf_vfsp->udf_parts;
1747 1746 for (j = 0; j < udf_vfsp->udf_npart; j++) {
1748 1747 if (udm->udm_pn == ud_part->udp_number) {
1749 1748 blk = ud_part->udp_start + blk;
1750 1749 break;
1751 1750 }
1752 1751 }
1753 1752 if (j == udf_vfsp->udf_npart) {
1754 1753 err = EINVAL;
1755 1754 break;
1756 1755 }
1757 1756
1758 1757 count = (count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1759 1758 udm->udm_bp[i] = ud_bread(dev,
1760 1759 blk << udf_vfsp->udf_l2d_shift, count);
1761 1760 if ((udm->udm_bp[i]->b_error != 0) ||
1762 1761 (udm->udm_bp[i]->b_resid)) {
1763 1762 err = EINVAL;
1764 1763 break;
1765 1764 }
1766 1765 udm->udm_addr[i] = (uint32_t *)udm->udm_bp[i]->b_un.b_addr;
1767 1766 }
1768 1767
↓ open down ↓ |
103 lines elided |
↑ open up ↑ |
1769 1768 end:
1770 1769 if (err)
1771 1770 ud_free_map(udm);
1772 1771 secbp->b_flags |= B_AGE | B_STALE;
1773 1772 brelse(secbp);
1774 1773 return (err);
1775 1774 }
1776 1775
1777 1776 int32_t
1778 1777 ud_read_sparing_tbls(struct udf_vfs *udf_vfsp,
1779 - dev_t dev, struct ud_map *map, struct pmap_typ2 *typ2)
1778 + dev_t dev, struct ud_map *map, struct pmap_typ2 *typ2)
1780 1779 {
1781 1780 int32_t index, valid = 0;
1782 1781 uint32_t sz;
1783 1782 struct buf *bp;
1784 1783 struct stbl *stbl;
1785 1784
1786 1785 map->udm_plen = SWAP_16(typ2->map2_pl);
1787 1786 map->udm_nspm = typ2->map2_nst;
1788 1787 map->udm_spsz = SWAP_32(typ2->map2_sest);
1789 1788 sz = (map->udm_spsz + udf_vfsp->udf_lbmask) & ~udf_vfsp->udf_lbmask;
1790 1789 if (sz == 0) {
1791 1790 return (0);
1792 1791 }
1793 1792
1794 1793 for (index = 0; index < map->udm_nspm; index++) {
1795 1794 map->udm_loc[index] = SWAP_32(typ2->map2_st[index]);
1796 1795
1797 1796 bp = ud_bread(dev,
1798 1797 map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz);
1799 1798 if ((bp->b_error != 0) || (bp->b_resid)) {
1800 1799 brelse(bp);
1801 1800 continue;
1802 1801 }
1803 1802 stbl = (struct stbl *)bp->b_un.b_addr;
1804 1803 if (strncmp(stbl->stbl_si.reg_id, UDF_SPAR_TBL, 23) != 0) {
1805 1804 printf("Sparing Identifier does not match\n");
1806 1805 bp->b_flags |= B_AGE | B_STALE;
1807 1806 brelse(bp);
1808 1807 continue;
1809 1808 }
1810 1809 map->udm_sbp[index] = bp;
1811 1810 map->udm_spaddr[index] = bp->b_un.b_addr;
1812 1811 #ifdef UNDEF
1813 1812 {
1814 1813 struct stbl_entry *te;
1815 1814 int32_t i, tbl_len;
1816 1815
1817 1816 te = (struct stbl_entry *)&stbl->stbl_entry;
1818 1817 tbl_len = SWAP_16(stbl->stbl_len);
1819 1818
1820 1819 printf("%x %x\n", tbl_len, SWAP_32(stbl->stbl_seqno));
1821 1820 printf("%x %x\n", bp->b_un.b_addr, te);
1822 1821
1823 1822 for (i = 0; i < tbl_len; i++) {
1824 1823 printf("%x %x\n", SWAP_32(te->sent_ol), SWAP_32(te->sent_ml));
1825 1824 te ++;
1826 1825 }
1827 1826 }
1828 1827 #endif
1829 1828 valid ++;
1830 1829 }
1831 1830
1832 1831 if (valid) {
1833 1832 return (0);
1834 1833 }
1835 1834 return (EINVAL);
1836 1835 }
1837 1836
1838 1837 uint32_t
1839 1838 ud_get_lbsize(dev_t dev, uint32_t *loc)
1840 1839 {
1841 1840 int32_t bsize, shift, index, end_index;
1842 1841 daddr_t last_block;
1843 1842 uint32_t avd_loc;
1844 1843 struct buf *bp;
1845 1844 struct anch_vol_desc_ptr *avdp;
1846 1845 uint32_t session_offset = 0;
1847 1846 int32_t rval;
1848 1847
1849 1848 if (ud_get_last_block(dev, &last_block) != 0) {
1850 1849 end_index = 1;
1851 1850 } else {
1852 1851 end_index = 3;
1853 1852 }
1854 1853
1855 1854 if (cdev_ioctl(dev, CDROMREADOFFSET, (intptr_t)&session_offset,
1856 1855 FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) {
1857 1856 session_offset = 0;
1858 1857 }
1859 1858
1860 1859 for (index = 0; index < end_index; index++) {
1861 1860
1862 1861 for (bsize = DEV_BSIZE, shift = 0;
1863 1862 bsize <= MAXBSIZE; bsize <<= 1, shift++) {
1864 1863
1865 1864 if (index == 0) {
1866 1865 avd_loc = 256;
1867 1866 if (bsize <= 2048) {
1868 1867 avd_loc +=
1869 1868 session_offset * 2048 / bsize;
1870 1869 } else {
1871 1870 avd_loc +=
1872 1871 session_offset / (bsize / 2048);
1873 1872 }
1874 1873 } else if (index == 1) {
1875 1874 avd_loc = last_block - (1 << shift);
1876 1875 } else {
1877 1876 avd_loc = last_block - (256 << shift);
1878 1877 }
1879 1878
1880 1879 bp = ud_bread(dev, avd_loc << shift,
1881 1880 ANCHOR_VOL_DESC_LEN);
1882 1881 if (geterror(bp) != 0) {
1883 1882 brelse(bp);
1884 1883 continue;
1885 1884 }
1886 1885
1887 1886 /*
1888 1887 * Verify if we have avdp here
1889 1888 */
1890 1889 avdp = (struct anch_vol_desc_ptr *)bp->b_un.b_addr;
1891 1890 if (ud_verify_tag_and_desc(&avdp->avd_tag,
1892 1891 UD_ANCH_VOL_DESC, avd_loc,
1893 1892 1, ANCHOR_VOL_DESC_LEN) != 0) {
1894 1893 bp->b_flags |= B_AGE | B_STALE;
1895 1894 brelse(bp);
1896 1895 continue;
1897 1896 }
1898 1897 bp->b_flags |= B_AGE | B_STALE;
1899 1898 brelse(bp);
1900 1899 *loc = avd_loc;
1901 1900 return (bsize);
1902 1901 }
1903 1902 }
1904 1903
1905 1904 /*
1906 1905 * Did not find AVD at all the locations
1907 1906 */
1908 1907 return (0);
1909 1908 }
1910 1909
1911 1910 static int
1912 1911 udfinit(int fstype, char *name)
1913 1912 {
1914 1913 static const fs_operation_def_t udf_vfsops_template[] = {
1915 1914 VFSNAME_MOUNT, { .vfs_mount = udf_mount },
1916 1915 VFSNAME_UNMOUNT, { .vfs_unmount = udf_unmount },
1917 1916 VFSNAME_ROOT, { .vfs_root = udf_root },
1918 1917 VFSNAME_STATVFS, { .vfs_statvfs = udf_statvfs },
1919 1918 VFSNAME_SYNC, { .vfs_sync = udf_sync },
1920 1919 VFSNAME_VGET, { .vfs_vget = udf_vget },
1921 1920 VFSNAME_MOUNTROOT, { .vfs_mountroot = udf_mountroot },
1922 1921 NULL, NULL
1923 1922 };
1924 1923 extern struct vnodeops *udf_vnodeops;
1925 1924 extern const fs_operation_def_t udf_vnodeops_template[];
1926 1925 int error;
1927 1926
1928 1927 ud_printf("udfinit\n");
1929 1928
1930 1929 error = vfs_setfsops(fstype, udf_vfsops_template, NULL);
1931 1930 if (error != 0) {
1932 1931 cmn_err(CE_WARN, "udfinit: bad vfs ops template");
1933 1932 return (error);
1934 1933 }
1935 1934
1936 1935 error = vn_make_ops(name, udf_vnodeops_template, &udf_vnodeops);
1937 1936 if (error != 0) {
1938 1937 (void) vfs_freevfsops_by_type(fstype);
1939 1938 cmn_err(CE_WARN, "udfinit: bad vnode ops template");
1940 1939 return (error);
1941 1940 }
1942 1941
1943 1942 udf_fstype = fstype;
1944 1943
1945 1944 ud_init_inodes();
1946 1945
1947 1946 return (0);
1948 1947 }
↓ open down ↓ |
159 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX