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