17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5b39a0235SMilan Cermak * Common Development and Distribution License (the "License"). 6b39a0235SMilan Cermak * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22b39a0235SMilan Cermak * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <sys/types.h> 267c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 277c478bd9Sstevel@tonic-gate #include <sys/param.h> 287c478bd9Sstevel@tonic-gate #include <sys/time.h> 297c478bd9Sstevel@tonic-gate #include <sys/systm.h> 307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 317c478bd9Sstevel@tonic-gate #include <sys/resource.h> 327c478bd9Sstevel@tonic-gate #include <sys/signal.h> 337c478bd9Sstevel@tonic-gate #include <sys/cred.h> 347c478bd9Sstevel@tonic-gate #include <sys/user.h> 357c478bd9Sstevel@tonic-gate #include <sys/buf.h> 367c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 397c478bd9Sstevel@tonic-gate #include <sys/mode.h> 407c478bd9Sstevel@tonic-gate #include <sys/proc.h> 417c478bd9Sstevel@tonic-gate #include <sys/disp.h> 427c478bd9Sstevel@tonic-gate #include <sys/file.h> 437c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 447c478bd9Sstevel@tonic-gate #include <sys/flock.h> 457c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 467c478bd9Sstevel@tonic-gate #include <sys/uio.h> 477c478bd9Sstevel@tonic-gate #include <sys/dnlc.h> 487c478bd9Sstevel@tonic-gate #include <sys/conf.h> 497c478bd9Sstevel@tonic-gate #include <sys/errno.h> 507c478bd9Sstevel@tonic-gate #include <sys/mman.h> 517c478bd9Sstevel@tonic-gate #include <sys/fbuf.h> 527c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 537c478bd9Sstevel@tonic-gate #include <sys/debug.h> 547c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 557c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 567c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 577c478bd9Sstevel@tonic-gate #include <sys/errno.h> 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 607c478bd9Sstevel@tonic-gate #include <sys/mount.h> 617c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 627c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 637c478bd9Sstevel@tonic-gate #include <sys/policy.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #include <vm/hat.h> 667c478bd9Sstevel@tonic-gate #include <vm/page.h> 677c478bd9Sstevel@tonic-gate #include <vm/pvn.h> 687c478bd9Sstevel@tonic-gate #include <vm/as.h> 697c478bd9Sstevel@tonic-gate #include <vm/seg.h> 707c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 717c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 727c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h> 737c478bd9Sstevel@tonic-gate #include <vm/rm.h> 747c478bd9Sstevel@tonic-gate #include <vm/page.h> 757c478bd9Sstevel@tonic-gate #include <sys/swap.h> 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h> 827c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h> 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate extern struct vnodeops *udf_vnodeops; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate kmutex_t ud_sync_busy; 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * udf_vfs list manipulation routines 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate kmutex_t udf_vfs_mutex; 917c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfs_instances; 927c478bd9Sstevel@tonic-gate #ifndef __lint 937c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_vfs_mutex, udf_vfs_instances)) 947c478bd9Sstevel@tonic-gate #endif 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate union ihead ud_ihead[UD_HASH_SZ]; 977c478bd9Sstevel@tonic-gate kmutex_t ud_icache_lock; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate #define UD_BEGIN 0x0 1007c478bd9Sstevel@tonic-gate #define UD_END 0x1 1017c478bd9Sstevel@tonic-gate #define UD_UNKN 0x2 1027c478bd9Sstevel@tonic-gate struct ud_inode *udf_ifreeh, *udf_ifreet; 1037c478bd9Sstevel@tonic-gate kmutex_t udf_ifree_lock; 1047c478bd9Sstevel@tonic-gate #ifndef __lint 1057c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreeh)) 1067c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(udf_ifree_lock, udf_ifreet)) 1077c478bd9Sstevel@tonic-gate #endif 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate kmutex_t ud_nino_lock; 1107c478bd9Sstevel@tonic-gate int32_t ud_max_inodes = 512; 1117c478bd9Sstevel@tonic-gate int32_t ud_cur_inodes = 0; 1127c478bd9Sstevel@tonic-gate #ifndef __lint 1137c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ud_nino_lock, ud_cur_inodes)) 1147c478bd9Sstevel@tonic-gate #endif 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate uid_t ud_default_uid = 0; 1177c478bd9Sstevel@tonic-gate gid_t ud_default_gid = 3; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int32_t ud_updat_ext4(struct ud_inode *, struct file_entry *); 1207c478bd9Sstevel@tonic-gate int32_t ud_updat_ext4096(struct ud_inode *, struct file_entry *); 1217c478bd9Sstevel@tonic-gate void ud_make_sad(struct icb_ext *, struct short_ad *, int32_t); 1227c478bd9Sstevel@tonic-gate void ud_make_lad(struct icb_ext *, struct long_ad *, int32_t); 1237c478bd9Sstevel@tonic-gate void ud_trunc_ext4(struct ud_inode *, u_offset_t); 1247c478bd9Sstevel@tonic-gate void ud_trunc_ext4096(struct ud_inode *, u_offset_t); 1257c478bd9Sstevel@tonic-gate void ud_add_to_free_list(struct ud_inode *, uint32_t); 1267c478bd9Sstevel@tonic-gate void ud_remove_from_free_list(struct ud_inode *, uint32_t); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate #ifdef DEBUG 1307c478bd9Sstevel@tonic-gate struct ud_inode * 1317c478bd9Sstevel@tonic-gate ud_search_icache(struct vfs *vfsp, uint16_t prn, uint32_t ploc) 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate int32_t hno; 1347c478bd9Sstevel@tonic-gate union ihead *ih; 1357c478bd9Sstevel@tonic-gate struct ud_inode *ip; 1367c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 1377c478bd9Sstevel@tonic-gate uint32_t loc, dummy; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate udf_vfsp = (struct udf_vfs *)vfsp->vfs_data; 1407c478bd9Sstevel@tonic-gate loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 1437c478bd9Sstevel@tonic-gate hno = UD_INOHASH(vfsp->vfs_dev, loc); 1447c478bd9Sstevel@tonic-gate ih = &ud_ihead[hno]; 1457c478bd9Sstevel@tonic-gate for (ip = ih->ih_chain[0]; 1467c478bd9Sstevel@tonic-gate ip != (struct ud_inode *)ih; 1477c478bd9Sstevel@tonic-gate ip = ip->i_forw) { 148b39a0235SMilan Cermak if ((prn == ip->i_icb_prn) && (ploc == ip->i_icb_block) && 1497c478bd9Sstevel@tonic-gate (vfsp->vfs_dev == ip->i_dev)) { 1507c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 1517c478bd9Sstevel@tonic-gate return (ip); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 1557c478bd9Sstevel@tonic-gate return (0); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate #endif 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1607c478bd9Sstevel@tonic-gate int 1617c478bd9Sstevel@tonic-gate ud_iget(struct vfs *vfsp, uint16_t prn, uint32_t ploc, 1627c478bd9Sstevel@tonic-gate struct ud_inode **ipp, struct buf *pbp, struct cred *cred) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate int32_t hno, nomem = 0, icb_tag_flags; 1657c478bd9Sstevel@tonic-gate union ihead *ih; 1667c478bd9Sstevel@tonic-gate struct ud_inode *ip; 1677c478bd9Sstevel@tonic-gate struct vnode *vp; 1687c478bd9Sstevel@tonic-gate struct buf *bp = NULL; 1697c478bd9Sstevel@tonic-gate struct file_entry *fe; 1707c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 1717c478bd9Sstevel@tonic-gate struct ext_attr_hdr *eah; 1727c478bd9Sstevel@tonic-gate struct attr_hdr *ah; 1737c478bd9Sstevel@tonic-gate int32_t ea_len, ea_off; 1747c478bd9Sstevel@tonic-gate daddr_t loc; 1757c478bd9Sstevel@tonic-gate uint64_t offset = 0; 1767c478bd9Sstevel@tonic-gate struct icb_ext *iext, *con; 1777c478bd9Sstevel@tonic-gate uint32_t length, dummy; 1787c478bd9Sstevel@tonic-gate int32_t ndesc, ftype; 1797c478bd9Sstevel@tonic-gate uint16_t old_prn; 1807c478bd9Sstevel@tonic-gate uint32_t old_block, old_lbano; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate ud_printf("ud_iget\n"); 1837c478bd9Sstevel@tonic-gate udf_vfsp = (struct udf_vfs *)vfsp->vfs_data; 1847c478bd9Sstevel@tonic-gate old_prn = 0; 1857c478bd9Sstevel@tonic-gate old_block = old_lbano = 0; 1867c478bd9Sstevel@tonic-gate ftype = 0; 1877c478bd9Sstevel@tonic-gate loc = ud_xlate_to_daddr(udf_vfsp, prn, ploc, 1, &dummy); 1887c478bd9Sstevel@tonic-gate loop: 1897c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 1907c478bd9Sstevel@tonic-gate hno = UD_INOHASH(vfsp->vfs_dev, loc); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate ih = &ud_ihead[hno]; 1937c478bd9Sstevel@tonic-gate for (ip = ih->ih_chain[0]; 1947c478bd9Sstevel@tonic-gate ip != (struct ud_inode *)ih; 1957c478bd9Sstevel@tonic-gate ip = ip->i_forw) { 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if ((prn == ip->i_icb_prn) && 1987c478bd9Sstevel@tonic-gate (ploc == ip->i_icb_block) && 1997c478bd9Sstevel@tonic-gate (vfsp->vfs_dev == ip->i_dev)) { 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate vp = ITOV(ip); 2027c478bd9Sstevel@tonic-gate VN_HOLD(vp); 2037c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_READER); 2067c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 2077c478bd9Sstevel@tonic-gate if ((ip->i_flag & IREF) == 0) { 2087c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 2097c478bd9Sstevel@tonic-gate ud_remove_from_free_list(ip, UD_UNKN); 2107c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate ip->i_flag |= IREF; 2137c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 2147c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate *ipp = ip; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (pbp != NULL) { 2197c478bd9Sstevel@tonic-gate brelse(pbp); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate return (0); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * We don't have it in the cache 2287c478bd9Sstevel@tonic-gate * Allocate a new entry 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate tryagain: 2317c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 2327c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 2337c478bd9Sstevel@tonic-gate if (ud_cur_inodes > ud_max_inodes) { 2347c478bd9Sstevel@tonic-gate int32_t purged; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 2377c478bd9Sstevel@tonic-gate while (udf_ifreeh == NULL || 2387c478bd9Sstevel@tonic-gate vn_has_cached_data(ITOV(udf_ifreeh))) { 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Try to put an inode on the freelist that's 2417c478bd9Sstevel@tonic-gate * sitting in the dnlc. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 2447c478bd9Sstevel@tonic-gate purged = dnlc_fs_purge1(udf_vnodeops); 2457c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 2467c478bd9Sstevel@tonic-gate if (!purged) { 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * If there's a free one available and it has no pages attached 2557c478bd9Sstevel@tonic-gate * take it. If we're over the high water mark, take it even if 2567c478bd9Sstevel@tonic-gate * it has attached pages. Otherwise, make a new one. 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate if (udf_ifreeh && 2597c478bd9Sstevel@tonic-gate (nomem || !vn_has_cached_data(ITOV(udf_ifreeh)) || 2607c478bd9Sstevel@tonic-gate ud_cur_inodes >= ud_max_inodes)) { 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 2637c478bd9Sstevel@tonic-gate ip = udf_ifreeh; 2647c478bd9Sstevel@tonic-gate vp = ITOV(ip); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate ud_remove_from_free_list(ip, UD_BEGIN); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 2697c478bd9Sstevel@tonic-gate if (ip->i_flag & IREF) { 2707c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iget: bad i_flag\n"); 2717c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 2727c478bd9Sstevel@tonic-gate if (pbp != NULL) { 2737c478bd9Sstevel@tonic-gate brelse(pbp); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate return (EINVAL); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * We call udf_syncip() to synchronously destroy all pages 2817c478bd9Sstevel@tonic-gate * associated with the vnode before re-using it. The pageout 2827c478bd9Sstevel@tonic-gate * thread may have beat us to this page so our v_count can 2837c478bd9Sstevel@tonic-gate * be > 0 at this point even though we are on the freelist. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 2867c478bd9Sstevel@tonic-gate ip->i_flag = (ip->i_flag & IMODTIME) | IREF; 2877c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate VN_HOLD(vp); 2907c478bd9Sstevel@tonic-gate if (ud_syncip(ip, B_INVAL, I_SYNC) != 0) { 2917c478bd9Sstevel@tonic-gate ud_idrop(ip); 2927c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 2937c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 2947c478bd9Sstevel@tonic-gate goto loop; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 2987c478bd9Sstevel@tonic-gate ip->i_flag &= ~IMODTIME; 2997c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (ip->i_ext) { 3027c478bd9Sstevel@tonic-gate kmem_free(ip->i_ext, 3037c478bd9Sstevel@tonic-gate sizeof (struct icb_ext) * ip->i_ext_count); 3047c478bd9Sstevel@tonic-gate ip->i_ext = 0; 3057c478bd9Sstevel@tonic-gate ip->i_ext_count = ip->i_ext_used = 0; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (ip->i_con) { 3097c478bd9Sstevel@tonic-gate kmem_free(ip->i_con, 3107c478bd9Sstevel@tonic-gate sizeof (struct icb_ext) * ip->i_con_count); 3117c478bd9Sstevel@tonic-gate ip->i_con = 0; 3127c478bd9Sstevel@tonic-gate ip->i_con_count = ip->i_con_used = ip->i_con_read = 0; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * The pageout thread may not have had a chance to release 3177c478bd9Sstevel@tonic-gate * its hold on the vnode (if it was active with this vp), 3187c478bd9Sstevel@tonic-gate * but the pages should all be invalidated. 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate } else { 3217c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 3227c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Try to get memory for this inode without blocking. 3257c478bd9Sstevel@tonic-gate * If we can't and there is something on the freelist, 3267c478bd9Sstevel@tonic-gate * go ahead and use it, otherwise block waiting for 3277c478bd9Sstevel@tonic-gate * memory holding the hash_lock. We expose a potential 3287c478bd9Sstevel@tonic-gate * deadlock if all users of memory have to do a ud_iget() 3297c478bd9Sstevel@tonic-gate * before releasing memory. 3307c478bd9Sstevel@tonic-gate */ 3317c478bd9Sstevel@tonic-gate ip = (struct ud_inode *)kmem_zalloc(sizeof (struct ud_inode), 3327c478bd9Sstevel@tonic-gate KM_NOSLEEP); 3337c478bd9Sstevel@tonic-gate vp = vn_alloc(KM_NOSLEEP); 3347c478bd9Sstevel@tonic-gate if ((ip == NULL) || (vp == NULL)) { 3357c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 3367c478bd9Sstevel@tonic-gate if (udf_ifreeh) { 3377c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 3387c478bd9Sstevel@tonic-gate if (ip != NULL) 3397c478bd9Sstevel@tonic-gate kmem_free(ip, sizeof (struct ud_inode)); 3407c478bd9Sstevel@tonic-gate if (vp != NULL) 3417c478bd9Sstevel@tonic-gate vn_free(vp); 3427c478bd9Sstevel@tonic-gate nomem = 1; 3437c478bd9Sstevel@tonic-gate goto tryagain; 3447c478bd9Sstevel@tonic-gate } else { 3457c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 3467c478bd9Sstevel@tonic-gate if (ip == NULL) 3477c478bd9Sstevel@tonic-gate ip = (struct ud_inode *) 3487c478bd9Sstevel@tonic-gate kmem_zalloc( 3497c478bd9Sstevel@tonic-gate sizeof (struct ud_inode), 3507c478bd9Sstevel@tonic-gate KM_SLEEP); 3517c478bd9Sstevel@tonic-gate if (vp == NULL) 3527c478bd9Sstevel@tonic-gate vp = vn_alloc(KM_SLEEP); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate ip->i_vnode = vp; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate ip->i_marker1 = (uint32_t)0xAAAAAAAA; 3587c478bd9Sstevel@tonic-gate ip->i_marker2 = (uint32_t)0xBBBBBBBB; 3597c478bd9Sstevel@tonic-gate ip->i_marker3 = (uint32_t)0xCCCCCCCC; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate rw_init(&ip->i_rwlock, NULL, RW_DEFAULT, NULL); 3627c478bd9Sstevel@tonic-gate rw_init(&ip->i_contents, NULL, RW_DEFAULT, NULL); 3637c478bd9Sstevel@tonic-gate mutex_init(&ip->i_tlock, NULL, MUTEX_DEFAULT, NULL); 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate ip->i_forw = ip; 3667c478bd9Sstevel@tonic-gate ip->i_back = ip; 3677c478bd9Sstevel@tonic-gate vp->v_data = (caddr_t)ip; 3687c478bd9Sstevel@tonic-gate vn_setops(vp, udf_vnodeops); 3697c478bd9Sstevel@tonic-gate ip->i_flag = IREF; 3707c478bd9Sstevel@tonic-gate cv_init(&ip->i_wrcv, NULL, CV_DRIVER, NULL); 3717c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 3727c478bd9Sstevel@tonic-gate ud_cur_inodes++; 3737c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (vp->v_count < 1) { 3797c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iget: v_count < 1\n"); 3807c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 3817c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 3827c478bd9Sstevel@tonic-gate if (pbp != NULL) { 3837c478bd9Sstevel@tonic-gate brelse(pbp); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate return (EINVAL); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate if (vn_has_cached_data(vp)) { 3887c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iget: v_pages not NULL\n"); 3897c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 3907c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 3917c478bd9Sstevel@tonic-gate if (pbp != NULL) { 3927c478bd9Sstevel@tonic-gate brelse(pbp); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate return (EINVAL); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * Move the inode on the chain for its new (ino, dev) pair 3997c478bd9Sstevel@tonic-gate */ 4007c478bd9Sstevel@tonic-gate remque(ip); 4017c478bd9Sstevel@tonic-gate ip->i_forw = ip; 4027c478bd9Sstevel@tonic-gate ip->i_back = ip; 4037c478bd9Sstevel@tonic-gate insque(ip, ih); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate ip->i_dev = vfsp->vfs_dev; 4067c478bd9Sstevel@tonic-gate ip->i_udf = udf_vfsp; 4077c478bd9Sstevel@tonic-gate ip->i_diroff = 0; 4087c478bd9Sstevel@tonic-gate ip->i_devvp = ip->i_udf->udf_devvp; 4097c478bd9Sstevel@tonic-gate ip->i_icb_prn = prn; 4107c478bd9Sstevel@tonic-gate ip->i_icb_block = ploc; 4117c478bd9Sstevel@tonic-gate ip->i_icb_lbano = loc; 4127c478bd9Sstevel@tonic-gate ip->i_nextr = 0; 4137c478bd9Sstevel@tonic-gate ip->i_seq = 0; 4147c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate read_de: 4177c478bd9Sstevel@tonic-gate if (pbp != NULL) { 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * assumption is that we will not 4207c478bd9Sstevel@tonic-gate * create a 4096 file 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate bp = pbp; 4237c478bd9Sstevel@tonic-gate } else { 4247c478bd9Sstevel@tonic-gate bp = ud_bread(ip->i_dev, 4257c478bd9Sstevel@tonic-gate ip->i_icb_lbano << udf_vfsp->udf_l2d_shift, 4267c478bd9Sstevel@tonic-gate udf_vfsp->udf_lbsize); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * Check I/O errors 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate fe = (struct file_entry *)bp->b_un.b_addr; 4337c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_ERROR) || 4347c478bd9Sstevel@tonic-gate (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 4357c478bd9Sstevel@tonic-gate ip->i_icb_block, 1, udf_vfsp->udf_lbsize) != 0)) { 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (((bp->b_flags & B_ERROR) == 0) && 4387c478bd9Sstevel@tonic-gate (ftype == STRAT_TYPE4096)) { 4397c478bd9Sstevel@tonic-gate if (ud_check_te_unrec(udf_vfsp, 4407c478bd9Sstevel@tonic-gate bp->b_un.b_addr, ip->i_icb_block) == 0) { 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate brelse(bp); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * restore old file entry location 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate ip->i_icb_prn = old_prn; 4487c478bd9Sstevel@tonic-gate ip->i_icb_block = old_block; 4497c478bd9Sstevel@tonic-gate ip->i_icb_lbano = old_lbano; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * reread old file entry 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate bp = ud_bread(ip->i_dev, 4557c478bd9Sstevel@tonic-gate old_lbano << udf_vfsp->udf_l2d_shift, 4567c478bd9Sstevel@tonic-gate udf_vfsp->udf_lbsize); 4577c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_ERROR) == 0) { 4587c478bd9Sstevel@tonic-gate fe = (struct file_entry *) 4597c478bd9Sstevel@tonic-gate bp->b_un.b_addr; 4607c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&fe->fe_tag, 461b39a0235SMilan Cermak UD_FILE_ENTRY, ip->i_icb_block, 1, 4627c478bd9Sstevel@tonic-gate udf_vfsp->udf_lbsize) == 0) { 4637c478bd9Sstevel@tonic-gate goto end_4096; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate error_ret: 4697c478bd9Sstevel@tonic-gate brelse(bp); 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * The inode may not contain anything useful. Mark it as 4727c478bd9Sstevel@tonic-gate * having an error and let anyone else who was waiting for 4737c478bd9Sstevel@tonic-gate * this know there was an error. Callers waiting for 4747c478bd9Sstevel@tonic-gate * access to this inode in ud_iget will find 4757c478bd9Sstevel@tonic-gate * the i_icb_lbano == 0, so there won't be a match. 4767c478bd9Sstevel@tonic-gate * It remains in the cache. Put it back on the freelist. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 4797c478bd9Sstevel@tonic-gate vp->v_count--; 4807c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 4817c478bd9Sstevel@tonic-gate ip->i_icb_lbano = 0; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* 4847c478bd9Sstevel@tonic-gate * The folowing two lines make 4857c478bd9Sstevel@tonic-gate * it impossible for any one do 4867c478bd9Sstevel@tonic-gate * a VN_HOLD and then a VN_RELE 4877c478bd9Sstevel@tonic-gate * so avoiding a ud_iinactive 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate ip->i_icb_prn = 0xffff; 4907c478bd9Sstevel@tonic-gate ip->i_icb_block = 0; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate /* 4937c478bd9Sstevel@tonic-gate * remove the bad inode from hash chains 4947c478bd9Sstevel@tonic-gate * so that during unmount we will not 4957c478bd9Sstevel@tonic-gate * go through this inode 4967c478bd9Sstevel@tonic-gate */ 4977c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 4987c478bd9Sstevel@tonic-gate remque(ip); 4997c478bd9Sstevel@tonic-gate ip->i_forw = ip; 5007c478bd9Sstevel@tonic-gate ip->i_back = ip; 5017c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* Put the inode at the front of the freelist */ 5047c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 5057c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 5067c478bd9Sstevel@tonic-gate ud_add_to_free_list(ip, UD_BEGIN); 5077c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 5087c478bd9Sstevel@tonic-gate ip->i_flag = 0; 5097c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 5107c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 5117c478bd9Sstevel@tonic-gate return (EIO); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) { 5157c478bd9Sstevel@tonic-gate struct buf *ibp = NULL; 5167c478bd9Sstevel@tonic-gate struct indirect_entry *ie; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * save old file_entry location 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate old_prn = ip->i_icb_prn; 5227c478bd9Sstevel@tonic-gate old_block = ip->i_icb_block; 5237c478bd9Sstevel@tonic-gate old_lbano = ip->i_icb_lbano; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate ftype = STRAT_TYPE4096; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * If astrat is 4096 different versions 5297c478bd9Sstevel@tonic-gate * of the file exist on the media. 5307c478bd9Sstevel@tonic-gate * we are supposed to get to the latest 5317c478bd9Sstevel@tonic-gate * version of the file 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * IE is supposed to be in the next block 5367c478bd9Sstevel@tonic-gate * of DE 5377c478bd9Sstevel@tonic-gate */ 538b39a0235SMilan Cermak ibp = ud_bread(ip->i_dev, 539b39a0235SMilan Cermak (ip->i_icb_lbano + 1) << udf_vfsp->udf_l2d_shift, 5407c478bd9Sstevel@tonic-gate udf_vfsp->udf_lbsize); 5417c478bd9Sstevel@tonic-gate if (ibp->b_flags & B_ERROR) { 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * Get rid of current ibp and 5447c478bd9Sstevel@tonic-gate * then goto error on DE's bp 5457c478bd9Sstevel@tonic-gate */ 5467c478bd9Sstevel@tonic-gate ie_error: 5477c478bd9Sstevel@tonic-gate brelse(ibp); 5487c478bd9Sstevel@tonic-gate goto error_ret; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate ie = (struct indirect_entry *)ibp->b_un.b_addr; 5527c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&ie->ie_tag, 553b39a0235SMilan Cermak UD_INDIRECT_ENT, ip->i_icb_block + 1, 5547c478bd9Sstevel@tonic-gate 1, udf_vfsp->udf_lbsize) == 0) { 5557c478bd9Sstevel@tonic-gate struct long_ad *lad; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate lad = &ie->ie_indirecticb; 5587c478bd9Sstevel@tonic-gate ip->i_icb_prn = SWAP_16(lad->lad_ext_prn); 5597c478bd9Sstevel@tonic-gate ip->i_icb_block = SWAP_32(lad->lad_ext_loc); 5607c478bd9Sstevel@tonic-gate ip->i_icb_lbano = ud_xlate_to_daddr(udf_vfsp, 5617c478bd9Sstevel@tonic-gate ip->i_icb_prn, ip->i_icb_block, 5627c478bd9Sstevel@tonic-gate 1, &dummy); 5637c478bd9Sstevel@tonic-gate brelse(ibp); 5647c478bd9Sstevel@tonic-gate brelse(bp); 5657c478bd9Sstevel@tonic-gate goto read_de; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * If this block is TE or unrecorded we 5707c478bd9Sstevel@tonic-gate * are at the last entry 5717c478bd9Sstevel@tonic-gate */ 5727c478bd9Sstevel@tonic-gate if (ud_check_te_unrec(udf_vfsp, ibp->b_un.b_addr, 5737c478bd9Sstevel@tonic-gate ip->i_icb_block + 1) != 0) { 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * This is not an unrecorded block 5767c478bd9Sstevel@tonic-gate * Check if it a valid IE and 5777c478bd9Sstevel@tonic-gate * get the address of DE that 5787c478bd9Sstevel@tonic-gate * this IE points to 5797c478bd9Sstevel@tonic-gate */ 5807c478bd9Sstevel@tonic-gate goto ie_error; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate /* 5837c478bd9Sstevel@tonic-gate * If ud_check_unrec returns "0" 5847c478bd9Sstevel@tonic-gate * this is the last in the chain 5857c478bd9Sstevel@tonic-gate * Latest file_entry 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate brelse(ibp); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate end_4096: 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate ip->i_uid = SWAP_32(fe->fe_uid); 5937c478bd9Sstevel@tonic-gate if (ip->i_uid == -1) { 5947c478bd9Sstevel@tonic-gate ip->i_uid = ud_default_uid; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate ip->i_gid = SWAP_32(fe->fe_gid); 5977c478bd9Sstevel@tonic-gate if (ip->i_gid == -1) { 5987c478bd9Sstevel@tonic-gate ip->i_gid = ud_default_gid; 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate ip->i_perm = SWAP_32(fe->fe_perms) & 0xFFFF; 601b39a0235SMilan Cermak if (fe->fe_icb_tag.itag_strategy == SWAP_16(STRAT_TYPE4096)) { 6027c478bd9Sstevel@tonic-gate ip->i_perm &= ~(IWRITE | (IWRITE >> 5) | (IWRITE >> 10)); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate ip->i_nlink = SWAP_16(fe->fe_lcount); 6067c478bd9Sstevel@tonic-gate ip->i_size = SWAP_64(fe->fe_info_len); 6077c478bd9Sstevel@tonic-gate ip->i_lbr = SWAP_64(fe->fe_lbr); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate ud_dtime2utime(&ip->i_atime, &fe->fe_acc_time); 6107c478bd9Sstevel@tonic-gate ud_dtime2utime(&ip->i_mtime, &fe->fe_mod_time); 6117c478bd9Sstevel@tonic-gate ud_dtime2utime(&ip->i_ctime, &fe->fe_attr_time); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate ip->i_uniqid = SWAP_64(fe->fe_uniq_id); 6157c478bd9Sstevel@tonic-gate icb_tag_flags = SWAP_16(fe->fe_icb_tag.itag_flags); 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate if ((fe->fe_icb_tag.itag_ftype == FTYPE_CHAR_DEV) || 6187c478bd9Sstevel@tonic-gate (fe->fe_icb_tag.itag_ftype == FTYPE_BLOCK_DEV)) { 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate eah = (struct ext_attr_hdr *)fe->fe_spec; 6217c478bd9Sstevel@tonic-gate ea_off = GET_32(&eah->eah_ial); 6227c478bd9Sstevel@tonic-gate ea_len = GET_32(&fe->fe_len_ear); 6237c478bd9Sstevel@tonic-gate if (ea_len && (ud_verify_tag_and_desc(&eah->eah_tag, 624b39a0235SMilan Cermak UD_EXT_ATTR_HDR, ip->i_icb_block, 1, 6257c478bd9Sstevel@tonic-gate sizeof (struct file_entry) - 6267c478bd9Sstevel@tonic-gate offsetof(struct file_entry, fe_spec)) == 0)) { 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate while (ea_off < ea_len) { 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * We now check the validity of ea_off. 6317c478bd9Sstevel@tonic-gate * (ea_len - ea_off) should be large enough to 6327c478bd9Sstevel@tonic-gate * hold the attribute header atleast. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate if ((ea_len - ea_off) < 6357c478bd9Sstevel@tonic-gate sizeof (struct attr_hdr)) { 6367c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 637b39a0235SMilan Cermak "ea_len(0x%x) - ea_off(0x%x) is " 638b39a0235SMilan Cermak "too small to hold attr. info. " 639b39a0235SMilan Cermak "blockno 0x%x\n", 6407c478bd9Sstevel@tonic-gate ea_len, ea_off, ip->i_icb_block); 6417c478bd9Sstevel@tonic-gate goto error_ret; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate ah = (struct attr_hdr *)&fe->fe_spec[ea_off]; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * Device Specification EA 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate if ((GET_32(&ah->ahdr_atype) == 12) && 6497c478bd9Sstevel@tonic-gate (ah->ahdr_astype == 1)) { 6507c478bd9Sstevel@tonic-gate struct dev_spec_ear *ds; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if ((ea_len - ea_off) < 6537c478bd9Sstevel@tonic-gate sizeof (struct dev_spec_ear)) { 6547c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 655b39a0235SMilan Cermak "ea_len(0x%x) - " 656b39a0235SMilan Cermak "ea_off(0x%x) is too small " 657b39a0235SMilan Cermak "to hold dev_spec_ear." 658b39a0235SMilan Cermak " blockno 0x%x\n", 659b39a0235SMilan Cermak ea_len, ea_off, 660b39a0235SMilan Cermak ip->i_icb_block); 6617c478bd9Sstevel@tonic-gate goto error_ret; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate ds = (struct dev_spec_ear *)ah; 6647c478bd9Sstevel@tonic-gate ip->i_major = GET_32(&ds->ds_major_id); 6657c478bd9Sstevel@tonic-gate ip->i_minor = GET_32(&ds->ds_minor_id); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* 6697c478bd9Sstevel@tonic-gate * Impl Use EA 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate if ((GET_32(&ah->ahdr_atype) == 2048) && 6727c478bd9Sstevel@tonic-gate (ah->ahdr_astype == 1)) { 6737c478bd9Sstevel@tonic-gate struct iu_ea *iuea; 6747c478bd9Sstevel@tonic-gate struct copy_mgt_info *cmi; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate if ((ea_len - ea_off) < 6777c478bd9Sstevel@tonic-gate sizeof (struct iu_ea)) { 6787c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 6797c478bd9Sstevel@tonic-gate "ea_len(0x%x) - ea_off(0x%x) is too small to hold iu_ea. blockno 0x%x\n", 6807c478bd9Sstevel@tonic-gate ea_len, ea_off, 6817c478bd9Sstevel@tonic-gate ip->i_icb_block); 6827c478bd9Sstevel@tonic-gate goto error_ret; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate iuea = (struct iu_ea *)ah; 6857c478bd9Sstevel@tonic-gate if (strncmp(iuea->iuea_ii.reg_id, 6867c478bd9Sstevel@tonic-gate UDF_FREEEASPACE, 6877c478bd9Sstevel@tonic-gate sizeof (iuea->iuea_ii.reg_id)) 6887c478bd9Sstevel@tonic-gate == 0) { 6897c478bd9Sstevel@tonic-gate /* skip it */ 6907c478bd9Sstevel@tonic-gate iuea = iuea; 6917c478bd9Sstevel@tonic-gate } else if (strncmp(iuea->iuea_ii.reg_id, 6927c478bd9Sstevel@tonic-gate UDF_CGMS_INFO, 6937c478bd9Sstevel@tonic-gate sizeof (iuea->iuea_ii.reg_id)) 6947c478bd9Sstevel@tonic-gate == 0) { 6957c478bd9Sstevel@tonic-gate cmi = (struct copy_mgt_info *) 6967c478bd9Sstevel@tonic-gate iuea->iuea_iu; 6977c478bd9Sstevel@tonic-gate cmi = cmi; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate /* ??? PARANOIA */ 7017c478bd9Sstevel@tonic-gate if (GET_32(&ah->ahdr_length) == 0) { 7027c478bd9Sstevel@tonic-gate break; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate ea_off += GET_32(&ah->ahdr_length); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate ip->i_nextr = 0; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate ip->i_maxent = SWAP_16(fe->fe_icb_tag.itag_max_ent); 7127c478bd9Sstevel@tonic-gate ip->i_astrat = SWAP_16(fe->fe_icb_tag.itag_strategy); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate ip->i_desc_type = icb_tag_flags & 0x7; 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* Strictly Paranoia */ 7177c478bd9Sstevel@tonic-gate ip->i_ext = NULL; 7187c478bd9Sstevel@tonic-gate ip->i_ext_count = ip->i_ext_used = 0; 7197c478bd9Sstevel@tonic-gate ip->i_con = 0; 7207c478bd9Sstevel@tonic-gate ip->i_con_count = ip->i_con_used = ip->i_con_read = 0; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate ip->i_data_off = 0xB0 + SWAP_32(fe->fe_len_ear); 7237c478bd9Sstevel@tonic-gate ip->i_max_emb = udf_vfsp->udf_lbsize - ip->i_data_off; 7247c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 7257c478bd9Sstevel@tonic-gate /* Short allocation desc */ 7267c478bd9Sstevel@tonic-gate struct short_ad *sad; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate ip->i_ext_used = 0; 7297c478bd9Sstevel@tonic-gate ip->i_ext_count = ndesc = 7307c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad); 731b39a0235SMilan Cermak ip->i_ext_count = 732b39a0235SMilan Cermak ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC; 7337c478bd9Sstevel@tonic-gate ip->i_ext = (struct icb_ext *)kmem_zalloc(ip->i_ext_count * 7347c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), KM_SLEEP); 7357c478bd9Sstevel@tonic-gate ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct short_ad); 7367c478bd9Sstevel@tonic-gate ip->i_cur_max_ext --; 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate if ((ip->i_astrat != STRAT_TYPE4) && 7397c478bd9Sstevel@tonic-gate (ip->i_astrat != STRAT_TYPE4096)) { 7407c478bd9Sstevel@tonic-gate goto error_ret; 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate sad = (struct short_ad *) 7447c478bd9Sstevel@tonic-gate (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 7457c478bd9Sstevel@tonic-gate iext = ip->i_ext; 7467c478bd9Sstevel@tonic-gate while (ndesc --) { 7477c478bd9Sstevel@tonic-gate length = SWAP_32(sad->sad_ext_len); 7487c478bd9Sstevel@tonic-gate if ((length & 0x3FFFFFFF) == 0) { 7497c478bd9Sstevel@tonic-gate break; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate if (((length >> 30) & IB_MASK) == IB_CON) { 7527c478bd9Sstevel@tonic-gate if (ip->i_con == NULL) { 7537c478bd9Sstevel@tonic-gate ip->i_con_count = EXT_PER_MALLOC; 7547c478bd9Sstevel@tonic-gate ip->i_con_used = 0; 7557c478bd9Sstevel@tonic-gate ip->i_con_read = 0; 7567c478bd9Sstevel@tonic-gate ip->i_con = kmem_zalloc( 7577c478bd9Sstevel@tonic-gate ip->i_con_count * 7587c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), 7597c478bd9Sstevel@tonic-gate KM_SLEEP); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate con = &ip->i_con[ip->i_con_used]; 7627c478bd9Sstevel@tonic-gate con->ib_prn = 0; 7637c478bd9Sstevel@tonic-gate con->ib_block = SWAP_32(sad->sad_ext_loc); 7647c478bd9Sstevel@tonic-gate con->ib_count = length & 0x3FFFFFFF; 7657c478bd9Sstevel@tonic-gate con->ib_flags = (length >> 30) & IB_MASK; 7667c478bd9Sstevel@tonic-gate ip->i_con_used++; 7677c478bd9Sstevel@tonic-gate sad ++; 7687c478bd9Sstevel@tonic-gate break; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate iext->ib_prn = 0; 7717c478bd9Sstevel@tonic-gate iext->ib_block = SWAP_32(sad->sad_ext_loc); 7727c478bd9Sstevel@tonic-gate length = SWAP_32(sad->sad_ext_len); 7737c478bd9Sstevel@tonic-gate iext->ib_count = length & 0x3FFFFFFF; 7747c478bd9Sstevel@tonic-gate iext->ib_offset = offset; 7757c478bd9Sstevel@tonic-gate iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 7767c478bd9Sstevel@tonic-gate iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 7777c478bd9Sstevel@tonic-gate offset += (iext->ib_count + udf_vfsp->udf_lbmask) & 7787c478bd9Sstevel@tonic-gate (~udf_vfsp->udf_lbmask); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate iext->ib_flags = (length >> 30) & IB_MASK; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate ip->i_ext_used++; 7837c478bd9Sstevel@tonic-gate iext++; 7847c478bd9Sstevel@tonic-gate sad ++; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 7877c478bd9Sstevel@tonic-gate /* Long allocation desc */ 7887c478bd9Sstevel@tonic-gate struct long_ad *lad; 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate ip->i_ext_used = 0; 7917c478bd9Sstevel@tonic-gate ip->i_ext_count = ndesc = 7927c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad); 793b39a0235SMilan Cermak ip->i_ext_count = 794b39a0235SMilan Cermak ((ip->i_ext_count / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC; 7957c478bd9Sstevel@tonic-gate ip->i_ext = (struct icb_ext *)kmem_zalloc(ip->i_ext_count * 7967c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), KM_SLEEP); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct long_ad); 7997c478bd9Sstevel@tonic-gate ip->i_cur_max_ext --; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if ((ip->i_astrat != STRAT_TYPE4) && 8027c478bd9Sstevel@tonic-gate (ip->i_astrat != STRAT_TYPE4096)) { 8037c478bd9Sstevel@tonic-gate goto error_ret; 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate lad = (struct long_ad *) 8077c478bd9Sstevel@tonic-gate (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 8087c478bd9Sstevel@tonic-gate iext = ip->i_ext; 8097c478bd9Sstevel@tonic-gate while (ndesc --) { 8107c478bd9Sstevel@tonic-gate length = SWAP_32(lad->lad_ext_len); 8117c478bd9Sstevel@tonic-gate if ((length & 0x3FFFFFFF) == 0) { 8127c478bd9Sstevel@tonic-gate break; 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate if (((length >> 30) & IB_MASK) == IB_CON) { 8157c478bd9Sstevel@tonic-gate if (ip->i_con == NULL) { 8167c478bd9Sstevel@tonic-gate ip->i_con_count = EXT_PER_MALLOC; 8177c478bd9Sstevel@tonic-gate ip->i_con_used = 0; 8187c478bd9Sstevel@tonic-gate ip->i_con_read = 0; 8197c478bd9Sstevel@tonic-gate ip->i_con = kmem_zalloc( 8207c478bd9Sstevel@tonic-gate ip->i_con_count * 8217c478bd9Sstevel@tonic-gate sizeof (struct icb_ext), 8227c478bd9Sstevel@tonic-gate KM_SLEEP); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate con = &ip->i_con[ip->i_con_used]; 8257c478bd9Sstevel@tonic-gate con->ib_prn = SWAP_16(lad->lad_ext_prn); 8267c478bd9Sstevel@tonic-gate con->ib_block = SWAP_32(lad->lad_ext_loc); 8277c478bd9Sstevel@tonic-gate con->ib_count = length & 0x3FFFFFFF; 8287c478bd9Sstevel@tonic-gate con->ib_flags = (length >> 30) & IB_MASK; 8297c478bd9Sstevel@tonic-gate ip->i_con_used++; 8307c478bd9Sstevel@tonic-gate lad ++; 8317c478bd9Sstevel@tonic-gate break; 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate iext->ib_prn = SWAP_16(lad->lad_ext_prn); 8347c478bd9Sstevel@tonic-gate iext->ib_block = SWAP_32(lad->lad_ext_loc); 8357c478bd9Sstevel@tonic-gate iext->ib_count = length & 0x3FFFFFFF; 8367c478bd9Sstevel@tonic-gate iext->ib_offset = offset; 8377c478bd9Sstevel@tonic-gate iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 8387c478bd9Sstevel@tonic-gate iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 8397c478bd9Sstevel@tonic-gate offset += (iext->ib_count + udf_vfsp->udf_lbmask) & 8407c478bd9Sstevel@tonic-gate (~udf_vfsp->udf_lbmask); 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate iext->ib_flags = (length >> 30) & IB_MASK; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate ip->i_ext_used++; 8457c478bd9Sstevel@tonic-gate iext++; 8467c478bd9Sstevel@tonic-gate lad ++; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 8497c478bd9Sstevel@tonic-gate ASSERT(SWAP_32(fe->fe_len_ear) < udf_vfsp->udf_lbsize); 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate if (SWAP_32(fe->fe_len_ear) > udf_vfsp->udf_lbsize) { 8527c478bd9Sstevel@tonic-gate goto error_ret; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate } else { 8557c478bd9Sstevel@tonic-gate /* Not to be used in UDF 1.50 */ 8567c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "Invalid Allocation Descriptor type %x\n", 8577c478bd9Sstevel@tonic-gate ip->i_desc_type); 8587c478bd9Sstevel@tonic-gate goto error_ret; 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate if (icb_tag_flags & ICB_FLAG_SETUID) { 8637c478bd9Sstevel@tonic-gate ip->i_char = ISUID; 8647c478bd9Sstevel@tonic-gate } else { 8657c478bd9Sstevel@tonic-gate ip->i_char = 0; 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate if (icb_tag_flags & ICB_FLAG_SETGID) { 8687c478bd9Sstevel@tonic-gate ip->i_char |= ISGID; 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate if (icb_tag_flags & ICB_FLAG_STICKY) { 8717c478bd9Sstevel@tonic-gate ip->i_char |= ISVTX; 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate switch (fe->fe_icb_tag.itag_ftype) { 8747c478bd9Sstevel@tonic-gate case FTYPE_DIRECTORY : 8757c478bd9Sstevel@tonic-gate ip->i_type = VDIR; 8767c478bd9Sstevel@tonic-gate break; 8777c478bd9Sstevel@tonic-gate case FTYPE_FILE : 8787c478bd9Sstevel@tonic-gate ip->i_type = VREG; 8797c478bd9Sstevel@tonic-gate break; 8807c478bd9Sstevel@tonic-gate case FTYPE_BLOCK_DEV : 8817c478bd9Sstevel@tonic-gate ip->i_type = VBLK; 8827c478bd9Sstevel@tonic-gate break; 8837c478bd9Sstevel@tonic-gate case FTYPE_CHAR_DEV : 8847c478bd9Sstevel@tonic-gate ip->i_type = VCHR; 8857c478bd9Sstevel@tonic-gate break; 8867c478bd9Sstevel@tonic-gate case FTYPE_FIFO : 8877c478bd9Sstevel@tonic-gate ip->i_type = VFIFO; 8887c478bd9Sstevel@tonic-gate break; 8897c478bd9Sstevel@tonic-gate case FTYPE_C_ISSOCK : 8907c478bd9Sstevel@tonic-gate ip->i_type = VSOCK; 8917c478bd9Sstevel@tonic-gate break; 8927c478bd9Sstevel@tonic-gate case FTYPE_SYMLINK : 8937c478bd9Sstevel@tonic-gate ip->i_type = VLNK; 8947c478bd9Sstevel@tonic-gate break; 8957c478bd9Sstevel@tonic-gate default : 8967c478bd9Sstevel@tonic-gate ip->i_type = VNON; 8977c478bd9Sstevel@tonic-gate break; 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate if (ip->i_type == VBLK || ip->i_type == VCHR) { 9017c478bd9Sstevel@tonic-gate ip->i_rdev = makedevice(ip->i_major, ip->i_minor); 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate /* 9057c478bd9Sstevel@tonic-gate * Fill in the rest. Don't bother with the vnode lock because nobody 9067c478bd9Sstevel@tonic-gate * should be looking at this vnode. We have already invalidated the 9077c478bd9Sstevel@tonic-gate * pages if it had any so pageout shouldn't be referencing this vnode 9087c478bd9Sstevel@tonic-gate * and we are holding the write contents lock so a look up can't use 9097c478bd9Sstevel@tonic-gate * the vnode. 9107c478bd9Sstevel@tonic-gate */ 9117c478bd9Sstevel@tonic-gate vp->v_vfsp = vfsp; 9127c478bd9Sstevel@tonic-gate vp->v_type = ip->i_type; 9137c478bd9Sstevel@tonic-gate vp->v_rdev = ip->i_rdev; 9147c478bd9Sstevel@tonic-gate if (ip->i_udf->udf_root_blkno == loc) { 9157c478bd9Sstevel@tonic-gate vp->v_flag = VROOT; 9167c478bd9Sstevel@tonic-gate } else { 9177c478bd9Sstevel@tonic-gate vp->v_flag = 0; 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate brelse(bp); 9217c478bd9Sstevel@tonic-gate *ipp = ip; 9227c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 9237c478bd9Sstevel@tonic-gate vn_exists(vp); 9247c478bd9Sstevel@tonic-gate return (0); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate void 9287c478bd9Sstevel@tonic-gate ud_iinactive(struct ud_inode *ip, struct cred *cr) 9297c478bd9Sstevel@tonic-gate { 9307c478bd9Sstevel@tonic-gate int32_t busy = 0; 9317c478bd9Sstevel@tonic-gate struct vnode *vp; 9327c478bd9Sstevel@tonic-gate vtype_t type; 9337c478bd9Sstevel@tonic-gate caddr_t addr, addr1; 9347c478bd9Sstevel@tonic-gate size_t size, size1; 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate ud_printf("ud_iinactive\n"); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * Get exclusive access to inode data. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate /* 9457c478bd9Sstevel@tonic-gate * Make sure no one reclaimed the inode before we put 9467c478bd9Sstevel@tonic-gate * it on the freelist or destroy it. We keep our 'hold' 9477c478bd9Sstevel@tonic-gate * on the vnode from vn_rele until we are ready to 9487c478bd9Sstevel@tonic-gate * do something with the inode (freelist/destroy). 9497c478bd9Sstevel@tonic-gate * 9507c478bd9Sstevel@tonic-gate * Pageout may put a VN_HOLD/VN_RELE at anytime during this 9517c478bd9Sstevel@tonic-gate * operation via an async putpage, so we must make sure 9527c478bd9Sstevel@tonic-gate * we don't free/destroy the inode more than once. ud_iget 9537c478bd9Sstevel@tonic-gate * may also put a VN_HOLD on the inode before it grabs 9547c478bd9Sstevel@tonic-gate * the i_contents lock. This is done so we don't kmem_free 9557c478bd9Sstevel@tonic-gate * an inode that a thread is waiting on. 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate vp = ITOV(ip); 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 9607c478bd9Sstevel@tonic-gate if (vp->v_count < 1) { 9617c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iinactive: v_count < 1\n"); 9627c478bd9Sstevel@tonic-gate return; 9637c478bd9Sstevel@tonic-gate } 964b39a0235SMilan Cermak if ((vp->v_count > 1) || ((ip->i_flag & IREF) == 0)) { 9657c478bd9Sstevel@tonic-gate vp->v_count--; /* release our hold from vn_rele */ 9667c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 9677c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 9687c478bd9Sstevel@tonic-gate return; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * For forced umount case: if i_udf is NULL, the contents of 9747c478bd9Sstevel@tonic-gate * the inode and all the pages have already been pushed back 9757c478bd9Sstevel@tonic-gate * to disk. It can be safely destroyed. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate if (ip->i_udf == NULL) { 9787c478bd9Sstevel@tonic-gate addr = (caddr_t)ip->i_ext; 9797c478bd9Sstevel@tonic-gate size = sizeof (struct icb_ext) * ip->i_ext_count; 9807c478bd9Sstevel@tonic-gate ip->i_ext = 0; 9817c478bd9Sstevel@tonic-gate ip->i_ext_count = ip->i_ext_used = 0; 9827c478bd9Sstevel@tonic-gate addr1 = (caddr_t)ip->i_con; 9837c478bd9Sstevel@tonic-gate size1 = sizeof (struct icb_ext) * ip->i_con_count; 9847c478bd9Sstevel@tonic-gate ip->i_con = 0; 9857c478bd9Sstevel@tonic-gate ip->i_con_count = ip->i_con_used = ip->i_con_read = 0; 9867c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 9877c478bd9Sstevel@tonic-gate vn_invalid(vp); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 9907c478bd9Sstevel@tonic-gate ud_cur_inodes--; 9917c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate cv_destroy(&ip->i_wrcv); /* throttling */ 9947c478bd9Sstevel@tonic-gate rw_destroy(&ip->i_rwlock); 9957c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 9967c478bd9Sstevel@tonic-gate rw_destroy(&ip->i_contents); 9977c478bd9Sstevel@tonic-gate kmem_free(addr, size); 9987c478bd9Sstevel@tonic-gate kmem_free(addr1, size1); 9997c478bd9Sstevel@tonic-gate vn_free(vp); 10007c478bd9Sstevel@tonic-gate kmem_free(ip, sizeof (struct ud_inode)); 10017c478bd9Sstevel@tonic-gate return; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate if ((ip->i_udf->udf_flags & UDF_FL_RDONLY) == 0) { 10057c478bd9Sstevel@tonic-gate if (ip->i_nlink <= 0) { 10067c478bd9Sstevel@tonic-gate ip->i_marker3 = (uint32_t)0xDDDD0000; 10077c478bd9Sstevel@tonic-gate ip->i_nlink = 1; /* prevent free-ing twice */ 10087c478bd9Sstevel@tonic-gate (void) ud_itrunc(ip, 0, 0, cr); 10097c478bd9Sstevel@tonic-gate type = ip->i_type; 10107c478bd9Sstevel@tonic-gate ip->i_perm = 0; 10117c478bd9Sstevel@tonic-gate ip->i_uid = 0; 10127c478bd9Sstevel@tonic-gate ip->i_gid = 0; 10137c478bd9Sstevel@tonic-gate ip->i_rdev = 0; /* Zero in core version of rdev */ 10147c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 10157c478bd9Sstevel@tonic-gate ip->i_flag |= IUPD|ICHG; 10167c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 10177c478bd9Sstevel@tonic-gate ud_ifree(ip, type); 10187c478bd9Sstevel@tonic-gate ip->i_icb_prn = 0xFFFF; 10197c478bd9Sstevel@tonic-gate } else if (!IS_SWAPVP(vp)) { 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * Write the inode out if dirty. Pages are 10227c478bd9Sstevel@tonic-gate * written back and put on the freelist. 10237c478bd9Sstevel@tonic-gate */ 10247c478bd9Sstevel@tonic-gate (void) ud_syncip(ip, B_FREE | B_ASYNC, 0); 10257c478bd9Sstevel@tonic-gate /* 10267c478bd9Sstevel@tonic-gate * Do nothing if inode is now busy -- inode may 10277c478bd9Sstevel@tonic-gate * have gone busy because ud_syncip 10287c478bd9Sstevel@tonic-gate * releases/reacquires the i_contents lock 10297c478bd9Sstevel@tonic-gate */ 10307c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 10317c478bd9Sstevel@tonic-gate if (vp->v_count > 1) { 10327c478bd9Sstevel@tonic-gate vp->v_count--; 10337c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 10347c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 10357c478bd9Sstevel@tonic-gate return; 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 10387c478bd9Sstevel@tonic-gate } else { 10397c478bd9Sstevel@tonic-gate ud_iupdat(ip, 0); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate /* 10457c478bd9Sstevel@tonic-gate * Put the inode on the end of the free list. 10467c478bd9Sstevel@tonic-gate * Possibly in some cases it would be better to 10477c478bd9Sstevel@tonic-gate * put the inode at the head of the free list, 10487c478bd9Sstevel@tonic-gate * (e.g.: where i_perm == 0 || i_number == 0) 10497c478bd9Sstevel@tonic-gate * but I will think about that later. 10507c478bd9Sstevel@tonic-gate * (i_number is rarely 0 - only after an i/o error in ud_iget, 10517c478bd9Sstevel@tonic-gate * where i_perm == 0, the inode will probably be wanted 10527c478bd9Sstevel@tonic-gate * again soon for an ialloc, so possibly we should keep it) 10537c478bd9Sstevel@tonic-gate */ 10547c478bd9Sstevel@tonic-gate /* 10557c478bd9Sstevel@tonic-gate * If inode is invalid or there is no page associated with 10567c478bd9Sstevel@tonic-gate * this inode, put the inode in the front of the free list. 10577c478bd9Sstevel@tonic-gate * Since we have a VN_HOLD on the vnode, and checked that it 10587c478bd9Sstevel@tonic-gate * wasn't already on the freelist when we entered, we can safely 10597c478bd9Sstevel@tonic-gate * put it on the freelist even if another thread puts a VN_HOLD 10607c478bd9Sstevel@tonic-gate * on it (pageout/ud_iget). 10617c478bd9Sstevel@tonic-gate */ 10627c478bd9Sstevel@tonic-gate tryagain: 10637c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 10647c478bd9Sstevel@tonic-gate if (vn_has_cached_data(vp)) { 10657c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 10667c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 10677c478bd9Sstevel@tonic-gate vp->v_count--; 10687c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 10697c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 10707c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 10717c478bd9Sstevel@tonic-gate ud_add_to_free_list(ip, UD_END); 10727c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 10737c478bd9Sstevel@tonic-gate ip->i_flag &= IMODTIME; 10747c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 10757c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 10767c478bd9Sstevel@tonic-gate } else if (busy || ud_cur_inodes < ud_max_inodes) { 10777c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 10787c478bd9Sstevel@tonic-gate /* 10797c478bd9Sstevel@tonic-gate * We're not over our high water mark, or it's 10807c478bd9Sstevel@tonic-gate * not safe to kmem_free the inode, so put it 10817c478bd9Sstevel@tonic-gate * on the freelist. 10827c478bd9Sstevel@tonic-gate */ 10837c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 10847c478bd9Sstevel@tonic-gate if (vn_has_cached_data(vp)) { 10857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n"); 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate vp->v_count--; 10887c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 10917c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 10927c478bd9Sstevel@tonic-gate ud_add_to_free_list(ip, UD_BEGIN); 10937c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 10947c478bd9Sstevel@tonic-gate ip->i_flag &= IMODTIME; 10957c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 10967c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 10977c478bd9Sstevel@tonic-gate } else { 10987c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 10997c478bd9Sstevel@tonic-gate if (vn_has_cached_data(vp)) { 11007c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ud_iinactive: v_pages not NULL\n"); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate /* 11037c478bd9Sstevel@tonic-gate * Try to free the inode. We must make sure 11047c478bd9Sstevel@tonic-gate * it's o.k. to destroy this inode. We can't destroy 11057c478bd9Sstevel@tonic-gate * if a thread is waiting for this inode. If we can't get the 11067c478bd9Sstevel@tonic-gate * cache now, put it back on the freelist. 11077c478bd9Sstevel@tonic-gate */ 11087c478bd9Sstevel@tonic-gate if (!mutex_tryenter(&ud_icache_lock)) { 11097c478bd9Sstevel@tonic-gate busy = 1; 11107c478bd9Sstevel@tonic-gate goto tryagain; 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 11137c478bd9Sstevel@tonic-gate if (vp->v_count > 1) { 11147c478bd9Sstevel@tonic-gate /* inode is wanted in ud_iget */ 11157c478bd9Sstevel@tonic-gate busy = 1; 11167c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 11177c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 11187c478bd9Sstevel@tonic-gate goto tryagain; 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 11217c478bd9Sstevel@tonic-gate remque(ip); 11227c478bd9Sstevel@tonic-gate ip->i_forw = ip; 11237c478bd9Sstevel@tonic-gate ip->i_back = ip; 11247c478bd9Sstevel@tonic-gate mutex_enter(&ud_nino_lock); 11257c478bd9Sstevel@tonic-gate ud_cur_inodes--; 11267c478bd9Sstevel@tonic-gate mutex_exit(&ud_nino_lock); 11277c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 11287c478bd9Sstevel@tonic-gate if (ip->i_icb_prn != 0xFFFF) { 11297c478bd9Sstevel@tonic-gate ud_iupdat(ip, 0); 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate addr = (caddr_t)ip->i_ext; 11327c478bd9Sstevel@tonic-gate size = sizeof (struct icb_ext) * ip->i_ext_count; 11337c478bd9Sstevel@tonic-gate ip->i_ext = 0; 11347c478bd9Sstevel@tonic-gate ip->i_ext_count = ip->i_ext_used = 0; 11357c478bd9Sstevel@tonic-gate addr1 = (caddr_t)ip->i_con; 11367c478bd9Sstevel@tonic-gate size1 = sizeof (struct icb_ext) * ip->i_con_count; 11377c478bd9Sstevel@tonic-gate ip->i_con = 0; 11387c478bd9Sstevel@tonic-gate ip->i_con_count = ip->i_con_used = ip->i_con_read = 0; 11397c478bd9Sstevel@tonic-gate cv_destroy(&ip->i_wrcv); /* throttling */ 11407c478bd9Sstevel@tonic-gate rw_destroy(&ip->i_rwlock); 11417c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 11427c478bd9Sstevel@tonic-gate rw_destroy(&ip->i_contents); 11437c478bd9Sstevel@tonic-gate kmem_free(addr, size); 11447c478bd9Sstevel@tonic-gate kmem_free(addr1, size1); 11457c478bd9Sstevel@tonic-gate ip->i_marker3 = (uint32_t)0xDDDDDDDD; 11467c478bd9Sstevel@tonic-gate vn_free(vp); 11477c478bd9Sstevel@tonic-gate kmem_free(ip, sizeof (struct ud_inode)); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate void 11537c478bd9Sstevel@tonic-gate ud_iupdat(struct ud_inode *ip, int32_t waitfor) 11547c478bd9Sstevel@tonic-gate { 11557c478bd9Sstevel@tonic-gate uint16_t flag, tag_flags; 1156*ad9a7bd3SRichard Lowe int32_t error; 11577c478bd9Sstevel@tonic-gate struct buf *bp; 11587c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 11597c478bd9Sstevel@tonic-gate struct file_entry *fe; 1160*ad9a7bd3SRichard Lowe uint16_t crc_len = 0; 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ip->i_contents)); 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate ud_printf("ud_iupdat\n"); 11657c478bd9Sstevel@tonic-gate /* 11667c478bd9Sstevel@tonic-gate * Return if file system has been forcibly umounted. 11677c478bd9Sstevel@tonic-gate */ 11687c478bd9Sstevel@tonic-gate if (ip->i_udf == NULL) { 11697c478bd9Sstevel@tonic-gate return; 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 11737c478bd9Sstevel@tonic-gate flag = ip->i_flag; /* Atomic read */ 11747c478bd9Sstevel@tonic-gate if ((flag & (IUPD|IACC|ICHG|IMOD|IMODACC)) != 0) { 11757c478bd9Sstevel@tonic-gate if (udf_vfsp->udf_flags & UDF_FL_RDONLY) { 11767c478bd9Sstevel@tonic-gate ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC|IATTCHG); 11777c478bd9Sstevel@tonic-gate return; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate bp = ud_bread(ip->i_dev, 11817c478bd9Sstevel@tonic-gate ip->i_icb_lbano << udf_vfsp->udf_l2d_shift, 11827c478bd9Sstevel@tonic-gate ip->i_udf->udf_lbsize); 11837c478bd9Sstevel@tonic-gate if (bp->b_flags & B_ERROR) { 11847c478bd9Sstevel@tonic-gate brelse(bp); 11857c478bd9Sstevel@tonic-gate return; 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate fe = (struct file_entry *)bp->b_un.b_addr; 11887c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 11897c478bd9Sstevel@tonic-gate ip->i_icb_block, 11907c478bd9Sstevel@tonic-gate 1, ip->i_udf->udf_lbsize) != 0) { 11917c478bd9Sstevel@tonic-gate brelse(bp); 11927c478bd9Sstevel@tonic-gate return; 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 11967c478bd9Sstevel@tonic-gate if (ip->i_flag & (IUPD|IACC|ICHG)) { 11977c478bd9Sstevel@tonic-gate IMARK(ip); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD|IMODACC); 12007c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate fe->fe_uid = SWAP_32(ip->i_uid); 12037c478bd9Sstevel@tonic-gate fe->fe_gid = SWAP_32(ip->i_gid); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate fe->fe_perms = SWAP_32(ip->i_perm); 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate fe->fe_lcount = SWAP_16(ip->i_nlink); 12087c478bd9Sstevel@tonic-gate fe->fe_info_len = SWAP_64(ip->i_size); 12097c478bd9Sstevel@tonic-gate fe->fe_lbr = SWAP_64(ip->i_lbr); 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate ud_utime2dtime(&ip->i_atime, &fe->fe_acc_time); 12127c478bd9Sstevel@tonic-gate ud_utime2dtime(&ip->i_mtime, &fe->fe_mod_time); 12137c478bd9Sstevel@tonic-gate ud_utime2dtime(&ip->i_ctime, &fe->fe_attr_time); 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate if (ip->i_char & ISUID) { 12167c478bd9Sstevel@tonic-gate tag_flags = ICB_FLAG_SETUID; 12177c478bd9Sstevel@tonic-gate } else { 12187c478bd9Sstevel@tonic-gate tag_flags = 0; 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate if (ip->i_char & ISGID) { 12217c478bd9Sstevel@tonic-gate tag_flags |= ICB_FLAG_SETGID; 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate if (ip->i_char & ISVTX) { 12247c478bd9Sstevel@tonic-gate tag_flags |= ICB_FLAG_STICKY; 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate tag_flags |= ip->i_desc_type; 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate /* 12297c478bd9Sstevel@tonic-gate * Remove the following it is no longer contig 12307c478bd9Sstevel@tonic-gate * if (ip->i_astrat == STRAT_TYPE4) { 12317c478bd9Sstevel@tonic-gate * tag_flags |= ICB_FLAG_CONTIG; 12327c478bd9Sstevel@tonic-gate * } 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate fe->fe_icb_tag.itag_flags &= ~SWAP_16((uint16_t)0x3C3); 12367c478bd9Sstevel@tonic-gate fe->fe_icb_tag.itag_strategy = SWAP_16(ip->i_astrat); 12377c478bd9Sstevel@tonic-gate fe->fe_icb_tag.itag_flags |= SWAP_16(tag_flags); 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate ud_update_regid(&fe->fe_impl_id); 12407c478bd9Sstevel@tonic-gate 1241*ad9a7bd3SRichard Lowe crc_len = offsetof(struct file_entry, fe_spec) + 12427c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_ear); 12437c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 12447c478bd9Sstevel@tonic-gate crc_len += ip->i_size; 12457c478bd9Sstevel@tonic-gate fe->fe_len_adesc = SWAP_32(((uint32_t)ip->i_size)); 1246b39a0235SMilan Cermak } else if ((ip->i_size != 0) && (ip->i_ext != NULL) && 12477c478bd9Sstevel@tonic-gate (ip->i_ext_used != 0)) { 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, 12507c478bd9Sstevel@tonic-gate ip->i_size)) == 0) { 12517c478bd9Sstevel@tonic-gate if (ip->i_astrat == STRAT_TYPE4) { 12527c478bd9Sstevel@tonic-gate error = ud_updat_ext4(ip, fe); 12537c478bd9Sstevel@tonic-gate } else if (ip->i_astrat == STRAT_TYPE4096) { 12547c478bd9Sstevel@tonic-gate error = ud_updat_ext4096(ip, fe); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate if (error) { 12577c478bd9Sstevel@tonic-gate udf_vfsp->udf_mark_bad = 1; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate crc_len += SWAP_32(fe->fe_len_adesc); 12617c478bd9Sstevel@tonic-gate } else { 12627c478bd9Sstevel@tonic-gate fe->fe_len_adesc = 0; 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate /* 12667c478bd9Sstevel@tonic-gate * Zero out the rest of the block 12677c478bd9Sstevel@tonic-gate */ 12687c478bd9Sstevel@tonic-gate bzero(bp->b_un.b_addr + crc_len, 12697c478bd9Sstevel@tonic-gate ip->i_udf->udf_lbsize - crc_len); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate ud_make_tag(ip->i_udf, &fe->fe_tag, 12727c478bd9Sstevel@tonic-gate UD_FILE_ENTRY, ip->i_icb_block, crc_len); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate if (waitfor) { 12767c478bd9Sstevel@tonic-gate BWRITE(bp); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * Synchronous write has guaranteed that inode 12807c478bd9Sstevel@tonic-gate * has been written on disk so clear the flag 12817c478bd9Sstevel@tonic-gate */ 12827c478bd9Sstevel@tonic-gate ip->i_flag &= ~(IBDWRITE); 12837c478bd9Sstevel@tonic-gate } else { 12847c478bd9Sstevel@tonic-gate bdwrite(bp); 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* 12877c478bd9Sstevel@tonic-gate * This write hasn't guaranteed that inode has been 12887c478bd9Sstevel@tonic-gate * written on the disk. 12897c478bd9Sstevel@tonic-gate * Since, all updat flags on indoe are cleared, we must 12907c478bd9Sstevel@tonic-gate * remember the condition in case inode is to be updated 12917c478bd9Sstevel@tonic-gate * synchronously later (e.g.- fsync()/fdatasync()) 12927c478bd9Sstevel@tonic-gate * and inode has not been modified yet. 12937c478bd9Sstevel@tonic-gate */ 12947c478bd9Sstevel@tonic-gate ip->i_flag |= (IBDWRITE); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate } else { 12977c478bd9Sstevel@tonic-gate /* 12987c478bd9Sstevel@tonic-gate * In case previous inode update was done asynchronously 12997c478bd9Sstevel@tonic-gate * (IBDWRITE) and this inode update request wants guaranteed 13007c478bd9Sstevel@tonic-gate * (synchronous) disk update, flush the inode. 13017c478bd9Sstevel@tonic-gate */ 13027c478bd9Sstevel@tonic-gate if (waitfor && (flag & IBDWRITE)) { 1303b39a0235SMilan Cermak blkflush(ip->i_dev, 1304b39a0235SMilan Cermak (daddr_t)fsbtodb(udf_vfsp, ip->i_icb_lbano)); 13057c478bd9Sstevel@tonic-gate ip->i_flag &= ~(IBDWRITE); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate int32_t 13117c478bd9Sstevel@tonic-gate ud_updat_ext4(struct ud_inode *ip, struct file_entry *fe) 13127c478bd9Sstevel@tonic-gate { 13137c478bd9Sstevel@tonic-gate uint32_t dummy; 13147c478bd9Sstevel@tonic-gate int32_t elen, ndent, index, count, con_index; 13157c478bd9Sstevel@tonic-gate daddr_t bno; 13167c478bd9Sstevel@tonic-gate struct buf *bp; 13177c478bd9Sstevel@tonic-gate struct short_ad *sad; 13187c478bd9Sstevel@tonic-gate struct long_ad *lad; 13197c478bd9Sstevel@tonic-gate struct icb_ext *iext, *icon; 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate ASSERT(ip); 13237c478bd9Sstevel@tonic-gate ASSERT(fe); 13247c478bd9Sstevel@tonic-gate ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) || 13257c478bd9Sstevel@tonic-gate (ip->i_desc_type == ICB_FLAG_LONG_AD)); 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 13287c478bd9Sstevel@tonic-gate elen = sizeof (struct short_ad); 13297c478bd9Sstevel@tonic-gate sad = (struct short_ad *) 13307c478bd9Sstevel@tonic-gate (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 13317c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 13327c478bd9Sstevel@tonic-gate elen = sizeof (struct long_ad); 13337c478bd9Sstevel@tonic-gate lad = (struct long_ad *) 13347c478bd9Sstevel@tonic-gate (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 13357c478bd9Sstevel@tonic-gate } else { 13367c478bd9Sstevel@tonic-gate /* This cannot happen return */ 13377c478bd9Sstevel@tonic-gate return (EINVAL); 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate ndent = ip->i_max_emb / elen; 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (ip->i_ext_used < ndent) { 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 13457c478bd9Sstevel@tonic-gate ud_make_sad(ip->i_ext, sad, ip->i_ext_used); 13467c478bd9Sstevel@tonic-gate } else { 13477c478bd9Sstevel@tonic-gate ud_make_lad(ip->i_ext, lad, ip->i_ext_used); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate fe->fe_len_adesc = SWAP_32(ip->i_ext_used * elen); 13507c478bd9Sstevel@tonic-gate con_index = 0; 13517c478bd9Sstevel@tonic-gate } else { 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate con_index = index = 0; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate while (index < ip->i_ext_used) { 13567c478bd9Sstevel@tonic-gate if (index == 0) { 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate * bp is already read 13597c478bd9Sstevel@tonic-gate * First few extents will go 13607c478bd9Sstevel@tonic-gate * into the file_entry 13617c478bd9Sstevel@tonic-gate */ 13627c478bd9Sstevel@tonic-gate count = ndent - 1; 1363b39a0235SMilan Cermak fe->fe_len_adesc = SWAP_32(ndent * elen); 13647c478bd9Sstevel@tonic-gate bp = NULL; 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate /* 13677c478bd9Sstevel@tonic-gate * Last entry to be cont ext 13687c478bd9Sstevel@tonic-gate */ 13697c478bd9Sstevel@tonic-gate icon = &ip->i_con[con_index]; 13707c478bd9Sstevel@tonic-gate } else { 13717c478bd9Sstevel@tonic-gate /* 13727c478bd9Sstevel@tonic-gate * Read the buffer 13737c478bd9Sstevel@tonic-gate */ 13747c478bd9Sstevel@tonic-gate icon = &ip->i_con[con_index]; 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate bno = ud_xlate_to_daddr(ip->i_udf, 13777c478bd9Sstevel@tonic-gate icon->ib_prn, icon->ib_block, 1378b39a0235SMilan Cermak icon->ib_count >> ip->i_udf->udf_l2d_shift, 1379b39a0235SMilan Cermak &dummy); 1380b39a0235SMilan Cermak bp = ud_bread(ip->i_dev, 1381b39a0235SMilan Cermak bno << ip->i_udf->udf_l2d_shift, 13827c478bd9Sstevel@tonic-gate ip->i_udf->udf_lbsize); 13837c478bd9Sstevel@tonic-gate if (bp->b_flags & B_ERROR) { 13847c478bd9Sstevel@tonic-gate brelse(bp); 13857c478bd9Sstevel@tonic-gate return (EIO); 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* 13897c478bd9Sstevel@tonic-gate * Figure out how many extents in 13907c478bd9Sstevel@tonic-gate * this time 13917c478bd9Sstevel@tonic-gate */ 13927c478bd9Sstevel@tonic-gate count = (bp->b_bcount - 13937c478bd9Sstevel@tonic-gate sizeof (struct alloc_ext_desc)) / elen; 13947c478bd9Sstevel@tonic-gate if (count > (ip->i_ext_used - index)) { 13957c478bd9Sstevel@tonic-gate count = ip->i_ext_used - index; 13967c478bd9Sstevel@tonic-gate } else { 13977c478bd9Sstevel@tonic-gate count --; 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate con_index++; 14007c478bd9Sstevel@tonic-gate if (con_index >= ip->i_con_used) { 14017c478bd9Sstevel@tonic-gate icon = NULL; 14027c478bd9Sstevel@tonic-gate } else { 14037c478bd9Sstevel@tonic-gate icon = &ip->i_con[con_index]; 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate /* 14107c478bd9Sstevel@tonic-gate * convert to on disk form and 14117c478bd9Sstevel@tonic-gate * update 14127c478bd9Sstevel@tonic-gate */ 14137c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 14147c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 14157c478bd9Sstevel@tonic-gate if (index != 0) { 14167c478bd9Sstevel@tonic-gate sad = (struct short_ad *) 14177c478bd9Sstevel@tonic-gate (bp->b_un.b_addr + 14187c478bd9Sstevel@tonic-gate sizeof (struct alloc_ext_desc)); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate ud_make_sad(iext, sad, count); 14217c478bd9Sstevel@tonic-gate sad += count; 14227c478bd9Sstevel@tonic-gate if (icon != NULL) { 14237c478bd9Sstevel@tonic-gate ud_make_sad(icon, sad, 1); 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate } else { 14267c478bd9Sstevel@tonic-gate if (index != 0) { 14277c478bd9Sstevel@tonic-gate lad = (struct long_ad *) 14287c478bd9Sstevel@tonic-gate (bp->b_un.b_addr + 14297c478bd9Sstevel@tonic-gate sizeof (struct alloc_ext_desc)); 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate ud_make_lad(iext, lad, count); 14327c478bd9Sstevel@tonic-gate lad += count; 14337c478bd9Sstevel@tonic-gate if (icon != NULL) { 14347c478bd9Sstevel@tonic-gate ud_make_lad(icon, lad, 1); 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate if (con_index != 0) { 14397c478bd9Sstevel@tonic-gate struct alloc_ext_desc *aed; 14407c478bd9Sstevel@tonic-gate int32_t sz; 14417c478bd9Sstevel@tonic-gate struct icb_ext *oicon; 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate oicon = &ip->i_con[con_index - 1]; 14447c478bd9Sstevel@tonic-gate sz = count * elen; 14457c478bd9Sstevel@tonic-gate if (icon != NULL) { 14467c478bd9Sstevel@tonic-gate sz += elen; 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate aed = (struct alloc_ext_desc *)bp->b_un.b_addr; 14497c478bd9Sstevel@tonic-gate aed->aed_len_aed = SWAP_32(sz); 14507c478bd9Sstevel@tonic-gate if (con_index == 1) { 14517c478bd9Sstevel@tonic-gate aed->aed_rev_ael = 14527c478bd9Sstevel@tonic-gate SWAP_32(ip->i_icb_block); 14537c478bd9Sstevel@tonic-gate } else { 14547c478bd9Sstevel@tonic-gate aed->aed_rev_ael = 14557c478bd9Sstevel@tonic-gate SWAP_32(oicon->ib_block); 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate sz += sizeof (struct alloc_ext_desc); 14587c478bd9Sstevel@tonic-gate ud_make_tag(ip->i_udf, &aed->aed_tag, 14597c478bd9Sstevel@tonic-gate UD_ALLOC_EXT_DESC, oicon->ib_block, sz); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * Write back to disk 14647c478bd9Sstevel@tonic-gate */ 14657c478bd9Sstevel@tonic-gate if (bp != NULL) { 14667c478bd9Sstevel@tonic-gate BWRITE(bp); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate index += count; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate if (con_index != ip->i_con_used) { 14747c478bd9Sstevel@tonic-gate int32_t lbmask, l2b, temp; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate temp = con_index; 14777c478bd9Sstevel@tonic-gate lbmask = ip->i_udf->udf_lbmask; 14787c478bd9Sstevel@tonic-gate l2b = ip->i_udf->udf_l2b_shift; 14797c478bd9Sstevel@tonic-gate /* 14807c478bd9Sstevel@tonic-gate * Free unused continuation extents 14817c478bd9Sstevel@tonic-gate */ 14827c478bd9Sstevel@tonic-gate for (; con_index < ip->i_con_used; con_index++) { 14837c478bd9Sstevel@tonic-gate icon = &ip->i_con[con_index]; 14847c478bd9Sstevel@tonic-gate count = (icon->ib_count + lbmask) >> l2b; 14857c478bd9Sstevel@tonic-gate ud_free_space(ip->i_udf->udf_vfs, icon->ib_prn, 14867c478bd9Sstevel@tonic-gate icon->ib_block, count); 14877c478bd9Sstevel@tonic-gate count = (count << l2b) - sizeof (struct alloc_ext_desc); 14887c478bd9Sstevel@tonic-gate ip->i_cur_max_ext -= (count / elen) - 1; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate ip->i_con_used = temp; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate return (0); 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14967c478bd9Sstevel@tonic-gate int32_t 14977c478bd9Sstevel@tonic-gate ud_updat_ext4096(struct ud_inode *ip, struct file_entry *fe) 14987c478bd9Sstevel@tonic-gate { 14997c478bd9Sstevel@tonic-gate return (ENXIO); 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate void 15037c478bd9Sstevel@tonic-gate ud_make_sad(struct icb_ext *iext, struct short_ad *sad, int32_t count) 15047c478bd9Sstevel@tonic-gate { 15057c478bd9Sstevel@tonic-gate int32_t index = 0, scount; 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate ASSERT(iext); 15087c478bd9Sstevel@tonic-gate ASSERT(sad); 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate if (count != 0) { 15117c478bd9Sstevel@tonic-gate ASSERT(count > 0); 15127c478bd9Sstevel@tonic-gate while (index < count) { 15137c478bd9Sstevel@tonic-gate scount = (iext->ib_count & 0x3FFFFFFF) | 15147c478bd9Sstevel@tonic-gate (iext->ib_flags << 30); 15157c478bd9Sstevel@tonic-gate sad->sad_ext_len = SWAP_32(scount); 15167c478bd9Sstevel@tonic-gate sad->sad_ext_loc = SWAP_32(iext->ib_block); 15177c478bd9Sstevel@tonic-gate sad++; 15187c478bd9Sstevel@tonic-gate iext++; 15197c478bd9Sstevel@tonic-gate index++; 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate void 15257c478bd9Sstevel@tonic-gate ud_make_lad(struct icb_ext *iext, struct long_ad *lad, int32_t count) 15267c478bd9Sstevel@tonic-gate { 15277c478bd9Sstevel@tonic-gate int32_t index = 0, scount; 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate ASSERT(iext); 15307c478bd9Sstevel@tonic-gate ASSERT(lad); 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate if (count != 0) { 15337c478bd9Sstevel@tonic-gate ASSERT(count > 0); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate while (index < count) { 15367c478bd9Sstevel@tonic-gate lad->lad_ext_prn = SWAP_16(iext->ib_prn); 15377c478bd9Sstevel@tonic-gate scount = (iext->ib_count & 0x3FFFFFFF) | 15387c478bd9Sstevel@tonic-gate (iext->ib_flags << 30); 15397c478bd9Sstevel@tonic-gate lad->lad_ext_len = SWAP_32(scount); 15407c478bd9Sstevel@tonic-gate lad->lad_ext_loc = SWAP_32(iext->ib_block); 15417c478bd9Sstevel@tonic-gate lad++; 15427c478bd9Sstevel@tonic-gate iext++; 15437c478bd9Sstevel@tonic-gate index++; 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate /* 15497c478bd9Sstevel@tonic-gate * Truncate the inode ip to at most length size. 15507c478bd9Sstevel@tonic-gate * Free affected disk blocks -- the blocks of the 15517c478bd9Sstevel@tonic-gate * file are removed in reverse order. 15527c478bd9Sstevel@tonic-gate */ 15537c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15547c478bd9Sstevel@tonic-gate int 15557c478bd9Sstevel@tonic-gate ud_itrunc(struct ud_inode *oip, u_offset_t length, 15567c478bd9Sstevel@tonic-gate int32_t flags, struct cred *cr) 15577c478bd9Sstevel@tonic-gate { 15587c478bd9Sstevel@tonic-gate int32_t error, boff; 15597c478bd9Sstevel@tonic-gate off_t bsize; 15607c478bd9Sstevel@tonic-gate mode_t mode; 15617c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate ud_printf("ud_itrunc\n"); 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&oip->i_contents)); 15667c478bd9Sstevel@tonic-gate udf_vfsp = oip->i_udf; 15677c478bd9Sstevel@tonic-gate bsize = udf_vfsp->udf_lbsize; 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate /* 15707c478bd9Sstevel@tonic-gate * We only allow truncation of regular files and directories 15717c478bd9Sstevel@tonic-gate * to arbritary lengths here. In addition, we allow symbolic 15727c478bd9Sstevel@tonic-gate * links to be truncated only to zero length. Other inode 15737c478bd9Sstevel@tonic-gate * types cannot have their length set here. 15747c478bd9Sstevel@tonic-gate */ 15757c478bd9Sstevel@tonic-gate mode = oip->i_type; 15767c478bd9Sstevel@tonic-gate if (mode == VFIFO) { 15777c478bd9Sstevel@tonic-gate return (0); 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate if ((mode != VREG) && (mode != VDIR) && 15807c478bd9Sstevel@tonic-gate (!(mode == VLNK && length == 0))) { 15817c478bd9Sstevel@tonic-gate return (EINVAL); 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate if (length == oip->i_size) { 15847c478bd9Sstevel@tonic-gate /* update ctime and mtime to please POSIX tests */ 15857c478bd9Sstevel@tonic-gate mutex_enter(&oip->i_tlock); 15867c478bd9Sstevel@tonic-gate oip->i_flag |= ICHG |IUPD; 15877c478bd9Sstevel@tonic-gate mutex_exit(&oip->i_tlock); 15887c478bd9Sstevel@tonic-gate return (0); 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate boff = blkoff(udf_vfsp, length); 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate if (length > oip->i_size) { 15947c478bd9Sstevel@tonic-gate /* 15957c478bd9Sstevel@tonic-gate * Trunc up case.ud_bmap_write will insure that the right blocks 15967c478bd9Sstevel@tonic-gate * are allocated. This includes doing any work needed for 15977c478bd9Sstevel@tonic-gate * allocating the last block. 15987c478bd9Sstevel@tonic-gate */ 15997c478bd9Sstevel@tonic-gate if (boff == 0) { 16007c478bd9Sstevel@tonic-gate error = ud_bmap_write(oip, length - 1, 16017c478bd9Sstevel@tonic-gate (int)bsize, 0, cr); 16027c478bd9Sstevel@tonic-gate } else { 16037c478bd9Sstevel@tonic-gate error = ud_bmap_write(oip, length - 1, boff, 0, cr); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate if (error == 0) { 16067c478bd9Sstevel@tonic-gate u_offset_t osize = oip->i_size; 16077c478bd9Sstevel@tonic-gate oip->i_size = length; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate * Make sure we zero out the remaining bytes of 16117c478bd9Sstevel@tonic-gate * the page in case a mmap scribbled on it. We 16127c478bd9Sstevel@tonic-gate * can't prevent a mmap from writing beyond EOF 16137c478bd9Sstevel@tonic-gate * on the last page of a file. 16147c478bd9Sstevel@tonic-gate */ 16157c478bd9Sstevel@tonic-gate if ((boff = blkoff(udf_vfsp, osize)) != 0) { 16167c478bd9Sstevel@tonic-gate pvn_vpzero(ITOV(oip), osize, 16177c478bd9Sstevel@tonic-gate (uint32_t)(bsize - boff)); 16187c478bd9Sstevel@tonic-gate } 16197c478bd9Sstevel@tonic-gate mutex_enter(&oip->i_tlock); 16207c478bd9Sstevel@tonic-gate oip->i_flag |= ICHG; 16217c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(oip); 16227c478bd9Sstevel@tonic-gate mutex_exit(&oip->i_tlock); 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate return (error); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate /* 16287c478bd9Sstevel@tonic-gate * Update the pages of the file. If the file is not being 16297c478bd9Sstevel@tonic-gate * truncated to a block boundary, the contents of the 16307c478bd9Sstevel@tonic-gate * pages following the end of the file must be zero'ed 16317c478bd9Sstevel@tonic-gate * in case it ever become accessable again because 16327c478bd9Sstevel@tonic-gate * of subsequent file growth. 16337c478bd9Sstevel@tonic-gate */ 16347c478bd9Sstevel@tonic-gate if (boff == 0) { 16357c478bd9Sstevel@tonic-gate (void) pvn_vplist_dirty(ITOV(oip), length, 16367c478bd9Sstevel@tonic-gate ud_putapage, B_INVAL | B_TRUNC, CRED()); 16377c478bd9Sstevel@tonic-gate } else { 16387c478bd9Sstevel@tonic-gate /* 16397c478bd9Sstevel@tonic-gate * Make sure that the last block is properly allocated. 16407c478bd9Sstevel@tonic-gate * We only really have to do this if the last block is 16417c478bd9Sstevel@tonic-gate * actually allocated. Just to be sure, we do it now 16427c478bd9Sstevel@tonic-gate * independent of current allocation. 16437c478bd9Sstevel@tonic-gate */ 16447c478bd9Sstevel@tonic-gate error = ud_bmap_write(oip, length - 1, boff, 0, cr); 16457c478bd9Sstevel@tonic-gate if (error) { 16467c478bd9Sstevel@tonic-gate return (error); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate pvn_vpzero(ITOV(oip), length, (uint32_t)(bsize - boff)); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate (void) pvn_vplist_dirty(ITOV(oip), length, 16527c478bd9Sstevel@tonic-gate ud_putapage, B_INVAL | B_TRUNC, CRED()); 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* Free the blocks */ 16577c478bd9Sstevel@tonic-gate if (oip->i_desc_type == ICB_FLAG_ONE_AD) { 16587c478bd9Sstevel@tonic-gate if (length > oip->i_max_emb) { 16597c478bd9Sstevel@tonic-gate return (EFBIG); 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate oip->i_size = length; 16627c478bd9Sstevel@tonic-gate mutex_enter(&oip->i_tlock); 16637c478bd9Sstevel@tonic-gate oip->i_flag |= ICHG|IUPD; 16647c478bd9Sstevel@tonic-gate mutex_exit(&oip->i_tlock); 16657c478bd9Sstevel@tonic-gate ud_iupdat(oip, 1); 16667c478bd9Sstevel@tonic-gate } else { 16677c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(oip, oip->i_size)) != 0) { 16687c478bd9Sstevel@tonic-gate return (error); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate if (oip->i_astrat == STRAT_TYPE4) { 16727c478bd9Sstevel@tonic-gate ud_trunc_ext4(oip, length); 16737c478bd9Sstevel@tonic-gate } else if (oip->i_astrat == STRAT_TYPE4096) { 16747c478bd9Sstevel@tonic-gate ud_trunc_ext4096(oip, length); 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate done: 16797c478bd9Sstevel@tonic-gate return (0); 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate void 16837c478bd9Sstevel@tonic-gate ud_trunc_ext4(struct ud_inode *ip, u_offset_t length) 16847c478bd9Sstevel@tonic-gate { 16857c478bd9Sstevel@tonic-gate int32_t index, l2b, count, ecount; 16867c478bd9Sstevel@tonic-gate int32_t elen, ndent, nient; 16877c478bd9Sstevel@tonic-gate u_offset_t ext_beg, ext_end; 16887c478bd9Sstevel@tonic-gate struct icb_ext *iext, *icon; 16897c478bd9Sstevel@tonic-gate int32_t lbmask, ext_used; 16907c478bd9Sstevel@tonic-gate uint32_t loc; 16917c478bd9Sstevel@tonic-gate struct icb_ext text; 16927c478bd9Sstevel@tonic-gate uint32_t con_freed; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate ASSERT((ip->i_desc_type == ICB_FLAG_SHORT_AD) || 16957c478bd9Sstevel@tonic-gate (ip->i_desc_type == ICB_FLAG_LONG_AD)); 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate if (ip->i_ext_used == 0) { 16987c478bd9Sstevel@tonic-gate return; 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate ext_used = ip->i_ext_used; 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate lbmask = ip->i_udf->udf_lbmask; 17047c478bd9Sstevel@tonic-gate l2b = ip->i_udf->udf_l2b_shift; 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate ASSERT(ip->i_ext); 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate ip->i_lbr = 0; 17097c478bd9Sstevel@tonic-gate for (index = 0; index < ext_used; index++) { 17107c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate /* 17137c478bd9Sstevel@tonic-gate * Find the begining and end 17147c478bd9Sstevel@tonic-gate * of current extent 17157c478bd9Sstevel@tonic-gate */ 17167c478bd9Sstevel@tonic-gate ext_beg = iext->ib_offset; 17177c478bd9Sstevel@tonic-gate ext_end = iext->ib_offset + 17187c478bd9Sstevel@tonic-gate ((iext->ib_count + lbmask) & ~lbmask); 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate /* 17217c478bd9Sstevel@tonic-gate * This is the extent that has offset "length" 17227c478bd9Sstevel@tonic-gate * make a copy of this extent and 17237c478bd9Sstevel@tonic-gate * remember the index. We can use 17247c478bd9Sstevel@tonic-gate * it to free blocks 17257c478bd9Sstevel@tonic-gate */ 1726b39a0235SMilan Cermak if ((length <= ext_end) && (length >= ext_beg)) { 17277c478bd9Sstevel@tonic-gate text = *iext; 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate iext->ib_count = length - ext_beg; 17307c478bd9Sstevel@tonic-gate ip->i_ext_used = index + 1; 17317c478bd9Sstevel@tonic-gate break; 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 17347c478bd9Sstevel@tonic-gate ip->i_lbr += iext->ib_count >> l2b; 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate if (ip->i_ext_used != index) { 17387c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 17397c478bd9Sstevel@tonic-gate ip->i_lbr += 17407c478bd9Sstevel@tonic-gate ((iext->ib_count + lbmask) & ~lbmask) >> l2b; 17417c478bd9Sstevel@tonic-gate } 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate ip->i_size = length; 17457c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 17467c478bd9Sstevel@tonic-gate ip->i_flag |= ICHG|IUPD; 17477c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 17487c478bd9Sstevel@tonic-gate ud_iupdat(ip, 1); 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate /* 17517c478bd9Sstevel@tonic-gate * Free the unused space 17527c478bd9Sstevel@tonic-gate */ 17537c478bd9Sstevel@tonic-gate if (text.ib_flags != IB_UN_RE_AL) { 17547c478bd9Sstevel@tonic-gate count = (ext_end - length) >> l2b; 17557c478bd9Sstevel@tonic-gate if (count) { 17567c478bd9Sstevel@tonic-gate loc = text.ib_block + 17577c478bd9Sstevel@tonic-gate (((length - text.ib_offset) + lbmask) >> l2b); 17587c478bd9Sstevel@tonic-gate ud_free_space(ip->i_udf->udf_vfs, text.ib_prn, 17597c478bd9Sstevel@tonic-gate loc, count); 17607c478bd9Sstevel@tonic-gate } 17617c478bd9Sstevel@tonic-gate } 17627c478bd9Sstevel@tonic-gate for (index = ip->i_ext_used; index < ext_used; index++) { 17637c478bd9Sstevel@tonic-gate iext = &ip->i_ext[index]; 17647c478bd9Sstevel@tonic-gate if (iext->ib_flags != IB_UN_RE_AL) { 17657c478bd9Sstevel@tonic-gate count = (iext->ib_count + lbmask) >> l2b; 17667c478bd9Sstevel@tonic-gate ud_free_space(ip->i_udf->udf_vfs, iext->ib_prn, 17677c478bd9Sstevel@tonic-gate iext->ib_block, count); 17687c478bd9Sstevel@tonic-gate } 17697c478bd9Sstevel@tonic-gate bzero(iext, sizeof (struct icb_ext)); 17707c478bd9Sstevel@tonic-gate continue; 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* 17747c478bd9Sstevel@tonic-gate * release any continuation blocks 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate if (ip->i_con) { 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate ASSERT(ip->i_con_count >= ip->i_con_used); 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate /* 17817c478bd9Sstevel@tonic-gate * Find out how many indirect blocks 17827c478bd9Sstevel@tonic-gate * are required and release the rest 17837c478bd9Sstevel@tonic-gate */ 17847c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 17857c478bd9Sstevel@tonic-gate elen = sizeof (struct short_ad); 17867c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 17877c478bd9Sstevel@tonic-gate elen = sizeof (struct long_ad); 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate ndent = ip->i_max_emb / elen; 17907c478bd9Sstevel@tonic-gate if (ip->i_ext_used > ndent) { 17917c478bd9Sstevel@tonic-gate ecount = ip->i_ext_used - ndent; 17927c478bd9Sstevel@tonic-gate } else { 17937c478bd9Sstevel@tonic-gate ecount = 0; 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate con_freed = 0; 17967c478bd9Sstevel@tonic-gate for (index = 0; index < ip->i_con_used; index++) { 17977c478bd9Sstevel@tonic-gate icon = &ip->i_con[index]; 17987c478bd9Sstevel@tonic-gate nient = icon->ib_count - 17997c478bd9Sstevel@tonic-gate (sizeof (struct alloc_ext_desc) + elen); 18007c478bd9Sstevel@tonic-gate /* Header + 1 indirect extent */ 18017c478bd9Sstevel@tonic-gate nient /= elen; 18027c478bd9Sstevel@tonic-gate if (ecount) { 18037c478bd9Sstevel@tonic-gate if (ecount > nient) { 18047c478bd9Sstevel@tonic-gate ecount -= nient; 18057c478bd9Sstevel@tonic-gate } else { 18067c478bd9Sstevel@tonic-gate ecount = 0; 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate } else { 18097c478bd9Sstevel@tonic-gate count = ((icon->ib_count + lbmask) & 18107c478bd9Sstevel@tonic-gate ~lbmask) >> l2b; 18117c478bd9Sstevel@tonic-gate ud_free_space(ip->i_udf->udf_vfs, 1812b39a0235SMilan Cermak icon->ib_prn, icon->ib_block, count); 18137c478bd9Sstevel@tonic-gate con_freed++; 18147c478bd9Sstevel@tonic-gate ip->i_cur_max_ext -= nient; 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate /* 18187c478bd9Sstevel@tonic-gate * set the continuation extents used(i_con_used)i to correct 18197c478bd9Sstevel@tonic-gate * value. It is possible for i_con_used to be zero, 18207c478bd9Sstevel@tonic-gate * if we free up all continuation extents. This happens 18217c478bd9Sstevel@tonic-gate * when ecount is 0 before entering the for loop above. 18227c478bd9Sstevel@tonic-gate */ 18237c478bd9Sstevel@tonic-gate ip->i_con_used -= con_freed; 18247c478bd9Sstevel@tonic-gate if (ip->i_con_read > ip->i_con_used) { 18257c478bd9Sstevel@tonic-gate ip->i_con_read = ip->i_con_used; 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate void 18317c478bd9Sstevel@tonic-gate ud_trunc_ext4096(struct ud_inode *ip, u_offset_t length) 18327c478bd9Sstevel@tonic-gate { 18337c478bd9Sstevel@tonic-gate /* 18347c478bd9Sstevel@tonic-gate * Truncate code is the same for 18357c478bd9Sstevel@tonic-gate * both file of type 4 and 4096 18367c478bd9Sstevel@tonic-gate */ 18377c478bd9Sstevel@tonic-gate ud_trunc_ext4(ip, length); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate /* 18417c478bd9Sstevel@tonic-gate * Remove any inodes in the inode cache belonging to dev 18427c478bd9Sstevel@tonic-gate * 18437c478bd9Sstevel@tonic-gate * There should not be any active ones, return error if any are found but 18447c478bd9Sstevel@tonic-gate * still invalidate others (N.B.: this is a user error, not a system error). 18457c478bd9Sstevel@tonic-gate * 18467c478bd9Sstevel@tonic-gate * Also, count the references to dev by block devices - this really 18477c478bd9Sstevel@tonic-gate * has nothing to do with the object of the procedure, but as we have 18487c478bd9Sstevel@tonic-gate * to scan the inode table here anyway, we might as well get the 18497c478bd9Sstevel@tonic-gate * extra benefit. 18507c478bd9Sstevel@tonic-gate */ 18517c478bd9Sstevel@tonic-gate int32_t 18527c478bd9Sstevel@tonic-gate ud_iflush(struct vfs *vfsp) 18537c478bd9Sstevel@tonic-gate { 18547c478bd9Sstevel@tonic-gate int32_t index, busy = 0; 18557c478bd9Sstevel@tonic-gate union ihead *ih; 18567c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 18577c478bd9Sstevel@tonic-gate dev_t dev; 18587c478bd9Sstevel@tonic-gate struct vnode *rvp, *vp; 18597c478bd9Sstevel@tonic-gate struct ud_inode *ip, *next; 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate ud_printf("ud_iflush\n"); 18627c478bd9Sstevel@tonic-gate udf_vfsp = (struct udf_vfs *)vfsp->vfs_data; 18637c478bd9Sstevel@tonic-gate rvp = udf_vfsp->udf_root; 18647c478bd9Sstevel@tonic-gate dev = vfsp->vfs_dev; 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 18677c478bd9Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++) { 18687c478bd9Sstevel@tonic-gate ih = &ud_ihead[index]; 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate next = ih->ih_chain[0]; 18717c478bd9Sstevel@tonic-gate while (next != (struct ud_inode *)ih) { 18727c478bd9Sstevel@tonic-gate ip = next; 18737c478bd9Sstevel@tonic-gate next = ip->i_forw; 18747c478bd9Sstevel@tonic-gate if (ip->i_dev != dev) { 18757c478bd9Sstevel@tonic-gate continue; 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate vp = ITOV(ip); 18787c478bd9Sstevel@tonic-gate /* 18797c478bd9Sstevel@tonic-gate * root inode is processed by the caller 18807c478bd9Sstevel@tonic-gate */ 18817c478bd9Sstevel@tonic-gate if (vp == rvp) { 18827c478bd9Sstevel@tonic-gate if (vp->v_count > 1) { 18837c478bd9Sstevel@tonic-gate busy = -1; 18847c478bd9Sstevel@tonic-gate } 18857c478bd9Sstevel@tonic-gate continue; 18867c478bd9Sstevel@tonic-gate } 18877c478bd9Sstevel@tonic-gate if (ip->i_flag & IREF) { 18887c478bd9Sstevel@tonic-gate /* 18897c478bd9Sstevel@tonic-gate * Set error indicator for return value, 18907c478bd9Sstevel@tonic-gate * but continue invalidating other 18917c478bd9Sstevel@tonic-gate * inodes. 18927c478bd9Sstevel@tonic-gate */ 18937c478bd9Sstevel@tonic-gate busy = -1; 18947c478bd9Sstevel@tonic-gate continue; 18957c478bd9Sstevel@tonic-gate } 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER); 18987c478bd9Sstevel@tonic-gate remque(ip); 18997c478bd9Sstevel@tonic-gate ip->i_forw = ip; 19007c478bd9Sstevel@tonic-gate ip->i_back = ip; 19017c478bd9Sstevel@tonic-gate /* 19027c478bd9Sstevel@tonic-gate * Hold the vnode since its not done 19037c478bd9Sstevel@tonic-gate * in VOP_PUTPAGE anymore. 19047c478bd9Sstevel@tonic-gate */ 19057c478bd9Sstevel@tonic-gate VN_HOLD(vp); 19067c478bd9Sstevel@tonic-gate /* 19077c478bd9Sstevel@tonic-gate * XXX Synchronous write holding 19087c478bd9Sstevel@tonic-gate * cache lock 19097c478bd9Sstevel@tonic-gate */ 19107c478bd9Sstevel@tonic-gate (void) ud_syncip(ip, B_INVAL, I_SYNC); 19117c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 19127c478bd9Sstevel@tonic-gate VN_RELE(vp); 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate } 19157c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate return (busy); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate /* 19227c478bd9Sstevel@tonic-gate * Check mode permission on inode. Mode is READ, WRITE or EXEC. 19237c478bd9Sstevel@tonic-gate * In the case of WRITE, the read-only status of the file system 19247c478bd9Sstevel@tonic-gate * is checked. The applicable mode bits are compared with the 19257c478bd9Sstevel@tonic-gate * requested form of access. If bits are missing, the secpolicy 19267c478bd9Sstevel@tonic-gate * function will check for privileges. 19277c478bd9Sstevel@tonic-gate */ 19287c478bd9Sstevel@tonic-gate int 1929b39a0235SMilan Cermak ud_iaccess(struct ud_inode *ip, int32_t mode, struct cred *cr, int dolock) 19307c478bd9Sstevel@tonic-gate { 19317c478bd9Sstevel@tonic-gate int shift = 0; 1932b39a0235SMilan Cermak int ret = 0; 1933b39a0235SMilan Cermak 1934b39a0235SMilan Cermak if (dolock) 1935b39a0235SMilan Cermak rw_enter(&ip->i_contents, RW_READER); 1936b39a0235SMilan Cermak ASSERT(RW_LOCK_HELD(&ip->i_contents)); 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate ud_printf("ud_iaccess\n"); 19397c478bd9Sstevel@tonic-gate if (mode & IWRITE) { 19407c478bd9Sstevel@tonic-gate /* 19417c478bd9Sstevel@tonic-gate * Disallow write attempts on read-only 19427c478bd9Sstevel@tonic-gate * file systems, unless the file is a block 19437c478bd9Sstevel@tonic-gate * or character device or a FIFO. 19447c478bd9Sstevel@tonic-gate */ 19457c478bd9Sstevel@tonic-gate if (ip->i_udf->udf_flags & UDF_FL_RDONLY) { 19467c478bd9Sstevel@tonic-gate if ((ip->i_type != VCHR) && 19477c478bd9Sstevel@tonic-gate (ip->i_type != VBLK) && 19487c478bd9Sstevel@tonic-gate (ip->i_type != VFIFO)) { 1949b39a0235SMilan Cermak ret = EROFS; 1950b39a0235SMilan Cermak goto out; 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate } 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate /* 19567c478bd9Sstevel@tonic-gate * Access check is based on only 19577c478bd9Sstevel@tonic-gate * one of owner, group, public. 19587c478bd9Sstevel@tonic-gate * If not owner, then check group. 19597c478bd9Sstevel@tonic-gate * If not a member of the group, then 19607c478bd9Sstevel@tonic-gate * check public access. 19617c478bd9Sstevel@tonic-gate */ 19627c478bd9Sstevel@tonic-gate if (crgetuid(cr) != ip->i_uid) { 19637c478bd9Sstevel@tonic-gate shift += 5; 19647c478bd9Sstevel@tonic-gate if (!groupmember((uid_t)ip->i_gid, cr)) 19657c478bd9Sstevel@tonic-gate shift += 5; 19667c478bd9Sstevel@tonic-gate } 19677c478bd9Sstevel@tonic-gate 1968134a1f4eSCasper H.S. Dik ret = secpolicy_vnode_access2(cr, ITOV(ip), ip->i_uid, 1969134a1f4eSCasper H.S. Dik UD2VA_PERM(ip->i_perm << shift), UD2VA_PERM(mode)); 1970b39a0235SMilan Cermak 1971b39a0235SMilan Cermak out: 1972b39a0235SMilan Cermak if (dolock) 1973b39a0235SMilan Cermak rw_exit(&ip->i_contents); 1974b39a0235SMilan Cermak return (ret); 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate void 19787c478bd9Sstevel@tonic-gate ud_imark(struct ud_inode *ip) 19797c478bd9Sstevel@tonic-gate { 19807c478bd9Sstevel@tonic-gate timestruc_t now; 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate gethrestime(&now); 19837c478bd9Sstevel@tonic-gate ud_printf("ud_imark\n"); 19847c478bd9Sstevel@tonic-gate if (ip->i_flag & IACC) { 19857c478bd9Sstevel@tonic-gate ip->i_atime.tv_sec = now.tv_sec; 19867c478bd9Sstevel@tonic-gate ip->i_atime.tv_nsec = now.tv_nsec; 19877c478bd9Sstevel@tonic-gate } 19887c478bd9Sstevel@tonic-gate if (ip->i_flag & IUPD) { 19897c478bd9Sstevel@tonic-gate ip->i_mtime.tv_sec = now.tv_sec; 19907c478bd9Sstevel@tonic-gate ip->i_mtime.tv_nsec = now.tv_nsec; 19917c478bd9Sstevel@tonic-gate ip->i_flag |= IMODTIME; 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate if (ip->i_flag & ICHG) { 19947c478bd9Sstevel@tonic-gate ip->i_diroff = 0; 19957c478bd9Sstevel@tonic-gate ip->i_ctime.tv_sec = now.tv_sec; 19967c478bd9Sstevel@tonic-gate ip->i_ctime.tv_nsec = now.tv_nsec; 19977c478bd9Sstevel@tonic-gate } 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate void 20027c478bd9Sstevel@tonic-gate ud_itimes_nolock(struct ud_inode *ip) 20037c478bd9Sstevel@tonic-gate { 20047c478bd9Sstevel@tonic-gate ud_printf("ud_itimes_nolock\n"); 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate if (ip->i_flag & (IUPD|IACC|ICHG)) { 20077c478bd9Sstevel@tonic-gate if (ip->i_flag & ICHG) { 20087c478bd9Sstevel@tonic-gate ip->i_flag |= IMOD; 20097c478bd9Sstevel@tonic-gate } else { 20107c478bd9Sstevel@tonic-gate ip->i_flag |= IMODACC; 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate ud_imark(ip); 20137c478bd9Sstevel@tonic-gate ip->i_flag &= ~(IACC|IUPD|ICHG); 20147c478bd9Sstevel@tonic-gate } 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate void 20187c478bd9Sstevel@tonic-gate ud_delcache(struct ud_inode *ip) 20197c478bd9Sstevel@tonic-gate { 20207c478bd9Sstevel@tonic-gate ud_printf("ud_delcache\n"); 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 20237c478bd9Sstevel@tonic-gate remque(ip); 20247c478bd9Sstevel@tonic-gate ip->i_forw = ip; 20257c478bd9Sstevel@tonic-gate ip->i_back = ip; 20267c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 20277c478bd9Sstevel@tonic-gate } 20287c478bd9Sstevel@tonic-gate 20297c478bd9Sstevel@tonic-gate void 20307c478bd9Sstevel@tonic-gate ud_idrop(struct ud_inode *ip) 20317c478bd9Sstevel@tonic-gate { 20327c478bd9Sstevel@tonic-gate struct vnode *vp = ITOV(ip); 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ip->i_contents)); 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate ud_printf("ud_idrop\n"); 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 20397c478bd9Sstevel@tonic-gate if (vp->v_count > 1) { 20407c478bd9Sstevel@tonic-gate vp->v_count--; 20417c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 20427c478bd9Sstevel@tonic-gate return; 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate vp->v_count = 0; 20457c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate /* 20497c478bd9Sstevel@tonic-gate * if inode is invalid or there is no page associated with 20507c478bd9Sstevel@tonic-gate * this inode, put the inode in the front of the free list 20517c478bd9Sstevel@tonic-gate */ 20527c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock); 20537c478bd9Sstevel@tonic-gate mutex_enter(&udf_ifree_lock); 20547c478bd9Sstevel@tonic-gate if (!vn_has_cached_data(vp) || ip->i_perm == 0) { 20557c478bd9Sstevel@tonic-gate ud_add_to_free_list(ip, UD_BEGIN); 20567c478bd9Sstevel@tonic-gate } else { 20577c478bd9Sstevel@tonic-gate /* 20587c478bd9Sstevel@tonic-gate * Otherwise, put the inode back on the end of the free list. 20597c478bd9Sstevel@tonic-gate */ 20607c478bd9Sstevel@tonic-gate ud_add_to_free_list(ip, UD_END); 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate mutex_exit(&udf_ifree_lock); 20637c478bd9Sstevel@tonic-gate ip->i_flag &= IMODTIME; 20647c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock); 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate void 20687c478bd9Sstevel@tonic-gate ud_add_to_free_list(struct ud_inode *ip, uint32_t at) 20697c478bd9Sstevel@tonic-gate { 20707c478bd9Sstevel@tonic-gate ASSERT(ip); 20717c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&udf_ifree_lock)); 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate #ifdef DEBUG 20747c478bd9Sstevel@tonic-gate /* Search if the element is already in the list */ 20757c478bd9Sstevel@tonic-gate if (udf_ifreeh != NULL) { 20767c478bd9Sstevel@tonic-gate struct ud_inode *iq; 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate iq = udf_ifreeh; 20797c478bd9Sstevel@tonic-gate while (iq) { 20807c478bd9Sstevel@tonic-gate if (iq == ip) { 20817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Duplicate %p\n", (void *)ip); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate iq = iq->i_freef; 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate #endif 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate ip->i_freef = NULL; 20897c478bd9Sstevel@tonic-gate ip->i_freeb = NULL; 20907c478bd9Sstevel@tonic-gate if (udf_ifreeh == NULL) { 20917c478bd9Sstevel@tonic-gate /* 20927c478bd9Sstevel@tonic-gate * Nothing on the list just add it 20937c478bd9Sstevel@tonic-gate */ 20947c478bd9Sstevel@tonic-gate udf_ifreeh = ip; 20957c478bd9Sstevel@tonic-gate udf_ifreet = ip; 20967c478bd9Sstevel@tonic-gate } else { 20977c478bd9Sstevel@tonic-gate if (at == UD_BEGIN) { 20987c478bd9Sstevel@tonic-gate /* 20997c478bd9Sstevel@tonic-gate * Add at the begining of the list 21007c478bd9Sstevel@tonic-gate */ 21017c478bd9Sstevel@tonic-gate ip->i_freef = udf_ifreeh; 21027c478bd9Sstevel@tonic-gate udf_ifreeh->i_freeb = ip; 21037c478bd9Sstevel@tonic-gate udf_ifreeh = ip; 21047c478bd9Sstevel@tonic-gate } else { 21057c478bd9Sstevel@tonic-gate /* 21067c478bd9Sstevel@tonic-gate * Add at the end of the list 21077c478bd9Sstevel@tonic-gate */ 21087c478bd9Sstevel@tonic-gate ip->i_freeb = udf_ifreet; 21097c478bd9Sstevel@tonic-gate udf_ifreet->i_freef = ip; 21107c478bd9Sstevel@tonic-gate udf_ifreet = ip; 21117c478bd9Sstevel@tonic-gate } 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate void 21167c478bd9Sstevel@tonic-gate ud_remove_from_free_list(struct ud_inode *ip, uint32_t at) 21177c478bd9Sstevel@tonic-gate { 21187c478bd9Sstevel@tonic-gate ASSERT(ip); 21197c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&udf_ifree_lock)); 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate #ifdef DEBUG 21227c478bd9Sstevel@tonic-gate { 21237c478bd9Sstevel@tonic-gate struct ud_inode *iq; 21247c478bd9Sstevel@tonic-gate uint32_t found = 0; 21257c478bd9Sstevel@tonic-gate 21267c478bd9Sstevel@tonic-gate iq = udf_ifreeh; 21277c478bd9Sstevel@tonic-gate while (iq) { 21287c478bd9Sstevel@tonic-gate if (iq == ip) { 21297c478bd9Sstevel@tonic-gate found++; 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate iq = iq->i_freef; 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate if (found != 1) { 21347c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ip %p is found %x times\n", 21357c478bd9Sstevel@tonic-gate (void *)ip, found); 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate #endif 21397c478bd9Sstevel@tonic-gate 2140b39a0235SMilan Cermak if ((ip->i_freef == NULL) && (ip->i_freeb == NULL)) { 21417c478bd9Sstevel@tonic-gate if (ip != udf_ifreeh) { 21427c478bd9Sstevel@tonic-gate return; 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 2146b39a0235SMilan Cermak if ((at == UD_BEGIN) || (ip == udf_ifreeh)) { 21477c478bd9Sstevel@tonic-gate udf_ifreeh = ip->i_freef; 21487c478bd9Sstevel@tonic-gate if (ip->i_freef == NULL) { 21497c478bd9Sstevel@tonic-gate udf_ifreet = NULL; 21507c478bd9Sstevel@tonic-gate } else { 21517c478bd9Sstevel@tonic-gate udf_ifreeh->i_freeb = NULL; 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate } else { 21547c478bd9Sstevel@tonic-gate ip->i_freeb->i_freef = ip->i_freef; 21557c478bd9Sstevel@tonic-gate if (ip->i_freef) { 21567c478bd9Sstevel@tonic-gate ip->i_freef->i_freeb = ip->i_freeb; 21577c478bd9Sstevel@tonic-gate } else { 21587c478bd9Sstevel@tonic-gate udf_ifreet = ip->i_freeb; 21597c478bd9Sstevel@tonic-gate } 21607c478bd9Sstevel@tonic-gate } 21617c478bd9Sstevel@tonic-gate ip->i_freef = NULL; 21627c478bd9Sstevel@tonic-gate ip->i_freeb = NULL; 21637c478bd9Sstevel@tonic-gate } 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate void 21667c478bd9Sstevel@tonic-gate ud_init_inodes(void) 21677c478bd9Sstevel@tonic-gate { 21687c478bd9Sstevel@tonic-gate union ihead *ih = ud_ihead; 21697c478bd9Sstevel@tonic-gate int index; 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate #ifndef __lint 21727c478bd9Sstevel@tonic-gate _NOTE(NO_COMPETING_THREADS_NOW); 21737c478bd9Sstevel@tonic-gate #endif 21747c478bd9Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++, ih++) { 21757c478bd9Sstevel@tonic-gate ih->ih_head[0] = ih; 21767c478bd9Sstevel@tonic-gate ih->ih_head[1] = ih; 21777c478bd9Sstevel@tonic-gate } 21787c478bd9Sstevel@tonic-gate mutex_init(&ud_icache_lock, NULL, MUTEX_DEFAULT, NULL); 21797c478bd9Sstevel@tonic-gate mutex_init(&ud_nino_lock, NULL, MUTEX_DEFAULT, NULL); 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate udf_ifreeh = NULL; 21827c478bd9Sstevel@tonic-gate udf_ifreet = NULL; 21837c478bd9Sstevel@tonic-gate mutex_init(&udf_ifree_lock, NULL, MUTEX_DEFAULT, NULL); 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate mutex_init(&ud_sync_busy, NULL, MUTEX_DEFAULT, NULL); 21867c478bd9Sstevel@tonic-gate udf_vfs_instances = NULL; 21877c478bd9Sstevel@tonic-gate mutex_init(&udf_vfs_mutex, NULL, MUTEX_DEFAULT, NULL); 21887c478bd9Sstevel@tonic-gate 21897c478bd9Sstevel@tonic-gate #ifndef __lint 21907c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW); 21917c478bd9Sstevel@tonic-gate #endif 21927c478bd9Sstevel@tonic-gate } 2193