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