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