xref: /illumos-gate/usr/src/uts/common/fs/udfs/udf_inode.c (revision ade42b55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b39a0235SMilan Cermak  * Common Development and Distribution License (the "License").
6b39a0235SMilan Cermak  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22b39a0235SMilan Cermak  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23*ade42b55SSebastien Roy  * Copyright (c) 2017 by Delphix. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
287c478bd9Sstevel@tonic-gate #include <sys/param.h>
297c478bd9Sstevel@tonic-gate #include <sys/time.h>
307c478bd9Sstevel@tonic-gate #include <sys/systm.h>
317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
327c478bd9Sstevel@tonic-gate #include <sys/resource.h>
337c478bd9Sstevel@tonic-gate #include <sys/signal.h>
347c478bd9Sstevel@tonic-gate #include <sys/cred.h>
357c478bd9Sstevel@tonic-gate #include <sys/user.h>
367c478bd9Sstevel@tonic-gate #include <sys/buf.h>
377c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
387c478bd9Sstevel@tonic-gate #include <sys/stat.h>
397c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
407c478bd9Sstevel@tonic-gate #include <sys/mode.h>
417c478bd9Sstevel@tonic-gate #include <sys/proc.h>
427c478bd9Sstevel@tonic-gate #include <sys/disp.h>
437c478bd9Sstevel@tonic-gate #include <sys/file.h>
447c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
457c478bd9Sstevel@tonic-gate #include <sys/flock.h>
467c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
477c478bd9Sstevel@tonic-gate #include <sys/uio.h>
487c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
497c478bd9Sstevel@tonic-gate #include <sys/conf.h>
507c478bd9Sstevel@tonic-gate #include <sys/errno.h>
517c478bd9Sstevel@tonic-gate #include <sys/mman.h>
527c478bd9Sstevel@tonic-gate #include <sys/fbuf.h>
537c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
547c478bd9Sstevel@tonic-gate #include <sys/debug.h>
557c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
567c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
577c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
587c478bd9Sstevel@tonic-gate #include <sys/errno.h>
597c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
607c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
617c478bd9Sstevel@tonic-gate #include <sys/mount.h>
627c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
637c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
647c478bd9Sstevel@tonic-gate #include <sys/policy.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #include <vm/hat.h>
677c478bd9Sstevel@tonic-gate #include <vm/page.h>
687c478bd9Sstevel@tonic-gate #include <vm/pvn.h>
697c478bd9Sstevel@tonic-gate #include <vm/as.h>
707c478bd9Sstevel@tonic-gate #include <vm/seg.h>
717c478bd9Sstevel@tonic-gate #include <vm/seg_map.h>
727c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
737c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
747c478bd9Sstevel@tonic-gate #include <vm/rm.h>
757c478bd9Sstevel@tonic-gate #include <vm/page.h>
767c478bd9Sstevel@tonic-gate #include <sys/swap.h>
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
837c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h>
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate extern struct vnodeops *udf_vnodeops;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate kmutex_t ud_sync_busy;
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * udf_vfs list manipulation routines
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate kmutex_t udf_vfs_mutex;
927c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfs_instances;
937c478bd9Sstevel@tonic-gate #ifndef	__lint
947c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_vfs_mutex, udf_vfs_instances))
957c478bd9Sstevel@tonic-gate #endif
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate union ihead ud_ihead[UD_HASH_SZ];
987c478bd9Sstevel@tonic-gate kmutex_t ud_icache_lock;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	UD_BEGIN	0x0
1017c478bd9Sstevel@tonic-gate #define	UD_END		0x1
1027c478bd9Sstevel@tonic-gate #define	UD_UNKN		0x2
1037c478bd9Sstevel@tonic-gate struct ud_inode *udf_ifreeh, *udf_ifreet;
1047c478bd9Sstevel@tonic-gate kmutex_t udf_ifree_lock;
1057c478bd9Sstevel@tonic-gate #ifndef	__lint
1067c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreeh))
1077c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreet))
1087c478bd9Sstevel@tonic-gate #endif
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate kmutex_t ud_nino_lock;
1117c478bd9Sstevel@tonic-gate int32_t ud_max_inodes = 512;
1127c478bd9Sstevel@tonic-gate int32_t ud_cur_inodes = 0;
1137c478bd9Sstevel@tonic-gate #ifndef	__lint
1147c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ud_nino_lock, ud_cur_inodes))
1157c478bd9Sstevel@tonic-gate #endif
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate uid_t ud_default_uid = 0;
1187c478bd9Sstevel@tonic-gate gid_t ud_default_gid = 3;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate int32_t ud_updat_ext4(struct ud_inode *, struct file_entry *);
1217c478bd9Sstevel@tonic-gate int32_t ud_updat_ext4096(struct ud_inode *, struct file_entry *);
1227c478bd9Sstevel@tonic-gate void ud_make_sad(struct icb_ext *, struct short_ad *, int32_t);
1237c478bd9Sstevel@tonic-gate void ud_make_lad(struct icb_ext *, struct long_ad *, int32_t);
1247c478bd9Sstevel@tonic-gate void ud_trunc_ext4(struct ud_inode *, u_offset_t);
1257c478bd9Sstevel@tonic-gate void ud_trunc_ext4096(struct ud_inode *, u_offset_t);
1267c478bd9Sstevel@tonic-gate void ud_add_to_free_list(struct ud_inode *, uint32_t);
1277c478bd9Sstevel@tonic-gate void ud_remove_from_free_list(struct ud_inode *, uint32_t);
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1317c478bd9Sstevel@tonic-gate struct ud_inode *
ud_search_icache(struct vfs * vfsp,uint16_t prn,uint32_t ploc)1327c478bd9Sstevel@tonic-gate ud_search_icache(struct vfs *vfsp, uint16_t prn, uint32_t ploc)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 	int32_t hno;
1357c478bd9Sstevel@tonic-gate 	union ihead *ih;
1367c478bd9Sstevel@tonic-gate 	struct ud_inode *ip;
1377c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
1387c478bd9Sstevel@tonic-gate 	uint32_t loc, dummy;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1417c478bd9Sstevel@tonic-gate 	loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_icache_lock);
1447c478bd9Sstevel@tonic-gate 	hno = UD_INOHASH(vfsp->vfs_dev, loc);
1457c478bd9Sstevel@tonic-gate 	ih = &ud_ihead[hno];
1467c478bd9Sstevel@tonic-gate 	for (ip = ih->ih_chain[0];
147b39a0235SMilan Cermak 	    ip != (struct ud_inode *)ih;
148b39a0235SMilan Cermak 	    ip = ip->i_forw) {
149b39a0235SMilan Cermak 		if ((prn == ip->i_icb_prn) && (ploc == ip->i_icb_block) &&
150b39a0235SMilan Cermak 		    (vfsp->vfs_dev == ip->i_dev)) {
1517c478bd9Sstevel@tonic-gate 			mutex_exit(&ud_icache_lock);
1527c478bd9Sstevel@tonic-gate 			return (ip);
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_icache_lock);
1567c478bd9Sstevel@tonic-gate 	return (0);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate #endif
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate /* ARGSUSED */
1617c478bd9Sstevel@tonic-gate int
ud_iget(struct vfs * vfsp,uint16_t prn,uint32_t ploc,struct ud_inode ** ipp,struct buf * pbp,struct cred * cred)162*ade42b55SSebastien Roy ud_iget(struct vfs *vfsp, uint16_t prn, uint32_t ploc, struct ud_inode **ipp,
163*ade42b55SSebastien Roy     struct buf *pbp, struct cred *cred)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	int32_t hno, nomem = 0, icb_tag_flags;
1667c478bd9Sstevel@tonic-gate 	union ihead *ih;
1677c478bd9Sstevel@tonic-gate 	struct ud_inode *ip;
1687c478bd9Sstevel@tonic-gate 	struct vnode *vp;
1697c478bd9Sstevel@tonic-gate 	struct buf *bp = NULL;
1707c478bd9Sstevel@tonic-gate 	struct file_entry *fe;
1717c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
1727c478bd9Sstevel@tonic-gate 	struct ext_attr_hdr *eah;
1737c478bd9Sstevel@tonic-gate 	struct attr_hdr *ah;
1747c478bd9Sstevel@tonic-gate 	int32_t ea_len, ea_off;
1757c478bd9Sstevel@tonic-gate 	daddr_t loc;
1767c478bd9Sstevel@tonic-gate 	uint64_t offset = 0;
1777c478bd9Sstevel@tonic-gate 	struct icb_ext *iext, *con;
1787c478bd9Sstevel@tonic-gate 	uint32_t length, dummy;
1797c478bd9Sstevel@tonic-gate 	int32_t ndesc, ftype;
1807c478bd9Sstevel@tonic-gate 	uint16_t old_prn;
1817c478bd9Sstevel@tonic-gate 	uint32_t old_block, old_lbano;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	ud_printf("ud_iget\n");
1847c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1857c478bd9Sstevel@tonic-gate 	old_prn = 0;
1867c478bd9Sstevel@tonic-gate 	old_block = old_lbano = 0;
1877c478bd9Sstevel@tonic-gate 	ftype = 0;
1887c478bd9Sstevel@tonic-gate 	loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy);
1897c478bd9Sstevel@tonic-gate loop:
1907c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_icache_lock);
1917c478bd9Sstevel@tonic-gate 	hno = UD_INOHASH(vfsp->vfs_dev, loc);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	ih = &ud_ihead[hno];
1947c478bd9Sstevel@tonic-gate 	for (ip = ih->ih_chain[0];
195b39a0235SMilan Cermak 	    ip != (struct ud_inode *)ih;
196b39a0235SMilan Cermak 	    ip = ip->i_forw) {
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		if ((prn == ip->i_icb_prn) &&
199b39a0235SMilan Cermak 		    (ploc == ip->i_icb_block) &&
200b39a0235SMilan Cermak 		    (vfsp->vfs_dev == ip->i_dev)) {
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 			vp = ITOV(ip);
2037c478bd9Sstevel@tonic-gate 			VN_HOLD(vp);
2047c478bd9Sstevel@tonic-gate 			mutex_exit(&ud_icache_lock);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 			rw_enter(&ip->i_contents, RW_READER);
2077c478bd9Sstevel@tonic-gate 			mutex_enter(&ip->i_tlock);
2087c478bd9Sstevel@tonic-gate 			if ((ip->i_flag & IREF) == 0) {
2097c478bd9Sstevel@tonic-gate 				mutex_enter(&udf_ifree_lock);
2107c478bd9Sstevel@tonic-gate 				ud_remove_from_free_list(ip, UD_UNKN);
2117c478bd9Sstevel@tonic-gate 				mutex_exit(&udf_ifree_lock);
2127c478bd9Sstevel@tonic-gate 			}
2137c478bd9Sstevel@tonic-gate 			ip->i_flag |= IREF;
2147c478bd9Sstevel@tonic-gate 			mutex_exit(&ip->i_tlock);
2157c478bd9Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 			*ipp = ip;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 			if (pbp != NULL) {
2207c478bd9Sstevel@tonic-gate 				brelse(pbp);
2217c478bd9Sstevel@tonic-gate 			}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 			return (0);
2247c478bd9Sstevel@tonic-gate 		}
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/*
2287c478bd9Sstevel@tonic-gate 	 * We don't have it in the cache
2297c478bd9Sstevel@tonic-gate 	 * Allocate a new entry
2307c478bd9Sstevel@tonic-gate 	 */
2317c478bd9Sstevel@tonic-gate tryagain:
2327c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_ifree_lock);
2337c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_nino_lock);
2347c478bd9Sstevel@tonic-gate 	if (ud_cur_inodes > ud_max_inodes) {
2357c478bd9Sstevel@tonic-gate 		int32_t purged;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
2387c478bd9Sstevel@tonic-gate 		while (udf_ifreeh == NULL ||
2397c478bd9Sstevel@tonic-gate 		    vn_has_cached_data(ITOV(udf_ifreeh))) {
2407c478bd9Sstevel@tonic-gate 			/*
2417c478bd9Sstevel@tonic-gate 			 * Try to put an inode on the freelist that's
2427c478bd9Sstevel@tonic-gate 			 * sitting in the dnlc.
2437c478bd9Sstevel@tonic-gate 			 */
2447c478bd9Sstevel@tonic-gate 			mutex_exit(&udf_ifree_lock);
2457c478bd9Sstevel@tonic-gate 			purged = dnlc_fs_purge1(udf_vnodeops);
2467c478bd9Sstevel@tonic-gate 			mutex_enter(&udf_ifree_lock);
2477c478bd9Sstevel@tonic-gate 			if (!purged) {
2487c478bd9Sstevel@tonic-gate 				break;
2497c478bd9Sstevel@tonic-gate 			}
2507c478bd9Sstevel@tonic-gate 		}
2517c478bd9Sstevel@tonic-gate 		mutex_enter(&ud_nino_lock);
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	/*
2557c478bd9Sstevel@tonic-gate 	 * If there's a free one available and it has no pages attached
2567c478bd9Sstevel@tonic-gate 	 * take it. If we're over the high water mark, take it even if
2577c478bd9Sstevel@tonic-gate 	 * it has attached pages. Otherwise, make a new one.
2587c478bd9Sstevel@tonic-gate 	 */
2597c478bd9Sstevel@tonic-gate 	if (udf_ifreeh &&
260b39a0235SMilan Cermak 	    (nomem || !vn_has_cached_data(ITOV(udf_ifreeh)) ||
261b39a0235SMilan Cermak 	    ud_cur_inodes >= ud_max_inodes)) {
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
2647c478bd9Sstevel@tonic-gate 		ip = udf_ifreeh;
2657c478bd9Sstevel@tonic-gate 		vp = ITOV(ip);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		ud_remove_from_free_list(ip, UD_BEGIN);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_ifree_lock);
2707c478bd9Sstevel@tonic-gate 		if (ip->i_flag & IREF) {
2717c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "ud_iget: bad i_flag\n");
2727c478bd9Sstevel@tonic-gate 			mutex_exit(&ud_icache_lock);
2737c478bd9Sstevel@tonic-gate 			if (pbp != NULL) {
2747c478bd9Sstevel@tonic-gate 				brelse(pbp);
2757c478bd9Sstevel@tonic-gate 			}
2767c478bd9Sstevel@tonic-gate 			return (EINVAL);
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 		/*
2817c478bd9Sstevel@tonic-gate 		 * We call udf_syncip() to synchronously destroy all pages
2827c478bd9Sstevel@tonic-gate 		 * associated with the vnode before re-using it. The pageout
2837c478bd9Sstevel@tonic-gate 		 * thread may have beat us to this page so our v_count can
2847c478bd9Sstevel@tonic-gate 		 * be > 0 at this point even though we are on the freelist.
2857c478bd9Sstevel@tonic-gate 		 */
2867c478bd9Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
2877c478bd9Sstevel@tonic-gate 		ip->i_flag = (ip->i_flag & IMODTIME) | IREF;
2887c478bd9Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 		VN_HOLD(vp);
2917c478bd9Sstevel@tonic-gate 		if (ud_syncip(ip, B_INVAL, I_SYNC) != 0) {
2927c478bd9Sstevel@tonic-gate 			ud_idrop(ip);
2937c478bd9Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
2947c478bd9Sstevel@tonic-gate 			mutex_exit(&ud_icache_lock);
2957c478bd9Sstevel@tonic-gate 			goto loop;
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
2997c478bd9Sstevel@tonic-gate 		ip->i_flag &= ~IMODTIME;
3007c478bd9Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		if (ip->i_ext) {
3037c478bd9Sstevel@tonic-gate 			kmem_free(ip->i_ext,
304b39a0235SMilan Cermak 			    sizeof (struct icb_ext) * ip->i_ext_count);
3057c478bd9Sstevel@tonic-gate 			ip->i_ext = 0;
3067c478bd9Sstevel@tonic-gate 			ip->i_ext_count = ip->i_ext_used = 0;
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 		if (ip->i_con) {
3107c478bd9Sstevel@tonic-gate 			kmem_free(ip->i_con,
311b39a0235SMilan Cermak 			    sizeof (struct icb_ext) * ip->i_con_count);
3127c478bd9Sstevel@tonic-gate 			ip->i_con = 0;
3137c478bd9Sstevel@tonic-gate 			ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 		/*
3177c478bd9Sstevel@tonic-gate 		 * The pageout thread may not have had a chance to release
3187c478bd9Sstevel@tonic-gate 		 * its hold on the vnode (if it was active with this vp),
3197c478bd9Sstevel@tonic-gate 		 * but the pages should all be invalidated.
3207c478bd9Sstevel@tonic-gate 		 */
3217c478bd9Sstevel@tonic-gate 	} else {
3227c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
3237c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_ifree_lock);
3247c478bd9Sstevel@tonic-gate 		/*
3257c478bd9Sstevel@tonic-gate 		 * Try to get memory for this inode without blocking.
3267c478bd9Sstevel@tonic-gate 		 * If we can't and there is something on the freelist,
3277c478bd9Sstevel@tonic-gate 		 * go ahead and use it, otherwise block waiting for
3287c478bd9Sstevel@tonic-gate 		 * memory holding the hash_lock. We expose a potential
3297c478bd9Sstevel@tonic-gate 		 * deadlock if all users of memory have to do a ud_iget()
3307c478bd9Sstevel@tonic-gate 		 * before releasing memory.
3317c478bd9Sstevel@tonic-gate 		 */
3327c478bd9Sstevel@tonic-gate 		ip = (struct ud_inode *)kmem_zalloc(sizeof (struct ud_inode),
333b39a0235SMilan Cermak 		    KM_NOSLEEP);
3347c478bd9Sstevel@tonic-gate 		vp = vn_alloc(KM_NOSLEEP);
3357c478bd9Sstevel@tonic-gate 		if ((ip == NULL) || (vp == NULL)) {
3367c478bd9Sstevel@tonic-gate 			mutex_enter(&udf_ifree_lock);
3377c478bd9Sstevel@tonic-gate 			if (udf_ifreeh) {
3387c478bd9Sstevel@tonic-gate 				mutex_exit(&udf_ifree_lock);
3397c478bd9Sstevel@tonic-gate 				if (ip != NULL)
3407c478bd9Sstevel@tonic-gate 					kmem_free(ip, sizeof (struct ud_inode));
3417c478bd9Sstevel@tonic-gate 				if (vp != NULL)
3427c478bd9Sstevel@tonic-gate 					vn_free(vp);
3437c478bd9Sstevel@tonic-gate 				nomem = 1;
3447c478bd9Sstevel@tonic-gate 				goto tryagain;
3457c478bd9Sstevel@tonic-gate 			} else {
3467c478bd9Sstevel@tonic-gate 				mutex_exit(&udf_ifree_lock);
3477c478bd9Sstevel@tonic-gate 				if (ip == NULL)
3487c478bd9Sstevel@tonic-gate 					ip = (struct ud_inode *)
3497c478bd9Sstevel@tonic-gate 					    kmem_zalloc(
350b39a0235SMilan Cermak 					    sizeof (struct ud_inode),
351b39a0235SMilan Cermak 					    KM_SLEEP);
3527c478bd9Sstevel@tonic-gate 				if (vp == NULL)
3537c478bd9Sstevel@tonic-gate 					vp = vn_alloc(KM_SLEEP);
3547c478bd9Sstevel@tonic-gate 			}
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 		ip->i_vnode = vp;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		ip->i_marker1 = (uint32_t)0xAAAAAAAA;
3597c478bd9Sstevel@tonic-gate 		ip->i_marker2 = (uint32_t)0xBBBBBBBB;
3607c478bd9Sstevel@tonic-gate 		ip->i_marker3 = (uint32_t)0xCCCCCCCC;
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 		rw_init(&ip->i_rwlock, NULL, RW_DEFAULT, NULL);
3637c478bd9Sstevel@tonic-gate 		rw_init(&ip->i_contents, NULL, RW_DEFAULT, NULL);
3647c478bd9Sstevel@tonic-gate 		mutex_init(&ip->i_tlock, NULL, MUTEX_DEFAULT, NULL);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 		ip->i_forw = ip;
3677c478bd9Sstevel@tonic-gate 		ip->i_back = ip;
3687c478bd9Sstevel@tonic-gate 		vp->v_data = (caddr_t)ip;
3697c478bd9Sstevel@tonic-gate 		vn_setops(vp, udf_vnodeops);
3707c478bd9Sstevel@tonic-gate 		ip->i_flag = IREF;
3717c478bd9Sstevel@tonic-gate 		cv_init(&ip->i_wrcv, NULL, CV_DRIVER, NULL);
3727c478bd9Sstevel@tonic-gate 		mutex_enter(&ud_nino_lock);
3737c478bd9Sstevel@tonic-gate 		ud_cur_inodes++;
3747c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (vp->v_count < 1) {
3807c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ud_iget: v_count < 1\n");
3817c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_icache_lock);
3827c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
3837c478bd9Sstevel@tonic-gate 		if (pbp != NULL) {
3847c478bd9Sstevel@tonic-gate 			brelse(pbp);
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 		return (EINVAL);
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 	if (vn_has_cached_data(vp)) {
3897c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ud_iget: v_pages not NULL\n");
3907c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_icache_lock);
3917c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
3927c478bd9Sstevel@tonic-gate 		if (pbp != NULL) {
3937c478bd9Sstevel@tonic-gate 			brelse(pbp);
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 		return (EINVAL);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	/*
3997c478bd9Sstevel@tonic-gate 	 * Move the inode on the chain for its new (ino, dev) pair
4007c478bd9Sstevel@tonic-gate 	 */
4017c478bd9Sstevel@tonic-gate 	remque(ip);
4027c478bd9Sstevel@tonic-gate 	ip->i_forw = ip;
4037c478bd9Sstevel@tonic-gate 	ip->i_back = ip;
4047c478bd9Sstevel@tonic-gate 	insque(ip, ih);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	ip->i_dev = vfsp->vfs_dev;
4077c478bd9Sstevel@tonic-gate 	ip->i_udf = udf_vfsp;
4087c478bd9Sstevel@tonic-gate 	ip->i_diroff = 0;
4097c478bd9Sstevel@tonic-gate 	ip->i_devvp = ip->i_udf->udf_devvp;
4107c478bd9Sstevel@tonic-gate 	ip->i_icb_prn = prn;
4117c478bd9Sstevel@tonic-gate 	ip->i_icb_block = ploc;
4127c478bd9Sstevel@tonic-gate 	ip->i_icb_lbano = loc;
4137c478bd9Sstevel@tonic-gate 	ip->i_nextr = 0;
4147c478bd9Sstevel@tonic-gate 	ip->i_seq = 0;
4157c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_icache_lock);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate read_de:
4187c478bd9Sstevel@tonic-gate 	if (pbp != NULL) {
4197c478bd9Sstevel@tonic-gate 		/*
4207c478bd9Sstevel@tonic-gate 		 * assumption is that we will not
4217c478bd9Sstevel@tonic-gate 		 * create a 4096 file
4227c478bd9Sstevel@tonic-gate 		 */
4237c478bd9Sstevel@tonic-gate 		bp = pbp;
4247c478bd9Sstevel@tonic-gate 	} else {
4257c478bd9Sstevel@tonic-gate 		bp = ud_bread(ip->i_dev,
426b39a0235SMilan Cermak 		    ip->i_icb_lbano << udf_vfsp->udf_l2d_shift,
427b39a0235SMilan Cermak 		    udf_vfsp->udf_lbsize);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	/*
4317c478bd9Sstevel@tonic-gate 	 * Check I/O errors
4327c478bd9Sstevel@tonic-gate 	 */
4337c478bd9Sstevel@tonic-gate 	fe = (struct file_entry *)bp->b_un.b_addr;
4347c478bd9Sstevel@tonic-gate 	if ((bp->b_flags & B_ERROR) ||
4357c478bd9Sstevel@tonic-gate 	    (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
4367c478bd9Sstevel@tonic-gate 	    ip->i_icb_block, 1, udf_vfsp->udf_lbsize) != 0)) {
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 		if (((bp->b_flags & B_ERROR) == 0) &&
439b39a0235SMilan Cermak 		    (ftype == STRAT_TYPE4096)) {
4407c478bd9Sstevel@tonic-gate 			if (ud_check_te_unrec(udf_vfsp,
441b39a0235SMilan Cermak 			    bp->b_un.b_addr, ip->i_icb_block) == 0) {
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 				brelse(bp);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 				/*
4467c478bd9Sstevel@tonic-gate 				 * restore old file entry location
4477c478bd9Sstevel@tonic-gate 				 */
4487c478bd9Sstevel@tonic-gate 				ip->i_icb_prn = old_prn;
4497c478bd9Sstevel@tonic-gate 				ip->i_icb_block = old_block;
4507c478bd9Sstevel@tonic-gate 				ip->i_icb_lbano = old_lbano;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 				/*
4537c478bd9Sstevel@tonic-gate 				 * reread old file entry
4547c478bd9Sstevel@tonic-gate 				 */
4557c478bd9Sstevel@tonic-gate 				bp = ud_bread(ip->i_dev,
456b39a0235SMilan Cermak 				    old_lbano << udf_vfsp->udf_l2d_shift,
457b39a0235SMilan Cermak 				    udf_vfsp->udf_lbsize);
4587c478bd9Sstevel@tonic-gate 				if ((bp->b_flags & B_ERROR) == 0) {
4597c478bd9Sstevel@tonic-gate 					fe = (struct file_entry *)
460b39a0235SMilan Cermak 					    bp->b_un.b_addr;
4617c478bd9Sstevel@tonic-gate 					if (ud_verify_tag_and_desc(&fe->fe_tag,
462b39a0235SMilan Cermak 					    UD_FILE_ENTRY, ip->i_icb_block, 1,
4637c478bd9Sstevel@tonic-gate 					    udf_vfsp->udf_lbsize) == 0) {
4647c478bd9Sstevel@tonic-gate 						goto end_4096;
4657c478bd9Sstevel@tonic-gate 					}
4667c478bd9Sstevel@tonic-gate 				}
4677c478bd9Sstevel@tonic-gate 			}
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate error_ret:
4707c478bd9Sstevel@tonic-gate 		brelse(bp);
4717c478bd9Sstevel@tonic-gate 		/*
4727c478bd9Sstevel@tonic-gate 		 * The inode may not contain anything useful. Mark it as
4737c478bd9Sstevel@tonic-gate 		 * having an error and let anyone else who was waiting for
4747c478bd9Sstevel@tonic-gate 		 * this know there was an error. Callers waiting for
4757c478bd9Sstevel@tonic-gate 		 * access to this inode in ud_iget will find
4767c478bd9Sstevel@tonic-gate 		 * the i_icb_lbano == 0, so there won't be a match.
4777c478bd9Sstevel@tonic-gate 		 * It remains in the cache. Put it back on the freelist.
4787c478bd9Sstevel@tonic-gate 		 */
4797c478bd9Sstevel@tonic-gate 		mutex_enter(&vp->v_lock);
480*ade42b55SSebastien Roy 		VN_RELE_LOCKED(vp);
4817c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
4827c478bd9Sstevel@tonic-gate 		ip->i_icb_lbano = 0;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 		/*
4857c478bd9Sstevel@tonic-gate 		 * The folowing two lines make
4867c478bd9Sstevel@tonic-gate 		 * it impossible for any one do
4877c478bd9Sstevel@tonic-gate 		 * a VN_HOLD and then a VN_RELE
4887c478bd9Sstevel@tonic-gate 		 * so avoiding a ud_iinactive
4897c478bd9Sstevel@tonic-gate 		 */
4907c478bd9Sstevel@tonic-gate 		ip->i_icb_prn = 0xffff;
4917c478bd9Sstevel@tonic-gate 		ip->i_icb_block = 0;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 		/*
4947c478bd9Sstevel@tonic-gate 		 * remove the bad inode from hash chains
4957c478bd9Sstevel@tonic-gate 		 * so that during unmount we will not
4967c478bd9Sstevel@tonic-gate 		 * go through this inode
4977c478bd9Sstevel@tonic-gate 		 */
4987c478bd9Sstevel@tonic-gate 		mutex_enter(&ud_icache_lock);
4997c478bd9Sstevel@tonic-gate 		remque(ip);
5007c478bd9Sstevel@tonic-gate 		ip->i_forw = ip;
5017c478bd9Sstevel@tonic-gate 		ip->i_back = ip;
5027c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_icache_lock);
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 		/* Put the inode at the front of the freelist */
5057c478bd9Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
5067c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_ifree_lock);
5077c478bd9Sstevel@tonic-gate 		ud_add_to_free_list(ip, UD_BEGIN);
5087c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_ifree_lock);
5097c478bd9Sstevel@tonic-gate 		ip->i_flag = 0;
5107c478bd9Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
5117c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
5127c478bd9Sstevel@tonic-gate 		return (EIO);
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) {
5167c478bd9Sstevel@tonic-gate 		struct buf *ibp = NULL;
5177c478bd9Sstevel@tonic-gate 		struct indirect_entry *ie;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		/*
5207c478bd9Sstevel@tonic-gate 		 * save old file_entry location
5217c478bd9Sstevel@tonic-gate 		 */
5227c478bd9Sstevel@tonic-gate 		old_prn = ip->i_icb_prn;
5237c478bd9Sstevel@tonic-gate 		old_block = ip->i_icb_block;
5247c478bd9Sstevel@tonic-gate 		old_lbano = ip->i_icb_lbano;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		ftype = STRAT_TYPE4096;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		/*
5297c478bd9Sstevel@tonic-gate 		 * If astrat is 4096 different versions
5307c478bd9Sstevel@tonic-gate 		 * of the file exist on the media.
5317c478bd9Sstevel@tonic-gate 		 * we are supposed to get to the latest
5327c478bd9Sstevel@tonic-gate 		 * version of the file
5337c478bd9Sstevel@tonic-gate 		 */
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		/*
5367c478bd9Sstevel@tonic-gate 		 * IE is supposed to be in the next block
5377c478bd9Sstevel@tonic-gate 		 * of DE
5387c478bd9Sstevel@tonic-gate 		 */
539b39a0235SMilan Cermak 		ibp = ud_bread(ip->i_dev,
540b39a0235SMilan Cermak 		    (ip->i_icb_lbano + 1) << udf_vfsp->udf_l2d_shift,
541b39a0235SMilan Cermak 		    udf_vfsp->udf_lbsize);
5427c478bd9Sstevel@tonic-gate 		if (ibp->b_flags & B_ERROR) {
5437c478bd9Sstevel@tonic-gate 			/*
5447c478bd9Sstevel@tonic-gate 			 * Get rid of current ibp and
5457c478bd9Sstevel@tonic-gate 			 * then goto error on DE's bp
5467c478bd9Sstevel@tonic-gate 			 */
5477c478bd9Sstevel@tonic-gate ie_error:
5487c478bd9Sstevel@tonic-gate 			brelse(ibp);
5497c478bd9Sstevel@tonic-gate 			goto error_ret;
5507c478bd9Sstevel@tonic-gate 		}
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		ie = (struct indirect_entry *)ibp->b_un.b_addr;
5537c478bd9Sstevel@tonic-gate 		if (ud_verify_tag_and_desc(&ie->ie_tag,
554b39a0235SMilan Cermak 		    UD_INDIRECT_ENT, ip->i_icb_block + 1,
5557c478bd9Sstevel@tonic-gate 		    1, udf_vfsp->udf_lbsize) == 0) {
5567c478bd9Sstevel@tonic-gate 			struct long_ad *lad;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 			lad = &ie->ie_indirecticb;
5597c478bd9Sstevel@tonic-gate 			ip->i_icb_prn = SWAP_16(lad->lad_ext_prn);
5607c478bd9Sstevel@tonic-gate 			ip->i_icb_block = SWAP_32(lad->lad_ext_loc);
5617c478bd9Sstevel@tonic-gate 			ip->i_icb_lbano = ud_xlate_to_daddr(udf_vfsp,
562b39a0235SMilan Cermak 			    ip->i_icb_prn, ip->i_icb_block,
563b39a0235SMilan Cermak 			    1, &dummy);
5647c478bd9Sstevel@tonic-gate 			brelse(ibp);
5657c478bd9Sstevel@tonic-gate 			brelse(bp);
5667c478bd9Sstevel@tonic-gate 			goto read_de;
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 		/*
5707c478bd9Sstevel@tonic-gate 		 * If this block is TE or unrecorded we
5717c478bd9Sstevel@tonic-gate 		 * are at the last entry
5727c478bd9Sstevel@tonic-gate 		 */
5737c478bd9Sstevel@tonic-gate 		if (ud_check_te_unrec(udf_vfsp, ibp->b_un.b_addr,
574b39a0235SMilan Cermak 		    ip->i_icb_block + 1) != 0) {
5757c478bd9Sstevel@tonic-gate 			/*
5767c478bd9Sstevel@tonic-gate 			 * This is not an unrecorded block
5777c478bd9Sstevel@tonic-gate 			 * Check if it a valid IE and
5787c478bd9Sstevel@tonic-gate 			 * get the address of DE that
5797c478bd9Sstevel@tonic-gate 			 * this IE points to
5807c478bd9Sstevel@tonic-gate 			 */
5817c478bd9Sstevel@tonic-gate 			goto ie_error;
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 		/*
5847c478bd9Sstevel@tonic-gate 		 * If ud_check_unrec returns "0"
5857c478bd9Sstevel@tonic-gate 		 * this is the last in the chain
5867c478bd9Sstevel@tonic-gate 		 * Latest file_entry
5877c478bd9Sstevel@tonic-gate 		 */
5887c478bd9Sstevel@tonic-gate 		brelse(ibp);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate end_4096:
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	ip->i_uid = SWAP_32(fe->fe_uid);
5947c478bd9Sstevel@tonic-gate 	if (ip->i_uid == -1) {
5957c478bd9Sstevel@tonic-gate 		ip->i_uid = ud_default_uid;
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 	ip->i_gid = SWAP_32(fe->fe_gid);
5987c478bd9Sstevel@tonic-gate 	if (ip->i_gid == -1) {
5997c478bd9Sstevel@tonic-gate 		ip->i_gid = ud_default_gid;
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 	ip->i_perm = SWAP_32(fe->fe_perms) & 0xFFFF;
602b39a0235SMilan Cermak 	if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) {
6037c478bd9Sstevel@tonic-gate 		ip->i_perm &= ~(IWRITE | (IWRITE >> 5) | (IWRITE >> 10));
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	ip->i_nlink = SWAP_16(fe->fe_lcount);
6077c478bd9Sstevel@tonic-gate 	ip->i_size = SWAP_64(fe->fe_info_len);
6087c478bd9Sstevel@tonic-gate 	ip->i_lbr = SWAP_64(fe->fe_lbr);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	ud_dtime2utime(&ip->i_atime, &fe->fe_acc_time);
6117c478bd9Sstevel@tonic-gate 	ud_dtime2utime(&ip->i_mtime, &fe->fe_mod_time);
6127c478bd9Sstevel@tonic-gate 	ud_dtime2utime(&ip->i_ctime, &fe->fe_attr_time);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	ip->i_uniqid = SWAP_64(fe->fe_uniq_id);
6167c478bd9Sstevel@tonic-gate 	icb_tag_flags = SWAP_16(fe->fe_icb_tag.itag_flags);
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	if ((fe->fe_icb_tag.itag_ftype == FTYPE_CHAR_DEV) ||
619b39a0235SMilan Cermak 	    (fe->fe_icb_tag.itag_ftype == FTYPE_BLOCK_DEV)) {
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 		eah = (struct ext_attr_hdr *)fe->fe_spec;
6227c478bd9Sstevel@tonic-gate 		ea_off = GET_32(&eah->eah_ial);
6237c478bd9Sstevel@tonic-gate 		ea_len = GET_32(&fe->fe_len_ear);
6247c478bd9Sstevel@tonic-gate 		if (ea_len && (ud_verify_tag_and_desc(&eah->eah_tag,
625b39a0235SMilan Cermak 		    UD_EXT_ATTR_HDR, ip->i_icb_block, 1,
6267c478bd9Sstevel@tonic-gate 		    sizeof (struct file_entry) -
6277c478bd9Sstevel@tonic-gate 		    offsetof(struct file_entry, fe_spec)) == 0)) {
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 			while (ea_off < ea_len) {
6307c478bd9Sstevel@tonic-gate 				/*
6317c478bd9Sstevel@tonic-gate 				 * We now check the validity of ea_off.
6327c478bd9Sstevel@tonic-gate 				 * (ea_len - ea_off) should be large enough to
6337c478bd9Sstevel@tonic-gate 				 * hold the attribute header atleast.
6347c478bd9Sstevel@tonic-gate 				 */
6357c478bd9Sstevel@tonic-gate 				if ((ea_len - ea_off) <
6367c478bd9Sstevel@tonic-gate 				    sizeof (struct attr_hdr)) {
6377c478bd9Sstevel@tonic-gate 					cmn_err(CE_NOTE,
638b39a0235SMilan Cermak 					    "ea_len(0x%x) - ea_off(0x%x) is "
639b39a0235SMilan Cermak 					    "too small to hold attr. info. "
640b39a0235SMilan Cermak 					    "blockno 0x%x\n",
6417c478bd9Sstevel@tonic-gate 					    ea_len, ea_off, ip->i_icb_block);
6427c478bd9Sstevel@tonic-gate 					goto error_ret;
6437c478bd9Sstevel@tonic-gate 				}
6447c478bd9Sstevel@tonic-gate 				ah = (struct attr_hdr *)&fe->fe_spec[ea_off];
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 				/*
6477c478bd9Sstevel@tonic-gate 				 * Device Specification EA
6487c478bd9Sstevel@tonic-gate 				 */
6497c478bd9Sstevel@tonic-gate 				if ((GET_32(&ah->ahdr_atype) == 12) &&
6507c478bd9Sstevel@tonic-gate 					(ah->ahdr_astype == 1)) {
6517c478bd9Sstevel@tonic-gate 					struct dev_spec_ear *ds;
6527c478bd9Sstevel@tonic-gate 
653b39a0235SMilan Cermak 					if ((ea_len - ea_off) <
654b39a0235SMilan Cermak 					    sizeof (struct dev_spec_ear)) {
655b39a0235SMilan Cermak 						cmn_err(CE_NOTE,
656b39a0235SMilan Cermak 						    "ea_len(0x%x) - "
657b39a0235SMilan Cermak 						    "ea_off(0x%x) is too small "
658b39a0235SMilan Cermak 						    "to hold dev_spec_ear."
659b39a0235SMilan Cermak 						    " blockno 0x%x\n",
660b39a0235SMilan Cermak 						    ea_len, ea_off,
661b39a0235SMilan Cermak 						    ip->i_icb_block);
662b39a0235SMilan Cermak 						goto error_ret;
663b39a0235SMilan Cermak 					}
664b39a0235SMilan Cermak 					ds = (struct dev_spec_ear *)ah;
665b39a0235SMilan Cermak 					ip->i_major = GET_32(&ds->ds_major_id);
666b39a0235SMilan Cermak 					ip->i_minor = GET_32(&ds->ds_minor_id);
6677c478bd9Sstevel@tonic-gate 				}
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 				/*
6707c478bd9Sstevel@tonic-gate 				 * Impl Use EA
6717c478bd9Sstevel@tonic-gate 				 */
6727c478bd9Sstevel@tonic-gate 				if ((GET_32(&ah->ahdr_atype) == 2048) &&
6737c478bd9Sstevel@tonic-gate 					(ah->ahdr_astype == 1)) {
6747c478bd9Sstevel@tonic-gate 					struct iu_ea *iuea;
6757c478bd9Sstevel@tonic-gate 					struct copy_mgt_info *cmi;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 					if ((ea_len - ea_off) <
6787c478bd9Sstevel@tonic-gate 					    sizeof (struct iu_ea)) {
6797c478bd9Sstevel@tonic-gate 						cmn_err(CE_NOTE,
6807c478bd9Sstevel@tonic-gate "ea_len(0x%x) - ea_off(0x%x) is too small to hold iu_ea. blockno 0x%x\n",
6817c478bd9Sstevel@tonic-gate 						    ea_len, ea_off,
6827c478bd9Sstevel@tonic-gate 						    ip->i_icb_block);
6837c478bd9Sstevel@tonic-gate 						goto error_ret;
6847c478bd9Sstevel@tonic-gate 					}
6857c478bd9Sstevel@tonic-gate 					iuea = (struct iu_ea *)ah;
6867c478bd9Sstevel@tonic-gate 					if (strncmp(iuea->iuea_ii.reg_id,
6877c478bd9Sstevel@tonic-gate 					    UDF_FREEEASPACE,
6887c478bd9Sstevel@tonic-gate 					    sizeof (iuea->iuea_ii.reg_id))
6897c478bd9Sstevel@tonic-gate 					    == 0) {
6907c478bd9Sstevel@tonic-gate 						/* skip it */
6917c478bd9Sstevel@tonic-gate 						iuea = iuea;
6927c478bd9Sstevel@tonic-gate 					} else if (strncmp(iuea->iuea_ii.reg_id,
6937c478bd9Sstevel@tonic-gate 					    UDF_CGMS_INFO,
6947c478bd9Sstevel@tonic-gate 					    sizeof (iuea->iuea_ii.reg_id))
6957c478bd9Sstevel@tonic-gate 					    == 0) {
6967c478bd9Sstevel@tonic-gate 						cmi = (struct copy_mgt_info *)
6977c478bd9Sstevel@tonic-gate 							iuea->iuea_iu;
6987c478bd9Sstevel@tonic-gate 						cmi = cmi;
6997c478bd9Sstevel@tonic-gate 					}
7007c478bd9Sstevel@tonic-gate 				}
7017c478bd9Sstevel@tonic-gate 				/* ??? PARANOIA */
7027c478bd9Sstevel@tonic-gate 				if (GET_32(&ah->ahdr_length) == 0) {
7037c478bd9Sstevel@tonic-gate 					break;
7047c478bd9Sstevel@tonic-gate 				}
7057c478bd9Sstevel@tonic-gate 				ea_off += GET_32(&ah->ahdr_length);
7067c478bd9Sstevel@tonic-gate 			}
7077c478bd9Sstevel@tonic-gate 		}
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	ip->i_nextr = 0;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	ip->i_maxent = SWAP_16(fe->fe_icb_tag.itag_max_ent);
7137c478bd9Sstevel@tonic-gate 	ip->i_astrat = SWAP_16(fe->fe_icb_tag.itag_strategy);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	ip->i_desc_type = icb_tag_flags & 0x7;
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	/* Strictly Paranoia */
7187c478bd9Sstevel@tonic-gate 	ip->i_ext = NULL;
7197c478bd9Sstevel@tonic-gate 	ip->i_ext_count = ip->i_ext_used = 0;
7207c478bd9Sstevel@tonic-gate 	ip->i_con = 0;
7217c478bd9Sstevel@tonic-gate 	ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	ip->i_data_off = 0xB0 + SWAP_32(fe->fe_len_ear);
7247c478bd9Sstevel@tonic-gate 	ip->i_max_emb =  udf_vfsp->udf_lbsize - ip->i_data_off;
7257c478bd9Sstevel@tonic-gate 	if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
7267c478bd9Sstevel@tonic-gate 		/* Short allocation desc */
7277c478bd9Sstevel@tonic-gate 		struct short_ad *sad;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 		ip->i_ext_used = 0;
7307c478bd9Sstevel@tonic-gate 		ip->i_ext_count = ndesc =
731b39a0235SMilan Cermak 		    SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
732b39a0235SMilan Cermak 		ip->i_ext_count =
733b39a0235SMilan Cermak 		    ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC;
7347c478bd9Sstevel@tonic-gate 		ip->i_ext = (struct icb_ext  *)kmem_zalloc(ip->i_ext_count *
735b39a0235SMilan Cermak 		    sizeof (struct icb_ext), KM_SLEEP);
7367c478bd9Sstevel@tonic-gate 		ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct short_ad);
7377c478bd9Sstevel@tonic-gate 		ip->i_cur_max_ext --;
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 		if ((ip->i_astrat != STRAT_TYPE4) &&
740b39a0235SMilan Cermak 		    (ip->i_astrat != STRAT_TYPE4096)) {
7417c478bd9Sstevel@tonic-gate 			goto error_ret;
7427c478bd9Sstevel@tonic-gate 		}
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 		sad = (struct short_ad *)
745b39a0235SMilan Cermak 		    (fe->fe_spec + SWAP_32(fe->fe_len_ear));
7467c478bd9Sstevel@tonic-gate 		iext = ip->i_ext;
7477c478bd9Sstevel@tonic-gate 		while (ndesc --) {
7487c478bd9Sstevel@tonic-gate 			length = SWAP_32(sad->sad_ext_len);
7497c478bd9Sstevel@tonic-gate 			if ((length & 0x3FFFFFFF) == 0) {
7507c478bd9Sstevel@tonic-gate 				break;
7517c478bd9Sstevel@tonic-gate 			}
7527c478bd9Sstevel@tonic-gate 			if (((length >> 30) & IB_MASK) == IB_CON) {
7537c478bd9Sstevel@tonic-gate 				if (ip->i_con == NULL) {
7547c478bd9Sstevel@tonic-gate 					ip->i_con_count = EXT_PER_MALLOC;
7557c478bd9Sstevel@tonic-gate 					ip->i_con_used = 0;
7567c478bd9Sstevel@tonic-gate 					ip->i_con_read = 0;
7577c478bd9Sstevel@tonic-gate 					ip->i_con = kmem_zalloc(
758b39a0235SMilan Cermak 					    ip->i_con_count *
759b39a0235SMilan Cermak 					    sizeof (struct icb_ext),
760b39a0235SMilan Cermak 					    KM_SLEEP);
7617c478bd9Sstevel@tonic-gate 				}
7627c478bd9Sstevel@tonic-gate 				con = &ip->i_con[ip->i_con_used];
7637c478bd9Sstevel@tonic-gate 				con->ib_prn = 0;
7647c478bd9Sstevel@tonic-gate 				con->ib_block = SWAP_32(sad->sad_ext_loc);
7657c478bd9Sstevel@tonic-gate 				con->ib_count = length & 0x3FFFFFFF;
7667c478bd9Sstevel@tonic-gate 				con->ib_flags = (length >> 30) & IB_MASK;
7677c478bd9Sstevel@tonic-gate 				ip->i_con_used++;
7687c478bd9Sstevel@tonic-gate 				sad ++;
7697c478bd9Sstevel@tonic-gate 				break;
7707c478bd9Sstevel@tonic-gate 			}
7717c478bd9Sstevel@tonic-gate 			iext->ib_prn = 0;
7727c478bd9Sstevel@tonic-gate 			iext->ib_block = SWAP_32(sad->sad_ext_loc);
7737c478bd9Sstevel@tonic-gate 			length = SWAP_32(sad->sad_ext_len);
7747c478bd9Sstevel@tonic-gate 			iext->ib_count = length & 0x3FFFFFFF;
7757c478bd9Sstevel@tonic-gate 			iext->ib_offset = offset;
7767c478bd9Sstevel@tonic-gate 			iext->ib_marker1 = (uint32_t)0xAAAAAAAA;
7777c478bd9Sstevel@tonic-gate 			iext->ib_marker2 = (uint32_t)0xBBBBBBBB;
7787c478bd9Sstevel@tonic-gate 			offset += (iext->ib_count + udf_vfsp->udf_lbmask) &
779b39a0235SMilan Cermak 			    (~udf_vfsp->udf_lbmask);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 			iext->ib_flags = (length >> 30) & IB_MASK;
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 			ip->i_ext_used++;
7847c478bd9Sstevel@tonic-gate 			iext++;
7857c478bd9Sstevel@tonic-gate 			sad ++;
7867c478bd9Sstevel@tonic-gate 		}
7877c478bd9Sstevel@tonic-gate 	} else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
7887c478bd9Sstevel@tonic-gate 		/* Long allocation desc */
7897c478bd9Sstevel@tonic-gate 		struct long_ad *lad;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 		ip->i_ext_used = 0;
7927c478bd9Sstevel@tonic-gate 		ip->i_ext_count = ndesc =
793b39a0235SMilan Cermak 		    SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
794b39a0235SMilan Cermak 		ip->i_ext_count =
795b39a0235SMilan Cermak 		    ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC;
7967c478bd9Sstevel@tonic-gate 		ip->i_ext = (struct icb_ext  *)kmem_zalloc(ip->i_ext_count *
797b39a0235SMilan Cermak 		    sizeof (struct icb_ext), KM_SLEEP);
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct long_ad);
8007c478bd9Sstevel@tonic-gate 		ip->i_cur_max_ext --;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 		if ((ip->i_astrat != STRAT_TYPE4) &&
803b39a0235SMilan Cermak 		    (ip->i_astrat != STRAT_TYPE4096)) {
8047c478bd9Sstevel@tonic-gate 			goto error_ret;
8057c478bd9Sstevel@tonic-gate 		}
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 		lad = (struct long_ad *)
808b39a0235SMilan Cermak 		    (fe->fe_spec + SWAP_32(fe->fe_len_ear));
8097c478bd9Sstevel@tonic-gate 		iext = ip->i_ext;
8107c478bd9Sstevel@tonic-gate 		while (ndesc --) {
8117c478bd9Sstevel@tonic-gate 			length = SWAP_32(lad->lad_ext_len);
8127c478bd9Sstevel@tonic-gate 			if ((length & 0x3FFFFFFF) == 0) {
8137c478bd9Sstevel@tonic-gate 				break;
8147c478bd9Sstevel@tonic-gate 			}
8157c478bd9Sstevel@tonic-gate 			if (((length >> 30) & IB_MASK) == IB_CON) {
8167c478bd9Sstevel@tonic-gate 				if (ip->i_con == NULL) {
8177c478bd9Sstevel@tonic-gate 					ip->i_con_count = EXT_PER_MALLOC;
8187c478bd9Sstevel@tonic-gate 					ip->i_con_used = 0;
8197c478bd9Sstevel@tonic-gate 					ip->i_con_read = 0;
8207c478bd9Sstevel@tonic-gate 					ip->i_con = kmem_zalloc(
821b39a0235SMilan Cermak 					    ip->i_con_count *
822b39a0235SMilan Cermak 					    sizeof (struct icb_ext),
823b39a0235SMilan Cermak 					    KM_SLEEP);
8247c478bd9Sstevel@tonic-gate 				}
8257c478bd9Sstevel@tonic-gate 				con = &ip->i_con[ip->i_con_used];
8267c478bd9Sstevel@tonic-gate 				con->ib_prn = SWAP_16(lad->lad_ext_prn);
8277c478bd9Sstevel@tonic-gate 				con->ib_block = SWAP_32(lad->lad_ext_loc);
8287c478bd9Sstevel@tonic-gate 				con->ib_count = length & 0x3FFFFFFF;
8297c478bd9Sstevel@tonic-gate 				con->ib_flags = (length >> 30) & IB_MASK;
8307c478bd9Sstevel@tonic-gate 				ip->i_con_used++;
8317c478bd9Sstevel@tonic-gate 				lad ++;
8327c478bd9Sstevel@tonic-gate 				break;
8337c478bd9Sstevel@tonic-gate 			}
8347c478bd9Sstevel@tonic-gate 			iext->ib_prn = SWAP_16(lad->lad_ext_prn);
8357c478bd9Sstevel@tonic-gate 			iext->ib_block = SWAP_32(lad->lad_ext_loc);
8367c478bd9Sstevel@tonic-gate 			iext->ib_count = length & 0x3FFFFFFF;
8377c478bd9Sstevel@tonic-gate 			iext->ib_offset = offset;
8387c478bd9Sstevel@tonic-gate 			iext->ib_marker1 = (uint32_t)0xAAAAAAAA;
8397c478bd9Sstevel@tonic-gate 			iext->ib_marker2 = (uint32_t)0xBBBBBBBB;
8407c478bd9Sstevel@tonic-gate 			offset += (iext->ib_count + udf_vfsp->udf_lbmask) &
841b39a0235SMilan Cermak 			    (~udf_vfsp->udf_lbmask);
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 			iext->ib_flags = (length >> 30) & IB_MASK;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 			ip->i_ext_used++;
8467c478bd9Sstevel@tonic-gate 			iext++;
8477c478bd9Sstevel@tonic-gate 			lad ++;
8487c478bd9Sstevel@tonic-gate 		}
8497c478bd9Sstevel@tonic-gate 	} else if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
8507c478bd9Sstevel@tonic-gate 		ASSERT(SWAP_32(fe->fe_len_ear) < udf_vfsp->udf_lbsize);
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 		if (SWAP_32(fe->fe_len_ear) > udf_vfsp->udf_lbsize) {
8537c478bd9Sstevel@tonic-gate 			goto error_ret;
8547c478bd9Sstevel@tonic-gate 		}
8557c478bd9Sstevel@tonic-gate 	} else {
8567c478bd9Sstevel@tonic-gate 		/* Not to be used in UDF 1.50 */
8577c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "Invalid Allocation Descriptor type %x\n",
858b39a0235SMilan Cermak 		    ip->i_desc_type);
8597c478bd9Sstevel@tonic-gate 		goto error_ret;
8607c478bd9Sstevel@tonic-gate 	}
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	if (icb_tag_flags & ICB_FLAG_SETUID) {
8647c478bd9Sstevel@tonic-gate 		ip->i_char = ISUID;
8657c478bd9Sstevel@tonic-gate 	} else {
8667c478bd9Sstevel@tonic-gate 		ip->i_char = 0;
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 	if (icb_tag_flags & ICB_FLAG_SETGID) {
8697c478bd9Sstevel@tonic-gate 		ip->i_char |= ISGID;
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 	if (icb_tag_flags & ICB_FLAG_STICKY) {
8727c478bd9Sstevel@tonic-gate 		ip->i_char |= ISVTX;
8737c478bd9Sstevel@tonic-gate 	}
8747c478bd9Sstevel@tonic-gate 	switch (fe->fe_icb_tag.itag_ftype) {
8757c478bd9Sstevel@tonic-gate 		case FTYPE_DIRECTORY :
8767c478bd9Sstevel@tonic-gate 			ip->i_type = VDIR;
8777c478bd9Sstevel@tonic-gate 			break;
8787c478bd9Sstevel@tonic-gate 		case FTYPE_FILE :
8797c478bd9Sstevel@tonic-gate 			ip->i_type = VREG;
8807c478bd9Sstevel@tonic-gate 			break;
8817c478bd9Sstevel@tonic-gate 		case FTYPE_BLOCK_DEV :
8827c478bd9Sstevel@tonic-gate 			ip->i_type = VBLK;
8837c478bd9Sstevel@tonic-gate 			break;
8847c478bd9Sstevel@tonic-gate 		case FTYPE_CHAR_DEV :
8857c478bd9Sstevel@tonic-gate 			ip->i_type = VCHR;
8867c478bd9Sstevel@tonic-gate 			break;
8877c478bd9Sstevel@tonic-gate 		case FTYPE_FIFO :
8887c478bd9Sstevel@tonic-gate 			ip->i_type = VFIFO;
8897c478bd9Sstevel@tonic-gate 			break;
8907c478bd9Sstevel@tonic-gate 		case FTYPE_C_ISSOCK :
8917c478bd9Sstevel@tonic-gate 			ip->i_type = VSOCK;
8927c478bd9Sstevel@tonic-gate 			break;
8937c478bd9Sstevel@tonic-gate 		case FTYPE_SYMLINK :
8947c478bd9Sstevel@tonic-gate 			ip->i_type = VLNK;
8957c478bd9Sstevel@tonic-gate 			break;
8967c478bd9Sstevel@tonic-gate 		default :
8977c478bd9Sstevel@tonic-gate 			ip->i_type = VNON;
8987c478bd9Sstevel@tonic-gate 			break;
8997c478bd9Sstevel@tonic-gate 	}
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	if (ip->i_type == VBLK || ip->i_type == VCHR) {
9027c478bd9Sstevel@tonic-gate 		ip->i_rdev = makedevice(ip->i_major, ip->i_minor);
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	/*
9067c478bd9Sstevel@tonic-gate 	 * Fill in the rest.  Don't bother with the vnode lock because nobody
9077c478bd9Sstevel@tonic-gate 	 * should be looking at this vnode.  We have already invalidated the
9087c478bd9Sstevel@tonic-gate 	 * pages if it had any so pageout shouldn't be referencing this vnode
9097c478bd9Sstevel@tonic-gate 	 * and we are holding the write contents lock so a look up can't use
9107c478bd9Sstevel@tonic-gate 	 * the vnode.
9117c478bd9Sstevel@tonic-gate 	 */
9127c478bd9Sstevel@tonic-gate 	vp->v_vfsp = vfsp;
9137c478bd9Sstevel@tonic-gate 	vp->v_type = ip->i_type;
9147c478bd9Sstevel@tonic-gate 	vp->v_rdev = ip->i_rdev;
9157c478bd9Sstevel@tonic-gate 	if (ip->i_udf->udf_root_blkno == loc) {
9167c478bd9Sstevel@tonic-gate 		vp->v_flag = VROOT;
9177c478bd9Sstevel@tonic-gate 	} else {
9187c478bd9Sstevel@tonic-gate 		vp->v_flag = 0;
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	brelse(bp);
9227c478bd9Sstevel@tonic-gate 	*ipp = ip;
9237c478bd9Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
9247c478bd9Sstevel@tonic-gate 	vn_exists(vp);
9257c478bd9Sstevel@tonic-gate 	return (0);
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate void
ud_iinactive(struct ud_inode * ip,struct cred * cr)9297c478bd9Sstevel@tonic-gate ud_iinactive(struct ud_inode *ip, struct cred *cr)
9307c478bd9Sstevel@tonic-gate {
9317c478bd9Sstevel@tonic-gate 	int32_t busy = 0;
9327c478bd9Sstevel@tonic-gate 	struct vnode *vp;
9337c478bd9Sstevel@tonic-gate 	vtype_t type;
9347c478bd9Sstevel@tonic-gate 	caddr_t addr, addr1;
9357c478bd9Sstevel@tonic-gate 	size_t size, size1;
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	ud_printf("ud_iinactive\n");
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	/*
9417c478bd9Sstevel@tonic-gate 	 * Get exclusive access to inode data.
9427c478bd9Sstevel@tonic-gate 	 */
9437c478bd9Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * Make sure no one reclaimed the inode before we put
9477c478bd9Sstevel@tonic-gate 	 * it on the freelist or destroy it. We keep our 'hold'
9487c478bd9Sstevel@tonic-gate 	 * on the vnode from vn_rele until we are ready to
9497c478bd9Sstevel@tonic-gate 	 * do something with the inode (freelist/destroy).
9507c478bd9Sstevel@tonic-gate 	 *
9517c478bd9Sstevel@tonic-gate 	 * Pageout may put a VN_HOLD/VN_RELE at anytime during this
9527c478bd9Sstevel@tonic-gate 	 * operation via an async putpage, so we must make sure
9537c478bd9Sstevel@tonic-gate 	 * we don't free/destroy the inode more than once. ud_iget
9547c478bd9Sstevel@tonic-gate 	 * may also put a VN_HOLD on the inode before it grabs
9557c478bd9Sstevel@tonic-gate 	 * the i_contents lock. This is done so we don't kmem_free
9567c478bd9Sstevel@tonic-gate 	 * an inode that a thread is waiting on.
9577c478bd9Sstevel@tonic-gate 	 */
9587c478bd9Sstevel@tonic-gate 	vp = ITOV(ip);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	mutex_enter(&vp->v_lock);
9617c478bd9Sstevel@tonic-gate 	if (vp->v_count < 1) {
9627c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ud_iinactive: v_count < 1\n");
9637c478bd9Sstevel@tonic-gate 		return;
9647c478bd9Sstevel@tonic-gate 	}
965b39a0235SMilan Cermak 	if ((vp->v_count > 1) || ((ip->i_flag & IREF) == 0)) {
966*ade42b55SSebastien Roy 		VN_RELE_LOCKED(vp);
9677c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
9687c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
9697c478bd9Sstevel@tonic-gate 		return;
9707c478bd9Sstevel@tonic-gate 	}
9717c478bd9Sstevel@tonic-gate 	mutex_exit(&vp->v_lock);
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	/*
9747c478bd9Sstevel@tonic-gate 	 * For forced umount case: if i_udf is NULL, the contents of
9757c478bd9Sstevel@tonic-gate 	 * the inode and all the pages have already been pushed back
9767c478bd9Sstevel@tonic-gate 	 * to disk. It can be safely destroyed.
9777c478bd9Sstevel@tonic-gate 	 */
9787c478bd9Sstevel@tonic-gate 	if (ip->i_udf == NULL) {
9797c478bd9Sstevel@tonic-gate 		addr = (caddr_t)ip->i_ext;
9807c478bd9Sstevel@tonic-gate 		size = sizeof (struct icb_ext) * ip->i_ext_count;
9817c478bd9Sstevel@tonic-gate 		ip->i_ext = 0;
9827c478bd9Sstevel@tonic-gate 		ip->i_ext_count = ip->i_ext_used = 0;
9837c478bd9Sstevel@tonic-gate 		addr1 = (caddr_t)ip->i_con;
9847c478bd9Sstevel@tonic-gate 		size1 = sizeof (struct icb_ext) * ip->i_con_count;
9857c478bd9Sstevel@tonic-gate 		ip->i_con = 0;
9867c478bd9Sstevel@tonic-gate 		ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
9877c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
9887c478bd9Sstevel@tonic-gate 		vn_invalid(vp);
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 		mutex_enter(&ud_nino_lock);
9917c478bd9Sstevel@tonic-gate 		ud_cur_inodes--;
9927c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		cv_destroy(&ip->i_wrcv);  /* throttling */
9957c478bd9Sstevel@tonic-gate 		rw_destroy(&ip->i_rwlock);
9967c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
9977c478bd9Sstevel@tonic-gate 		rw_destroy(&ip->i_contents);
9987c478bd9Sstevel@tonic-gate 		kmem_free(addr, size);
9997c478bd9Sstevel@tonic-gate 		kmem_free(addr1, size1);
10007c478bd9Sstevel@tonic-gate 		vn_free(vp);
10017c478bd9Sstevel@tonic-gate 		kmem_free(ip, sizeof (struct ud_inode));
10027c478bd9Sstevel@tonic-gate 		return;
10037c478bd9Sstevel@tonic-gate 	}
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	if ((ip->i_udf->udf_flags & UDF_FL_RDONLY) == 0) {
10067c478bd9Sstevel@tonic-gate 		if (ip->i_nlink <= 0) {
10077c478bd9Sstevel@tonic-gate 			ip->i_marker3 = (uint32_t)0xDDDD0000;
10087c478bd9Sstevel@tonic-gate 			ip->i_nlink = 1;	/* prevent free-ing twice */
10097c478bd9Sstevel@tonic-gate 			(void) ud_itrunc(ip, 0, 0, cr);
10107c478bd9Sstevel@tonic-gate 			type = ip->i_type;
10117c478bd9Sstevel@tonic-gate 			ip->i_perm = 0;
10127c478bd9Sstevel@tonic-gate 			ip->i_uid = 0;
10137c478bd9Sstevel@tonic-gate 			ip->i_gid = 0;
10147c478bd9Sstevel@tonic-gate 			ip->i_rdev = 0;	/* Zero in core version of rdev */
10157c478bd9Sstevel@tonic-gate 			mutex_enter(&ip->i_tlock);
10167c478bd9Sstevel@tonic-gate 			ip->i_flag |= IUPD|ICHG;
10177c478bd9Sstevel@tonic-gate 			mutex_exit(&ip->i_tlock);
10187c478bd9Sstevel@tonic-gate 			ud_ifree(ip, type);
10197c478bd9Sstevel@tonic-gate 			ip->i_icb_prn = 0xFFFF;
10207c478bd9Sstevel@tonic-gate 		} else if (!IS_SWAPVP(vp)) {
10217c478bd9Sstevel@tonic-gate 			/*
10227c478bd9Sstevel@tonic-gate 			 * Write the inode out if dirty. Pages are
10237c478bd9Sstevel@tonic-gate 			 * written back and put on the freelist.
10247c478bd9Sstevel@tonic-gate 			 */
10257c478bd9Sstevel@tonic-gate 			(void) ud_syncip(ip, B_FREE | B_ASYNC, 0);
10267c478bd9Sstevel@tonic-gate 			/*
10277c478bd9Sstevel@tonic-gate 			 * Do nothing if inode is now busy -- inode may
10287c478bd9Sstevel@tonic-gate 			 * have gone busy because ud_syncip
10297c478bd9Sstevel@tonic-gate 			 * releases/reacquires the i_contents lock
10307c478bd9Sstevel@tonic-gate 			 */
10317c478bd9Sstevel@tonic-gate 			mutex_enter(&vp->v_lock);
10327c478bd9Sstevel@tonic-gate 			if (vp->v_count > 1) {
1033*ade42b55SSebastien Roy 				VN_RELE_LOCKED(vp);
10347c478bd9Sstevel@tonic-gate 				mutex_exit(&vp->v_lock);
10357c478bd9Sstevel@tonic-gate 				rw_exit(&ip->i_contents);
10367c478bd9Sstevel@tonic-gate 				return;
10377c478bd9Sstevel@tonic-gate 			}
10387c478bd9Sstevel@tonic-gate 			mutex_exit(&vp->v_lock);
10397c478bd9Sstevel@tonic-gate 		} else {
10407c478bd9Sstevel@tonic-gate 			ud_iupdat(ip, 0);
10417c478bd9Sstevel@tonic-gate 		}
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	/*
10467c478bd9Sstevel@tonic-gate 	 * Put the inode on the end of the free list.
10477c478bd9Sstevel@tonic-gate 	 * Possibly in some cases it would be better to
10487c478bd9Sstevel@tonic-gate 	 * put the inode at the head of the free list,
10497c478bd9Sstevel@tonic-gate 	 * (e.g.: where i_perm == 0 || i_number == 0)
10507c478bd9Sstevel@tonic-gate 	 * but I will think about that later.
10517c478bd9Sstevel@tonic-gate 	 * (i_number is rarely 0 - only after an i/o error in ud_iget,
10527c478bd9Sstevel@tonic-gate 	 * where i_perm == 0, the inode will probably be wanted
10537c478bd9Sstevel@tonic-gate 	 * again soon for an ialloc, so possibly we should keep it)
10547c478bd9Sstevel@tonic-gate 	 */
10557c478bd9Sstevel@tonic-gate 	/*
10567c478bd9Sstevel@tonic-gate 	 * If inode is invalid or there is no page associated with
10577c478bd9Sstevel@tonic-gate 	 * this inode, put the inode in the front of the free list.
10587c478bd9Sstevel@tonic-gate 	 * Since we have a VN_HOLD on the vnode, and checked that it
10597c478bd9Sstevel@tonic-gate 	 * wasn't already on the freelist when we entered, we can safely
10607c478bd9Sstevel@tonic-gate 	 * put it on the freelist even if another thread puts a VN_HOLD
10617c478bd9Sstevel@tonic-gate 	 * on it (pageout/ud_iget).
10627c478bd9Sstevel@tonic-gate 	 */
10637c478bd9Sstevel@tonic-gate tryagain:
10647c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_nino_lock);
10657c478bd9Sstevel@tonic-gate 	if (vn_has_cached_data(vp)) {
10667c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
10677c478bd9Sstevel@tonic-gate 		mutex_enter(&vp->v_lock);
1068*ade42b55SSebastien Roy 		VN_RELE_LOCKED(vp);
10697c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
10707c478bd9Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
10717c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_ifree_lock);
10727c478bd9Sstevel@tonic-gate 		ud_add_to_free_list(ip, UD_END);
10737c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_ifree_lock);
10747c478bd9Sstevel@tonic-gate 		ip->i_flag &= IMODTIME;
10757c478bd9Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
10767c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
10777c478bd9Sstevel@tonic-gate 	} else if (busy || ud_cur_inodes < ud_max_inodes) {
10787c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
10797c478bd9Sstevel@tonic-gate 		/*
10807c478bd9Sstevel@tonic-gate 		 * We're not over our high water mark, or it's
10817c478bd9Sstevel@tonic-gate 		 * not safe to kmem_free the inode, so put it
10827c478bd9Sstevel@tonic-gate 		 * on the freelist.
10837c478bd9Sstevel@tonic-gate 		 */
10847c478bd9Sstevel@tonic-gate 		mutex_enter(&vp->v_lock);
10857c478bd9Sstevel@tonic-gate 		if (vn_has_cached_data(vp)) {
10867c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n");
10877c478bd9Sstevel@tonic-gate 		}
1088*ade42b55SSebastien Roy 		VN_RELE_LOCKED(vp);
10897c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
10927c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_ifree_lock);
10937c478bd9Sstevel@tonic-gate 		ud_add_to_free_list(ip, UD_BEGIN);
10947c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_ifree_lock);
10957c478bd9Sstevel@tonic-gate 	ip->i_flag &= IMODTIME;
10967c478bd9Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
10977c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
10987c478bd9Sstevel@tonic-gate 	} else {
10997c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
11007c478bd9Sstevel@tonic-gate 		if (vn_has_cached_data(vp)) {
11017c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n");
11027c478bd9Sstevel@tonic-gate 		}
11037c478bd9Sstevel@tonic-gate 		/*
11047c478bd9Sstevel@tonic-gate 		 * Try to free the inode. We must make sure
11057c478bd9Sstevel@tonic-gate 		 * it's o.k. to destroy this inode. We can't destroy
11067c478bd9Sstevel@tonic-gate 		 * if a thread is waiting for this inode. If we can't get the
11077c478bd9Sstevel@tonic-gate 		 * cache now, put it back on the freelist.
11087c478bd9Sstevel@tonic-gate 		 */
11097c478bd9Sstevel@tonic-gate 		if (!mutex_tryenter(&ud_icache_lock)) {
11107c478bd9Sstevel@tonic-gate 			busy = 1;
11117c478bd9Sstevel@tonic-gate 			goto tryagain;
11127c478bd9Sstevel@tonic-gate 		}
11137c478bd9Sstevel@tonic-gate 		mutex_enter(&vp->v_lock);
11147c478bd9Sstevel@tonic-gate 		if (vp->v_count > 1) {
11157c478bd9Sstevel@tonic-gate 			/* inode is wanted in ud_iget */
11167c478bd9Sstevel@tonic-gate 			busy = 1;
11177c478bd9Sstevel@tonic-gate 			mutex_exit(&vp->v_lock);
11187c478bd9Sstevel@tonic-gate 			mutex_exit(&ud_icache_lock);
11197c478bd9Sstevel@tonic-gate 			goto tryagain;
11207c478bd9Sstevel@tonic-gate 		}
11217c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
11227c478bd9Sstevel@tonic-gate 		remque(ip);
11237c478bd9Sstevel@tonic-gate 		ip->i_forw = ip;
11247c478bd9Sstevel@tonic-gate 		ip->i_back = ip;
11257c478bd9Sstevel@tonic-gate 		mutex_enter(&ud_nino_lock);
11267c478bd9Sstevel@tonic-gate 		ud_cur_inodes--;
11277c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_nino_lock);
11287c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_icache_lock);
11297c478bd9Sstevel@tonic-gate 		if (ip->i_icb_prn != 0xFFFF) {
11307c478bd9Sstevel@tonic-gate 			ud_iupdat(ip, 0);
11317c478bd9Sstevel@tonic-gate 		}
11327c478bd9Sstevel@tonic-gate 		addr = (caddr_t)ip->i_ext;
11337c478bd9Sstevel@tonic-gate 		size = sizeof (struct icb_ext) * ip->i_ext_count;
11347c478bd9Sstevel@tonic-gate 		ip->i_ext = 0;
11357c478bd9Sstevel@tonic-gate 		ip->i_ext_count = ip->i_ext_used = 0;
11367c478bd9Sstevel@tonic-gate 		addr1 = (caddr_t)ip->i_con;
11377c478bd9Sstevel@tonic-gate 		size1 = sizeof (struct icb_ext) * ip->i_con_count;
11387c478bd9Sstevel@tonic-gate 		ip->i_con = 0;
11397c478bd9Sstevel@tonic-gate 		ip->i_con_count = ip->i_con_used = ip->i_con_read = 0;
11407c478bd9Sstevel@tonic-gate 		cv_destroy(&ip->i_wrcv);  /* throttling */
11417c478bd9Sstevel@tonic-gate 		rw_destroy(&ip->i_rwlock);
11427c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
11437c478bd9Sstevel@tonic-gate 		rw_destroy(&ip->i_contents);
11447c478bd9Sstevel@tonic-gate 		kmem_free(addr, size);
11457c478bd9Sstevel@tonic-gate 		kmem_free(addr1, size1);
11467c478bd9Sstevel@tonic-gate 		ip->i_marker3 = (uint32_t)0xDDDDDDDD;
11477c478bd9Sstevel@tonic-gate 		vn_free(vp);
11487c478bd9Sstevel@tonic-gate 		kmem_free(ip, sizeof (struct ud_inode));
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate void
ud_iupdat(struct ud_inode * ip,int32_t waitfor)11547c478bd9Sstevel@tonic-gate ud_iupdat(struct ud_inode *ip, int32_t waitfor)
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate 	uint16_t flag, tag_flags;
1157ad9a7bd3SRichard Lowe 	int32_t error;
11587c478bd9Sstevel@tonic-gate 	struct buf *bp;
11597c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
11607c478bd9Sstevel@tonic-gate 	struct file_entry *fe;
1161ad9a7bd3SRichard Lowe 	uint16_t crc_len = 0;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	ASSERT(RW_WRITE_HELD(&ip->i_contents));
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 	ud_printf("ud_iupdat\n");
11667c478bd9Sstevel@tonic-gate 	/*
11677c478bd9Sstevel@tonic-gate 	 * Return if file system has been forcibly umounted.
11687c478bd9Sstevel@tonic-gate 	 */
11697c478bd9Sstevel@tonic-gate 	if (ip->i_udf == NULL) {
11707c478bd9Sstevel@tonic-gate 		return;
11717c478bd9Sstevel@tonic-gate 	}
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	udf_vfsp = ip->i_udf;
11747c478bd9Sstevel@tonic-gate 	flag = ip->i_flag;	/* Atomic read */
11757c478bd9Sstevel@tonic-gate 	if ((flag & (IUPD|IACC|ICHG|IMOD|IMODACC)) != 0) {
11767c478bd9Sstevel@tonic-gate 		if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
11777c478bd9Sstevel@tonic-gate 			ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC|IATTCHG);
11787c478bd9Sstevel@tonic-gate 			return;
11797c478bd9Sstevel@tonic-gate 		}
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 		bp = ud_bread(ip->i_dev,
1182b39a0235SMilan Cermak 		    ip->i_icb_lbano << udf_vfsp->udf_l2d_shift,
1183b39a0235SMilan Cermak 		    ip->i_udf->udf_lbsize);
11847c478bd9Sstevel@tonic-gate 		if (bp->b_flags & B_ERROR) {
11857c478bd9Sstevel@tonic-gate 			brelse(bp);
11867c478bd9Sstevel@tonic-gate 			return;
11877c478bd9Sstevel@tonic-gate 		}
11887c478bd9Sstevel@tonic-gate 		fe = (struct file_entry *)bp->b_un.b_addr;
11897c478bd9Sstevel@tonic-gate 		if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
11907c478bd9Sstevel@tonic-gate 		    ip->i_icb_block,
11917c478bd9Sstevel@tonic-gate 		    1, ip->i_udf->udf_lbsize) != 0) {
11927c478bd9Sstevel@tonic-gate 			brelse(bp);
11937c478bd9Sstevel@tonic-gate 			return;
11947c478bd9Sstevel@tonic-gate 		}
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
11977c478bd9Sstevel@tonic-gate 		if (ip->i_flag & (IUPD|IACC|ICHG)) {
11987c478bd9Sstevel@tonic-gate 			IMARK(ip);
11997c478bd9Sstevel@tonic-gate 		}
12007c478bd9Sstevel@tonic-gate 		ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC);
12017c478bd9Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 		fe->fe_uid = SWAP_32(ip->i_uid);
12047c478bd9Sstevel@tonic-gate 		fe->fe_gid = SWAP_32(ip->i_gid);
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 		fe->fe_perms = SWAP_32(ip->i_perm);
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 		fe->fe_lcount = SWAP_16(ip->i_nlink);
12097c478bd9Sstevel@tonic-gate 		fe->fe_info_len = SWAP_64(ip->i_size);
12107c478bd9Sstevel@tonic-gate 		fe->fe_lbr = SWAP_64(ip->i_lbr);
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&ip->i_atime, &fe->fe_acc_time);
12137c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&ip->i_mtime, &fe->fe_mod_time);
12147c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&ip->i_ctime, &fe->fe_attr_time);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 		if (ip->i_char & ISUID) {
12177c478bd9Sstevel@tonic-gate 			tag_flags = ICB_FLAG_SETUID;
12187c478bd9Sstevel@tonic-gate 		} else {
12197c478bd9Sstevel@tonic-gate 			tag_flags = 0;
12207c478bd9Sstevel@tonic-gate 		}
12217c478bd9Sstevel@tonic-gate 		if (ip->i_char & ISGID) {
12227c478bd9Sstevel@tonic-gate 			tag_flags |= ICB_FLAG_SETGID;
12237c478bd9Sstevel@tonic-gate 		}
12247c478bd9Sstevel@tonic-gate 		if (ip->i_char & ISVTX) {
12257c478bd9Sstevel@tonic-gate 			tag_flags |= ICB_FLAG_STICKY;
12267c478bd9Sstevel@tonic-gate 		}
12277c478bd9Sstevel@tonic-gate 		tag_flags |= ip->i_desc_type;
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 		/*
12307c478bd9Sstevel@tonic-gate 		 * Remove the following it is no longer contig
12317c478bd9Sstevel@tonic-gate 		 * if (ip->i_astrat  == STRAT_TYPE4) {
12327c478bd9Sstevel@tonic-gate 		 *	tag_flags |= ICB_FLAG_CONTIG;
12337c478bd9Sstevel@tonic-gate 		 * }
12347c478bd9Sstevel@tonic-gate 		 */
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 		fe->fe_icb_tag.itag_flags &= ~SWAP_16((uint16_t)0x3C3);
12377c478bd9Sstevel@tonic-gate 		fe->fe_icb_tag.itag_strategy = SWAP_16(ip->i_astrat);
12387c478bd9Sstevel@tonic-gate 		fe->fe_icb_tag.itag_flags |= SWAP_16(tag_flags);
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 		ud_update_regid(&fe->fe_impl_id);
12417c478bd9Sstevel@tonic-gate 
1242ad9a7bd3SRichard Lowe 		crc_len = offsetof(struct file_entry, fe_spec) +
1243b39a0235SMilan Cermak 		    SWAP_32(fe->fe_len_ear);
12447c478bd9Sstevel@tonic-gate 		if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
12457c478bd9Sstevel@tonic-gate 			crc_len += ip->i_size;
12467c478bd9Sstevel@tonic-gate 			fe->fe_len_adesc = SWAP_32(((uint32_t)ip->i_size));
1247b39a0235SMilan Cermak 		} else if ((ip->i_size != 0) && (ip->i_ext != NULL) &&
1248b39a0235SMilan Cermak 		    (ip->i_ext_used != 0)) {
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 			if ((error = ud_read_icb_till_off(ip,
1251b39a0235SMilan Cermak 			    ip->i_size)) == 0) {
12527c478bd9Sstevel@tonic-gate 				if (ip->i_astrat == STRAT_TYPE4) {
12537c478bd9Sstevel@tonic-gate 					error = ud_updat_ext4(ip, fe);
12547c478bd9Sstevel@tonic-gate 				} else if (ip->i_astrat == STRAT_TYPE4096) {
12557c478bd9Sstevel@tonic-gate 					error = ud_updat_ext4096(ip, fe);
12567c478bd9Sstevel@tonic-gate 				}
12577c478bd9Sstevel@tonic-gate 				if (error) {
12587c478bd9Sstevel@tonic-gate 					udf_vfsp->udf_mark_bad = 1;
12597c478bd9Sstevel@tonic-gate 				}
12607c478bd9Sstevel@tonic-gate 			}
12617c478bd9Sstevel@tonic-gate 			crc_len += SWAP_32(fe->fe_len_adesc);
12627c478bd9Sstevel@tonic-gate 		} else {
12637c478bd9Sstevel@tonic-gate 			fe->fe_len_adesc = 0;
12647c478bd9Sstevel@tonic-gate 		}
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 		/*
12677c478bd9Sstevel@tonic-gate 		 * Zero out the rest of the block
12687c478bd9Sstevel@tonic-gate 		 */
12697c478bd9Sstevel@tonic-gate 		bzero(bp->b_un.b_addr + crc_len,
1270b39a0235SMilan Cermak 		    ip->i_udf->udf_lbsize - crc_len);
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 		ud_make_tag(ip->i_udf, &fe->fe_tag,
1273b39a0235SMilan Cermak 		    UD_FILE_ENTRY, ip->i_icb_block, crc_len);
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 		if (waitfor) {
12777c478bd9Sstevel@tonic-gate 			BWRITE(bp);
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 			/*
12807c478bd9Sstevel@tonic-gate 			 * Synchronous write has guaranteed that inode
12817c478bd9Sstevel@tonic-gate 			 * has been written on disk so clear the flag
12827c478bd9Sstevel@tonic-gate 			 */
12837c478bd9Sstevel@tonic-gate 			ip->i_flag &= ~(IBDWRITE);
12847c478bd9Sstevel@tonic-gate 		} else {
12857c478bd9Sstevel@tonic-gate 			bdwrite(bp);
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 			/*
12887c478bd9Sstevel@tonic-gate 			 * This write hasn't guaranteed that inode has been
12897c478bd9Sstevel@tonic-gate 			 * written on the disk.
12907c478bd9Sstevel@tonic-gate 			 * Since, all updat flags on indoe are cleared, we must
12917c478bd9Sstevel@tonic-gate 			 * remember the condition in case inode is to be updated
12927c478bd9Sstevel@tonic-gate 			 * synchronously later (e.g.- fsync()/fdatasync())
12937c478bd9Sstevel@tonic-gate 			 * and inode has not been modified yet.
12947c478bd9Sstevel@tonic-gate 			 */
12957c478bd9Sstevel@tonic-gate 			ip->i_flag |= (IBDWRITE);
12967c478bd9Sstevel@tonic-gate 		}
12977c478bd9Sstevel@tonic-gate 	} else {
12987c478bd9Sstevel@tonic-gate 		/*
12997c478bd9Sstevel@tonic-gate 		 * In case previous inode update was done asynchronously
13007c478bd9Sstevel@tonic-gate 		 * (IBDWRITE) and this inode update request wants guaranteed
13017c478bd9Sstevel@tonic-gate 		 * (synchronous) disk update, flush the inode.
13027c478bd9Sstevel@tonic-gate 		 */
13037c478bd9Sstevel@tonic-gate 		if (waitfor && (flag & IBDWRITE)) {
1304b39a0235SMilan Cermak 			blkflush(ip->i_dev,
1305b39a0235SMilan Cermak 			    (daddr_t)fsbtodb(udf_vfsp, ip->i_icb_lbano));
13067c478bd9Sstevel@tonic-gate 			ip->i_flag &= ~(IBDWRITE);
13077c478bd9Sstevel@tonic-gate 		}
13087c478bd9Sstevel@tonic-gate 	}
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate int32_t
ud_updat_ext4(struct ud_inode * ip,struct file_entry * fe)13127c478bd9Sstevel@tonic-gate ud_updat_ext4(struct ud_inode *ip, struct file_entry *fe)
13137c478bd9Sstevel@tonic-gate {
13147c478bd9Sstevel@tonic-gate 	uint32_t dummy;
13157c478bd9Sstevel@tonic-gate 	int32_t elen, ndent, index, count, con_index;
13167c478bd9Sstevel@tonic-gate 	daddr_t bno;
13177c478bd9Sstevel@tonic-gate 	struct buf *bp;
13187c478bd9Sstevel@tonic-gate 	struct short_ad *sad;
13197c478bd9Sstevel@tonic-gate 	struct long_ad *lad;
13207c478bd9Sstevel@tonic-gate 	struct icb_ext *iext, *icon;
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 	ASSERT(ip);
13247c478bd9Sstevel@tonic-gate 	ASSERT(fe);
13257c478bd9Sstevel@tonic-gate 	ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) ||
1326b39a0235SMilan Cermak 	    (ip->i_desc_type == ICB_FLAG_LONG_AD));
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate 	if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
13297c478bd9Sstevel@tonic-gate 		elen = sizeof (struct short_ad);
13307c478bd9Sstevel@tonic-gate 		sad = (struct short_ad *)
1331b39a0235SMilan Cermak 		    (fe->fe_spec + SWAP_32(fe->fe_len_ear));
13327c478bd9Sstevel@tonic-gate 	} else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
13337c478bd9Sstevel@tonic-gate 		elen = sizeof (struct long_ad);
13347c478bd9Sstevel@tonic-gate 		lad = (struct long_ad *)
1335b39a0235SMilan Cermak 		    (fe->fe_spec + SWAP_32(fe->fe_len_ear));
13367c478bd9Sstevel@tonic-gate 	} else {
13377c478bd9Sstevel@tonic-gate 		/* This cannot happen return */
13387c478bd9Sstevel@tonic-gate 		return (EINVAL);
13397c478bd9Sstevel@tonic-gate 	}
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 	ndent = ip->i_max_emb / elen;
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 	if (ip->i_ext_used < ndent) {
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 		if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
13467c478bd9Sstevel@tonic-gate 			ud_make_sad(ip->i_ext, sad, ip->i_ext_used);
13477c478bd9Sstevel@tonic-gate 		} else {
13487c478bd9Sstevel@tonic-gate 			ud_make_lad(ip->i_ext, lad, ip->i_ext_used);
13497c478bd9Sstevel@tonic-gate 		}
13507c478bd9Sstevel@tonic-gate 		fe->fe_len_adesc = SWAP_32(ip->i_ext_used * elen);
13517c478bd9Sstevel@tonic-gate 		con_index = 0;
13527c478bd9Sstevel@tonic-gate 	} else {
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate 		con_index = index = 0;
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 		while (index < ip->i_ext_used) {
13577c478bd9Sstevel@tonic-gate 			if (index == 0) {
13587c478bd9Sstevel@tonic-gate 				/*
13597c478bd9Sstevel@tonic-gate 				 * bp is already read
13607c478bd9Sstevel@tonic-gate 				 * First few extents will go
13617c478bd9Sstevel@tonic-gate 				 * into the file_entry
13627c478bd9Sstevel@tonic-gate 				 */
13637c478bd9Sstevel@tonic-gate 				count = ndent - 1;
1364b39a0235SMilan Cermak 				fe->fe_len_adesc = SWAP_32(ndent * elen);
13657c478bd9Sstevel@tonic-gate 				bp = NULL;
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 				/*
13687c478bd9Sstevel@tonic-gate 				 * Last entry to be cont ext
13697c478bd9Sstevel@tonic-gate 				 */
13707c478bd9Sstevel@tonic-gate 				icon = &ip->i_con[con_index];
13717c478bd9Sstevel@tonic-gate 			} else {
13727c478bd9Sstevel@tonic-gate 				/*
13737c478bd9Sstevel@tonic-gate 				 * Read the buffer
13747c478bd9Sstevel@tonic-gate 				 */
13757c478bd9Sstevel@tonic-gate 				icon = &ip->i_con[con_index];
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 				bno = ud_xlate_to_daddr(ip->i_udf,
1378b39a0235SMilan Cermak 				    icon->ib_prn, icon->ib_block,
1379b39a0235SMilan Cermak 				    icon->ib_count >> ip->i_udf->udf_l2d_shift,
1380b39a0235SMilan Cermak 				    &dummy);
1381b39a0235SMilan Cermak 				bp = ud_bread(ip->i_dev,
1382b39a0235SMilan Cermak 				    bno << ip->i_udf->udf_l2d_shift,
1383b39a0235SMilan Cermak 				    ip->i_udf->udf_lbsize);
13847c478bd9Sstevel@tonic-gate 				if (bp->b_flags & B_ERROR) {
13857c478bd9Sstevel@tonic-gate 					brelse(bp);
13867c478bd9Sstevel@tonic-gate 					return (EIO);
13877c478bd9Sstevel@tonic-gate 				}
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 				/*
13907c478bd9Sstevel@tonic-gate 				 * Figure out how many extents in
13917c478bd9Sstevel@tonic-gate 				 * this time
13927c478bd9Sstevel@tonic-gate 				 */
13937c478bd9Sstevel@tonic-gate 				count = (bp->b_bcount -
1394b39a0235SMilan Cermak 				    sizeof (struct alloc_ext_desc)) / elen;
13957c478bd9Sstevel@tonic-gate 				if (count > (ip->i_ext_used - index)) {
13967c478bd9Sstevel@tonic-gate 					count = ip->i_ext_used - index;
13977c478bd9Sstevel@tonic-gate 				} else {
13987c478bd9Sstevel@tonic-gate 					count --;
13997c478bd9Sstevel@tonic-gate 				}
14007c478bd9Sstevel@tonic-gate 				con_index++;
14017c478bd9Sstevel@tonic-gate 				if (con_index >= ip->i_con_used) {
14027c478bd9Sstevel@tonic-gate 					icon = NULL;
14037c478bd9Sstevel@tonic-gate 				} else {
14047c478bd9Sstevel@tonic-gate 					icon = &ip->i_con[con_index];
14057c478bd9Sstevel@tonic-gate 				}
14067c478bd9Sstevel@tonic-gate 			}
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 			/*
14117c478bd9Sstevel@tonic-gate 			 * convert to on disk form and
14127c478bd9Sstevel@tonic-gate 			 * update
14137c478bd9Sstevel@tonic-gate 			 */
14147c478bd9Sstevel@tonic-gate 			iext = &ip->i_ext[index];
14157c478bd9Sstevel@tonic-gate 			if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
14167c478bd9Sstevel@tonic-gate 				if (index != 0) {
14177c478bd9Sstevel@tonic-gate 					sad = (struct short_ad *)
1418b39a0235SMilan Cermak 					    (bp->b_un.b_addr +
1419b39a0235SMilan Cermak 					    sizeof (struct alloc_ext_desc));
14207c478bd9Sstevel@tonic-gate 				}
14217c478bd9Sstevel@tonic-gate 				ud_make_sad(iext, sad, count);
14227c478bd9Sstevel@tonic-gate 				sad += count;
14237c478bd9Sstevel@tonic-gate 				if (icon != NULL) {
14247c478bd9Sstevel@tonic-gate 					ud_make_sad(icon, sad, 1);
14257c478bd9Sstevel@tonic-gate 				}
14267c478bd9Sstevel@tonic-gate 			} else {
14277c478bd9Sstevel@tonic-gate 				if (index != 0) {
14287c478bd9Sstevel@tonic-gate 					lad = (struct long_ad *)
1429b39a0235SMilan Cermak 					    (bp->b_un.b_addr +
1430b39a0235SMilan Cermak 					    sizeof (struct alloc_ext_desc));
14317c478bd9Sstevel@tonic-gate 				}
14327c478bd9Sstevel@tonic-gate 				ud_make_lad(iext, lad, count);
14337c478bd9Sstevel@tonic-gate 				lad += count;
14347c478bd9Sstevel@tonic-gate 				if (icon != NULL) {
14357c478bd9Sstevel@tonic-gate 					ud_make_lad(icon, lad, 1);
14367c478bd9Sstevel@tonic-gate 				}
14377c478bd9Sstevel@tonic-gate 			}
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate 			if (con_index != 0) {
14407c478bd9Sstevel@tonic-gate 				struct alloc_ext_desc *aed;
14417c478bd9Sstevel@tonic-gate 				int32_t sz;
14427c478bd9Sstevel@tonic-gate 				struct icb_ext *oicon;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 				oicon = &ip->i_con[con_index - 1];
14457c478bd9Sstevel@tonic-gate 				sz = count * elen;
14467c478bd9Sstevel@tonic-gate 				if (icon != NULL) {
14477c478bd9Sstevel@tonic-gate 					sz += elen;
14487c478bd9Sstevel@tonic-gate 				}
14497c478bd9Sstevel@tonic-gate 				aed = (struct alloc_ext_desc *)bp->b_un.b_addr;
14507c478bd9Sstevel@tonic-gate 				aed->aed_len_aed = SWAP_32(sz);
14517c478bd9Sstevel@tonic-gate 				if (con_index == 1) {
14527c478bd9Sstevel@tonic-gate 					aed->aed_rev_ael =
1453b39a0235SMilan Cermak 					    SWAP_32(ip->i_icb_block);
14547c478bd9Sstevel@tonic-gate 				} else {
14557c478bd9Sstevel@tonic-gate 					aed->aed_rev_ael =
1456b39a0235SMilan Cermak 					    SWAP_32(oicon->ib_block);
14577c478bd9Sstevel@tonic-gate 				}
14587c478bd9Sstevel@tonic-gate 				sz += sizeof (struct alloc_ext_desc);
14597c478bd9Sstevel@tonic-gate 				ud_make_tag(ip->i_udf, &aed->aed_tag,
1460b39a0235SMilan Cermak 				    UD_ALLOC_EXT_DESC, oicon->ib_block, sz);
14617c478bd9Sstevel@tonic-gate 			}
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 			/*
14647c478bd9Sstevel@tonic-gate 			 * Write back to disk
14657c478bd9Sstevel@tonic-gate 			 */
14667c478bd9Sstevel@tonic-gate 			if (bp != NULL) {
14677c478bd9Sstevel@tonic-gate 				BWRITE(bp);
14687c478bd9Sstevel@tonic-gate 			}
14697c478bd9Sstevel@tonic-gate 			index += count;
14707c478bd9Sstevel@tonic-gate 		}
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 	}
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	if (con_index != ip->i_con_used) {
14757c478bd9Sstevel@tonic-gate 		int32_t lbmask, l2b, temp;
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 		temp = con_index;
14787c478bd9Sstevel@tonic-gate 		lbmask = ip->i_udf->udf_lbmask;
14797c478bd9Sstevel@tonic-gate 		l2b = ip->i_udf->udf_l2b_shift;
14807c478bd9Sstevel@tonic-gate 		/*
14817c478bd9Sstevel@tonic-gate 		 * Free unused continuation extents
14827c478bd9Sstevel@tonic-gate 		 */
14837c478bd9Sstevel@tonic-gate 		for (; con_index < ip->i_con_used; con_index++) {
14847c478bd9Sstevel@tonic-gate 			icon = &ip->i_con[con_index];
14857c478bd9Sstevel@tonic-gate 			count = (icon->ib_count + lbmask) >> l2b;
14867c478bd9Sstevel@tonic-gate 			ud_free_space(ip->i_udf->udf_vfs, icon->ib_prn,
1487b39a0235SMilan Cermak 			    icon->ib_block, count);
14887c478bd9Sstevel@tonic-gate 			count = (count << l2b) - sizeof (struct alloc_ext_desc);
14897c478bd9Sstevel@tonic-gate 			ip->i_cur_max_ext -= (count / elen) - 1;
14907c478bd9Sstevel@tonic-gate 		}
14917c478bd9Sstevel@tonic-gate 		ip->i_con_used = temp;
14927c478bd9Sstevel@tonic-gate 	}
14937c478bd9Sstevel@tonic-gate 	return (0);
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate /* ARGSUSED */
14977c478bd9Sstevel@tonic-gate int32_t
ud_updat_ext4096(struct ud_inode * ip,struct file_entry * fe)14987c478bd9Sstevel@tonic-gate ud_updat_ext4096(struct ud_inode *ip, struct file_entry *fe)
14997c478bd9Sstevel@tonic-gate {
15007c478bd9Sstevel@tonic-gate 	return (ENXIO);
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate void
ud_make_sad(struct icb_ext * iext,struct short_ad * sad,int32_t count)15047c478bd9Sstevel@tonic-gate ud_make_sad(struct icb_ext *iext, struct short_ad *sad, int32_t count)
15057c478bd9Sstevel@tonic-gate {
15067c478bd9Sstevel@tonic-gate 	int32_t index = 0, scount;
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 	ASSERT(iext);
15097c478bd9Sstevel@tonic-gate 	ASSERT(sad);
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate 	if (count != 0) {
15127c478bd9Sstevel@tonic-gate 		ASSERT(count > 0);
15137c478bd9Sstevel@tonic-gate 		while (index < count) {
15147c478bd9Sstevel@tonic-gate 			scount = (iext->ib_count & 0x3FFFFFFF) |
1515b39a0235SMilan Cermak 			    (iext->ib_flags << 30);
15167c478bd9Sstevel@tonic-gate 			sad->sad_ext_len = SWAP_32(scount);
15177c478bd9Sstevel@tonic-gate 			sad->sad_ext_loc = SWAP_32(iext->ib_block);
15187c478bd9Sstevel@tonic-gate 			sad++;
15197c478bd9Sstevel@tonic-gate 			iext++;
15207c478bd9Sstevel@tonic-gate 			index++;
15217c478bd9Sstevel@tonic-gate 		}
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate void
ud_make_lad(struct icb_ext * iext,struct long_ad * lad,int32_t count)15267c478bd9Sstevel@tonic-gate ud_make_lad(struct icb_ext *iext, struct long_ad *lad, int32_t count)
15277c478bd9Sstevel@tonic-gate {
15287c478bd9Sstevel@tonic-gate 	int32_t index = 0, scount;
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	ASSERT(iext);
15317c478bd9Sstevel@tonic-gate 	ASSERT(lad);
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	if (count != 0) {
15347c478bd9Sstevel@tonic-gate 		ASSERT(count > 0);
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 		while (index < count) {
15377c478bd9Sstevel@tonic-gate 			lad->lad_ext_prn = SWAP_16(iext->ib_prn);
15387c478bd9Sstevel@tonic-gate 			scount = (iext->ib_count & 0x3FFFFFFF) |
1539b39a0235SMilan Cermak 			    (iext->ib_flags << 30);
15407c478bd9Sstevel@tonic-gate 			lad->lad_ext_len = SWAP_32(scount);
15417c478bd9Sstevel@tonic-gate 			lad->lad_ext_loc = SWAP_32(iext->ib_block);
15427c478bd9Sstevel@tonic-gate 			lad++;
15437c478bd9Sstevel@tonic-gate 			iext++;
15447c478bd9Sstevel@tonic-gate 			index++;
15457c478bd9Sstevel@tonic-gate 		}
15467c478bd9Sstevel@tonic-gate 	}
15477c478bd9Sstevel@tonic-gate }
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate /*
15507c478bd9Sstevel@tonic-gate  * Truncate the inode ip to at most length size.
15517c478bd9Sstevel@tonic-gate  * Free affected disk blocks -- the blocks of the
15527c478bd9Sstevel@tonic-gate  * file are removed in reverse order.
15537c478bd9Sstevel@tonic-gate  */
15547c478bd9Sstevel@tonic-gate /* ARGSUSED */
15557c478bd9Sstevel@tonic-gate int
ud_itrunc(struct ud_inode * oip,u_offset_t length,int32_t flags,struct cred * cr)15567c478bd9Sstevel@tonic-gate ud_itrunc(struct ud_inode *oip, u_offset_t length,
1557b39a0235SMilan Cermak     int32_t flags, struct cred *cr)
15587c478bd9Sstevel@tonic-gate {
15597c478bd9Sstevel@tonic-gate 	int32_t error, boff;
15607c478bd9Sstevel@tonic-gate 	off_t bsize;
15617c478bd9Sstevel@tonic-gate 	mode_t mode;
15627c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
15637c478bd9Sstevel@tonic-gate 
15647c478bd9Sstevel@tonic-gate 	ud_printf("ud_itrunc\n");
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	ASSERT(RW_WRITE_HELD(&oip->i_contents));
15677c478bd9Sstevel@tonic-gate 	udf_vfsp = oip->i_udf;
15687c478bd9Sstevel@tonic-gate 	bsize = udf_vfsp->udf_lbsize;
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 	/*
15717c478bd9Sstevel@tonic-gate 	 * We only allow truncation of regular files and directories
15727c478bd9Sstevel@tonic-gate 	 * to arbritary lengths here.  In addition, we allow symbolic
15737c478bd9Sstevel@tonic-gate 	 * links to be truncated only to zero length.  Other inode
15747c478bd9Sstevel@tonic-gate 	 * types cannot have their length set here.
15757c478bd9Sstevel@tonic-gate 	 */
15767c478bd9Sstevel@tonic-gate 	mode = oip->i_type;
15777c478bd9Sstevel@tonic-gate 	if (mode == VFIFO) {
15787c478bd9Sstevel@tonic-gate 		return (0);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate 	if ((mode != VREG) && (mode != VDIR) &&
1581b39a0235SMilan Cermak 	    (!(mode == VLNK && length == 0))) {
15827c478bd9Sstevel@tonic-gate 		return (EINVAL);
15837c478bd9Sstevel@tonic-gate 	}
15847c478bd9Sstevel@tonic-gate 	if (length == oip->i_size) {
15857c478bd9Sstevel@tonic-gate 		/* update ctime and mtime to please POSIX tests */
15867c478bd9Sstevel@tonic-gate 		mutex_enter(&oip->i_tlock);
15877c478bd9Sstevel@tonic-gate 		oip->i_flag |= ICHG |IUPD;
15887c478bd9Sstevel@tonic-gate 		mutex_exit(&oip->i_tlock);
15897c478bd9Sstevel@tonic-gate 		return (0);
15907c478bd9Sstevel@tonic-gate 	}
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	boff = blkoff(udf_vfsp, length);
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 	if (length > oip->i_size) {
15957c478bd9Sstevel@tonic-gate 		/*
15967c478bd9Sstevel@tonic-gate 		 * Trunc up case.ud_bmap_write will insure that the right blocks
15977c478bd9Sstevel@tonic-gate 		 * are allocated.  This includes doing any work needed for
15987c478bd9Sstevel@tonic-gate 		 * allocating the last block.
15997c478bd9Sstevel@tonic-gate 		 */
16007c478bd9Sstevel@tonic-gate 		if (boff == 0) {
16017c478bd9Sstevel@tonic-gate 			error = ud_bmap_write(oip, length - 1,
1602b39a0235SMilan Cermak 			    (int)bsize, 0, cr);
16037c478bd9Sstevel@tonic-gate 		} else {
16047c478bd9Sstevel@tonic-gate 			error = ud_bmap_write(oip, length - 1, boff, 0, cr);
16057c478bd9Sstevel@tonic-gate 		}
16067c478bd9Sstevel@tonic-gate 		if (error == 0) {
16077c478bd9Sstevel@tonic-gate 			u_offset_t osize = oip->i_size;
16087c478bd9Sstevel@tonic-gate 			oip->i_size  = length;
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 			/*
16117c478bd9Sstevel@tonic-gate 			 * Make sure we zero out the remaining bytes of
16127c478bd9Sstevel@tonic-gate 			 * the page in case a mmap scribbled on it. We
16137c478bd9Sstevel@tonic-gate 			 * can't prevent a mmap from writing beyond EOF
16147c478bd9Sstevel@tonic-gate 			 * on the last page of a file.
16157c478bd9Sstevel@tonic-gate 			 */
16167c478bd9Sstevel@tonic-gate 			if ((boff = blkoff(udf_vfsp, osize)) != 0) {
16177c478bd9Sstevel@tonic-gate 				pvn_vpzero(ITOV(oip), osize,
1618b39a0235SMilan Cermak 				    (uint32_t)(bsize - boff));
16197c478bd9Sstevel@tonic-gate 			}
16207c478bd9Sstevel@tonic-gate 			mutex_enter(&oip->i_tlock);
16217c478bd9Sstevel@tonic-gate 			oip->i_flag |= ICHG;
16227c478bd9Sstevel@tonic-gate 			ITIMES_NOLOCK(oip);
16237c478bd9Sstevel@tonic-gate 			mutex_exit(&oip->i_tlock);
16247c478bd9Sstevel@tonic-gate 		}
16257c478bd9Sstevel@tonic-gate 		return (error);
16267c478bd9Sstevel@tonic-gate 	}
16277c478bd9Sstevel@tonic-gate 
16287c478bd9Sstevel@tonic-gate 	/*
16297c478bd9Sstevel@tonic-gate 	 * Update the pages of the file.  If the file is not being
16307c478bd9Sstevel@tonic-gate 	 * truncated to a block boundary, the contents of the
16317c478bd9Sstevel@tonic-gate 	 * pages following the end of the file must be zero'ed
16327c478bd9Sstevel@tonic-gate 	 * in case it ever become accessable again because
16337c478bd9Sstevel@tonic-gate 	 * of subsequent file growth.
16347c478bd9Sstevel@tonic-gate 	 */
16357c478bd9Sstevel@tonic-gate 	if (boff == 0) {
16367c478bd9Sstevel@tonic-gate 		(void) pvn_vplist_dirty(ITOV(oip), length,
1637b39a0235SMilan Cermak 		    ud_putapage, B_INVAL | B_TRUNC, CRED());
16387c478bd9Sstevel@tonic-gate 	} else {
16397c478bd9Sstevel@tonic-gate 		/*
16407c478bd9Sstevel@tonic-gate 		 * Make sure that the last block is properly allocated.
16417c478bd9Sstevel@tonic-gate 		 * We only really have to do this if the last block is
16427c478bd9Sstevel@tonic-gate 		 * actually allocated.  Just to be sure, we do it now
16437c478bd9Sstevel@tonic-gate 		 * independent of current allocation.
16447c478bd9Sstevel@tonic-gate 		 */
16457c478bd9Sstevel@tonic-gate 		error = ud_bmap_write(oip, length - 1, boff, 0, cr);
16467c478bd9Sstevel@tonic-gate 		if (error) {
16477c478bd9Sstevel@tonic-gate 			return (error);
16487c478bd9Sstevel@tonic-gate 		}
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 		pvn_vpzero(ITOV(oip), length, (uint32_t)(bsize - boff));
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 		(void) pvn_vplist_dirty(ITOV(oip), length,
1653b39a0235SMilan Cermak 		    ud_putapage, B_INVAL | B_TRUNC, CRED());
16547c478bd9Sstevel@tonic-gate 	}
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 
16577c478bd9Sstevel@tonic-gate 	/* Free the blocks */
16587c478bd9Sstevel@tonic-gate 	if (oip->i_desc_type == ICB_FLAG_ONE_AD) {
16597c478bd9Sstevel@tonic-gate 		if (length > oip->i_max_emb) {
16607c478bd9Sstevel@tonic-gate 			return (EFBIG);
16617c478bd9Sstevel@tonic-gate 		}
16627c478bd9Sstevel@tonic-gate 		oip->i_size = length;
16637c478bd9Sstevel@tonic-gate 		mutex_enter(&oip->i_tlock);
16647c478bd9Sstevel@tonic-gate 		oip->i_flag |= ICHG|IUPD;
16657c478bd9Sstevel@tonic-gate 		mutex_exit(&oip->i_tlock);
16667c478bd9Sstevel@tonic-gate 		ud_iupdat(oip, 1);
16677c478bd9Sstevel@tonic-gate 	} else {
16687c478bd9Sstevel@tonic-gate 		if ((error = ud_read_icb_till_off(oip, oip->i_size)) != 0) {
16697c478bd9Sstevel@tonic-gate 			return (error);
16707c478bd9Sstevel@tonic-gate 		}
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate 		if (oip->i_astrat == STRAT_TYPE4) {
16737c478bd9Sstevel@tonic-gate 			ud_trunc_ext4(oip, length);
16747c478bd9Sstevel@tonic-gate 		} else if (oip->i_astrat == STRAT_TYPE4096) {
16757c478bd9Sstevel@tonic-gate 			ud_trunc_ext4096(oip, length);
16767c478bd9Sstevel@tonic-gate 		}
16777c478bd9Sstevel@tonic-gate 	}
16787c478bd9Sstevel@tonic-gate 
16797c478bd9Sstevel@tonic-gate done:
16807c478bd9Sstevel@tonic-gate 	return (0);
16817c478bd9Sstevel@tonic-gate }
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate void
ud_trunc_ext4(struct ud_inode * ip,u_offset_t length)16847c478bd9Sstevel@tonic-gate ud_trunc_ext4(struct ud_inode *ip, u_offset_t length)
16857c478bd9Sstevel@tonic-gate {
16867c478bd9Sstevel@tonic-gate 	int32_t index, l2b, count, ecount;
16877c478bd9Sstevel@tonic-gate 	int32_t elen, ndent, nient;
16887c478bd9Sstevel@tonic-gate 	u_offset_t ext_beg, ext_end;
16897c478bd9Sstevel@tonic-gate 	struct icb_ext *iext, *icon;
16907c478bd9Sstevel@tonic-gate 	int32_t lbmask, ext_used;
16917c478bd9Sstevel@tonic-gate 	uint32_t loc;
16927c478bd9Sstevel@tonic-gate 	struct icb_ext text;
16937c478bd9Sstevel@tonic-gate 	uint32_t con_freed;
16947c478bd9Sstevel@tonic-gate 
16957c478bd9Sstevel@tonic-gate 	ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) ||
1696b39a0235SMilan Cermak 	    (ip->i_desc_type == ICB_FLAG_LONG_AD));
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 	if (ip->i_ext_used == 0) {
16997c478bd9Sstevel@tonic-gate 		return;
17007c478bd9Sstevel@tonic-gate 	}
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	ext_used = ip->i_ext_used;
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	lbmask = ip->i_udf->udf_lbmask;
17057c478bd9Sstevel@tonic-gate 	l2b = ip->i_udf->udf_l2b_shift;
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 	ASSERT(ip->i_ext);
17087c478bd9Sstevel@tonic-gate 
17097c478bd9Sstevel@tonic-gate 	ip->i_lbr = 0;
17107c478bd9Sstevel@tonic-gate 	for (index = 0; index < ext_used; index++) {
17117c478bd9Sstevel@tonic-gate 		iext = &ip->i_ext[index];
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 		/*
17147c478bd9Sstevel@tonic-gate 		 * Find the begining and end
17157c478bd9Sstevel@tonic-gate 		 * of current extent
17167c478bd9Sstevel@tonic-gate 		 */
17177c478bd9Sstevel@tonic-gate 		ext_beg = iext->ib_offset;
17187c478bd9Sstevel@tonic-gate 		ext_end = iext->ib_offset +
1719b39a0235SMilan Cermak 		    ((iext->ib_count + lbmask) & ~lbmask);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 		/*
17227c478bd9Sstevel@tonic-gate 		 * This is the extent that has offset "length"
17237c478bd9Sstevel@tonic-gate 		 * make a copy of this extent and
17247c478bd9Sstevel@tonic-gate 		 * remember the index. We can use
17257c478bd9Sstevel@tonic-gate 		 * it to free blocks
17267c478bd9Sstevel@tonic-gate 		 */
1727b39a0235SMilan Cermak 		if ((length <= ext_end) && (length >= ext_beg)) {
17287c478bd9Sstevel@tonic-gate 			text = *iext;
17297c478bd9Sstevel@tonic-gate 
17307c478bd9Sstevel@tonic-gate 			iext->ib_count = length - ext_beg;
17317c478bd9Sstevel@tonic-gate 			ip->i_ext_used = index + 1;
17327c478bd9Sstevel@tonic-gate 			break;
17337c478bd9Sstevel@tonic-gate 		}
17347c478bd9Sstevel@tonic-gate 		if (iext->ib_flags != IB_UN_RE_AL) {
17357c478bd9Sstevel@tonic-gate 			ip->i_lbr += iext->ib_count >> l2b;
17367c478bd9Sstevel@tonic-gate 		}
17377c478bd9Sstevel@tonic-gate 	}
17387c478bd9Sstevel@tonic-gate 	if (ip->i_ext_used != index) {
17397c478bd9Sstevel@tonic-gate 		if (iext->ib_flags != IB_UN_RE_AL) {
17407c478bd9Sstevel@tonic-gate 			ip->i_lbr +=
1741b39a0235SMilan Cermak 			    ((iext->ib_count + lbmask) & ~lbmask) >> l2b;
17427c478bd9Sstevel@tonic-gate 		}
17437c478bd9Sstevel@tonic-gate 	}
17447c478bd9Sstevel@tonic-gate 
17457c478bd9Sstevel@tonic-gate 	ip->i_size = length;
17467c478bd9Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
17477c478bd9Sstevel@tonic-gate 	ip->i_flag |= ICHG|IUPD;
17487c478bd9Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
17497c478bd9Sstevel@tonic-gate 	ud_iupdat(ip, 1);
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	/*
17527c478bd9Sstevel@tonic-gate 	 * Free the unused space
17537c478bd9Sstevel@tonic-gate 	 */
17547c478bd9Sstevel@tonic-gate 	if (text.ib_flags != IB_UN_RE_AL) {
17557c478bd9Sstevel@tonic-gate 		count = (ext_end - length) >> l2b;
17567c478bd9Sstevel@tonic-gate 		if (count) {
17577c478bd9Sstevel@tonic-gate 			loc = text.ib_block +
1758b39a0235SMilan Cermak 			    (((length - text.ib_offset) + lbmask) >> l2b);
17597c478bd9Sstevel@tonic-gate 			ud_free_space(ip->i_udf->udf_vfs, text.ib_prn,
1760b39a0235SMilan Cermak 			    loc, count);
17617c478bd9Sstevel@tonic-gate 		}
17627c478bd9Sstevel@tonic-gate 	}
17637c478bd9Sstevel@tonic-gate 	for (index = ip->i_ext_used; index < ext_used; index++) {
17647c478bd9Sstevel@tonic-gate 		iext = &ip->i_ext[index];
17657c478bd9Sstevel@tonic-gate 		if (iext->ib_flags != IB_UN_RE_AL) {
17667c478bd9Sstevel@tonic-gate 			count = (iext->ib_count + lbmask) >> l2b;
17677c478bd9Sstevel@tonic-gate 			ud_free_space(ip->i_udf->udf_vfs, iext->ib_prn,
1768b39a0235SMilan Cermak 			    iext->ib_block, count);
17697c478bd9Sstevel@tonic-gate 		}
17707c478bd9Sstevel@tonic-gate 		bzero(iext, sizeof (struct icb_ext));
17717c478bd9Sstevel@tonic-gate 		continue;
17727c478bd9Sstevel@tonic-gate 	}
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	/*
17757c478bd9Sstevel@tonic-gate 	 * release any continuation blocks
17767c478bd9Sstevel@tonic-gate 	 */
17777c478bd9Sstevel@tonic-gate 	if (ip->i_con) {
17787c478bd9Sstevel@tonic-gate 
17797c478bd9Sstevel@tonic-gate 		ASSERT(ip->i_con_count >= ip->i_con_used);
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 		/*
17827c478bd9Sstevel@tonic-gate 		 * Find out how many indirect blocks
17837c478bd9Sstevel@tonic-gate 		 * are required and release the rest
17847c478bd9Sstevel@tonic-gate 		 */
17857c478bd9Sstevel@tonic-gate 		if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
17867c478bd9Sstevel@tonic-gate 			elen = sizeof (struct short_ad);
17877c478bd9Sstevel@tonic-gate 		} else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
17887c478bd9Sstevel@tonic-gate 			elen = sizeof (struct long_ad);
17897c478bd9Sstevel@tonic-gate 		}
17907c478bd9Sstevel@tonic-gate 		ndent = ip->i_max_emb / elen;
17917c478bd9Sstevel@tonic-gate 		if (ip->i_ext_used > ndent) {
17927c478bd9Sstevel@tonic-gate 			ecount = ip->i_ext_used - ndent;
17937c478bd9Sstevel@tonic-gate 		} else {
17947c478bd9Sstevel@tonic-gate 			ecount = 0;
17957c478bd9Sstevel@tonic-gate 		}
17967c478bd9Sstevel@tonic-gate 		con_freed = 0;
17977c478bd9Sstevel@tonic-gate 		for (index = 0; index < ip->i_con_used; index++) {
17987c478bd9Sstevel@tonic-gate 			icon = &ip->i_con[index];
17997c478bd9Sstevel@tonic-gate 			nient = icon->ib_count -
1800b39a0235SMilan Cermak 			    (sizeof (struct alloc_ext_desc) + elen);
1801b39a0235SMilan Cermak 			/* Header + 1 indirect extent */
18027c478bd9Sstevel@tonic-gate 			nient /= elen;
18037c478bd9Sstevel@tonic-gate 			if (ecount) {
18047c478bd9Sstevel@tonic-gate 				if (ecount > nient) {
18057c478bd9Sstevel@tonic-gate 					ecount -= nient;
18067c478bd9Sstevel@tonic-gate 				} else {
18077c478bd9Sstevel@tonic-gate 					ecount = 0;
18087c478bd9Sstevel@tonic-gate 				}
18097c478bd9Sstevel@tonic-gate 			} else {
18107c478bd9Sstevel@tonic-gate 				count = ((icon->ib_count + lbmask) &
1811b39a0235SMilan Cermak 				    ~lbmask) >> l2b;
18127c478bd9Sstevel@tonic-gate 				ud_free_space(ip->i_udf->udf_vfs,
1813b39a0235SMilan Cermak 				    icon->ib_prn, icon->ib_block, count);
18147c478bd9Sstevel@tonic-gate 				con_freed++;
18157c478bd9Sstevel@tonic-gate 				ip->i_cur_max_ext -= nient;
18167c478bd9Sstevel@tonic-gate 			}
18177c478bd9Sstevel@tonic-gate 		}
18187c478bd9Sstevel@tonic-gate 		/*
18197c478bd9Sstevel@tonic-gate 		 * set the continuation extents used(i_con_used)i to correct
18207c478bd9Sstevel@tonic-gate 		 * value. It is possible for i_con_used to be zero,
18217c478bd9Sstevel@tonic-gate 		 * if we free up all continuation extents. This happens
18227c478bd9Sstevel@tonic-gate 		 * when ecount is 0 before entering the for loop above.
18237c478bd9Sstevel@tonic-gate 		 */
18247c478bd9Sstevel@tonic-gate 		ip->i_con_used -= con_freed;
18257c478bd9Sstevel@tonic-gate 		if (ip->i_con_read > ip->i_con_used) {
18267c478bd9Sstevel@tonic-gate 			ip->i_con_read = ip->i_con_used;
18277c478bd9Sstevel@tonic-gate 		}
18287c478bd9Sstevel@tonic-gate 	}
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate 
18317c478bd9Sstevel@tonic-gate void
ud_trunc_ext4096(struct ud_inode * ip,u_offset_t length)18327c478bd9Sstevel@tonic-gate ud_trunc_ext4096(struct ud_inode *ip, u_offset_t length)
18337c478bd9Sstevel@tonic-gate {
18347c478bd9Sstevel@tonic-gate 	/*
18357c478bd9Sstevel@tonic-gate 	 * Truncate code is the same for
18367c478bd9Sstevel@tonic-gate 	 * both file of type 4 and 4096
18377c478bd9Sstevel@tonic-gate 	 */
18387c478bd9Sstevel@tonic-gate 	ud_trunc_ext4(ip, length);
18397c478bd9Sstevel@tonic-gate }
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate /*
18427c478bd9Sstevel@tonic-gate  * Remove any inodes in the inode cache belonging to dev
18437c478bd9Sstevel@tonic-gate  *
18447c478bd9Sstevel@tonic-gate  * There should not be any active ones, return error if any are found but
18457c478bd9Sstevel@tonic-gate  * still invalidate others (N.B.: this is a user error, not a system error).
18467c478bd9Sstevel@tonic-gate  *
18477c478bd9Sstevel@tonic-gate  * Also, count the references to dev by block devices - this really
18487c478bd9Sstevel@tonic-gate  * has nothing to do with the object of the procedure, but as we have
18497c478bd9Sstevel@tonic-gate  * to scan the inode table here anyway, we might as well get the
18507c478bd9Sstevel@tonic-gate  * extra benefit.
18517c478bd9Sstevel@tonic-gate  */
18527c478bd9Sstevel@tonic-gate int32_t
ud_iflush(struct vfs * vfsp)18537c478bd9Sstevel@tonic-gate ud_iflush(struct vfs *vfsp)
18547c478bd9Sstevel@tonic-gate {
18557c478bd9Sstevel@tonic-gate 	int32_t index, busy = 0;
18567c478bd9Sstevel@tonic-gate 	union ihead *ih;
18577c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
18587c478bd9Sstevel@tonic-gate 	dev_t dev;
18597c478bd9Sstevel@tonic-gate 	struct vnode *rvp, *vp;
18607c478bd9Sstevel@tonic-gate 	struct ud_inode *ip, *next;
18617c478bd9Sstevel@tonic-gate 
18627c478bd9Sstevel@tonic-gate 	ud_printf("ud_iflush\n");
18637c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
18647c478bd9Sstevel@tonic-gate 	rvp = udf_vfsp->udf_root;
18657c478bd9Sstevel@tonic-gate 	dev = vfsp->vfs_dev;
18667c478bd9Sstevel@tonic-gate 
18677c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_icache_lock);
18687c478bd9Sstevel@tonic-gate 	for (index = 0; index < UD_HASH_SZ; index++) {
18697c478bd9Sstevel@tonic-gate 		ih = &ud_ihead[index];
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate 		next = ih->ih_chain[0];
18727c478bd9Sstevel@tonic-gate 		while (next != (struct ud_inode *)ih) {
18737c478bd9Sstevel@tonic-gate 			ip = next;
18747c478bd9Sstevel@tonic-gate 			next = ip->i_forw;
18757c478bd9Sstevel@tonic-gate 			if (ip->i_dev != dev) {
18767c478bd9Sstevel@tonic-gate 				continue;
18777c478bd9Sstevel@tonic-gate 			}
18787c478bd9Sstevel@tonic-gate 			vp = ITOV(ip);
18797c478bd9Sstevel@tonic-gate 			/*
18807c478bd9Sstevel@tonic-gate 			 * root inode is processed by the caller
18817c478bd9Sstevel@tonic-gate 			 */
18827c478bd9Sstevel@tonic-gate 			if (vp == rvp) {
18837c478bd9Sstevel@tonic-gate 				if (vp->v_count > 1) {
18847c478bd9Sstevel@tonic-gate 					busy = -1;
18857c478bd9Sstevel@tonic-gate 				}
18867c478bd9Sstevel@tonic-gate 				continue;
18877c478bd9Sstevel@tonic-gate 			}
18887c478bd9Sstevel@tonic-gate 			if (ip->i_flag & IREF) {
18897c478bd9Sstevel@tonic-gate 				/*
18907c478bd9Sstevel@tonic-gate 				 * Set error indicator for return value,
18917c478bd9Sstevel@tonic-gate 				 * but continue invalidating other
18927c478bd9Sstevel@tonic-gate 				 * inodes.
18937c478bd9Sstevel@tonic-gate 				 */
18947c478bd9Sstevel@tonic-gate 				busy = -1;
18957c478bd9Sstevel@tonic-gate 				continue;
18967c478bd9Sstevel@tonic-gate 			}
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 			rw_enter(&ip->i_contents, RW_WRITER);
18997c478bd9Sstevel@tonic-gate 			remque(ip);
19007c478bd9Sstevel@tonic-gate 			ip->i_forw = ip;
19017c478bd9Sstevel@tonic-gate 			ip->i_back = ip;
19027c478bd9Sstevel@tonic-gate 			/*
19037c478bd9Sstevel@tonic-gate 			 * Hold the vnode since its not done
19047c478bd9Sstevel@tonic-gate 			 * in VOP_PUTPAGE anymore.
19057c478bd9Sstevel@tonic-gate 			 */
19067c478bd9Sstevel@tonic-gate 			VN_HOLD(vp);
19077c478bd9Sstevel@tonic-gate 			/*
19087c478bd9Sstevel@tonic-gate 			 * XXX Synchronous write holding
19097c478bd9Sstevel@tonic-gate 			 * cache lock
19107c478bd9Sstevel@tonic-gate 			 */
19117c478bd9Sstevel@tonic-gate 			(void) ud_syncip(ip, B_INVAL, I_SYNC);
19127c478bd9Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
19137c478bd9Sstevel@tonic-gate 			VN_RELE(vp);
19147c478bd9Sstevel@tonic-gate 		}
19157c478bd9Sstevel@tonic-gate 	}
19167c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_icache_lock);
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 	return (busy);
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate /*
19237c478bd9Sstevel@tonic-gate  * Check mode permission on inode.  Mode is READ, WRITE or EXEC.
19247c478bd9Sstevel@tonic-gate  * In the case of WRITE, the read-only status of the file system
19257c478bd9Sstevel@tonic-gate  * is checked.  The applicable mode bits are compared with the
19267c478bd9Sstevel@tonic-gate  * requested form of access.  If bits are missing, the secpolicy
19277c478bd9Sstevel@tonic-gate  * function will check for privileges.
19287c478bd9Sstevel@tonic-gate  */
19297c478bd9Sstevel@tonic-gate int
ud_iaccess(struct ud_inode * ip,int32_t mode,struct cred * cr,int dolock)1930b39a0235SMilan Cermak ud_iaccess(struct ud_inode *ip, int32_t mode, struct cred *cr, int dolock)
19317c478bd9Sstevel@tonic-gate {
19327c478bd9Sstevel@tonic-gate 	int shift = 0;
1933b39a0235SMilan Cermak 	int ret = 0;
1934b39a0235SMilan Cermak 
1935b39a0235SMilan Cermak 	if (dolock)
1936b39a0235SMilan Cermak 		rw_enter(&ip->i_contents, RW_READER);
1937b39a0235SMilan Cermak 	ASSERT(RW_LOCK_HELD(&ip->i_contents));
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	ud_printf("ud_iaccess\n");
19407c478bd9Sstevel@tonic-gate 	if (mode & IWRITE) {
19417c478bd9Sstevel@tonic-gate 		/*
19427c478bd9Sstevel@tonic-gate 		 * Disallow write attempts on read-only
19437c478bd9Sstevel@tonic-gate 		 * file systems, unless the file is a block
19447c478bd9Sstevel@tonic-gate 		 * or character device or a FIFO.
19457c478bd9Sstevel@tonic-gate 		 */
19467c478bd9Sstevel@tonic-gate 		if (ip->i_udf->udf_flags & UDF_FL_RDONLY) {
19477c478bd9Sstevel@tonic-gate 			if ((ip->i_type != VCHR) &&
19487c478bd9Sstevel@tonic-gate 			    (ip->i_type != VBLK) &&
19497c478bd9Sstevel@tonic-gate 			    (ip->i_type != VFIFO)) {
1950b39a0235SMilan Cermak 				ret = EROFS;
1951b39a0235SMilan Cermak 				goto out;
19527c478bd9Sstevel@tonic-gate 			}
19537c478bd9Sstevel@tonic-gate 		}
19547c478bd9Sstevel@tonic-gate 	}
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	/*
19577c478bd9Sstevel@tonic-gate 	 * Access check is based on only
19587c478bd9Sstevel@tonic-gate 	 * one of owner, group, public.
19597c478bd9Sstevel@tonic-gate 	 * If not owner, then check group.
19607c478bd9Sstevel@tonic-gate 	 * If not a member of the group, then
19617c478bd9Sstevel@tonic-gate 	 * check public access.
19627c478bd9Sstevel@tonic-gate 	 */
19637c478bd9Sstevel@tonic-gate 	if (crgetuid(cr) != ip->i_uid) {
19647c478bd9Sstevel@tonic-gate 		shift += 5;
19657c478bd9Sstevel@tonic-gate 		if (!groupmember((uid_t)ip->i_gid, cr))
19667c478bd9Sstevel@tonic-gate 			shift += 5;
19677c478bd9Sstevel@tonic-gate 	}
19687c478bd9Sstevel@tonic-gate 
1969134a1f4eSCasper H.S. Dik 	ret = secpolicy_vnode_access2(cr, ITOV(ip), ip->i_uid,
1970134a1f4eSCasper H.S. Dik 	    UD2VA_PERM(ip->i_perm << shift), UD2VA_PERM(mode));
1971b39a0235SMilan Cermak 
1972b39a0235SMilan Cermak out:
1973b39a0235SMilan Cermak 	if (dolock)
1974b39a0235SMilan Cermak 		rw_exit(&ip->i_contents);
1975b39a0235SMilan Cermak 	return (ret);
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate 
19787c478bd9Sstevel@tonic-gate void
ud_imark(struct ud_inode * ip)19797c478bd9Sstevel@tonic-gate ud_imark(struct ud_inode *ip)
19807c478bd9Sstevel@tonic-gate {
19817c478bd9Sstevel@tonic-gate 	timestruc_t	now;
19827c478bd9Sstevel@tonic-gate 
19837c478bd9Sstevel@tonic-gate 	gethrestime(&now);
19847c478bd9Sstevel@tonic-gate 	ud_printf("ud_imark\n");
19857c478bd9Sstevel@tonic-gate 	if (ip->i_flag & IACC) {
19867c478bd9Sstevel@tonic-gate 		ip->i_atime.tv_sec = now.tv_sec;
19877c478bd9Sstevel@tonic-gate 		ip->i_atime.tv_nsec = now.tv_nsec;
19887c478bd9Sstevel@tonic-gate 	}
19897c478bd9Sstevel@tonic-gate 	if (ip->i_flag & IUPD) {
19907c478bd9Sstevel@tonic-gate 		ip->i_mtime.tv_sec = now.tv_sec;
19917c478bd9Sstevel@tonic-gate 		ip->i_mtime.tv_nsec = now.tv_nsec;
19927c478bd9Sstevel@tonic-gate 		ip->i_flag |= IMODTIME;
19937c478bd9Sstevel@tonic-gate 	}
19947c478bd9Sstevel@tonic-gate 	if (ip->i_flag & ICHG) {
19957c478bd9Sstevel@tonic-gate 		ip->i_diroff = 0;
19967c478bd9Sstevel@tonic-gate 		ip->i_ctime.tv_sec = now.tv_sec;
19977c478bd9Sstevel@tonic-gate 		ip->i_ctime.tv_nsec = now.tv_nsec;
19987c478bd9Sstevel@tonic-gate 	}
19997c478bd9Sstevel@tonic-gate }
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 
20027c478bd9Sstevel@tonic-gate void
ud_itimes_nolock(struct ud_inode * ip)20037c478bd9Sstevel@tonic-gate ud_itimes_nolock(struct ud_inode *ip)
20047c478bd9Sstevel@tonic-gate {
20057c478bd9Sstevel@tonic-gate 	ud_printf("ud_itimes_nolock\n");
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 	if (ip->i_flag & (IUPD|IACC|ICHG)) {
20087c478bd9Sstevel@tonic-gate 		if (ip->i_flag & ICHG) {
20097c478bd9Sstevel@tonic-gate 			ip->i_flag |= IMOD;
20107c478bd9Sstevel@tonic-gate 		} else {
20117c478bd9Sstevel@tonic-gate 			ip->i_flag |= IMODACC;
20127c478bd9Sstevel@tonic-gate 		}
20137c478bd9Sstevel@tonic-gate 		ud_imark(ip);
20147c478bd9Sstevel@tonic-gate 		ip->i_flag &= ~(IACC|IUPD|ICHG);
20157c478bd9Sstevel@tonic-gate 	}
20167c478bd9Sstevel@tonic-gate }
20177c478bd9Sstevel@tonic-gate 
20187c478bd9Sstevel@tonic-gate void
ud_delcache(struct ud_inode * ip)20197c478bd9Sstevel@tonic-gate ud_delcache(struct ud_inode *ip)
20207c478bd9Sstevel@tonic-gate {
20217c478bd9Sstevel@tonic-gate 	ud_printf("ud_delcache\n");
20227c478bd9Sstevel@tonic-gate 
20237c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_icache_lock);
20247c478bd9Sstevel@tonic-gate 	remque(ip);
20257c478bd9Sstevel@tonic-gate 	ip->i_forw = ip;
20267c478bd9Sstevel@tonic-gate 	ip->i_back = ip;
20277c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_icache_lock);
20287c478bd9Sstevel@tonic-gate }
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate void
ud_idrop(struct ud_inode * ip)20317c478bd9Sstevel@tonic-gate ud_idrop(struct ud_inode *ip)
20327c478bd9Sstevel@tonic-gate {
20337c478bd9Sstevel@tonic-gate 	struct vnode *vp = ITOV(ip);
20347c478bd9Sstevel@tonic-gate 
20357c478bd9Sstevel@tonic-gate 	ASSERT(RW_WRITE_HELD(&ip->i_contents));
20367c478bd9Sstevel@tonic-gate 
20377c478bd9Sstevel@tonic-gate 	ud_printf("ud_idrop\n");
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	mutex_enter(&vp->v_lock);
2040*ade42b55SSebastien Roy 	VN_RELE_LOCKED(vp);
2041*ade42b55SSebastien Roy 	if (vp->v_count > 0) {
20427c478bd9Sstevel@tonic-gate 		mutex_exit(&vp->v_lock);
20437c478bd9Sstevel@tonic-gate 		return;
20447c478bd9Sstevel@tonic-gate 	}
20457c478bd9Sstevel@tonic-gate 	mutex_exit(&vp->v_lock);
20467c478bd9Sstevel@tonic-gate 
20477c478bd9Sstevel@tonic-gate 	/*
20487c478bd9Sstevel@tonic-gate 	 *  if inode is invalid or there is no page associated with
20497c478bd9Sstevel@tonic-gate 	 *  this inode, put the inode in the front of the free list
20507c478bd9Sstevel@tonic-gate 	 */
20517c478bd9Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
20527c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_ifree_lock);
20537c478bd9Sstevel@tonic-gate 	if (!vn_has_cached_data(vp) || ip->i_perm == 0) {
20547c478bd9Sstevel@tonic-gate 		ud_add_to_free_list(ip, UD_BEGIN);
20557c478bd9Sstevel@tonic-gate 	} else {
20567c478bd9Sstevel@tonic-gate 		/*
20577c478bd9Sstevel@tonic-gate 		 * Otherwise, put the inode back on the end of the free list.
20587c478bd9Sstevel@tonic-gate 		 */
20597c478bd9Sstevel@tonic-gate 		ud_add_to_free_list(ip, UD_END);
20607c478bd9Sstevel@tonic-gate 	}
20617c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_ifree_lock);
20627c478bd9Sstevel@tonic-gate 	ip->i_flag &= IMODTIME;
20637c478bd9Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
20647c478bd9Sstevel@tonic-gate }
20657c478bd9Sstevel@tonic-gate 
20667c478bd9Sstevel@tonic-gate void
ud_add_to_free_list(struct ud_inode * ip,uint32_t at)20677c478bd9Sstevel@tonic-gate ud_add_to_free_list(struct ud_inode *ip, uint32_t at)
20687c478bd9Sstevel@tonic-gate {
20697c478bd9Sstevel@tonic-gate 	ASSERT(ip);
20707c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&udf_ifree_lock));
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate #ifdef	DEBUG
20737c478bd9Sstevel@tonic-gate 	/* Search if the element is already in the list */
20747c478bd9Sstevel@tonic-gate 	if (udf_ifreeh != NULL) {
20757c478bd9Sstevel@tonic-gate 		struct ud_inode *iq;
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 		iq = udf_ifreeh;
20787c478bd9Sstevel@tonic-gate 		while (iq) {
20797c478bd9Sstevel@tonic-gate 			if (iq == ip) {
20807c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "Duplicate %p\n", (void *)ip);
20817c478bd9Sstevel@tonic-gate 			}
20827c478bd9Sstevel@tonic-gate 			iq = iq->i_freef;
20837c478bd9Sstevel@tonic-gate 		}
20847c478bd9Sstevel@tonic-gate 	}
20857c478bd9Sstevel@tonic-gate #endif
20867c478bd9Sstevel@tonic-gate 
20877c478bd9Sstevel@tonic-gate 	ip->i_freef = NULL;
20887c478bd9Sstevel@tonic-gate 	ip->i_freeb = NULL;
20897c478bd9Sstevel@tonic-gate 	if (udf_ifreeh == NULL) {
20907c478bd9Sstevel@tonic-gate 		/*
20917c478bd9Sstevel@tonic-gate 		 * Nothing on the list just add it
20927c478bd9Sstevel@tonic-gate 		 */
20937c478bd9Sstevel@tonic-gate 		udf_ifreeh = ip;
20947c478bd9Sstevel@tonic-gate 		udf_ifreet = ip;
20957c478bd9Sstevel@tonic-gate 	} else {
20967c478bd9Sstevel@tonic-gate 		if (at == UD_BEGIN) {
20977c478bd9Sstevel@tonic-gate 			/*
20987c478bd9Sstevel@tonic-gate 			 * Add at the begining of the list
20997c478bd9Sstevel@tonic-gate 			 */
21007c478bd9Sstevel@tonic-gate 			ip->i_freef = udf_ifreeh;
21017c478bd9Sstevel@tonic-gate 			udf_ifreeh->i_freeb = ip;
21027c478bd9Sstevel@tonic-gate 			udf_ifreeh = ip;
21037c478bd9Sstevel@tonic-gate 		} else {
21047c478bd9Sstevel@tonic-gate 			/*
21057c478bd9Sstevel@tonic-gate 			 * Add at the end of the list
21067c478bd9Sstevel@tonic-gate 			 */
21077c478bd9Sstevel@tonic-gate 			ip->i_freeb = udf_ifreet;
21087c478bd9Sstevel@tonic-gate 			udf_ifreet->i_freef = ip;
21097c478bd9Sstevel@tonic-gate 			udf_ifreet = ip;
21107c478bd9Sstevel@tonic-gate 		}
21117c478bd9Sstevel@tonic-gate 	}
21127c478bd9Sstevel@tonic-gate }
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate void
ud_remove_from_free_list(struct ud_inode * ip,uint32_t at)21157c478bd9Sstevel@tonic-gate ud_remove_from_free_list(struct ud_inode *ip, uint32_t at)
21167c478bd9Sstevel@tonic-gate {
21177c478bd9Sstevel@tonic-gate 	ASSERT(ip);
21187c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&udf_ifree_lock));
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate #ifdef	DEBUG
21217c478bd9Sstevel@tonic-gate 	{
21227c478bd9Sstevel@tonic-gate 		struct ud_inode *iq;
21237c478bd9Sstevel@tonic-gate 		uint32_t found = 0;
21247c478bd9Sstevel@tonic-gate 
21257c478bd9Sstevel@tonic-gate 		iq = udf_ifreeh;
21267c478bd9Sstevel@tonic-gate 		while (iq) {
21277c478bd9Sstevel@tonic-gate 			if (iq == ip) {
21287c478bd9Sstevel@tonic-gate 				found++;
21297c478bd9Sstevel@tonic-gate 			}
21307c478bd9Sstevel@tonic-gate 			iq = iq->i_freef;
21317c478bd9Sstevel@tonic-gate 		}
21327c478bd9Sstevel@tonic-gate 		if (found != 1) {
21337c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "ip %p is found %x times\n",
2134b39a0235SMilan Cermak 			    (void *)ip,  found);
21357c478bd9Sstevel@tonic-gate 		}
21367c478bd9Sstevel@tonic-gate 	}
21377c478bd9Sstevel@tonic-gate #endif
21387c478bd9Sstevel@tonic-gate 
2139b39a0235SMilan Cermak 	if ((ip->i_freef == NULL) && (ip->i_freeb == NULL)) {
21407c478bd9Sstevel@tonic-gate 		if (ip != udf_ifreeh) {
21417c478bd9Sstevel@tonic-gate 			return;
21427c478bd9Sstevel@tonic-gate 		}
21437c478bd9Sstevel@tonic-gate 	}
21447c478bd9Sstevel@tonic-gate 
2145b39a0235SMilan Cermak 	if ((at == UD_BEGIN) || (ip == udf_ifreeh)) {
21467c478bd9Sstevel@tonic-gate 		udf_ifreeh = ip->i_freef;
21477c478bd9Sstevel@tonic-gate 		if (ip->i_freef == NULL) {
21487c478bd9Sstevel@tonic-gate 			udf_ifreet = NULL;
21497c478bd9Sstevel@tonic-gate 		} else {
21507c478bd9Sstevel@tonic-gate 			udf_ifreeh->i_freeb = NULL;
21517c478bd9Sstevel@tonic-gate 		}
21527c478bd9Sstevel@tonic-gate 	} else {
21537c478bd9Sstevel@tonic-gate 		ip->i_freeb->i_freef = ip->i_freef;
21547c478bd9Sstevel@tonic-gate 		if (ip->i_freef) {
21557c478bd9Sstevel@tonic-gate 			ip->i_freef->i_freeb = ip->i_freeb;
21567c478bd9Sstevel@tonic-gate 		} else {
21577c478bd9Sstevel@tonic-gate 			udf_ifreet = ip->i_freeb;
21587c478bd9Sstevel@tonic-gate 		}
21597c478bd9Sstevel@tonic-gate 	}
21607c478bd9Sstevel@tonic-gate 	ip->i_freef = NULL;
21617c478bd9Sstevel@tonic-gate 	ip->i_freeb = NULL;
21627c478bd9Sstevel@tonic-gate }
21637c478bd9Sstevel@tonic-gate 
21647c478bd9Sstevel@tonic-gate void
ud_init_inodes(void)21657c478bd9Sstevel@tonic-gate ud_init_inodes(void)
21667c478bd9Sstevel@tonic-gate {
21677c478bd9Sstevel@tonic-gate 	union ihead *ih = ud_ihead;
21687c478bd9Sstevel@tonic-gate 	int index;
21697c478bd9Sstevel@tonic-gate 
21707c478bd9Sstevel@tonic-gate #ifndef	__lint
21717c478bd9Sstevel@tonic-gate 	_NOTE(NO_COMPETING_THREADS_NOW);
21727c478bd9Sstevel@tonic-gate #endif
21737c478bd9Sstevel@tonic-gate 	for (index = 0; index < UD_HASH_SZ; index++, ih++) {
21747c478bd9Sstevel@tonic-gate 		ih->ih_head[0] = ih;
21757c478bd9Sstevel@tonic-gate 		ih->ih_head[1] = ih;
21767c478bd9Sstevel@tonic-gate 	}
21777c478bd9Sstevel@tonic-gate 	mutex_init(&ud_icache_lock, NULL, MUTEX_DEFAULT, NULL);
21787c478bd9Sstevel@tonic-gate 	mutex_init(&ud_nino_lock, NULL, MUTEX_DEFAULT, NULL);
21797c478bd9Sstevel@tonic-gate 
21807c478bd9Sstevel@tonic-gate 	udf_ifreeh = NULL;
21817c478bd9Sstevel@tonic-gate 	udf_ifreet = NULL;
21827c478bd9Sstevel@tonic-gate 	mutex_init(&udf_ifree_lock, NULL, MUTEX_DEFAULT, NULL);
21837c478bd9Sstevel@tonic-gate 
21847c478bd9Sstevel@tonic-gate 	mutex_init(&ud_sync_busy, NULL, MUTEX_DEFAULT, NULL);
21857c478bd9Sstevel@tonic-gate 	udf_vfs_instances = NULL;
21867c478bd9Sstevel@tonic-gate 	mutex_init(&udf_vfs_mutex, NULL, MUTEX_DEFAULT, NULL);
21877c478bd9Sstevel@tonic-gate 
21887c478bd9Sstevel@tonic-gate #ifndef	__lint
21897c478bd9Sstevel@tonic-gate 	_NOTE(COMPETING_THREADS_NOW);
21907c478bd9Sstevel@tonic-gate #endif
21917c478bd9Sstevel@tonic-gate }
2192