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