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
59int
60ufs_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	}
109out:
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 */
118void
119ufs_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