1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/mode.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/flock.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/dnlc.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/fbuf.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #include <vm/hat.h> 69*7c478bd9Sstevel@tonic-gate #include <vm/page.h> 70*7c478bd9Sstevel@tonic-gate #include <vm/pvn.h> 71*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 72*7c478bd9Sstevel@tonic-gate #include <vm/seg.h> 73*7c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 74*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 75*7c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h> 76*7c478bd9Sstevel@tonic-gate #include <vm/rm.h> 77*7c478bd9Sstevel@tonic-gate #include <vm/page.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/swap.h> 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h> 85*7c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h> 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate int32_t ud_break_create_new_icb(struct ud_inode *, int32_t, uint32_t); 89*7c478bd9Sstevel@tonic-gate int32_t ud_bump_ext_count(struct ud_inode *, int32_t); 90*7c478bd9Sstevel@tonic-gate void ud_remove_ext_at_index(struct ud_inode *, int32_t); 91*7c478bd9Sstevel@tonic-gate int32_t ud_last_alloc_ext(struct ud_inode *, uint64_t, uint32_t, int32_t); 92*7c478bd9Sstevel@tonic-gate int32_t ud_create_ext(struct ud_inode *, int32_t, uint32_t, 93*7c478bd9Sstevel@tonic-gate int32_t, uint64_t, uint64_t *); 94*7c478bd9Sstevel@tonic-gate int32_t ud_zero_it(struct ud_inode *, uint32_t, uint32_t); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate #define ALLOC_SPACE 0x01 97*7c478bd9Sstevel@tonic-gate #define NEW_EXT 0x02 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #define MEXT_BITS 30 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate int32_t 102*7c478bd9Sstevel@tonic-gate ud_bmap_has_holes(struct ud_inode *ip) 103*7c478bd9Sstevel@tonic-gate { 104*7c478bd9Sstevel@tonic-gate int32_t i, error = 0; 105*7c478bd9Sstevel@tonic-gate struct icb_ext *iext; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate ud_printf("ud_bmap_has_holes\n"); 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate ASSERT(RW_LOCK_HELD(&ip->i_contents)); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* ICB_FLAG_ONE_AD is always continuos */ 112*7c478bd9Sstevel@tonic-gate if (ip->i_desc_type != ICB_FLAG_ONE_AD) { 113*7c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, ip->i_size)) == 0) { 114*7c478bd9Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) { 115*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 116*7c478bd9Sstevel@tonic-gate if (iext->ib_flags == IB_UN_RE_AL) { 117*7c478bd9Sstevel@tonic-gate error = 1; 118*7c478bd9Sstevel@tonic-gate break; 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate return (error); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate int32_t 128*7c478bd9Sstevel@tonic-gate ud_bmap_read(struct ud_inode *ip, u_offset_t off, daddr_t *bnp, int32_t *lenp) 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate struct icb_ext *iext; 131*7c478bd9Sstevel@tonic-gate daddr_t bno; 132*7c478bd9Sstevel@tonic-gate int32_t lbmask, i, l2b, l2d, error = 0, count; 133*7c478bd9Sstevel@tonic-gate uint32_t length, block, dummy; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate ud_printf("ud_bmap_read\n"); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate ASSERT(RW_LOCK_HELD(&ip->i_contents)); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate lbmask = ip->i_udf->udf_lbmask; 140*7c478bd9Sstevel@tonic-gate l2b = ip->i_udf->udf_l2b_shift; 141*7c478bd9Sstevel@tonic-gate l2d = ip->i_udf->udf_l2d_shift; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, ip->i_size)) == 0) { 144*7c478bd9Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) { 145*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 146*7c478bd9Sstevel@tonic-gate if ((iext->ib_offset <= off) && 147*7c478bd9Sstevel@tonic-gate (off < (iext->ib_offset + iext->ib_count))) { 148*7c478bd9Sstevel@tonic-gate length = ((iext->ib_offset + 149*7c478bd9Sstevel@tonic-gate iext->ib_count - off) + 150*7c478bd9Sstevel@tonic-gate lbmask) & ~lbmask; 151*7c478bd9Sstevel@tonic-gate if (iext->ib_flags == IB_UN_RE_AL) { 152*7c478bd9Sstevel@tonic-gate *bnp = UDF_HOLE; 153*7c478bd9Sstevel@tonic-gate *lenp = length; 154*7c478bd9Sstevel@tonic-gate break; 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate block = iext->ib_block + 158*7c478bd9Sstevel@tonic-gate ((off - iext->ib_offset) >> l2b); 159*7c478bd9Sstevel@tonic-gate count = length >> l2b; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate bno = ud_xlate_to_daddr(ip->i_udf, 162*7c478bd9Sstevel@tonic-gate iext->ib_prn, block, count, &dummy); 163*7c478bd9Sstevel@tonic-gate ASSERT(dummy != 0); 164*7c478bd9Sstevel@tonic-gate ASSERT(dummy <= count); 165*7c478bd9Sstevel@tonic-gate *bnp = bno << l2d; 166*7c478bd9Sstevel@tonic-gate *lenp = dummy << l2b; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate break; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate if (i == ip->i_ext_used) { 172*7c478bd9Sstevel@tonic-gate error = EINVAL; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate return (error); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Extent allocation in the inode 182*7c478bd9Sstevel@tonic-gate * Initially when the inode is allocated we 183*7c478bd9Sstevel@tonic-gate * will allocate EXT_PER_MALLOC extents and once these 184*7c478bd9Sstevel@tonic-gate * are used we allocate another 10 and copy 185*7c478bd9Sstevel@tonic-gate * the old extents and start using the others 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate #define BASE(count) ((count) & ~lbmask) 188*7c478bd9Sstevel@tonic-gate #define CEIL(count) (((count) + lbmask) & ~lbmask) 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate #define PBASE(count) ((count) & PAGEMASK) 191*7c478bd9Sstevel@tonic-gate #define PCEIL(count) (((count) + PAGEOFFSET) & PAGEMASK) 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 195*7c478bd9Sstevel@tonic-gate int32_t 196*7c478bd9Sstevel@tonic-gate ud_bmap_write(struct ud_inode *ip, 197*7c478bd9Sstevel@tonic-gate u_offset_t off, int32_t size, int32_t alloc_only, struct cred *cr) 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate int32_t error = 0, i, isdir, issync; 200*7c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 201*7c478bd9Sstevel@tonic-gate struct icb_ext *iext, *pext; 202*7c478bd9Sstevel@tonic-gate uint32_t blkno, sz; 203*7c478bd9Sstevel@tonic-gate u_offset_t isize; 204*7c478bd9Sstevel@tonic-gate uint32_t acount, prox; 205*7c478bd9Sstevel@tonic-gate int32_t blkcount, next; 206*7c478bd9Sstevel@tonic-gate int32_t lbmask, l2b; 207*7c478bd9Sstevel@tonic-gate uint64_t end_req, end_ext, mext_sz, icb_offset, count; 208*7c478bd9Sstevel@tonic-gate int32_t dtype_changed = 0, memory_allocated = 0; 209*7c478bd9Sstevel@tonic-gate struct fbuf *fbp = NULL; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate ud_printf("ud_bmap_write\n"); 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ip->i_contents)); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 217*7c478bd9Sstevel@tonic-gate lbmask = udf_vfsp->udf_lbmask; 218*7c478bd9Sstevel@tonic-gate l2b = udf_vfsp->udf_l2b_shift; 219*7c478bd9Sstevel@tonic-gate mext_sz = (1 << MEXT_BITS) - PAGESIZE; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (lblkno(udf_vfsp, off) < 0) { 222*7c478bd9Sstevel@tonic-gate return (EFBIG); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate issync = ((ip->i_flag & ISYNC) != 0); 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate isdir = (ip->i_type == VDIR); 228*7c478bd9Sstevel@tonic-gate if (isdir || issync) { 229*7c478bd9Sstevel@tonic-gate alloc_only = 0; /* make sure */ 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate end_req = BASE(off) + size; 233*7c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 234*7c478bd9Sstevel@tonic-gate if (end_req < ip->i_max_emb) { 235*7c478bd9Sstevel@tonic-gate goto out; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate if (ip->i_size != 0) { 239*7c478bd9Sstevel@tonic-gate error = fbread(ITOV(ip), 0, ip->i_size, S_OTHER, &fbp); 240*7c478bd9Sstevel@tonic-gate if (error != 0) { 241*7c478bd9Sstevel@tonic-gate goto out; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate } else { 244*7c478bd9Sstevel@tonic-gate fbp = NULL; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Change the desc_type 248*7c478bd9Sstevel@tonic-gate */ 249*7c478bd9Sstevel@tonic-gate ip->i_desc_type = ICB_FLAG_SHORT_AD; 250*7c478bd9Sstevel@tonic-gate dtype_changed = 1; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate one_ad_no_i_ext: 253*7c478bd9Sstevel@tonic-gate ASSERT(ip->i_ext == NULL); 254*7c478bd9Sstevel@tonic-gate ASSERT(ip->i_astrat == STRAT_TYPE4); 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate ip->i_ext_used = 0; 257*7c478bd9Sstevel@tonic-gate ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct short_ad); 258*7c478bd9Sstevel@tonic-gate ip->i_cur_max_ext --; 259*7c478bd9Sstevel@tonic-gate if (end_req > mext_sz) { 260*7c478bd9Sstevel@tonic-gate next = end_req / mext_sz; 261*7c478bd9Sstevel@tonic-gate } else { 262*7c478bd9Sstevel@tonic-gate next = 1; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate ip->i_ext_count = 265*7c478bd9Sstevel@tonic-gate ((next / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC; 266*7c478bd9Sstevel@tonic-gate iext = ip->i_ext = (struct icb_ext *)kmem_zalloc( 267*7c478bd9Sstevel@tonic-gate ip->i_ext_count * sizeof (struct icb_ext), KM_SLEEP); 268*7c478bd9Sstevel@tonic-gate memory_allocated = 1; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* There will be atleast EXT_PER_MALLOC icb_ext's allocated */ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate one_ad_i_ext: 273*7c478bd9Sstevel@tonic-gate icb_offset = 0; 274*7c478bd9Sstevel@tonic-gate count = end_req; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* Can we create a HOLE */ 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if ((PCEIL(ip->i_size) < PBASE(off)) && 279*7c478bd9Sstevel@tonic-gate ((PBASE(off) - PCEIL(ip->i_size)) >= PAGESIZE)) { 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate if (ip->i_size != 0) { 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * Allocate one block for 285*7c478bd9Sstevel@tonic-gate * old data.(cannot be more than one page) 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate count = PAGESIZE; 289*7c478bd9Sstevel@tonic-gate if (error = ud_create_ext(ip, ip->i_ext_used, 290*7c478bd9Sstevel@tonic-gate ALLOC_SPACE | NEW_EXT, alloc_only, 291*7c478bd9Sstevel@tonic-gate icb_offset, &count)) { 292*7c478bd9Sstevel@tonic-gate goto embedded_error; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate icb_offset = PAGESIZE; 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* 298*7c478bd9Sstevel@tonic-gate * Allocate a hole from PCEIL(ip->i_size) to PBASE(off) 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate count = PBASE(off) - PCEIL(ip->i_size); 302*7c478bd9Sstevel@tonic-gate (void) ud_create_ext(ip, ip->i_ext_used, NEW_EXT, 303*7c478bd9Sstevel@tonic-gate alloc_only, icb_offset, &count); 304*7c478bd9Sstevel@tonic-gate icb_offset = PBASE(off); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * Allocate the rest of the space PBASE(off) to end_req 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate count = end_req - PBASE(off); 310*7c478bd9Sstevel@tonic-gate } else { 311*7c478bd9Sstevel@tonic-gate /* 312*7c478bd9Sstevel@tonic-gate * If no hole can be created then allocate 313*7c478bd9Sstevel@tonic-gate * space till the end of the request 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate count = end_req; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (error = ud_create_ext(ip, ip->i_ext_used, 321*7c478bd9Sstevel@tonic-gate ALLOC_SPACE | NEW_EXT, 322*7c478bd9Sstevel@tonic-gate alloc_only, icb_offset, &count)) { 323*7c478bd9Sstevel@tonic-gate embedded_error: 324*7c478bd9Sstevel@tonic-gate /* 325*7c478bd9Sstevel@tonic-gate * Something error 326*7c478bd9Sstevel@tonic-gate * most probable file system is full 327*7c478bd9Sstevel@tonic-gate * we know that the file came in as a embedded file. 328*7c478bd9Sstevel@tonic-gate * undo what ever we did in this block of code 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate if (dtype_changed) { 331*7c478bd9Sstevel@tonic-gate ip->i_desc_type = ICB_FLAG_ONE_AD; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) { 334*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 335*7c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 336*7c478bd9Sstevel@tonic-gate ud_free_space(ip->i_udf->udf_vfs, 337*7c478bd9Sstevel@tonic-gate iext->ib_prn, iext->ib_block, 338*7c478bd9Sstevel@tonic-gate (iext->ib_count + lbmask) >> 339*7c478bd9Sstevel@tonic-gate l2b); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate if (memory_allocated) { 343*7c478bd9Sstevel@tonic-gate kmem_free(ip->i_ext, 344*7c478bd9Sstevel@tonic-gate ip->i_ext_count * 345*7c478bd9Sstevel@tonic-gate sizeof (struct icb_ext)); 346*7c478bd9Sstevel@tonic-gate ip->i_ext = NULL; 347*7c478bd9Sstevel@tonic-gate ip->i_ext_count = ip->i_ext_used = 0; 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (fbp != NULL) { 352*7c478bd9Sstevel@tonic-gate fbrelse(fbp, S_WRITE); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate return (error); 356*7c478bd9Sstevel@tonic-gate } else { 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * Type 4 directories being created 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate if (ip->i_ext == NULL) { 362*7c478bd9Sstevel@tonic-gate goto one_ad_no_i_ext; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Read the entire icb's to memory 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate if (ud_read_icb_till_off(ip, ip->i_size) != 0) { 369*7c478bd9Sstevel@tonic-gate error = EINVAL; 370*7c478bd9Sstevel@tonic-gate goto out; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate isize = CEIL(ip->i_size); 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if (end_req > isize) { 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * The new file size is greater 379*7c478bd9Sstevel@tonic-gate * than the old size 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if (ip->i_ext == NULL) { 383*7c478bd9Sstevel@tonic-gate goto one_ad_no_i_ext; 384*7c478bd9Sstevel@tonic-gate } else if (ip->i_ext_used == 0) { 385*7c478bd9Sstevel@tonic-gate goto one_ad_i_ext; 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate error = ud_last_alloc_ext(ip, off, size, alloc_only); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate return (error); 391*7c478bd9Sstevel@tonic-gate } else { 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * File growing the new size will be less than 395*7c478bd9Sstevel@tonic-gate * iext->ib_offset + CEIL(iext->ib_count) 396*7c478bd9Sstevel@tonic-gate */ 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate if (end_req > (iext->ib_offset + iext->ib_count)) { 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate iext->ib_count = end_req - iext->ib_offset; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 405*7c478bd9Sstevel@tonic-gate error = 0; 406*7c478bd9Sstevel@tonic-gate goto out; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate /* By this point the end of last extent is >= BASE(off) + size */ 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate ASSERT(ip->i_ext); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * Figure out the icb_ext that has offset "off" 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) { 420*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 421*7c478bd9Sstevel@tonic-gate if ((iext->ib_offset <= off) && 422*7c478bd9Sstevel@tonic-gate ((iext->ib_offset + iext->ib_count) > off)) { 423*7c478bd9Sstevel@tonic-gate break; 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * iext will have offset "off" 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate do { 433*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if ((iext->ib_flags & IB_UN_RE_AL) == 0) { 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * Already allocated do nothing 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate i++; 442*7c478bd9Sstevel@tonic-gate } else { 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * We are in a hole. 446*7c478bd9Sstevel@tonic-gate * allocate the required space 447*7c478bd9Sstevel@tonic-gate * while trying to create smaller holes 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate if ((PBASE(off) > PBASE(iext->ib_offset)) && 451*7c478bd9Sstevel@tonic-gate ((PBASE(off) - PBASE(iext->ib_offset)) >= 452*7c478bd9Sstevel@tonic-gate PAGESIZE)) { 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * Allocate space from begining of 456*7c478bd9Sstevel@tonic-gate * old hole to the begining of new hole 457*7c478bd9Sstevel@tonic-gate * We want all holes created by us 458*7c478bd9Sstevel@tonic-gate * to be MMUPAGE Aligned 459*7c478bd9Sstevel@tonic-gate */ 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate if (PBASE(iext->ib_offset) != 462*7c478bd9Sstevel@tonic-gate BASE(iext->ib_offset)) { 463*7c478bd9Sstevel@tonic-gate if ((error = ud_break_create_new_icb( 464*7c478bd9Sstevel@tonic-gate ip, i, BASE(iext->ib_offset) - 465*7c478bd9Sstevel@tonic-gate PBASE(iext->ib_offset))) != 0) { 466*7c478bd9Sstevel@tonic-gate return (error); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate goto alloc_cur_ext; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * Create the new hole 473*7c478bd9Sstevel@tonic-gate */ 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate if ((error = ud_break_create_new_icb(ip, i, 476*7c478bd9Sstevel@tonic-gate PBASE(off) - iext->ib_offset)) != 0) { 477*7c478bd9Sstevel@tonic-gate return (error); 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 480*7c478bd9Sstevel@tonic-gate i++; 481*7c478bd9Sstevel@tonic-gate continue; 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate end_ext = iext->ib_offset + iext->ib_count; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if ((PBASE(end_ext) > PCEIL(end_req)) && 487*7c478bd9Sstevel@tonic-gate ((PBASE(end_ext) - PCEIL(end_req)) >= 488*7c478bd9Sstevel@tonic-gate PAGESIZE)) { 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * We can create a hole 491*7c478bd9Sstevel@tonic-gate * from PCEIL(end_req) - BASE(end_ext) 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate if ((error = ud_break_create_new_icb(ip, i, 494*7c478bd9Sstevel@tonic-gate PCEIL(end_req) - iext->ib_offset)) != 0) { 495*7c478bd9Sstevel@tonic-gate return (error); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate alloc_cur_ext: 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * Allocate the current extent 503*7c478bd9Sstevel@tonic-gate */ 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * If the previous extent 508*7c478bd9Sstevel@tonic-gate * is allocated then try to allocate 509*7c478bd9Sstevel@tonic-gate * adjascent to the previous extent 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate prox = 0; 512*7c478bd9Sstevel@tonic-gate if (i != 0) { 513*7c478bd9Sstevel@tonic-gate pext = &ip->i_ext[i - 1]; 514*7c478bd9Sstevel@tonic-gate if (pext->ib_flags != IB_UN_RE_AL) { 515*7c478bd9Sstevel@tonic-gate prox = pext->ib_block + 516*7c478bd9Sstevel@tonic-gate (CEIL(pext->ib_count) >> l2b); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 521*7c478bd9Sstevel@tonic-gate blkcount = CEIL(iext->ib_count) >> l2b; 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate if ((error = ud_alloc_space(ip->i_vfs, 524*7c478bd9Sstevel@tonic-gate ip->i_icb_prn, prox, blkcount, 525*7c478bd9Sstevel@tonic-gate &blkno, &sz, 1, 0)) != 0) { 526*7c478bd9Sstevel@tonic-gate return (error); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate ip->i_lbr += sz; 529*7c478bd9Sstevel@tonic-gate if (sz == 0) { 530*7c478bd9Sstevel@tonic-gate return (ENOSPC); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate if (alloc_only == 0) { 534*7c478bd9Sstevel@tonic-gate error = ud_zero_it(ip, blkno, sz); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate acount = sz << l2b; 538*7c478bd9Sstevel@tonic-gate if ((prox == blkno) && 539*7c478bd9Sstevel@tonic-gate ((pext->ib_count + acount) < mext_sz)) { 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * We are able to allocate adjascent to 543*7c478bd9Sstevel@tonic-gate * the previous extent. Increment the 544*7c478bd9Sstevel@tonic-gate * previous extent count if the size 545*7c478bd9Sstevel@tonic-gate * of the extent is not greater than 546*7c478bd9Sstevel@tonic-gate * max extent size 547*7c478bd9Sstevel@tonic-gate */ 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate pext = &ip->i_ext[i - 1]; 550*7c478bd9Sstevel@tonic-gate pext->ib_count += acount; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate if (sz == blkcount) { 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * and get rid of the current 555*7c478bd9Sstevel@tonic-gate * extent since we have 556*7c478bd9Sstevel@tonic-gate * allocated all of its size 557*7c478bd9Sstevel@tonic-gate * and incremented the 558*7c478bd9Sstevel@tonic-gate * previous extents count 559*7c478bd9Sstevel@tonic-gate */ 560*7c478bd9Sstevel@tonic-gate ud_remove_ext_at_index(ip, i); 561*7c478bd9Sstevel@tonic-gate } else { 562*7c478bd9Sstevel@tonic-gate /* 563*7c478bd9Sstevel@tonic-gate * reduce the count of the 564*7c478bd9Sstevel@tonic-gate * current extent by the amount 565*7c478bd9Sstevel@tonic-gate * allocated in the last extent 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate ASSERT(acount < iext->ib_count); 568*7c478bd9Sstevel@tonic-gate iext->ib_count -= acount; 569*7c478bd9Sstevel@tonic-gate iext->ib_offset += acount; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate } else { 572*7c478bd9Sstevel@tonic-gate if (sz < blkcount) { 573*7c478bd9Sstevel@tonic-gate if ((error = ud_break_create_new_icb( 574*7c478bd9Sstevel@tonic-gate ip, i, sz << l2b)) != 0) { 575*7c478bd9Sstevel@tonic-gate return (error); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 579*7c478bd9Sstevel@tonic-gate count -= CEIL(iext->ib_count); 580*7c478bd9Sstevel@tonic-gate iext->ib_prn = ip->i_icb_prn; 581*7c478bd9Sstevel@tonic-gate iext->ib_block = blkno; 582*7c478bd9Sstevel@tonic-gate iext->ib_flags &= ~IB_UN_RE_AL; 583*7c478bd9Sstevel@tonic-gate /* 584*7c478bd9Sstevel@tonic-gate * iext->ib_flags |= IB_UN_REC; 585*7c478bd9Sstevel@tonic-gate */ 586*7c478bd9Sstevel@tonic-gate i++; 587*7c478bd9Sstevel@tonic-gate continue; 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } while ((iext->ib_offset + iext->ib_count) < end_req); 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate out: 593*7c478bd9Sstevel@tonic-gate return (error); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* 598*7c478bd9Sstevel@tonic-gate * increase i_con/i_ext arrays and set new elements 599*7c478bd9Sstevel@tonic-gate * using long or short allocation descriptors 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate static void 602*7c478bd9Sstevel@tonic-gate ud_common_ad(struct ud_inode *ip, struct buf *bp) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate int32_t ndesc, count, lbmask; 605*7c478bd9Sstevel@tonic-gate uint32_t length; 606*7c478bd9Sstevel@tonic-gate struct alloc_ext_desc *aed; 607*7c478bd9Sstevel@tonic-gate struct icb_ext *iext, *con; 608*7c478bd9Sstevel@tonic-gate u_offset_t offset; 609*7c478bd9Sstevel@tonic-gate long_ad_t *lad; 610*7c478bd9Sstevel@tonic-gate short_ad_t *sad; 611*7c478bd9Sstevel@tonic-gate int islong; 612*7c478bd9Sstevel@tonic-gate void *addr; 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate addr = bp->b_un.b_addr + sizeof (struct alloc_ext_desc); 615*7c478bd9Sstevel@tonic-gate aed = (struct alloc_ext_desc *)bp->b_un.b_addr; 616*7c478bd9Sstevel@tonic-gate length = SWAP_32(aed->aed_len_aed); 617*7c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 618*7c478bd9Sstevel@tonic-gate islong = 1; 619*7c478bd9Sstevel@tonic-gate lad = addr; 620*7c478bd9Sstevel@tonic-gate ndesc = length / sizeof (*lad); 621*7c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 622*7c478bd9Sstevel@tonic-gate islong = 0; 623*7c478bd9Sstevel@tonic-gate sad = addr; 624*7c478bd9Sstevel@tonic-gate ndesc = length / sizeof (*sad); 625*7c478bd9Sstevel@tonic-gate } else 626*7c478bd9Sstevel@tonic-gate return; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate /* 629*7c478bd9Sstevel@tonic-gate * realloc i_ext array 630*7c478bd9Sstevel@tonic-gate */ 631*7c478bd9Sstevel@tonic-gate count = (((ip->i_ext_used + ndesc) / EXT_PER_MALLOC) + 1) * 632*7c478bd9Sstevel@tonic-gate EXT_PER_MALLOC; 633*7c478bd9Sstevel@tonic-gate addr = kmem_zalloc(count * sizeof (struct icb_ext), KM_SLEEP); 634*7c478bd9Sstevel@tonic-gate bcopy(ip->i_ext, addr, ip->i_ext_used * sizeof (struct icb_ext)); 635*7c478bd9Sstevel@tonic-gate kmem_free(ip->i_ext, ip->i_ext_count * sizeof (struct icb_ext)); 636*7c478bd9Sstevel@tonic-gate ip->i_ext = addr; 637*7c478bd9Sstevel@tonic-gate ip->i_ext_count = count; 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate /* 640*7c478bd9Sstevel@tonic-gate * scan descriptors 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate lbmask = ip->i_udf->udf_lbmask; 643*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 644*7c478bd9Sstevel@tonic-gate offset = iext->ib_offset + iext->ib_count; 645*7c478bd9Sstevel@tonic-gate iext++; 646*7c478bd9Sstevel@tonic-gate while (ndesc--) { 647*7c478bd9Sstevel@tonic-gate if (islong) 648*7c478bd9Sstevel@tonic-gate length = SWAP_32(lad->lad_ext_len); 649*7c478bd9Sstevel@tonic-gate else 650*7c478bd9Sstevel@tonic-gate length = SWAP_32(sad->sad_ext_len); 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if ((length & 0x3FFFFFFF) == 0) 653*7c478bd9Sstevel@tonic-gate break; 654*7c478bd9Sstevel@tonic-gate else if (((length >> 30) & IB_MASK) == IB_CON) { 655*7c478bd9Sstevel@tonic-gate if (ip->i_con_used == ip->i_con_count) { 656*7c478bd9Sstevel@tonic-gate struct icb_ext *old; 657*7c478bd9Sstevel@tonic-gate int32_t old_count; 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate old = ip->i_con; 660*7c478bd9Sstevel@tonic-gate old_count = ip->i_con_count * 661*7c478bd9Sstevel@tonic-gate sizeof (struct icb_ext); 662*7c478bd9Sstevel@tonic-gate ip->i_con_count += EXT_PER_MALLOC; 663*7c478bd9Sstevel@tonic-gate ip->i_con = kmem_zalloc(ip->i_con_count * 664*7c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), KM_SLEEP); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate if (old) { 667*7c478bd9Sstevel@tonic-gate bcopy(old, ip->i_con, old_count); 668*7c478bd9Sstevel@tonic-gate kmem_free(old, old_count); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate con = &ip->i_con[ip->i_con_used]; 672*7c478bd9Sstevel@tonic-gate if (islong) { 673*7c478bd9Sstevel@tonic-gate con->ib_prn = SWAP_16(lad->lad_ext_prn); 674*7c478bd9Sstevel@tonic-gate con->ib_block = SWAP_32(lad->lad_ext_loc); 675*7c478bd9Sstevel@tonic-gate } else { 676*7c478bd9Sstevel@tonic-gate con->ib_prn = ip->i_icb_prn; 677*7c478bd9Sstevel@tonic-gate con->ib_block = SWAP_32(sad->sad_ext_loc); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate con->ib_count = length & 0x3FFFFFFF; 680*7c478bd9Sstevel@tonic-gate con->ib_flags = (length >> 30) & IB_MASK; 681*7c478bd9Sstevel@tonic-gate ip->i_con_used++; 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate if (islong) { 686*7c478bd9Sstevel@tonic-gate iext->ib_prn = SWAP_16(lad->lad_ext_prn); 687*7c478bd9Sstevel@tonic-gate iext->ib_block = SWAP_32(lad->lad_ext_loc); 688*7c478bd9Sstevel@tonic-gate lad++; 689*7c478bd9Sstevel@tonic-gate } else { 690*7c478bd9Sstevel@tonic-gate iext->ib_prn = 0; 691*7c478bd9Sstevel@tonic-gate iext->ib_block = SWAP_32(sad->sad_ext_loc); 692*7c478bd9Sstevel@tonic-gate sad++; 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate iext->ib_count = length & 0x3FFFFFFF; 695*7c478bd9Sstevel@tonic-gate iext->ib_offset = offset; 696*7c478bd9Sstevel@tonic-gate iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 697*7c478bd9Sstevel@tonic-gate iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 698*7c478bd9Sstevel@tonic-gate offset += (iext->ib_count + lbmask) & (~lbmask); 699*7c478bd9Sstevel@tonic-gate iext->ib_flags = (length >> 30) & IB_MASK; 700*7c478bd9Sstevel@tonic-gate ip->i_ext_used++; 701*7c478bd9Sstevel@tonic-gate iext++; 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate static int32_t 707*7c478bd9Sstevel@tonic-gate ud_read_next_cont(struct ud_inode *ip) 708*7c478bd9Sstevel@tonic-gate { 709*7c478bd9Sstevel@tonic-gate uint32_t dummy, error = 0; 710*7c478bd9Sstevel@tonic-gate struct alloc_ext_desc *aed; 711*7c478bd9Sstevel@tonic-gate struct icb_ext *cont; 712*7c478bd9Sstevel@tonic-gate struct buf *bp; 713*7c478bd9Sstevel@tonic-gate daddr_t bno; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate cont = &ip->i_con[ip->i_con_read]; 716*7c478bd9Sstevel@tonic-gate ASSERT(cont->ib_count > 0); 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate bno = ud_xlate_to_daddr(ip->i_udf, cont->ib_prn, cont->ib_block, 719*7c478bd9Sstevel@tonic-gate 1, &dummy); 720*7c478bd9Sstevel@tonic-gate bp = ud_bread(ip->i_dev, bno << ip->i_udf->udf_l2d_shift, 721*7c478bd9Sstevel@tonic-gate cont->ib_count); 722*7c478bd9Sstevel@tonic-gate if (bp->b_flags & B_ERROR) 723*7c478bd9Sstevel@tonic-gate error = bp->b_error; 724*7c478bd9Sstevel@tonic-gate else { 725*7c478bd9Sstevel@tonic-gate aed = (struct alloc_ext_desc *)bp->b_un.b_addr; 726*7c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&aed->aed_tag, UD_ALLOC_EXT_DESC, 727*7c478bd9Sstevel@tonic-gate cont->ib_block, 1, cont->ib_count)) 728*7c478bd9Sstevel@tonic-gate error = EINVAL; 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate if (error == 0) 732*7c478bd9Sstevel@tonic-gate ud_common_ad(ip, bp); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate brelse(bp); 735*7c478bd9Sstevel@tonic-gate return (error); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate int32_t 740*7c478bd9Sstevel@tonic-gate ud_read_icb_till_off(struct ud_inode *ip, u_offset_t offset) 741*7c478bd9Sstevel@tonic-gate { 742*7c478bd9Sstevel@tonic-gate int32_t error = 0; 743*7c478bd9Sstevel@tonic-gate struct icb_ext *iext; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate ud_printf("ud_read_icb_till_off\n"); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) 748*7c478bd9Sstevel@tonic-gate return (0); 749*7c478bd9Sstevel@tonic-gate else if ((ip->i_astrat != STRAT_TYPE4) && 750*7c478bd9Sstevel@tonic-gate (ip->i_astrat != STRAT_TYPE4096)) 751*7c478bd9Sstevel@tonic-gate return (EINVAL); 752*7c478bd9Sstevel@tonic-gate else if (ip->i_ext_used == 0) 753*7c478bd9Sstevel@tonic-gate return ((ip->i_size == 0) ? 0 : EINVAL); 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate /* 756*7c478bd9Sstevel@tonic-gate * supported allocation strategies are 757*7c478bd9Sstevel@tonic-gate * STRAT_TYPE4 and STRAT_TYPE4096 758*7c478bd9Sstevel@tonic-gate */ 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_con_lock); 761*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 762*7c478bd9Sstevel@tonic-gate while ((iext->ib_offset + iext->ib_count) < offset) { 763*7c478bd9Sstevel@tonic-gate if (ip->i_con_used == ip->i_con_read) { 764*7c478bd9Sstevel@tonic-gate error = EINVAL; 765*7c478bd9Sstevel@tonic-gate break; 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate if (error = ud_read_next_cont(ip)) 768*7c478bd9Sstevel@tonic-gate break; 769*7c478bd9Sstevel@tonic-gate ip->i_con_read++; 770*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_con_lock); 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate return (error); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate /* 779*7c478bd9Sstevel@tonic-gate * Assumption is the off is beyond ip->i_size 780*7c478bd9Sstevel@tonic-gate * And we will have atleast one ext used 781*7c478bd9Sstevel@tonic-gate */ 782*7c478bd9Sstevel@tonic-gate int32_t 783*7c478bd9Sstevel@tonic-gate ud_last_alloc_ext(struct ud_inode *ip, uint64_t off, 784*7c478bd9Sstevel@tonic-gate uint32_t size, int32_t alloc_only) 785*7c478bd9Sstevel@tonic-gate { 786*7c478bd9Sstevel@tonic-gate struct icb_ext *iext; 787*7c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 788*7c478bd9Sstevel@tonic-gate int32_t lbsize, lbmask; 789*7c478bd9Sstevel@tonic-gate uint64_t end_req, end_count, icb_offset; 790*7c478bd9Sstevel@tonic-gate uint64_t count; 791*7c478bd9Sstevel@tonic-gate int32_t error = 0; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 795*7c478bd9Sstevel@tonic-gate lbsize = udf_vfsp->udf_lbsize; 796*7c478bd9Sstevel@tonic-gate lbmask = udf_vfsp->udf_lbmask; 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate end_req = BASE(off) + size; 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate /* 802*7c478bd9Sstevel@tonic-gate * If we are here it means the file 803*7c478bd9Sstevel@tonic-gate * is growing beyond the end of the 804*7c478bd9Sstevel@tonic-gate * current block. So round up the 805*7c478bd9Sstevel@tonic-gate * last extent 806*7c478bd9Sstevel@tonic-gate */ 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 809*7c478bd9Sstevel@tonic-gate iext->ib_count = CEIL(iext->ib_count); 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* 812*7c478bd9Sstevel@tonic-gate * Figure out if we can create 813*7c478bd9Sstevel@tonic-gate * a hole here 814*7c478bd9Sstevel@tonic-gate */ 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate end_count = iext->ib_offset + iext->ib_count; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate if ((PCEIL(end_count) < PBASE(off)) && 820*7c478bd9Sstevel@tonic-gate ((PBASE(off) - PCEIL(end_count)) >= PAGESIZE)) { 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate count = PCEIL(end_count) - CEIL(end_count); 823*7c478bd9Sstevel@tonic-gate if (count >= lbsize) { 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate /* 826*7c478bd9Sstevel@tonic-gate * There is space between the begining 827*7c478bd9Sstevel@tonic-gate * of the hole to be created and 828*7c478bd9Sstevel@tonic-gate * end of the last offset 829*7c478bd9Sstevel@tonic-gate * Allocate blocks for it 830*7c478bd9Sstevel@tonic-gate */ 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 833*7c478bd9Sstevel@tonic-gate icb_offset = iext->ib_offset + CEIL(iext->ib_count); 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate if (iext->ib_flags == IB_UN_RE_AL) { 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* 838*7c478bd9Sstevel@tonic-gate * Previous extent is a unallocated 839*7c478bd9Sstevel@tonic-gate * extent. Create a new allocated 840*7c478bd9Sstevel@tonic-gate * extent 841*7c478bd9Sstevel@tonic-gate */ 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate error = ud_create_ext(ip, ip->i_ext_used, 844*7c478bd9Sstevel@tonic-gate ALLOC_SPACE | NEW_EXT, 845*7c478bd9Sstevel@tonic-gate alloc_only, icb_offset, &count); 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate } else { 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* 850*7c478bd9Sstevel@tonic-gate * Last extent is allocated 851*7c478bd9Sstevel@tonic-gate * try to allocate adjascent to the 852*7c478bd9Sstevel@tonic-gate * last extent 853*7c478bd9Sstevel@tonic-gate */ 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate error = ud_create_ext(ip, ip->i_ext_used - 1, 856*7c478bd9Sstevel@tonic-gate ALLOC_SPACE, alloc_only, 857*7c478bd9Sstevel@tonic-gate icb_offset, &count); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate if (error != 0) { 861*7c478bd9Sstevel@tonic-gate return (error); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 866*7c478bd9Sstevel@tonic-gate end_count = iext->ib_offset + iext->ib_count; 867*7c478bd9Sstevel@tonic-gate count = PBASE(off) - PCEIL(end_count); 868*7c478bd9Sstevel@tonic-gate icb_offset = PCEIL(end_count); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate if (iext->ib_flags == IB_UN_RE_AL) { 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * The last extent is unallocated 874*7c478bd9Sstevel@tonic-gate * Just bump the extent count 875*7c478bd9Sstevel@tonic-gate */ 876*7c478bd9Sstevel@tonic-gate (void) ud_create_ext(ip, ip->i_ext_used - 1, 877*7c478bd9Sstevel@tonic-gate 0, alloc_only, icb_offset, &count); 878*7c478bd9Sstevel@tonic-gate } else { 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate /* 881*7c478bd9Sstevel@tonic-gate * Last extent is allocated 882*7c478bd9Sstevel@tonic-gate * round up the size of the extent to 883*7c478bd9Sstevel@tonic-gate * lbsize and allocate a new unallocated extent 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate iext->ib_count = CEIL(iext->ib_count); 886*7c478bd9Sstevel@tonic-gate (void) ud_create_ext(ip, ip->i_ext_used, 887*7c478bd9Sstevel@tonic-gate NEW_EXT, alloc_only, icb_offset, &count); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate icb_offset = PBASE(off); 891*7c478bd9Sstevel@tonic-gate } else { 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate /* 894*7c478bd9Sstevel@tonic-gate * We cannot create any hole inbetween 895*7c478bd9Sstevel@tonic-gate * the last extent and the off so 896*7c478bd9Sstevel@tonic-gate * round up the count in the last extent 897*7c478bd9Sstevel@tonic-gate */ 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 900*7c478bd9Sstevel@tonic-gate iext->ib_count = CEIL(iext->ib_count); 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[ip->i_ext_used - 1]; 906*7c478bd9Sstevel@tonic-gate count = end_req - (iext->ib_offset + iext->ib_count); 907*7c478bd9Sstevel@tonic-gate icb_offset = iext->ib_offset + CEIL(iext->ib_count); 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate if (iext->ib_flags == IB_UN_RE_AL) { 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate /* 912*7c478bd9Sstevel@tonic-gate * Last extent was a unallocated extent 913*7c478bd9Sstevel@tonic-gate * create a new extent 914*7c478bd9Sstevel@tonic-gate */ 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate error = ud_create_ext(ip, ip->i_ext_used, 917*7c478bd9Sstevel@tonic-gate ALLOC_SPACE | NEW_EXT, alloc_only, icb_offset, &count); 918*7c478bd9Sstevel@tonic-gate } else { 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * Last extent was an allocated extent 922*7c478bd9Sstevel@tonic-gate * try to allocate adjascent to the old blocks 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate error = ud_create_ext(ip, ip->i_ext_used - 1, 926*7c478bd9Sstevel@tonic-gate ALLOC_SPACE, alloc_only, icb_offset, &count); 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate return (error); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * Break up the icb_ext at index 934*7c478bd9Sstevel@tonic-gate * into two icb_ext, 935*7c478bd9Sstevel@tonic-gate * one at index ib_count "count" and 936*7c478bd9Sstevel@tonic-gate * the other at index+1 with ib_count = old_ib_count - count 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate int32_t 939*7c478bd9Sstevel@tonic-gate ud_break_create_new_icb(struct ud_inode *ip, 940*7c478bd9Sstevel@tonic-gate int32_t index, uint32_t count) 941*7c478bd9Sstevel@tonic-gate { 942*7c478bd9Sstevel@tonic-gate int32_t i, error; 943*7c478bd9Sstevel@tonic-gate struct icb_ext *iext, *next; 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate ud_printf("ud_break_create_new_icb\n"); 947*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate ASSERT(count < iext->ib_count); 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate if ((error = ud_bump_ext_count(ip, KM_SLEEP)) != 0) { 952*7c478bd9Sstevel@tonic-gate return (error); 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate for (i = ip->i_ext_used; i > index; i--) { 956*7c478bd9Sstevel@tonic-gate ip->i_ext[i] = ip->i_ext[i - 1]; 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate next = &ip->i_ext[index + 1]; 960*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate iext->ib_count = count; 963*7c478bd9Sstevel@tonic-gate next->ib_count -= count; 964*7c478bd9Sstevel@tonic-gate next->ib_offset = iext->ib_offset + iext->ib_count; 965*7c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 966*7c478bd9Sstevel@tonic-gate next->ib_block = iext->ib_block + 967*7c478bd9Sstevel@tonic-gate iext->ib_count >> ip->i_udf->udf_l2b_shift; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate ip->i_ext_used++; 970*7c478bd9Sstevel@tonic-gate return (0); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate void 974*7c478bd9Sstevel@tonic-gate ud_remove_ext_at_index(struct ud_inode *ip, int32_t index) 975*7c478bd9Sstevel@tonic-gate { 976*7c478bd9Sstevel@tonic-gate int32_t i; 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate ASSERT(index <= ip->i_ext_used); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate for (i = index; i < ip->i_ext_used; i++) { 981*7c478bd9Sstevel@tonic-gate if ((i + 1) < ip->i_ext_count) { 982*7c478bd9Sstevel@tonic-gate ip->i_ext[i] = ip->i_ext[i + 1]; 983*7c478bd9Sstevel@tonic-gate } else { 984*7c478bd9Sstevel@tonic-gate bzero(&ip->i_ext[i], sizeof (struct icb_ext)); 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate ip->i_ext_used --; 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate int32_t 991*7c478bd9Sstevel@tonic-gate ud_bump_ext_count(struct ud_inode *ip, int32_t sleep_flag) 992*7c478bd9Sstevel@tonic-gate { 993*7c478bd9Sstevel@tonic-gate int32_t error = 0; 994*7c478bd9Sstevel@tonic-gate struct icb_ext *iext; 995*7c478bd9Sstevel@tonic-gate uint32_t old_count, elen; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate ASSERT(ip); 998*7c478bd9Sstevel@tonic-gate ASSERT(sleep_flag == KM_SLEEP); 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate ud_printf("ud_bump_ext_count\n"); 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate if (ip->i_ext_used >= ip->i_ext_count) { 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate old_count = sizeof (struct icb_ext) * ip->i_ext_count; 1005*7c478bd9Sstevel@tonic-gate ip->i_ext_count += EXT_PER_MALLOC; 1006*7c478bd9Sstevel@tonic-gate iext = kmem_zalloc(sizeof (struct icb_ext) * 1007*7c478bd9Sstevel@tonic-gate ip->i_ext_count, sleep_flag); 1008*7c478bd9Sstevel@tonic-gate bcopy(ip->i_ext, iext, old_count); 1009*7c478bd9Sstevel@tonic-gate kmem_free(ip->i_ext, old_count); 1010*7c478bd9Sstevel@tonic-gate ip->i_ext = iext; 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if (ip->i_ext_used >= ip->i_cur_max_ext) { 1014*7c478bd9Sstevel@tonic-gate int32_t prox; 1015*7c478bd9Sstevel@tonic-gate struct icb_ext *icon; 1016*7c478bd9Sstevel@tonic-gate uint32_t blkno, sz; 1017*7c478bd9Sstevel@tonic-gate int32_t lbmask, l2b; 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate lbmask = ip->i_udf->udf_lbmask; 1020*7c478bd9Sstevel@tonic-gate l2b = ip->i_udf->udf_l2b_shift; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, ip->i_size)) != 0) { 1023*7c478bd9Sstevel@tonic-gate return (error); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate /* 1027*7c478bd9Sstevel@tonic-gate * If there are any old cont extents 1028*7c478bd9Sstevel@tonic-gate * allocate the new one ajscant to the old one 1029*7c478bd9Sstevel@tonic-gate */ 1030*7c478bd9Sstevel@tonic-gate if (ip->i_con_used != 0) { 1031*7c478bd9Sstevel@tonic-gate icon = &ip->i_con[ip->i_con_used - 1]; 1032*7c478bd9Sstevel@tonic-gate prox = icon->ib_block + (CEIL(icon->ib_count) >> l2b); 1033*7c478bd9Sstevel@tonic-gate } else { 1034*7c478bd9Sstevel@tonic-gate prox = 0; 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate /* 1038*7c478bd9Sstevel@tonic-gate * Allocate space 1039*7c478bd9Sstevel@tonic-gate */ 1040*7c478bd9Sstevel@tonic-gate if ((error = ud_alloc_space(ip->i_vfs, ip->i_icb_prn, 1041*7c478bd9Sstevel@tonic-gate prox, 1, &blkno, &sz, 0, 0)) != 0) { 1042*7c478bd9Sstevel@tonic-gate return (error); 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate if (sz == 0) { 1045*7c478bd9Sstevel@tonic-gate return (ENOSPC); 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate sz <<= l2b; 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate if (ip->i_con_used == ip->i_con_count) { 1051*7c478bd9Sstevel@tonic-gate struct icb_ext *old; 1052*7c478bd9Sstevel@tonic-gate int32_t old_count; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate old = ip->i_con; 1055*7c478bd9Sstevel@tonic-gate old_count = ip->i_con_count * 1056*7c478bd9Sstevel@tonic-gate sizeof (struct icb_ext); 1057*7c478bd9Sstevel@tonic-gate ip->i_con_count += EXT_PER_MALLOC; 1058*7c478bd9Sstevel@tonic-gate ip->i_con = kmem_zalloc(ip->i_con_count * 1059*7c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), KM_SLEEP); 1060*7c478bd9Sstevel@tonic-gate if (old != 0) { 1061*7c478bd9Sstevel@tonic-gate bcopy(old, ip->i_con, old_count); 1062*7c478bd9Sstevel@tonic-gate kmem_free(old, old_count); 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate icon = &ip->i_con[ip->i_con_used++]; 1066*7c478bd9Sstevel@tonic-gate icon->ib_flags = IB_CON; 1067*7c478bd9Sstevel@tonic-gate icon->ib_prn = ip->i_icb_prn; 1068*7c478bd9Sstevel@tonic-gate icon->ib_block = blkno; 1069*7c478bd9Sstevel@tonic-gate icon->ib_count = sz; 1070*7c478bd9Sstevel@tonic-gate icon->ib_offset = 0; 1071*7c478bd9Sstevel@tonic-gate icon->ib_marker1 = (uint32_t)0xAAAAAAAA; 1072*7c478bd9Sstevel@tonic-gate icon->ib_marker2 = (uint32_t)0xBBBBBBBB; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate /* 1075*7c478bd9Sstevel@tonic-gate * Bump the i_cur_max_ext according to 1076*7c478bd9Sstevel@tonic-gate * the space allocated 1077*7c478bd9Sstevel@tonic-gate */ 1078*7c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 1079*7c478bd9Sstevel@tonic-gate elen = sizeof (struct short_ad); 1080*7c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 1081*7c478bd9Sstevel@tonic-gate elen = sizeof (struct long_ad); 1082*7c478bd9Sstevel@tonic-gate } else { 1083*7c478bd9Sstevel@tonic-gate return (ENOSPC); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate sz = sz - (sizeof (struct alloc_ext_desc) + elen); 1086*7c478bd9Sstevel@tonic-gate ip->i_cur_max_ext += sz / elen; 1087*7c478bd9Sstevel@tonic-gate } 1088*7c478bd9Sstevel@tonic-gate return (error); 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate int32_t 1092*7c478bd9Sstevel@tonic-gate ud_create_ext(struct ud_inode *ip, int32_t index, uint32_t flags, 1093*7c478bd9Sstevel@tonic-gate int32_t alloc_only, uint64_t offset, uint64_t *count) 1094*7c478bd9Sstevel@tonic-gate { 1095*7c478bd9Sstevel@tonic-gate struct icb_ext *iext, *pext; 1096*7c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 1097*7c478bd9Sstevel@tonic-gate int32_t error = 0, blkcount, acount; 1098*7c478bd9Sstevel@tonic-gate uint32_t blkno, sz, prox, mext_sz; 1099*7c478bd9Sstevel@tonic-gate int32_t lbmask, l2b; 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate if (*count == 0) { 1102*7c478bd9Sstevel@tonic-gate return (0); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate begin: 1106*7c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 1107*7c478bd9Sstevel@tonic-gate lbmask = udf_vfsp->udf_lbmask; 1108*7c478bd9Sstevel@tonic-gate l2b = udf_vfsp->udf_l2b_shift; 1109*7c478bd9Sstevel@tonic-gate mext_sz = (1 << MEXT_BITS) - PAGESIZE; 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate if ((error = ud_bump_ext_count(ip, KM_SLEEP)) != 0) { 1112*7c478bd9Sstevel@tonic-gate return (error); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 1116*7c478bd9Sstevel@tonic-gate if (flags & ALLOC_SPACE) { 1117*7c478bd9Sstevel@tonic-gate if ((flags & NEW_EXT) || 1118*7c478bd9Sstevel@tonic-gate (ip->i_ext_count == 0)) { 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate iext->ib_flags = 0; 1121*7c478bd9Sstevel@tonic-gate iext->ib_prn = ip->i_icb_prn; 1122*7c478bd9Sstevel@tonic-gate if (*count > mext_sz) { 1123*7c478bd9Sstevel@tonic-gate blkcount = mext_sz >> l2b; 1124*7c478bd9Sstevel@tonic-gate } else { 1125*7c478bd9Sstevel@tonic-gate blkcount = CEIL(*count) >> l2b; 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate if ((error = ud_alloc_space(ip->i_vfs, 1128*7c478bd9Sstevel@tonic-gate ip->i_icb_prn, 0, blkcount, 1129*7c478bd9Sstevel@tonic-gate &blkno, &sz, 1, 0)) != 0) { 1130*7c478bd9Sstevel@tonic-gate return (error); 1131*7c478bd9Sstevel@tonic-gate } 1132*7c478bd9Sstevel@tonic-gate if (sz == 0) { 1133*7c478bd9Sstevel@tonic-gate return (ENOSPC); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate ip->i_lbr += sz; 1136*7c478bd9Sstevel@tonic-gate iext->ib_block = blkno; 1137*7c478bd9Sstevel@tonic-gate acount = sz << l2b; 1138*7c478bd9Sstevel@tonic-gate if ((sz << l2b) > *count) { 1139*7c478bd9Sstevel@tonic-gate iext->ib_count = *count; 1140*7c478bd9Sstevel@tonic-gate *count = 0; 1141*7c478bd9Sstevel@tonic-gate } else { 1142*7c478bd9Sstevel@tonic-gate iext->ib_count = sz << l2b; 1143*7c478bd9Sstevel@tonic-gate *count -= iext->ib_count; 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate iext->ib_offset = offset; 1146*7c478bd9Sstevel@tonic-gate if (ip->i_ext_used <= index) 1147*7c478bd9Sstevel@tonic-gate ip->i_ext_used ++; 1148*7c478bd9Sstevel@tonic-gate } else { 1149*7c478bd9Sstevel@tonic-gate if ((iext->ib_count + *count) > mext_sz) { 1150*7c478bd9Sstevel@tonic-gate blkcount = (mext_sz - iext->ib_count) >> l2b; 1151*7c478bd9Sstevel@tonic-gate } else { 1152*7c478bd9Sstevel@tonic-gate blkcount = CEIL(*count) >> l2b; 1153*7c478bd9Sstevel@tonic-gate } 1154*7c478bd9Sstevel@tonic-gate if (blkcount == 0) { 1155*7c478bd9Sstevel@tonic-gate flags |= NEW_EXT; 1156*7c478bd9Sstevel@tonic-gate index++; 1157*7c478bd9Sstevel@tonic-gate goto begin; 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate prox = iext->ib_block + (CEIL(iext->ib_count) >> l2b); 1160*7c478bd9Sstevel@tonic-gate if ((error = ud_alloc_space(ip->i_vfs, 1161*7c478bd9Sstevel@tonic-gate ip->i_icb_prn, prox, blkcount, 1162*7c478bd9Sstevel@tonic-gate &blkno, &sz, 1, 0)) != 0) { 1163*7c478bd9Sstevel@tonic-gate return (error); 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate if (sz == 0) { 1166*7c478bd9Sstevel@tonic-gate return (ENOSPC); 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate acount = sz << l2b; 1169*7c478bd9Sstevel@tonic-gate if (acount > *count) { 1170*7c478bd9Sstevel@tonic-gate acount = *count; 1171*7c478bd9Sstevel@tonic-gate *count = 0; 1172*7c478bd9Sstevel@tonic-gate } else { 1173*7c478bd9Sstevel@tonic-gate *count -= acount; 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate ip->i_lbr += sz; 1176*7c478bd9Sstevel@tonic-gate if (prox == blkno) { 1177*7c478bd9Sstevel@tonic-gate iext->ib_count += acount; 1178*7c478bd9Sstevel@tonic-gate } else { 1179*7c478bd9Sstevel@tonic-gate if ((error = ud_bump_ext_count(ip, KM_SLEEP)) 1180*7c478bd9Sstevel@tonic-gate != 0) { 1181*7c478bd9Sstevel@tonic-gate return (error); 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate pext = &ip->i_ext[index]; 1184*7c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index + 1]; 1185*7c478bd9Sstevel@tonic-gate iext->ib_flags = 0; 1186*7c478bd9Sstevel@tonic-gate iext->ib_prn = ip->i_icb_prn; 1187*7c478bd9Sstevel@tonic-gate iext->ib_block = blkno; 1188*7c478bd9Sstevel@tonic-gate iext->ib_offset = 1189*7c478bd9Sstevel@tonic-gate pext->ib_offset + pext->ib_count; 1190*7c478bd9Sstevel@tonic-gate iext->ib_count = acount; 1191*7c478bd9Sstevel@tonic-gate /* 1192*7c478bd9Sstevel@tonic-gate * Increment the index, since we have used 1193*7c478bd9Sstevel@tonic-gate * the extent at [index+1] above. 1194*7c478bd9Sstevel@tonic-gate */ 1195*7c478bd9Sstevel@tonic-gate index++; 1196*7c478bd9Sstevel@tonic-gate if (ip->i_ext_used <= index) 1197*7c478bd9Sstevel@tonic-gate ip->i_ext_used ++; 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate } 1200*7c478bd9Sstevel@tonic-gate if (alloc_only == 0) { 1201*7c478bd9Sstevel@tonic-gate error = ud_zero_it(ip, blkno, sz); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate if (*count) { 1204*7c478bd9Sstevel@tonic-gate offset = iext->ib_offset + CEIL(iext->ib_count); 1205*7c478bd9Sstevel@tonic-gate flags |= NEW_EXT; 1206*7c478bd9Sstevel@tonic-gate index++; 1207*7c478bd9Sstevel@tonic-gate goto begin; 1208*7c478bd9Sstevel@tonic-gate } 1209*7c478bd9Sstevel@tonic-gate } else { 1210*7c478bd9Sstevel@tonic-gate if (flags & NEW_EXT) { 1211*7c478bd9Sstevel@tonic-gate iext->ib_flags = IB_UN_RE_AL; 1212*7c478bd9Sstevel@tonic-gate iext->ib_prn = 0; 1213*7c478bd9Sstevel@tonic-gate iext->ib_block = 0; 1214*7c478bd9Sstevel@tonic-gate if (*count > mext_sz) { 1215*7c478bd9Sstevel@tonic-gate iext->ib_count = mext_sz; 1216*7c478bd9Sstevel@tonic-gate *count -= iext->ib_count; 1217*7c478bd9Sstevel@tonic-gate } else { 1218*7c478bd9Sstevel@tonic-gate iext->ib_count = *count; 1219*7c478bd9Sstevel@tonic-gate *count = 0; 1220*7c478bd9Sstevel@tonic-gate } 1221*7c478bd9Sstevel@tonic-gate iext->ib_offset = offset; 1222*7c478bd9Sstevel@tonic-gate if (ip->i_ext_used <= index) 1223*7c478bd9Sstevel@tonic-gate ip->i_ext_used ++; 1224*7c478bd9Sstevel@tonic-gate } else { 1225*7c478bd9Sstevel@tonic-gate ASSERT(iext->ib_flags == IB_UN_RE_AL); 1226*7c478bd9Sstevel@tonic-gate if ((iext->ib_count + *count) > mext_sz) { 1227*7c478bd9Sstevel@tonic-gate acount = mext_sz - iext->ib_count; 1228*7c478bd9Sstevel@tonic-gate iext->ib_count += acount; 1229*7c478bd9Sstevel@tonic-gate *count -= acount; 1230*7c478bd9Sstevel@tonic-gate } else { 1231*7c478bd9Sstevel@tonic-gate iext->ib_count += *count; 1232*7c478bd9Sstevel@tonic-gate *count = 0; 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate if (*count != 0) { 1236*7c478bd9Sstevel@tonic-gate offset = iext->ib_offset + CEIL(iext->ib_count); 1237*7c478bd9Sstevel@tonic-gate flags |= NEW_EXT; 1238*7c478bd9Sstevel@tonic-gate index++; 1239*7c478bd9Sstevel@tonic-gate goto begin; 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 1243*7c478bd9Sstevel@tonic-gate iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 1244*7c478bd9Sstevel@tonic-gate return (error); 1245*7c478bd9Sstevel@tonic-gate } 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate #undef CEIL 1248*7c478bd9Sstevel@tonic-gate #undef BASE 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate int32_t 1251*7c478bd9Sstevel@tonic-gate ud_zero_it(struct ud_inode *ip, uint32_t start_block, uint32_t block_count) 1252*7c478bd9Sstevel@tonic-gate { 1253*7c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 1254*7c478bd9Sstevel@tonic-gate uint32_t bno, dummy; 1255*7c478bd9Sstevel@tonic-gate int32_t error; 1256*7c478bd9Sstevel@tonic-gate struct buf *bp; 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate /* 1259*7c478bd9Sstevel@tonic-gate * Donot use bio routines 1260*7c478bd9Sstevel@tonic-gate * since the buffer can sit 1261*7c478bd9Sstevel@tonic-gate * long enough in cache for the space 1262*7c478bd9Sstevel@tonic-gate * to be allocated/freed and 1263*7c478bd9Sstevel@tonic-gate * then allocated 1264*7c478bd9Sstevel@tonic-gate */ 1265*7c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 1266*7c478bd9Sstevel@tonic-gate bno = ud_xlate_to_daddr(udf_vfsp, 1267*7c478bd9Sstevel@tonic-gate ip->i_icb_prn, start_block, block_count, &dummy); 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate dummy = block_count << udf_vfsp->udf_l2b_shift; 1270*7c478bd9Sstevel@tonic-gate bp = (struct buf *)kmem_zalloc(biosize(), KM_SLEEP); 1271*7c478bd9Sstevel@tonic-gate sema_init(&bp->b_sem, 0, NULL, SEMA_DEFAULT, NULL); 1272*7c478bd9Sstevel@tonic-gate sema_init(&bp->b_io, 0, NULL, SEMA_DEFAULT, NULL); 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate bp->b_flags = B_WRITE | B_BUSY; 1275*7c478bd9Sstevel@tonic-gate bp->b_edev = ip->i_dev; 1276*7c478bd9Sstevel@tonic-gate bp->b_dev = cmpdev(ip->i_dev); 1277*7c478bd9Sstevel@tonic-gate bp->b_blkno = bno << udf_vfsp->udf_l2d_shift; 1278*7c478bd9Sstevel@tonic-gate bp->b_bcount = dummy; 1279*7c478bd9Sstevel@tonic-gate bp->b_un.b_addr = kmem_zalloc(bp->b_bcount, KM_SLEEP); 1280*7c478bd9Sstevel@tonic-gate bp->b_file = ip->i_vnode; 1281*7c478bd9Sstevel@tonic-gate bp->b_offset = -1; 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate (void) bdev_strategy(bp); 1284*7c478bd9Sstevel@tonic-gate if (error = biowait(bp)) { 1285*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "error in write\n"); 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate kmem_free(bp->b_un.b_addr, dummy); 1289*7c478bd9Sstevel@tonic-gate sema_destroy(&bp->b_io); 1290*7c478bd9Sstevel@tonic-gate sema_destroy(&bp->b_sem); 1291*7c478bd9Sstevel@tonic-gate kmem_free((caddr_t)bp, biosize()); 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate return (error); 1294*7c478bd9Sstevel@tonic-gate } 1295