Home | History | Annotate | Download | only in udfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/t_lock.h>
     31 #include <sys/param.h>
     32 #include <sys/time.h>
     33 #include <sys/systm.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/resource.h>
     36 #include <sys/signal.h>
     37 #include <sys/cred.h>
     38 #include <sys/user.h>
     39 #include <sys/buf.h>
     40 #include <sys/vfs.h>
     41 #include <sys/stat.h>
     42 #include <sys/vnode.h>
     43 #include <sys/mode.h>
     44 #include <sys/proc.h>
     45 #include <sys/disp.h>
     46 #include <sys/file.h>
     47 #include <sys/fcntl.h>
     48 #include <sys/flock.h>
     49 #include <sys/kmem.h>
     50 #include <sys/uio.h>
     51 #include <sys/dnlc.h>
     52 #include <sys/conf.h>
     53 #include <sys/errno.h>
     54 #include <sys/mman.h>
     55 #include <sys/fbuf.h>
     56 #include <sys/pathname.h>
     57 #include <sys/debug.h>
     58 #include <sys/vmsystm.h>
     59 #include <sys/cmn_err.h>
     60 #include <sys/dirent.h>
     61 #include <sys/errno.h>
     62 #include <sys/modctl.h>
     63 #include <sys/statvfs.h>
     64 #include <sys/mount.h>
     65 #include <sys/sunddi.h>
     66 #include <sys/bootconf.h>
     67 #include <sys/policy.h>
     68 
     69 #include <vm/hat.h>
     70 #include <vm/page.h>
     71 #include <vm/pvn.h>
     72 #include <vm/as.h>
     73 #include <vm/seg.h>
     74 #include <vm/seg_map.h>
     75 #include <vm/seg_kmem.h>
     76 #include <vm/seg_vn.h>
     77 #include <vm/rm.h>
     78 #include <vm/page.h>
     79 #include <sys/swap.h>
     80 
     81 #include <fs/fs_subr.h>
     82 
     83 #include <sys/fs/udf_volume.h>
     84 #include <sys/fs/udf_inode.h>
     85 
     86 #ifdef	DEBUG
     87 extern struct ud_inode *ud_search_icache(struct vfs *, uint16_t, uint32_t);
     88 #endif
     89 
     90 int32_t ud_alloc_space_bmap(struct vfs *, struct ud_part *,
     91 	uint32_t, uint32_t, uint32_t *, uint32_t *, int32_t);
     92 int32_t ud_check_free_and_mark_used(struct vfs *,
     93 	struct ud_part *, uint32_t, uint32_t *);
     94 int32_t ud_check_free(uint8_t *, uint8_t *, uint32_t, uint32_t);
     95 void ud_mark_used(uint8_t *, uint32_t, uint32_t);
     96 void ud_mark_free(uint8_t *, uint32_t, uint32_t);
     97 int32_t ud_alloc_space_stbl(struct vfs *, struct ud_part *,
     98 	uint32_t, uint32_t, uint32_t *, uint32_t *, int32_t);
     99 int32_t ud_free_space_bmap(struct vfs *,
    100 	struct ud_part *, uint32_t, uint32_t);
    101 int32_t ud_free_space_stbl(struct vfs *,
    102 	struct ud_part *, uint32_t, uint32_t);
    103 
    104 
    105 /*
    106  * WORKSAROUND to the buffer cache crap
    107  * If the requested block exists in the buffer cache
    108  * buffer cache does not care about the count
    109  * it just returns the old buffer(does not even
    110  * set resid value). Same problem exists if the
    111  * block that is requested is not the first block
    112  * in the cached buffer then this will return
    113  * a different buffer. We work around the above by
    114  * using a fixed size request to the buffer cache
    115  * all the time. This is currently udf_lbsize.
    116  * (Actually it is restricted to udf_lbsize
    117  * because iget always does udf_lbsize requests)
    118  */
    119 
    120 
    121 /*
    122  * allocate blkcount blocks continuously
    123  * near "proximity" block in partion defined by prn.
    124  * if proximity != 0 means less_is_ok = 0
    125  * return the starting block no and count
    126  * of blocks allocated in start_blkno & size
    127  * if less_is_ok == 0 then allocate only if
    128  * entire requirement can be met.
    129  */
    130 int32_t
    131 ud_alloc_space(struct vfs *vfsp, uint16_t prn,
    132 	uint32_t proximity, uint32_t blkcount,
    133 	uint32_t *start_blkno, uint32_t *size,
    134 	int32_t less_is_ok, int32_t metadata)
    135 {
    136 	int32_t i, error = 0;
    137 	struct udf_vfs *udf_vfsp;
    138 	struct ud_part *ud_part;
    139 
    140 	ud_printf("ud_alloc_space\n");
    141 
    142 
    143 /*
    144  * prom_printf("ud_alloc_space %x %x %x %x\n",
    145  * proximity, blkcount, less_is_ok, metadata);
    146  */
    147 
    148 	if (blkcount == 0) {
    149 		*start_blkno = 0;
    150 		*size = 0;
    151 		return (0);
    152 	}
    153 
    154 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    155 	ud_part = udf_vfsp->udf_parts;
    156 	for (i = 0; i < udf_vfsp->udf_npart; i++) {
    157 		if (prn == ud_part->udp_number) {
    158 			break;
    159 		}
    160 		ud_part ++;
    161 	}
    162 
    163 	if (i == udf_vfsp->udf_npart) {
    164 		return (1);
    165 	}
    166 	*start_blkno = 0;
    167 	*size = 0;
    168 	if (metadata) {
    169 		error = ud_alloc_from_cache(udf_vfsp, ud_part, start_blkno);
    170 		if (error == 0) {
    171 			*size = 1;
    172 			return (0);
    173 		}
    174 	}
    175 	if (ud_part->udp_nfree != 0) {
    176 		if (ud_part->udp_flags == UDP_BITMAPS) {
    177 			error = ud_alloc_space_bmap(vfsp, ud_part, proximity,
    178 				blkcount, start_blkno, size, less_is_ok);
    179 		} else {
    180 			error = ud_alloc_space_stbl(vfsp, ud_part, proximity,
    181 				blkcount, start_blkno, size, less_is_ok);
    182 		}
    183 		if (error == 0) {
    184 			mutex_enter(&udf_vfsp->udf_lock);
    185 			ASSERT(ud_part->udp_nfree >= *size);
    186 			ASSERT(udf_vfsp->udf_freeblks >= *size);
    187 			ud_part->udp_nfree -= *size;
    188 			udf_vfsp->udf_freeblks -= *size;
    189 			mutex_exit(&udf_vfsp->udf_lock);
    190 		}
    191 	} else {
    192 		error = ENOSPC;
    193 	}
    194 /*
    195  * prom_printf("end %x %x %x\n", error, *start_blkno, *size);
    196  */
    197 
    198 	return (error);
    199 }
    200 
    201 #ifdef	SKIP_USED_BLOCKS
    202 /*
    203  * This table is manually constructed
    204  */
    205 int8_t skip[256] = {
    206 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    207 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    208 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    209 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    210 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    211 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    212 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    213 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    214 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    215 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    216 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    217 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    218 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    219 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    220 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    221 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    222 };
    223 #endif
    224 
    225 #define	HDR_BLKS	(24 * 8)
    226 
    227 int32_t
    228 ud_alloc_space_bmap(struct vfs *vfsp,
    229 	struct ud_part *ud_part, uint32_t proximity,
    230 	uint32_t blkcount, uint32_t *start_blkno,
    231 	uint32_t *size, int32_t less_is_ok)
    232 {
    233 	struct buf *bp = NULL;
    234 	struct udf_vfs *udf_vfsp;
    235 	uint32_t old_loc, old_size, new_size;
    236 	uint8_t *addr, *eaddr;
    237 	uint32_t loop_count, loop_begin, loop_end;
    238 	uint32_t bno, begin, dummy, temp, lbsz, bb_count;
    239 	uint32_t bblk = 0, eblk = 0;
    240 	int32_t fragmented;
    241 
    242 	ud_printf("ud_alloc_space_bmap\n");
    243 
    244 	ASSERT(ud_part);
    245 	ASSERT(ud_part->udp_flags == UDP_BITMAPS);
    246 
    247 	if (ud_part->udp_unall_len == 0) {
    248 		return (ENOSPC);
    249 	}
    250 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    251 	lbsz = udf_vfsp->udf_lbsize;
    252 	bb_count = udf_vfsp->udf_lbsize << 3;
    253 
    254 	if (proximity != 0) {
    255 		/*
    256 		 * directly try allocating
    257 		 * at proximity
    258 		 */
    259 		temp = blkcount;
    260 		if (ud_check_free_and_mark_used(vfsp,
    261 				ud_part, proximity, &temp) == 0) {
    262 			if (temp != 0) {
    263 				*start_blkno = proximity;
    264 				*size = temp;
    265 				return (0);
    266 			}
    267 		}
    268 		*start_blkno = 0;
    269 		*size = 0;
    270 	}
    271 
    272 	mutex_enter(&udf_vfsp->udf_lock);
    273 	fragmented = udf_vfsp->udf_fragmented;
    274 	mutex_exit(&udf_vfsp->udf_lock);
    275 retry:
    276 	old_loc = old_size = 0;
    277 
    278 	mutex_enter(&udf_vfsp->udf_lock);
    279 	loop_begin = (ud_part->udp_last_alloc + CLSTR_MASK) & ~CLSTR_MASK;
    280 	mutex_exit(&udf_vfsp->udf_lock);
    281 
    282 	loop_end = ud_part->udp_nblocks + HDR_BLKS;
    283 	loop_count = (loop_begin) ? 2 : 1;
    284 	while (loop_count--) {
    285 		for (bno = loop_begin + HDR_BLKS; bno + blkcount < loop_end; ) {
    286 
    287 
    288 			/*
    289 			 * Each bread is restricted to lbsize
    290 			 * due to the way bread is implemented
    291 			 */
    292 			if ((bp == NULL) ||
    293 				((eblk - bno) < blkcount)) {
    294 				if (bp != NULL) {
    295 					brelse(bp);
    296 				}
    297 				begin = ud_part->udp_unall_loc +
    298 						bno / bb_count;
    299 				bp = ud_bread(vfsp->vfs_dev,
    300 					ud_xlate_to_daddr(udf_vfsp,
    301 						ud_part->udp_number,
    302 						begin, 1, &dummy)
    303 					<< udf_vfsp->udf_l2d_shift, lbsz);
    304 				if (bp->b_flags & B_ERROR) {
    305 					brelse(bp);
    306 					return (EIO);
    307 				}
    308 				bblk = begin * bb_count;
    309 				eblk = bblk + bb_count;
    310 				addr = (uint8_t *)bp->b_un.b_addr;
    311 				eaddr = addr + bp->b_bcount;
    312 			}
    313 
    314 			if (blkcount > (eblk - bno)) {
    315 				temp = eblk - bno;
    316 			} else {
    317 				temp = blkcount;
    318 			}
    319 			if ((new_size = ud_check_free(addr, eaddr,
    320 					bno - bblk, temp)) == temp) {
    321 				ud_mark_used(addr, bno - bblk, temp);
    322 				bdwrite(bp);
    323 				*start_blkno = bno - HDR_BLKS;
    324 				*size = temp;
    325 				mutex_enter(&udf_vfsp->udf_lock);
    326 				ud_part->udp_last_alloc =
    327 					bno + temp - HDR_BLKS;
    328 				mutex_exit(&udf_vfsp->udf_lock);
    329 				return (0);
    330 			}
    331 			if (less_is_ok) {
    332 				if (old_size < new_size) {
    333 					old_loc = bno - HDR_BLKS;
    334 					old_size = new_size;
    335 				}
    336 			}
    337 			if (new_size != 0) {
    338 				bno += new_size;
    339 			} else {
    340 #ifdef	SKIP_USED_BLOCKS
    341 				/*
    342 				 * Skipping 0's
    343 				 * implement a allocated block skip
    344 				 * using a while loop with an
    345 				 * preinitialised array of 256 elements
    346 				 * for number of blocks skipped
    347 				 */
    348 				bno &= ~3;
    349 				while (skip[addr[(bno - bblk) >> 3]] == 8)
    350 					bno += 8;
    351 				bno += skip[addr[(bno - bblk) >> 3]];
    352 #else
    353 				bno++;
    354 #endif
    355 			}
    356 			if (!fragmented) {
    357 				bno = (bno + CLSTR_MASK) & ~CLSTR_MASK;
    358 			}
    359 		}
    360 		if (bp != NULL) {
    361 			brelse(bp);
    362 			bp = NULL;
    363 		}
    364 		if (loop_count) {
    365 			loop_end = loop_begin + HDR_BLKS;
    366 			loop_begin = 0;
    367 		}
    368 	}
    369 	if ((old_size == 0) && (!fragmented)) {
    370 		mutex_enter(&udf_vfsp->udf_lock);
    371 		fragmented = udf_vfsp->udf_fragmented = 1;
    372 		mutex_exit(&udf_vfsp->udf_lock);
    373 		goto retry;
    374 	}
    375 	if (less_is_ok && (old_size != 0)) {
    376 
    377 		/*
    378 		 * Check once again
    379 		 * somebody else might have
    380 		 * already allocated behind us
    381 		 */
    382 		if (ud_check_free_and_mark_used(vfsp,
    383 				ud_part, old_loc, &old_size) == 0) {
    384 			if (old_size != 0) {
    385 				*start_blkno = old_loc;
    386 				*size = old_size;
    387 				mutex_enter(&udf_vfsp->udf_lock);
    388 				ud_part->udp_last_alloc = old_loc + old_size;
    389 				mutex_exit(&udf_vfsp->udf_lock);
    390 				return (0);
    391 			}
    392 		}
    393 
    394 		/*
    395 		 * Failed what ever the reason
    396 		 */
    397 		goto retry;
    398 	}
    399 	return (ENOSPC);
    400 }
    401 
    402 /*
    403  * start is the block from the begining
    404  * of the partition ud_part
    405  */
    406 int32_t
    407 ud_check_free_and_mark_used(struct vfs *vfsp,
    408 	struct ud_part *ud_part, uint32_t start, uint32_t *count)
    409 {
    410 	struct buf *bp;
    411 	struct udf_vfs *udf_vfsp;
    412 	uint32_t begin, dummy, bb_count;
    413 
    414 	/*
    415 	 * Adjust start for the header
    416 	 */
    417 	start += HDR_BLKS;
    418 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    419 	bb_count = udf_vfsp->udf_lbsize << 3;
    420 
    421 	/*
    422 	 * Read just on block worth of bitmap
    423 	 */
    424 	begin = ud_part->udp_unall_loc + (start / bb_count);
    425 	bp = ud_bread(vfsp->vfs_dev,
    426 		ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number,
    427 			begin, 1, &dummy) << udf_vfsp->udf_l2d_shift,
    428 			udf_vfsp->udf_lbsize);
    429 	if (bp->b_flags & B_ERROR) {
    430 		brelse(bp);
    431 		return (EIO);
    432 	}
    433 
    434 	/*
    435 	 * Adjust the count if necessary
    436 	 */
    437 	start -= begin * bb_count;
    438 	if ((start + *count) > bb_count) {
    439 		*count = bb_count - start;
    440 		ASSERT(*count > 0);
    441 	}
    442 	if (ud_check_free((uint8_t *)bp->b_un.b_addr,
    443 			(uint8_t *)bp->b_un.b_addr + bp->b_bcount,
    444 			start, *count) != *count) {
    445 		brelse(bp);
    446 		return (1);
    447 	}
    448 	ud_mark_used((uint8_t *)bp->b_un.b_addr, start, *count);
    449 	bdwrite(bp);
    450 
    451 	return (0);
    452 }
    453 
    454 int32_t
    455 ud_check_free(uint8_t *addr, uint8_t *eaddr, uint32_t start, uint32_t count)
    456 {
    457 	int32_t i = 0;
    458 
    459 	for (i = 0; i < count; i++) {
    460 		if (&addr[start >> 3] >= eaddr) {
    461 			break;
    462 		}
    463 		if ((addr[start >> 3] & (1 << (start & 0x7))) == 0) {
    464 			break;
    465 		}
    466 		start ++;
    467 	}
    468 	return (i);
    469 }
    470 
    471 void
    472 ud_mark_used(uint8_t *addr, uint32_t start, uint32_t count)
    473 {
    474 	int32_t i = 0;
    475 
    476 	for (i = 0; i < count; i++) {
    477 		addr[start >> 3] &= ~(1 << (start & 0x7));
    478 		start++;
    479 	}
    480 }
    481 
    482 void
    483 ud_mark_free(uint8_t *addr, uint32_t start, uint32_t count)
    484 {
    485 	int32_t i = 0;
    486 
    487 	for (i = 0; i < count; i++) {
    488 		addr[start >> 3] |= (1 << (start & 0x7));
    489 		start++;
    490 	}
    491 }
    492 
    493 /* ARGSUSED */
    494 int32_t
    495 ud_alloc_space_stbl(struct vfs *vfsp,
    496 	struct ud_part *ud_part, uint32_t proximity,
    497 	uint32_t blkcount, uint32_t *start_blkno,
    498 	uint32_t *size, int32_t less_is_ok)
    499 {
    500 	uint16_t adesc;
    501 	uint32_t temp, sz;
    502 	int32_t error, index, count, larg_index, larg_sz;
    503 	struct buf *bp;
    504 	struct udf_vfs *udf_vfsp;
    505 	struct unall_space_ent *use;
    506 
    507 	ASSERT(ud_part);
    508 	ASSERT(ud_part->udp_flags == UDP_SPACETBLS);
    509 
    510 	ud_printf("ud_alloc_space_stbl\n");
    511 
    512 	if (ud_part->udp_unall_len == 0) {
    513 		return (ENOSPC);
    514 	}
    515 
    516 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    517 	ASSERT((ud_part->udp_unall_len + 40) <= udf_vfsp->udf_lbsize);
    518 
    519 	bp = ud_bread(vfsp->vfs_dev,
    520 			ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number,
    521 				ud_part->udp_unall_loc, 1, &temp),
    522 			udf_vfsp->udf_lbsize);
    523 
    524 	use = (struct unall_space_ent *)bp->b_un.b_addr;
    525 	sz = SWAP_32(use->use_len_ad);
    526 	adesc = SWAP_16(use->use_icb_tag.itag_flags) & 0x7;
    527 	if (adesc == ICB_FLAG_SHORT_AD) {
    528 		struct short_ad *sad;
    529 
    530 		sad = (struct short_ad *)use->use_ad;
    531 		count = sz / sizeof (struct short_ad);
    532 
    533 		/*
    534 		 * Search the entire list for
    535 		 * a extent which can give the entire data
    536 		 * Do only first fit
    537 		 */
    538 		larg_index = larg_sz = 0;
    539 		for (index = 0; index < count; index++, sad++) {
    540 			temp = SWAP_32(sad->sad_ext_len) >>
    541 					udf_vfsp->udf_l2b_shift;
    542 			if (temp == blkcount) {
    543 				/*
    544 				 * We found the right fit
    545 				 * return the values and
    546 				 * compress the table
    547 				 */
    548 				less_is_ok = 1;
    549 				larg_index = index;
    550 				larg_sz = temp;
    551 				goto compress_sad;
    552 			} else if (temp > blkcount) {
    553 				/*
    554 				 * We found an entry larger than the
    555 				 * requirement. Change the start block
    556 				 * number and the count to reflect the
    557 				 * allocation
    558 				 */
    559 				*start_blkno = SWAP_32(sad->sad_ext_loc);
    560 				*size = blkcount;
    561 				temp = (temp - blkcount) <<
    562 					udf_vfsp->udf_l2b_shift;
    563 				sad->sad_ext_len = SWAP_32(temp);
    564 				temp = SWAP_32(sad->sad_ext_loc) + blkcount;
    565 				sad->sad_ext_loc = SWAP_32(temp);
    566 				goto end;
    567 			}
    568 			/*
    569 			 * Let us keep track of the largest
    570 			 * extent available if less_is_ok.
    571 			 */
    572 			if (less_is_ok) {
    573 				if (temp > larg_sz) {
    574 					larg_sz = temp;
    575 					larg_index = index;
    576 				}
    577 			}
    578 		}
    579 compress_sad:
    580 		if ((less_is_ok) &&
    581 			(larg_sz != 0)) {
    582 			/*
    583 			 * If we came here we could
    584 			 * not find a extent to cover the entire size
    585 			 * return whatever could be allocated
    586 			 * and compress the table
    587 			 */
    588 			sad = (struct short_ad *)use->use_ad;
    589 			sad += larg_index;
    590 			*start_blkno = SWAP_32(sad->sad_ext_loc);
    591 			*size = larg_sz;
    592 			for (index = larg_index; index < count;
    593 					index++, sad++) {
    594 				*sad = *(sad+1);
    595 			}
    596 			sz -= sizeof (struct short_ad);
    597 			use->use_len_ad = SWAP_32(sz);
    598 		} else {
    599 			error = ENOSPC;
    600 		}
    601 		goto end;
    602 	} else if (adesc == ICB_FLAG_LONG_AD) {
    603 		struct long_ad *lad;
    604 
    605 		lad = (struct long_ad *)use->use_ad;
    606 		count = sz / sizeof (struct long_ad);
    607 
    608 		/*
    609 		 * Search the entire list for
    610 		 * a extent which can give the entire data
    611 		 * Do only first fit
    612 		 */
    613 		larg_index = larg_sz = 0;
    614 		for (index = 0; index < count; index++, lad++) {
    615 			temp = SWAP_32(lad->lad_ext_len) >>
    616 					udf_vfsp->udf_l2b_shift;
    617 			if (temp == blkcount) {
    618 				/*
    619 				 * We found the right fit
    620 				 * return the values and
    621 				 * compress the table
    622 				 */
    623 				less_is_ok = 1;
    624 				larg_index = index;
    625 				larg_sz = temp;
    626 				goto compress_lad;
    627 			} else if (temp > blkcount) {
    628 				/*
    629 				 * We found an entry larger than the
    630 				 * requirement. Change the start block
    631 				 * number and the count to reflect the
    632 				 * allocation
    633 				 */
    634 				*start_blkno = SWAP_32(lad->lad_ext_loc);
    635 				*size = blkcount;
    636 				temp = (temp - blkcount) <<
    637 					udf_vfsp->udf_l2b_shift;
    638 				lad->lad_ext_len = SWAP_32(temp);
    639 				temp = SWAP_32(lad->lad_ext_loc) + blkcount;
    640 				lad->lad_ext_loc = SWAP_32(temp);
    641 				goto end;
    642 			}
    643 			/*
    644 			 * Let us keep track of the largest
    645 			 * extent available if less_is_ok.
    646 			 */
    647 			if (less_is_ok) {
    648 				if (temp > larg_sz) {
    649 					larg_sz = temp;
    650 					larg_index = index;
    651 				}
    652 			}
    653 		}
    654 compress_lad:
    655 		if ((less_is_ok) &&
    656 			(larg_sz != 0)) {
    657 			/*
    658 			 * If we came here we could
    659 			 * not find a extent to cover the entire size
    660 			 * return whatever could be allocated
    661 			 * and compress the table
    662 			 */
    663 			lad = (struct long_ad *)use->use_ad;
    664 			lad += larg_index;
    665 			*start_blkno = SWAP_32(lad->lad_ext_loc);
    666 			*size = larg_sz;
    667 			for (index = larg_index; index < count;
    668 					index++, lad++) {
    669 				*lad = *(lad+1);
    670 			}
    671 			sz -= sizeof (struct long_ad);
    672 			use->use_len_ad = SWAP_32(sz);
    673 		} else {
    674 			error = ENOSPC;
    675 		}
    676 		goto end;
    677 	} else {
    678 		error = ENOSPC;
    679 	}
    680 end:
    681 	if (!error) {
    682 		bdwrite(bp);
    683 	} else {
    684 		brelse(bp);
    685 	}
    686 	return (error);
    687 }
    688 
    689 
    690 /*
    691  * release blkcount blocks starting from beginblk
    692  * Call appropriate bmap/space table fucntions
    693  */
    694 void
    695 ud_free_space(struct vfs *vfsp, uint16_t prn,
    696 	uint32_t beginblk, uint32_t blkcount)
    697 {
    698 	int32_t i, error;
    699 	struct ud_part *ud_part;
    700 	struct udf_vfs *udf_vfsp;
    701 
    702 	ud_printf("ud_free_space\n");
    703 
    704 	if (blkcount == 0) {
    705 		return;
    706 	}
    707 
    708 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    709 	ud_part = udf_vfsp->udf_parts;
    710 	for (i = 0; i < udf_vfsp->udf_npart; i++) {
    711 		if (prn == ud_part->udp_number) {
    712 			break;
    713 		}
    714 		ud_part ++;
    715 	}
    716 
    717 	if (i == udf_vfsp->udf_npart) {
    718 		return;
    719 	}
    720 
    721 	if (ud_part->udp_flags == UDP_BITMAPS) {
    722 		error = ud_free_space_bmap(vfsp, ud_part, beginblk, blkcount);
    723 	} else {
    724 		error = ud_free_space_stbl(vfsp, ud_part, beginblk, blkcount);
    725 	}
    726 
    727 	if (error) {
    728 		udf_vfsp->udf_mark_bad = 1;
    729 	}
    730 }
    731 
    732 /*
    733  * If there is a freed table then
    734  * release blocks to the freed table
    735  * other wise release to the un allocated table.
    736  * Findout the offset into the bitmap and
    737  * mark the blocks as free blocks
    738  */
    739 int32_t
    740 ud_free_space_bmap(struct vfs *vfsp,
    741 	struct ud_part *ud_part,
    742 	uint32_t beginblk, uint32_t blkcount)
    743 {
    744 	struct buf *bp;
    745 	struct udf_vfs *udf_vfsp;
    746 	uint32_t block, begin, end, blkno, count, map_end_blk, dummy;
    747 
    748 	ud_printf("ud_free_space_bmap\n");
    749 
    750 	ASSERT(ud_part);
    751 	ASSERT(ud_part->udp_flags == UDP_BITMAPS);
    752 /*
    753  * prom_printf("%x %x\n", udblock, udcount);
    754  */
    755 
    756 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    757 	if ((ud_part->udp_freed_len == 0) &&
    758 		(ud_part->udp_unall_len == 0)) {
    759 		return (ENOSPC);
    760 	}
    761 	/*
    762 	 * decide unallocated/freed table to use
    763 	 */
    764 	if (ud_part->udp_freed_len == 0) {
    765 		begin = ud_part->udp_unall_loc;
    766 		map_end_blk = ud_part->udp_unall_len << 3;
    767 	} else {
    768 		begin = ud_part->udp_freed_loc;
    769 		map_end_blk = ud_part->udp_freed_len << 3;
    770 	}
    771 
    772 	if (beginblk + blkcount > map_end_blk) {
    773 		return (ENOSPC);
    774 	}
    775 
    776 	/* adjust for the bitmap header */
    777 	beginblk += HDR_BLKS;
    778 
    779 	end = begin + ((beginblk + blkcount) / (udf_vfsp->udf_lbsize << 3));
    780 	begin += (beginblk / (udf_vfsp->udf_lbsize << 3));
    781 
    782 	for (block = begin; block <= end; block++) {
    783 
    784 		bp = ud_bread(vfsp->vfs_dev,
    785 			ud_xlate_to_daddr(udf_vfsp,
    786 				ud_part->udp_number, block, 1, &dummy)
    787 				<< udf_vfsp->udf_l2d_shift,
    788 			udf_vfsp->udf_lbsize);
    789 		if (bp->b_flags & B_ERROR) {
    790 			brelse(bp);
    791 			return (EIO);
    792 		}
    793 		ASSERT(dummy == 1);
    794 
    795 		mutex_enter(&udf_vfsp->udf_lock);
    796 
    797 		/*
    798 		 * add freed blocks to the bitmap
    799 		 */
    800 
    801 		blkno = beginblk - (block * (udf_vfsp->udf_lbsize << 3));
    802 		if (blkno + blkcount > (udf_vfsp->udf_lbsize << 3)) {
    803 			count = (udf_vfsp->udf_lbsize << 3) - blkno;
    804 		} else {
    805 			count = blkcount;
    806 		}
    807 
    808 /*
    809  * if (begin != end) {
    810  *	printf("%x %x %x %x %x %x\n",
    811  *		begin, end, block, blkno, count);
    812  *	printf("%x %x %x\n", bp->b_un.b_addr, blkno, count);
    813  * }
    814  */
    815 
    816 		ud_mark_free((uint8_t *)bp->b_un.b_addr, blkno, count);
    817 
    818 		beginblk += count;
    819 		blkcount -= count;
    820 
    821 		if (ud_part->udp_freed_len == 0) {
    822 			ud_part->udp_nfree += count;
    823 			udf_vfsp->udf_freeblks += count;
    824 		}
    825 		mutex_exit(&udf_vfsp->udf_lock);
    826 
    827 		bdwrite(bp);
    828 	}
    829 
    830 	return (0);
    831 }
    832 
    833 
    834 /* ARGSUSED */
    835 /*
    836  * search the entire table if there is
    837  * a entry with which we can merge the
    838  * current entry. Other wise create
    839  * a new entry at the end of the table
    840  */
    841 int32_t
    842 ud_free_space_stbl(struct vfs *vfsp,
    843 	struct ud_part *ud_part,
    844 	uint32_t beginblk, uint32_t blkcount)
    845 {
    846 	uint16_t adesc;
    847 	int32_t error = 0, index, count;
    848 	uint32_t block, dummy, sz;
    849 	struct buf *bp;
    850 	struct udf_vfs *udf_vfsp;
    851 	struct unall_space_ent *use;
    852 
    853 	ud_printf("ud_free_space_stbl\n");
    854 
    855 	ASSERT(ud_part);
    856 	ASSERT(ud_part->udp_flags == UDP_SPACETBLS);
    857 
    858 	if ((ud_part->udp_freed_len == 0) &&
    859 		(ud_part->udp_unall_len == 0)) {
    860 		return (ENOSPC);
    861 	}
    862 
    863 	if (ud_part->udp_freed_len != 0) {
    864 		block = ud_part->udp_freed_loc;
    865 	} else {
    866 		block = ud_part->udp_unall_loc;
    867 	}
    868 
    869 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
    870 	ASSERT((ud_part->udp_unall_len + 40) <= udf_vfsp->udf_lbsize);
    871 
    872 	bp = ud_bread(vfsp->vfs_dev,
    873 			ud_xlate_to_daddr(udf_vfsp, ud_part->udp_number,
    874 				block, 1, &dummy), udf_vfsp->udf_lbsize);
    875 
    876 	use = (struct unall_space_ent *)bp->b_un.b_addr;
    877 	sz = SWAP_32(use->use_len_ad);
    878 	adesc = SWAP_16(use->use_icb_tag.itag_flags) & 0x7;
    879 	if (adesc == ICB_FLAG_SHORT_AD) {
    880 		struct short_ad *sad;
    881 
    882 		sad = (struct short_ad *)use->use_ad;
    883 		count = sz / sizeof (struct short_ad);
    884 		/*
    885 		 * Check if the blocks being freed
    886 		 * are continuous with any of the
    887 		 * existing extents
    888 		 */
    889 		for (index = 0; index < count; index++, sad++) {
    890 			if (beginblk == (SWAP_32(sad->sad_ext_loc) +
    891 					(SWAP_32(sad->sad_ext_len) /
    892 					udf_vfsp->udf_lbsize))) {
    893 				dummy = SWAP_32(sad->sad_ext_len) +
    894 					blkcount * udf_vfsp->udf_lbsize;
    895 				sad->sad_ext_len = SWAP_32(dummy);
    896 				goto end;
    897 			} else if ((beginblk + blkcount) ==
    898 					SWAP_32(sad->sad_ext_loc)) {
    899 				sad->sad_ext_loc = SWAP_32(beginblk);
    900 				goto end;
    901 			}
    902 		}
    903 
    904 		/*
    905 		 * We need to add a new entry
    906 		 * Check if we space.
    907 		 */
    908 		if ((40 + sz + sizeof (struct short_ad)) >
    909 				udf_vfsp->udf_lbsize) {
    910 			error = ENOSPC;
    911 			goto end;
    912 		}
    913 
    914 		/*
    915 		 * We have enough space
    916 		 * just add the entry at the end
    917 		 */
    918 		dummy = SWAP_32(use->use_len_ad);
    919 		sad = (struct short_ad *)&use->use_ad[dummy];
    920 		sz = blkcount * udf_vfsp->udf_lbsize;
    921 		sad->sad_ext_len = SWAP_32(sz);
    922 		sad->sad_ext_loc = SWAP_32(beginblk);
    923 		dummy += sizeof (struct short_ad);
    924 		use->use_len_ad = SWAP_32(dummy);
    925 	} else if (adesc == ICB_FLAG_LONG_AD) {
    926 		struct long_ad *lad;
    927 
    928 		lad = (struct long_ad *)use->use_ad;
    929 		count = sz / sizeof (struct long_ad);
    930 		/*
    931 		 * Check if the blocks being freed
    932 		 * are continuous with any of the
    933 		 * existing extents
    934 		 */
    935 		for (index = 0; index < count; index++, lad++) {
    936 			if (beginblk == (SWAP_32(lad->lad_ext_loc) +
    937 					(SWAP_32(lad->lad_ext_len) /
    938 					udf_vfsp->udf_lbsize))) {
    939 				dummy = SWAP_32(lad->lad_ext_len) +
    940 					blkcount * udf_vfsp->udf_lbsize;
    941 				lad->lad_ext_len = SWAP_32(dummy);
    942 				goto end;
    943 			} else if ((beginblk + blkcount) ==
    944 					SWAP_32(lad->lad_ext_loc)) {
    945 				lad->lad_ext_loc = SWAP_32(beginblk);
    946 				goto end;
    947 			}
    948 		}
    949 
    950 		/*
    951 		 * We need to add a new entry
    952 		 * Check if we space.
    953 		 */
    954 		if ((40 + sz + sizeof (struct long_ad)) >
    955 				udf_vfsp->udf_lbsize) {
    956 			error = ENOSPC;
    957 			goto end;
    958 		}
    959 
    960 		/*
    961 		 * We have enough space
    962 		 * just add the entry at the end
    963 		 */
    964 		dummy = SWAP_32(use->use_len_ad);
    965 		lad = (struct long_ad *)&use->use_ad[dummy];
    966 		sz = blkcount * udf_vfsp->udf_lbsize;
    967 		lad->lad_ext_len = SWAP_32(sz);
    968 		lad->lad_ext_loc = SWAP_32(beginblk);
    969 		lad->lad_ext_prn = SWAP_16(ud_part->udp_number);
    970 		dummy += sizeof (struct long_ad);
    971 		use->use_len_ad = SWAP_32(dummy);
    972 	} else {
    973 		error = ENOSPC;
    974 		goto end;
    975 	}
    976 
    977 end:
    978 	if (!error) {
    979 		bdwrite(bp);
    980 	} else {
    981 		brelse(bp);
    982 	}
    983 	return (error);
    984 }
    985 
    986 /* ARGSUSED */
    987 int32_t
    988 ud_ialloc(struct ud_inode *pip,
    989 	struct ud_inode **ipp, struct vattr *vap, struct cred *cr)
    990 {
    991 	int32_t err;
    992 	uint32_t blkno, size, loc;
    993 	uint32_t imode, ichar, lbsize, ea_len, dummy;
    994 	uint16_t prn, flags;
    995 	struct buf *bp;
    996 	struct file_entry *fe;
    997 	struct timespec32 time;
    998 	struct timespec32 settime;
    999 	struct icb_tag *icb;
   1000 	struct ext_attr_hdr *eah;
   1001 	struct dev_spec_ear *ds;
   1002 	struct udf_vfs *udf_vfsp;
   1003 	timestruc_t now;
   1004 	uid_t uid;
   1005 	gid_t gid;
   1006 
   1007 
   1008 	ASSERT(pip);
   1009 	ASSERT(vap != NULL);
   1010 
   1011 	ud_printf("ud_ialloc\n");
   1012 
   1013 	if (((vap->va_mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) ||
   1014 	    ((vap->va_mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime)))
   1015 		return (EOVERFLOW);
   1016 
   1017 	udf_vfsp = pip->i_udf;
   1018 	lbsize = udf_vfsp->udf_lbsize;
   1019 	prn = pip->i_icb_prn;
   1020 
   1021 	if ((err = ud_alloc_space(pip->i_vfs, prn,
   1022 			0, 1, &blkno, &size, 0, 1)) != 0) {
   1023 		return (err);
   1024 	}
   1025 	loc = ud_xlate_to_daddr(udf_vfsp, prn, blkno, 1, &dummy);
   1026 	ASSERT(dummy == 1);
   1027 
   1028 	bp = ud_bread(pip->i_dev, loc << udf_vfsp->udf_l2d_shift, lbsize);
   1029 	if (bp->b_flags & B_ERROR) {
   1030 		ud_free_space(pip->i_vfs, prn, blkno, size);
   1031 		return (EIO);
   1032 	}
   1033 	bzero(bp->b_un.b_addr, bp->b_bcount);
   1034 	fe = (struct file_entry *)bp->b_un.b_addr;
   1035 
   1036 	uid = crgetuid(cr);
   1037 	fe->fe_uid = SWAP_32(uid);
   1038 
   1039 	/*
   1040 	 * To determine the group-id of the created file:
   1041 	 * 1) If the gid is set in the attribute list (non-Sun & pre-4.0
   1042 	 *	clients are not likely to set the gid), then use it if
   1043 	 *	the process is privileged, belongs to the target group,
   1044 	 *	or the group is the same as the parent directory.
   1045 	 * 2) If the filesystem was not mounted with the Old-BSD-compatible
   1046 	 *	GRPID option, and the directory's set-gid bit is clear,
   1047 	 *	then use the process's gid.
   1048 	 * 3) Otherwise, set the group-id to the gid of the parent directory.
   1049 	 */
   1050 	if ((vap->va_mask & AT_GID) &&
   1051 		((vap->va_gid == pip->i_gid) || groupmember(vap->va_gid, cr) ||
   1052 		secpolicy_vnode_create_gid(cr) == 0)) {
   1053 		/*
   1054 		 * XXX - is this only the case when a 4.0 NFS client, or a
   1055 		 * client derived from that code, makes a call over the wire?
   1056 		 */
   1057 		fe->fe_gid = SWAP_32(vap->va_gid);
   1058 	} else {
   1059 		gid = crgetgid(cr);
   1060 		fe->fe_gid = (pip->i_char & ISGID) ?
   1061 				SWAP_32(pip->i_gid) : SWAP_32(gid);
   1062 	}
   1063 
   1064 	imode = MAKEIMODE(vap->va_type, vap->va_mode);
   1065 	ichar = imode & (VSUID | VSGID | VSVTX);
   1066 	imode = UD_UPERM2DPERM(imode);
   1067 
   1068 	/*
   1069 	 * Under solaris only the owner can
   1070 	 * change the attributes of files so set
   1071 	 * the change attribute bit only for user
   1072 	 */
   1073 	imode |= IATTR;
   1074 
   1075 	/*
   1076 	 * File delete permissions on Solaris are
   1077 	 * the permissions on the directory but not the file
   1078 	 * when we create a file just inherit the directorys
   1079 	 * write permission to be the file delete permissions
   1080 	 * Atleast we will be consistent in the files we create
   1081 	 */
   1082 	imode |= (pip->i_perm & (IWRITE | IWRITE >> 5 | IWRITE >> 10)) << 3;
   1083 
   1084 	fe->fe_perms = SWAP_32(imode);
   1085 
   1086 	/*
   1087 	 * udf does not have a "." entry in dir's
   1088 	 * so even directories have only one link
   1089 	 */
   1090 	fe->fe_lcount = SWAP_16(1);
   1091 
   1092 	fe->fe_info_len = 0;
   1093 	fe->fe_lbr = 0;
   1094 
   1095 	gethrestime(&now);
   1096 	time.tv_sec = now.tv_sec;
   1097 	time.tv_nsec = now.tv_nsec;
   1098 	if (vap->va_mask & AT_ATIME) {
   1099 		TIMESPEC_TO_TIMESPEC32(&settime, &vap->va_atime)
   1100 		ud_utime2dtime(&settime, &fe->fe_acc_time);
   1101 	} else
   1102 		ud_utime2dtime(&time, &fe->fe_acc_time);
   1103 	if (vap->va_mask & AT_MTIME) {
   1104 		TIMESPEC_TO_TIMESPEC32(&settime, &vap->va_mtime)
   1105 		ud_utime2dtime(&settime, &fe->fe_mod_time);
   1106 	} else
   1107 		ud_utime2dtime(&time, &fe->fe_mod_time);
   1108 	ud_utime2dtime(&time, &fe->fe_attr_time);
   1109 
   1110 	ud_update_regid(&fe->fe_impl_id);
   1111 
   1112 	mutex_enter(&udf_vfsp->udf_lock);
   1113 	fe->fe_uniq_id = SWAP_64(udf_vfsp->udf_maxuniq);
   1114 	udf_vfsp->udf_maxuniq++;
   1115 	mutex_exit(&udf_vfsp->udf_lock);
   1116 
   1117 	ea_len = 0;
   1118 	if ((vap->va_type == VBLK) ||
   1119 		(vap->va_type == VCHR)) {
   1120 		eah = (struct ext_attr_hdr *)fe->fe_spec;
   1121 		ea_len = (sizeof (struct ext_attr_hdr) + 3) & ~3;
   1122 		eah->eah_ial = SWAP_32(ea_len);
   1123 
   1124 		ds = (struct dev_spec_ear *)&fe->fe_spec[ea_len];
   1125 		ea_len += ud_make_dev_spec_ear(ds,
   1126 			getmajor(vap->va_rdev), getminor(vap->va_rdev));
   1127 		ea_len = (ea_len + 3) & ~3;
   1128 		eah->eah_aal = SWAP_32(ea_len);
   1129 		ud_make_tag(udf_vfsp, &eah->eah_tag,
   1130 			UD_EXT_ATTR_HDR, blkno, ea_len);
   1131 	}
   1132 
   1133 	fe->fe_len_ear = SWAP_32(ea_len);
   1134 	fe->fe_len_adesc = 0;
   1135 
   1136 	icb = &fe->fe_icb_tag;
   1137 	icb->itag_prnde = 0;
   1138 	icb->itag_strategy = SWAP_16(STRAT_TYPE4);
   1139 	icb->itag_param = 0;
   1140 	icb->itag_max_ent = SWAP_16(1);
   1141 	switch (vap->va_type) {
   1142 		case VREG :
   1143 			icb->itag_ftype = FTYPE_FILE;
   1144 			break;
   1145 		case VDIR :
   1146 			icb->itag_ftype = FTYPE_DIRECTORY;
   1147 			break;
   1148 		case VBLK :
   1149 			icb->itag_ftype = FTYPE_BLOCK_DEV;
   1150 			break;
   1151 		case VCHR :
   1152 			icb->itag_ftype = FTYPE_CHAR_DEV;
   1153 			break;
   1154 		case VLNK :
   1155 			icb->itag_ftype = FTYPE_SYMLINK;
   1156 			break;
   1157 		case VFIFO :
   1158 			icb->itag_ftype = FTYPE_FIFO;
   1159 			break;
   1160 		case VSOCK :
   1161 			icb->itag_ftype = FTYPE_C_ISSOCK;
   1162 			break;
   1163 		default :
   1164 			brelse(bp);
   1165 			goto error;
   1166 	}
   1167 	icb->itag_lb_loc = 0;
   1168 	icb->itag_lb_prn = 0;
   1169 	flags = ICB_FLAG_ONE_AD;
   1170 	if ((pip->i_char & ISGID) && (vap->va_type == VDIR)) {
   1171 		ichar |= ISGID;
   1172 	} else {
   1173 		if ((ichar & ISGID) &&
   1174 		    secpolicy_vnode_setids_setgids(cr,
   1175 			    (gid_t)SWAP_32(fe->fe_gid)) != 0) {
   1176 			ichar &= ~ISGID;
   1177 		}
   1178 	}
   1179 	if (ichar & ISUID) {
   1180 		flags |= ICB_FLAG_SETUID;
   1181 	}
   1182 	if (ichar & ISGID) {
   1183 		flags |= ICB_FLAG_SETGID;
   1184 	}
   1185 	if (ichar & ISVTX) {
   1186 		flags |= ICB_FLAG_STICKY;
   1187 	}
   1188 	icb->itag_flags = SWAP_16(flags);
   1189 	ud_make_tag(udf_vfsp, &fe->fe_tag, UD_FILE_ENTRY, blkno,
   1190 		((uint32_t)&((struct file_entry *)0)->fe_spec) +
   1191 			SWAP_32(fe->fe_len_ear) + SWAP_32(fe->fe_len_adesc));
   1192 
   1193 	BWRITE2(bp);
   1194 
   1195 	mutex_enter(&udf_vfsp->udf_lock);
   1196 	if (vap->va_type == VDIR) {
   1197 		udf_vfsp->udf_ndirs++;
   1198 	} else {
   1199 		udf_vfsp->udf_nfiles++;
   1200 	}
   1201 	mutex_exit(&udf_vfsp->udf_lock);
   1202 
   1203 #ifdef	DEBUG
   1204 	{
   1205 		struct ud_inode *ip;
   1206 
   1207 		if ((ip = ud_search_icache(pip->i_vfs, prn, blkno)) != NULL) {
   1208 			cmn_err(CE_NOTE, "duplicate %p %x\n",
   1209 				(void *)ip, (uint32_t)ip->i_icb_lbano);
   1210 		}
   1211 	}
   1212 #endif
   1213 
   1214 	if ((err = ud_iget(pip->i_vfs, prn, blkno, ipp, bp, cr)) != 0) {
   1215 error:
   1216 		ud_free_space(pip->i_vfs, prn, blkno, size);
   1217 		return (err);
   1218 	}
   1219 
   1220 	return (0);
   1221 
   1222 noinodes:
   1223 	cmn_err(CE_NOTE, "%s: out of inodes\n", pip->i_udf->udf_volid);
   1224 	return (ENOSPC);
   1225 }
   1226 
   1227 
   1228 void
   1229 ud_ifree(struct ud_inode *ip, vtype_t type)
   1230 {
   1231 	struct udf_vfs *udf_vfsp;
   1232 	struct buf *bp;
   1233 
   1234 	ud_printf("ud_ifree\n");
   1235 
   1236 	if (ip->i_vfs == NULL) {
   1237 		return;
   1238 	}
   1239 
   1240 	udf_vfsp = (struct udf_vfs *)ip->i_vfs->vfs_data;
   1241 	bp = ud_bread(ip->i_dev, ip->i_icb_lbano <<
   1242 			udf_vfsp->udf_l2d_shift,
   1243 			udf_vfsp->udf_lbsize);
   1244 	if (bp->b_flags & B_ERROR) {
   1245 		/*
   1246 		 * Error get rid of bp
   1247 		 */
   1248 		brelse(bp);
   1249 	} else {
   1250 		/*
   1251 		 * Just trash the inode
   1252 		 */
   1253 		bzero(bp->b_un.b_addr, 0x10);
   1254 		BWRITE(bp);
   1255 	}
   1256 	ud_free_space(ip->i_vfs, ip->i_icb_prn,
   1257 		ip->i_icb_block, 1);
   1258 	mutex_enter(&udf_vfsp->udf_lock);
   1259 	if (type == VDIR) {
   1260 		if (udf_vfsp->udf_ndirs > 1) {
   1261 			udf_vfsp->udf_ndirs--;
   1262 		}
   1263 	} else {
   1264 		if (udf_vfsp->udf_nfiles > 0) {
   1265 			udf_vfsp->udf_nfiles --;
   1266 		}
   1267 	}
   1268 	mutex_exit(&udf_vfsp->udf_lock);
   1269 }
   1270 
   1271 
   1272 /*
   1273  * Free storage space associated with the specified inode.  The portion
   1274  * to be freed is specified by lp->l_start and lp->l_len (already
   1275  * normalized to a "whence" of 0).
   1276  *
   1277  * This is an experimental facility whose continued existence is not
   1278  * guaranteed.  Currently, we only support the special case
   1279  * of l_len == 0, meaning free to end of file.
   1280  *
   1281  * Blocks are freed in reverse order.  This FILO algorithm will tend to
   1282  * maintain a contiguous free list much longer than FIFO.
   1283  * See also ufs_itrunc() in ufs_inode.c.
   1284  *
   1285  * Bug: unused bytes in the last retained block are not cleared.
   1286  * This may result in a "hole" in the file that does not read as zeroes.
   1287  */
   1288 int32_t
   1289 ud_freesp(struct vnode *vp,
   1290 	struct flock64 *lp,
   1291 	int32_t flag, struct cred *cr)
   1292 {
   1293 	int32_t i;
   1294 	struct ud_inode *ip = VTOI(vp);
   1295 	int32_t error;
   1296 
   1297 	ASSERT(vp->v_type == VREG);
   1298 	ASSERT(lp->l_start >= (offset_t)0);	/* checked by convoff */
   1299 
   1300 	ud_printf("udf_freesp\n");
   1301 
   1302 	if (lp->l_len != 0) {
   1303 		return (EINVAL);
   1304 	}
   1305 
   1306 	rw_enter(&ip->i_contents, RW_READER);
   1307 	if (ip->i_size == (u_offset_t)lp->l_start) {
   1308 		rw_exit(&ip->i_contents);
   1309 		return (0);
   1310 	}
   1311 
   1312 	/*
   1313 	 * Check if there is any active mandatory lock on the
   1314 	 * range that will be truncated/expanded.
   1315 	 */
   1316 	if (MANDLOCK(vp, ip->i_char)) {
   1317 		offset_t save_start;
   1318 
   1319 		save_start = lp->l_start;
   1320 
   1321 		if (ip->i_size < lp->l_start) {
   1322 			/*
   1323 			 * "Truncate up" case: need to make sure there
   1324 			 * is no lock beyond current end-of-file. To
   1325 			 * do so, we need to set l_start to the size
   1326 			 * of the file temporarily.
   1327 			 */
   1328 			lp->l_start = ip->i_size;
   1329 		}
   1330 		lp->l_type = F_WRLCK;
   1331 		lp->l_sysid = 0;
   1332 		lp->l_pid = ttoproc(curthread)->p_pid;
   1333 		i = (flag & (FNDELAY|FNONBLOCK)) ? 0 : SLPFLCK;
   1334 		rw_exit(&ip->i_contents);
   1335 		if ((i = reclock(vp, lp, i, 0, lp->l_start, NULL)) != 0 ||
   1336 		    lp->l_type != F_UNLCK) {
   1337 			return (i ? i : EAGAIN);
   1338 		}
   1339 		rw_enter(&ip->i_contents, RW_READER);
   1340 
   1341 		lp->l_start = save_start;
   1342 	}
   1343 	/*
   1344 	 * Make sure a write isn't in progress (allocating blocks)
   1345 	 * by acquiring i_rwlock (we promised ufs_bmap we wouldn't
   1346 	 * truncate while it was allocating blocks).
   1347 	 * Grab the locks in the right order.
   1348 	 */
   1349 	rw_exit(&ip->i_contents);
   1350 	rw_enter(&ip->i_rwlock, RW_WRITER);
   1351 	rw_enter(&ip->i_contents, RW_WRITER);
   1352 	error = ud_itrunc(ip, lp->l_start, 0, cr);
   1353 	rw_exit(&ip->i_contents);
   1354 	rw_exit(&ip->i_rwlock);
   1355 	return (error);
   1356 }
   1357 
   1358 
   1359 
   1360 /*
   1361  * Cache is implemented by
   1362  * allocating a cluster of blocks
   1363  */
   1364 int32_t
   1365 ud_alloc_from_cache(struct udf_vfs *udf_vfsp,
   1366 	struct ud_part *part, uint32_t *blkno)
   1367 {
   1368 	uint32_t bno, sz;
   1369 	int32_t error, index, free = 0;
   1370 
   1371 	ud_printf("ud_alloc_from_cache\n");
   1372 
   1373 	ASSERT(udf_vfsp);
   1374 
   1375 	mutex_enter(&udf_vfsp->udf_lock);
   1376 	if (part->udp_cache_count == 0) {
   1377 		mutex_exit(&udf_vfsp->udf_lock);
   1378 		/* allocate new cluster */
   1379 		if ((error = ud_alloc_space(udf_vfsp->udf_vfs,
   1380 				part->udp_number, 0, CLSTR_SIZE,
   1381 				&bno, &sz, 1, 0)) != 0) {
   1382 			return (error);
   1383 		}
   1384 		if (sz == 0) {
   1385 			return (ENOSPC);
   1386 		}
   1387 		mutex_enter(&udf_vfsp->udf_lock);
   1388 		if (part->udp_cache_count == 0) {
   1389 			for (index = 0; index < sz; index++, bno++) {
   1390 				part->udp_cache[index] = bno;
   1391 			}
   1392 			part->udp_cache_count = sz;
   1393 		} else {
   1394 			free = 1;
   1395 		}
   1396 	}
   1397 	part->udp_cache_count--;
   1398 	*blkno = part->udp_cache[part->udp_cache_count];
   1399 	mutex_exit(&udf_vfsp->udf_lock);
   1400 	if (free) {
   1401 		ud_free_space(udf_vfsp->udf_vfs, part->udp_number, bno, sz);
   1402 	}
   1403 	return (0);
   1404 }
   1405 
   1406 /*
   1407  * Will be called from unmount
   1408  */
   1409 int32_t
   1410 ud_release_cache(struct udf_vfs *udf_vfsp)
   1411 {
   1412 	int32_t i, error = 0;
   1413 	struct ud_part *part;
   1414 	uint32_t start, nblks;
   1415 
   1416 	ud_printf("ud_release_cache\n");
   1417 
   1418 	mutex_enter(&udf_vfsp->udf_lock);
   1419 	part = udf_vfsp->udf_parts;
   1420 	for (i = 0; i < udf_vfsp->udf_npart; i++, part++) {
   1421 		if (part->udp_cache_count) {
   1422 			nblks = part->udp_cache_count;
   1423 			start = part->udp_cache[0];
   1424 			part->udp_cache_count = 0;
   1425 			mutex_exit(&udf_vfsp->udf_lock);
   1426 			ud_free_space(udf_vfsp->udf_vfs,
   1427 				part->udp_number, start, nblks);
   1428 			mutex_enter(&udf_vfsp->udf_lock);
   1429 		}
   1430 	}
   1431 	mutex_exit(&udf_vfsp->udf_lock);
   1432 	return (error);
   1433 }
   1434