xref: /illumos-gate/usr/src/uts/common/fs/udfs/udf_alloc.c (revision ad9a7bd3)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
297c478bd9Sstevel@tonic-gate #include <sys/param.h>
307c478bd9Sstevel@tonic-gate #include <sys/time.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
337c478bd9Sstevel@tonic-gate #include <sys/resource.h>
347c478bd9Sstevel@tonic-gate #include <sys/signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/cred.h>
367c478bd9Sstevel@tonic-gate #include <sys/user.h>
377c478bd9Sstevel@tonic-gate #include <sys/buf.h>
387c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
417c478bd9Sstevel@tonic-gate #include <sys/mode.h>
427c478bd9Sstevel@tonic-gate #include <sys/proc.h>
437c478bd9Sstevel@tonic-gate #include <sys/disp.h>
447c478bd9Sstevel@tonic-gate #include <sys/file.h>
457c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
467c478bd9Sstevel@tonic-gate #include <sys/flock.h>
477c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
487c478bd9Sstevel@tonic-gate #include <sys/uio.h>
497c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
507c478bd9Sstevel@tonic-gate #include <sys/conf.h>
517c478bd9Sstevel@tonic-gate #include <sys/errno.h>
527c478bd9Sstevel@tonic-gate #include <sys/mman.h>
537c478bd9Sstevel@tonic-gate #include <sys/fbuf.h>
547c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
557c478bd9Sstevel@tonic-gate #include <sys/debug.h>
567c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
577c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
587c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
597c478bd9Sstevel@tonic-gate #include <sys/errno.h>
607c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
617c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
627c478bd9Sstevel@tonic-gate #include <sys/mount.h>
637c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
647c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
657c478bd9Sstevel@tonic-gate #include <sys/policy.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #include <vm/hat.h>
687c478bd9Sstevel@tonic-gate #include <vm/page.h>
697c478bd9Sstevel@tonic-gate #include <vm/pvn.h>
707c478bd9Sstevel@tonic-gate #include <vm/as.h>
717c478bd9Sstevel@tonic-gate #include <vm/seg.h>
727c478bd9Sstevel@tonic-gate #include <vm/seg_map.h>
737c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
747c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
757c478bd9Sstevel@tonic-gate #include <vm/rm.h>
767c478bd9Sstevel@tonic-gate #include <vm/page.h>
777c478bd9Sstevel@tonic-gate #include <sys/swap.h>
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
827c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h>
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #ifdef	DEBUG
857c478bd9Sstevel@tonic-gate extern struct ud_inode *ud_search_icache(struct vfs *, uint16_t, uint32_t);
867c478bd9Sstevel@tonic-gate #endif
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate int32_t ud_alloc_space_bmap(struct vfs *, struct ud_part *,
897c478bd9Sstevel@tonic-gate 	uint32_t, uint32_t, uint32_t *, uint32_t *, int32_t);
907c478bd9Sstevel@tonic-gate int32_t ud_check_free_and_mark_used(struct vfs *,
917c478bd9Sstevel@tonic-gate 	struct ud_part *, uint32_t, uint32_t *);
927c478bd9Sstevel@tonic-gate int32_t ud_check_free(uint8_t *, uint8_t *, uint32_t, uint32_t);
937c478bd9Sstevel@tonic-gate void ud_mark_used(uint8_t *, uint32_t, uint32_t);
947c478bd9Sstevel@tonic-gate void ud_mark_free(uint8_t *, uint32_t, uint32_t);
957c478bd9Sstevel@tonic-gate int32_t ud_alloc_space_stbl(struct vfs *, struct ud_part *,
967c478bd9Sstevel@tonic-gate 	uint32_t, uint32_t, uint32_t *, uint32_t *, int32_t);
977c478bd9Sstevel@tonic-gate int32_t ud_free_space_bmap(struct vfs *,
987c478bd9Sstevel@tonic-gate 	struct ud_part *, uint32_t, uint32_t);
997c478bd9Sstevel@tonic-gate int32_t ud_free_space_stbl(struct vfs *,
1007c478bd9Sstevel@tonic-gate 	struct ud_part *, uint32_t, uint32_t);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * WORKSAROUND to the buffer cache crap
1057c478bd9Sstevel@tonic-gate  * If the requested block exists in the buffer cache
1067c478bd9Sstevel@tonic-gate  * buffer cache does not care about the count
1077c478bd9Sstevel@tonic-gate  * it just returns the old buffer(does not even
1087c478bd9Sstevel@tonic-gate  * set resid value). Same problem exists if the
1097c478bd9Sstevel@tonic-gate  * block that is requested is not the first block
1107c478bd9Sstevel@tonic-gate  * in the cached buffer then this will return
1117c478bd9Sstevel@tonic-gate  * a different buffer. We work around the above by
1127c478bd9Sstevel@tonic-gate  * using a fixed size request to the buffer cache
1137c478bd9Sstevel@tonic-gate  * all the time. This is currently udf_lbsize.
1147c478bd9Sstevel@tonic-gate  * (Actually it is restricted to udf_lbsize
1157c478bd9Sstevel@tonic-gate  * because iget always does udf_lbsize requests)
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * allocate blkcount blocks continuously
1217c478bd9Sstevel@tonic-gate  * near "proximity" block in partion defined by prn.
1227c478bd9Sstevel@tonic-gate  * if proximity != 0 means less_is_ok = 0
1237c478bd9Sstevel@tonic-gate  * return the starting block no and count
1247c478bd9Sstevel@tonic-gate  * of blocks allocated in start_blkno & size
1257c478bd9Sstevel@tonic-gate  * if less_is_ok == 0 then allocate only if
1267c478bd9Sstevel@tonic-gate  * entire requirement can be met.
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate int32_t
ud_alloc_space(struct vfs * vfsp,uint16_t prn,uint32_t proximity,uint32_t blkcount,uint32_t * start_blkno,uint32_t * size,int32_t less_is_ok,int32_t metadata)1297c478bd9Sstevel@tonic-gate ud_alloc_space(struct vfs *vfsp, uint16_t prn,
1307c478bd9Sstevel@tonic-gate 	uint32_t proximity, uint32_t blkcount,
1317c478bd9Sstevel@tonic-gate 	uint32_t *start_blkno, uint32_t *size,
1327c478bd9Sstevel@tonic-gate 	int32_t less_is_ok, int32_t metadata)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 	int32_t i, error = 0;
1357c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
1367c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	ud_printf("ud_alloc_space\n");
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * prom_printf("ud_alloc_space %x %x %x %x\n",
1437c478bd9Sstevel@tonic-gate  * proximity, blkcount, less_is_ok, metadata);
1447c478bd9Sstevel@tonic-gate  */
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (blkcount == 0) {
1477c478bd9Sstevel@tonic-gate 		*start_blkno = 0;
1487c478bd9Sstevel@tonic-gate 		*size = 0;
1497c478bd9Sstevel@tonic-gate 		return (0);
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1537c478bd9Sstevel@tonic-gate 	ud_part = udf_vfsp->udf_parts;
1547c478bd9Sstevel@tonic-gate 	for (i = 0; i < udf_vfsp->udf_npart; i++) {
1557c478bd9Sstevel@tonic-gate 		if (prn == ud_part->udp_number) {
1567c478bd9Sstevel@tonic-gate 			break;
1577c478bd9Sstevel@tonic-gate 		}
1587c478bd9Sstevel@tonic-gate 		ud_part ++;
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	if (i == udf_vfsp->udf_npart) {
1627c478bd9Sstevel@tonic-gate 		return (1);
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 	*start_blkno = 0;
1657c478bd9Sstevel@tonic-gate 	*size = 0;
1667c478bd9Sstevel@tonic-gate 	if (metadata) {
1677c478bd9Sstevel@tonic-gate 		error = ud_alloc_from_cache(udf_vfsp, ud_part, start_blkno);
1687c478bd9Sstevel@tonic-gate 		if (error == 0) {
1697c478bd9Sstevel@tonic-gate 			*size = 1;
1707c478bd9Sstevel@tonic-gate 			return (0);
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 	if (ud_part->udp_nfree != 0) {
1747c478bd9Sstevel@tonic-gate 		if (ud_part->udp_flags == UDP_BITMAPS) {
1757c478bd9Sstevel@tonic-gate 			error = ud_alloc_space_bmap(vfsp, ud_part, proximity,
176*ad9a7bd3SRichard Lowe 			    blkcount, start_blkno, size, less_is_ok);
1777c478bd9Sstevel@tonic-gate 		} else {
1787c478bd9Sstevel@tonic-gate 			error = ud_alloc_space_stbl(vfsp, ud_part, proximity,
179*ad9a7bd3SRichard Lowe 			    blkcount, start_blkno, size, less_is_ok);
1807c478bd9Sstevel@tonic-gate 		}
1817c478bd9Sstevel@tonic-gate 		if (error == 0) {
1827c478bd9Sstevel@tonic-gate 			mutex_enter(&udf_vfsp->udf_lock);
1837c478bd9Sstevel@tonic-gate 			ASSERT(ud_part->udp_nfree >= *size);
1847c478bd9Sstevel@tonic-gate 			ASSERT(udf_vfsp->udf_freeblks >= *size);
1857c478bd9Sstevel@tonic-gate 			ud_part->udp_nfree -= *size;
1867c478bd9Sstevel@tonic-gate 			udf_vfsp->udf_freeblks -= *size;
1877c478bd9Sstevel@tonic-gate 			mutex_exit(&udf_vfsp->udf_lock);
1887c478bd9Sstevel@tonic-gate 		}
1897c478bd9Sstevel@tonic-gate 	} else {
1907c478bd9Sstevel@tonic-gate 		error = ENOSPC;
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * prom_printf("end %x %x %x\n", error, *start_blkno, *size);
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	return (error);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate #ifdef	SKIP_USED_BLOCKS
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate  * This table is manually constructed
2027c478bd9Sstevel@tonic-gate  */
2037c478bd9Sstevel@tonic-gate int8_t skip[256] = {
2047c478bd9Sstevel@tonic-gate 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2057c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2067c478bd9Sstevel@tonic-gate 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2077c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2087c478bd9Sstevel@tonic-gate 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2097c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2107c478bd9Sstevel@tonic-gate 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2117c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2127c478bd9Sstevel@tonic-gate 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2137c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2147c478bd9Sstevel@tonic-gate 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2157c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2167c478bd9Sstevel@tonic-gate 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2177c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2187c478bd9Sstevel@tonic-gate 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
2197c478bd9Sstevel@tonic-gate 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
2207c478bd9Sstevel@tonic-gate };
2217c478bd9Sstevel@tonic-gate #endif
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate #define	HDR_BLKS	(24 * 8)
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate int32_t
ud_alloc_space_bmap(struct vfs * vfsp,struct ud_part * ud_part,uint32_t proximity,uint32_t blkcount,uint32_t * start_blkno,uint32_t * size,int32_t less_is_ok)2267c478bd9Sstevel@tonic-gate ud_alloc_space_bmap(struct vfs *vfsp,
2277c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part, uint32_t proximity,
2287c478bd9Sstevel@tonic-gate 	uint32_t blkcount, uint32_t *start_blkno,
2297c478bd9Sstevel@tonic-gate 	uint32_t *size, int32_t less_is_ok)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	struct buf *bp = NULL;
2327c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
2337c478bd9Sstevel@tonic-gate 	uint32_t old_loc, old_size, new_size;
2347c478bd9Sstevel@tonic-gate 	uint8_t *addr, *eaddr;
2357c478bd9Sstevel@tonic-gate 	uint32_t loop_count, loop_begin, loop_end;
2367c478bd9Sstevel@tonic-gate 	uint32_t bno, begin, dummy, temp, lbsz, bb_count;
2377c478bd9Sstevel@tonic-gate 	uint32_t bblk = 0, eblk = 0;
2387c478bd9Sstevel@tonic-gate 	int32_t fragmented;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	ud_printf("ud_alloc_space_bmap\n");
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	ASSERT(ud_part);
2437c478bd9Sstevel@tonic-gate 	ASSERT(ud_part->udp_flags == UDP_BITMAPS);
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (ud_part->udp_unall_len == 0) {
2467c478bd9Sstevel@tonic-gate 		return (ENOSPC);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
2497c478bd9Sstevel@tonic-gate 	lbsz = udf_vfsp->udf_lbsize;
2507c478bd9Sstevel@tonic-gate 	bb_count = udf_vfsp->udf_lbsize << 3;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	if (proximity != 0) {
2537c478bd9Sstevel@tonic-gate 		/*
2547c478bd9Sstevel@tonic-gate 		 * directly try allocating
2557c478bd9Sstevel@tonic-gate 		 * at proximity
2567c478bd9Sstevel@tonic-gate 		 */
2577c478bd9Sstevel@tonic-gate 		temp = blkcount;
2587c478bd9Sstevel@tonic-gate 		if (ud_check_free_and_mark_used(vfsp,
259*ad9a7bd3SRichard Lowe 		    ud_part, proximity, &temp) == 0) {
2607c478bd9Sstevel@tonic-gate 			if (temp != 0) {
2617c478bd9Sstevel@tonic-gate 				*start_blkno = proximity;
2627c478bd9Sstevel@tonic-gate 				*size = temp;
2637c478bd9Sstevel@tonic-gate 				return (0);
2647c478bd9Sstevel@tonic-gate 			}
2657c478bd9Sstevel@tonic-gate 		}
2667c478bd9Sstevel@tonic-gate 		*start_blkno = 0;
2677c478bd9Sstevel@tonic-gate 		*size = 0;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
2717c478bd9Sstevel@tonic-gate 	fragmented = udf_vfsp->udf_fragmented;
2727c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
2737c478bd9Sstevel@tonic-gate retry:
2747c478bd9Sstevel@tonic-gate 	old_loc = old_size = 0;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
2777c478bd9Sstevel@tonic-gate 	loop_begin = (ud_part->udp_last_alloc + CLSTR_MASK) & ~CLSTR_MASK;
2787c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	loop_end = ud_part->udp_nblocks + HDR_BLKS;
2817c478bd9Sstevel@tonic-gate 	loop_count = (loop_begin) ? 2 : 1;
2827c478bd9Sstevel@tonic-gate 	while (loop_count--) {
2837c478bd9Sstevel@tonic-gate 		for (bno = loop_begin + HDR_BLKS; bno + blkcount < loop_end; ) {
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			/*
2877c478bd9Sstevel@tonic-gate 			 * Each bread is restricted to lbsize
2887c478bd9Sstevel@tonic-gate 			 * due to the way bread is implemented
2897c478bd9Sstevel@tonic-gate 			 */
2907c478bd9Sstevel@tonic-gate 			if ((bp == NULL) ||
291*ad9a7bd3SRichard Lowe 			    ((eblk - bno) < blkcount)) {
2927c478bd9Sstevel@tonic-gate 				if (bp != NULL) {
2937c478bd9Sstevel@tonic-gate 					brelse(bp);
2947c478bd9Sstevel@tonic-gate 				}
2957c478bd9Sstevel@tonic-gate 				begin = ud_part->udp_unall_loc +
296*ad9a7bd3SRichard Lowe 				    bno / bb_count;
2977c478bd9Sstevel@tonic-gate 				bp = ud_bread(vfsp->vfs_dev,
298*ad9a7bd3SRichard Lowe 				    ud_xlate_to_daddr(udf_vfsp,
299*ad9a7bd3SRichard Lowe 				    ud_part->udp_number,
300*ad9a7bd3SRichard Lowe 				    begin, 1, &dummy) <<
301*ad9a7bd3SRichard Lowe 				    udf_vfsp->udf_l2d_shift, lbsz);
3027c478bd9Sstevel@tonic-gate 				if (bp->b_flags & B_ERROR) {
3037c478bd9Sstevel@tonic-gate 					brelse(bp);
3047c478bd9Sstevel@tonic-gate 					return (EIO);
3057c478bd9Sstevel@tonic-gate 				}
3067c478bd9Sstevel@tonic-gate 				bblk = begin * bb_count;
3077c478bd9Sstevel@tonic-gate 				eblk = bblk + bb_count;
3087c478bd9Sstevel@tonic-gate 				addr = (uint8_t *)bp->b_un.b_addr;
3097c478bd9Sstevel@tonic-gate 				eaddr = addr + bp->b_bcount;
3107c478bd9Sstevel@tonic-gate 			}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 			if (blkcount > (eblk - bno)) {
3137c478bd9Sstevel@tonic-gate 				temp = eblk - bno;
3147c478bd9Sstevel@tonic-gate 			} else {
3157c478bd9Sstevel@tonic-gate 				temp = blkcount;
3167c478bd9Sstevel@tonic-gate 			}
3177c478bd9Sstevel@tonic-gate 			if ((new_size = ud_check_free(addr, eaddr,
318*ad9a7bd3SRichard Lowe 			    bno - bblk, temp)) == temp) {
3197c478bd9Sstevel@tonic-gate 				ud_mark_used(addr, bno - bblk, temp);
3207c478bd9Sstevel@tonic-gate 				bdwrite(bp);
3217c478bd9Sstevel@tonic-gate 				*start_blkno = bno - HDR_BLKS;
3227c478bd9Sstevel@tonic-gate 				*size = temp;
3237c478bd9Sstevel@tonic-gate 				mutex_enter(&udf_vfsp->udf_lock);
3247c478bd9Sstevel@tonic-gate 				ud_part->udp_last_alloc =
325*ad9a7bd3SRichard Lowe 				    bno + temp - HDR_BLKS;
3267c478bd9Sstevel@tonic-gate 				mutex_exit(&udf_vfsp->udf_lock);
3277c478bd9Sstevel@tonic-gate 				return (0);
3287c478bd9Sstevel@tonic-gate 			}
3297c478bd9Sstevel@tonic-gate 			if (less_is_ok) {
3307c478bd9Sstevel@tonic-gate 				if (old_size < new_size) {
3317c478bd9Sstevel@tonic-gate 					old_loc = bno - HDR_BLKS;
3327c478bd9Sstevel@tonic-gate 					old_size = new_size;
3337c478bd9Sstevel@tonic-gate 				}
3347c478bd9Sstevel@tonic-gate 			}
3357c478bd9Sstevel@tonic-gate 			if (new_size != 0) {
3367c478bd9Sstevel@tonic-gate 				bno += new_size;
3377c478bd9Sstevel@tonic-gate 			} else {
3387c478bd9Sstevel@tonic-gate #ifdef	SKIP_USED_BLOCKS
3397c478bd9Sstevel@tonic-gate 				/*
3407c478bd9Sstevel@tonic-gate 				 * Skipping 0's
3417c478bd9Sstevel@tonic-gate 				 * implement a allocated block skip
3427c478bd9Sstevel@tonic-gate 				 * using a while loop with an
3437c478bd9Sstevel@tonic-gate 				 * preinitialised array of 256 elements
3447c478bd9Sstevel@tonic-gate 				 * for number of blocks skipped
3457c478bd9Sstevel@tonic-gate 				 */
3467c478bd9Sstevel@tonic-gate 				bno &= ~3;
3477c478bd9Sstevel@tonic-gate 				while (skip[addr[(bno - bblk) >> 3]] == 8)
3487c478bd9Sstevel@tonic-gate 					bno += 8;
3497c478bd9Sstevel@tonic-gate 				bno += skip[addr[(bno - bblk) >> 3]];
3507c478bd9Sstevel@tonic-gate #else
3517c478bd9Sstevel@tonic-gate 				bno++;
3527c478bd9Sstevel@tonic-gate #endif
3537c478bd9Sstevel@tonic-gate 			}
3547c478bd9Sstevel@tonic-gate 			if (!fragmented) {
3557c478bd9Sstevel@tonic-gate 				bno = (bno + CLSTR_MASK) & ~CLSTR_MASK;
3567c478bd9Sstevel@tonic-gate 			}
3577c478bd9Sstevel@tonic-gate 		}
3587c478bd9Sstevel@tonic-gate 		if (bp != NULL) {
3597c478bd9Sstevel@tonic-gate 			brelse(bp);
3607c478bd9Sstevel@tonic-gate 			bp = NULL;
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 		if (loop_count) {
3637c478bd9Sstevel@tonic-gate 			loop_end = loop_begin + HDR_BLKS;
3647c478bd9Sstevel@tonic-gate 			loop_begin = 0;
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 	if ((old_size == 0) && (!fragmented)) {
3687c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_vfsp->udf_lock);
3697c478bd9Sstevel@tonic-gate 		fragmented = udf_vfsp->udf_fragmented = 1;
3707c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_vfsp->udf_lock);
3717c478bd9Sstevel@tonic-gate 		goto retry;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	if (less_is_ok && (old_size != 0)) {
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 		/*
3767c478bd9Sstevel@tonic-gate 		 * Check once again
3777c478bd9Sstevel@tonic-gate 		 * somebody else might have
3787c478bd9Sstevel@tonic-gate 		 * already allocated behind us
3797c478bd9Sstevel@tonic-gate 		 */
3807c478bd9Sstevel@tonic-gate 		if (ud_check_free_and_mark_used(vfsp,
381*ad9a7bd3SRichard Lowe 		    ud_part, old_loc, &old_size) == 0) {
3827c478bd9Sstevel@tonic-gate 			if (old_size != 0) {
3837c478bd9Sstevel@tonic-gate 				*start_blkno = old_loc;
3847c478bd9Sstevel@tonic-gate 				*size = old_size;
3857c478bd9Sstevel@tonic-gate 				mutex_enter(&udf_vfsp->udf_lock);
3867c478bd9Sstevel@tonic-gate 				ud_part->udp_last_alloc = old_loc + old_size;
3877c478bd9Sstevel@tonic-gate 				mutex_exit(&udf_vfsp->udf_lock);
3887c478bd9Sstevel@tonic-gate 				return (0);
3897c478bd9Sstevel@tonic-gate 			}
3907c478bd9Sstevel@tonic-gate 		}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 		/*
3937c478bd9Sstevel@tonic-gate 		 * Failed what ever the reason
3947c478bd9Sstevel@tonic-gate 		 */
3957c478bd9Sstevel@tonic-gate 		goto retry;
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 	return (ENOSPC);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate  * start is the block from the begining
4027c478bd9Sstevel@tonic-gate  * of the partition ud_part
4037c478bd9Sstevel@tonic-gate  */
4047c478bd9Sstevel@tonic-gate int32_t
ud_check_free_and_mark_used(struct vfs * vfsp,struct ud_part * ud_part,uint32_t start,uint32_t * count)4057c478bd9Sstevel@tonic-gate ud_check_free_and_mark_used(struct vfs *vfsp,
4067c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part, uint32_t start, uint32_t *count)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 	struct buf *bp;
4097c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
4107c478bd9Sstevel@tonic-gate 	uint32_t begin, dummy, bb_count;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	/*
4137c478bd9Sstevel@tonic-gate 	 * Adjust start for the header
4147c478bd9Sstevel@tonic-gate 	 */
4157c478bd9Sstevel@tonic-gate 	start += HDR_BLKS;
4167c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
4177c478bd9Sstevel@tonic-gate 	bb_count = udf_vfsp->udf_lbsize << 3;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	/*
4207c478bd9Sstevel@tonic-gate 	 * Read just on block worth of bitmap
4217c478bd9Sstevel@tonic-gate 	 */
4227c478bd9Sstevel@tonic-gate 	begin = ud_part->udp_unall_loc + (start / bb_count);
4237c478bd9Sstevel@tonic-gate 	bp = ud_bread(vfsp->vfs_dev,
424*ad9a7bd3SRichard Lowe 	    ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number,
425*ad9a7bd3SRichard Lowe 	    begin, 1, &dummy) << udf_vfsp->udf_l2d_shift,
426*ad9a7bd3SRichard Lowe 	    udf_vfsp->udf_lbsize);
4277c478bd9Sstevel@tonic-gate 	if (bp->b_flags & B_ERROR) {
4287c478bd9Sstevel@tonic-gate 		brelse(bp);
4297c478bd9Sstevel@tonic-gate 		return (EIO);
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/*
4337c478bd9Sstevel@tonic-gate 	 * Adjust the count if necessary
4347c478bd9Sstevel@tonic-gate 	 */
4357c478bd9Sstevel@tonic-gate 	start -= begin * bb_count;
4367c478bd9Sstevel@tonic-gate 	if ((start + *count) > bb_count) {
4377c478bd9Sstevel@tonic-gate 		*count = bb_count - start;
4387c478bd9Sstevel@tonic-gate 		ASSERT(*count > 0);
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 	if (ud_check_free((uint8_t *)bp->b_un.b_addr,
441*ad9a7bd3SRichard Lowe 	    (uint8_t *)bp->b_un.b_addr + bp->b_bcount, start,
442*ad9a7bd3SRichard Lowe 	    *count) != *count) {
4437c478bd9Sstevel@tonic-gate 		brelse(bp);
4447c478bd9Sstevel@tonic-gate 		return (1);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 	ud_mark_used((uint8_t *)bp->b_un.b_addr, start, *count);
4477c478bd9Sstevel@tonic-gate 	bdwrite(bp);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	return (0);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate int32_t
ud_check_free(uint8_t * addr,uint8_t * eaddr,uint32_t start,uint32_t count)4537c478bd9Sstevel@tonic-gate ud_check_free(uint8_t *addr, uint8_t *eaddr, uint32_t start, uint32_t count)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	int32_t i = 0;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
4587c478bd9Sstevel@tonic-gate 		if (&addr[start >> 3] >= eaddr) {
4597c478bd9Sstevel@tonic-gate 			break;
4607c478bd9Sstevel@tonic-gate 		}
4617c478bd9Sstevel@tonic-gate 		if ((addr[start >> 3] & (1 << (start & 0x7))) == 0) {
4627c478bd9Sstevel@tonic-gate 			break;
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 		start ++;
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate 	return (i);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate void
ud_mark_used(uint8_t * addr,uint32_t start,uint32_t count)4707c478bd9Sstevel@tonic-gate ud_mark_used(uint8_t *addr, uint32_t start, uint32_t count)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	int32_t i = 0;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
4757c478bd9Sstevel@tonic-gate 		addr[start >> 3] &= ~(1 << (start & 0x7));
4767c478bd9Sstevel@tonic-gate 		start++;
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate void
ud_mark_free(uint8_t * addr,uint32_t start,uint32_t count)4817c478bd9Sstevel@tonic-gate ud_mark_free(uint8_t *addr, uint32_t start, uint32_t count)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	int32_t i = 0;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
4867c478bd9Sstevel@tonic-gate 		addr[start >> 3] |= (1 << (start & 0x7));
4877c478bd9Sstevel@tonic-gate 		start++;
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate /* ARGSUSED */
4927c478bd9Sstevel@tonic-gate int32_t
ud_alloc_space_stbl(struct vfs * vfsp,struct ud_part * ud_part,uint32_t proximity,uint32_t blkcount,uint32_t * start_blkno,uint32_t * size,int32_t less_is_ok)4937c478bd9Sstevel@tonic-gate ud_alloc_space_stbl(struct vfs *vfsp,
4947c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part, uint32_t proximity,
4957c478bd9Sstevel@tonic-gate 	uint32_t blkcount, uint32_t *start_blkno,
4967c478bd9Sstevel@tonic-gate 	uint32_t *size, int32_t less_is_ok)
4977c478bd9Sstevel@tonic-gate {
4987c478bd9Sstevel@tonic-gate 	uint16_t adesc;
4997c478bd9Sstevel@tonic-gate 	uint32_t temp, sz;
5007c478bd9Sstevel@tonic-gate 	int32_t error, index, count, larg_index, larg_sz;
5017c478bd9Sstevel@tonic-gate 	struct buf *bp;
5027c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
5037c478bd9Sstevel@tonic-gate 	struct unall_space_ent *use;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	ASSERT(ud_part);
5067c478bd9Sstevel@tonic-gate 	ASSERT(ud_part->udp_flags == UDP_SPACETBLS);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	ud_printf("ud_alloc_space_stbl\n");
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	if (ud_part->udp_unall_len == 0) {
5117c478bd9Sstevel@tonic-gate 		return (ENOSPC);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
5157c478bd9Sstevel@tonic-gate 	ASSERT((ud_part->udp_unall_len + 40) <= udf_vfsp->udf_lbsize);
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	bp = ud_bread(vfsp->vfs_dev,
518*ad9a7bd3SRichard Lowe 	    ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number,
519*ad9a7bd3SRichard Lowe 	    ud_part->udp_unall_loc, 1, &temp), udf_vfsp->udf_lbsize);
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	use = (struct unall_space_ent *)bp->b_un.b_addr;
5227c478bd9Sstevel@tonic-gate 	sz = SWAP_32(use->use_len_ad);
5237c478bd9Sstevel@tonic-gate 	adesc = SWAP_16(use->use_icb_tag.itag_flags) & 0x7;
5247c478bd9Sstevel@tonic-gate 	if (adesc == ICB_FLAG_SHORT_AD) {
5257c478bd9Sstevel@tonic-gate 		struct short_ad *sad;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 		sad = (struct short_ad *)use->use_ad;
5287c478bd9Sstevel@tonic-gate 		count = sz / sizeof (struct short_ad);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		/*
5317c478bd9Sstevel@tonic-gate 		 * Search the entire list for
5327c478bd9Sstevel@tonic-gate 		 * a extent which can give the entire data
5337c478bd9Sstevel@tonic-gate 		 * Do only first fit
5347c478bd9Sstevel@tonic-gate 		 */
5357c478bd9Sstevel@tonic-gate 		larg_index = larg_sz = 0;
5367c478bd9Sstevel@tonic-gate 		for (index = 0; index < count; index++, sad++) {
5377c478bd9Sstevel@tonic-gate 			temp = SWAP_32(sad->sad_ext_len) >>
538*ad9a7bd3SRichard Lowe 			    udf_vfsp->udf_l2b_shift;
5397c478bd9Sstevel@tonic-gate 			if (temp == blkcount) {
5407c478bd9Sstevel@tonic-gate 				/*
5417c478bd9Sstevel@tonic-gate 				 * We found the right fit
5427c478bd9Sstevel@tonic-gate 				 * return the values and
5437c478bd9Sstevel@tonic-gate 				 * compress the table
5447c478bd9Sstevel@tonic-gate 				 */
5457c478bd9Sstevel@tonic-gate 				less_is_ok = 1;
5467c478bd9Sstevel@tonic-gate 				larg_index = index;
5477c478bd9Sstevel@tonic-gate 				larg_sz = temp;
5487c478bd9Sstevel@tonic-gate 				goto compress_sad;
5497c478bd9Sstevel@tonic-gate 			} else if (temp > blkcount) {
5507c478bd9Sstevel@tonic-gate 				/*
5517c478bd9Sstevel@tonic-gate 				 * We found an entry larger than the
5527c478bd9Sstevel@tonic-gate 				 * requirement. Change the start block
5537c478bd9Sstevel@tonic-gate 				 * number and the count to reflect the
5547c478bd9Sstevel@tonic-gate 				 * allocation
5557c478bd9Sstevel@tonic-gate 				 */
5567c478bd9Sstevel@tonic-gate 				*start_blkno = SWAP_32(sad->sad_ext_loc);
5577c478bd9Sstevel@tonic-gate 				*size = blkcount;
5587c478bd9Sstevel@tonic-gate 				temp = (temp - blkcount) <<
559*ad9a7bd3SRichard Lowe 				    udf_vfsp->udf_l2b_shift;
5607c478bd9Sstevel@tonic-gate 				sad->sad_ext_len = SWAP_32(temp);
5617c478bd9Sstevel@tonic-gate 				temp = SWAP_32(sad->sad_ext_loc) + blkcount;
5627c478bd9Sstevel@tonic-gate 				sad->sad_ext_loc = SWAP_32(temp);
5637c478bd9Sstevel@tonic-gate 				goto end;
5647c478bd9Sstevel@tonic-gate 			}
5657c478bd9Sstevel@tonic-gate 			/*
5667c478bd9Sstevel@tonic-gate 			 * Let us keep track of the largest
5677c478bd9Sstevel@tonic-gate 			 * extent available if less_is_ok.
5687c478bd9Sstevel@tonic-gate 			 */
5697c478bd9Sstevel@tonic-gate 			if (less_is_ok) {
5707c478bd9Sstevel@tonic-gate 				if (temp > larg_sz) {
5717c478bd9Sstevel@tonic-gate 					larg_sz = temp;
5727c478bd9Sstevel@tonic-gate 					larg_index = index;
5737c478bd9Sstevel@tonic-gate 				}
5747c478bd9Sstevel@tonic-gate 			}
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate compress_sad:
577*ad9a7bd3SRichard Lowe 		if ((less_is_ok) && (larg_sz != 0)) {
5787c478bd9Sstevel@tonic-gate 			/*
5797c478bd9Sstevel@tonic-gate 			 * If we came here we could
5807c478bd9Sstevel@tonic-gate 			 * not find a extent to cover the entire size
5817c478bd9Sstevel@tonic-gate 			 * return whatever could be allocated
5827c478bd9Sstevel@tonic-gate 			 * and compress the table
5837c478bd9Sstevel@tonic-gate 			 */
5847c478bd9Sstevel@tonic-gate 			sad = (struct short_ad *)use->use_ad;
5857c478bd9Sstevel@tonic-gate 			sad += larg_index;
5867c478bd9Sstevel@tonic-gate 			*start_blkno = SWAP_32(sad->sad_ext_loc);
5877c478bd9Sstevel@tonic-gate 			*size = larg_sz;
5887c478bd9Sstevel@tonic-gate 			for (index = larg_index; index < count;
589*ad9a7bd3SRichard Lowe 			    index++, sad++) {
5907c478bd9Sstevel@tonic-gate 				*sad = *(sad+1);
5917c478bd9Sstevel@tonic-gate 			}
5927c478bd9Sstevel@tonic-gate 			sz -= sizeof (struct short_ad);
5937c478bd9Sstevel@tonic-gate 			use->use_len_ad = SWAP_32(sz);
5947c478bd9Sstevel@tonic-gate 		} else {
5957c478bd9Sstevel@tonic-gate 			error = ENOSPC;
5967c478bd9Sstevel@tonic-gate 		}
5977c478bd9Sstevel@tonic-gate 		goto end;
5987c478bd9Sstevel@tonic-gate 	} else if (adesc == ICB_FLAG_LONG_AD) {
5997c478bd9Sstevel@tonic-gate 		struct long_ad *lad;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 		lad = (struct long_ad *)use->use_ad;
6027c478bd9Sstevel@tonic-gate 		count = sz / sizeof (struct long_ad);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		/*
6057c478bd9Sstevel@tonic-gate 		 * Search the entire list for
6067c478bd9Sstevel@tonic-gate 		 * a extent which can give the entire data
6077c478bd9Sstevel@tonic-gate 		 * Do only first fit
6087c478bd9Sstevel@tonic-gate 		 */
6097c478bd9Sstevel@tonic-gate 		larg_index = larg_sz = 0;
6107c478bd9Sstevel@tonic-gate 		for (index = 0; index < count; index++, lad++) {
6117c478bd9Sstevel@tonic-gate 			temp = SWAP_32(lad->lad_ext_len) >>
612*ad9a7bd3SRichard Lowe 			    udf_vfsp->udf_l2b_shift;
6137c478bd9Sstevel@tonic-gate 			if (temp == blkcount) {
6147c478bd9Sstevel@tonic-gate 				/*
6157c478bd9Sstevel@tonic-gate 				 * We found the right fit
6167c478bd9Sstevel@tonic-gate 				 * return the values and
6177c478bd9Sstevel@tonic-gate 				 * compress the table
6187c478bd9Sstevel@tonic-gate 				 */
6197c478bd9Sstevel@tonic-gate 				less_is_ok = 1;
6207c478bd9Sstevel@tonic-gate 				larg_index = index;
6217c478bd9Sstevel@tonic-gate 				larg_sz = temp;
6227c478bd9Sstevel@tonic-gate 				goto compress_lad;
6237c478bd9Sstevel@tonic-gate 			} else if (temp > blkcount) {
6247c478bd9Sstevel@tonic-gate 				/*
6257c478bd9Sstevel@tonic-gate 				 * We found an entry larger than the
6267c478bd9Sstevel@tonic-gate 				 * requirement. Change the start block
6277c478bd9Sstevel@tonic-gate 				 * number and the count to reflect the
6287c478bd9Sstevel@tonic-gate 				 * allocation
6297c478bd9Sstevel@tonic-gate 				 */
6307c478bd9Sstevel@tonic-gate 				*start_blkno = SWAP_32(lad->lad_ext_loc);
6317c478bd9Sstevel@tonic-gate 				*size = blkcount;
6327c478bd9Sstevel@tonic-gate 				temp = (temp - blkcount) <<
633*ad9a7bd3SRichard Lowe 				    udf_vfsp->udf_l2b_shift;
6347c478bd9Sstevel@tonic-gate 				lad->lad_ext_len = SWAP_32(temp);
6357c478bd9Sstevel@tonic-gate 				temp = SWAP_32(lad->lad_ext_loc) + blkcount;
6367c478bd9Sstevel@tonic-gate 				lad->lad_ext_loc = SWAP_32(temp);
6377c478bd9Sstevel@tonic-gate 				goto end;
6387c478bd9Sstevel@tonic-gate 			}
6397c478bd9Sstevel@tonic-gate 			/*
6407c478bd9Sstevel@tonic-gate 			 * Let us keep track of the largest
6417c478bd9Sstevel@tonic-gate 			 * extent available if less_is_ok.
6427c478bd9Sstevel@tonic-gate 			 */
6437c478bd9Sstevel@tonic-gate 			if (less_is_ok) {
6447c478bd9Sstevel@tonic-gate 				if (temp > larg_sz) {
6457c478bd9Sstevel@tonic-gate 					larg_sz = temp;
6467c478bd9Sstevel@tonic-gate 					larg_index = index;
6477c478bd9Sstevel@tonic-gate 				}
6487c478bd9Sstevel@tonic-gate 			}
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate compress_lad:
651*ad9a7bd3SRichard Lowe 		if ((less_is_ok) && (larg_sz != 0)) {
6527c478bd9Sstevel@tonic-gate 			/*
6537c478bd9Sstevel@tonic-gate 			 * If we came here we could
6547c478bd9Sstevel@tonic-gate 			 * not find a extent to cover the entire size
6557c478bd9Sstevel@tonic-gate 			 * return whatever could be allocated
6567c478bd9Sstevel@tonic-gate 			 * and compress the table
6577c478bd9Sstevel@tonic-gate 			 */
6587c478bd9Sstevel@tonic-gate 			lad = (struct long_ad *)use->use_ad;
6597c478bd9Sstevel@tonic-gate 			lad += larg_index;
6607c478bd9Sstevel@tonic-gate 			*start_blkno = SWAP_32(lad->lad_ext_loc);
6617c478bd9Sstevel@tonic-gate 			*size = larg_sz;
6627c478bd9Sstevel@tonic-gate 			for (index = larg_index; index < count;
663*ad9a7bd3SRichard Lowe 			    index++, lad++) {
6647c478bd9Sstevel@tonic-gate 				*lad = *(lad+1);
6657c478bd9Sstevel@tonic-gate 			}
6667c478bd9Sstevel@tonic-gate 			sz -= sizeof (struct long_ad);
6677c478bd9Sstevel@tonic-gate 			use->use_len_ad = SWAP_32(sz);
6687c478bd9Sstevel@tonic-gate 		} else {
6697c478bd9Sstevel@tonic-gate 			error = ENOSPC;
6707c478bd9Sstevel@tonic-gate 		}
6717c478bd9Sstevel@tonic-gate 		goto end;
6727c478bd9Sstevel@tonic-gate 	} else {
6737c478bd9Sstevel@tonic-gate 		error = ENOSPC;
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate end:
6767c478bd9Sstevel@tonic-gate 	if (!error) {
6777c478bd9Sstevel@tonic-gate 		bdwrite(bp);
6787c478bd9Sstevel@tonic-gate 	} else {
6797c478bd9Sstevel@tonic-gate 		brelse(bp);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 	return (error);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate  * release blkcount blocks starting from beginblk
6877c478bd9Sstevel@tonic-gate  * Call appropriate bmap/space table fucntions
6887c478bd9Sstevel@tonic-gate  */
6897c478bd9Sstevel@tonic-gate void
ud_free_space(struct vfs * vfsp,uint16_t prn,uint32_t beginblk,uint32_t blkcount)6907c478bd9Sstevel@tonic-gate ud_free_space(struct vfs *vfsp, uint16_t prn,
6917c478bd9Sstevel@tonic-gate 	uint32_t beginblk, uint32_t blkcount)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	int32_t i, error;
6947c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part;
6957c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	ud_printf("ud_free_space\n");
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if (blkcount == 0) {
7007c478bd9Sstevel@tonic-gate 		return;
7017c478bd9Sstevel@tonic-gate 	}
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
7047c478bd9Sstevel@tonic-gate 	ud_part = udf_vfsp->udf_parts;
7057c478bd9Sstevel@tonic-gate 	for (i = 0; i < udf_vfsp->udf_npart; i++) {
7067c478bd9Sstevel@tonic-gate 		if (prn == ud_part->udp_number) {
7077c478bd9Sstevel@tonic-gate 			break;
7087c478bd9Sstevel@tonic-gate 		}
7097c478bd9Sstevel@tonic-gate 		ud_part ++;
7107c478bd9Sstevel@tonic-gate 	}
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	if (i == udf_vfsp->udf_npart) {
7137c478bd9Sstevel@tonic-gate 		return;
7147c478bd9Sstevel@tonic-gate 	}
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	if (ud_part->udp_flags == UDP_BITMAPS) {
7177c478bd9Sstevel@tonic-gate 		error = ud_free_space_bmap(vfsp, ud_part, beginblk, blkcount);
7187c478bd9Sstevel@tonic-gate 	} else {
7197c478bd9Sstevel@tonic-gate 		error = ud_free_space_stbl(vfsp, ud_part, beginblk, blkcount);
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	if (error) {
7237c478bd9Sstevel@tonic-gate 		udf_vfsp->udf_mark_bad = 1;
7247c478bd9Sstevel@tonic-gate 	}
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /*
7287c478bd9Sstevel@tonic-gate  * If there is a freed table then
7297c478bd9Sstevel@tonic-gate  * release blocks to the freed table
7307c478bd9Sstevel@tonic-gate  * other wise release to the un allocated table.
7317c478bd9Sstevel@tonic-gate  * Findout the offset into the bitmap and
7327c478bd9Sstevel@tonic-gate  * mark the blocks as free blocks
7337c478bd9Sstevel@tonic-gate  */
7347c478bd9Sstevel@tonic-gate int32_t
ud_free_space_bmap(struct vfs * vfsp,struct ud_part * ud_part,uint32_t beginblk,uint32_t blkcount)7357c478bd9Sstevel@tonic-gate ud_free_space_bmap(struct vfs *vfsp,
7367c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part,
7377c478bd9Sstevel@tonic-gate 	uint32_t beginblk, uint32_t blkcount)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	struct buf *bp;
7407c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
7417c478bd9Sstevel@tonic-gate 	uint32_t block, begin, end, blkno, count, map_end_blk, dummy;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	ud_printf("ud_free_space_bmap\n");
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	ASSERT(ud_part);
7467c478bd9Sstevel@tonic-gate 	ASSERT(ud_part->udp_flags == UDP_BITMAPS);
7477c478bd9Sstevel@tonic-gate /*
7487c478bd9Sstevel@tonic-gate  * prom_printf("%x %x\n", udblock, udcount);
7497c478bd9Sstevel@tonic-gate  */
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
7527c478bd9Sstevel@tonic-gate 	if ((ud_part->udp_freed_len == 0) &&
753*ad9a7bd3SRichard Lowe 	    (ud_part->udp_unall_len == 0)) {
7547c478bd9Sstevel@tonic-gate 		return (ENOSPC);
7557c478bd9Sstevel@tonic-gate 	}
7567c478bd9Sstevel@tonic-gate 	/*
7577c478bd9Sstevel@tonic-gate 	 * decide unallocated/freed table to use
7587c478bd9Sstevel@tonic-gate 	 */
7597c478bd9Sstevel@tonic-gate 	if (ud_part->udp_freed_len == 0) {
7607c478bd9Sstevel@tonic-gate 		begin = ud_part->udp_unall_loc;
7617c478bd9Sstevel@tonic-gate 		map_end_blk = ud_part->udp_unall_len << 3;
7627c478bd9Sstevel@tonic-gate 	} else {
7637c478bd9Sstevel@tonic-gate 		begin = ud_part->udp_freed_loc;
7647c478bd9Sstevel@tonic-gate 		map_end_blk = ud_part->udp_freed_len << 3;
7657c478bd9Sstevel@tonic-gate 	}
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	if (beginblk + blkcount > map_end_blk) {
7687c478bd9Sstevel@tonic-gate 		return (ENOSPC);
7697c478bd9Sstevel@tonic-gate 	}
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	/* adjust for the bitmap header */
7727c478bd9Sstevel@tonic-gate 	beginblk += HDR_BLKS;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	end = begin + ((beginblk + blkcount) / (udf_vfsp->udf_lbsize << 3));
7757c478bd9Sstevel@tonic-gate 	begin += (beginblk / (udf_vfsp->udf_lbsize << 3));
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	for (block = begin; block <= end; block++) {
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		bp = ud_bread(vfsp->vfs_dev,
780*ad9a7bd3SRichard Lowe 		    ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number, block, 1,
781*ad9a7bd3SRichard Lowe 		    &dummy) << udf_vfsp->udf_l2d_shift, udf_vfsp->udf_lbsize);
7827c478bd9Sstevel@tonic-gate 		if (bp->b_flags & B_ERROR) {
7837c478bd9Sstevel@tonic-gate 			brelse(bp);
7847c478bd9Sstevel@tonic-gate 			return (EIO);
7857c478bd9Sstevel@tonic-gate 		}
7867c478bd9Sstevel@tonic-gate 		ASSERT(dummy == 1);
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_vfsp->udf_lock);
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		/*
7917c478bd9Sstevel@tonic-gate 		 * add freed blocks to the bitmap
7927c478bd9Sstevel@tonic-gate 		 */
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 		blkno = beginblk - (block * (udf_vfsp->udf_lbsize << 3));
7957c478bd9Sstevel@tonic-gate 		if (blkno + blkcount > (udf_vfsp->udf_lbsize << 3)) {
7967c478bd9Sstevel@tonic-gate 			count = (udf_vfsp->udf_lbsize << 3) - blkno;
7977c478bd9Sstevel@tonic-gate 		} else {
7987c478bd9Sstevel@tonic-gate 			count = blkcount;
7997c478bd9Sstevel@tonic-gate 		}
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate /*
8027c478bd9Sstevel@tonic-gate  * if (begin != end) {
8037c478bd9Sstevel@tonic-gate  *	printf("%x %x %x %x %x %x\n",
8047c478bd9Sstevel@tonic-gate  *		begin, end, block, blkno, count);
8057c478bd9Sstevel@tonic-gate  *	printf("%x %x %x\n", bp->b_un.b_addr, blkno, count);
8067c478bd9Sstevel@tonic-gate  * }
8077c478bd9Sstevel@tonic-gate  */
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		ud_mark_free((uint8_t *)bp->b_un.b_addr, blkno, count);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 		beginblk += count;
8127c478bd9Sstevel@tonic-gate 		blkcount -= count;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		if (ud_part->udp_freed_len == 0) {
8157c478bd9Sstevel@tonic-gate 			ud_part->udp_nfree += count;
8167c478bd9Sstevel@tonic-gate 			udf_vfsp->udf_freeblks += count;
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_vfsp->udf_lock);
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		bdwrite(bp);
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	return (0);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate /* ARGSUSED */
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate  * search the entire table if there is
8307c478bd9Sstevel@tonic-gate  * a entry with which we can merge the
8317c478bd9Sstevel@tonic-gate  * current entry. Other wise create
8327c478bd9Sstevel@tonic-gate  * a new entry at the end of the table
8337c478bd9Sstevel@tonic-gate  */
8347c478bd9Sstevel@tonic-gate int32_t
ud_free_space_stbl(struct vfs * vfsp,struct ud_part * ud_part,uint32_t beginblk,uint32_t blkcount)8357c478bd9Sstevel@tonic-gate ud_free_space_stbl(struct vfs *vfsp,
8367c478bd9Sstevel@tonic-gate 	struct ud_part *ud_part,
8377c478bd9Sstevel@tonic-gate 	uint32_t beginblk, uint32_t blkcount)
8387c478bd9Sstevel@tonic-gate {
8397c478bd9Sstevel@tonic-gate 	uint16_t adesc;
8407c478bd9Sstevel@tonic-gate 	int32_t error = 0, index, count;
8417c478bd9Sstevel@tonic-gate 	uint32_t block, dummy, sz;
8427c478bd9Sstevel@tonic-gate 	struct buf *bp;
8437c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
8447c478bd9Sstevel@tonic-gate 	struct unall_space_ent *use;
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	ud_printf("ud_free_space_stbl\n");
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	ASSERT(ud_part);
8497c478bd9Sstevel@tonic-gate 	ASSERT(ud_part->udp_flags == UDP_SPACETBLS);
8507c478bd9Sstevel@tonic-gate 
851*ad9a7bd3SRichard Lowe 	if ((ud_part->udp_freed_len == 0) && (ud_part->udp_unall_len == 0)) {
8527c478bd9Sstevel@tonic-gate 		return (ENOSPC);
8537c478bd9Sstevel@tonic-gate 	}
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	if (ud_part->udp_freed_len != 0) {
8567c478bd9Sstevel@tonic-gate 		block = ud_part->udp_freed_loc;
8577c478bd9Sstevel@tonic-gate 	} else {
8587c478bd9Sstevel@tonic-gate 		block = ud_part->udp_unall_loc;
8597c478bd9Sstevel@tonic-gate 	}
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
8627c478bd9Sstevel@tonic-gate 	ASSERT((ud_part->udp_unall_len + 40) <= udf_vfsp->udf_lbsize);
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	bp = ud_bread(vfsp->vfs_dev,
865*ad9a7bd3SRichard Lowe 	    ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number, block, 1, &dummy),
866*ad9a7bd3SRichard Lowe 	    udf_vfsp->udf_lbsize);
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 	use = (struct unall_space_ent *)bp->b_un.b_addr;
8697c478bd9Sstevel@tonic-gate 	sz = SWAP_32(use->use_len_ad);
8707c478bd9Sstevel@tonic-gate 	adesc = SWAP_16(use->use_icb_tag.itag_flags) & 0x7;
8717c478bd9Sstevel@tonic-gate 	if (adesc == ICB_FLAG_SHORT_AD) {
8727c478bd9Sstevel@tonic-gate 		struct short_ad *sad;
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 		sad = (struct short_ad *)use->use_ad;
8757c478bd9Sstevel@tonic-gate 		count = sz / sizeof (struct short_ad);
8767c478bd9Sstevel@tonic-gate 		/*
8777c478bd9Sstevel@tonic-gate 		 * Check if the blocks being freed
8787c478bd9Sstevel@tonic-gate 		 * are continuous with any of the
8797c478bd9Sstevel@tonic-gate 		 * existing extents
8807c478bd9Sstevel@tonic-gate 		 */
8817c478bd9Sstevel@tonic-gate 		for (index = 0; index < count; index++, sad++) {
8827c478bd9Sstevel@tonic-gate 			if (beginblk == (SWAP_32(sad->sad_ext_loc) +
883*ad9a7bd3SRichard Lowe 			    (SWAP_32(sad->sad_ext_len) /
884*ad9a7bd3SRichard Lowe 			    udf_vfsp->udf_lbsize))) {
8857c478bd9Sstevel@tonic-gate 				dummy = SWAP_32(sad->sad_ext_len) +
886*ad9a7bd3SRichard Lowe 				    blkcount * udf_vfsp->udf_lbsize;
8877c478bd9Sstevel@tonic-gate 				sad->sad_ext_len = SWAP_32(dummy);
8887c478bd9Sstevel@tonic-gate 				goto end;
8897c478bd9Sstevel@tonic-gate 			} else if ((beginblk + blkcount) ==
890*ad9a7bd3SRichard Lowe 			    SWAP_32(sad->sad_ext_loc)) {
8917c478bd9Sstevel@tonic-gate 				sad->sad_ext_loc = SWAP_32(beginblk);
8927c478bd9Sstevel@tonic-gate 				goto end;
8937c478bd9Sstevel@tonic-gate 			}
8947c478bd9Sstevel@tonic-gate 		}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 		/*
8977c478bd9Sstevel@tonic-gate 		 * We need to add a new entry
8987c478bd9Sstevel@tonic-gate 		 * Check if we space.
8997c478bd9Sstevel@tonic-gate 		 */
9007c478bd9Sstevel@tonic-gate 		if ((40 + sz + sizeof (struct short_ad)) >
901*ad9a7bd3SRichard Lowe 		    udf_vfsp->udf_lbsize) {
9027c478bd9Sstevel@tonic-gate 			error = ENOSPC;
9037c478bd9Sstevel@tonic-gate 			goto end;
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		/*
9077c478bd9Sstevel@tonic-gate 		 * We have enough space
9087c478bd9Sstevel@tonic-gate 		 * just add the entry at the end
9097c478bd9Sstevel@tonic-gate 		 */
9107c478bd9Sstevel@tonic-gate 		dummy = SWAP_32(use->use_len_ad);
9117c478bd9Sstevel@tonic-gate 		sad = (struct short_ad *)&use->use_ad[dummy];
9127c478bd9Sstevel@tonic-gate 		sz = blkcount * udf_vfsp->udf_lbsize;
9137c478bd9Sstevel@tonic-gate 		sad->sad_ext_len = SWAP_32(sz);
9147c478bd9Sstevel@tonic-gate 		sad->sad_ext_loc = SWAP_32(beginblk);
9157c478bd9Sstevel@tonic-gate 		dummy += sizeof (struct short_ad);
9167c478bd9Sstevel@tonic-gate 		use->use_len_ad = SWAP_32(dummy);
9177c478bd9Sstevel@tonic-gate 	} else if (adesc == ICB_FLAG_LONG_AD) {
9187c478bd9Sstevel@tonic-gate 		struct long_ad *lad;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 		lad = (struct long_ad *)use->use_ad;
9217c478bd9Sstevel@tonic-gate 		count = sz / sizeof (struct long_ad);
9227c478bd9Sstevel@tonic-gate 		/*
9237c478bd9Sstevel@tonic-gate 		 * Check if the blocks being freed
9247c478bd9Sstevel@tonic-gate 		 * are continuous with any of the
9257c478bd9Sstevel@tonic-gate 		 * existing extents
9267c478bd9Sstevel@tonic-gate 		 */
9277c478bd9Sstevel@tonic-gate 		for (index = 0; index < count; index++, lad++) {
9287c478bd9Sstevel@tonic-gate 			if (beginblk == (SWAP_32(lad->lad_ext_loc) +
929*ad9a7bd3SRichard Lowe 			    (SWAP_32(lad->lad_ext_len) /
930*ad9a7bd3SRichard Lowe 			    udf_vfsp->udf_lbsize))) {
9317c478bd9Sstevel@tonic-gate 				dummy = SWAP_32(lad->lad_ext_len) +
932*ad9a7bd3SRichard Lowe 				    blkcount * udf_vfsp->udf_lbsize;
9337c478bd9Sstevel@tonic-gate 				lad->lad_ext_len = SWAP_32(dummy);
9347c478bd9Sstevel@tonic-gate 				goto end;
9357c478bd9Sstevel@tonic-gate 			} else if ((beginblk + blkcount) ==
936*ad9a7bd3SRichard Lowe 			    SWAP_32(lad->lad_ext_loc)) {
9377c478bd9Sstevel@tonic-gate 				lad->lad_ext_loc = SWAP_32(beginblk);
9387c478bd9Sstevel@tonic-gate 				goto end;
9397c478bd9Sstevel@tonic-gate 			}
9407c478bd9Sstevel@tonic-gate 		}
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 		/*
9437c478bd9Sstevel@tonic-gate 		 * We need to add a new entry
9447c478bd9Sstevel@tonic-gate 		 * Check if we space.
9457c478bd9Sstevel@tonic-gate 		 */
9467c478bd9Sstevel@tonic-gate 		if ((40 + sz + sizeof (struct long_ad)) >
947*ad9a7bd3SRichard Lowe 		    udf_vfsp->udf_lbsize) {
9487c478bd9Sstevel@tonic-gate 			error = ENOSPC;
9497c478bd9Sstevel@tonic-gate 			goto end;
9507c478bd9Sstevel@tonic-gate 		}
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 		/*
9537c478bd9Sstevel@tonic-gate 		 * We have enough space
9547c478bd9Sstevel@tonic-gate 		 * just add the entry at the end
9557c478bd9Sstevel@tonic-gate 		 */
9567c478bd9Sstevel@tonic-gate 		dummy = SWAP_32(use->use_len_ad);
9577c478bd9Sstevel@tonic-gate 		lad = (struct long_ad *)&use->use_ad[dummy];
9587c478bd9Sstevel@tonic-gate 		sz = blkcount * udf_vfsp->udf_lbsize;
9597c478bd9Sstevel@tonic-gate 		lad->lad_ext_len = SWAP_32(sz);
9607c478bd9Sstevel@tonic-gate 		lad->lad_ext_loc = SWAP_32(beginblk);
9617c478bd9Sstevel@tonic-gate 		lad->lad_ext_prn = SWAP_16(ud_part->udp_number);
9627c478bd9Sstevel@tonic-gate 		dummy += sizeof (struct long_ad);
9637c478bd9Sstevel@tonic-gate 		use->use_len_ad = SWAP_32(dummy);
9647c478bd9Sstevel@tonic-gate 	} else {
9657c478bd9Sstevel@tonic-gate 		error = ENOSPC;
9667c478bd9Sstevel@tonic-gate 		goto end;
9677c478bd9Sstevel@tonic-gate 	}
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate end:
9707c478bd9Sstevel@tonic-gate 	if (!error) {
9717c478bd9Sstevel@tonic-gate 		bdwrite(bp);
9727c478bd9Sstevel@tonic-gate 	} else {
9737c478bd9Sstevel@tonic-gate 		brelse(bp);
9747c478bd9Sstevel@tonic-gate 	}
9757c478bd9Sstevel@tonic-gate 	return (error);
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate /* ARGSUSED */
9797c478bd9Sstevel@tonic-gate int32_t
ud_ialloc(struct ud_inode * pip,struct ud_inode ** ipp,struct vattr * vap,struct cred * cr)9807c478bd9Sstevel@tonic-gate ud_ialloc(struct ud_inode *pip,
9817c478bd9Sstevel@tonic-gate 	struct ud_inode **ipp, struct vattr *vap, struct cred *cr)
9827c478bd9Sstevel@tonic-gate {
9837c478bd9Sstevel@tonic-gate 	int32_t err;
9847c478bd9Sstevel@tonic-gate 	uint32_t blkno, size, loc;
9857c478bd9Sstevel@tonic-gate 	uint32_t imode, ichar, lbsize, ea_len, dummy;
9867c478bd9Sstevel@tonic-gate 	uint16_t prn, flags;
9877c478bd9Sstevel@tonic-gate 	struct buf *bp;
9887c478bd9Sstevel@tonic-gate 	struct file_entry *fe;
9897c478bd9Sstevel@tonic-gate 	struct timespec32 time;
9907c478bd9Sstevel@tonic-gate 	struct timespec32 settime;
9917c478bd9Sstevel@tonic-gate 	struct icb_tag *icb;
9927c478bd9Sstevel@tonic-gate 	struct ext_attr_hdr *eah;
9937c478bd9Sstevel@tonic-gate 	struct dev_spec_ear *ds;
9947c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
9957c478bd9Sstevel@tonic-gate 	timestruc_t now;
9967c478bd9Sstevel@tonic-gate 	uid_t uid;
9977c478bd9Sstevel@tonic-gate 	gid_t gid;
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	ASSERT(pip);
10017c478bd9Sstevel@tonic-gate 	ASSERT(vap != NULL);
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	ud_printf("ud_ialloc\n");
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	if (((vap->va_mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) ||
10067c478bd9Sstevel@tonic-gate 	    ((vap->va_mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime)))
10077c478bd9Sstevel@tonic-gate 		return (EOVERFLOW);
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	udf_vfsp = pip->i_udf;
10107c478bd9Sstevel@tonic-gate 	lbsize = udf_vfsp->udf_lbsize;
10117c478bd9Sstevel@tonic-gate 	prn = pip->i_icb_prn;
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	if ((err = ud_alloc_space(pip->i_vfs, prn,
1014*ad9a7bd3SRichard Lowe 	    0, 1, &blkno, &size, 0, 1)) != 0) {
10157c478bd9Sstevel@tonic-gate 		return (err);
10167c478bd9Sstevel@tonic-gate 	}
10177c478bd9Sstevel@tonic-gate 	loc = ud_xlate_to_daddr(udf_vfsp, prn, blkno, 1, &dummy);
10187c478bd9Sstevel@tonic-gate 	ASSERT(dummy == 1);
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	bp = ud_bread(pip->i_dev, loc << udf_vfsp->udf_l2d_shift, lbsize);
10217c478bd9Sstevel@tonic-gate 	if (bp->b_flags & B_ERROR) {
10227c478bd9Sstevel@tonic-gate 		ud_free_space(pip->i_vfs, prn, blkno, size);
10237c478bd9Sstevel@tonic-gate 		return (EIO);
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 	bzero(bp->b_un.b_addr, bp->b_bcount);
10267c478bd9Sstevel@tonic-gate 	fe = (struct file_entry *)bp->b_un.b_addr;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	uid = crgetuid(cr);
10297c478bd9Sstevel@tonic-gate 	fe->fe_uid = SWAP_32(uid);
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	/*
10327c478bd9Sstevel@tonic-gate 	 * To determine the group-id of the created file:
10337c478bd9Sstevel@tonic-gate 	 * 1) If the gid is set in the attribute list (non-Sun & pre-4.0
10347c478bd9Sstevel@tonic-gate 	 *	clients are not likely to set the gid), then use it if
10357c478bd9Sstevel@tonic-gate 	 *	the process is privileged, belongs to the target group,
10367c478bd9Sstevel@tonic-gate 	 *	or the group is the same as the parent directory.
10377c478bd9Sstevel@tonic-gate 	 * 2) If the filesystem was not mounted with the Old-BSD-compatible
10387c478bd9Sstevel@tonic-gate 	 *	GRPID option, and the directory's set-gid bit is clear,
10397c478bd9Sstevel@tonic-gate 	 *	then use the process's gid.
10407c478bd9Sstevel@tonic-gate 	 * 3) Otherwise, set the group-id to the gid of the parent directory.
10417c478bd9Sstevel@tonic-gate 	 */
10427c478bd9Sstevel@tonic-gate 	if ((vap->va_mask & AT_GID) &&
1043*ad9a7bd3SRichard Lowe 	    ((vap->va_gid == pip->i_gid) || groupmember(vap->va_gid, cr) ||
1044*ad9a7bd3SRichard Lowe 	    secpolicy_vnode_create_gid(cr) == 0)) {
10457c478bd9Sstevel@tonic-gate 		/*
10467c478bd9Sstevel@tonic-gate 		 * XXX - is this only the case when a 4.0 NFS client, or a
10477c478bd9Sstevel@tonic-gate 		 * client derived from that code, makes a call over the wire?
10487c478bd9Sstevel@tonic-gate 		 */
10497c478bd9Sstevel@tonic-gate 		fe->fe_gid = SWAP_32(vap->va_gid);
10507c478bd9Sstevel@tonic-gate 	} else {
10517c478bd9Sstevel@tonic-gate 		gid = crgetgid(cr);
10527c478bd9Sstevel@tonic-gate 		fe->fe_gid = (pip->i_char & ISGID) ?
1053*ad9a7bd3SRichard Lowe 		    SWAP_32(pip->i_gid) : SWAP_32(gid);
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	imode = MAKEIMODE(vap->va_type, vap->va_mode);
10577c478bd9Sstevel@tonic-gate 	ichar = imode & (VSUID | VSGID | VSVTX);
10587c478bd9Sstevel@tonic-gate 	imode = UD_UPERM2DPERM(imode);
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	/*
10617c478bd9Sstevel@tonic-gate 	 * Under solaris only the owner can
10627c478bd9Sstevel@tonic-gate 	 * change the attributes of files so set
10637c478bd9Sstevel@tonic-gate 	 * the change attribute bit only for user
10647c478bd9Sstevel@tonic-gate 	 */
10657c478bd9Sstevel@tonic-gate 	imode |= IATTR;
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	/*
10687c478bd9Sstevel@tonic-gate 	 * File delete permissions on Solaris are
10697c478bd9Sstevel@tonic-gate 	 * the permissions on the directory but not the file
10707c478bd9Sstevel@tonic-gate 	 * when we create a file just inherit the directorys
10717c478bd9Sstevel@tonic-gate 	 * write permission to be the file delete permissions
10727c478bd9Sstevel@tonic-gate 	 * Atleast we will be consistent in the files we create
10737c478bd9Sstevel@tonic-gate 	 */
10747c478bd9Sstevel@tonic-gate 	imode |= (pip->i_perm & (IWRITE | IWRITE >> 5 | IWRITE >> 10)) << 3;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	fe->fe_perms = SWAP_32(imode);
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	/*
10797c478bd9Sstevel@tonic-gate 	 * udf does not have a "." entry in dir's
10807c478bd9Sstevel@tonic-gate 	 * so even directories have only one link
10817c478bd9Sstevel@tonic-gate 	 */
10827c478bd9Sstevel@tonic-gate 	fe->fe_lcount = SWAP_16(1);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	fe->fe_info_len = 0;
10857c478bd9Sstevel@tonic-gate 	fe->fe_lbr = 0;
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	gethrestime(&now);
10887c478bd9Sstevel@tonic-gate 	time.tv_sec = now.tv_sec;
10897c478bd9Sstevel@tonic-gate 	time.tv_nsec = now.tv_nsec;
10907c478bd9Sstevel@tonic-gate 	if (vap->va_mask & AT_ATIME) {
10917c478bd9Sstevel@tonic-gate 		TIMESPEC_TO_TIMESPEC32(&settime, &vap->va_atime)
10927c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&settime, &fe->fe_acc_time);
10937c478bd9Sstevel@tonic-gate 	} else
10947c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&time, &fe->fe_acc_time);
10957c478bd9Sstevel@tonic-gate 	if (vap->va_mask & AT_MTIME) {
10967c478bd9Sstevel@tonic-gate 		TIMESPEC_TO_TIMESPEC32(&settime, &vap->va_mtime)
10977c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&settime, &fe->fe_mod_time);
10987c478bd9Sstevel@tonic-gate 	} else
10997c478bd9Sstevel@tonic-gate 		ud_utime2dtime(&time, &fe->fe_mod_time);
11007c478bd9Sstevel@tonic-gate 	ud_utime2dtime(&time, &fe->fe_attr_time);
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	ud_update_regid(&fe->fe_impl_id);
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
11057c478bd9Sstevel@tonic-gate 	fe->fe_uniq_id = SWAP_64(udf_vfsp->udf_maxuniq);
11067c478bd9Sstevel@tonic-gate 	udf_vfsp->udf_maxuniq++;
11077c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	ea_len = 0;
1110*ad9a7bd3SRichard Lowe 	if ((vap->va_type == VBLK) || (vap->va_type == VCHR)) {
11117c478bd9Sstevel@tonic-gate 		eah = (struct ext_attr_hdr *)fe->fe_spec;
11127c478bd9Sstevel@tonic-gate 		ea_len = (sizeof (struct ext_attr_hdr) + 3) & ~3;
11137c478bd9Sstevel@tonic-gate 		eah->eah_ial = SWAP_32(ea_len);
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 		ds = (struct dev_spec_ear *)&fe->fe_spec[ea_len];
11167c478bd9Sstevel@tonic-gate 		ea_len += ud_make_dev_spec_ear(ds,
1117*ad9a7bd3SRichard Lowe 		    getmajor(vap->va_rdev), getminor(vap->va_rdev));
11187c478bd9Sstevel@tonic-gate 		ea_len = (ea_len + 3) & ~3;
11197c478bd9Sstevel@tonic-gate 		eah->eah_aal = SWAP_32(ea_len);
11207c478bd9Sstevel@tonic-gate 		ud_make_tag(udf_vfsp, &eah->eah_tag,
1121*ad9a7bd3SRichard Lowe 		    UD_EXT_ATTR_HDR, blkno, ea_len);
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	fe->fe_len_ear = SWAP_32(ea_len);
11257c478bd9Sstevel@tonic-gate 	fe->fe_len_adesc = 0;
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	icb = &fe->fe_icb_tag;
11287c478bd9Sstevel@tonic-gate 	icb->itag_prnde = 0;
11297c478bd9Sstevel@tonic-gate 	icb->itag_strategy = SWAP_16(STRAT_TYPE4);
11307c478bd9Sstevel@tonic-gate 	icb->itag_param = 0;
11317c478bd9Sstevel@tonic-gate 	icb->itag_max_ent = SWAP_16(1);
11327c478bd9Sstevel@tonic-gate 	switch (vap->va_type) {
11337c478bd9Sstevel@tonic-gate 		case VREG :
11347c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_FILE;
11357c478bd9Sstevel@tonic-gate 			break;
11367c478bd9Sstevel@tonic-gate 		case VDIR :
11377c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_DIRECTORY;
11387c478bd9Sstevel@tonic-gate 			break;
11397c478bd9Sstevel@tonic-gate 		case VBLK :
11407c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_BLOCK_DEV;
11417c478bd9Sstevel@tonic-gate 			break;
11427c478bd9Sstevel@tonic-gate 		case VCHR :
11437c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_CHAR_DEV;
11447c478bd9Sstevel@tonic-gate 			break;
11457c478bd9Sstevel@tonic-gate 		case VLNK :
11467c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_SYMLINK;
11477c478bd9Sstevel@tonic-gate 			break;
11487c478bd9Sstevel@tonic-gate 		case VFIFO :
11497c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_FIFO;
11507c478bd9Sstevel@tonic-gate 			break;
11517c478bd9Sstevel@tonic-gate 		case VSOCK :
11527c478bd9Sstevel@tonic-gate 			icb->itag_ftype = FTYPE_C_ISSOCK;
11537c478bd9Sstevel@tonic-gate 			break;
11547c478bd9Sstevel@tonic-gate 		default :
11557c478bd9Sstevel@tonic-gate 			brelse(bp);
11567c478bd9Sstevel@tonic-gate 			goto error;
11577c478bd9Sstevel@tonic-gate 	}
11587c478bd9Sstevel@tonic-gate 	icb->itag_lb_loc = 0;
11597c478bd9Sstevel@tonic-gate 	icb->itag_lb_prn = 0;
11607c478bd9Sstevel@tonic-gate 	flags = ICB_FLAG_ONE_AD;
11617c478bd9Sstevel@tonic-gate 	if ((pip->i_char & ISGID) && (vap->va_type == VDIR)) {
11627c478bd9Sstevel@tonic-gate 		ichar |= ISGID;
11637c478bd9Sstevel@tonic-gate 	} else {
11647c478bd9Sstevel@tonic-gate 		if ((ichar & ISGID) &&
11657c478bd9Sstevel@tonic-gate 		    secpolicy_vnode_setids_setgids(cr,
1166*ad9a7bd3SRichard Lowe 		    (gid_t)SWAP_32(fe->fe_gid)) != 0) {
11677c478bd9Sstevel@tonic-gate 			ichar &= ~ISGID;
11687c478bd9Sstevel@tonic-gate 		}
11697c478bd9Sstevel@tonic-gate 	}
11707c478bd9Sstevel@tonic-gate 	if (ichar & ISUID) {
11717c478bd9Sstevel@tonic-gate 		flags |= ICB_FLAG_SETUID;
11727c478bd9Sstevel@tonic-gate 	}
11737c478bd9Sstevel@tonic-gate 	if (ichar & ISGID) {
11747c478bd9Sstevel@tonic-gate 		flags |= ICB_FLAG_SETGID;
11757c478bd9Sstevel@tonic-gate 	}
11767c478bd9Sstevel@tonic-gate 	if (ichar & ISVTX) {
11777c478bd9Sstevel@tonic-gate 		flags |= ICB_FLAG_STICKY;
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 	icb->itag_flags = SWAP_16(flags);
11807c478bd9Sstevel@tonic-gate 	ud_make_tag(udf_vfsp, &fe->fe_tag, UD_FILE_ENTRY, blkno,
1181*ad9a7bd3SRichard Lowe 	    offsetof(struct file_entry, fe_spec) +
1182*ad9a7bd3SRichard Lowe 	    SWAP_32(fe->fe_len_ear) + SWAP_32(fe->fe_len_adesc));
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	BWRITE2(bp);
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
11877c478bd9Sstevel@tonic-gate 	if (vap->va_type == VDIR) {
11887c478bd9Sstevel@tonic-gate 		udf_vfsp->udf_ndirs++;
11897c478bd9Sstevel@tonic-gate 	} else {
11907c478bd9Sstevel@tonic-gate 		udf_vfsp->udf_nfiles++;
11917c478bd9Sstevel@tonic-gate 	}
11927c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11957c478bd9Sstevel@tonic-gate 	{
11967c478bd9Sstevel@tonic-gate 		struct ud_inode *ip;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 		if ((ip = ud_search_icache(pip->i_vfs, prn, blkno)) != NULL) {
11997c478bd9Sstevel@tonic-gate 			cmn_err(CE_NOTE, "duplicate %p %x\n",
1200*ad9a7bd3SRichard Lowe 			    (void *)ip, (uint32_t)ip->i_icb_lbano);
12017c478bd9Sstevel@tonic-gate 		}
12027c478bd9Sstevel@tonic-gate 	}
12037c478bd9Sstevel@tonic-gate #endif
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	if ((err = ud_iget(pip->i_vfs, prn, blkno, ipp, bp, cr)) != 0) {
12067c478bd9Sstevel@tonic-gate error:
12077c478bd9Sstevel@tonic-gate 		ud_free_space(pip->i_vfs, prn, blkno, size);
12087c478bd9Sstevel@tonic-gate 		return (err);
12097c478bd9Sstevel@tonic-gate 	}
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	return (0);
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate noinodes:
12147c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, "%s: out of inodes\n", pip->i_udf->udf_volid);
12157c478bd9Sstevel@tonic-gate 	return (ENOSPC);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate void
ud_ifree(struct ud_inode * ip,vtype_t type)12207c478bd9Sstevel@tonic-gate ud_ifree(struct ud_inode *ip, vtype_t type)
12217c478bd9Sstevel@tonic-gate {
12227c478bd9Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
12237c478bd9Sstevel@tonic-gate 	struct buf *bp;
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 	ud_printf("ud_ifree\n");
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	if (ip->i_vfs == NULL) {
12287c478bd9Sstevel@tonic-gate 		return;
12297c478bd9Sstevel@tonic-gate 	}
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 	udf_vfsp = (struct udf_vfs *)ip->i_vfs->vfs_data;
12327c478bd9Sstevel@tonic-gate 	bp = ud_bread(ip->i_dev, ip->i_icb_lbano <<
1233*ad9a7bd3SRichard Lowe 	    udf_vfsp->udf_l2d_shift, udf_vfsp->udf_lbsize);
12347c478bd9Sstevel@tonic-gate 	if (bp->b_flags & B_ERROR) {
12357c478bd9Sstevel@tonic-gate 		/*
12367c478bd9Sstevel@tonic-gate 		 * Error get rid of bp
12377c478bd9Sstevel@tonic-gate 		 */
12387c478bd9Sstevel@tonic-gate 		brelse(bp);
12397c478bd9Sstevel@tonic-gate 	} else {
12407c478bd9Sstevel@tonic-gate 		/*
12417c478bd9Sstevel@tonic-gate 		 * Just trash the inode
12427c478bd9Sstevel@tonic-gate 		 */
12437c478bd9Sstevel@tonic-gate 		bzero(bp->b_un.b_addr, 0x10);
12447c478bd9Sstevel@tonic-gate 		BWRITE(bp);
12457c478bd9Sstevel@tonic-gate 	}
1246*ad9a7bd3SRichard Lowe 	ud_free_space(ip->i_vfs, ip->i_icb_prn, ip->i_icb_block, 1);
12477c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
12487c478bd9Sstevel@tonic-gate 	if (type == VDIR) {
12497c478bd9Sstevel@tonic-gate 		if (udf_vfsp->udf_ndirs > 1) {
12507c478bd9Sstevel@tonic-gate 			udf_vfsp->udf_ndirs--;
12517c478bd9Sstevel@tonic-gate 		}
12527c478bd9Sstevel@tonic-gate 	} else {
12537c478bd9Sstevel@tonic-gate 		if (udf_vfsp->udf_nfiles > 0) {
12547c478bd9Sstevel@tonic-gate 			udf_vfsp->udf_nfiles --;
12557c478bd9Sstevel@tonic-gate 		}
12567c478bd9Sstevel@tonic-gate 	}
12577c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate /*
12627c478bd9Sstevel@tonic-gate  * Free storage space associated with the specified inode.  The portion
12637c478bd9Sstevel@tonic-gate  * to be freed is specified by lp->l_start and lp->l_len (already
12647c478bd9Sstevel@tonic-gate  * normalized to a "whence" of 0).
12657c478bd9Sstevel@tonic-gate  *
12667c478bd9Sstevel@tonic-gate  * This is an experimental facility whose continued existence is not
12677c478bd9Sstevel@tonic-gate  * guaranteed.  Currently, we only support the special case
12687c478bd9Sstevel@tonic-gate  * of l_len == 0, meaning free to end of file.
12697c478bd9Sstevel@tonic-gate  *
12707c478bd9Sstevel@tonic-gate  * Blocks are freed in reverse order.  This FILO algorithm will tend to
12717c478bd9Sstevel@tonic-gate  * maintain a contiguous free list much longer than FIFO.
12727c478bd9Sstevel@tonic-gate  * See also ufs_itrunc() in ufs_inode.c.
12737c478bd9Sstevel@tonic-gate  *
12747c478bd9Sstevel@tonic-gate  * Bug: unused bytes in the last retained block are not cleared.
12757c478bd9Sstevel@tonic-gate  * This may result in a "hole" in the file that does not read as zeroes.
12767c478bd9Sstevel@tonic-gate  */
12777c478bd9Sstevel@tonic-gate int32_t
ud_freesp(struct vnode * vp,struct flock64 * lp,int32_t flag,struct cred * cr)12787c478bd9Sstevel@tonic-gate ud_freesp(struct vnode *vp,
12797c478bd9Sstevel@tonic-gate 	struct flock64 *lp,
12807c478bd9Sstevel@tonic-gate 	int32_t flag, struct cred *cr)
12817c478bd9Sstevel@tonic-gate {
12827c478bd9Sstevel@tonic-gate 	int32_t i;
12837c478bd9Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
12847c478bd9Sstevel@tonic-gate 	int32_t error;
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	ASSERT(vp->v_type == VREG);
12877c478bd9Sstevel@tonic-gate 	ASSERT(lp->l_start >= (offset_t)0);	/* checked by convoff */
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	ud_printf("udf_freesp\n");
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	if (lp->l_len != 0) {
12927c478bd9Sstevel@tonic-gate 		return (EINVAL);
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
12967c478bd9Sstevel@tonic-gate 	if (ip->i_size == (u_offset_t)lp->l_start) {
12977c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
12987c478bd9Sstevel@tonic-gate 		return (0);
12997c478bd9Sstevel@tonic-gate 	}
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	/*
13027c478bd9Sstevel@tonic-gate 	 * Check if there is any active mandatory lock on the
13037c478bd9Sstevel@tonic-gate 	 * range that will be truncated/expanded.
13047c478bd9Sstevel@tonic-gate 	 */
13057c478bd9Sstevel@tonic-gate 	if (MANDLOCK(vp, ip->i_char)) {
13067c478bd9Sstevel@tonic-gate 		offset_t save_start;
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 		save_start = lp->l_start;
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 		if (ip->i_size < lp->l_start) {
13117c478bd9Sstevel@tonic-gate 			/*
13127c478bd9Sstevel@tonic-gate 			 * "Truncate up" case: need to make sure there
13137c478bd9Sstevel@tonic-gate 			 * is no lock beyond current end-of-file. To
13147c478bd9Sstevel@tonic-gate 			 * do so, we need to set l_start to the size
13157c478bd9Sstevel@tonic-gate 			 * of the file temporarily.
13167c478bd9Sstevel@tonic-gate 			 */
13177c478bd9Sstevel@tonic-gate 			lp->l_start = ip->i_size;
13187c478bd9Sstevel@tonic-gate 		}
13197c478bd9Sstevel@tonic-gate 		lp->l_type = F_WRLCK;
13207c478bd9Sstevel@tonic-gate 		lp->l_sysid = 0;
13217c478bd9Sstevel@tonic-gate 		lp->l_pid = ttoproc(curthread)->p_pid;
13227c478bd9Sstevel@tonic-gate 		i = (flag & (FNDELAY|FNONBLOCK)) ? 0 : SLPFLCK;
13237c478bd9Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
13247c478bd9Sstevel@tonic-gate 		if ((i = reclock(vp, lp, i, 0, lp->l_start, NULL)) != 0 ||
13257c478bd9Sstevel@tonic-gate 		    lp->l_type != F_UNLCK) {
13267c478bd9Sstevel@tonic-gate 			return (i ? i : EAGAIN);
13277c478bd9Sstevel@tonic-gate 		}
13287c478bd9Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_READER);
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 		lp->l_start = save_start;
13317c478bd9Sstevel@tonic-gate 	}
13327c478bd9Sstevel@tonic-gate 	/*
13337c478bd9Sstevel@tonic-gate 	 * Make sure a write isn't in progress (allocating blocks)
13347c478bd9Sstevel@tonic-gate 	 * by acquiring i_rwlock (we promised ufs_bmap we wouldn't
13357c478bd9Sstevel@tonic-gate 	 * truncate while it was allocating blocks).
13367c478bd9Sstevel@tonic-gate 	 * Grab the locks in the right order.
13377c478bd9Sstevel@tonic-gate 	 */
13387c478bd9Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
13397c478bd9Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
13407c478bd9Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
13417c478bd9Sstevel@tonic-gate 	error = ud_itrunc(ip, lp->l_start, 0, cr);
13427c478bd9Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
13437c478bd9Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
13447c478bd9Sstevel@tonic-gate 	return (error);
13457c478bd9Sstevel@tonic-gate }
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate /*
13507c478bd9Sstevel@tonic-gate  * Cache is implemented by
13517c478bd9Sstevel@tonic-gate  * allocating a cluster of blocks
13527c478bd9Sstevel@tonic-gate  */
13537c478bd9Sstevel@tonic-gate int32_t
ud_alloc_from_cache(struct udf_vfs * udf_vfsp,struct ud_part * part,uint32_t * blkno)13547c478bd9Sstevel@tonic-gate ud_alloc_from_cache(struct udf_vfs *udf_vfsp,
13557c478bd9Sstevel@tonic-gate 	struct ud_part *part, uint32_t *blkno)
13567c478bd9Sstevel@tonic-gate {
13577c478bd9Sstevel@tonic-gate 	uint32_t bno, sz;
13587c478bd9Sstevel@tonic-gate 	int32_t error, index, free = 0;
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	ud_printf("ud_alloc_from_cache\n");
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 	ASSERT(udf_vfsp);
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
13657c478bd9Sstevel@tonic-gate 	if (part->udp_cache_count == 0) {
13667c478bd9Sstevel@tonic-gate 		mutex_exit(&udf_vfsp->udf_lock);
13677c478bd9Sstevel@tonic-gate 		/* allocate new cluster */
13687c478bd9Sstevel@tonic-gate 		if ((error = ud_alloc_space(udf_vfsp->udf_vfs,
1369*ad9a7bd3SRichard Lowe 		    part->udp_number, 0, CLSTR_SIZE, &bno, &sz, 1, 0)) != 0) {
13707c478bd9Sstevel@tonic-gate 			return (error);
13717c478bd9Sstevel@tonic-gate 		}
13727c478bd9Sstevel@tonic-gate 		if (sz == 0) {
13737c478bd9Sstevel@tonic-gate 			return (ENOSPC);
13747c478bd9Sstevel@tonic-gate 		}
13757c478bd9Sstevel@tonic-gate 		mutex_enter(&udf_vfsp->udf_lock);
13767c478bd9Sstevel@tonic-gate 		if (part->udp_cache_count == 0) {
13777c478bd9Sstevel@tonic-gate 			for (index = 0; index < sz; index++, bno++) {
13787c478bd9Sstevel@tonic-gate 				part->udp_cache[index] = bno;
13797c478bd9Sstevel@tonic-gate 			}
13807c478bd9Sstevel@tonic-gate 			part->udp_cache_count = sz;
13817c478bd9Sstevel@tonic-gate 		} else {
13827c478bd9Sstevel@tonic-gate 			free = 1;
13837c478bd9Sstevel@tonic-gate 		}
13847c478bd9Sstevel@tonic-gate 	}
13857c478bd9Sstevel@tonic-gate 	part->udp_cache_count--;
13867c478bd9Sstevel@tonic-gate 	*blkno = part->udp_cache[part->udp_cache_count];
13877c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
13887c478bd9Sstevel@tonic-gate 	if (free) {
13897c478bd9Sstevel@tonic-gate 		ud_free_space(udf_vfsp->udf_vfs, part->udp_number, bno, sz);
13907c478bd9Sstevel@tonic-gate 	}
13917c478bd9Sstevel@tonic-gate 	return (0);
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate /*
13957c478bd9Sstevel@tonic-gate  * Will be called from unmount
13967c478bd9Sstevel@tonic-gate  */
13977c478bd9Sstevel@tonic-gate int32_t
ud_release_cache(struct udf_vfs * udf_vfsp)13987c478bd9Sstevel@tonic-gate ud_release_cache(struct udf_vfs *udf_vfsp)
13997c478bd9Sstevel@tonic-gate {
14007c478bd9Sstevel@tonic-gate 	int32_t i, error = 0;
14017c478bd9Sstevel@tonic-gate 	struct ud_part *part;
14027c478bd9Sstevel@tonic-gate 	uint32_t start, nblks;
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 	ud_printf("ud_release_cache\n");
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_lock);
14077c478bd9Sstevel@tonic-gate 	part = udf_vfsp->udf_parts;
14087c478bd9Sstevel@tonic-gate 	for (i = 0; i < udf_vfsp->udf_npart; i++, part++) {
14097c478bd9Sstevel@tonic-gate 		if (part->udp_cache_count) {
14107c478bd9Sstevel@tonic-gate 			nblks = part->udp_cache_count;
14117c478bd9Sstevel@tonic-gate 			start = part->udp_cache[0];
14127c478bd9Sstevel@tonic-gate 			part->udp_cache_count = 0;
14137c478bd9Sstevel@tonic-gate 			mutex_exit(&udf_vfsp->udf_lock);
14147c478bd9Sstevel@tonic-gate 			ud_free_space(udf_vfsp->udf_vfs,
1415*ad9a7bd3SRichard Lowe 			    part->udp_number, start, nblks);
14167c478bd9Sstevel@tonic-gate 			mutex_enter(&udf_vfsp->udf_lock);
14177c478bd9Sstevel@tonic-gate 		}
14187c478bd9Sstevel@tonic-gate 	}
14197c478bd9Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_lock);
14207c478bd9Sstevel@tonic-gate 	return (error);
14217c478bd9Sstevel@tonic-gate }
1422