1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/t_lock.h> 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/signal.h> 33 #include <sys/cred.h> 34 #include <sys/proc.h> 35 #include <sys/disp.h> 36 #include <sys/user.h> 37 #include <sys/vfs.h> 38 #include <sys/vnode.h> 39 #include <sys/stat.h> 40 #include <sys/mode.h> 41 #include <sys/buf.h> 42 #include <sys/uio.h> 43 #include <sys/dnlc.h> 44 #include <sys/pathname.h> 45 #include <sys/fs/ufs_inode.h> 46 #include <sys/fs/ufs_fs.h> 47 #include <sys/mount.h> 48 #include <sys/fs/ufs_fsdir.h> 49 #include <sys/fs/ufs_trans.h> 50 #include <sys/fs/ufs_panic.h> 51 #include <sys/fs/ufs_quota.h> 52 #include <sys/errno.h> 53 #include <sys/debug.h> 54 #include <vm/seg.h> 55 #include <sys/sysmacros.h> 56 #include <sys/cmn_err.h> 57 #include <sys/cpuvar.h> 58 #include <sys/unistd.h> 59 60 int 61 ufs_xattr_getattrdir( 62 vnode_t *dvp, 63 struct inode **sip, 64 int flags, 65 struct cred *cr) 66 { 67 struct vfs *vfsp; 68 struct inode *ip, *sdp; 69 int error; 70 71 ip = VTOI(dvp); 72 if (flags & LOOKUP_XATTR) { 73 if (ip && ((ip->i_oeftflag) != 0)) { 74 vfsp = dvp->v_vfsp; 75 76 error = ufs_iget(vfsp, ip->i_oeftflag, sip, cr); 77 if (error) 78 return (error); 79 80 sdp = *sip; 81 82 /* 83 * Make sure it really is an ATTRDIR 84 */ 85 if ((sdp->i_mode & IFMT) != IFATTRDIR) { 86 cmn_err(CE_NOTE, "ufs_getattrdir: inode %d" 87 " points to attribute directory %d " 88 "which is not an attribute directory;" 89 "run fsck on file system", 90 (int)ip->i_number, (int)sdp->i_number); 91 VN_RELE(ITOV(sdp)); 92 return (ENOENT); 93 } 94 ITOV(sdp)->v_type = VDIR; 95 ITOV(sdp)->v_flag |= V_XATTRDIR; 96 error = 0; 97 goto out; 98 } else if (flags & CREATE_XATTR_DIR) { 99 error = ufs_xattrmkdir(ip, sip, 1, cr); 100 } else { 101 error = ENOENT; 102 goto out; 103 } 104 105 } else if (flags & CREATE_XATTR_DIR) { 106 error = ufs_xattrmkdir(ip, sip, 1, cr); 107 } else { 108 error = ENOENT; 109 } 110 out: 111 return (error); 112 } 113 114 115 /* 116 * Unhook an attribute directory from a parent file/dir 117 * Only do so, if we are the only user of the vnode. 118 */ 119 void 120 ufs_unhook_shadow(struct inode *ip, struct inode *sip) 121 { 122 struct vnode *datavp = ITOV(ip); 123 struct vnode *dirvp = ITOV(sip); 124 int hno; 125 kmutex_t *ihm; 126 127 ASSERT(RW_WRITE_HELD(&sip->i_contents)); 128 ASSERT(RW_WRITE_HELD(&ip->i_contents)); 129 130 if (vn_is_readonly(ITOV(ip))) 131 return; 132 133 if (ip->i_ufsvfs == NULL || sip->i_ufsvfs == NULL) 134 return; 135 136 hno = INOHASH(ip->i_number); 137 ihm = &ih_lock[hno]; 138 mutex_enter(ihm); 139 140 mutex_enter(&datavp->v_lock); 141 mutex_enter(&dirvp->v_lock); 142 143 if (dirvp->v_count != 1 && datavp->v_count != 1) { 144 mutex_exit(&dirvp->v_lock); 145 mutex_exit(&datavp->v_lock); 146 mutex_exit(ihm); 147 return; 148 } 149 150 /* 151 * Delete shadow from ip 152 */ 153 154 sip->i_nlink -= 2; 155 ufs_setreclaim(sip); 156 TRANS_INODE(sip->i_ufsvfs, sip); 157 sip->i_flag |= ICHG; 158 sip->i_seq++; 159 ITIMES_NOLOCK(sip); 160 161 /* 162 * Update src file 163 */ 164 ip->i_oeftflag = 0; 165 TRANS_INODE(ip->i_ufsvfs, ip); 166 ip->i_flag |= ICHG; 167 ip->i_seq++; 168 ufs_iupdat(ip, 1); 169 mutex_exit(&dirvp->v_lock); 170 mutex_exit(&datavp->v_lock); 171 mutex_exit(ihm); 172 } 173