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 #pragma ident "%Z%%M% %I% %E% SMI"
26
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/cred.h>
31 #include <sys/proc.h>
32 #include <sys/user.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/pathname.h>
36 #include <sys/uio.h>
37 #include <sys/tiuser.h>
38 #include <sys/sysmacros.h>
39 #include <sys/kmem.h>
40 #include <sys/mount.h>
41 #include <sys/ioctl.h>
42 #include <sys/statvfs.h>
43 #include <sys/errno.h>
44 #include <sys/debug.h>
45 #include <sys/cmn_err.h>
46 #include <sys/utsname.h>
47 #include <sys/bootconf.h>
48 #include <sys/modctl.h>
49
50 #include <sys/fs/cachefs_fs.h>
51
52 /*ARGSUSED*/
53 static int
c_nop_init_cached_object(fscache_t * fscp,cnode_t * cp,vattr_t * vap,cred_t * cr)54 c_nop_init_cached_object(fscache_t *fscp, cnode_t *cp, vattr_t *vap,
55 cred_t *cr)
56 {
57 int error;
58 cachefs_metadata_t *mdp = &cp->c_metadata;
59
60 ASSERT(cr != NULL);
61 ASSERT(MUTEX_HELD(&cp->c_statelock));
62
63 /* NFSv4 always sets strict consistency */
64 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
65
66 /* if attributes not passed in then get them */
67 if (vap == NULL) {
68 /* if not connected then cannot get attrs */
69 if ((fscp->fs_cdconnected != CFS_CD_CONNECTED) ||
70 (fscp->fs_backvfsp == NULL))
71 return (ETIMEDOUT);
72
73 /* get backvp if necessary */
74 if (cp->c_backvp == NULL) {
75 error = cachefs_getbackvp(fscp, cp);
76 if (error)
77 return (error);
78 }
79
80 /* get the attributes */
81 cp->c_attr.va_mask = AT_ALL;
82 ASSERT(cp->c_backvp != NULL);
83 error = VOP_GETATTR(cp->c_backvp, &cp->c_attr, 0, cr, NULL);
84 if (error)
85 return (error);
86 } else {
87 /* copy passed in attributes into the cnode */
88 cp->c_attr = *vap;
89 }
90
91 cp->c_size = cp->c_attr.va_size;
92 mdp->md_consttype = CFS_FS_CONST_NOCONST;
93 cp->c_flags |= CN_UPDATED;
94 return (0);
95 }
96
97 /*ARGSUSED*/
98 static int
c_nop_check_cached_object(struct fscache * fscp,struct cnode * cp,int verify_what,cred_t * cr)99 c_nop_check_cached_object(struct fscache *fscp, struct cnode *cp,
100 int verify_what, cred_t *cr)
101 {
102 struct vattr attrs;
103 int fail = 0, backhit = 0;
104 int error = 0;
105 cachefs_metadata_t *mdp = &cp->c_metadata;
106
107 ASSERT(cr);
108 ASSERT(MUTEX_HELD(&cp->c_statelock));
109
110 /* nothing to do if not connected */
111 if ((fscp->fs_cdconnected != CFS_CD_CONNECTED) ||
112 (fscp->fs_backvfsp == NULL))
113 goto out;
114
115 /* done if do not have to check */
116 if (((verify_what & C_BACK_CHECK) == 0) &&
117 ((mdp->md_flags & MD_NEEDATTRS) == 0))
118 goto out;
119
120 /* get backvp if necessary */
121 if (cp->c_backvp == NULL) {
122 error = cachefs_getbackvp(fscp, cp);
123 if (error)
124 goto out;
125 }
126
127 /* get the file attributes from the back fs */
128 attrs.va_mask = AT_ALL;
129 error = VOP_GETATTR(cp->c_backvp, &attrs, 0, cr, NULL);
130 backhit = 1;
131 if (error)
132 goto out;
133
134 cp->c_attr = attrs;
135 if (attrs.va_size > cp->c_size)
136 cp->c_size = attrs.va_size;
137 mdp->md_flags &= ~MD_NEEDATTRS;
138 cachefs_cnode_setlocalstats(cp);
139 cp->c_flags |= CN_UPDATED;
140
141 out:
142 if (backhit != 0) {
143 if (fail != 0)
144 fscp->fs_stats.st_fails++;
145 else
146 fscp->fs_stats.st_passes++;
147 }
148
149 return (error);
150 }
151
152 static void
c_nop_modify_cached_object(struct fscache * fscp,struct cnode * cp,cred_t * cr)153 c_nop_modify_cached_object(struct fscache *fscp, struct cnode *cp, cred_t *cr)
154 {
155 struct vattr attrs;
156 int error;
157 nlink_t nlink;
158 cachefs_metadata_t *mdp = &cp->c_metadata;
159
160 ASSERT(MUTEX_HELD(&cp->c_statelock));
161 ASSERT(fscp->fs_cdconnected == CFS_CD_CONNECTED);
162 ASSERT(fscp->fs_backvfsp);
163
164 fscp->fs_stats.st_modifies++;
165
166 /* from now on, make sure we're using the server's idea of time */
167 mdp->md_flags &= ~(MD_LOCALCTIME | MD_LOCALMTIME);
168 mdp->md_flags |= MD_NEEDATTRS;
169
170 /* if in write-around mode, make sure file is nocached */
171 if (CFS_ISFS_WRITE_AROUND(fscp)) {
172 if ((cp->c_flags & CN_NOCACHE) == 0)
173 cachefs_nocache(cp);
174 }
175
176 /* get the new attributes so we don't wait forever to get them */
177 if (cp->c_backvp == NULL) {
178 error = cachefs_getbackvp(fscp, cp);
179 if (error)
180 return;
181 }
182 attrs.va_mask = AT_ALL;
183 error = VOP_GETATTR(cp->c_backvp, &attrs, 0, cr, NULL);
184 if (error)
185 return;
186 nlink = cp->c_attr.va_nlink;
187 cp->c_attr = attrs;
188 cp->c_attr.va_nlink = nlink;
189 if ((attrs.va_size > cp->c_size) || !vn_has_cached_data(CTOV(cp)))
190 cp->c_size = attrs.va_size;
191 mdp->md_flags &= ~MD_NEEDATTRS;
192 cachefs_cnode_setlocalstats(cp);
193 cp->c_flags |= CN_UPDATED;
194 }
195
196 /*ARGSUSED*/
197 static void
c_nop_invalidate_cached_object(struct fscache * fscp,struct cnode * cp,cred_t * cr)198 c_nop_invalidate_cached_object(struct fscache *fscp, struct cnode *cp,
199 cred_t *cr)
200 {
201 cachefs_metadata_t *mdp = &cp->c_metadata;
202
203 ASSERT(MUTEX_HELD(&cp->c_statelock));
204 mdp->md_flags |= MD_NEEDATTRS;
205 cp->c_flags |= CN_UPDATED;
206 }
207
208 /*ARGSUSED*/
209 static void
c_nop_convert_cached_object(struct fscache * fscp,struct cnode * cp,cred_t * cr)210 c_nop_convert_cached_object(struct fscache *fscp, struct cnode *cp,
211 cred_t *cr)
212 {
213 cachefs_metadata_t *mdp = &cp->c_metadata;
214 mdp->md_flags |= MD_NEEDATTRS;
215 mdp->md_consttype = CFS_FS_CONST_NOCONST;
216 cp->c_flags |= CN_UPDATED;
217 }
218
219 struct cachefsops nopcfsops = {
220 c_nop_init_cached_object,
221 c_nop_check_cached_object,
222 c_nop_modify_cached_object,
223 c_nop_invalidate_cached_object,
224 c_nop_convert_cached_object
225 };
226