1 6741 th199096 /* 2 6741 th199096 * CDDL HEADER START 3 6741 th199096 * 4 6741 th199096 * The contents of this file are subject to the terms of the 5 6741 th199096 * Common Development and Distribution License (the "License"). 6 6741 th199096 * You may not use this file except in compliance with the License. 7 6741 th199096 * 8 6741 th199096 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 6741 th199096 * or http://www.opensolaris.org/os/licensing. 10 6741 th199096 * See the License for the specific language governing permissions 11 6741 th199096 * and limitations under the License. 12 6741 th199096 * 13 6741 th199096 * When distributing Covered Code, include this CDDL HEADER in each 14 6741 th199096 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 6741 th199096 * If applicable, add the following below this CDDL HEADER, with the 16 6741 th199096 * fields enclosed by brackets "[]" replaced with your own identifying 17 6741 th199096 * information: Portions Copyright [yyyy] [name of copyright owner] 18 6741 th199096 * 19 6741 th199096 * CDDL HEADER END 20 6741 th199096 */ 21 6741 th199096 /* 22 8422 James * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 6741 th199096 * Use is subject to license terms. 24 6741 th199096 */ 25 6741 th199096 26 6741 th199096 /* 27 6741 th199096 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 28 6741 th199096 * All Rights Reserved 29 6741 th199096 */ 30 6741 th199096 31 6741 th199096 #include <sys/param.h> 32 6741 th199096 #include <sys/types.h> 33 6741 th199096 #include <sys/systm.h> 34 6741 th199096 #include <sys/cred.h> 35 6741 th199096 #include <sys/buf.h> 36 6741 th199096 #include <sys/vfs.h> 37 6741 th199096 #include <sys/vnode.h> 38 6741 th199096 #include <sys/uio.h> 39 6741 th199096 #include <sys/errno.h> 40 6741 th199096 #include <sys/sysmacros.h> 41 6741 th199096 #include <sys/statvfs.h> 42 6741 th199096 #include <sys/kmem.h> 43 6741 th199096 #include <sys/dirent.h> 44 6741 th199096 #include <sys/cmn_err.h> 45 6741 th199096 #include <sys/disp.h> 46 6741 th199096 #include <sys/debug.h> 47 6741 th199096 #include <sys/systeminfo.h> 48 6741 th199096 #include <sys/flock.h> 49 6741 th199096 #include <sys/pathname.h> 50 6741 th199096 #include <sys/nbmlock.h> 51 6741 th199096 #include <sys/share.h> 52 6741 th199096 #include <sys/atomic.h> 53 6741 th199096 #include <sys/policy.h> 54 6741 th199096 #include <sys/fem.h> 55 6741 th199096 #include <sys/sdt.h> 56 6741 th199096 #include <sys/ddi.h> 57 7397 rick #include <sys/modctl.h> 58 9396 rick #include <sys/timod.h> 59 10016 Thomas #include <sys/id_space.h> 60 6741 th199096 61 6741 th199096 #include <rpc/types.h> 62 6741 th199096 #include <rpc/auth.h> 63 6741 th199096 #include <rpc/rpcsec_gss.h> 64 6741 th199096 #include <rpc/svc.h> 65 6741 th199096 66 6741 th199096 #include <nfs/nfs.h> 67 6741 th199096 #include <nfs/export.h> 68 6741 th199096 #include <nfs/lm.h> 69 6741 th199096 #include <nfs/nfs4.h> 70 6741 th199096 71 6741 th199096 #include <sys/strsubr.h> 72 6741 th199096 #include <sys/strsun.h> 73 6741 th199096 74 6741 th199096 #include <inet/common.h> 75 6741 th199096 #include <inet/ip.h> 76 6741 th199096 #include <inet/ip6.h> 77 6741 th199096 78 6741 th199096 #include <sys/tsol/label.h> 79 6741 th199096 #include <sys/tsol/tndb.h> 80 6741 th199096 81 6741 th199096 #include <nfs/nfs4_attrmap.h> 82 6741 th199096 #include <nfs/nfs4_srv_attr.h> 83 6741 th199096 #include <nfs/mds_state.h> 84 8424 lisa #include <nfs/mds_odl.h> 85 6741 th199096 86 6741 th199096 #include <nfs/nfs41_filehandle.h> 87 8424 lisa #include <nfs/ctl_mds_clnt.h> 88 10016 Thomas 89 10016 Thomas #include <nfs/spe_impl.h> 90 6741 th199096 91 6741 th199096 #define RFS4_MAXLOCK_TRIES 4 /* Try to get the lock this many times */ 92 6741 th199096 static int rfs4_maxlock_tries = RFS4_MAXLOCK_TRIES; 93 6741 th199096 #define RFS4_LOCK_DELAY 10 /* Milliseconds */ 94 6741 th199096 static clock_t rfs4_lock_delay = RFS4_LOCK_DELAY; 95 6741 th199096 96 6741 th199096 int mds_strict_seqid = 0; 97 6741 th199096 98 7739 jwahlig static void ping_cb_null_thr(mds_session_t *); 99 6741 th199096 100 6741 th199096 /* End of Tunables */ 101 6741 th199096 102 6741 th199096 /* 103 6741 th199096 * Used to bump the stateid4.seqid value and show changes in the stateid 104 6741 th199096 */ 105 6741 th199096 #define next_stateid(sp) (++(sp)->v41_bits.chgseq) 106 6741 th199096 107 6741 th199096 /* 108 6741 th199096 * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent. 109 6741 th199096 * This is used to return NFS4ERR_TOOSMALL when clients specify 110 6741 th199096 * maxcount that isn't large enough to hold the smallest possible 111 6741 th199096 * XDR encoded dirent. 112 6741 th199096 * 113 6741 th199096 * sizeof cookie (8 bytes) + 114 6741 th199096 * sizeof name_len (4 bytes) + 115 6741 th199096 * sizeof smallest (padded) name (4 bytes) + 116 6741 th199096 * sizeof bitmap4_len (12 bytes) + NOTE: we always encode len=2 bm4 117 6741 th199096 * sizeof attrlist4_len (4 bytes) + 118 6741 th199096 * sizeof next boolean (4 bytes) 119 6741 th199096 * 120 6741 th199096 * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing 121 6741 th199096 * the smallest possible entry4 (assumes no attrs requested). 122 6741 th199096 * sizeof nfsstat4 (4 bytes) + 123 6741 th199096 * sizeof verifier4 (8 bytes) + 124 6741 th199096 * sizeof entry4list bool (4 bytes) + 125 6741 th199096 * sizeof entry4 (36 bytes) + 126 6741 th199096 * sizeof eof bool (4 bytes) 127 6741 th199096 * 128 6741 th199096 * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to 129 6741 th199096 * VOP_READDIR. Its value is the size of the maximum possible dirent 130 6741 th199096 * for solaris. The DIRENT64_RECLEN macro returns the size of dirent 131 6741 th199096 * required for a given name length. MAXNAMELEN is the maximum 132 6741 th199096 * filename length allowed in Solaris. The first two DIRENT64_RECLEN() 133 6741 th199096 * macros are to allow for . and .. entries -- just a minor tweak to try 134 6741 th199096 * and guarantee that buffer we give to VOP_READDIR will be large enough 135 6741 th199096 * to hold ., .., and the largest possible solaris dirent64. 136 6741 th199096 */ 137 6741 th199096 #define RFS4_MINLEN_ENTRY4 36 138 6741 th199096 #define RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4) 139 6741 th199096 #define RFS4_MINLEN_RDDIR_BUF \ 140 6741 th199096 (DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN)) 141 6741 th199096 142 6741 th199096 /* 143 6741 th199096 * It would be better to pad to 4 bytes since that's what XDR would do, 144 6741 th199096 * but the dirents UFS gives us are already padded to 8, so just take 145 6741 th199096 * what we're given. Dircount is only a hint anyway. Currently the 146 6741 th199096 * solaris kernel is ASCII only, so there's no point in calling the 147 6741 th199096 * UTF8 functions. 148 6741 th199096 * 149 6741 th199096 * dirent64: named padded to provide 8 byte struct alignment 150 6741 th199096 * d_ino(8) + d_off(8) + d_reclen(2) + d_name(namelen + null(1) + pad) 151 6741 th199096 * 152 6741 th199096 * cookie: uint64_t + utf8namelen: uint_t + utf8name padded to 8 bytes 153 6741 th199096 * 154 6741 th199096 */ 155 6741 th199096 #define DIRENT64_TO_DIRCOUNT(dp) \ 156 6741 th199096 (3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen)) 157 6741 th199096 158 6741 th199096 /* 159 6741 th199096 * types of label comparison 160 6741 th199096 */ 161 6741 th199096 #define EQUALITY_CHECK 0 162 6741 th199096 #define DOMINANCE_CHECK 1 163 6741 th199096 164 6741 th199096 static sysid_t lockt_sysid; /* dummy sysid for all LOCKT calls */ 165 6741 th199096 166 7739 jwahlig void rfs4_init_compound_state(struct compound_state *); 167 6741 th199096 168 8023 Sam static void nullfree(nfs_resop4 *, compound_state_t *); 169 6741 th199096 static void mds_op_inval(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 170 8023 Sam compound_state_t *); 171 6741 th199096 static void mds_op_notsup(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 172 8023 Sam compound_state_t *); 173 6741 th199096 static void mds_op_access(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 174 8023 Sam compound_state_t *); 175 6741 th199096 static void mds_op_close(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 176 8023 Sam compound_state_t *); 177 6741 th199096 static void mds_op_commit(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 178 8023 Sam compound_state_t *); 179 6741 th199096 static void mds_op_create(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 180 8023 Sam compound_state_t *); 181 6741 th199096 static void mds_op_create_free(nfs_resop4 *resop); 182 6741 th199096 static void mds_op_delegreturn(nfs_argop4 *, nfs_resop4 *, 183 8023 Sam struct svc_req *, compound_state_t *); 184 6741 th199096 static void mds_op_getattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 185 8023 Sam compound_state_t *); 186 8023 Sam static void mds_op_getattr_free(nfs_resop4 *, compound_state_t *); 187 6741 th199096 static void mds_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 188 8023 Sam compound_state_t *); 189 8023 Sam static void mds_op_getfh_free(nfs_resop4 *, compound_state_t *); 190 6741 th199096 static void mds_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 191 8023 Sam compound_state_t *); 192 6741 th199096 static void mds_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 193 8023 Sam compound_state_t *); 194 8023 Sam static void mds_lock_denied_free(nfs_resop4 *, compound_state_t *); 195 6741 th199096 static void mds_op_locku(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 196 8023 Sam compound_state_t *); 197 6741 th199096 static void mds_op_lockt(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 198 8023 Sam compound_state_t *); 199 6741 th199096 static void mds_op_lookup(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 200 8023 Sam compound_state_t *); 201 6741 th199096 static void mds_op_lookupp(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 202 8023 Sam compound_state_t *); 203 6741 th199096 static void mds_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, 204 8023 Sam struct svc_req *req, compound_state_t *); 205 6741 th199096 static void mds_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 206 8023 Sam compound_state_t *); 207 6741 th199096 static void mds_op_open(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 208 8023 Sam compound_state_t *); 209 6741 th199096 static void mds_op_open_downgrade(nfs_argop4 *, nfs_resop4 *, 210 8023 Sam struct svc_req *, compound_state_t *); 211 6741 th199096 static void mds_op_putfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 212 8023 Sam compound_state_t *); 213 6741 th199096 static void mds_op_putpubfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 214 8023 Sam compound_state_t *); 215 6741 th199096 static void mds_op_putrootfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 216 8023 Sam compound_state_t *); 217 6741 th199096 static void mds_op_read(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 218 8023 Sam compound_state_t *); 219 8023 Sam static void mds_op_read_free(nfs_resop4 *, compound_state_t *); 220 6741 th199096 void mds_op_readdir(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 221 8023 Sam compound_state_t *); 222 8023 Sam static void mds_op_readdir_free(nfs_resop4 *, compound_state_t *); 223 6741 th199096 static void mds_op_readlink(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 224 8023 Sam compound_state_t *); 225 8023 Sam static void mds_op_readlink_free(nfs_resop4 *, compound_state_t *); 226 6741 th199096 static void mds_op_release_lockowner(nfs_argop4 *, nfs_resop4 *, 227 8023 Sam struct svc_req *, compound_state_t *); 228 6741 th199096 static void mds_op_remove(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 229 8023 Sam compound_state_t *); 230 6741 th199096 static void mds_op_rename(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 231 8023 Sam compound_state_t *); 232 6741 th199096 static void mds_op_renew(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 233 8023 Sam compound_state_t *); 234 6741 th199096 static void mds_op_restorefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 235 8023 Sam compound_state_t *); 236 6741 th199096 static void mds_op_savefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 237 8023 Sam compound_state_t *); 238 6741 th199096 static void mds_op_setattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 239 8023 Sam compound_state_t *); 240 6741 th199096 static void mds_op_verify(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 241 8023 Sam compound_state_t *); 242 6741 th199096 static void mds_op_write(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 243 8023 Sam compound_state_t *); 244 6741 th199096 static void mds_op_exchange_id(nfs_argop4 *, nfs_resop4 *, 245 8023 Sam struct svc_req *, compound_state_t *); 246 9396 rick static void mds_op_exid_free(nfs_resop4 *, compound_state_t *); 247 6741 th199096 static void mds_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 248 8023 Sam compound_state_t *); 249 6741 th199096 static void mds_op_secinfonn(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 250 8023 Sam compound_state_t *); 251 6741 th199096 nfsstat4 do_rfs4_op_secinfo(struct compound_state *, char *, int, 252 6741 th199096 SECINFO4res *); 253 6741 th199096 254 8023 Sam static void mds_op_secinfo_free(nfs_resop4 *, compound_state_t *); 255 6741 th199096 256 6741 th199096 static void mds_op_backchannel_ctl(nfs_argop4 *, nfs_resop4 *, 257 8023 Sam struct svc_req *, compound_state_t *); 258 6741 th199096 static void mds_op_bind_conn_to_session(nfs_argop4 *, nfs_resop4 *, 259 8023 Sam struct svc_req *, compound_state_t *); 260 6741 th199096 static void mds_op_create_clientid(nfs_argop4 *, nfs_resop4 *, 261 8023 Sam struct svc_req *, compound_state_t *); 262 6741 th199096 static void mds_op_create_session(nfs_argop4 *, nfs_resop4 *, 263 8023 Sam struct svc_req *, compound_state_t *); 264 6741 th199096 static void mds_op_destroy_session(nfs_argop4 *, nfs_resop4 *, 265 8023 Sam struct svc_req *, compound_state_t *); 266 6741 th199096 static void mds_op_sequence(nfs_argop4 *, nfs_resop4 *, 267 8023 Sam struct svc_req *, compound_state_t *); 268 6741 th199096 269 6741 th199096 static void mds_op_get_devlist(nfs_argop4 *, nfs_resop4 *, 270 8023 Sam struct svc_req *, compound_state_t *); 271 6741 th199096 272 6741 th199096 static void mds_op_get_devinfo(nfs_argop4 *, nfs_resop4 *, 273 8023 Sam struct svc_req *, compound_state_t *); 274 6741 th199096 275 6741 th199096 static void mds_op_layout_get(nfs_argop4 *, nfs_resop4 *, 276 8023 Sam struct svc_req *, compound_state_t *); 277 9106 Piyush static void mds_op_layout_get_free(nfs_resop4 *, compound_state_t *); 278 6741 th199096 279 6741 th199096 static void mds_op_layout_commit(nfs_argop4 *, nfs_resop4 *, 280 8023 Sam struct svc_req *, compound_state_t *); 281 6741 th199096 282 6741 th199096 static void mds_op_layout_return(nfs_argop4 *, nfs_resop4 *, 283 8023 Sam struct svc_req *, compound_state_t *); 284 7739 jwahlig 285 7739 jwahlig static void mds_op_reclaim_complete(nfs_argop4 *, nfs_resop4 *, 286 8023 Sam struct svc_req *, compound_state_t *); 287 6741 th199096 288 10475 rick static int seq_chk_limits(nfs_argop4 *, nfs_resop4 *, compound_state_t *); 289 10475 rick 290 6741 th199096 nfsstat4 check_open_access(uint32_t, 291 6741 th199096 struct compound_state *, struct svc_req *); 292 6741 th199096 nfsstat4 rfs4_client_sysid(rfs4_client_t *, sysid_t *); 293 6741 th199096 294 8023 Sam static void mds_free_reply(nfs_resop4 *, compound_state_t *); 295 6741 th199096 296 6741 th199096 vnode_t *do_rfs4_op_mknod(CREATE4args *, CREATE4res *, struct svc_req *, 297 6741 th199096 struct compound_state *, vattr_t *, char *); 298 6741 th199096 299 6741 th199096 nfsstat4 rfs4_do_lock(rfs4_lo_state_t *, nfs_lock_type4, seqid4, 300 6741 th199096 offset4, length4, cred_t *, nfs_resop4 *); 301 6741 th199096 302 6741 th199096 rfs4_lo_state_t *mds_findlo_state_by_owner(rfs4_lockowner_t *, 303 7739 jwahlig rfs4_state_t *, bool_t *); 304 6741 th199096 305 6741 th199096 bool_t in_flavor_list(int, int *, int); 306 6741 th199096 307 6741 th199096 nfsstat4 attrmap4_to_vattrmask(attrmap4 *, struct nfs4_svgetit_arg *); 308 6741 th199096 309 6741 th199096 nfsstat4 bitmap4_get_sysattrs(struct nfs4_svgetit_arg *); 310 6741 th199096 311 6741 th199096 nfsstat4 do_rfs4_op_getattr(attrmap4 *, fattr4 *, struct nfs4_svgetit_arg *); 312 6741 th199096 313 6741 th199096 nfsstat4 do_rfs4_op_lookup(char *, uint_t, struct svc_req *, 314 6741 th199096 struct compound_state *); 315 6741 th199096 316 7739 jwahlig rfs4_lockowner_t *mds_findlockowner_by_pid(nfs_server_instance_t *, pid_t); 317 7739 jwahlig 318 7739 jwahlig mds_session_t *mds_findsession_by_id(nfs_server_instance_t *, sessionid4); 319 7739 jwahlig 320 7739 jwahlig rfs4_openowner_t *mds_findopenowner(nfs_server_instance_t *, open_owner4 *, 321 7739 jwahlig bool_t *); 322 6741 th199096 323 6741 th199096 static void mds_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *, 324 8023 Sam compound_state_t *); 325 6741 th199096 326 10016 Thomas extern mds_mpd_t *mds_find_mpd(nfs_server_instance_t *, id_t); 327 8035 James extern void rfs41_lo_seqid(stateid_t *); 328 9215 James extern void mds_delete_layout(vnode_t *); 329 9215 James extern void mds_clean_grants_by_fsid(rfs4_client_t *, vnode_t *); 330 10016 Thomas extern mds_layout_t *mds_add_layout(layout_core_t *lc); 331 6741 th199096 332 6741 th199096 nfsstat4 333 6741 th199096 create_vnode(vnode_t *, char *, vattr_t *, createmode4, timespec32_t *, 334 6741 th199096 cred_t *, vnode_t **, bool_t *); 335 6741 th199096 336 6741 th199096 337 6741 th199096 /* HACKERY */ 338 6741 th199096 nfsstat4 rfs4_get_all_state(struct compound_state *, stateid4 *, 339 6741 th199096 rfs4_state_t **, rfs4_deleg_state_t **, rfs4_lo_state_t **); 340 6741 th199096 341 7739 jwahlig void rfs4_ss_clid(struct compound_state *, rfs4_client_t *, struct svc_req *); 342 7739 jwahlig void rfs4_ss_chkclid(struct compound_state *, rfs4_client_t *); 343 8422 James 344 8422 James int layout_match(stateid_t, stateid4, nfsstat4 *); 345 7739 jwahlig 346 6741 th199096 extern stateid4 special0; 347 6741 th199096 extern stateid4 special1; 348 6741 th199096 349 6741 th199096 #define ISSPECIAL(id) (stateid4_cmp(id, &special0) || \ 350 6741 th199096 stateid4_cmp(id, &special1)) 351 6741 th199096 352 8023 Sam void rfs4_cn_release(compound_state_t *); 353 7739 jwahlig 354 7739 jwahlig mds_layout_grant_t *rfs41_findlogrant(struct compound_state *, 355 7739 jwahlig rfs4_file_t *, rfs4_client_t *, bool_t *); 356 7739 jwahlig void rfs41_lo_grant_rele(mds_layout_grant_t *); 357 7812 James mds_ever_grant_t *rfs41_findevergrant(rfs4_client_t *, vnode_t *, bool_t *); 358 7812 James void rfs41_ever_grant_rele(mds_ever_grant_t *); 359 8415 Sam 360 8415 Sam static uint32_t compute_use_pnfs_flags(uint32_t); 361 6741 th199096 362 6741 th199096 /* ARGSUSED */ 363 6741 th199096 static void 364 6741 th199096 mds_op_notsup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 365 8023 Sam compound_state_t *cs) 366 8023 Sam { 367 7312 Danhua DTRACE_NFSV4_1(op__notsup__start, 368 7312 Danhua strcut compound_state *, cs); 369 7312 Danhua 370 6741 th199096 *cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_NOTSUPP; 371 7312 Danhua 372 7312 Danhua DTRACE_NFSV4_1(op__notsup__done, 373 7312 Danhua struct compound_state *, cs); 374 6741 th199096 } 375 10475 rick 376 6741 th199096 /* ARGSUSED */ 377 6741 th199096 static void 378 6741 th199096 mds_op_illegal(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 379 8023 Sam compound_state_t *cs) 380 8023 Sam { 381 7312 Danhua DTRACE_NFSV4_1(op__illegal__start, 382 7312 Danhua struct compound_state *, cs); 383 6741 th199096 384 6741 th199096 *cs->statusp = 385 6741 th199096 *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_OP_ILLEGAL; 386 7312 Danhua 387 7312 Danhua DTRACE_NFSV4_1(op__illegal__done, 388 7312 Danhua struct compound_state *, cs); 389 6741 th199096 } 390 6741 th199096 391 6741 th199096 /* ARGSUSED */ 392 6741 th199096 static void 393 6741 th199096 mds_op_inval(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 394 8023 Sam compound_state_t *cs) 395 8023 Sam { 396 7312 Danhua DTRACE_NFSV4_1(op__inval__start, 397 7312 Danhua struct compound_state *, cs); 398 7312 Danhua 399 6741 th199096 *cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_INVAL; 400 7312 Danhua 401 7312 Danhua DTRACE_NFSV4_1(op__inval__done, 402 7312 Danhua struct compound_state *, cs); 403 6741 th199096 } 404 6741 th199096 405 6741 th199096 /*ARGSUSED*/ 406 6741 th199096 static void 407 8023 Sam nullfree(nfs_resop4 *resop, compound_state_t *cs) 408 8023 Sam { 409 8023 Sam } 410 8023 Sam 411 8023 Sam static op_disp_tbl_t mds_disptab[] = { 412 6741 th199096 {mds_op_illegal, nullfree, DISP_OP_BAD, "BAD Op 0"}, 413 6741 th199096 {mds_op_illegal, nullfree, DISP_OP_BAD, "BAD Op 1"}, 414 6741 th199096 {mds_op_illegal, nullfree, DISP_OP_BAD, "BAD Op 2"}, 415 6741 th199096 {mds_op_access, nullfree, DISP_OP_MDS, "ACCESS"}, 416 6741 th199096 {mds_op_close, nullfree, DISP_OP_MDS, "CLOSE"}, 417 8023 Sam {mds_op_commit, nullfree, DISP_OP_BOTH, "COMMIT"}, 418 6741 th199096 {mds_op_create, nullfree, DISP_OP_MDS, "CREATE"}, 419 6741 th199096 {mds_op_inval, nullfree, DISP_OP_BAD, "BAD Op 7"}, 420 6741 th199096 {mds_op_delegreturn, nullfree, DISP_OP_MDS, "DELEGRETURN"}, 421 6741 th199096 {mds_op_getattr, mds_op_getattr_free, DISP_OP_MDS, "GETATTR"}, 422 6741 th199096 {mds_op_getfh, mds_op_getfh_free, DISP_OP_MDS, "GETFH"}, 423 6741 th199096 {mds_op_link, nullfree, DISP_OP_MDS, "LINK"}, 424 6741 th199096 {mds_op_lock, mds_lock_denied_free, DISP_OP_MDS, "LOCK"}, 425 6741 th199096 {mds_op_lockt, mds_lock_denied_free, DISP_OP_MDS, "LOCKT"}, 426 6741 th199096 {mds_op_locku, nullfree, DISP_OP_MDS, "LOCKU"}, 427 6741 th199096 {mds_op_lookup, nullfree, DISP_OP_MDS, "LOOKUP"}, 428 6741 th199096 {mds_op_lookupp, nullfree, DISP_OP_MDS, "LOOKUPP"}, 429 6741 th199096 {mds_op_nverify, nullfree, DISP_OP_MDS, "NVERIFY"}, 430 6741 th199096 {mds_op_open, mds_free_reply, DISP_OP_MDS, "OPEN"}, 431 6741 th199096 {mds_op_openattr, nullfree, DISP_OP_MDS, "OPENATTR"}, 432 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BAD, "BAD Op 20"}, 433 6741 th199096 {mds_op_open_downgrade, nullfree, DISP_OP_MDS, "OPEN_DOWNGRADE"}, 434 8023 Sam {mds_op_putfh, nullfree, DISP_OP_BOTH, "PUTFH"}, 435 6741 th199096 {mds_op_putpubfh, nullfree, DISP_OP_MDS, "PUTPUBFH"}, 436 6741 th199096 {mds_op_putrootfh, nullfree, DISP_OP_MDS, "PUTROOTFH"}, 437 8023 Sam {mds_op_read, mds_op_read_free, DISP_OP_BOTH, "READ"}, 438 6741 th199096 {mds_op_readdir, mds_op_readdir_free, DISP_OP_MDS, "READDIR"}, 439 6741 th199096 {mds_op_readlink, mds_op_readlink_free, DISP_OP_MDS, "READLINK"}, 440 6741 th199096 {mds_op_remove, nullfree, DISP_OP_MDS, "REMOVE"}, 441 6741 th199096 {mds_op_rename, nullfree, DISP_OP_MDS, "RENAME"}, 442 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BAD, "BAD Op 30"}, 443 6741 th199096 {mds_op_restorefh, nullfree, DISP_OP_MDS, "RESTOREFH"}, 444 6741 th199096 {mds_op_savefh, nullfree, DISP_OP_MDS, "SAVEFH"}, 445 6741 th199096 {mds_op_secinfo, mds_op_secinfo_free, DISP_OP_MDS, "SECINFO"}, 446 6741 th199096 {mds_op_setattr, nullfree, DISP_OP_MDS, "SETATTR"}, 447 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BAD, "BAD Op 35"}, 448 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BAD, "BAD Op 36"}, 449 6741 th199096 {mds_op_verify, nullfree, DISP_OP_MDS, "VERIFY"}, 450 8023 Sam {mds_op_write, nullfree, DISP_OP_BOTH, "WRITE"}, 451 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BAD, "BAD Op 39"}, 452 6741 th199096 {mds_op_backchannel_ctl, nullfree, DISP_OP_BOTH, "BACKCHANNEL_CTL"}, 453 6741 th199096 {mds_op_bind_conn_to_session, nullfree, 454 6741 th199096 DISP_OP_BOTH, "BIND_CONN_TO_SESS"}, 455 9396 rick {mds_op_exchange_id, mds_op_exid_free, DISP_OP_BOTH, "EXCHANGE_ID"}, 456 6741 th199096 {mds_op_create_session, nullfree, DISP_OP_BOTH, "CREATE_SESS"}, 457 6741 th199096 {mds_op_destroy_session, nullfree, DISP_OP_BOTH, "DESTROY_SESS"}, 458 6741 th199096 {mds_op_illegal, nullfree, DISP_OP_MDS, "FREE_STATEID"}, 459 6741 th199096 {mds_op_illegal, nullfree, DISP_OP_MDS, "GET_DIR_DELEG"}, 460 6741 th199096 {mds_op_get_devinfo, nullfree, DISP_OP_MDS, "GET_DEVINFO"}, 461 6741 th199096 {mds_op_get_devlist, nullfree, DISP_OP_MDS, "GET_DEVLIST"}, 462 6741 th199096 {mds_op_layout_commit, nullfree, DISP_OP_MDS, "LAYOUT_COMMIT"}, 463 9106 Piyush {mds_op_layout_get, mds_op_layout_get_free, DISP_OP_MDS, "LAYOUT_GET"}, 464 6741 th199096 {mds_op_layout_return, nullfree, DISP_OP_MDS, "LAYOUT_RETURN"}, 465 8023 Sam {mds_op_secinfonn, nullfree, 466 6741 th199096 DISP_OP_BOTH, "SECINFO_NONAME"}, 467 6741 th199096 {mds_op_sequence, nullfree, DISP_OP_BOTH, "SEQUENCE"}, 468 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BOTH, "SET_SSV"}, 469 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_MDS, "TEST_STATEID"}, 470 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_MDS, "WANT_DELEG"}, 471 6741 th199096 {mds_op_notsup, nullfree, DISP_OP_BOTH, "DESTROY_CLIENTID"}, 472 7739 jwahlig {mds_op_reclaim_complete, nullfree, DISP_OP_MDS, "RECLAIM_COMPLETE"} 473 6741 th199096 }; 474 6741 th199096 475 6741 th199096 static uint_t mds_disp_cnt = sizeof (mds_disptab) / sizeof (mds_disptab[0]); 476 6741 th199096 477 6741 th199096 #define OP_ILLEGAL_IDX (mds_disp_cnt) 478 6741 th199096 479 6741 th199096 extern size_t strlcpy(char *dst, const char *src, size_t dstsize); 480 6741 th199096 481 6741 th199096 #ifdef nextdp 482 6741 th199096 #undef nextdp 483 6741 th199096 #endif 484 6741 th199096 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 485 6741 th199096 486 8023 Sam /*ARGSUSED*/ 487 8023 Sam static void 488 8023 Sam mds_op_readdir_free(nfs_resop4 *resop, compound_state_t *cs) 489 6741 th199096 { 490 6741 th199096 /* Common function used for NFSv4.0 and NFSv4.1 */ 491 6741 th199096 rfs4_op_readdir_free(resop); 492 6741 th199096 } 493 6741 th199096 494 6741 th199096 /*ARGSUSED*/ 495 6741 th199096 static void 496 8023 Sam mds_op_secinfo_free(nfs_resop4 *resop, compound_state_t *cs) 497 6741 th199096 { 498 6741 th199096 /* Common function used for NFSv4.0 and NFSv4.1 */ 499 6741 th199096 rfs4_op_secinfo_free(resop); 500 6741 th199096 } 501 6741 th199096 502 6741 th199096 /* 503 6741 th199096 */ 504 6741 th199096 void 505 6741 th199096 mds_srvrfini(void) 506 6741 th199096 { 507 6741 th199096 /* some shutdown stuff for the minor verson 1 server */ 508 6741 th199096 } 509 6741 th199096 510 6741 th199096 nfsstat4 rfs4_state_has_access(rfs4_state_t *, int, vnode_t *); 511 6741 th199096 int rfs4_verify_attr(struct nfs4_svgetit_arg *, attrmap4 *, 512 6741 th199096 struct nfs4_ntov_table *); 513 6741 th199096 514 6741 th199096 515 6741 th199096 /* 516 6741 th199096 * Given the I/O mode (FREAD or FWRITE), the vnode, the stateid and whether 517 6741 th199096 * the file is being truncated, return NFS4_OK if allowed or approriate 518 6741 th199096 * V4 error if not. Note NFS4ERR_DELAY will be returned and a recall on 519 6741 th199096 * the associated file will be done if the I/O is not consistent with any 520 6741 th199096 * delegation in effect on the file. Should be holding VOP_RWLOCK, either 521 6741 th199096 * as reader or writer as appropriate. rfs4_op_open will accquire the 522 6741 th199096 * VOP_RWLOCK as writer when setting up delegation. If the stateid is bad 523 6741 th199096 * this routine will return NFS4ERR_BAD_STATEID. In addition, through the 524 6741 th199096 * deleg parameter, we will return whether a write delegation is held by 525 6741 th199096 * the client associated with this stateid. 526 6741 th199096 * If the server instance associated with the relevant client is in its 527 6741 th199096 * grace period, return NFS4ERR_GRACE. 528 6741 th199096 */ 529 6741 th199096 nfsstat4 530 6741 th199096 mds_validate_stateid(int mode, struct compound_state *cs, vnode_t *vp, 531 6741 th199096 stateid4 *stateid, bool_t trunc, bool_t *deleg, bool_t do_access) 532 6741 th199096 { 533 6741 th199096 rfs4_file_t *fp; 534 6741 th199096 bool_t create = FALSE; 535 6741 th199096 rfs4_state_t *sp; 536 6741 th199096 rfs4_deleg_state_t *dsp; 537 6741 th199096 rfs4_lo_state_t *lsp; 538 6741 th199096 stateid_t *id = (stateid_t *)stateid; 539 6741 th199096 nfsstat4 stat = NFS4_OK; 540 6741 th199096 541 6741 th199096 if (ISSPECIAL(stateid)) { 542 7739 jwahlig fp = rfs4_findfile(cs->instp, vp, NULL, &create); 543 6741 th199096 if (fp == NULL) 544 6741 th199096 return (NFS4_OK); 545 10447 Thomas if (fp->rf_dinfo->rd_dtype == OPEN_DELEGATE_NONE) { 546 6741 th199096 rfs4_file_rele(fp); 547 6741 th199096 return (NFS4_OK); 548 6741 th199096 } 549 6741 th199096 if (mode == FWRITE || 550 10447 Thomas fp->rf_dinfo->rd_dtype == OPEN_DELEGATE_WRITE) { 551 6741 th199096 rfs4_recall_deleg(fp, trunc, NULL); 552 6741 th199096 rfs4_file_rele(fp); 553 6741 th199096 return (NFS4ERR_DELAY); 554 6741 th199096 } 555 6741 th199096 rfs4_file_rele(fp); 556 6741 th199096 return (NFS4_OK); 557 6741 th199096 } 558 6741 th199096 559 6741 th199096 stat = rfs4_get_all_state(cs, stateid, &sp, &dsp, &lsp); 560 6741 th199096 if (stat != NFS4_OK) 561 6741 th199096 return (stat); 562 6741 th199096 563 6741 th199096 /* 564 6741 th199096 * Ordering of the following 'if' statements is specific 565 6741 th199096 * since rfs4_get_all_state() may return a value for sp and 566 6741 th199096 * lsp. First we check lsp, then 'fall' through to sp. 567 6741 th199096 */ 568 6741 th199096 if (lsp != NULL) { 569 6741 th199096 /* Is associated server instance in its grace period? */ 570 10447 Thomas if (rfs4_clnt_in_grace(lsp->rls_locker->rl_client)) { 571 6741 th199096 rfs4_lo_state_rele(lsp, FALSE); 572 6741 th199096 if (sp != NULL) 573 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 574 6741 th199096 return (NFS4ERR_GRACE); 575 6741 th199096 } 576 6741 th199096 577 10447 Thomas if (lsp->rls_lockid.v41_bits.chgseq != 0) { 578 6741 th199096 /* Seqid in the future? - that's bad */ 579 10447 Thomas if (lsp->rls_lockid.v41_bits.chgseq < 580 6741 th199096 id->v41_bits.chgseq) { 581 6741 th199096 rfs4_lo_state_rele(lsp, FALSE); 582 6741 th199096 if (sp != NULL) 583 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 584 6741 th199096 return (NFS4ERR_BAD_STATEID); 585 6741 th199096 } 586 6741 th199096 /* Seqid in the past? - that's old */ 587 10447 Thomas if (lsp->rls_lockid.v41_bits.chgseq > 588 6741 th199096 id->v41_bits.chgseq) { 589 6741 th199096 rfs4_lo_state_rele(lsp, FALSE); 590 6741 th199096 if (sp != NULL) 591 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 592 6741 th199096 return (NFS4ERR_OLD_STATEID); 593 6741 th199096 } 594 6741 th199096 } 595 6741 th199096 596 6741 th199096 /* Ensure specified filehandle matches */ 597 10447 Thomas if (lsp->rls_state->rs_finfo->rf_vp != vp) { 598 6741 th199096 rfs4_lo_state_rele(lsp, FALSE); 599 6741 th199096 if (sp != NULL) 600 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 601 6741 th199096 return (NFS4ERR_BAD_STATEID); 602 6741 th199096 } 603 6741 th199096 rfs4_lo_state_rele(lsp, FALSE); 604 6741 th199096 } 605 6741 th199096 606 6741 th199096 /* 607 6741 th199096 * Stateid provided was an "open" or via the lock stateid 608 6741 th199096 */ 609 6741 th199096 if (sp != NULL) { 610 6741 th199096 /* 611 6741 th199096 * only check if the passed in stateid was an OPENID, 612 6741 th199096 * ie. Skip if we got here via the LOCKID. 613 6741 th199096 */ 614 6741 th199096 if (id->v41_bits.type == OPENID) { 615 6741 th199096 /* Is associated server instance in its grace period? */ 616 10447 Thomas if (rfs4_clnt_in_grace(sp->rs_owner->ro_client)) { 617 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 618 6741 th199096 return (NFS4ERR_GRACE); 619 6741 th199096 } 620 6741 th199096 621 10447 Thomas if (sp->rs_stateid.v41_bits.chgseq != 0) { 622 6741 th199096 /* Seqid in the future? - that's bad */ 623 10447 Thomas if (sp->rs_stateid.v41_bits.chgseq < 624 6741 th199096 id->v41_bits.chgseq) { 625 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 626 6741 th199096 return (NFS4ERR_BAD_STATEID); 627 6741 th199096 } 628 6741 th199096 /* Seqid in the past - that's old */ 629 10447 Thomas if (sp->rs_stateid.v41_bits.chgseq > 630 6741 th199096 id->v41_bits.chgseq) { 631 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 632 6741 th199096 return (NFS4ERR_OLD_STATEID); 633 6741 th199096 } 634 6741 th199096 } 635 6741 th199096 636 6741 th199096 /* Ensure specified filehandle matches */ 637 10447 Thomas if (sp->rs_finfo->rf_vp != vp) { 638 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 639 6741 th199096 return (NFS4ERR_BAD_STATEID); 640 6741 th199096 } 641 6741 th199096 } 642 10447 Thomas if (sp->rs_owner->ro_need_confirm) { 643 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 644 6741 th199096 return (NFS4ERR_BAD_STATEID); 645 6741 th199096 } 646 6741 th199096 647 10447 Thomas if (sp->rs_closed == TRUE) { 648 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 649 6741 th199096 return (NFS4ERR_OLD_STATEID); 650 6741 th199096 } 651 6741 th199096 652 6741 th199096 if (do_access) 653 6741 th199096 stat = rfs4_state_has_access(sp, mode, vp); 654 6741 th199096 else 655 6741 th199096 stat = NFS4_OK; 656 6741 th199096 657 6741 th199096 /* 658 6741 th199096 * Return whether this state has write 659 6741 th199096 * delegation if desired 660 6741 th199096 */ 661 6741 th199096 if (deleg && 662 10447 Thomas (sp->rs_finfo->rf_dinfo->rd_dtype == OPEN_DELEGATE_WRITE)) 663 6741 th199096 *deleg = TRUE; 664 6741 th199096 665 6741 th199096 /* 666 6741 th199096 * We got a valid stateid, so we update the 667 6741 th199096 * lease on the client. Ideally we would like 668 6741 th199096 * to do this after the calling op succeeds, 669 6741 th199096 * but for now this will be good 670 6741 th199096 * enough. Callers of this routine are 671 6741 th199096 * currently insulated from the state stuff. 672 6741 th199096 */ 673 10447 Thomas rfs4_update_lease(sp->rs_owner->ro_client); 674 6741 th199096 675 6741 th199096 /* 676 6741 th199096 * If a delegation is present on this file and 677 6741 th199096 * this is a WRITE, then update the lastwrite 678 6741 th199096 * time to indicate that activity is present. 679 6741 th199096 */ 680 10447 Thomas if (sp->rs_finfo->rf_dinfo->rd_dtype == OPEN_DELEGATE_WRITE && 681 6741 th199096 mode == FWRITE) { 682 10447 Thomas sp->rs_finfo->rf_dinfo->rd_time_lastwrite = 683 6741 th199096 gethrestime_sec(); 684 6741 th199096 } 685 6741 th199096 686 10447 Thomas rfs4_dbe_rele(sp->rs_dbe); 687 6741 th199096 return (stat); 688 6741 th199096 } 689 6741 th199096 690 6741 th199096 if (dsp != NULL) { 691 6741 th199096 /* Is associated server instance in its grace period? */ 692 10447 Thomas if (rfs4_clnt_in_grace(dsp->rds_client)) { 693 6741 th199096 rfs4_deleg_state_rele(dsp); 694 6741 th199096 return (NFS4ERR_GRACE); 695 6741 th199096 } 696 6741 th199096 697 10447 Thomas if ((dsp->rds_delegid.v41_bits.chgseq != 0) && 698 10447 Thomas (dsp->rds_delegid.v41_bits.chgseq != id->v41_bits.chgseq)) { 699 6741 th199096 rfs4_deleg_state_rele(dsp); 700 6741 th199096 return (NFS4ERR_BAD_STATEID); 701 6741 th199096 } 702 6741 th199096 703 6741 th199096 /* Ensure specified filehandle matches */ 704 10447 Thomas if (dsp->rds_finfo->rf_vp != vp) { 705 6741 th199096 rfs4_deleg_state_rele(dsp); 706 6741 th199096 return (NFS4ERR_BAD_STATEID); 707 6741 th199096 } 708 6741 th199096 /* 709 6741 th199096 * Return whether this state has write 710 6741 th199096 * delegation if desired 711 6741 th199096 */ 712 6741 th199096 if (deleg && 713 10447 Thomas (dsp->rds_finfo->rf_dinfo->rd_dtype == OPEN_DELEGATE_WRITE)) 714 6741 th199096 *deleg = TRUE; 715 6741 th199096 716 10447 Thomas rfs4_update_lease(dsp->rds_client); 717 6741 th199096 718 6741 th199096 /* 719 6741 th199096 * If a delegation is present on this file and 720 6741 th199096 * this is a WRITE, then update the lastwrite 721 6741 th199096 * time to indicate that activity is present. 722 6741 th199096 */ 723 10447 Thomas if (dsp->rds_finfo->rf_dinfo->rd_dtype == OPEN_DELEGATE_WRITE && 724 6741 th199096 mode == FWRITE) { 725 10447 Thomas dsp->rds_finfo->rf_dinfo->rd_time_lastwrite = 726 6741 th199096 gethrestime_sec(); 727 6741 th199096 } 728 6741 th199096 729 6741 th199096 /* 730 6741 th199096 * XXX - what happens if this is a WRITE and the 731 6741 th199096 * delegation type of for READ. 732 6741 th199096 */ 733 6741 th199096 rfs4_deleg_state_rele(dsp); 734 6741 th199096 735 6741 th199096 return (stat); 736 6741 th199096 } 737 6741 th199096 /* 738 6741 th199096 * If we got this far, something bad happened 739 6741 th199096 */ 740 6741 th199096 return (NFS4ERR_BAD_STATEID); 741 6741 th199096 } 742 6741 th199096 743 6741 th199096 nfsstat4 744 6741 th199096 mds_setattr(attrmap4 *resp, fattr4 *fattrp, struct compound_state *cs, 745 6741 th199096 stateid4 *stateid) 746 6741 th199096 { 747 6741 th199096 int error = 0; 748 6741 th199096 struct nfs4_svgetit_arg sarg; 749 6741 th199096 bool_t trunc; 750 6741 th199096 751 6741 th199096 nfsstat4 status = NFS4_OK; 752 6741 th199096 cred_t *cr = cs->cr; 753 6741 th199096 vnode_t *vp = cs->vp; 754 6741 th199096 struct nfs4_ntov_table ntov; 755 6741 th199096 struct statvfs64 sb; 756 6741 th199096 struct vattr bva; 757 6741 th199096 struct flock64 bf; 758 6741 th199096 int in_crit = 0; 759 6741 th199096 uint_t saved_mask = 0; 760 6741 th199096 caller_context_t ct; 761 6741 th199096 attrvers_t avers; 762 6741 th199096 struct nfs4_ntov_map *nvmap; 763 6741 th199096 764 6741 th199096 avers = RFS4_ATTRVERS(cs); 765 6741 th199096 nvmap = NFS4_NTOV_MAP(avers); 766 6741 th199096 *resp = NFS4_EMPTY_ATTRMAP(avers); 767 6741 th199096 sarg.sbp = &sb; 768 6741 th199096 nfs4_ntov_table_init(&ntov, avers); 769 6741 th199096 status = do_rfs4_set_attrs(resp, fattrp, cs, &sarg, &ntov, 770 6741 th199096 NFS4ATTR_SETIT); 771 6741 th199096 if (status != NFS4_OK) { 772 6741 th199096 /* 773 6741 th199096 * failed set attrs 774 6741 th199096 */ 775 6741 th199096 goto done; 776 6741 th199096 } 777 6741 th199096 778 6741 th199096 if (sarg.vap->va_mask == 0 && ! ATTR_ISSET(fattrp->attrmask, ACL) && 779 6741 th199096 ! ATTR_ISSET(fattrp->attrmask, LAYOUT_HINT)) { 780 6741 th199096 /* 781 6741 th199096 * no further work to be done 782 6741 th199096 */ 783 6741 th199096 goto done; 784 6741 th199096 } 785 6741 th199096 786 6741 th199096 ct.cc_sysid = 0; 787 6741 th199096 ct.cc_pid = 0; 788 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 789 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 790 6741 th199096 791 6741 th199096 /* 792 6741 th199096 * If we got a request to set the ACL and the MODE, only 793 6741 th199096 * allow changing VSUID, VSGID, and VSVTX. Attempting 794 6741 th199096 * to change any other bits, along with setting an ACL, 795 6741 th199096 * gives NFS4ERR_INVAL. 796 6741 th199096 */ 797 6741 th199096 if (ATTR_ISSET(fattrp->attrmask, ACL) && 798 6741 th199096 ATTR_ISSET(fattrp->attrmask, MODE)) { 799 6741 th199096 vattr_t va; 800 6741 th199096 801 6741 th199096 va.va_mask = AT_MODE; 802 6741 th199096 error = VOP_GETATTR(vp, &va, 0, cs->cr, &ct); 803 6741 th199096 if (error) { 804 6741 th199096 status = puterrno4(error); 805 6741 th199096 goto done; 806 6741 th199096 } 807 6741 th199096 if ((sarg.vap->va_mode ^ va.va_mode) & 808 6741 th199096 ~(VSUID | VSGID | VSVTX)) { 809 6741 th199096 status = NFS4ERR_INVAL; 810 6741 th199096 goto done; 811 6741 th199096 } 812 6741 th199096 } 813 6741 th199096 814 6741 th199096 /* Check stateid only if size has been set */ 815 6741 th199096 if (sarg.vap->va_mask & AT_SIZE) { 816 6741 th199096 trunc = (sarg.vap->va_size == 0); 817 6741 th199096 status = mds_validate_stateid(FWRITE, 818 6741 th199096 cs, cs->vp, stateid, trunc, 819 6741 th199096 &cs->deleg, sarg.vap->va_mask & AT_SIZE); 820 6741 th199096 if (status != NFS4_OK) 821 6741 th199096 goto done; 822 6741 th199096 } 823 6741 th199096 824 6741 th199096 /* XXX start of possible race with delegations */ 825 6741 th199096 826 6741 th199096 /* 827 6741 th199096 * We need to specially handle size changes because it is 828 6741 th199096 * possible for the client to create a file with read-only 829 6741 th199096 * modes, but with the file opened for writing. If the client 830 6741 th199096 * then tries to set the file size, e.g. ftruncate(3C), 831 6741 th199096 * fcntl(F_FREESP), the normal access checking done in 832 6741 th199096 * VOP_SETATTR would prevent the client from doing it even though 833 6741 th199096 * it should be allowed to do so. To get around this, we do the 834 6741 th199096 * access checking for ourselves and use VOP_SPACE which doesn't 835 6741 th199096 * do the access checking. 836 6741 th199096 * Also the client should not be allowed to change the file 837 6741 th199096 * size if there is a conflicting non-blocking mandatory lock in 838 6741 th199096 * the region of the change. 839 6741 th199096 */ 840 6741 th199096 if (vp->v_type == VREG && (sarg.vap->va_mask & AT_SIZE)) { 841 6741 th199096 u_offset_t offset; 842 6741 th199096 ssize_t length; 843 6741 th199096 844 6741 th199096 /* 845 6741 th199096 * ufs_setattr clears AT_SIZE from vap->va_mask, but 846 6741 th199096 * before returning, sarg.vap->va_mask is used to 847 6741 th199096 * generate the setattr reply bitmap. We also clear 848 6741 th199096 * AT_SIZE below before calling VOP_SPACE. For both 849 6741 th199096 * of these cases, the va_mask needs to be saved here 850 6741 th199096 * and restored after calling VOP_SETATTR. 851 6741 th199096 */ 852 6741 th199096 saved_mask = sarg.vap->va_mask; 853 6741 th199096 854 6741 th199096 /* 855 6741 th199096 * Check any possible conflict due to NBMAND locks. 856 6741 th199096 * Get into critical region before VOP_GETATTR, so the 857 6741 th199096 * size attribute is valid when checking conflicts. 858 6741 th199096 */ 859 6741 th199096 if (nbl_need_check(vp)) { 860 6741 th199096 nbl_start_crit(vp, RW_READER); 861 6741 th199096 in_crit = 1; 862 6741 th199096 } 863 6741 th199096 864 6741 th199096 bva.va_mask = AT_UID|AT_SIZE; 865 6741 th199096 if (error = VOP_GETATTR(vp, &bva, 0, cr, &ct)) { 866 6741 th199096 status = puterrno4(error); 867 6741 th199096 goto done; 868 6741 th199096 } 869 6741 th199096 870 6741 th199096 if (in_crit) { 871 6741 th199096 if (sarg.vap->va_size < bva.va_size) { 872 6741 th199096 offset = sarg.vap->va_size; 873 6741 th199096 length = bva.va_size - sarg.vap->va_size; 874 6741 th199096 } else { 875 6741 th199096 offset = bva.va_size; 876 6741 th199096 length = sarg.vap->va_size - bva.va_size; 877 6741 th199096 } 878 6741 th199096 if (nbl_conflict(vp, NBL_WRITE, offset, length, 0, 879 6741 th199096 &ct)) { 880 6741 th199096 status = NFS4ERR_LOCKED; 881 6741 th199096 goto done; 882 6741 th199096 } 883 6741 th199096 } 884 6741 th199096 885 6741 th199096 if (crgetuid(cr) == bva.va_uid) { 886 6741 th199096 sarg.vap->va_mask &= ~AT_SIZE; 887 6741 th199096 bf.l_type = F_WRLCK; 888 6741 th199096 bf.l_whence = 0; 889 6741 th199096 bf.l_start = (off64_t)sarg.vap->va_size; 890 6741 th199096 bf.l_len = 0; 891 6741 th199096 bf.l_sysid = 0; 892 6741 th199096 bf.l_pid = 0; 893 6741 th199096 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE, 894 6741 th199096 (offset_t)sarg.vap->va_size, cr, &ct); 895 6741 th199096 } 896 6741 th199096 } 897 6741 th199096 898 6741 th199096 if (!error && sarg.vap->va_mask != 0) 899 6741 th199096 error = VOP_SETATTR(vp, sarg.vap, sarg.flag, cr, &ct); 900 6741 th199096 901 6741 th199096 /* restore va_mask -- ufs_setattr clears AT_SIZE */ 902 6741 th199096 if (saved_mask & AT_SIZE) 903 6741 th199096 sarg.vap->va_mask |= AT_SIZE; 904 6741 th199096 905 6741 th199096 /* 906 6741 th199096 * If an ACL was being set, it has been delayed until now, 907 6741 th199096 * in order to set the mode (via the VOP_SETATTR() above) first. 908 6741 th199096 */ 909 6741 th199096 if (! error && ATTR_ISSET(fattrp->attrmask, ACL)) { 910 6741 th199096 int i; 911 6741 th199096 912 6741 th199096 for (i = 0; i < ntov.attrcnt; i++) 913 6741 th199096 if (ntov.amap[i] == FATTR4_ACL) 914 6741 th199096 break; 915 6741 th199096 if (i < ntov.attrcnt) { 916 6741 th199096 error = (*nvmap[FATTR4_ACL].sv_getit)(NFS4ATTR_SETIT, 917 6741 th199096 &sarg, &ntov.na[i]); 918 6741 th199096 if (error == 0) { 919 6741 th199096 ATTR_SET(*resp, ACL); 920 6741 th199096 } else if (error == ENOTSUP) { 921 6741 th199096 (void) rfs4_verify_attr(&sarg, resp, &ntov); 922 6741 th199096 status = NFS4ERR_ATTRNOTSUPP; 923 6741 th199096 goto done; 924 6741 th199096 } 925 6741 th199096 } else { 926 6741 th199096 error = EINVAL; 927 6741 th199096 } 928 6741 th199096 } 929 6741 th199096 930 6741 th199096 if (! error && ATTR_ISSET(fattrp->attrmask, LAYOUT_HINT)) { 931 6741 th199096 /* 932 6741 th199096 * Store layout hint. Layout hint will be stored 933 6741 th199096 * in file struct (which means it can only be set 934 6741 th199096 * when the file is open). If layout hint is allowed 935 6741 th199096 * for files not open, then it must be stored 936 6741 th199096 * persistently. 937 6741 th199096 * 938 6741 th199096 * status assignment placates lint. it will 939 6741 th199096 * be replaced with code to store the layout 940 6741 th199096 * hint. 941 6741 th199096 */ 942 6741 th199096 status = NFS4_OK; 943 6741 th199096 } 944 6741 th199096 945 6741 th199096 if (error) { 946 6741 th199096 /* check if a monitor detected a delegation conflict */ 947 6741 th199096 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) 948 6741 th199096 status = NFS4ERR_DELAY; 949 6741 th199096 else 950 6741 th199096 status = puterrno4(error); 951 6741 th199096 952 6741 th199096 /* 953 6741 th199096 * Set the response bitmap when setattr failed. 954 6741 th199096 * If VOP_SETATTR partially succeeded, test by doing a 955 6741 th199096 * VOP_GETATTR on the object and comparing the data 956 6741 th199096 * to the setattr arguments. 957 6741 th199096 */ 958 6741 th199096 (void) rfs4_verify_attr(&sarg, resp, &ntov); 959 6741 th199096 } else { 960 6741 th199096 /* 961 6741 th199096 * Force modified metadata out to stable storage. 962 6741 th199096 */ 963 6741 th199096 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct); 964 6741 th199096 /* 965 6741 th199096 * Set response bitmap 966 6741 th199096 */ 967 6741 th199096 nfs4_vmask_to_nmask_set(sarg.vap->va_mask, resp); 968 6741 th199096 } 969 6741 th199096 970 6741 th199096 /* Return early and already have a NFSv4 error */ 971 6741 th199096 done: 972 6741 th199096 /* 973 6741 th199096 * Except for nfs4_vmask_to_nmask_set(), vattr --> fattr 974 6741 th199096 * conversion sets both readable and writeable NFS4 attrs 975 6741 th199096 * for AT_MTIME and AT_ATIME. The line below masks out 976 6741 th199096 * unrequested attrs from the setattr result bitmap. This 977 6741 th199096 * is placed after the done: label to catch the ATTRNOTSUP 978 6741 th199096 * case. 979 6741 th199096 */ 980 6741 th199096 ATTRMAP_MASK(*resp, fattrp->attrmask); 981 6741 th199096 982 6741 th199096 if (in_crit) 983 6741 th199096 nbl_end_crit(vp); 984 6741 th199096 985 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 986 6741 th199096 987 6741 th199096 return (status); 988 6741 th199096 } 989 6741 th199096 990 6741 th199096 /* ARGSUSED */ 991 6741 th199096 void 992 6741 th199096 mds_op_secinfonn(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 993 8023 Sam compound_state_t *cs) 994 8023 Sam { 995 6741 th199096 SECINFO_NO_NAME4res *respnn; 996 6741 th199096 int dotdot; 997 6741 th199096 998 7312 Danhua DTRACE_NFSV4_1(op__secinfo__no__name__start, 999 7312 Danhua struct compound_state *, cs); 1000 7312 Danhua 1001 6741 th199096 respnn = &resop->nfs_resop4_u.opsecinfo_no_name; 1002 6741 th199096 1003 6741 th199096 /* 1004 6741 th199096 * Current file handle (cfh) should have been set before 1005 6741 th199096 * getting into this function. If not, return error. 1006 6741 th199096 */ 1007 6741 th199096 if (cs->vp == NULL) { 1008 6741 th199096 *cs->statusp = respnn->status = NFS4ERR_NOFILEHANDLE; 1009 7312 Danhua goto final; 1010 6741 th199096 } 1011 6741 th199096 1012 6741 th199096 dotdot = 1013 6741 th199096 (argop->nfs_argop4_u.opsecinfo_no_name == SECINFO_STYLE4_PARENT); 1014 6741 th199096 1015 6741 th199096 *cs->statusp = respnn->status = do_rfs4_op_secinfo(cs, NULL, 1016 6741 th199096 dotdot, (SECINFO4res *)respnn); 1017 7312 Danhua 1018 7312 Danhua final: 1019 7312 Danhua DTRACE_NFSV4_2(op__secinfo__no__name__done, 1020 7312 Danhua struct compound_state *, cs, 1021 7312 Danhua SECINFO_NO_NAME4res *, respnn); 1022 6741 th199096 } 1023 6741 th199096 1024 6741 th199096 /* ARGSUSED */ 1025 6741 th199096 void 1026 6741 th199096 mds_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1027 8023 Sam compound_state_t *cs) 1028 8023 Sam { 1029 6741 th199096 SECINFO4res *resp; 1030 6741 th199096 utf8string *utfnm; 1031 6741 th199096 uint_t len, dotdot; 1032 6741 th199096 char *nm; 1033 6741 th199096 1034 7312 Danhua SECINFO4args *args = &argop->nfs_argop4_u.opsecinfo; 1035 7312 Danhua 1036 7312 Danhua DTRACE_NFSV4_2(op__secinfo__start, struct compound_state *, cs, 1037 7312 Danhua SECINFO4args *, args); 1038 7312 Danhua 1039 6741 th199096 resp = &resop->nfs_resop4_u.opsecinfo; 1040 6741 th199096 1041 6741 th199096 /* 1042 6741 th199096 * Current file handle (cfh) should have been set before 1043 6741 th199096 * getting into this function. If not, return error. 1044 6741 th199096 */ 1045 6741 th199096 if (cs->vp == NULL) { 1046 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1047 7312 Danhua goto final; 1048 6741 th199096 } 1049 6741 th199096 if (cs->vp->v_type != VDIR) { 1050 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 1051 7312 Danhua goto final; 1052 6741 th199096 } 1053 6741 th199096 1054 6741 th199096 /* 1055 6741 th199096 * Verify the component name. If failed, error out, but 1056 6741 th199096 * do not error out if the component name is a "..". 1057 6741 th199096 * SECINFO will return its parents secinfo data for SECINFO "..". 1058 6741 th199096 */ 1059 6741 th199096 utfnm = &argop->nfs_argop4_u.opsecinfo.name; 1060 6741 th199096 if (!utf8_dir_verify(utfnm)) { 1061 6741 th199096 if (utfnm->utf8string_len != 2 || 1062 6741 th199096 utfnm->utf8string_val[0] != '.' || 1063 6741 th199096 utfnm->utf8string_val[1] != '.') { 1064 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1065 7312 Danhua goto final; 1066 6741 th199096 } 1067 6741 th199096 dotdot = 1; 1068 6741 th199096 } else 1069 6741 th199096 dotdot = 0; 1070 6741 th199096 1071 6741 th199096 nm = utf8_to_str(utfnm, &len, NULL); 1072 6741 th199096 if (nm == NULL) { 1073 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1074 7312 Danhua goto final; 1075 6741 th199096 } 1076 6741 th199096 1077 6741 th199096 if (len > MAXNAMELEN) { 1078 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG; 1079 6741 th199096 kmem_free(nm, len); 1080 7312 Danhua goto final; 1081 6741 th199096 } 1082 6741 th199096 1083 6741 th199096 *cs->statusp = resp->status = do_rfs4_op_secinfo(cs, nm, dotdot, resp); 1084 6741 th199096 1085 6741 th199096 kmem_free(nm, len); 1086 7312 Danhua 1087 7312 Danhua final: 1088 7312 Danhua DTRACE_NFSV4_2(op__secinfo__done, struct compound_state *, cs, 1089 7312 Danhua SECINFO4res *, resp); 1090 6741 th199096 } 1091 6741 th199096 1092 6741 th199096 /* 1093 6741 th199096 * verify and nverify are exactly the same, except that nverify 1094 6741 th199096 * succeeds when some argument changed, and verify succeeds when 1095 6741 th199096 * when none changed. 1096 6741 th199096 */ 1097 6741 th199096 1098 6741 th199096 /* ARGSUSED */ 1099 6741 th199096 void 1100 6741 th199096 mds_op_verify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1101 8023 Sam compound_state_t *cs) 1102 8023 Sam { 1103 6741 th199096 VERIFY4args *args = &argop->nfs_argop4_u.opverify; 1104 6741 th199096 VERIFY4res *resp = &resop->nfs_resop4_u.opverify; 1105 6741 th199096 int error; 1106 6741 th199096 struct nfs4_svgetit_arg sarg; 1107 6741 th199096 struct statvfs64 sb; 1108 6741 th199096 struct nfs4_ntov_table ntov; 1109 6741 th199096 1110 7312 Danhua DTRACE_NFSV4_2(op__verify__start, struct compound_state *, cs, 1111 7312 Danhua VERIFY4args *, args); 1112 7312 Danhua 1113 7312 Danhua if (cs->vp == NULL) { 1114 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1115 7312 Danhua goto final; 1116 6741 th199096 } 1117 6741 th199096 1118 6741 th199096 sarg.sbp = &sb; 1119 6741 th199096 nfs4_ntov_table_init(&ntov, RFS4_ATTRVERS(cs)); 1120 6741 th199096 resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs, 1121 6741 th199096 &sarg, &ntov, NFS4ATTR_VERIT); 1122 6741 th199096 if (resp->status != NFS4_OK) { 1123 6741 th199096 /* 1124 6741 th199096 * do_rfs4_set_attrs will try to verify systemwide attrs, 1125 6741 th199096 * so could return -1 for "no match". 1126 6741 th199096 */ 1127 6741 th199096 if (resp->status == -1) 1128 6741 th199096 resp->status = NFS4ERR_NOT_SAME; 1129 6741 th199096 goto done; 1130 6741 th199096 } 1131 6741 th199096 error = rfs4_verify_attr(&sarg, NULL, &ntov); 1132 6741 th199096 switch (error) { 1133 6741 th199096 case 0: 1134 6741 th199096 resp->status = NFS4_OK; 1135 6741 th199096 break; 1136 6741 th199096 case -1: 1137 6741 th199096 resp->status = NFS4ERR_NOT_SAME; 1138 6741 th199096 break; 1139 6741 th199096 default: 1140 6741 th199096 resp->status = puterrno4(error); 1141 6741 th199096 break; 1142 6741 th199096 } 1143 6741 th199096 done: 1144 6741 th199096 *cs->statusp = resp->status; 1145 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1146 7312 Danhua 1147 7312 Danhua final: 1148 7312 Danhua DTRACE_NFSV4_2(op__verify__done, struct compound_state *, cs, 1149 7312 Danhua VERIFY4res *, resp); 1150 6741 th199096 } 1151 6741 th199096 1152 6741 th199096 /* ARGSUSED */ 1153 6741 th199096 void 1154 6741 th199096 mds_op_nverify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1155 8023 Sam compound_state_t *cs) 1156 8023 Sam { 1157 6741 th199096 NVERIFY4args *args = &argop->nfs_argop4_u.opnverify; 1158 6741 th199096 NVERIFY4res *resp = &resop->nfs_resop4_u.opnverify; 1159 6741 th199096 int error; 1160 6741 th199096 struct nfs4_svgetit_arg sarg; 1161 6741 th199096 struct statvfs64 sb; 1162 6741 th199096 struct nfs4_ntov_table ntov; 1163 6741 th199096 1164 7312 Danhua DTRACE_NFSV4_2(op__nverify__start, struct compound_state *, cs, 1165 7312 Danhua NVERIFY4args *, args); 1166 7312 Danhua 1167 7312 Danhua if (cs->vp == NULL) { 1168 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1169 7312 Danhua goto final; 1170 6741 th199096 } 1171 6741 th199096 sarg.sbp = &sb; 1172 6741 th199096 nfs4_ntov_table_init(&ntov, RFS4_ATTRVERS(cs)); 1173 6741 th199096 resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs, 1174 6741 th199096 &sarg, &ntov, NFS4ATTR_VERIT); 1175 6741 th199096 if (resp->status != NFS4_OK) { 1176 6741 th199096 /* 1177 6741 th199096 * do_rfs4_set_attrs will try to verify systemwide attrs, 1178 6741 th199096 * so could return -1 for "no match". 1179 6741 th199096 */ 1180 6741 th199096 if (resp->status == -1) 1181 6741 th199096 resp->status = NFS4_OK; 1182 6741 th199096 goto done; 1183 6741 th199096 } 1184 6741 th199096 error = rfs4_verify_attr(&sarg, NULL, &ntov); 1185 6741 th199096 switch (error) { 1186 6741 th199096 case 0: 1187 6741 th199096 resp->status = NFS4ERR_SAME; 1188 6741 th199096 break; 1189 6741 th199096 case -1: 1190 6741 th199096 resp->status = NFS4_OK; 1191 6741 th199096 break; 1192 6741 th199096 default: 1193 6741 th199096 resp->status = puterrno4(error); 1194 6741 th199096 break; 1195 6741 th199096 } 1196 6741 th199096 done: 1197 6741 th199096 *cs->statusp = resp->status; 1198 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1199 7312 Danhua 1200 7312 Danhua final: 1201 7312 Danhua DTRACE_NFSV4_2(op__nverify__done, struct compound_state *, cs, 1202 7312 Danhua NVERIFY4res *, resp); 1203 7312 Danhua 1204 6741 th199096 } 1205 6741 th199096 1206 6741 th199096 /* ARGSUSED */ 1207 6741 th199096 void 1208 6741 th199096 mds_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1209 8023 Sam compound_state_t *cs) 1210 8023 Sam { 1211 6741 th199096 ACCESS4args *args = &argop->nfs_argop4_u.opaccess; 1212 6741 th199096 ACCESS4res *resp = &resop->nfs_resop4_u.opaccess; 1213 6741 th199096 int error; 1214 6741 th199096 vnode_t *vp; 1215 6741 th199096 struct vattr va; 1216 6741 th199096 int checkwriteperm; 1217 6741 th199096 cred_t *cr = cs->cr; 1218 6741 th199096 bslabel_t *clabel, *slabel; 1219 6741 th199096 ts_label_t *tslabel; 1220 6741 th199096 boolean_t admin_low_client; 1221 6741 th199096 1222 7312 Danhua DTRACE_NFSV4_2(op__access__start, struct compound_state *, cs, 1223 7312 Danhua ACCESS4args *, args); 1224 7312 Danhua 1225 7312 Danhua if (cs->vp == NULL) { 1226 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1227 7312 Danhua goto final; 1228 6741 th199096 } 1229 6741 th199096 1230 6741 th199096 ASSERT(cr != NULL); 1231 6741 th199096 1232 6741 th199096 vp = cs->vp; 1233 6741 th199096 1234 6741 th199096 /* 1235 6741 th199096 * If the file system is exported read only, it is not appropriate 1236 6741 th199096 * to check write permissions for regular files and directories. 1237 6741 th199096 * Special files are interpreted by the client, so the underlying 1238 6741 th199096 * permissions are sent back to the client for interpretation. 1239 6741 th199096 */ 1240 6741 th199096 if (rdonly4(cs->exi, cs->vp, req) && 1241 6741 th199096 (vp->v_type == VREG || vp->v_type == VDIR)) 1242 6741 th199096 checkwriteperm = 0; 1243 6741 th199096 else 1244 6741 th199096 checkwriteperm = 1; 1245 6741 th199096 1246 6741 th199096 /* 1247 6741 th199096 * XXX 1248 6741 th199096 * We need the mode so that we can correctly determine access 1249 6741 th199096 * permissions relative to a mandatory lock file. Access to 1250 6741 th199096 * mandatory lock files is denied on the server, so it might 1251 6741 th199096 * as well be reflected to the server during the open. 1252 6741 th199096 */ 1253 6741 th199096 va.va_mask = AT_MODE; 1254 6741 th199096 error = VOP_GETATTR(vp, &va, 0, cr, NULL); 1255 6741 th199096 if (error) { 1256 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1257 7312 Danhua goto final; 1258 6741 th199096 } 1259 6741 th199096 resp->access = 0; 1260 6741 th199096 resp->supported = 0; 1261 6741 th199096 1262 6741 th199096 if (is_system_labeled()) { 1263 6741 th199096 ASSERT(req->rq_label != NULL); 1264 6741 th199096 clabel = req->rq_label; 1265 6741 th199096 DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *, 1266 6741 th199096 "got client label from request(1)", 1267 6741 th199096 struct svc_req *, req); 1268 6741 th199096 if (!blequal(&l_admin_low->tsl_label, clabel)) { 1269 10447 Thomas if ((tslabel = nfs_getflabel(vp, cs->exi)) == NULL) { 1270 6741 th199096 *cs->statusp = resp->status = puterrno4(EACCES); 1271 7312 Danhua goto final; 1272 6741 th199096 } 1273 6741 th199096 slabel = label2bslabel(tslabel); 1274 6741 th199096 DTRACE_PROBE3(tx__rfs4__log__info__opaccess__slabel, 1275 6741 th199096 char *, "got server label(1) for vp(2)", 1276 6741 th199096 bslabel_t *, slabel, vnode_t *, vp); 1277 6741 th199096 1278 6741 th199096 admin_low_client = B_FALSE; 1279 6741 th199096 } else 1280 6741 th199096 admin_low_client = B_TRUE; 1281 6741 th199096 } 1282 6741 th199096 1283 6741 th199096 if (args->access & ACCESS4_READ) { 1284 6741 th199096 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL); 1285 6741 th199096 if (!error && !MANDLOCK(vp, va.va_mode) && 1286 6741 th199096 (!is_system_labeled() || admin_low_client || 1287 6741 th199096 bldominates(clabel, slabel))) 1288 6741 th199096 resp->access |= ACCESS4_READ; 1289 6741 th199096 resp->supported |= ACCESS4_READ; 1290 6741 th199096 } 1291 6741 th199096 if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) { 1292 6741 th199096 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL); 1293 6741 th199096 if (!error && (!is_system_labeled() || admin_low_client || 1294 6741 th199096 bldominates(clabel, slabel))) 1295 6741 th199096 resp->access |= ACCESS4_LOOKUP; 1296 6741 th199096 resp->supported |= ACCESS4_LOOKUP; 1297 6741 th199096 } 1298 6741 th199096 if (checkwriteperm && 1299 6741 th199096 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) { 1300 6741 th199096 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL); 1301 6741 th199096 if (!error && !MANDLOCK(vp, va.va_mode) && 1302 6741 th199096 (!is_system_labeled() || admin_low_client || 1303 6741 th199096 blequal(clabel, slabel))) 1304 6741 th199096 resp->access |= 1305 6741 th199096 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND)); 1306 6741 th199096 resp->supported |= (ACCESS4_MODIFY|ACCESS4_EXTEND); 1307 6741 th199096 } 1308 6741 th199096 1309 6741 th199096 if (checkwriteperm && 1310 6741 th199096 (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) { 1311 6741 th199096 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL); 1312 6741 th199096 if (!error && (!is_system_labeled() || admin_low_client || 1313 6741 th199096 blequal(clabel, slabel))) 1314 6741 th199096 resp->access |= ACCESS4_DELETE; 1315 6741 th199096 resp->supported |= ACCESS4_DELETE; 1316 6741 th199096 } 1317 6741 th199096 if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) { 1318 6741 th199096 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL); 1319 6741 th199096 if (!error && !MANDLOCK(vp, va.va_mode) && 1320 6741 th199096 (!is_system_labeled() || admin_low_client || 1321 6741 th199096 bldominates(clabel, slabel))) 1322 6741 th199096 resp->access |= ACCESS4_EXECUTE; 1323 6741 th199096 resp->supported |= ACCESS4_EXECUTE; 1324 6741 th199096 } 1325 6741 th199096 1326 6741 th199096 if (is_system_labeled() && !admin_low_client) 1327 6741 th199096 label_rele(tslabel); 1328 6741 th199096 1329 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 1330 7312 Danhua 1331 7312 Danhua final: 1332 7312 Danhua DTRACE_NFSV4_2(op__access__done, struct compound_state *, cs, 1333 7312 Danhua ACCESS4res *, resp); 1334 6741 th199096 } 1335 6741 th199096 1336 6741 th199096 /* ARGSUSED */ 1337 6741 th199096 static void 1338 6741 th199096 mds_op_commit(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1339 8023 Sam compound_state_t *cs) 1340 8023 Sam { 1341 6741 th199096 COMMIT4args *args = &argop->nfs_argop4_u.opcommit; 1342 6741 th199096 COMMIT4res *resp = &resop->nfs_resop4_u.opcommit; 1343 6741 th199096 int error; 1344 6741 th199096 vnode_t *vp = cs->vp; 1345 6741 th199096 cred_t *cr = cs->cr; 1346 6741 th199096 vattr_t va; 1347 6741 th199096 caller_context_t ct; 1348 6741 th199096 1349 7312 Danhua DTRACE_NFSV4_2(op__commit__start, struct compound_state *, cs, 1350 7312 Danhua COMMIT4args *, args); 1351 6741 th199096 1352 6741 th199096 if (vp == NULL) { 1353 8033 Sam /* 1354 8033 Sam * XXX kludge: fake the commit if we are a data server 1355 8033 Sam * This will be replaced once we have nnop_commit(). 1356 8033 Sam */ 1357 8033 Sam if (cs->nn != NULL) { 1358 8033 Sam *cs->statusp = resp->status = NFS4_OK; 1359 8033 Sam resp->writeverf = cs->instp->Write4verf; 1360 8033 Sam } else { 1361 8033 Sam *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1362 8033 Sam } 1363 7312 Danhua goto final; 1364 7312 Danhua } 1365 7312 Danhua if (cs->access == CS_ACCESS_DENIED) { 1366 7312 Danhua *cs->statusp = resp->status = NFS4ERR_ACCESS; 1367 7312 Danhua goto final; 1368 6741 th199096 } 1369 6741 th199096 1370 6741 th199096 if (args->offset + args->count < args->offset) { 1371 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1372 7312 Danhua goto final; 1373 6741 th199096 } 1374 6741 th199096 1375 6741 th199096 ct.cc_sysid = 0; 1376 6741 th199096 ct.cc_pid = 0; 1377 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 1378 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 1379 6741 th199096 1380 6741 th199096 va.va_mask = AT_UID; 1381 6741 th199096 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 1382 6741 th199096 1383 6741 th199096 /* 1384 6741 th199096 * If we can't get the attributes, then we can't do the 1385 6741 th199096 * right access checking. So, we'll fail the request. 1386 6741 th199096 */ 1387 6741 th199096 if (error) { 1388 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1389 7312 Danhua goto final; 1390 6741 th199096 } 1391 6741 th199096 if (rdonly4(cs->exi, cs->vp, req)) { 1392 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ROFS; 1393 7312 Danhua goto final; 1394 6741 th199096 } 1395 6741 th199096 1396 6741 th199096 if (vp->v_type != VREG) { 1397 6741 th199096 if (vp->v_type == VDIR) 1398 6741 th199096 resp->status = NFS4ERR_ISDIR; 1399 6741 th199096 else 1400 6741 th199096 resp->status = NFS4ERR_INVAL; 1401 6741 th199096 *cs->statusp = resp->status; 1402 7312 Danhua goto final; 1403 6741 th199096 } 1404 6741 th199096 1405 6741 th199096 if (crgetuid(cr) != va.va_uid && 1406 6741 th199096 (error = VOP_ACCESS(vp, VWRITE, 0, cs->cr, &ct))) { 1407 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1408 7312 Danhua goto final; 1409 6741 th199096 } 1410 6741 th199096 1411 6741 th199096 error = VOP_PUTPAGE(vp, args->offset, args->count, 0, cr, &ct); 1412 6741 th199096 if (!error) 1413 6741 th199096 error = VOP_FSYNC(vp, FNODSYNC, cr, &ct); 1414 6741 th199096 1415 6741 th199096 if (error) { 1416 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1417 7312 Danhua goto final; 1418 6741 th199096 } 1419 6741 th199096 1420 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 1421 6741 th199096 resp->writeverf = cs->instp->Write4verf; 1422 7312 Danhua 1423 7312 Danhua final: 1424 7312 Danhua DTRACE_NFSV4_2(op__commit__done, struct compound_state *, cs, 1425 7312 Danhua COMMIT4res *, resp); 1426 6741 th199096 } 1427 6741 th199096 1428 6741 th199096 /* 1429 6741 th199096 * rfs4_op_mknod is called from rfs4_op_create after all initial verification 1430 6741 th199096 * was completed. It does the nfsv4 create for special files. 1431 6741 th199096 * 1432 6741 th199096 * nfsv4 create is used to create non-regular files. For regular files, 1433 6741 th199096 * use nfsv4 open. 1434 6741 th199096 */ 1435 6741 th199096 /* ARGSUSED */ 1436 6741 th199096 static void 1437 6741 th199096 mds_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1438 8023 Sam compound_state_t *cs) 1439 6741 th199096 { 1440 6741 th199096 CREATE4args *args = &argop->nfs_argop4_u.opcreate; 1441 6741 th199096 CREATE4res *resp = &resop->nfs_resop4_u.opcreate; 1442 6741 th199096 int error; 1443 6741 th199096 struct vattr bva, iva, iva2, ava, *vap; 1444 6741 th199096 cred_t *cr = cs->cr; 1445 6741 th199096 vnode_t *dvp = cs->vp; 1446 6741 th199096 vnode_t *vp = NULL; 1447 9399 Thomas vnode_t *realvp; 1448 6741 th199096 char *nm, *lnm; 1449 6741 th199096 uint_t len, llen; 1450 6741 th199096 int syncval = 0; 1451 6741 th199096 struct nfs4_svgetit_arg sarg; 1452 6741 th199096 struct nfs4_ntov_table ntov; 1453 6741 th199096 struct statvfs64 sb; 1454 6741 th199096 nfsstat4 status; 1455 6741 th199096 caller_context_t ct; 1456 6741 th199096 1457 7312 Danhua DTRACE_NFSV4_2(op__create__start, struct compound_state *, cs, 1458 7312 Danhua CREATE4args *, args); 1459 7312 Danhua 1460 6741 th199096 resp->attrset = NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1461 6741 th199096 1462 6741 th199096 if (dvp == NULL) { 1463 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1464 7312 Danhua goto final; 1465 6741 th199096 } 1466 6741 th199096 1467 6741 th199096 /* 1468 6741 th199096 * If there is an unshared filesystem mounted on this vnode, 1469 6741 th199096 * do not allow to create an object in this directory. 1470 6741 th199096 */ 1471 6741 th199096 if (vn_ismntpt(dvp)) { 1472 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ACCESS; 1473 7312 Danhua goto final; 1474 6741 th199096 } 1475 6741 th199096 1476 6741 th199096 ct.cc_sysid = 0; 1477 6741 th199096 ct.cc_pid = 0; 1478 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 1479 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 1480 6741 th199096 1481 6741 th199096 /* Verify that type is correct */ 1482 6741 th199096 switch (args->type) { 1483 6741 th199096 case NF4LNK: 1484 6741 th199096 case NF4BLK: 1485 6741 th199096 case NF4CHR: 1486 6741 th199096 case NF4SOCK: 1487 6741 th199096 case NF4FIFO: 1488 6741 th199096 case NF4DIR: 1489 6741 th199096 break; 1490 6741 th199096 default: 1491 6741 th199096 *cs->statusp = resp->status = NFS4ERR_BADTYPE; 1492 7312 Danhua goto final; 1493 6741 th199096 }; 1494 6741 th199096 1495 6741 th199096 if (cs->access == CS_ACCESS_DENIED) { 1496 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ACCESS; 1497 7312 Danhua goto final; 1498 6741 th199096 } 1499 6741 th199096 if (dvp->v_type != VDIR) { 1500 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 1501 7312 Danhua goto final; 1502 6741 th199096 } 1503 6741 th199096 if (!utf8_dir_verify(&args->objname)) { 1504 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1505 7312 Danhua goto final; 1506 6741 th199096 } 1507 6741 th199096 1508 6741 th199096 if (rdonly4(cs->exi, cs->vp, req)) { 1509 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ROFS; 1510 7312 Danhua goto final; 1511 6741 th199096 } 1512 6741 th199096 1513 6741 th199096 /* 1514 6741 th199096 * Name of newly created object 1515 6741 th199096 */ 1516 6741 th199096 nm = utf8_to_fn(&args->objname, &len, NULL); 1517 6741 th199096 if (nm == NULL) { 1518 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1519 7312 Danhua goto final; 1520 6741 th199096 } 1521 6741 th199096 1522 6741 th199096 if (len > MAXNAMELEN) { 1523 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG; 1524 6741 th199096 kmem_free(nm, len); 1525 7312 Danhua goto final; 1526 6741 th199096 } 1527 6741 th199096 1528 6741 th199096 sarg.sbp = &sb; 1529 6741 th199096 nfs4_ntov_table_init(&ntov, RFS4_ATTRVERS(cs)); 1530 6741 th199096 1531 6741 th199096 status = do_rfs4_set_attrs(&resp->attrset, 1532 6741 th199096 &args->createattrs, cs, &sarg, &ntov, NFS4ATTR_SETIT); 1533 6741 th199096 1534 6741 th199096 if (sarg.vap->va_mask == 0 && status == NFS4_OK) 1535 6741 th199096 status = NFS4ERR_INVAL; 1536 6741 th199096 1537 6741 th199096 if (status != NFS4_OK) { 1538 6741 th199096 *cs->statusp = resp->status = status; 1539 6741 th199096 kmem_free(nm, len); 1540 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1541 7312 Danhua 1542 6741 th199096 resp->attrset = NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1543 7312 Danhua goto final; 1544 6741 th199096 } 1545 6741 th199096 1546 6741 th199096 /* Get "before" change value */ 1547 6741 th199096 bva.va_mask = AT_CTIME|AT_SEQ; 1548 6741 th199096 error = VOP_GETATTR(dvp, &bva, 0, cr, &ct); 1549 6741 th199096 if (error) { 1550 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1551 6741 th199096 kmem_free(nm, len); 1552 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1553 7312 Danhua 1554 6741 th199096 resp->attrset = NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1555 7312 Danhua goto final; 1556 6741 th199096 } 1557 6741 th199096 NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bva.va_ctime) 1558 6741 th199096 1559 6741 th199096 vap = sarg.vap; 1560 6741 th199096 1561 6741 th199096 /* 1562 6741 th199096 * Set default initial values for attributes when not specified 1563 6741 th199096 * in createattrs. 1564 6741 th199096 */ 1565 6741 th199096 if ((vap->va_mask & AT_UID) == 0) { 1566 6741 th199096 vap->va_uid = crgetuid(cr); 1567 6741 th199096 vap->va_mask |= AT_UID; 1568 6741 th199096 } 1569 6741 th199096 if ((vap->va_mask & AT_GID) == 0) { 1570 6741 th199096 vap->va_gid = crgetgid(cr); 1571 6741 th199096 vap->va_mask |= AT_GID; 1572 6741 th199096 } 1573 6741 th199096 1574 6741 th199096 vap->va_mask |= AT_TYPE; 1575 6741 th199096 switch (args->type) { 1576 6741 th199096 case NF4DIR: 1577 6741 th199096 vap->va_type = VDIR; 1578 6741 th199096 if ((vap->va_mask & AT_MODE) == 0) { 1579 6741 th199096 vap->va_mode = 0700; /* default: owner rwx only */ 1580 6741 th199096 vap->va_mask |= AT_MODE; 1581 6741 th199096 } 1582 6741 th199096 error = VOP_MKDIR(dvp, nm, vap, &vp, cr, &ct, 0, NULL); 1583 6741 th199096 if (error) 1584 6741 th199096 break; 1585 6741 th199096 1586 6741 th199096 /* 1587 6741 th199096 * Get the initial "after" sequence number, if it fails, 1588 6741 th199096 * set to zero 1589 6741 th199096 */ 1590 6741 th199096 iva.va_mask = AT_SEQ; 1591 6741 th199096 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, &ct)) 1592 6741 th199096 iva.va_seq = 0; 1593 6741 th199096 break; 1594 6741 th199096 case NF4LNK: 1595 6741 th199096 vap->va_type = VLNK; 1596 6741 th199096 if ((vap->va_mask & AT_MODE) == 0) { 1597 6741 th199096 vap->va_mode = 0700; /* default: owner rwx only */ 1598 6741 th199096 vap->va_mask |= AT_MODE; 1599 6741 th199096 } 1600 6741 th199096 1601 6741 th199096 /* 1602 6741 th199096 * symlink names must be treated as data 1603 6741 th199096 */ 1604 6741 th199096 lnm = utf8_to_str(&args->ftype4_u.linkdata, &llen, NULL); 1605 6741 th199096 1606 6741 th199096 if (lnm == NULL) { 1607 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1608 6741 th199096 kmem_free(nm, len); 1609 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1610 6741 th199096 resp->attrset = 1611 6741 th199096 NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1612 7312 Danhua goto final; 1613 6741 th199096 } 1614 6741 th199096 1615 6741 th199096 if (llen > MAXPATHLEN) { 1616 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG; 1617 6741 th199096 kmem_free(nm, len); 1618 6741 th199096 kmem_free(lnm, llen); 1619 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1620 6741 th199096 resp->attrset = 1621 6741 th199096 NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1622 7312 Danhua goto final; 1623 6741 th199096 } 1624 6741 th199096 1625 6741 th199096 error = VOP_SYMLINK(dvp, nm, vap, lnm, cr, &ct, 0); 1626 6741 th199096 if (lnm != NULL) 1627 6741 th199096 kmem_free(lnm, llen); 1628 6741 th199096 if (error) 1629 6741 th199096 break; 1630 6741 th199096 1631 6741 th199096 /* 1632 6741 th199096 * Get the initial "after" sequence number, if it fails, 1633 6741 th199096 * set to zero 1634 6741 th199096 */ 1635 6741 th199096 iva.va_mask = AT_SEQ; 1636 6741 th199096 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, &ct)) 1637 6741 th199096 iva.va_seq = 0; 1638 6741 th199096 1639 6741 th199096 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cr, 1640 6741 th199096 &ct, 0, NULL); 1641 6741 th199096 if (error) 1642 6741 th199096 break; 1643 6741 th199096 1644 6741 th199096 /* 1645 6741 th199096 * va_seq is not safe over VOP calls, check it again 1646 6741 th199096 * if it has changed zero out iva to force atomic = FALSE. 1647 6741 th199096 */ 1648 6741 th199096 iva2.va_mask = AT_SEQ; 1649 6741 th199096 if (VOP_GETATTR(dvp, &iva2, 0, cs->cr, &ct) || 1650 6741 th199096 iva2.va_seq != iva.va_seq) 1651 6741 th199096 iva.va_seq = 0; 1652 6741 th199096 break; 1653 6741 th199096 default: 1654 6741 th199096 /* 1655 6741 th199096 * probably a special file. 1656 6741 th199096 */ 1657 6741 th199096 if ((vap->va_mask & AT_MODE) == 0) { 1658 6741 th199096 vap->va_mode = 0600; /* default: owner rw only */ 1659 6741 th199096 vap->va_mask |= AT_MODE; 1660 6741 th199096 } 1661 6741 th199096 syncval = FNODSYNC; 1662 6741 th199096 /* 1663 6741 th199096 * We know this will only generate one VOP call 1664 6741 th199096 */ 1665 6741 th199096 vp = do_rfs4_op_mknod(args, resp, req, cs, vap, nm); 1666 6741 th199096 1667 6741 th199096 if (vp == NULL) { 1668 6741 th199096 kmem_free(nm, len); 1669 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1670 6741 th199096 resp->attrset = NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1671 7312 Danhua goto final; 1672 6741 th199096 } 1673 6741 th199096 1674 6741 th199096 /* 1675 6741 th199096 * Get the initial "after" sequence number, if it fails, 1676 6741 th199096 * set to zero 1677 6741 th199096 */ 1678 6741 th199096 iva.va_mask = AT_SEQ; 1679 6741 th199096 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, &ct)) 1680 6741 th199096 iva.va_seq = 0; 1681 6741 th199096 1682 6741 th199096 break; 1683 6741 th199096 } 1684 6741 th199096 kmem_free(nm, len); 1685 6741 th199096 1686 6741 th199096 if (error) { 1687 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1688 6741 th199096 } 1689 6741 th199096 1690 6741 th199096 /* 1691 6741 th199096 * Force modified data and metadata out to stable storage. 1692 6741 th199096 */ 1693 6741 th199096 (void) VOP_FSYNC(dvp, 0, cr, &ct); 1694 6741 th199096 1695 6741 th199096 if (resp->status != NFS4_OK) { 1696 6741 th199096 if (vp != NULL) 1697 6741 th199096 VN_RELE(vp); 1698 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1699 6741 th199096 resp->attrset = NFS4_EMPTY_ATTRMAP(RFS4_ATTRVERS(cs)); 1700 7312 Danhua goto final; 1701 6741 th199096 } 1702 6741 th199096 1703 6741 th199096 /* 1704 6741 th199096 * Finish setup of cinfo response, "before" value already set. 1705 6741 th199096 * Get "after" change value, if it fails, simply return the 1706 6741 th199096 * before value. 1707 6741 th199096 */ 1708 6741 th199096 ava.va_mask = AT_CTIME|AT_SEQ; 1709 6741 th199096 if (VOP_GETATTR(dvp, &ava, 0, cr, &ct)) { 1710 6741 th199096 ava.va_ctime = bva.va_ctime; 1711 6741 th199096 ava.va_seq = 0; 1712 6741 th199096 } 1713 6741 th199096 NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, ava.va_ctime); 1714 6741 th199096 1715 6741 th199096 /* 1716 6741 th199096 * True verification that object was created with correct 1717 6741 th199096 * attrs is impossible. The attrs could have been changed 1718 6741 th199096 * immediately after object creation. If attributes did 1719 6741 th199096 * not verify, the only recourse for the server is to 1720 6741 th199096 * destroy the object. Maybe if some attrs (like gid) 1721 6741 th199096 * are set incorrectly, the object should be destroyed; 1722 6741 th199096 * however, seems bad as a default policy. Do we really 1723 6741 th199096 * want to destroy an object over one of the times not 1724 6741 th199096 * verifying correctly? For these reasons, the server 1725 6741 th199096 * currently sets bits in attrset for createattrs 1726 6741 th199096 * that were set; however, no verification is done. 1727 6741 th199096 * 1728 6741 th199096 * vmask_to_nmask accounts for vattr bits set on create 1729 6741 th199096 * [do_rfs4_set_attrs() only sets resp bits for 1730 6741 th199096 * non-vattr/vfs bits.] 1731 6741 th199096 * Mask off any bits set by default so as not to return 1732 6741 th199096 * more attrset bits than were requested in createattrs 1733 6741 th199096 */ 1734 6741 th199096 nfs4_vmask_to_nmask(sarg.vap->va_mask, &resp->attrset, 1735 6741 th199096 RFS4_ATTRVERS(cs)); 1736 6741 th199096 ATTRMAP_MASK(resp->attrset, args->createattrs.attrmask); 1737 6741 th199096 nfs4_ntov_table_free(&ntov, &sarg); 1738 6741 th199096 1739 6741 th199096 error = mknfs41_fh(&cs->fh, vp, cs->exi); 1740 6741 th199096 if (error) { 1741 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 1742 6741 th199096 } 1743 6741 th199096 1744 6741 th199096 /* 1745 6741 th199096 * The cinfo.atomic = TRUE only if we got no errors, we have 1746 6741 th199096 * non-zero va_seq's, and it has incremented by exactly one 1747 6741 th199096 * during the creation and it didn't change during the VOP_LOOKUP 1748 6741 th199096 * or VOP_FSYNC. 1749 6741 th199096 */ 1750 6741 th199096 if (!error && bva.va_seq && iva.va_seq && ava.va_seq && 1751 6741 th199096 iva.va_seq == (bva.va_seq + 1) && 1752 6741 th199096 iva.va_seq == ava.va_seq) 1753 6741 th199096 resp->cinfo.atomic = TRUE; 1754 6741 th199096 else 1755 6741 th199096 resp->cinfo.atomic = FALSE; 1756 6741 th199096 1757 9399 Thomas /* 1758 9399 Thomas * Force modified metadata out to stable storage. 1759 9399 Thomas * 1760 9399 Thomas * if a underlying vp exists, pass it to VOP_FSYNC 1761 9399 Thomas */ 1762 9399 Thomas if (VOP_REALVP(vp, &realvp, &ct) == 0) 1763 9399 Thomas (void) VOP_FSYNC(realvp, syncval, cr, &ct); 1764 9399 Thomas else 1765 9399 Thomas (void) VOP_FSYNC(vp, syncval, cr, &ct); 1766 6741 th199096 1767 6741 th199096 if (resp->status != NFS4_OK) { 1768 6741 th199096 VN_RELE(vp); 1769 7312 Danhua goto final; 1770 6741 th199096 } 1771 6741 th199096 if (cs->vp) 1772 6741 th199096 VN_RELE(cs->vp); 1773 6741 th199096 1774 6741 th199096 cs->vp = vp; 1775 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 1776 7312 Danhua 1777 7312 Danhua final: 1778 7312 Danhua DTRACE_NFSV4_2(op__create__done, struct compound_state *, cs, 1779 7312 Danhua CREATE4res *, resp); 1780 6741 th199096 } 1781 6741 th199096 1782 6741 th199096 1783 6741 th199096 /*ARGSUSED*/ 1784 6741 th199096 static void 1785 6741 th199096 mds_op_delegreturn(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1786 8023 Sam compound_state_t *cs) 1787 6741 th199096 { 1788 6741 th199096 DELEGRETURN4args *args = &argop->nfs_argop4_u.opdelegreturn; 1789 6741 th199096 DELEGRETURN4res *resp = &resop->nfs_resop4_u.opdelegreturn; 1790 6741 th199096 rfs4_deleg_state_t *dsp; 1791 6741 th199096 nfsstat4 status; 1792 6741 th199096 1793 7312 Danhua DTRACE_NFSV4_2(op__delegreturn__start, struct compound_state *, cs, 1794 7312 Danhua DELEGRETURN4args *, args); 1795 7312 Danhua 1796 6741 th199096 status = rfs4_get_deleg_state(cs, &args->deleg_stateid, &dsp); 1797 6741 th199096 resp->status = *cs->statusp = status; 1798 6741 th199096 if (status != NFS4_OK) 1799 7312 Danhua goto final; 1800 6741 th199096 1801 6741 th199096 /* Ensure specified filehandle matches */ 1802 10447 Thomas if (cs->vp != dsp->rds_finfo->rf_vp) { 1803 6741 th199096 resp->status = *cs->statusp = NFS4ERR_BAD_STATEID; 1804 6741 th199096 } else 1805 6741 th199096 rfs4_return_deleg(dsp, FALSE); 1806 6741 th199096 1807 10447 Thomas rfs4_update_lease(dsp->rds_client); 1808 6741 th199096 1809 6741 th199096 rfs4_deleg_state_rele(dsp); 1810 7312 Danhua 1811 7312 Danhua final: 1812 7312 Danhua DTRACE_NFSV4_2(op__delegreturn__done, struct compound_state *, cs, 1813 7312 Danhua DELEGRETURN4res *, resp); 1814 6741 th199096 } 1815 6741 th199096 1816 6741 th199096 1817 6741 th199096 1818 6741 th199096 /* ARGSUSED */ 1819 6741 th199096 static void 1820 6741 th199096 mds_op_getattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1821 8023 Sam compound_state_t *cs) 1822 6741 th199096 { 1823 6741 th199096 GETATTR4args *args = &argop->nfs_argop4_u.opgetattr; 1824 6741 th199096 GETATTR4res *resp = &resop->nfs_resop4_u.opgetattr; 1825 6741 th199096 struct nfs4_svgetit_arg sarg; 1826 6741 th199096 struct statvfs64 sb; 1827 6741 th199096 nfsstat4 status; 1828 6741 th199096 1829 7312 Danhua DTRACE_NFSV4_2(op__getattr__start, struct compound_state *, cs, 1830 7312 Danhua GETATTR4args *, args); 1831 7312 Danhua 1832 7312 Danhua if (cs->vp == NULL) { 1833 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1834 7312 Danhua goto final; 1835 7312 Danhua } 1836 7312 Danhua 1837 7312 Danhua if (cs->access == CS_ACCESS_DENIED) { 1838 7312 Danhua *cs->statusp = resp->status = NFS4ERR_ACCESS; 1839 7312 Danhua goto final; 1840 6741 th199096 } 1841 6741 th199096 1842 6741 th199096 sarg.sbp = &sb; 1843 6741 th199096 sarg.cs = cs; 1844 6741 th199096 1845 6741 th199096 status = attrmap4_to_vattrmask(&args->attr_request, &sarg); 1846 6741 th199096 if (status == NFS4_OK) { 1847 6741 th199096 status = bitmap4_get_sysattrs(&sarg); 1848 6741 th199096 if (status == NFS4_OK) 1849 6741 th199096 status = do_rfs4_op_getattr(&args->attr_request, 1850 6741 th199096 &resp->obj_attributes, &sarg); 1851 6741 th199096 } 1852 6741 th199096 *cs->statusp = resp->status = status; 1853 7312 Danhua 1854 7312 Danhua final: 1855 7312 Danhua DTRACE_NFSV4_2(op__getattr__done, struct compound_state *, cs, 1856 7312 Danhua GETATTR4res *, resp); 1857 6741 th199096 } 1858 6741 th199096 1859 6741 th199096 /*ARGSUSED*/ 1860 6741 th199096 void 1861 8023 Sam mds_op_getattr_free(nfs_resop4 *resop, compound_state_t *cs) 1862 6741 th199096 { 1863 6741 th199096 /* Common function for NFSv4.0 and NFSv4.1 */ 1864 6741 th199096 rfs4_op_getattr_free(resop); 1865 6741 th199096 } 1866 6741 th199096 1867 6741 th199096 /* ARGSUSED */ 1868 6741 th199096 static void 1869 6741 th199096 mds_op_getfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1870 8023 Sam compound_state_t *cs) 1871 6741 th199096 { 1872 6741 th199096 GETFH4res *resp = &resop->nfs_resop4_u.opgetfh; 1873 6741 th199096 1874 7312 Danhua DTRACE_NFSV4_1(op__getfh__start, 1875 7312 Danhua struct compound_state *, cs); 1876 7312 Danhua 1877 7312 Danhua if (cs->vp == NULL) { 1878 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1879 7312 Danhua goto final; 1880 7312 Danhua } 1881 7312 Danhua if (cs->access == CS_ACCESS_DENIED) { 1882 7312 Danhua *cs->statusp = resp->status = NFS4ERR_ACCESS; 1883 7312 Danhua goto final; 1884 6741 th199096 } 1885 6741 th199096 1886 6741 th199096 resp->object.nfs_fh4_val = 1887 6741 th199096 kmem_alloc(cs->fh.nfs_fh4_len, KM_SLEEP); 1888 6741 th199096 nfs_fh4_copy(&cs->fh, &resp->object); 1889 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 1890 7312 Danhua 1891 7312 Danhua final: 1892 7312 Danhua DTRACE_NFSV4_2(op__getfh__done, struct compound_state *, cs, 1893 7312 Danhua GETFH4res *, resp); 1894 6741 th199096 } 1895 6741 th199096 1896 6741 th199096 /*ARGSUSED*/ 1897 6741 th199096 static void 1898 8023 Sam mds_op_getfh_free(nfs_resop4 *resop, compound_state_t *cs) 1899 6741 th199096 { 1900 6741 th199096 /* Common function for NFSv4.0 and NFSv4.1 */ 1901 6741 th199096 rfs4_op_getfh_free(resop); 1902 6741 th199096 } 1903 6741 th199096 1904 6741 th199096 /* 1905 6741 th199096 * link: args: SAVED_FH: file, CURRENT_FH: target directory 1906 6741 th199096 * res: status. If success - CURRENT_FH unchanged, return change_info 1907 6741 th199096 */ 1908 6741 th199096 /* ARGSUSED */ 1909 6741 th199096 static void 1910 6741 th199096 mds_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 1911 8023 Sam compound_state_t *cs) 1912 6741 th199096 { 1913 6741 th199096 LINK4args *args = &argop->nfs_argop4_u.oplink; 1914 6741 th199096 LINK4res *resp = &resop->nfs_resop4_u.oplink; 1915 6741 th199096 int error; 1916 6741 th199096 vnode_t *vp; 1917 6741 th199096 vnode_t *dvp; 1918 6741 th199096 struct vattr bdva, idva, adva; 1919 6741 th199096 char *nm; 1920 6741 th199096 uint_t len; 1921 6741 th199096 caller_context_t ct; 1922 6741 th199096 1923 7312 Danhua DTRACE_NFSV4_2(op__link__start, struct compound_state *, cs, 1924 7312 Danhua LINK4args *, args); 1925 7312 Danhua 1926 6741 th199096 /* SAVED_FH: source object */ 1927 6741 th199096 vp = cs->saved_vp; 1928 6741 th199096 if (vp == NULL) { 1929 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1930 7312 Danhua goto final; 1931 6741 th199096 } 1932 6741 th199096 1933 6741 th199096 /* CURRENT_FH: target directory */ 1934 6741 th199096 dvp = cs->vp; 1935 6741 th199096 if (dvp == NULL) { 1936 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 1937 7312 Danhua goto final; 1938 6741 th199096 } 1939 6741 th199096 1940 6741 th199096 /* 1941 6741 th199096 * If there is a non-shared filesystem mounted on this vnode, 1942 6741 th199096 * do not allow to link any file in this directory. 1943 6741 th199096 */ 1944 6741 th199096 if (vn_ismntpt(dvp)) { 1945 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ACCESS; 1946 7312 Danhua goto final; 1947 7312 Danhua } 1948 7312 Danhua 1949 7312 Danhua if (cs->access == CS_ACCESS_DENIED) { 1950 7312 Danhua *cs->statusp = resp->status = NFS4ERR_ACCESS; 1951 7312 Danhua goto final; 1952 6741 th199096 } 1953 6741 th199096 1954 6741 th199096 /* Check source object's type validity */ 1955 6741 th199096 if (vp->v_type == VDIR) { 1956 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ISDIR; 1957 7312 Danhua goto final; 1958 6741 th199096 } 1959 6741 th199096 1960 6741 th199096 /* Check target directory's type */ 1961 6741 th199096 if (dvp->v_type != VDIR) { 1962 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 1963 7312 Danhua goto final; 1964 6741 th199096 } 1965 6741 th199096 1966 6741 th199096 if (cs->saved_exi != cs->exi) { 1967 6741 th199096 *cs->statusp = resp->status = NFS4ERR_XDEV; 1968 7312 Danhua goto final; 1969 6741 th199096 } 1970 6741 th199096 1971 6741 th199096 if (!utf8_dir_verify(&args->newname)) { 1972 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1973 7312 Danhua goto final; 1974 6741 th199096 } 1975 6741 th199096 1976 6741 th199096 nm = utf8_to_fn(&args->newname, &len, NULL); 1977 6741 th199096 if (nm == NULL) { 1978 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 1979 7312 Danhua goto final; 1980 6741 th199096 } 1981 6741 th199096 1982 6741 th199096 if (len > MAXNAMELEN) { 1983 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG; 1984 6741 th199096 kmem_free(nm, len); 1985 7312 Danhua goto final; 1986 6741 th199096 } 1987 6741 th199096 1988 6741 th199096 if (rdonly4(cs->exi, cs->vp, req)) { 1989 6741 th199096 *cs->statusp = resp->status = NFS4ERR_ROFS; 1990 6741 th199096 kmem_free(nm, len); 1991 7312 Danhua goto final; 1992 6741 th199096 } 1993 6741 th199096 1994 6741 th199096 ct.cc_sysid = 0; 1995 6741 th199096 ct.cc_pid = 0; 1996 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 1997 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 1998 6741 th199096 1999 6741 th199096 /* Get "before" change value */ 2000 6741 th199096 bdva.va_mask = AT_CTIME|AT_SEQ; 2001 6741 th199096 error = VOP_GETATTR(dvp, &bdva, 0, cs->cr, &ct); 2002 6741 th199096 if (error) { 2003 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 2004 6741 th199096 kmem_free(nm, len); 2005 7312 Danhua goto final; 2006 6741 th199096 } 2007 6741 th199096 2008 6741 th199096 NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime) 2009 6741 th199096 2010 6741 th199096 error = VOP_LINK(dvp, vp, nm, cs->cr, &ct, 0); 2011 6741 th199096 2012 6741 th199096 kmem_free(nm, len); 2013 6741 th199096 2014 6741 th199096 /* 2015 6741 th199096 * Get the initial "after" sequence number, if it fails, set to zero 2016 6741 th199096 */ 2017 6741 th199096 idva.va_mask = AT_SEQ; 2018 6741 th199096 if (VOP_GETATTR(dvp, &idva, 0, cs->cr, &ct)) 2019 6741 th199096 idva.va_seq = 0; 2020 6741 th199096 2021 6741 th199096 /* 2022 6741 th199096 * Force modified data and metadata out to stable storage. 2023 6741 th199096 */ 2024 6741 th199096 (void) VOP_FSYNC(vp, FNODSYNC, cs->cr, &ct); 2025 6741 th199096 (void) VOP_FSYNC(dvp, 0, cs->cr, &ct); 2026 6741 th199096 2027 6741 th199096 if (error) { 2028 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 2029 7312 Danhua goto final; 2030 6741 th199096 } 2031 6741 th199096 2032 6741 th199096 /* 2033 6741 th199096 * Get "after" change value, if it fails, simply return the 2034 6741 th199096 * before value. 2035 6741 th199096 */ 2036 6741 th199096 adva.va_mask = AT_CTIME|AT_SEQ; 2037 6741 th199096 if (VOP_GETATTR(dvp, &adva, 0, cs->cr, &ct)) { 2038 6741 th199096 adva.va_ctime = bdva.va_ctime; 2039 6741 th199096 adva.va_seq = 0; 2040 6741 th199096 } 2041 6741 th199096 2042 6741 th199096 NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime) 2043 6741 th199096 2044 6741 th199096 /* 2045 6741 th199096 * The cinfo.atomic = TRUE only if we have 2046 6741 th199096 * non-zero va_seq's, and it has incremented by exactly one 2047 6741 th199096 * during the VOP_LINK and it didn't change during the VOP_FSYNC. 2048 6741 th199096 */ 2049 6741 th199096 if (bdva.va_seq && idva.va_seq && adva.va_seq && 2050 6741 th199096 idva.va_seq == (bdva.va_seq + 1) && 2051 6741 th199096 idva.va_seq == adva.va_seq) 2052 6741 th199096 resp->cinfo.atomic = TRUE; 2053 6741 th199096 else 2054 6741 th199096 resp->cinfo.atomic = FALSE; 2055 6741 th199096 2056 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2057 7312 Danhua 2058 7312 Danhua final: 2059 7312 Danhua DTRACE_NFSV4_2(op__link__done, struct compound_state *, cs, 2060 7312 Danhua LINK4res *, resp); 2061 6741 th199096 } 2062 6741 th199096 2063 6741 th199096 /* 2064 6741 th199096 * Used by mds_op_lookup and mds_op_lookupp to do the actual work. 2065 6741 th199096 */ 2066 6741 th199096 2067 6741 th199096 /* ARGSUSED */ 2068 6741 th199096 static nfsstat4 2069 6741 th199096 mds_do_lookup(char *nm, uint_t buflen, struct svc_req *req, 2070 6741 th199096 struct compound_state *cs) 2071 6741 th199096 { 2072 6741 th199096 int error; 2073 6741 th199096 int different_export = 0; 2074 6741 th199096 vnode_t *vp, *tvp, *pre_tvp = NULL, *oldvp = NULL; 2075 6741 th199096 struct exportinfo *exi = NULL, *pre_exi = NULL; 2076 6741 th199096 nfsstat4 stat; 2077 6741 th199096 fid_t fid; 2078 6741 th199096 int attrdir, dotdot, walk; 2079 6741 th199096 bool_t is_newvp = FALSE; 2080 6741 th199096 caller_context_t ct; 2081 6741 th199096 nfs41_fh_fmt_t *fhp; 2082 6741 th199096 2083 6741 th199096 fhp = (nfs41_fh_fmt_t *)cs->fh.nfs_fh4_val; 2084 6741 th199096 2085 6741 th199096 attrdir = ((cs->vp->v_flag & V_XATTRDIR) == V_XATTRDIR) 2086 6741 th199096 ? FH41_ATTRDIR : 0; 2087 6741 th199096 2088 6741 th199096 ASSERT(FH41_GET_FLAG(fhp, FH41_ATTRDIR) == attrdir); 2089 6741 th199096 2090 6741 th199096 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0'); 2091 6741 th199096 2092 6741 th199096 /* 2093 6741 th199096 * If dotdotting, then need to check whether it's 2094 6741 th199096 * above the root of a filesystem, or above an 2095 6741 th199096 * export point. 2096 6741 th199096 */ 2097 6741 th199096 if (dotdot) { 2098 6741 th199096 2099 6741 th199096 /* 2100 6741 th199096 * If dotdotting at the root of a filesystem, then 2101 6741 th199096 * need to traverse back to the mounted-on filesystem 2102 6741 th199096 * and do the dotdot lookup there. 2103 6741 th199096 */ 2104 6741 th199096 if (cs->vp->v_flag & VROOT) { 2105 6741 th199096 2106 6741 th199096 /* 2107 6741 th199096 * If at the system root, then can 2108 6741 th199096 * go up no further. 2109 6741 th199096 */ 2110 6741 th199096 if (VN_CMP(cs->vp, rootdir)) 2111 6741 th199096 return (puterrno4(ENOENT)); 2112 6741 th199096 2113 6741 th199096 /* 2114 6741 th199096 * Traverse back to the mounted-on filesystem 2115 6741 th199096 */ 2116 6741 th199096 cs->vp = untraverse(cs->vp); 2117 6741 th199096 2118 6741 th199096 /* 2119 6741 th199096 * Set the different_export flag so we remember 2120 6741 th199096 * to pick up a new exportinfo entry for 2121 6741 th199096 * this new filesystem. 2122 6741 th199096 */ 2123 6741 th199096 different_export = 1; 2124 6741 th199096 } else { 2125 6741 th199096 2126 6741 th199096 /* 2127 6741 th199096 * If dotdotting above an export point then set 2128 6741 th199096 * the different_export to get new export info. 2129 6741 th199096 */ 2130 6741 th199096 different_export = nfs_exported(cs->exi, cs->vp); 2131 6741 th199096 } 2132 6741 th199096 } 2133 6741 th199096 2134 6741 th199096 ct.cc_sysid = 0; 2135 6741 th199096 ct.cc_pid = 0; 2136 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 2137 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 2138 6741 th199096 2139 6741 th199096 error = VOP_LOOKUP(cs->vp, nm, &vp, NULL, 0, NULL, cs->cr, 2140 6741 th199096 &ct, 0, NULL); 2141 6741 th199096 if (error) 2142 6741 th199096 return (puterrno4(error)); 2143 6741 th199096 2144 6741 th199096 /* 2145 6741 th199096 * If the vnode is in a pseudo filesystem, check whether it is visible. 2146 6741 th199096 * 2147 6741 th199096 * XXX if the vnode is a symlink and it is not visible in 2148 6741 th199096 * a pseudo filesystem, return ENOENT (not following symlink). 2149 6741 th199096 * V4 client can not mount such symlink. 2150 6741 th199096 * 2151 6741 th199096 * In the same exported filesystem, if the security flavor used 2152 6741 th199096 * is not an explicitly shared flavor, limit the view to the visible 2153 6741 th199096 * list entries only. This is not a WRONGSEC case because it's already 2154 6741 th199096 * checked via PUTROOTFH/PUTPUBFH or PUTFH. 2155 6741 th199096 */ 2156 6741 th199096 if (!different_export && 2157 6741 th199096 (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) || 2158 6741 th199096 cs->access & CS_ACCESS_LIMITED)) { 2159 6741 th199096 if (! nfs_visible(cs->exi, vp, &different_export)) { 2160 6741 th199096 VN_RELE(vp); 2161 6741 th199096 return (puterrno4(ENOENT)); 2162 6741 th199096 } 2163 6741 th199096 } 2164 6741 th199096 2165 6741 th199096 /* 2166 6741 th199096 * If it's a mountpoint, then traverse it. 2167 6741 th199096 */ 2168 6741 th199096 if (vn_ismntpt(vp)) { 2169 6741 th199096 pre_exi = cs->exi; /* save pre-traversed exportinfo */ 2170 6741 th199096 pre_tvp = vp; /* save pre-traversed vnode */ 2171 6741 th199096 2172 6741 th199096 /* 2173 6741 th199096 * hold pre_tvp to counteract rele by traverse. We will 2174 6741 th199096 * need pre_tvp below if checkexport4 fails 2175 6741 th199096 */ 2176 6741 th199096 VN_HOLD(pre_tvp); 2177 6741 th199096 tvp = vp; 2178 6741 th199096 if ((error = traverse(&tvp)) != 0) { 2179 6741 th199096 VN_RELE(vp); 2180 6741 th199096 VN_RELE(pre_tvp); 2181 6741 th199096 return (puterrno4(error)); 2182 6741 th199096 } 2183 6741 th199096 vp = tvp; 2184 6741 th199096 different_export = 1; 2185 6741 th199096 2186 6741 th199096 } else if (vp->v_vfsp != cs->vp->v_vfsp) { 2187 6741 th199096 /* 2188 6741 th199096 * The vfsp comparison is to handle the case where 2189 6741 th199096 * a LOFS mount is shared. lo_lookup traverses mount points, 2190 6741 th199096 * and NFS is unaware of local fs transistions because 2191 6741 th199096 * v_vfsmountedhere isn't set. For this special LOFS case, 2192 6741 th199096 * the dir and the obj returned by lookup will have different 2193 6741 th199096 * vfs ptrs. 2194 6741 th199096 */ 2195 6741 th199096 different_export = 1; 2196 6741 th199096 } 2197 6741 th199096 2198 6741 th199096 if (different_export) { 2199 6741 th199096 bzero(&fid, sizeof (fid)); 2200 6741 th199096 fid.fid_len = MAXFIDSZ; 2201 6741 th199096 error = vop_fid_pseudo(vp, &fid); 2202 6741 th199096 if (error) { 2203 6741 th199096 VN_RELE(vp); 2204 6741 th199096 if (pre_tvp) 2205 6741 th199096 VN_RELE(pre_tvp); 2206 6741 th199096 return (puterrno4(error)); 2207 6741 th199096 } 2208 6741 th199096 2209 6741 th199096 if (dotdot) 2210 6741 th199096 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE); 2211 6741 th199096 else 2212 6741 th199096 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp); 2213 6741 th199096 2214 6741 th199096 if (exi == NULL) { 2215 6741 th199096 if (pre_tvp) { 2216 6741 th199096 /* 2217 6741 th199096 * If this vnode is a mounted-on vnode, 2218 6741 th199096 * but the mounted-on file system is not 2219 6741 th199096 * exported, send back the filehandle for 2220 6741 th199096 * the mounted-on vnode, not the root of 2221 6741 th199096 * the mounted-on file system. 2222 6741 th199096 */ 2223 6741 th199096 VN_RELE(vp); 2224 6741 th199096 vp = pre_tvp; 2225 6741 th199096 exi = pre_exi; 2226 6741 th199096 } else { 2227 6741 th199096 VN_RELE(vp); 2228 6741 th199096 return (puterrno4(EACCES)); 2229 6741 th199096 } 2230 6741 th199096 } else if (pre_tvp) { 2231 6741 th199096 /* we're done with pre_tvp now. release extra hold */ 2232 6741 th199096 VN_RELE(pre_tvp); 2233 6741 th199096 } 2234 6741 th199096 2235 6741 th199096 cs->exi = exi; 2236 6741 th199096 2237 6741 th199096 /* 2238 6741 th199096 * Now do a checkauth4. 2239 6741 th199096 * 2240 6741 th199096 * Checking here since the client/principle may not have 2241 6741 th199096 * access to the cs->exi exported file system. 2242 6741 th199096 * 2243 6741 th199096 * If the client has access we also need to validate 2244 6741 th199096 * the principle since it may have been re-mapped. 2245 6741 th199096 * 2246 6741 th199096 * We start with a new credential as a previous call to 2247 6741 th199096 * checkauth4(), via a PUT*FH operation, wrote over cs->cr. 2248 6741 th199096 */ 2249 6741 th199096 crfree(cs->cr); 2250 6741 th199096 cs->cr = crdup(cs->basecr); 2251 6741 th199096 2252 6741 th199096 if (cs->vp) 2253 6741 th199096 oldvp = cs->vp; 2254 6741 th199096 cs->vp = vp; 2255 6741 th199096 is_newvp = TRUE; 2256 6741 th199096 2257 6741 th199096 stat = call_checkauth4(cs, req); 2258 6741 th199096 if (stat != NFS4_OK) { 2259 6741 th199096 VN_RELE(cs->vp); 2260 6741 th199096 cs->vp = oldvp; 2261 6741 th199096 return (stat); 2262 6741 th199096 } 2263 6741 th199096 } 2264 6741 th199096 2265 6741 th199096 /* 2266 6741 th199096 * After various NFS checks, do a label check on the path 2267 6741 th199096 * component. The label on this path should either be the 2268 6741 th199096 * global zone's label or a zone's label. We are only 2269 6741 th199096 * interested in the zone's label because exported files 2270 6741 th199096 * in global zone is accessible (though read-only) to 2271 6741 th199096 * clients. The exportability/visibility check is already 2272 6741 th199096 * done before reaching this code. 2273 6741 th199096 */ 2274 6741 th199096 if (is_system_labeled()) { 2275 6741 th199096 bslabel_t *clabel; 2276 6741 th199096 2277 6741 th199096 ASSERT(req->rq_label != NULL); 2278 6741 th199096 clabel = req->rq_label; 2279 6741 th199096 DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *, 2280 6741 th199096 "got client label from request(1)", struct svc_req *, req); 2281 6741 th199096 2282 6741 th199096 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2283 10447 Thomas if (!do_rfs_label_check(clabel, vp, 2284 10447 Thomas DOMINANCE_CHECK, cs->exi)) { 2285 6741 th199096 error = EACCES; 2286 6741 th199096 goto err_out; 2287 6741 th199096 } 2288 6741 th199096 } else { 2289 6741 th199096 /* 2290 6741 th199096 * We grant access to admin_low label clients 2291 6741 th199096 * only if the client is trusted, i.e. also 2292 6741 th199096 * running Solaris Trusted Extension. 2293 6741 th199096 */ 2294 6741 th199096 struct sockaddr *ca; 2295 6741 th199096 int addr_type; 2296 6741 th199096 void *ipaddr; 2297 6741 th199096 tsol_tpc_t *tp; 2298 6741 th199096 2299 6741 th199096 ca = (struct sockaddr *)svc_getrpccaller( 2300 6741 th199096 req->rq_xprt)->buf; 2301 6741 th199096 if (ca->sa_family == AF_INET) { 2302 6741 th199096 addr_type = IPV4_VERSION; 2303 6741 th199096 ipaddr = &((struct sockaddr_in *)ca)->sin_addr; 2304 6741 th199096 } else if (ca->sa_family == AF_INET6) { 2305 6741 th199096 addr_type = IPV6_VERSION; 2306 6741 th199096 ipaddr = &((struct sockaddr_in6 *) 2307 6741 th199096 ca)->sin6_addr; 2308 6741 th199096 } 2309 6741 th199096 tp = find_tpc(ipaddr, addr_type, B_FALSE); 2310 6741 th199096 if (tp == NULL || tp->tpc_tp.tp_doi != 2311 6741 th199096 l_admin_low->tsl_doi || tp->tpc_tp.host_type != 2312 6741 th199096 SUN_CIPSO) { 2313 6741 th199096 error = EACCES; 2314 6741 th199096 goto err_out; 2315 6741 th199096 } 2316 6741 th199096 } 2317 6741 th199096 } 2318 6741 th199096 2319 6741 th199096 error = mknfs41_fh(&cs->fh, vp, cs->exi); 2320 6741 th199096 2321 6741 th199096 err_out: 2322 6741 th199096 if (error) { 2323 6741 th199096 if (is_newvp) { 2324 6741 th199096 VN_RELE(cs->vp); 2325 6741 th199096 cs->vp = oldvp; 2326 6741 th199096 } else 2327 6741 th199096 VN_RELE(vp); 2328 6741 th199096 return (puterrno4(error)); 2329 6741 th199096 } 2330 6741 th199096 2331 6741 th199096 if (!is_newvp) { 2332 6741 th199096 if (cs->vp) 2333 6741 th199096 VN_RELE(cs->vp); 2334 6741 th199096 cs->vp = vp; 2335 6741 th199096 } else if (oldvp) 2336 6741 th199096 VN_RELE(oldvp); 2337 6741 th199096 2338 6741 th199096 /* 2339 6741 th199096 * if did lookup on attrdir and didn't lookup .., set named 2340 6741 th199096 * attr fh flag 2341 6741 th199096 */ 2342 6741 th199096 if (attrdir && ! dotdot) 2343 6741 th199096 FH41_SET_FLAG(fhp, FH41_NAMEDATTR); 2344 6741 th199096 2345 6741 th199096 /* Assume false for now, open proc will set this */ 2346 6741 th199096 cs->mandlock = FALSE; 2347 6741 th199096 2348 6741 th199096 return (NFS4_OK); 2349 6741 th199096 } 2350 6741 th199096 2351 6741 th199096 /* ARGSUSED */ 2352 6741 th199096 static void 2353 6741 th199096 mds_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 2354 8023 Sam compound_state_t *cs) 2355 6741 th199096 { 2356 6741 th199096 LOOKUP4args *args = &argop->nfs_argop4_u.oplookup; 2357 6741 th199096 LOOKUP4res *resp = &resop->nfs_resop4_u.oplookup; 2358 6741 th199096 char *nm; 2359 6741 th199096 uint_t len; 2360 6741 th199096 2361 7312 Danhua DTRACE_NFSV4_2(op__lookup__start, struct compound_state *, cs, 2362 7312 Danhua LOOKUP4args *, args); 2363 7312 Danhua 2364 7312 Danhua if (cs->vp == NULL) { 2365 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 2366 7312 Danhua goto final; 2367 6741 th199096 } 2368 6741 th199096 2369 6741 th199096 if (cs->vp->v_type == VLNK) { 2370 6741 th199096 *cs->statusp = resp->status = NFS4ERR_SYMLINK; 2371 7312 Danhua goto final; 2372 6741 th199096 } 2373 6741 th199096 2374 6741 th199096 if (cs->vp->v_type != VDIR) { 2375 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 2376 7312 Danhua goto final; 2377 6741 th199096 } 2378 6741 th199096 2379 6741 th199096 if (!utf8_dir_verify(&args->objname)) { 2380 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 2381 7312 Danhua goto final; 2382 6741 th199096 } 2383 6741 th199096 2384 6741 th199096 nm = utf8_to_str(&args->objname, &len, NULL); 2385 6741 th199096 if (nm == NULL) { 2386 6741 th199096 *cs->statusp = resp->status = NFS4ERR_INVAL; 2387 7312 Danhua goto final; 2388 6741 th199096 } 2389 6741 th199096 2390 6741 th199096 if (len > MAXNAMELEN) { 2391 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG; 2392 6741 th199096 kmem_free(nm, len); 2393 7312 Danhua goto final; 2394 6741 th199096 } 2395 6741 th199096 2396 6741 th199096 *cs->statusp = resp->status = mds_do_lookup(nm, len, req, cs); 2397 6741 th199096 2398 6741 th199096 kmem_free(nm, len); 2399 7312 Danhua 2400 7312 Danhua final: 2401 7312 Danhua DTRACE_NFSV4_2(op__lookup__done, struct compound_state *, cs, 2402 7312 Danhua LOOKUP4res *, resp); 2403 6741 th199096 } 2404 6741 th199096 2405 6741 th199096 /* ARGSUSED */ 2406 6741 th199096 static void 2407 6741 th199096 mds_op_lookupp(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req, 2408 8023 Sam compound_state_t *cs) 2409 6741 th199096 { 2410 6741 th199096 LOOKUPP4res *resp = &resop->nfs_resop4_u.oplookupp; 2411 6741 th199096 2412 7312 Danhua DTRACE_NFSV4_1(op__lookupp__start, struct compound_state *, cs); 2413 7312 Danhua 2414 7312 Danhua if (cs->vp == NULL) { 2415 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 2416 7312 Danhua goto final; 2417 6741 th199096 } 2418 6741 th199096 2419 6741 th199096 if (cs->vp->v_type != VDIR) { 2420 6741 th199096 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 2421 7312 Danhua goto final; 2422 6741 th199096 } 2423 6741 th199096 2424 6741 th199096 *cs->statusp = resp->status = mds_do_lookup("..", 3, req, cs); 2425 6741 th199096 2426 6741 th199096 /* 2427 6741 th199096 * From NFSV4 Specification, LOOKUPP should not check for 2428 6741 th199096 * NFS4ERR_WRONGSEC. Retrun NFS4_OK instead. 2429 6741 th199096 */ 2430 6741 th199096 if (resp->status == NFS4ERR_WRONGSEC) { 2431 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2432 6741 th199096 } 2433 7312 Danhua 2434 7312 Danhua final: 2435 7312 Danhua DTRACE_NFSV4_2(op__lookupp__done, struct compound_state *, cs, 2436 7312 Danhua LOOKUPP4res *, resp); 2437 6741 th199096 } 2438 6741 th199096 2439 6741 th199096 2440 6741 th199096 /*ARGSUSED2*/ 2441 6741 th199096 static void 2442 6741 th199096 mds_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 2443 8023 Sam compound_state_t *cs) 2444 6741 th199096 { 2445 6741 th199096 OPENATTR4args *args = &argop->nfs_argop4_u.opopenattr; 2446 6741 th199096 OPENATTR4res *resp = &resop->nfs_resop4_u.opopenattr; 2447 6741 th199096 vnode_t *avp = NULL; 2448 6741 th199096 int lookup_flags = LOOKUP_XATTR, error; 2449 6741 th199096 int exp_ro = 0; 2450 6741 th199096 caller_context_t ct; 2451 6741 th199096 2452 7312 Danhua DTRACE_NFSV4_2(op__openattr__start, struct compound_state *, cs, 2453 7312 Danhua OPENATTR4args *, args); 2454 7312 Danhua 2455 7312 Danhua if (cs->vp == NULL) { 2456 7312 Danhua *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 2457 7312 Danhua goto final; 2458 6741 th199096 } 2459 6741 th199096 2460 6741 th199096 /* 2461 6741 th199096 * Make a couple of checks made by copen() 2462 6741 th199096 * 2463 6741 th199096 * Check to make sure underlying fs supports xattrs. This 2464 6741 th199096 * is required because solaris filesystem implementations 2465 6741 th199096 * (UFS/TMPFS) don't enforce the noxattr mount option 2466 6741 th199096 * in VOP_LOOKUP(LOOKUP_XATTR). If fs doesn't support this 2467 6741 th199096 * pathconf cmd or if fs supports cmd but doesn't claim 2468 6741 th199096 * support for xattr, return NOTSUPP. It would be better 2469 6741 th199096 * to use VOP_PATHCONF( _PC_XATTR_ENABLED) for this; however, 2470 6741 th199096 * that cmd is not available to VOP_PATHCONF interface 2471 6741 th199096 * (it's only implemented inside pathconf syscall)... 2472 6741 th199096 * 2473 6741 th199096 * Verify permission to put attributes on files (access 2474 6741 th199096 * checks from copen). 2475 6741 th199096 */ 2476 6741 th199096 2477 6741 th199096 if ((cs->vp->v_vfsp->vfs_flag & VFS_XATTR) == 0) { 2478 6741 th199096 error = ENOTSUP; 2479 6741 th199096 goto error_out; 2480 6741 th199096 } 2481 6741 th199096 2482 6741 th199096 ct.cc_sysid = 0; 2483 6741 th199096 ct.cc_pid = 0; 2484 7739 jwahlig ct.cc_caller_id = cs->instp->caller_id; 2485 7739 jwahlig ct.cc_flags = CC_DONTBLOCK; 2486 6741 th199096 2487 6741 th199096 if ((VOP_ACCESS(cs->vp, VREAD, 0, cs->cr, &ct) != 0) && 2488 6741 th199096 (VOP_ACCESS(cs->vp, VWRITE, 0, cs->cr, &ct) != 0) && 2489 6741 th199096 (VOP_ACCESS(cs->vp, VEXEC, 0, cs->cr, &ct) != 0)) { 2490 6741 th199096 error = EACCES; 2491 6741 th199096 goto error_out; 2492 6741 th199096 } 2493 6741 th199096 2494 6741 th199096 /* 2495 6741 th199096 * The CREATE_XATTR_DIR VOP flag cannot be specified if 2496 6741 th199096 * the file system is exported read-only -- regardless of 2497 6741 th199096 * createdir flag. Otherwise the attrdir would be created 2498 6741 th199096 * (assuming server fs isn't mounted readonly locally). If 2499 6741 th199096 * VOP_LOOKUP returns ENOENT in this case, the error will 2500 6741 th199096 * be translated into EROFS. ENOSYS is mapped to ENOTSUP 2501 6741 th199096 * because specfs has no VOP_LOOKUP op, so the macro would 2502 6741 th199096 * return ENOSYS. EINVAL is returned by all (current) 2503 6741 th199096 * Solaris file system implementations when any of their 2504 6741 th199096 * restrictions are violated (xattr(dir) can't have xattrdir). 2505 6741 th199096 * Returning NOTSUPP is more appropriate in this case 2506 6741 th199096 * because the object will never be able to have an attrdir. 2507 6741 th199096 */ 2508 6741 th199096 if (args->createdir && ! (exp_ro = rdonly4(cs->exi, cs->vp, req))) 2509 6741 th199096 lookup_flags |= CREATE_XATTR_DIR; 2510 6741 th199096 2511 6741 th199096 error = VOP_LOOKUP(cs->vp, "", &avp, NULL, lookup_flags, NULL, 2512 6741 th199096 cs->cr, &ct, 0, NULL); 2513 6741 th199096 2514 6741 th199096 if (error) { 2515 6741 th199096 if (error == ENOENT && args->createdir && exp_ro) 2516 6741 th199096 error = EROFS; 2517 6741 th199096 else if (error == EINVAL || error == ENOSYS) 2518 6741 th199096 error = ENOTSUP; 2519 6741 th199096 goto error_out; 2520 6741 th199096 } 2521 6741 th199096 2522 6741 th199096 ASSERT(avp->v_flag & V_XATTRDIR); 2523 6741 th199096 2524 6741 th199096 error = mknfs41_fh(&cs->fh, avp, cs->exi); 2525 6741 th199096 2526 6741 th199096 if (error) { 2527 6741 th199096 VN_RELE(avp); 2528 6741 th199096 goto error_out; 2529 6741 th199096 } 2530 6741 th199096 2531 6741 th199096 VN_RELE(cs->vp); 2532 6741 th199096 cs->vp = avp; 2533 6741 th199096 2534 6741 th199096 /* 2535 6741 th199096 * There is no requirement for an attrdir fh flag 2536 6741 th199096 * because the attrdir has a vnode flag to distinguish 2537 6741 th199096 * it from regular (non-xattr) directories. The 2538 6741 th199096 * FH41_ATTRDIR flag is set for future sanity checks. 2539 6741 th199096 */ 2540 6741 th199096 FH41_SET_FLAG((nfs41_fh_fmt_t *)cs->fh.nfs_fh4_val, FH41_ATTRDIR); 2541 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2542 7312 Danhua goto final; 2543 6741 th199096 2544 6741 th199096 error_out: 2545 6741 th199096 2546 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 2547 7312 Danhua 2548 7312 Danhua final: 2549 7312 Danhua DTRACE_NFSV4_2(op__openattr__done, struct compound_state *, cs, 2550 7312 Danhua OPENATTR4res *, resp); 2551 6741 th199096 } 2552 6741 th199096 2553 6741 th199096 static int 2554 7739 jwahlig do_io(int direction, vnode_t *vp, struct uio *uio, int ioflag, cred_t *cred, 2555 7739 jwahlig caller_context_t *ct) 2556 6741 th199096 { 2557 6741 th199096 int error; 2558 6741 th199096 int i; 2559 6741 th199096 clock_t delaytime; 2560 6741 th199096 2561 6741 th199096 delaytime = MSEC_TO_TICK_ROUNDUP(rfs4_lock_delay); 2562 6741 th199096 2563 6741 th199096 /* 2564 6741 th199096 * Don't block on mandatory locks. If this routine returns 2565 6741 th199096 * EAGAIN, the caller should return NFS4ERR_LOCKED. 2566 6741 th199096 */ 2567 6741 th199096 uio->uio_fmode = FNONBLOCK; 2568 6741 th199096 2569 6741 th199096 for (i = 0; i < rfs4_maxlock_tries; i++) { 2570 6741 th199096 if (direction == FREAD) { 2571 7739 jwahlig (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, ct); 2572 7739 jwahlig error = VOP_READ(vp, uio, ioflag, cred, ct); 2573 7739 jwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, ct); 2574 7739 jwahlig } else { 2575 7739 jwahlig (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, ct); 2576 7739 jwahlig error = VOP_WRITE(vp, uio, ioflag, cred, ct); 2577 7739 jwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, ct); 2578 6741 th199096 } 2579 6741 th199096 2580 6741 th199096 if (error != EAGAIN) 2581 6741 th199096 break; 2582 6741 th199096 2583 6741 th199096 if (i < rfs4_maxlock_tries - 1) { 2584 6741 th199096 delay(delaytime); 2585 6741 th199096 delaytime *= 2; 2586 6741 th199096 } 2587 6741 th199096 } 2588 6741 th199096 2589 6741 th199096 return (error); 2590 6741 th199096 } 2591 6741 th199096 2592 6741 th199096 /* ARGSUSED */ 2593 6741 th199096 static void 2594 6741 th199096 mds_op_read(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 2595 8023 Sam compound_state_t *cs) 2596 8023 Sam { 2597 6741 th199096 READ4args *args = &argop->nfs_argop4_u.opread; 2598 6741 th199096 READ4res *resp = &resop->nfs_resop4_u.opread; 2599 6741 th199096 int error; 2600 8023 Sam nnode_t *nn = NULL; 2601 6741 th199096 struct iovec iov; 2602 6741 th199096 struct uio uio; 2603 6741 th199096 bool_t *deleg = &cs->deleg; 2604 6741 th199096 nfsstat4 stat; 2605 6741 th199096 mblk_t *mp; 2606 6741 th199096 int alloc_err = 0; 2607 6741 th199096 caller_context_t ct; 2608 8023 Sam uint32_t nnioflags = 0; 2609 6741 th199096 2610 7312 Danhua DTRACE_NFSV4_2(op__read__start, struct compound_state *, cs, 2611 7312 Danhua READ4args, args); 2612 6741 th199096 2613 8023 Sam nn = cs->nn; 2614 8023 Sam if (nn == NULL) { 2615 8023 Sam *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 2616 8023 Sam goto final; 2617 8023 Sam } 2618 8023 Sam if (cs->access == CS_ACCESS_DENIED) { 2619 8023 Sam *cs->statusp = resp->status = NFS4ERR_ACCESS; 2620 8023 Sam goto final; 2621 8023 Sam } 2622 8023 Sam 2623 8023 Sam if ((stat = nnop_check_stateid(nn, cs, FREAD, &args->stateid, 2624 8431 Piyush FALSE, deleg, TRUE, &ct, NULL)) != NFS4_OK) { 2625 6741 th199096 *cs->statusp = resp->status = stat; 2626 8023 Sam goto final; 2627 8023 Sam } 2628 8023 Sam 2629 8023 Sam error = nnop_io_prep(nn, &nnioflags, cs->cr, &ct, args->offset, 2630 8023 Sam args->count, NULL); 2631 8023 Sam if (error != 0) { 2632 8023 Sam *cs->statusp = resp->status = nnode_stat4(error, 1); 2633 8023 Sam goto out; 2634 8023 Sam } 2635 8023 Sam 2636 8023 Sam if (nnioflags & NNODE_IO_FLAG_PAST_EOF) { 2637 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2638 6741 th199096 resp->eof = TRUE; 2639 6741 th199096 resp->data_len = 0; 2640 6741 th199096 resp->data_val = NULL; 2641 6741 th199096 resp->mblk = NULL; 2642 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2643 6741 th199096 goto out; 2644 6741 th199096 } 2645 6741 th199096 2646 6741 th199096 if (args->count == 0) { 2647 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2648 6741 th199096 resp->eof = FALSE; 2649 6741 th199096 resp->data_len = 0; 2650 6741 th199096 resp->data_val = NULL; 2651 6741 th199096 resp->mblk = NULL; 2652 6741 th199096 goto out; 2653 6741 th199096 } 2654 6741 th199096 2655 6741 th199096 /* 2656 6741 th199096 * Do not allocate memory more than maximum allowed 2657 6741 th199096 * transfer size 2658 6741 th199096 */ 2659 6741 th199096 if (args->count > rfs4_tsize(req)) 2660 6741 th199096 args->count = rfs4_tsize(req); 2661 6741 th199096 2662 8023 Sam if (args->wlist) { 2663 8023 Sam mp = NULL; 2664 8023 Sam (void) rdma_get_wchunk(req, &iov, args->wlist); 2665 8023 Sam } else { 2666 8023 Sam /* 2667 8023 Sam * mp will contain the data to be sent out in the read reply. 2668 8023 Sam * It will be freed after the reply has been sent. 2669 8023 Sam * Let's roundup the data to a BYTES_PER_XDR_UNIT multiple, 2670 8023 Sam * so that the call to xdrmblk_putmblk() never fails. 2671 8023 Sam * If the first alloc of the requested size fails, then 2672 8023 Sam * decrease the size to something more reasonable and wait 2673 8023 Sam * for the allocation to occur. 2674 8023 Sam */ 2675 8023 Sam mp = allocb(RNDUP(args->count), BPRI_MED); 2676 8023 Sam if (mp == NULL) { 2677 8023 Sam if (args->count > MAXBSIZE) 2678 8023 Sam args->count = MAXBSIZE; 2679 8023 Sam mp = allocb_wait(RNDUP(args->count), BPRI_MED, 2680 8023 Sam STR_NOSIG, &alloc_err); 2681 8023 Sam } 2682 8023 Sam ASSERT(mp != NULL); 2683 8023 Sam ASSERT(alloc_err == 0); 2684 8023 Sam 2685 8023 Sam iov.iov_base = (caddr_t)mp->b_datap->db_base; 2686 8023 Sam iov.iov_len = args->count; 2687 8023 Sam } 2688 8023 Sam 2689 6741 th199096 uio.uio_iov = &iov; 2690 6741 th199096 uio.uio_iovcnt = 1; 2691 6741 th199096 uio.uio_segflg = UIO_SYSSPACE; 2692 6741 th199096 uio.uio_extflg = UIO_COPY_CACHED; 2693 6741 th199096 uio.uio_loffset = args->offset; 2694 6741 th199096 uio.uio_resid = args->count; 2695 6741 th199096 2696 8023 Sam error = nnop_read(nn, &nnioflags, cs->cr, &ct, &uio, 0); 2697 6741 th199096 if (error) { 2698 8028 Sam if (mp != NULL) 2699 8028 Sam freeb(mp); 2700 8023 Sam *cs->statusp = resp->status = nnode_stat4(error, 1); 2701 6741 th199096 goto out; 2702 6741 th199096 } 2703 6741 th199096 2704 6741 th199096 *cs->statusp = resp->status = NFS4_OK; 2705 6741 th199096 2706 6741 th199096 ASSERT(uio.uio_resid >= 0); 2707 6741 th199096 resp->data_len = args->count - uio.uio_resid; 2708 6741 th199096 resp->data_val = (char *)mp->b_datap->db_base; 2709 6741 th199096 resp->mblk = mp; 2710 6741 th199096 2711 8023 Sam resp->eof = (nnioflags & NNODE_IO_FLAG_EOF) ? TRUE : FALSE; 2712 8023 Sam 2713 8023 Sam out: 2714 8023 Sam nnop_io_release(nn, nnioflags, &ct); 2715 7312 Danhua 2716 7312 Danhua final: 2717 7312 Danhua DTRACE_NFSV4_2(op__read__done, struct compound_state *, cs, 2718 7312 Danhua READ4res *, resp); 2719 6741 th199096 } 2720 6741 th199096 2721 6741 th199096 /*ARGSUSED*/ 2722 6741 th199096 static void 2723 8023 Sam mds_op_read_free(nfs_resop4 *resop, compound_state_t *cs) 2724 6741 th199096 { 2725 6741 th199096 /* Common function for NFSv4.0 and NFSv4.1 */ 2726 6741 th199096 rfs4_op_read_free(resop); 2727 6741 th199096 } 2728 6741 th199096 2729 6741 th199096 /* ARGSUSED */ 2730 6741 th199096 static void 2731 6741 th199096 mds_op_putpubfh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req, 2732 8023 Sam compound_state_t *cs) 2733 6741 th199096 { 2734 6741 th199096 PUTPUBFH4res *resp = &resop->nfs_resop4_u.opputpubfh; 2735 6741 th199096 int error; 2736 6741 th199096 vnode_t *vp; 2737 6741 th199096 struct exportinfo *exi, *sav_exi; 2738 6741 th199096 nfs41_fh_fmt_t *fhp; 2739 6741 th199096 fid_t exp_fid; 2740 7312 Danhua 2741 7312 Danhua DTRACE_NFSV4_1(op__putpubfh__start, struct compound_state *, cs); 2742 6741 th199096 2743 6741 th199096 if (cs->vp) { 2744 6741 th199096 VN_RELE(cs->vp); 2745 6741 th199096 cs->vp = NULL; 2746 6741 th199096 } 2747 6741 th199096 2748 6741 th199096 if (cs->cr) 2749 6741 th199096 crfree(cs->cr); 2750 6741 th199096 2751 6741 th199096 cs->cr = crdup(cs->basecr); 2752 6741 th199096 2753 6741 th199096 vp = exi_public->exi_vp; 2754 6741 th199096 if (vp == NULL) { 2755 6741 th199096 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT; 2756 7312 Danhua goto final; 2757 6741 th199096 } 2758 6741 th199096 2759 6741 th199096 error = mknfs41_fh(&cs->fh, vp, exi_public); 2760 6741 th199096 if (error != 0) { 2761 6741 th199096 *cs->statusp = resp->status = puterrno4(error); 2762 7312 Danhua goto final; 2763 6741 th199096 } 2764 6741 th199096 sav_exi = cs->exi; 2765 6741 th199096 if (exi_public == exi_root) { 2766 6741 th199096 /* 2767 6741 th199096 * No filesystem is actually shared public, so we default 2768 6741 th199096 * to exi_root. In this case, we must check whether root 2769 6741 th199096 * is exported. 2770 6741 th199096 */ 2771 6741 th199096 fhp = (nfs41_fh_fmt_t *)cs->fh.nfs_fh4_val; 2772 6741 th199096 2773 6741 th199096 exp_fid.fid_len = fhp->fh.v1.export_fid.len; 2774 6741 th199096 2775 6741 th199096 bcopy(fhp->fh.v1.export_fid.val, exp_fid.fid_data, 2776 6741 th199096 exp_fid.fid_len); 2777 6741 th199096 2778 6741 th199096 /* 2779 6741 th199096 * if root filesystem is exported, the exportinfo struct that we 2780 6741 th199096 * should use is what checkexport4 returns, because root_exi is 2781 6741 th199096 * actually a mostly empty struct. 2782 6741 th199096 */ 2783 6741 th199096 exi = checkexport4(&fhp->fh.v1.export_fsid, &exp_fid, NULL); 2784 6741 th199096 cs->exi = ((exi != NULL) ? exi : exi_public); 2785 6741 th199096 } else { 2786 6741 th199096 /* 2787 6741 th199096 * it's a properly shared filesystem 2788 6741 th199096 */ 2789 6741 th199096 cs->exi = exi_public; 2790 6741 th199096 } 2791 6741 th199096 2792 6741 th199096 VN_HOLD(vp); 2793 6741 th199096 cs->vp = vp; 2794 6741 th199096 2795 6741 th199096 if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) { 2796 6741 th199096 VN_RELE(cs->vp); 2797 6741 th199096 cs->vp = NULL; 2798 6741 th199096 cs->exi = sav_exi; 2799 7312 Danhua goto final; 2800 7312 Danhua } 2801 7312 Danhua 2802 7312 Danhua *cs->statusp = resp->status = NFS4_OK; 2803 7312 Danhua 2804 7312 Danhua final: 2805 7312 Danhua DTRACE_NFSV4_2(op__putpubfh__done, struct compound_state *, cs, 2806 7312 Danhua PUTPUBFH4res *, resp); 2807 6741 th199096 } 2808 6741 th199096 2809 7739 jwahlig /* 2810 7739 jwahlig * XXX - issue with put*fh operations. 2811 7739 jwahlig * 2812 7739 jwahlig * let us assume that /export/home is shared via NFS and a NFS client 2813 7739 jwahlig * wishes to mount /export/home/joe. 2814 7739 jwahlig * 2815 7739 jwahlig * If /export, home, or joe have restrictive search permissions, then 2816 7739 jwahlig * the NFS Server should not return a filehandle to the client. 2817 7739 jwahlig * 2818 7739 jwahlig * This case is easy to enforce. However, the NFS Client does not know 2819 7739 jwahlig * which security flavor should be used until the pathname has been 2820 7739 jwahlig * fully resolved. In addition there is another complication for uid 2821 7739 jwahlig * mapping. If the credential being used is root, the default behaviour 2822 7739 jwahlig * will be to map it to the anonymous user. However the NFS Server can not 2823 7739 jwahlig * map it until the pathname has been fully resolved. 2824 7739 jwahlig * 2825 7739 jwahlig * XXX: JEFF: Proposed solution. 2826 7739 jwahlig * 2827 7739 jwahlig * Luckily, SECINFO uses a full pathname. So what we will 2828 7739 jwahlig * have to do in mds_op_lookup is check that flavor of 2829 7739 jwahlig * the target object matches that of the request, and if root was the 2830 7739 jwahlig * caller, check for the root= and anon= options, and if necessary, 2831 7739 jwahlig * repeat the lookup using the right cred_t. 2832 7739 jwahlig * 2833 7739 jwahlig * But that's not done yet. 2834 7739 jwahlig */ 2835 6741 th199096 /* ARGSUSED */ 2836 6741 th199096 static void 2837 6741 th199096 mds_op_putfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 2838 8023 Sam compound_state_t *cs) 2839 6741 th199096 { 2840 6741 th199096 PUTFH4args *args = &argop->nfs_argop4_u.opputfh; 2841 6741 th199096 PUTFH4res *resp = &resop->nfs_resop4_u.opputfh; 2842 8023 Sam nfs41_fh_fmt_t *fhp = NULL; 2843 6741 th199096 fid_t exp_fid; 2844 8023 Sam int error; 2845 6741 th199096 2846 7312 Danhua DTRACE_NFSV4_2(op__putfh__start, struct compound_state *, cs, 2847 7312 Danhua PUTFH4args *, args); 2848 7312 Danhua 2849 6741 th199096 /* 2850 8023 Sam * release the old nnode, vnode and cred. 2851 8023 Sam */ 2852 8023 Sam if (cs->nn) 2853 8023 Sam nnode_rele(&cs->nn); 2854 6741 th199096 if (cs->vp) { 2855 6741 th199096 VN_RELE(cs->vp); 2856 6741 th199096 cs->vp = NULL; 2857 6741 th199096 } 2858 6741 th199096 if (cs->cr) { 2859 6741 th199096 crfree(cs->cr); 2860 6741 th199096 cs->cr = NULL; 2861 6741 th199096 } 2862 6741 th199096 2863 6741 th199096 2864 6741 th199096 /* 2865 8424 lisa * Check exportinfo only if it's a FH41_TYPE_NFS filehandle. 2866 8023 Sam * If the filehandle is otherwise incorrect, 2867 8023 Sam * nnode_from_fh_v41() will return an error. 2868 8023 Sam */ 2869 8424 lisa fhp = (nfs41_fh_fmt_t *)args->object.nfs_fh4_val; 2870 8424 lisa if (fhp->type == FH41_TYPE_NFS) { 2871 8023 Sam