1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/types.h>
26 #include <sys/t_lock.h>
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/systm.h>
30 #include <sys/sysmacros.h>
31 #include <sys/resource.h>
32 #include <sys/signal.h>
33 #include <sys/cred.h>
34 #include <sys/user.h>
35 #include <sys/buf.h>
36 #include <sys/vfs.h>
37 #include <sys/stat.h>
38 #include <sys/vnode.h>
39 #include <sys/mode.h>
40 #include <sys/proc.h>
41 #include <sys/disp.h>
42 #include <sys/file.h>
43 #include <sys/fcntl.h>
44 #include <sys/flock.h>
45 #include <sys/kmem.h>
46 #include <sys/uio.h>
47 #include <sys/dnlc.h>
48 #include <sys/conf.h>
49 #include <sys/errno.h>
50 #include <sys/mman.h>
51 #include <sys/fbuf.h>
52 #include <sys/pathname.h>
53 #include <sys/debug.h>
54 #include <sys/vmsystm.h>
55 #include <sys/cmn_err.h>
56 #include <sys/dirent.h>
57 #include <sys/errno.h>
58 #include <sys/modctl.h>
59 #include <sys/statvfs.h>
60 #include <sys/mount.h>
61 #include <sys/sunddi.h>
62 #include <sys/bootconf.h>
63 #include <sys/policy.h>
64
65 #include <vm/hat.h>
66 #include <vm/page.h>
67 #include <vm/pvn.h>
68 #include <vm/as.h>
69 #include <vm/seg.h>
70 #include <vm/seg_map.h>
71 #include <vm/seg_kmem.h>
72 #include <vm/seg_vn.h>
73 #include <vm/rm.h>
74 #include <vm/page.h>
75 #include <sys/swap.h>
76
77
78 #include <fs/fs_subr.h>
79
80
81 #include <sys/fs/udf_volume.h>
82 #include <sys/fs/udf_inode.h>
83
84 extern struct vnodeops *udf_vnodeops;
85
86 kmutex_t ud_sync_busy;
87 /*
88 * udf_vfs list manipulation routines
89 */
90 kmutex_t udf_vfs_mutex;
91 struct udf_vfs *udf_vfs_instances;
92 #ifndef __lint
93 _NOTE(MUTEX_PROTECTS_DATA(udf_vfs_mutex, udf_vfs_instances))
94 #endif
95
96 union ihead ud_ihead[UD_HASH_SZ];
97 kmutex_t ud_icache_lock;
98
99 #define UD_BEGIN 0x0
100 #define UD_END 0x1
101 #define UD_UNKN 0x2
102 struct ud_inode *udf_ifreeh, *udf_ifreet;
103 kmutex_t udf_ifree_lock;
104 #ifndef __lint
105 _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreeh))
106 _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreet))
107 #endif
108
109 kmutex_t ud_nino_lock;
110 int32_t ud_max_inodes = 512;
111 int32_t ud_cur_inodes = 0;
112 #ifndef __lint
113 _NOTE(MUTEX_PROTECTS_DATA(ud_nino_lock, ud_cur_inodes))
114 #endif
115
116 uid_t ud_default_uid = 0;
117 gid_t ud_default_gid = 3;
118
119 int32_t ud_updat_ext4(struct ud_inode *, struct file_entry *);
120 int32_t ud_updat_ext4096(struct ud_inode *, struct file_entry *);
121 void ud_make_sad(struct icb_ext *, struct short_ad *, int32_t);
122 void ud_make_lad(struct icb_ext *, struct long_ad *, int32_t);
123 void ud_trunc_ext4(struct ud_inode *, u_offset_t);
124 void ud_trunc_ext4096(struct ud_inode *, u_offset_t);
125 void ud_add_to_free_list(struct ud_inode *, uint32_t);
126 void ud_remove_from_free_list(struct ud_inode *, uint32_t);
127
128
129 #ifdef DEBUG
130 struct ud_inode *
ud_search_icache(struct vfs * vfsp,uint16_t prn,uint32_t ploc)131 ud_search_icache(struct vfs *vfsp, uint16_t prn, uint32_t ploc)
132 {
133 int32_t hno;
134 union ihead *ih;
135 struct ud_inode *ip;
136 struct udf_vfs *udf_vfsp;
137 uint32_t loc, dummy;
138
139 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
140 loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy);
141
142 mutex_enter(&ud_icache_lock);
143 hno = UD_INOHASH(vfsp->vfs_dev, loc);
144 ih = &ud_ihead[hno];
145 for (ip = ih->ih_chain[0];
146 ip != (struct ud_inode *)ih;
147 ip = ip->i_forw) {
148 if ((prn == ip->i_icb_prn) && (ploc == ip->i_icb_block) &&
149 (vfsp->vfs_dev == ip->i_dev)) {
150 mutex_exit(&ud_icache_lock);
151 return (ip);
152 }
153 }
154 mutex_exit(&ud_icache_lock);
155 return (0);
156 }
157 #endif
158
159 /* ARGSUSED */
160 int
ud_iget(struct vfs * vfsp,uint16_t prn,uint32_t ploc,struct ud_inode ** ipp,struct buf * pbp,struct cred * cred)161 ud_iget(struct vfs *vfsp, uint16_t prn, uint32_t ploc,
162 struct ud_inode **ipp, struct buf *pbp, struct cred *cred)
163 {
164 int32_t hno, nomem = 0, icb_tag_flags;
165 union ihead *ih;
166 struct ud_inode *ip;
167 struct vnode *vp;
168 struct buf *bp = NULL;
169 struct file_entry *fe;
170 struct udf_vfs *udf_vfsp;
171 struct ext_attr_hdr *eah;
172 struct attr_hdr *ah;
173 int32_t ea_len, ea_off;
174 daddr_t loc;
175 uint64_t offset = 0;
176 struct icb_ext *iext, *con;
177 uint32_t length, dummy;
178 int32_t ndesc, ftype;
179 uint16_t old_prn;
180 uint32_t old_block, old_lbano;
181
182 ud_printf("ud_iget\n");
183 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
184 old_prn = 0;
185 old_block = old_lbano = 0;
186 ftype = 0;
187 loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy);
188 loop:
189 mutex_enter(&ud_icache_lock);
190 hno = UD_INOHASH(vfsp->vfs_dev, loc);
191
192 ih = &ud_ihead[hno];
193 for (ip = ih->ih_chain[0];
194 ip != (struct ud_inode *)ih;
195 ip = ip->i_forw) {
196
197 if ((prn == ip->i_icb_prn) &&
198 (ploc == ip->i_icb_block) &&
199 (vfsp->vfs_dev == ip->i_dev)) {
200
201 vp = ITOV(ip);
202 VN_HOLD(vp);
203 mutex_exit(&ud_icache_lock);
204
205 rw_enter(&ip->i_contents, RW_READER);
206 mutex_enter(&ip->i_tlock);
207 if ((ip->i_flag & IREF) == 0) {
208 mutex_enter(&udf_ifree_lock);
209 ud_remove_from_free_list(ip, UD_UNKN);
210 mutex_exit(&udf_ifree_lock);
211 }
212 ip->i_flag |= IREF;
213 mutex_exit(&ip->i_tlock);
214 rw_exit(&ip->i_contents);
215
216 *ipp = ip;
217
218 if (pbp != NULL) {
219 brelse(pbp);
220 }
221
222 return (0);
223 }
224 }
225
226 /*
227 * We don't have it in the cache
228 * Allocate a new entry
229 */
230 tryagain:
231 mutex_enter(&udf_ifree_lock);
232 mutex_enter(&ud_nino_lock);
233 if (ud_cur_inodes > ud_max_inodes) {
234 int32_t purged;
235
236 mutex_exit(&ud_nino_lock);
237 while (udf_ifreeh == NULL ||
238 vn_has_cached_data(ITOV(udf_ifreeh))) {
239 /*
240 * Try to put an inode on the freelist that's
241 * sitting in the dnlc.
242 */
243 mutex_exit(&udf_ifree_lock);
244 purged = dnlc_fs_purge1(udf_vnodeops);
245 mutex_enter(&udf_ifree_lock);
246 if (!purged) {
247 break;
248 }
249 }
250 mutex_enter(&ud_nino_lock);
251 }
252
253 /*
254 * If there's a free one available and it has no pages attached
255 * take it. If we're over the high water mark, take it even if
256 * it has attached pages. Otherwise, make a new one.
257 */
258 if (udf_ifreeh &&
259 (nomem || !vn_has_cached_data(ITOV(udf_ifreeh)) ||
260 ud_cur_inodes >= ud_max_inodes)) {
261
262 mutex_exit(&ud_nino_lock);
263 ip = udf_ifreeh;
264 vp = ITOV(ip);
265
266 ud_remove_from_free_list(ip, UD_BEGIN);
267
268 mutex_exit(&udf_ifree_lock);
269 if (ip->i_flag & IREF) {
270 cmn_err(CE_WARN, "ud_iget: bad i_flag\n");
271 mutex_exit(&ud_icache_lock);
272 if (pbp != NULL) {
273 brelse(pbp);
274 }
275 return (EINVAL);
276 }
277 rw_enter(&ip->i_contents, RW_WRITER);
278
279 /*
280 * We call udf_syncip() to synchronously destroy all pages
281 * associated with the vnode before re-using it. The pageout
282 * thread may have beat us to this page so our v_count can
283 * be > 0 at this point even though we are on the freelist.
284 */
285 mutex_enter(&ip->i_tlock);
286 ip->i_flag = (ip->i_flag & IMODTIME) | IREF;
287 mutex_exit(&ip->i_tlock);
288
289 VN_HOLD(vp);
290 if (ud_syncip(ip, B_INVAL, I_SYNC) != 0) {
291 ud_idrop(ip);
292 rw_exit(&ip->i_contents);
293 mutex_exit(&ud_icache_lock);
294 goto loop;
295 }
296
297 mutex_enter(&ip->i_tlock);
298 ip->i_flag &= ~IMODTIME;
299 mutex_exit(&ip->i_tlock);
300
301 if (ip->i_ext) {
302 kmem_free(ip->i_ext,
303 sizeof (struct icb_ext) * ip->i_ext_count);
304 ip->i_ext = 0;
305 ip->i_ext_count = ip->i_ext_used = 0;
306 }
307
308 if (ip->i_con) {
309 kmem_free(ip->i_con,
310 sizeof (struct icb_ext) * ip->i_con_count);
311 ip->i_con = 0;
312 ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
313 }
314
315 /*
316 * The pageout thread may not have had a chance to release
317 * its hold on the vnode (if it was active with this vp),
318 * but the pages should all be invalidated.
319 */
320 } else {
321 mutex_exit(&ud_nino_lock);
322 mutex_exit(&udf_ifree_lock);
323 /*
324 * Try to get memory for this inode without blocking.
325 * If we can't and there is something on the freelist,
326 * go ahead and use it, otherwise block waiting for
327 * memory holding the hash_lock. We expose a potential
328 * deadlock if all users of memory have to do a ud_iget()
329 * before releasing memory.
330 */
331 ip = (struct ud_inode *)kmem_zalloc(sizeof (struct ud_inode),
332 KM_NOSLEEP);
333 vp = vn_alloc(KM_NOSLEEP);
334 if ((ip == NULL) || (vp == NULL)) {
335 mutex_enter(&udf_ifree_lock);
336 if (udf_ifreeh) {
337 mutex_exit(&udf_ifree_lock);
338 if (ip != NULL)
339 kmem_free(ip, sizeof (struct ud_inode));
340 if (vp != NULL)
341 vn_free(vp);
342 nomem = 1;
343 goto tryagain;
344 } else {
345 mutex_exit(&udf_ifree_lock);
346 if (ip == NULL)
347 ip = (struct ud_inode *)
348 kmem_zalloc(
349 sizeof (struct ud_inode),
350 KM_SLEEP);
351 if (vp == NULL)
352 vp = vn_alloc(KM_SLEEP);
353 }
354 }
355 ip->i_vnode = vp;
356
357 ip->i_marker1 = (uint32_t)0xAAAAAAAA;
358 ip->i_marker2 = (uint32_t)0xBBBBBBBB;
359 ip->i_marker3 = (uint32_t)0xCCCCCCCC;
360
361 rw_init(&ip->i_rwlock, NULL, RW_DEFAULT, NULL);
362 rw_init(&ip->i_contents, NULL, RW_DEFAULT, NULL);
363 mutex_init(&ip->i_tlock, NULL, MUTEX_DEFAULT, NULL);
364
365 ip->i_forw = ip;
366 ip->i_back = ip;
367 vp->v_data = (caddr_t)ip;
368 vn_setops(vp, udf_vnodeops);
369 ip->i_flag = IREF;
370 cv_init(&ip->i_wrcv, NULL, CV_DRIVER, NULL);
371 mutex_enter(&ud_nino_lock);
372 ud_cur_inodes++;
373 mutex_exit(&ud_nino_lock);
374
375 rw_enter(&ip->i_contents, RW_WRITER);
376 }
377
378 if (vp->v_count < 1) {
379 cmn_err(CE_WARN, "ud_iget: v_count < 1\n");
380 mutex_exit(&ud_icache_lock);
381 rw_exit(&ip->i_contents);
382 if (pbp != NULL) {
383 brelse(pbp);
384 }
385 return (EINVAL);
386 }
387 if (vn_has_cached_data(vp)) {
388 cmn_err(CE_WARN, "ud_iget: v_pages not NULL\n");
389 mutex_exit(&ud_icache_lock);
390 rw_exit(&ip->i_contents);
391 if (pbp != NULL) {
392 brelse(pbp);
393 }
394 return (EINVAL);
395 }
396
397 /*
398 * Move the inode on the chain for its new (ino, dev) pair
399 */
400 remque(ip);
401 ip->i_forw = ip;
402 ip->i_back = ip;
403 insque(ip, ih);
404
405 ip->i_dev = vfsp->vfs_dev;
406 ip->i_udf = udf_vfsp;
407 ip->i_diroff = 0;
408 ip->i_devvp = ip->i_udf->udf_devvp;
409 ip->i_icb_prn = prn;
410 ip->i_icb_block = ploc;
411 ip->i_icb_lbano = loc;
412 ip->i_nextr = 0;
413 ip->i_seq = 0;
414 mutex_exit(&ud_icache_lock);
415
416 read_de:
417 if (pbp != NULL) {
418 /*
419 * assumption is that we will not
420 * create a 4096 file
421 */
422 bp = pbp;
423 } else {
424 bp = ud_bread(ip->i_dev,
425 ip->i_icb_lbano << udf_vfsp->udf_l2d_shift,
426 udf_vfsp->udf_lbsize);
427 }
428
429 /*
430 * Check I/O errors
431 */
432 fe = (struct file_entry *)bp->b_un.b_addr;
433 if ((bp->b_flags & B_ERROR) ||
434 (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
435 ip->i_icb_block, 1, udf_vfsp->udf_lbsize) != 0)) {
436
437 if (((bp->b_flags & B_ERROR) == 0) &&
438 (ftype == STRAT_TYPE4096)) {
439 if (ud_check_te_unrec(udf_vfsp,
440 bp->b_un.b_addr, ip->i_icb_block) == 0) {
441
442 brelse(bp);
443
444 /*
445 * restore old file entry location
446 */
447 ip->i_icb_prn = old_prn;
448 ip->i_icb_block = old_block;
449 ip->i_icb_lbano = old_lbano;
450
451 /*
452 * reread old file entry
453 */
454 bp = ud_bread(ip->i_dev,
455 old_lbano << udf_vfsp->udf_l2d_shift,
456 udf_vfsp->udf_lbsize);
457 if ((bp->b_flags & B_ERROR) == 0) {
458 fe = (struct file_entry *)
459 bp->b_un.b_addr;
460 if (ud_verify_tag_and_desc(&fe->fe_tag,
461 UD_FILE_ENTRY, ip->i_icb_block, 1,
462 udf_vfsp->udf_lbsize) == 0) {
463 goto end_4096;
464 }
465 }
466 }
467 }
468 error_ret:
469 brelse(bp);
470 /*
471 * The inode may not contain anything useful. Mark it as
472 * having an error and let anyone else who was waiting for
473 * this know there was an error. Callers waiting for
474 * access to this inode in ud_iget will find
475 * the i_icb_lbano == 0, so there won't be a match.
476 * It remains in the cache. Put it back on the freelist.
477 */
478 mutex_enter(&vp->v_lock);
479 vp->v_count--;
480 mutex_exit(&vp->v_lock);
481 ip->i_icb_lbano = 0;
482
483 /*
484 * The folowing two lines make
485 * it impossible for any one do
486 * a VN_HOLD and then a VN_RELE
487 * so avoiding a ud_iinactive
488 */
489 ip->i_icb_prn = 0xffff;
490 ip->i_icb_block = 0;
491
492 /*
493 * remove the bad inode from hash chains
494 * so that during unmount we will not
495 * go through this inode
496 */
497 mutex_enter(&ud_icache_lock);
498 remque(ip);
499 ip->i_forw = ip;
500 ip->i_back = ip;
501 mutex_exit(&ud_icache_lock);
502
503 /* Put the inode at the front of the freelist */
504 mutex_enter(&ip->i_tlock);
505 mutex_enter(&udf_ifree_lock);
506 ud_add_to_free_list(ip, UD_BEGIN);
507 mutex_exit(&udf_ifree_lock);
508 ip->i_flag = 0;
509 mutex_exit(&ip->i_tlock);
510 rw_exit(&ip->i_contents);
511 return (EIO);
512 }
513
514 if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) {
515 struct buf *ibp = NULL;
516 struct indirect_entry *ie;
517
518 /*
519 * save old file_entry location
520 */
521 old_prn = ip->i_icb_prn;
522 old_block = ip->i_icb_block;
523 old_lbano = ip->i_icb_lbano;
524
525 ftype = STRAT_TYPE4096;
526
527 /*
528 * If astrat is 4096 different versions
529 * of the file exist on the media.
530 * we are supposed to get to the latest
531 * version of the file
532 */
533
534 /*
535 * IE is supposed to be in the next block
536 * of DE
537 */
538 ibp = ud_bread(ip->i_dev,
539 (ip->i_icb_lbano + 1) << udf_vfsp->udf_l2d_shift,
540 udf_vfsp->udf_lbsize);
541 if (ibp->b_flags & B_ERROR) {
542 /*
543 * Get rid of current ibp and
544 * then goto error on DE's bp
545 */
546 ie_error:
547 brelse(ibp);
548 goto error_ret;
549 }
550
551 ie = (struct indirect_entry *)ibp->b_un.b_addr;
552 if (ud_verify_tag_and_desc(&ie->ie_tag,
553 UD_INDIRECT_ENT, ip->i_icb_block + 1,
554 1, udf_vfsp->udf_lbsize) == 0) {
555 struct long_ad *lad;
556
557 lad = &ie->ie_indirecticb;
558 ip->i_icb_prn = SWAP_16(lad->lad_ext_prn);
559 ip->i_icb_block = SWAP_32(lad->lad_ext_loc);
560 ip->i_icb_lbano = ud_xlate_to_daddr(udf_vfsp,
561 ip->i_icb_prn, ip->i_icb_block,
562 1, &dummy);
563 brelse(ibp);
564 brelse(bp);
565 goto read_de;
566 }
567
568 /*
569 * If this block is TE or unrecorded we
570 * are at the last entry
571 */
572 if (ud_check_te_unrec(udf_vfsp, ibp->b_un.b_addr,
573 ip->i_icb_block + 1) != 0) {
574 /*
575 * This is not an unrecorded block
576 * Check if it a valid IE and
577 * get the address of DE that
578 * this IE points to
579 */
580 goto ie_error;
581 }
582 /*
583 * If ud_check_unrec returns "0"
584 * this is the last in the chain
585 * Latest file_entry
586 */
587 brelse(ibp);
588 }
589
590 end_4096:
591
592 ip->i_uid = SWAP_32(fe->fe_uid);
593 if (ip->i_uid == -1) {
594 ip->i_uid = ud_default_uid;
595 }
596 ip->i_gid = SWAP_32(fe->fe_gid);
597 if (ip->i_gid == -1) {
598 ip->i_gid = ud_default_gid;
599 }
600 ip->i_perm = SWAP_32(fe->fe_perms) & 0xFFFF;
601 if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) {
602 ip->i_perm &= ~(IWRITE | (IWRITE >> 5) | (IWRITE >> 10));
603 }
604
605 ip->i_nlink = SWAP_16(fe->fe_lcount);
606 ip->i_size = SWAP_64(fe->fe_info_len);
607 ip->i_lbr = SWAP_64(fe->fe_lbr);
608
609 ud_dtime2utime(&ip->i_atime, &fe->fe_acc_time);
610 ud_dtime2utime(&ip->i_mtime, &fe->fe_mod_time);
611 ud_dtime2utime(&ip->i_ctime, &fe->fe_attr_time);
612
613
614 ip->i_uniqid = SWAP_64(fe->fe_uniq_id);
615 icb_tag_flags = SWAP_16(fe->fe_icb_tag.itag_flags);
616
617 if ((fe->fe_icb_tag.itag_ftype == FTYPE_CHAR_DEV) ||
618 (fe->fe_icb_tag.itag_ftype == FTYPE_BLOCK_DEV)) {
619
620 eah = (struct ext_attr_hdr *)fe->fe_spec;
621 ea_off = GET_32(&eah->eah_ial);
622 ea_len = GET_32(&fe->fe_len_ear);
623 if (ea_len && (ud_verify_tag_and_desc(&eah->eah_tag,
624 UD_EXT_ATTR_HDR, ip->i_icb_block, 1,
625 sizeof (struct file_entry) -
626 offsetof(struct file_entry, fe_spec)) == 0)) {
627
628 while (ea_off < ea_len) {
629 /*
630 * We now check the validity of ea_off.
631 * (ea_len - ea_off) should be large enough to
632 * hold the attribute header atleast.
633 */
634 if ((ea_len - ea_off) <
635 sizeof (struct attr_hdr)) {
636 cmn_err(CE_NOTE,
637 "ea_len(0x%x) - ea_off(0x%x) is "
638 "too small to hold attr. info. "
639 "blockno 0x%x\n",
640 ea_len, ea_off, ip->i_icb_block);
641 goto error_ret;
642 }
643 ah = (struct attr_hdr *)&fe->fe_spec[ea_off];
644
645 /*
646 * Device Specification EA
647 */
648 if ((GET_32(&ah->ahdr_atype) == 12) &&
649 (ah->ahdr_astype == 1)) {
650 struct dev_spec_ear *ds;
651
652 if ((ea_len - ea_off) <
653 sizeof (struct dev_spec_ear)) {
654 cmn_err(CE_NOTE,
655 "ea_len(0x%x) - "
656 "ea_off(0x%x) is too small "
657 "to hold dev_spec_ear."
658 " blockno 0x%x\n",
659 ea_len, ea_off,
660 ip->i_icb_block);
661 goto error_ret;
662 }
663 ds = (struct dev_spec_ear *)ah;
664 ip->i_major = GET_32(&ds->ds_major_id);
665 ip->i_minor = GET_32(&ds->ds_minor_id);
666 }
667
668 /*
669 * Impl Use EA
670 */
671 if ((GET_32(&ah->ahdr_atype) == 2048) &&
672 (ah->ahdr_astype == 1)) {
673 struct iu_ea *iuea;
674 struct copy_mgt_info *cmi;
675
676 if ((ea_len - ea_off) <
677 sizeof (struct iu_ea)) {
678 cmn_err(CE_NOTE,
679 "ea_len(0x%x) - ea_off(0x%x) is too small to hold iu_ea. blockno 0x%x\n",
680 ea_len, ea_off,
681 ip->i_icb_block);
682 goto error_ret;
683 }
684 iuea = (struct iu_ea *)ah;
685 if (strncmp(iuea->iuea_ii.reg_id,
686 UDF_FREEEASPACE,
687 sizeof (iuea->iuea_ii.reg_id))
688 == 0) {
689 /* skip it */
690 iuea = iuea;
691 } else if (strncmp(iuea->iuea_ii.reg_id,
692 UDF_CGMS_INFO,
693 sizeof (iuea->iuea_ii.reg_id))
694 == 0) {
695 cmi = (struct copy_mgt_info *)
696 iuea->iuea_iu;
697 cmi = cmi;
698 }
699 }
700 /* ??? PARANOIA */
701 if (GET_32(&ah->ahdr_length) == 0) {
702 break;
703 }
704 ea_off += GET_32(&ah->ahdr_length);
705 }
706 }
707 }
708
709 ip->i_nextr = 0;
710
711 ip->i_maxent = SWAP_16(fe->fe_icb_tag.itag_max_ent);
712 ip->i_astrat = SWAP_16(fe->fe_icb_tag.itag_strategy);
713
714 ip->i_desc_type = icb_tag_flags & 0x7;
715
716 /* Strictly Paranoia */
717 ip->i_ext = NULL;
718 ip->i_ext_count = ip->i_ext_used = 0;
719 ip->i_con = 0;
720 ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
721
722 ip->i_data_off = 0xB0 + SWAP_32(fe->fe_len_ear);
723 ip->i_max_emb = udf_vfsp->udf_lbsize - ip->i_data_off;
724 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
725 /* Short allocation desc */
726 struct short_ad *sad;
727
728 ip->i_ext_used = 0;
729 ip->i_ext_count = ndesc =
730 SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
731 ip->i_ext_count =
732 ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC;
733 ip->i_ext = (struct icb_ext *)kmem_zalloc(ip->i_ext_count *
734 sizeof (struct icb_ext), KM_SLEEP);
735 ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct short_ad);
736 ip->i_cur_max_ext --;
737
738 if ((ip->i_astrat != STRAT_TYPE4) &&
739 (ip->i_astrat != STRAT_TYPE4096)) {
740 goto error_ret;
741 }
742
743 sad = (struct short_ad *)
744 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
745 iext = ip->i_ext;
746 while (ndesc --) {
747 length = SWAP_32(sad->sad_ext_len);
748 if ((length & 0x3FFFFFFF) == 0) {
749 break;
750 }
751 if (((length >> 30) & IB_MASK) == IB_CON) {
752 if (ip->i_con == NULL) {
753 ip->i_con_count = EXT_PER_MALLOC;
754 ip->i_con_used = 0;
755 ip->i_con_read = 0;
756 ip->i_con = kmem_zalloc(
757 ip->i_con_count *
758 sizeof (struct icb_ext),
759 KM_SLEEP);
760 }
761 con = &ip->i_con[ip->i_con_used];
762 con->ib_prn = 0;
763 con->ib_block = SWAP_32(sad->sad_ext_loc);
764 con->ib_count = length & 0x3FFFFFFF;
765 con->ib_flags = (length >> 30) & IB_MASK;
766 ip->i_con_used++;
767 sad ++;
768 break;
769 }
770 iext->ib_prn = 0;
771 iext->ib_block = SWAP_32(sad->sad_ext_loc);
772 length = SWAP_32(sad->sad_ext_len);
773 iext->ib_count = length & 0x3FFFFFFF;
774 iext->ib_offset = offset;
775 iext->ib_marker1 = (uint32_t)0xAAAAAAAA;
776 iext->ib_marker2 = (uint32_t)0xBBBBBBBB;
777 offset += (iext->ib_count + udf_vfsp->udf_lbmask) &
778 (~udf_vfsp->udf_lbmask);
779
780 iext->ib_flags = (length >> 30) & IB_MASK;
781
782 ip->i_ext_used++;
783 iext++;
784 sad ++;
785 }
786 } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
787 /* Long allocation desc */
788 struct long_ad *lad;
789
790 ip->i_ext_used = 0;
791 ip->i_ext_count = ndesc =
792 SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
793 ip->i_ext_count =
794 ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC;
795 ip->i_ext = (struct icb_ext *)kmem_zalloc(ip->i_ext_count *
796 sizeof (struct icb_ext), KM_SLEEP);
797
798 ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct long_ad);
799 ip->i_cur_max_ext --;
800
801 if ((ip->i_astrat != STRAT_TYPE4) &&
802 (ip->i_astrat != STRAT_TYPE4096)) {
803 goto error_ret;
804 }
805
806 lad = (struct long_ad *)
807 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
808 iext = ip->i_ext;
809 while (ndesc --) {
810 length = SWAP_32(lad->lad_ext_len);
811 if ((length & 0x3FFFFFFF) == 0) {
812 break;
813 }
814 if (((length >> 30) & IB_MASK) == IB_CON) {
815 if (ip->i_con == NULL) {
816 ip->i_con_count = EXT_PER_MALLOC;
817 ip->i_con_used = 0;
818 ip->i_con_read = 0;
819 ip->i_con = kmem_zalloc(
820 ip->i_con_count *
821 sizeof (struct icb_ext),
822 KM_SLEEP);
823 }
824 con = &ip->i_con[ip->i_con_used];
825 con->ib_prn = SWAP_16(lad->lad_ext_prn);
826 con->ib_block = SWAP_32(lad->lad_ext_loc);
827 con->ib_count = length & 0x3FFFFFFF;
828 con->ib_flags = (length >> 30) & IB_MASK;
829 ip->i_con_used++;
830 lad ++;
831 break;
832 }
833 iext->ib_prn = SWAP_16(lad->lad_ext_prn);
834 iext->ib_block = SWAP_32(lad->lad_ext_loc);
835 iext->ib_count = length & 0x3FFFFFFF;
836 iext->ib_offset = offset;
837 iext->ib_marker1 = (uint32_t)0xAAAAAAAA;
838 iext->ib_marker2 = (uint32_t)0xBBBBBBBB;
839 offset += (iext->ib_count + udf_vfsp->udf_lbmask) &
840 (~udf_vfsp->udf_lbmask);
841
842 iext->ib_flags = (length >> 30) & IB_MASK;
843
844 ip->i_ext_used++;
845 iext++;
846 lad ++;
847 }
848 } else if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
849 ASSERT(SWAP_32(fe->fe_len_ear) < udf_vfsp->udf_lbsize);
850
851 if (SWAP_32(fe->fe_len_ear) > udf_vfsp->udf_lbsize) {
852 goto error_ret;
853 }
854 } else {
855 /* Not to be used in UDF 1.50 */
856 cmn_err(CE_NOTE, "Invalid Allocation Descriptor type %x\n",
857 ip->i_desc_type);
858 goto error_ret;
859 }
860
861
862 if (icb_tag_flags & ICB_FLAG_SETUID) {
863 ip->i_char = ISUID;
864 } else {
865 ip->i_char = 0;
866 }
867 if (icb_tag_flags & ICB_FLAG_SETGID) {
868 ip->i_char |= ISGID;
869 }
870 if (icb_tag_flags & ICB_FLAG_STICKY) {
871 ip->i_char |= ISVTX;
872 }
873 switch (fe->fe_icb_tag.itag_ftype) {
874 case FTYPE_DIRECTORY :
875 ip->i_type = VDIR;
876 break;
877 case FTYPE_FILE :
878 ip->i_type = VREG;
879 break;
880 case FTYPE_BLOCK_DEV :
881 ip->i_type = VBLK;
882 break;
883 case FTYPE_CHAR_DEV :
884 ip->i_type = VCHR;
885 break;
886 case FTYPE_FIFO :
887 ip->i_type = VFIFO;
888 break;
889 case FTYPE_C_ISSOCK :
890 ip->i_type = VSOCK;
891 break;
892 case FTYPE_SYMLINK :
893 ip->i_type = VLNK;
894 break;
895 default :
896 ip->i_type = VNON;
897 break;
898 }
899
900 if (ip->i_type == VBLK || ip->i_type == VCHR) {
901 ip->i_rdev = makedevice(ip->i_major, ip->i_minor);
902 }
903
904 /*
905 * Fill in the rest. Don't bother with the vnode lock because nobody
906 * should be looking at this vnode. We have already invalidated the
907 * pages if it had any so pageout shouldn't be referencing this vnode
908 * and we are holding the write contents lock so a look up can't use
909 * the vnode.
910 */
911 vp->v_vfsp = vfsp;
912 vp->v_type = ip->i_type;
913 vp->v_rdev = ip->i_rdev;
914 if (ip->i_udf->udf_root_blkno == loc) {
915 vp->v_flag = VROOT;
916 } else {
917 vp->v_flag = 0;
918 }
919
920 brelse(bp);
921 *ipp = ip;
922 rw_exit(&ip->i_contents);
923 vn_exists(vp);
924 return (0);
925 }
926
927 void
ud_iinactive(struct ud_inode * ip,struct cred * cr)928 ud_iinactive(struct ud_inode *ip, struct cred *cr)
929 {
930 int32_t busy = 0;
931 struct vnode *vp;
932 vtype_t type;
933 caddr_t addr, addr1;
934 size_t size, size1;
935
936
937 ud_printf("ud_iinactive\n");
938
939 /*
940 * Get exclusive access to inode data.
941 */
942 rw_enter(&ip->i_contents, RW_WRITER);
943
944 /*
945 * Make sure no one reclaimed the inode before we put
946 * it on the freelist or destroy it. We keep our 'hold'
947 * on the vnode from vn_rele until we are ready to
948 * do something with the inode (freelist/destroy).
949 *
950 * Pageout may put a VN_HOLD/VN_RELE at anytime during this
951 * operation via an async putpage, so we must make sure
952 * we don't free/destroy the inode more than once. ud_iget
953 * may also put a VN_HOLD on the inode before it grabs
954 * the i_contents lock. This is done so we don't kmem_free
955 * an inode that a thread is waiting on.
956 */
957 vp = ITOV(ip);
958
959 mutex_enter(&vp->v_lock);
960 if (vp->v_count < 1) {
961 cmn_err(CE_WARN, "ud_iinactive: v_count < 1\n");
962 return;
963 }
964 if ((vp->v_count > 1) || ((ip->i_flag & IREF) == 0)) {
965 vp->v_count--; /* release our hold from vn_rele */
966 mutex_exit(&vp->v_lock);
967 rw_exit(&ip->i_contents);
968 return;
969 }
970 mutex_exit(&vp->v_lock);
971
972 /*
973 * For forced umount case: if i_udf is NULL, the contents of
974 * the inode and all the pages have already been pushed back
975 * to disk. It can be safely destroyed.
976 */
977 if (ip->i_udf == NULL) {
978 addr = (caddr_t)ip->i_ext;
979 size = sizeof (struct icb_ext) * ip->i_ext_count;
980 ip->i_ext = 0;
981 ip->i_ext_count = ip->i_ext_used = 0;
982 addr1 = (caddr_t)ip->i_con;
983 size1 = sizeof (struct icb_ext) * ip->i_con_count;
984 ip->i_con = 0;
985 ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
986 rw_exit(&ip->i_contents);
987 vn_invalid(vp);
988
989 mutex_enter(&ud_nino_lock);
990 ud_cur_inodes--;
991 mutex_exit(&ud_nino_lock);
992
993 cv_destroy(&ip->i_wrcv); /* throttling */
994 rw_destroy(&ip->i_rwlock);
995 rw_exit(&ip->i_contents);
996 rw_destroy(&ip->i_contents);
997 kmem_free(addr, size);
998 kmem_free(addr1, size1);
999 vn_free(vp);
1000 kmem_free(ip, sizeof (struct ud_inode));
1001 return;
1002 }
1003
1004 if ((ip->i_udf->udf_flags & UDF_FL_RDONLY) == 0) {
1005 if (ip->i_nlink <= 0) {
1006 ip->i_marker3 = (uint32_t)0xDDDD0000;
1007 ip->i_nlink = 1; /* prevent free-ing twice */
1008 (void) ud_itrunc(ip, 0, 0, cr);
1009 type = ip->i_type;
1010 ip->i_perm = 0;
1011 ip->i_uid = 0;
1012 ip->i_gid = 0;
1013 ip->i_rdev = 0; /* Zero in core version of rdev */
1014 mutex_enter(&ip->i_tlock);
1015 ip->i_flag |= IUPD|ICHG;
1016 mutex_exit(&ip->i_tlock);
1017 ud_ifree(ip, type);
1018 ip->i_icb_prn = 0xFFFF;
1019 } else if (!IS_SWAPVP(vp)) {
1020 /*
1021 * Write the inode out if dirty. Pages are
1022 * written back and put on the freelist.
1023 */
1024 (void) ud_syncip(ip, B_FREE | B_ASYNC, 0);
1025 /*
1026 * Do nothing if inode is now busy -- inode may
1027 * have gone busy because ud_syncip
1028 * releases/reacquires the i_contents lock
1029 */
1030 mutex_enter(&vp->v_lock);
1031 if (vp->v_count > 1) {
1032 vp->v_count--;
1033 mutex_exit(&vp->v_lock);
1034 rw_exit(&ip->i_contents);
1035 return;
1036 }
1037 mutex_exit(&vp->v_lock);
1038 } else {
1039 ud_iupdat(ip, 0);
1040 }
1041 }
1042
1043
1044 /*
1045 * Put the inode on the end of the free list.
1046 * Possibly in some cases it would be better to
1047 * put the inode at the head of the free list,
1048 * (e.g.: where i_perm == 0 || i_number == 0)
1049 * but I will think about that later.
1050 * (i_number is rarely 0 - only after an i/o error in ud_iget,
1051 * where i_perm == 0, the inode will probably be wanted
1052 * again soon for an ialloc, so possibly we should keep it)
1053 */
1054 /*
1055 * If inode is invalid or there is no page associated with
1056 * this inode, put the inode in the front of the free list.
1057 * Since we have a VN_HOLD on the vnode, and checked that it
1058 * wasn't already on the freelist when we entered, we can safely
1059 * put it on the freelist even if another thread puts a VN_HOLD
1060 * on it (pageout/ud_iget).
1061 */
1062 tryagain:
1063 mutex_enter(&ud_nino_lock);
1064 if (vn_has_cached_data(vp)) {
1065 mutex_exit(&ud_nino_lock);
1066 mutex_enter(&vp->v_lock);
1067 vp->v_count--;
1068 mutex_exit(&vp->v_lock);
1069 mutex_enter(&ip->i_tlock);
1070 mutex_enter(&udf_ifree_lock);
1071 ud_add_to_free_list(ip, UD_END);
1072 mutex_exit(&udf_ifree_lock);
1073 ip->i_flag &= IMODTIME;
1074 mutex_exit(&ip->i_tlock);
1075 rw_exit(&ip->i_contents);
1076 } else if (busy || ud_cur_inodes < ud_max_inodes) {
1077 mutex_exit(&ud_nino_lock);
1078 /*
1079 * We're not over our high water mark, or it's
1080 * not safe to kmem_free the inode, so put it
1081 * on the freelist.
1082 */
1083 mutex_enter(&vp->v_lock);
1084 if (vn_has_cached_data(vp)) {
1085 cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n");
1086 }
1087 vp->v_count--;
1088 mutex_exit(&vp->v_lock);
1089
1090 mutex_enter(&ip->i_tlock);
1091 mutex_enter(&udf_ifree_lock);
1092 ud_add_to_free_list(ip, UD_BEGIN);
1093 mutex_exit(&udf_ifree_lock);
1094 ip->i_flag &= IMODTIME;
1095 mutex_exit(&ip->i_tlock);
1096 rw_exit(&ip->i_contents);
1097 } else {
1098 mutex_exit(&ud_nino_lock);
1099 if (vn_has_cached_data(vp)) {
1100 cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n");
1101 }
1102 /*
1103 * Try to free the inode. We must make sure
1104 * it's o.k. to destroy this inode. We can't destroy
1105 * if a thread is waiting for this inode. If we can't get the
1106 * cache now, put it back on the freelist.
1107 */
1108 if (!mutex_tryenter(&ud_icache_lock)) {
1109 busy = 1;
1110 goto tryagain;
1111 }
1112 mutex_enter(&vp->v_lock);
1113 if (vp->v_count > 1) {
1114 /* inode is wanted in ud_iget */
1115 busy = 1;
1116 mutex_exit(&vp->v_lock);
1117 mutex_exit(&ud_icache_lock);
1118 goto tryagain;
1119 }
1120 mutex_exit(&vp->v_lock);
1121 remque(ip);
1122 ip->i_forw = ip;
1123 ip->i_back = ip;
1124 mutex_enter(&ud_nino_lock);
1125 ud_cur_inodes--;
1126 mutex_exit(&ud_nino_lock);
1127 mutex_exit(&ud_icache_lock);
1128 if (ip->i_icb_prn != 0xFFFF) {
1129 ud_iupdat(ip, 0);
1130 }
1131 addr = (caddr_t)ip->i_ext;
1132 size = sizeof (struct icb_ext) * ip->i_ext_count;
1133 ip->i_ext = 0;
1134 ip->i_ext_count = ip->i_ext_used = 0;
1135 addr1 = (caddr_t)ip->i_con;
1136 size1 = sizeof (struct icb_ext) * ip->i_con_count;
1137 ip->i_con = 0;
1138 ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
1139 cv_destroy(&ip->i_wrcv); /* throttling */
1140 rw_destroy(&ip->i_rwlock);
1141 rw_exit(&ip->i_contents);
1142 rw_destroy(&ip->i_contents);
1143 kmem_free(addr, size);
1144 kmem_free(addr1, size1);
1145 ip->i_marker3 = (uint32_t)0xDDDDDDDD;
1146 vn_free(vp);
1147 kmem_free(ip, sizeof (struct ud_inode));
1148 }
1149 }
1150
1151
1152 void
ud_iupdat(struct ud_inode * ip,int32_t waitfor)1153 ud_iupdat(struct ud_inode *ip, int32_t waitfor)
1154 {
1155 uint16_t flag, tag_flags;
1156 int32_t error, crc_len = 0;
1157 struct buf *bp;
1158 struct udf_vfs *udf_vfsp;
1159 struct file_entry *fe;
1160
1161 ASSERT(RW_WRITE_HELD(&ip->i_contents));
1162
1163 ud_printf("ud_iupdat\n");
1164 /*
1165 * Return if file system has been forcibly umounted.
1166 */
1167 if (ip->i_udf == NULL) {
1168 return;
1169 }
1170
1171 udf_vfsp = ip->i_udf;
1172 flag = ip->i_flag; /* Atomic read */
1173 if ((flag & (IUPD|IACC|ICHG|IMOD|IMODACC)) != 0) {
1174 if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
1175 ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC|IATTCHG);
1176 return;
1177 }
1178
1179 bp = ud_bread(ip->i_dev,
1180 ip->i_icb_lbano << udf_vfsp->udf_l2d_shift,
1181 ip->i_udf->udf_lbsize);
1182 if (bp->b_flags & B_ERROR) {
1183 brelse(bp);
1184 return;
1185 }
1186 fe = (struct file_entry *)bp->b_un.b_addr;
1187 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
1188 ip->i_icb_block,
1189 1, ip->i_udf->udf_lbsize) != 0) {
1190 brelse(bp);
1191 return;
1192 }
1193
1194 mutex_enter(&ip->i_tlock);
1195 if (ip->i_flag & (IUPD|IACC|ICHG)) {
1196 IMARK(ip);
1197 }
1198 ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC);
1199 mutex_exit(&ip->i_tlock);
1200
1201 fe->fe_uid = SWAP_32(ip->i_uid);
1202 fe->fe_gid = SWAP_32(ip->i_gid);
1203
1204 fe->fe_perms = SWAP_32(ip->i_perm);
1205
1206 fe->fe_lcount = SWAP_16(ip->i_nlink);
1207 fe->fe_info_len = SWAP_64(ip->i_size);
1208 fe->fe_lbr = SWAP_64(ip->i_lbr);
1209
1210 ud_utime2dtime(&ip->i_atime, &fe->fe_acc_time);
1211 ud_utime2dtime(&ip->i_mtime, &fe->fe_mod_time);
1212 ud_utime2dtime(&ip->i_ctime, &fe->fe_attr_time);
1213
1214 if (ip->i_char & ISUID) {
1215 tag_flags = ICB_FLAG_SETUID;
1216 } else {
1217 tag_flags = 0;
1218 }
1219 if (ip->i_char & ISGID) {
1220 tag_flags |= ICB_FLAG_SETGID;
1221 }
1222 if (ip->i_char & ISVTX) {
1223 tag_flags |= ICB_FLAG_STICKY;
1224 }
1225 tag_flags |= ip->i_desc_type;
1226
1227 /*
1228 * Remove the following it is no longer contig
1229 * if (ip->i_astrat == STRAT_TYPE4) {
1230 * tag_flags |= ICB_FLAG_CONTIG;
1231 * }
1232 */
1233
1234 fe->fe_icb_tag.itag_flags &= ~SWAP_16((uint16_t)0x3C3);
1235 fe->fe_icb_tag.itag_strategy = SWAP_16(ip->i_astrat);
1236 fe->fe_icb_tag.itag_flags |= SWAP_16(tag_flags);
1237
1238 ud_update_regid(&fe->fe_impl_id);
1239
1240 crc_len = ((uint32_t)&((struct file_entry *)0)->fe_spec) +
1241 SWAP_32(fe->fe_len_ear);
1242 if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
1243 crc_len += ip->i_size;
1244 fe->fe_len_adesc = SWAP_32(((uint32_t)ip->i_size));
1245 } else if ((ip->i_size != 0) && (ip->i_ext != NULL) &&
1246 (ip->i_ext_used != 0)) {
1247
1248 if ((error = ud_read_icb_till_off(ip,
1249 ip->i_size)) == 0) {
1250 if (ip->i_astrat == STRAT_TYPE4) {
1251 error = ud_updat_ext4(ip, fe);
1252 } else if (ip->i_astrat == STRAT_TYPE4096) {
1253 error = ud_updat_ext4096(ip, fe);
1254 }
1255 if (error) {
1256 udf_vfsp->udf_mark_bad = 1;
1257 }
1258 }
1259 crc_len += SWAP_32(fe->fe_len_adesc);
1260 } else {
1261 fe->fe_len_adesc = 0;
1262 }
1263
1264 /*
1265 * Zero out the rest of the block
1266 */
1267 bzero(bp->b_un.b_addr + crc_len,
1268 ip->i_udf->udf_lbsize - crc_len);
1269
1270 ud_make_tag(ip->i_udf, &fe->fe_tag,
1271 UD_FILE_ENTRY, ip->i_icb_block, crc_len);
1272
1273
1274 if (waitfor) {
1275 BWRITE(bp);
1276
1277 /*
1278 * Synchronous write has guaranteed that inode
1279 * has been written on disk so clear the flag
1280 */
1281 ip->i_flag &= ~(IBDWRITE);
1282 } else {
1283 bdwrite(bp);
1284
1285 /*
1286 * This write hasn't guaranteed that inode has been
1287 * written on the disk.
1288 * Since, all updat flags on indoe are cleared, we must
1289 * remember the condition in case inode is to be updated
1290 * synchronously later (e.g.- fsync()/fdatasync())
1291 * and inode has not been modified yet.
1292 */
1293 ip->i_flag |= (IBDWRITE);
1294 }
1295 } else {
1296 /*
1297 * In case previous inode update was done asynchronously
1298 * (IBDWRITE) and this inode update request wants guaranteed
1299 * (synchronous) disk update, flush the inode.
1300 */
1301 if (waitfor && (flag & IBDWRITE)) {
1302 blkflush(ip->i_dev,
1303 (daddr_t)fsbtodb(udf_vfsp, ip->i_icb_lbano));
1304 ip->i_flag &= ~(IBDWRITE);
1305 }
1306 }
1307 }
1308
1309 int32_t
ud_updat_ext4(struct ud_inode * ip,struct file_entry * fe)1310 ud_updat_ext4(struct ud_inode *ip, struct file_entry *fe)
1311 {
1312 uint32_t dummy;
1313 int32_t elen, ndent, index, count, con_index;
1314 daddr_t bno;
1315 struct buf *bp;
1316 struct short_ad *sad;
1317 struct long_ad *lad;
1318 struct icb_ext *iext, *icon;
1319
1320
1321 ASSERT(ip);
1322 ASSERT(fe);
1323 ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) ||
1324 (ip->i_desc_type == ICB_FLAG_LONG_AD));
1325
1326 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
1327 elen = sizeof (struct short_ad);
1328 sad = (struct short_ad *)
1329 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1330 } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
1331 elen = sizeof (struct long_ad);
1332 lad = (struct long_ad *)
1333 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1334 } else {
1335 /* This cannot happen return */
1336 return (EINVAL);
1337 }
1338
1339 ndent = ip->i_max_emb / elen;
1340
1341 if (ip->i_ext_used < ndent) {
1342
1343 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
1344 ud_make_sad(ip->i_ext, sad, ip->i_ext_used);
1345 } else {
1346 ud_make_lad(ip->i_ext, lad, ip->i_ext_used);
1347 }
1348 fe->fe_len_adesc = SWAP_32(ip->i_ext_used * elen);
1349 con_index = 0;
1350 } else {
1351
1352 con_index = index = 0;
1353
1354 while (index < ip->i_ext_used) {
1355 if (index == 0) {
1356 /*
1357 * bp is already read
1358 * First few extents will go
1359 * into the file_entry
1360 */
1361 count = ndent - 1;
1362 fe->fe_len_adesc = SWAP_32(ndent * elen);
1363 bp = NULL;
1364
1365 /*
1366 * Last entry to be cont ext
1367 */
1368 icon = &ip->i_con[con_index];
1369 } else {
1370 /*
1371 * Read the buffer
1372 */
1373 icon = &ip->i_con[con_index];
1374
1375 bno = ud_xlate_to_daddr(ip->i_udf,
1376 icon->ib_prn, icon->ib_block,
1377 icon->ib_count >> ip->i_udf->udf_l2d_shift,
1378 &dummy);
1379 bp = ud_bread(ip->i_dev,
1380 bno << ip->i_udf->udf_l2d_shift,
1381 ip->i_udf->udf_lbsize);
1382 if (bp->b_flags & B_ERROR) {
1383 brelse(bp);
1384 return (EIO);
1385 }
1386
1387 /*
1388 * Figure out how many extents in
1389 * this time
1390 */
1391 count = (bp->b_bcount -
1392 sizeof (struct alloc_ext_desc)) / elen;
1393 if (count > (ip->i_ext_used - index)) {
1394 count = ip->i_ext_used - index;
1395 } else {
1396 count --;
1397 }
1398 con_index++;
1399 if (con_index >= ip->i_con_used) {
1400 icon = NULL;
1401 } else {
1402 icon = &ip->i_con[con_index];
1403 }
1404 }
1405
1406
1407
1408 /*
1409 * convert to on disk form and
1410 * update
1411 */
1412 iext = &ip->i_ext[index];
1413 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
1414 if (index != 0) {
1415 sad = (struct short_ad *)
1416 (bp->b_un.b_addr +
1417 sizeof (struct alloc_ext_desc));
1418 }
1419 ud_make_sad(iext, sad, count);
1420 sad += count;
1421 if (icon != NULL) {
1422 ud_make_sad(icon, sad, 1);
1423 }
1424 } else {
1425 if (index != 0) {
1426 lad = (struct long_ad *)
1427 (bp->b_un.b_addr +
1428 sizeof (struct alloc_ext_desc));
1429 }
1430 ud_make_lad(iext, lad, count);
1431 lad += count;
1432 if (icon != NULL) {
1433 ud_make_lad(icon, lad, 1);
1434 }
1435 }
1436
1437 if (con_index != 0) {
1438 struct alloc_ext_desc *aed;
1439 int32_t sz;
1440 struct icb_ext *oicon;
1441
1442 oicon = &ip->i_con[con_index - 1];
1443 sz = count * elen;
1444 if (icon != NULL) {
1445 sz += elen;
1446 }
1447 aed = (struct alloc_ext_desc *)bp->b_un.b_addr;
1448 aed->aed_len_aed = SWAP_32(sz);
1449 if (con_index == 1) {
1450 aed->aed_rev_ael =
1451 SWAP_32(ip->i_icb_block);
1452 } else {
1453 aed->aed_rev_ael =
1454 SWAP_32(oicon->ib_block);
1455 }
1456 sz += sizeof (struct alloc_ext_desc);
1457 ud_make_tag(ip->i_udf, &aed->aed_tag,
1458 UD_ALLOC_EXT_DESC, oicon->ib_block, sz);
1459 }
1460
1461 /*
1462 * Write back to disk
1463 */
1464 if (bp != NULL) {
1465 BWRITE(bp);
1466 }
1467 index += count;
1468 }
1469
1470 }
1471
1472 if (con_index != ip->i_con_used) {
1473 int32_t lbmask, l2b, temp;
1474
1475 temp = con_index;
1476 lbmask = ip->i_udf->udf_lbmask;
1477 l2b = ip->i_udf->udf_l2b_shift;
1478 /*
1479 * Free unused continuation extents
1480 */
1481 for (; con_index < ip->i_con_used; con_index++) {
1482 icon = &ip->i_con[con_index];
1483 count = (icon->ib_count + lbmask) >> l2b;
1484 ud_free_space(ip->i_udf->udf_vfs, icon->ib_prn,
1485 icon->ib_block, count);
1486 count = (count << l2b) - sizeof (struct alloc_ext_desc);
1487 ip->i_cur_max_ext -= (count / elen) - 1;
1488 }
1489 ip->i_con_used = temp;
1490 }
1491 return (0);
1492 }
1493
1494 /* ARGSUSED */
1495 int32_t
ud_updat_ext4096(struct ud_inode * ip,struct file_entry * fe)1496 ud_updat_ext4096(struct ud_inode *ip, struct file_entry *fe)
1497 {
1498 return (ENXIO);
1499 }
1500
1501 void
ud_make_sad(struct icb_ext * iext,struct short_ad * sad,int32_t count)1502 ud_make_sad(struct icb_ext *iext, struct short_ad *sad, int32_t count)
1503 {
1504 int32_t index = 0, scount;
1505
1506 ASSERT(iext);
1507 ASSERT(sad);
1508
1509 if (count != 0) {
1510 ASSERT(count > 0);
1511 while (index < count) {
1512 scount = (iext->ib_count & 0x3FFFFFFF) |
1513 (iext->ib_flags << 30);
1514 sad->sad_ext_len = SWAP_32(scount);
1515 sad->sad_ext_loc = SWAP_32(iext->ib_block);
1516 sad++;
1517 iext++;
1518 index++;
1519 }
1520 }
1521 }
1522
1523 void
ud_make_lad(struct icb_ext * iext,struct long_ad * lad,int32_t count)1524 ud_make_lad(struct icb_ext *iext, struct long_ad *lad, int32_t count)
1525 {
1526 int32_t index = 0, scount;
1527
1528 ASSERT(iext);
1529 ASSERT(lad);
1530
1531 if (count != 0) {
1532 ASSERT(count > 0);
1533
1534 while (index < count) {
1535 lad->lad_ext_prn = SWAP_16(iext->ib_prn);
1536 scount = (iext->ib_count & 0x3FFFFFFF) |
1537 (iext->ib_flags << 30);
1538 lad->lad_ext_len = SWAP_32(scount);
1539 lad->lad_ext_loc = SWAP_32(iext->ib_block);
1540 lad++;
1541 iext++;
1542 index++;
1543 }
1544 }
1545 }
1546
1547 /*
1548 * Truncate the inode ip to at most length size.
1549 * Free affected disk blocks -- the blocks of the
1550 * file are removed in reverse order.
1551 */
1552 /* ARGSUSED */
1553 int
ud_itrunc(struct ud_inode * oip,u_offset_t length,int32_t flags,struct cred * cr)1554 ud_itrunc(struct ud_inode *oip, u_offset_t length,
1555 int32_t flags, struct cred *cr)
1556 {
1557 int32_t error, boff;
1558 off_t bsize;
1559 mode_t mode;
1560 struct udf_vfs *udf_vfsp;
1561
1562 ud_printf("ud_itrunc\n");
1563
1564 ASSERT(RW_WRITE_HELD(&oip->i_contents));
1565 udf_vfsp = oip->i_udf;
1566 bsize = udf_vfsp->udf_lbsize;
1567
1568 /*
1569 * We only allow truncation of regular files and directories
1570 * to arbritary lengths here. In addition, we allow symbolic
1571 * links to be truncated only to zero length. Other inode
1572 * types cannot have their length set here.
1573 */
1574 mode = oip->i_type;
1575 if (mode == VFIFO) {
1576 return (0);
1577 }
1578 if ((mode != VREG) && (mode != VDIR) &&
1579 (!(mode == VLNK && length == 0))) {
1580 return (EINVAL);
1581 }
1582 if (length == oip->i_size) {
1583 /* update ctime and mtime to please POSIX tests */
1584 mutex_enter(&oip->i_tlock);
1585 oip->i_flag |= ICHG |IUPD;
1586 mutex_exit(&oip->i_tlock);
1587 return (0);
1588 }
1589
1590 boff = blkoff(udf_vfsp, length);
1591
1592 if (length > oip->i_size) {
1593 /*
1594 * Trunc up case.ud_bmap_write will insure that the right blocks
1595 * are allocated. This includes doing any work needed for
1596 * allocating the last block.
1597 */
1598 if (boff == 0) {
1599 error = ud_bmap_write(oip, length - 1,
1600 (int)bsize, 0, cr);
1601 } else {
1602 error = ud_bmap_write(oip, length - 1, boff, 0, cr);
1603 }
1604 if (error == 0) {
1605 u_offset_t osize = oip->i_size;
1606 oip->i_size = length;
1607
1608 /*
1609 * Make sure we zero out the remaining bytes of
1610 * the page in case a mmap scribbled on it. We
1611 * can't prevent a mmap from writing beyond EOF
1612 * on the last page of a file.
1613 */
1614 if ((boff = blkoff(udf_vfsp, osize)) != 0) {
1615 pvn_vpzero(ITOV(oip), osize,
1616 (uint32_t)(bsize - boff));
1617 }
1618 mutex_enter(&oip->i_tlock);
1619 oip->i_flag |= ICHG;
1620 ITIMES_NOLOCK(oip);
1621 mutex_exit(&oip->i_tlock);
1622 }
1623 return (error);
1624 }
1625
1626 /*
1627 * Update the pages of the file. If the file is not being
1628 * truncated to a block boundary, the contents of the
1629 * pages following the end of the file must be zero'ed
1630 * in case it ever become accessable again because
1631 * of subsequent file growth.
1632 */
1633 if (boff == 0) {
1634 (void) pvn_vplist_dirty(ITOV(oip), length,
1635 ud_putapage, B_INVAL | B_TRUNC, CRED());
1636 } else {
1637 /*
1638 * Make sure that the last block is properly allocated.
1639 * We only really have to do this if the last block is
1640 * actually allocated. Just to be sure, we do it now
1641 * independent of current allocation.
1642 */
1643 error = ud_bmap_write(oip, length - 1, boff, 0, cr);
1644 if (error) {
1645 return (error);
1646 }
1647
1648 pvn_vpzero(ITOV(oip), length, (uint32_t)(bsize - boff));
1649
1650 (void) pvn_vplist_dirty(ITOV(oip), length,
1651 ud_putapage, B_INVAL | B_TRUNC, CRED());
1652 }
1653
1654
1655 /* Free the blocks */
1656 if (oip->i_desc_type == ICB_FLAG_ONE_AD) {
1657 if (length > oip->i_max_emb) {
1658 return (EFBIG);
1659 }
1660 oip->i_size = length;
1661 mutex_enter(&oip->i_tlock);
1662 oip->i_flag |= ICHG|IUPD;
1663 mutex_exit(&oip->i_tlock);
1664 ud_iupdat(oip, 1);
1665 } else {
1666 if ((error = ud_read_icb_till_off(oip, oip->i_size)) != 0) {
1667 return (error);
1668 }
1669
1670 if (oip->i_astrat == STRAT_TYPE4) {
1671 ud_trunc_ext4(oip, length);
1672 } else if (oip->i_astrat == STRAT_TYPE4096) {
1673 ud_trunc_ext4096(oip, length);
1674 }
1675 }
1676
1677 done:
1678 return (0);
1679 }
1680
1681 void
ud_trunc_ext4(struct ud_inode * ip,u_offset_t length)1682 ud_trunc_ext4(struct ud_inode *ip, u_offset_t length)
1683 {
1684 int32_t index, l2b, count, ecount;
1685 int32_t elen, ndent, nient;
1686 u_offset_t ext_beg, ext_end;
1687 struct icb_ext *iext, *icon;
1688 int32_t lbmask, ext_used;
1689 uint32_t loc;
1690 struct icb_ext text;
1691 uint32_t con_freed;
1692
1693 ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) ||
1694 (ip->i_desc_type == ICB_FLAG_LONG_AD));
1695
1696 if (ip->i_ext_used == 0) {
1697 return;
1698 }
1699
1700 ext_used = ip->i_ext_used;
1701
1702 lbmask = ip->i_udf->udf_lbmask;
1703 l2b = ip->i_udf->udf_l2b_shift;
1704
1705 ASSERT(ip->i_ext);
1706
1707 ip->i_lbr = 0;
1708 for (index = 0; index < ext_used; index++) {
1709 iext = &ip->i_ext[index];
1710
1711 /*
1712 * Find the begining and end
1713 * of current extent
1714 */
1715 ext_beg = iext->ib_offset;
1716 ext_end = iext->ib_offset +
1717 ((iext->ib_count + lbmask) & ~lbmask);
1718
1719 /*
1720 * This is the extent that has offset "length"
1721 * make a copy of this extent and
1722 * remember the index. We can use
1723 * it to free blocks
1724 */
1725 if ((length <= ext_end) && (length >= ext_beg)) {
1726 text = *iext;
1727
1728 iext->ib_count = length - ext_beg;
1729 ip->i_ext_used = index + 1;
1730 break;
1731 }
1732 if (iext->ib_flags != IB_UN_RE_AL) {
1733 ip->i_lbr += iext->ib_count >> l2b;
1734 }
1735 }
1736 if (ip->i_ext_used != index) {
1737 if (iext->ib_flags != IB_UN_RE_AL) {
1738 ip->i_lbr +=
1739 ((iext->ib_count + lbmask) & ~lbmask) >> l2b;
1740 }
1741 }
1742
1743 ip->i_size = length;
1744 mutex_enter(&ip->i_tlock);
1745 ip->i_flag |= ICHG|IUPD;
1746 mutex_exit(&ip->i_tlock);
1747 ud_iupdat(ip, 1);
1748
1749 /*
1750 * Free the unused space
1751 */
1752 if (text.ib_flags != IB_UN_RE_AL) {
1753 count = (ext_end - length) >> l2b;
1754 if (count) {
1755 loc = text.ib_block +
1756 (((length - text.ib_offset) + lbmask) >> l2b);
1757 ud_free_space(ip->i_udf->udf_vfs, text.ib_prn,
1758 loc, count);
1759 }
1760 }
1761 for (index = ip->i_ext_used; index < ext_used; index++) {
1762 iext = &ip->i_ext[index];
1763 if (iext->ib_flags != IB_UN_RE_AL) {
1764 count = (iext->ib_count + lbmask) >> l2b;
1765 ud_free_space(ip->i_udf->udf_vfs, iext->ib_prn,
1766 iext->ib_block, count);
1767 }
1768 bzero(iext, sizeof (struct icb_ext));
1769 continue;
1770 }
1771
1772 /*
1773 * release any continuation blocks
1774 */
1775 if (ip->i_con) {
1776
1777 ASSERT(ip->i_con_count >= ip->i_con_used);
1778
1779 /*
1780 * Find out how many indirect blocks
1781 * are required and release the rest
1782 */
1783 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
1784 elen = sizeof (struct short_ad);
1785 } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
1786 elen = sizeof (struct long_ad);
1787 }
1788 ndent = ip->i_max_emb / elen;
1789 if (ip->i_ext_used > ndent) {
1790 ecount = ip->i_ext_used - ndent;
1791 } else {
1792 ecount = 0;
1793 }
1794 con_freed = 0;
1795 for (index = 0; index < ip->i_con_used; index++) {
1796 icon = &ip->i_con[index];
1797 nient = icon->ib_count -
1798 (sizeof (struct alloc_ext_desc) + elen);
1799 /* Header + 1 indirect extent */
1800 nient /= elen;
1801 if (ecount) {
1802 if (ecount > nient) {
1803 ecount -= nient;
1804 } else {
1805 ecount = 0;
1806 }
1807 } else {
1808 count = ((icon->ib_count + lbmask) &
1809 ~lbmask) >> l2b;
1810 ud_free_space(ip->i_udf->udf_vfs,
1811 icon->ib_prn, icon->ib_block, count);
1812 con_freed++;
1813 ip->i_cur_max_ext -= nient;
1814 }
1815 }
1816 /*
1817 * set the continuation extents used(i_con_used)i to correct
1818 * value. It is possible for i_con_used to be zero,
1819 * if we free up all continuation extents. This happens
1820 * when ecount is 0 before entering the for loop above.
1821 */
1822 ip->i_con_used -= con_freed;
1823 if (ip->i_con_read > ip->i_con_used) {
1824 ip->i_con_read = ip->i_con_used;
1825 }
1826 }
1827 }
1828
1829 void
ud_trunc_ext4096(struct ud_inode * ip,u_offset_t length)1830 ud_trunc_ext4096(struct ud_inode *ip, u_offset_t length)
1831 {
1832 /*
1833 * Truncate code is the same for
1834 * both file of type 4 and 4096
1835 */
1836 ud_trunc_ext4(ip, length);
1837 }
1838
1839 /*
1840 * Remove any inodes in the inode cache belonging to dev
1841 *
1842 * There should not be any active ones, return error if any are found but
1843 * still invalidate others (N.B.: this is a user error, not a system error).
1844 *
1845 * Also, count the references to dev by block devices - this really
1846 * has nothing to do with the object of the procedure, but as we have
1847 * to scan the inode table here anyway, we might as well get the
1848 * extra benefit.
1849 */
1850 int32_t
ud_iflush(struct vfs * vfsp)1851 ud_iflush(struct vfs *vfsp)
1852 {
1853 int32_t index, busy = 0;
1854 union ihead *ih;
1855 struct udf_vfs *udf_vfsp;
1856 dev_t dev;
1857 struct vnode *rvp, *vp;
1858 struct ud_inode *ip, *next;
1859
1860 ud_printf("ud_iflush\n");
1861 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1862 rvp = udf_vfsp->udf_root;
1863 dev = vfsp->vfs_dev;
1864
1865 mutex_enter(&ud_icache_lock);
1866 for (index = 0; index < UD_HASH_SZ; index++) {
1867 ih = &ud_ihead[index];
1868
1869 next = ih->ih_chain[0];
1870 while (next != (struct ud_inode *)ih) {
1871 ip = next;
1872 next = ip->i_forw;
1873 if (ip->i_dev != dev) {
1874 continue;
1875 }
1876 vp = ITOV(ip);
1877 /*
1878 * root inode is processed by the caller
1879 */
1880 if (vp == rvp) {
1881 if (vp->v_count > 1) {
1882 busy = -1;
1883 }
1884 continue;
1885 }
1886 if (ip->i_flag & IREF) {
1887 /*
1888 * Set error indicator for return value,
1889 * but continue invalidating other
1890 * inodes.
1891 */
1892 busy = -1;
1893 continue;
1894 }
1895
1896 rw_enter(&ip->i_contents, RW_WRITER);
1897 remque(ip);
1898 ip->i_forw = ip;
1899 ip->i_back = ip;
1900 /*
1901 * Hold the vnode since its not done
1902 * in VOP_PUTPAGE anymore.
1903 */
1904 VN_HOLD(vp);
1905 /*
1906 * XXX Synchronous write holding
1907 * cache lock
1908 */
1909 (void) ud_syncip(ip, B_INVAL, I_SYNC);
1910 rw_exit(&ip->i_contents);
1911 VN_RELE(vp);
1912 }
1913 }
1914 mutex_exit(&ud_icache_lock);
1915
1916 return (busy);
1917 }
1918
1919
1920 /*
1921 * Check mode permission on inode. Mode is READ, WRITE or EXEC.
1922 * In the case of WRITE, the read-only status of the file system
1923 * is checked. The applicable mode bits are compared with the
1924 * requested form of access. If bits are missing, the secpolicy
1925 * function will check for privileges.
1926 */
1927 int
ud_iaccess(struct ud_inode * ip,int32_t mode,struct cred * cr,int dolock)1928 ud_iaccess(struct ud_inode *ip, int32_t mode, struct cred *cr, int dolock)
1929 {
1930 int shift = 0;
1931 int ret = 0;
1932
1933 if (dolock)
1934 rw_enter(&ip->i_contents, RW_READER);
1935 ASSERT(RW_LOCK_HELD(&ip->i_contents));
1936
1937 ud_printf("ud_iaccess\n");
1938 if (mode & IWRITE) {
1939 /*
1940 * Disallow write attempts on read-only
1941 * file systems, unless the file is a block
1942 * or character device or a FIFO.
1943 */
1944 if (ip->i_udf->udf_flags & UDF_FL_RDONLY) {
1945 if ((ip->i_type != VCHR) &&
1946 (ip->i_type != VBLK) &&
1947 (ip->i_type != VFIFO)) {
1948 ret = EROFS;
1949 goto out;
1950 }
1951 }
1952 }
1953
1954 /*
1955 * Access check is based on only
1956 * one of owner, group, public.
1957 * If not owner, then check group.
1958 * If not a member of the group, then
1959 * check public access.
1960 */
1961 if (crgetuid(cr) != ip->i_uid) {
1962 shift += 5;
1963 if (!groupmember((uid_t)ip->i_gid, cr))
1964 shift += 5;
1965 }
1966
1967 ret = secpolicy_vnode_access2(cr, ITOV(ip), ip->i_uid,
1968 UD2VA_PERM(ip->i_perm << shift), UD2VA_PERM(mode));
1969
1970 out:
1971 if (dolock)
1972 rw_exit(&ip->i_contents);
1973 return (ret);
1974 }
1975
1976 void
ud_imark(struct ud_inode * ip)1977 ud_imark(struct ud_inode *ip)
1978 {
1979 timestruc_t now;
1980
1981 gethrestime(&now);
1982 ud_printf("ud_imark\n");
1983 if (ip->i_flag & IACC) {
1984 ip->i_atime.tv_sec = now.tv_sec;
1985 ip->i_atime.tv_nsec = now.tv_nsec;
1986 }
1987 if (ip->i_flag & IUPD) {
1988 ip->i_mtime.tv_sec = now.tv_sec;
1989 ip->i_mtime.tv_nsec = now.tv_nsec;
1990 ip->i_flag |= IMODTIME;
1991 }
1992 if (ip->i_flag & ICHG) {
1993 ip->i_diroff = 0;
1994 ip->i_ctime.tv_sec = now.tv_sec;
1995 ip->i_ctime.tv_nsec = now.tv_nsec;
1996 }
1997 }
1998
1999
2000 void
ud_itimes_nolock(struct ud_inode * ip)2001 ud_itimes_nolock(struct ud_inode *ip)
2002 {
2003 ud_printf("ud_itimes_nolock\n");
2004
2005 if (ip->i_flag & (IUPD|IACC|ICHG)) {
2006 if (ip->i_flag & ICHG) {
2007 ip->i_flag |= IMOD;
2008 } else {
2009 ip->i_flag |= IMODACC;
2010 }
2011 ud_imark(ip);
2012 ip->i_flag &= ~(IACC|IUPD|ICHG);
2013 }
2014 }
2015
2016 void
ud_delcache(struct ud_inode * ip)2017 ud_delcache(struct ud_inode *ip)
2018 {
2019 ud_printf("ud_delcache\n");
2020
2021 mutex_enter(&ud_icache_lock);
2022 remque(ip);
2023 ip->i_forw = ip;
2024 ip->i_back = ip;
2025 mutex_exit(&ud_icache_lock);
2026 }
2027
2028 void
ud_idrop(struct ud_inode * ip)2029 ud_idrop(struct ud_inode *ip)
2030 {
2031 struct vnode *vp = ITOV(ip);
2032
2033 ASSERT(RW_WRITE_HELD(&ip->i_contents));
2034
2035 ud_printf("ud_idrop\n");
2036
2037 mutex_enter(&vp->v_lock);
2038 if (vp->v_count > 1) {
2039 vp->v_count--;
2040 mutex_exit(&vp->v_lock);
2041 return;
2042 }
2043 vp->v_count = 0;
2044 mutex_exit(&vp->v_lock);
2045
2046
2047 /*
2048 * if inode is invalid or there is no page associated with
2049 * this inode, put the inode in the front of the free list
2050 */
2051 mutex_enter(&ip->i_tlock);
2052 mutex_enter(&udf_ifree_lock);
2053 if (!vn_has_cached_data(vp) || ip->i_perm == 0) {
2054 ud_add_to_free_list(ip, UD_BEGIN);
2055 } else {
2056 /*
2057 * Otherwise, put the inode back on the end of the free list.
2058 */
2059 ud_add_to_free_list(ip, UD_END);
2060 }
2061 mutex_exit(&udf_ifree_lock);
2062 ip->i_flag &= IMODTIME;
2063 mutex_exit(&ip->i_tlock);
2064 }
2065
2066 void
ud_add_to_free_list(struct ud_inode * ip,uint32_t at)2067 ud_add_to_free_list(struct ud_inode *ip, uint32_t at)
2068 {
2069 ASSERT(ip);
2070 ASSERT(mutex_owned(&udf_ifree_lock));
2071
2072 #ifdef DEBUG
2073 /* Search if the element is already in the list */
2074 if (udf_ifreeh != NULL) {
2075 struct ud_inode *iq;
2076
2077 iq = udf_ifreeh;
2078 while (iq) {
2079 if (iq == ip) {
2080 cmn_err(CE_WARN, "Duplicate %p\n", (void *)ip);
2081 }
2082 iq = iq->i_freef;
2083 }
2084 }
2085 #endif
2086
2087 ip->i_freef = NULL;
2088 ip->i_freeb = NULL;
2089 if (udf_ifreeh == NULL) {
2090 /*
2091 * Nothing on the list just add it
2092 */
2093 udf_ifreeh = ip;
2094 udf_ifreet = ip;
2095 } else {
2096 if (at == UD_BEGIN) {
2097 /*
2098 * Add at the begining of the list
2099 */
2100 ip->i_freef = udf_ifreeh;
2101 udf_ifreeh->i_freeb = ip;
2102 udf_ifreeh = ip;
2103 } else {
2104 /*
2105 * Add at the end of the list
2106 */
2107 ip->i_freeb = udf_ifreet;
2108 udf_ifreet->i_freef = ip;
2109 udf_ifreet = ip;
2110 }
2111 }
2112 }
2113
2114 void
ud_remove_from_free_list(struct ud_inode * ip,uint32_t at)2115 ud_remove_from_free_list(struct ud_inode *ip, uint32_t at)
2116 {
2117 ASSERT(ip);
2118 ASSERT(mutex_owned(&udf_ifree_lock));
2119
2120 #ifdef DEBUG
2121 {
2122 struct ud_inode *iq;
2123 uint32_t found = 0;
2124
2125 iq = udf_ifreeh;
2126 while (iq) {
2127 if (iq == ip) {
2128 found++;
2129 }
2130 iq = iq->i_freef;
2131 }
2132 if (found != 1) {
2133 cmn_err(CE_WARN, "ip %p is found %x times\n",
2134 (void *)ip, found);
2135 }
2136 }
2137 #endif
2138
2139 if ((ip->i_freef == NULL) && (ip->i_freeb == NULL)) {
2140 if (ip != udf_ifreeh) {
2141 return;
2142 }
2143 }
2144
2145 if ((at == UD_BEGIN) || (ip == udf_ifreeh)) {
2146 udf_ifreeh = ip->i_freef;
2147 if (ip->i_freef == NULL) {
2148 udf_ifreet = NULL;
2149 } else {
2150 udf_ifreeh->i_freeb = NULL;
2151 }
2152 } else {
2153 ip->i_freeb->i_freef = ip->i_freef;
2154 if (ip->i_freef) {
2155 ip->i_freef->i_freeb = ip->i_freeb;
2156 } else {
2157 udf_ifreet = ip->i_freeb;
2158 }
2159 }
2160 ip->i_freef = NULL;
2161 ip->i_freeb = NULL;
2162 }
2163
2164 void
ud_init_inodes(void)2165 ud_init_inodes(void)
2166 {
2167 union ihead *ih = ud_ihead;
2168 int index;
2169
2170 #ifndef __lint
2171 _NOTE(NO_COMPETING_THREADS_NOW);
2172 #endif
2173 for (index = 0; index < UD_HASH_SZ; index++, ih++) {
2174 ih->ih_head[0] = ih;
2175 ih->ih_head[1] = ih;
2176 }
2177 mutex_init(&ud_icache_lock, NULL, MUTEX_DEFAULT, NULL);
2178 mutex_init(&ud_nino_lock, NULL, MUTEX_DEFAULT, NULL);
2179
2180 udf_ifreeh = NULL;
2181 udf_ifreet = NULL;
2182 mutex_init(&udf_ifree_lock, NULL, MUTEX_DEFAULT, NULL);
2183
2184 mutex_init(&ud_sync_busy, NULL, MUTEX_DEFAULT, NULL);
2185 udf_vfs_instances = NULL;
2186 mutex_init(&udf_vfs_mutex, NULL, MUTEX_DEFAULT, NULL);
2187
2188 #ifndef __lint
2189 _NOTE(COMPETING_THREADS_NOW);
2190 #endif
2191 }
2192