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