nfs4_srv.c revision 2f172c55ef76964744bc62b4500ece87f3089b4d
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER START
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The contents of this file are subject to the terms of the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Common Development and Distribution License (the "License").
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You may not use this file except in compliance with the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * See the License for the specific language governing permissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and limitations under the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * When distributing Covered Code, include this CDDL HEADER in each
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If applicable, add the following below this CDDL HEADER, with the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fields enclosed by brackets "[]" replaced with your own identifying
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * information: Portions Copyright [yyyy] [name of copyright owner]
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER END
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Use is subject to license terms.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * All Rights Reserved
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define RFS4_MAXLOCK_TRIES 4 /* Try to get the lock this many times */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int rdma_setup_read_data4(READ4args *, READ4res *);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Used to bump the stateid4.seqid value and show changes in the stateid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This is used to return NFS4ERR_TOOSMALL when clients specify
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * maxcount that isn't large enough to hold the smallest possible
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * XDR encoded dirent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof cookie (8 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof name_len (4 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof smallest (padded) name (4 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof bitmap4_len (12 bytes) + NOTE: we always encode len=2 bm4
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof attrlist4_len (4 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof next boolean (4 bytes)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the smallest possible entry4 (assumes no attrs requested).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof nfsstat4 (4 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof verifier4 (8 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof entry4list bool (4 bytes) +
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * sizeof entry4 (36 bytes) +
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sizeof eof bool (4 bytes)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * VOP_READDIR. Its value is the size of the maximum possible dirent
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * for solaris. The DIRENT64_RECLEN macro returns the size of dirent
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * required for a given name length. MAXNAMELEN is the maximum
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * filename length allowed in Solaris. The first two DIRENT64_RECLEN()
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * macros are to allow for . and .. entries -- just a minor tweak to try
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and guarantee that buffer we give to VOP_READDIR will be large enough
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to hold ., .., and the largest possible solaris dirent64.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN))
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * It would be better to pad to 4 bytes since that's what XDR would do,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * but the dirents UFS gives us are already padded to 8, so just take
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * what we're given. Dircount is only a hint anyway. Currently the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * solaris kernel is ASCII only, so there's no point in calling the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * UTF8 functions.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * dirent64: named padded to provide 8 byte struct alignment
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * d_ino(8) + d_off(8) + d_reclen(2) + d_name(namelen + null(1) + pad)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * cookie: uint64_t + utf8namelen: uint_t + utf8name padded to 8 bytes
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppotime_t rfs4_start_time; /* Initialized in rfs4_srvrinit */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic sysid_t lockt_sysid; /* dummy sysid for all LOCKT calls */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanvoid rfs4_init_compound_state(struct compound_state *);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_inval(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_access(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_close(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_commit(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void rfs4_op_create(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void rfs4_op_delegreturn(nfs_argop4 *, nfs_resop4 *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_delegpurge(nfs_argop4 *, nfs_resop4 *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_getattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanstatic void rfs4_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void rfs4_op_illegal(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_locku(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_lockt(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_lookup(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_lookupp(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_open(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_open_confirm(nfs_argop4 *, nfs_resop4 *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_open_downgrade(nfs_argop4 *, nfs_resop4 *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_putfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_putpubfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_putrootfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_read(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_readlink(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_release_lockowner(nfs_argop4 *, nfs_resop4 *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_remove(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_rename(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_renew(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_restorefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_savefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_setattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_verify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_write(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_setclientid(nfs_argop4 *, nfs_resop4 *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void rfs4_op_setclientid_confirm(nfs_argop4 *, nfs_resop4 *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void rfs4_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepponfsstat4 rfs4_client_sysid(rfs4_client_t *, sysid_t *);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * translation table for attrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic nfsstat4 do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct compound_state *cs, struct nfs4_svgetit_arg *sargp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_servinst_t *rfs4_cur_servinst = NULL; /* current server instance */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppokmutex_t rfs4_servinst_lock; /* protects linked list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint rfs4_seen_first_compound; /* set first time we see one */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * NFS4 op dispatch table
8e6a2a040587479821d1e682a28bcef7e75f19a6lm void (*dis_resfree)(); /* frees space allocated by proc */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * NFS VERSION 4
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* RFS_NULL = 0 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* UNUSED = 1 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* UNUSED = 2 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_ACCESS = 3 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_CLOSE = 4 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_COMMIT = 5 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_CREATE = 6 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_DELEGPURGE = 7 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_DELEGRETURN = 8 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_GETATTR = 9 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {rfs4_op_getattr, rfs4_op_getattr_free, RPC_IDEMPOTENT},
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_GETFH = 10 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_LINK = 11 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_LOCK = 12 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_LOCKT = 13 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_LOCKU = 14 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_LOOKUP = 15 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb {rfs4_op_lookup, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_LOOKUPP = 16 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb {rfs4_op_lookupp, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_NVERIFY = 17 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_OPEN = 18 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_OPENATTR = 19 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_OPEN_CONFIRM = 20 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_OPEN_DOWNGRADE = 21 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_OPEN_PUTFH = 22 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_PUTPUBFH = 23 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_PUTROOTFH = 24 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_READ = 25 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_READDIR = 26 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {rfs4_op_readdir, rfs4_op_readdir_free, RPC_IDEMPOTENT},
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_READLINK = 27 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {rfs4_op_readlink, rfs4_op_readlink_free, RPC_IDEMPOTENT},
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_REMOVE = 28 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_RENAME = 29 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_RENEW = 30 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_RESTOREFH = 31 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_SAVEFH = 32 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_SECINFO = 33 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_SETATTR = 34 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* OP_SETCLIENTID = 35 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_SETCLIENTID_CONFIRM = 36 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* OP_VERIFY = 37 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_WRITE = 38 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* OP_RELEASE_LOCKOWNER = 39 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic uint_t rfsv4disp_cnt = sizeof (rfsv4disptab) / sizeof (rfsv4disptab[0]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char *rfs4_op_string[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_null",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_1 unused",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_2 unused",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_access",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_close",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_commit",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_create",
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb "rfs4_op_delegpurge",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_delegreturn",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_getattr",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_getfh",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_link",
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb "rfs4_op_lock",
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb "rfs4_op_lockt",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_locku",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "rfs4_op_lookup",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_lookupp",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_nverify",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_open",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_openattr",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_open_confirm",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_open_downgrade",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_putfh",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "rfs4_op_putpubfh",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_putrootfh",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_read",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_readdir",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "rfs4_op_readlink",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_remove",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "rfs4_op_rename",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "rfs4_op_renew",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "rfs4_op_restorefh",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_savefh",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "rfs4_op_secinfo",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_setattr",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_setclientid",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_setclient_confirm",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_verify",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_write",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_release_lockowner",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "rfs4_op_illegal"
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanextern size_t strlcpy(char *dst, const char *src, size_t dstsize);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanextern void rfs4_free_fs_locations4(fs_locations4 *);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanstatic const fs_operation_def_t nfs4_rd_deleg_tmpl[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VOPNAME_SETATTR, { .femop_setattr = deleg_rd_setattr },
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb VOPNAME_SETSECATTR, { .femop_setsecattr = deleg_rd_setsecattr },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic const fs_operation_def_t nfs4_wr_deleg_tmpl[] = {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram VOPNAME_SETATTR, { .femop_setattr = deleg_wr_setattr },
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan VOPNAME_RWLOCK, { .femop_rwlock = deleg_wr_rwlock },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VOPNAME_SETSECATTR, { .femop_setsecattr = deleg_wr_setsecattr },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VOPNAME_VNEVENT, { .femop_vnevent = deleg_wr_vnevent },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo extern void rfs4_attr_init();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The following algorithm attempts to find a unique verifier
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * to be used as the write verifier returned from the server
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to the client. It is important that this verifier change
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * whenever the server reboots. Of secondary importance, it
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is important for the verifier to be unique between two
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * different servers.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Thus, an attempt is made to use the system hostid and the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * current time in seconds when the nfssrv kernel module is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * loaded. It is assumed that an NFS server will not be able
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to boot and then to reboot in less than a second. If the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * hostid has not been set, then the current high resolution
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * time is used. This will ensure different verifiers each
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * time the server reboots and minimize the chances that two
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * different servers will have the same verifier.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * XXX - this is broken on LP64 kernels.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&rfs4_deleg_lock, NULL, MUTEX_DEFAULT, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Used to manage create/destroy of server state */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&rfs4_state_lock, NULL, MUTEX_DEFAULT, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Used to manage access to server instance linked list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&rfs4_servinst_lock, NULL, MUTEX_DEFAULT, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Used to manage access to rfs4_deleg_policy */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rw_init(&rfs4_deleg_policy_lock, NULL, RW_DEFAULT, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = fem_create("deleg_rdops", nfs4_rd_deleg_tmpl, &deleg_rdops);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (0);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram sip->start_time = (time_t)TICK_TO_SEC(ddi_get_lbolt());
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * returns true if the instance's grace period has never been started
8e6a2a040587479821d1e682a28bcef7e75f19a6lm return (start_time == 0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Indicates if server instance is within the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * grace period.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram grace_expiry = sip->start_time + sip->grace_period;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (((time_t)TICK_TO_SEC(ddi_get_lbolt())) < grace_expiry);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rfs4_servinst_in_grace(cp->rc_server_instance));
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * reset all currently active grace periods
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * start any new instances' grace periods
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
8e6a2a040587479821d1e682a28bcef7e75f19a6lmrfs4_dss_newpath(rfs4_servinst_t *sip, char *path, unsigned index)
8e6a2a040587479821d1e682a28bcef7e75f19a6lm dss_path = kmem_alloc(sizeof (rfs4_dss_path_t), KM_SLEEP);
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * Take a copy of the string, since the original may be overwritten.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Sadly, no strdup() in the kernel.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* allow for NUL */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* associate with servinst */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Add to list of served paths.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * No locking required, as we're only ever called at startup.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* this is the first dss_path_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* needed for insque/remque */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Create a new server instance, and make it the currently active instance.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Note that starting the grace period too early will reduce the clients'
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * recovery window.
b4d0458e18abef7b5e036915e96807c219ec1d58raghuramrfs4_servinst_create(int start_grace, int dss_npaths, char **dss_paths)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram unsigned i;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram sip = kmem_alloc(sizeof (rfs4_servinst_t), KM_SLEEP);
3af08d828975d7e2581b6829e0eecff14d87a483lm * This initial dummy entry is required to setup for insque/remque.
3af08d828975d7e2581b6829e0eecff14d87a483lm * It must be skipped over whenever the list is traversed.
3af08d828975d7e2581b6829e0eecff14d87a483lm oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
3af08d828975d7e2581b6829e0eecff14d87a483lm /* insque/remque require initial list entry to be self-terminated */
3af08d828975d7e2581b6829e0eecff14d87a483lm for (i = 0; i < dss_npaths; i++) {
3af08d828975d7e2581b6829e0eecff14d87a483lm sip->dss_paths[i] = rfs4_dss_newpath(sip, dss_paths[i], i);
3af08d828975d7e2581b6829e0eecff14d87a483lm /* add to linked list */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* make the new instance "current" */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * In future, we might add a rfs4_servinst_destroy(sip) but, for now, destroy
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * all instances directly.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Assign the current server instance to a client_t.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Should be called with cp->rc_dbe held.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_servinst_assign(rfs4_client_t *cp, rfs4_servinst_t *sip)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The lock ensures that if the current instance is in the process
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * of changing, we will see the new one.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This is a fall-through for invalid or not implemented (yet) ops
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_inval(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_INVAL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if the security flavor, nfsnum, is in the flavor_list.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoin_flavor_list(int nfsnum, int *flavor_list, int count)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < count; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Used by rfs4_op_secinfo to get the security information from the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * export structure associated with the component.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppodo_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * If dotdotting, then need to check whether it's above the
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * root of a filesystem, or above an export point.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If dotdotting at the root of a filesystem, then
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * need to traverse back to the mounted-on filesystem
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and do the dotdot lookup there.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If at the system root, then can
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * go up no further.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Traverse back to the mounted-on filesystem
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Set the different_export flag so we remember
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to pick up a new exportinfo entry for
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * this new filesystem.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If dotdotting above an export point then set
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * the different_export to get new export info.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get the vnode for the component "nm".
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If the vnode is in a pseudo filesystem, or if the security flavor
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * used in the request is valid but not an explicitly shared flavor,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * or the access bit indicates that this is a limited access,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * check whether this vnode is visible.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If it's a mountpoint, then traverse it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* remember that we had to traverse mountpoint */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If vp isn't a mountpoint and the vfs ptrs aren't the same,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * then vp is probably an LOFS object. We don't need the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * realvp, we just need to know that we might have crossed
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * a server fs boundary and need to call checkexport4.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * (LOFS lookup hides server fs mountpoints, and actually calls
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * traverse)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get the export information for it.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If this vnode is a mounted-on vnode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * but the mounted-on file system is not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * exported, send back the secinfo for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the exported node that the mounted-on
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vnode lives in.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Create the secinfo result based on the security information
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * from the exportinfo structure (exi).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Return all flavors for a pseudo node.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * For a real export node, return the flavor that the client
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * has access with.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo count = exi->exi_export.ex_seccnt; /* total sec count */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < count; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get oid opaque data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ret_cnt = 0, k = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo count = exi->exi_export.ex_seccnt; /* total sec count */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo flavor_list = kmem_alloc(count * sizeof (int), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* find out which flavors to return */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < count; i ++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Create the returning SECINFO value */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resok_val = kmem_alloc(ret_cnt * sizeof (secinfo4), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < count; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If the flavor is in the flavor list,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fill in resok_val.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get oid opaque data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * SECINFO (Operation 33): Obtain required security information on
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the component name in the format of (security-mechanism-oid, qop, service)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * triplets.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__secinfo__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Current file handle (cfh) should have been set before getting
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * into this function. If not, return error.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Verify the component name. If failed, error out, but
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * do not error out if the component name is a "..".
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * SECINFO will return its parents secinfo data for SECINFO "..".
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* If necessary, convert to UTF-8 for illbehaved clients */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *cs->statusp = resp->status = do_rfs4_op_secinfo(cs, name, resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__secinfo__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Free SECINFO result.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* If this is not an Ok result, nothing to free. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < count; i++) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__access__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0 /* XXX allow access even if !cs->access. Eventually only pseudo fs */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If the file system is exported read only, it is not appropriate
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to check write permissions for regular files and directories.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Special files are interpreted by the client, so the underlying
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * permissions are sent back to the client for interpretation.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We need the mode so that we can correctly determine access
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk * permissions relative to a mandatory lock file. Access to
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk * mandatory lock files is denied on the server, so it might
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * as well be reflected to the server during the open.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "got client label from request(1)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char *, "got server label(1) for vp(2)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!error && (!is_system_labeled() || admin_low_client ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!error && (!is_system_labeled() || admin_low_client ||
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__access__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_commit(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__commit__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If we can't get the attributes, then we can't do the
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk * right access checking. So, we'll fail the request.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_PUTPAGE(vp, args->offset, args->count, 0, cr, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__commit__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * rfs4_op_mknod is called from rfs4_op_create after all initial verification
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * was completed. It does the nfsv4 create for special files.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppodo_rfs4_op_mknod(CREATE4args *args, CREATE4res *resp, struct svc_req *req,
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk vap->va_rdev = makedevice(args->ftype4_u.devdata.specdata1,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Must specify the mode.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_CREATE(dvp, nm, vap, excl, mode, &vp, cr, 0, NULL, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * nfsv4 create is used to create non-regular files. For regular files,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * use nfsv4 open.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__create__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If there is an unshared filesystem mounted on this vnode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * do not allow to create an object in this directory.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Verify that type is correct */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Name of newly created object
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* If necessary, convert to UTF-8 for poorly behaved clients */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram &args->createattrs, cs, &sarg, &ntov, NFS4ATTR_SETIT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Get "before" change value */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bva.va_ctime)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Set default initial values for attributes when not specified
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * in createattrs.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_MKDIR(dvp, nm, vap, &vp, cr, NULL, 0, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Get the initial "after" sequence number, if it fails,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * set to zero
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * symlink names must be treated as data
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram lnm = utf8_to_str(&args->ftype4_u.linkdata, &llen, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get the initial "after" sequence number, if it fails,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * set to zero
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * va_seq is not safe over VOP calls, check it again
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * if it has changed zero out iva to force atomic = FALSE.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * probably a special file.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * We know this will only generate one VOP call
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get the initial "after" sequence number, if it fails,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * set to zero
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Force modified data and metadata out to stable storage.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Finish setup of cinfo response, "before" value already set.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get "after" change value, if it fails, simply return the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * before value.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, ava.va_ctime);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * True verification that object was created with correct
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * attrs is impossible. The attrs could have been changed
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * immediately after object creation. If attributes did
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * not verify, the only recourse for the server is to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * destroy the object. Maybe if some attrs (like gid)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * are set incorrectly, the object should be destroyed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * however, seems bad as a default policy. Do we really
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * want to destroy an object over one of the times not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * verifying correctly? For these reasons, the server
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * currently sets bits in attrset for createattrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * that were set; however, no verification is done.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vmask_to_nmask accounts for vattr bits set on create
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * [do_rfs4_set_attrs() only sets resp bits for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Mask off any bits set by default so as not to return
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * more attrset bits than were requested in createattrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nfs4_vmask_to_nmask(sarg.vap->va_mask, &resp->attrset);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The cinfo.atomic = TRUE only if we got no errors, we have
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * non-zero va_seq's, and it has incremented by exactly one
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * during the creation and it didn't change during the VOP_LOOKUP
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * or VOP_FSYNC.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!error && bva.va_seq && iva.va_seq && ava.va_seq &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo iva.va_seq == (bva.va_seq + 1) && iva.va_seq == ava.va_seq)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Force modified metadata out to stable storage.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * if a underlying vp exists, pass it to VOP_FSYNC
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__create__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*ARGSUSED*/
8e6a2a040587479821d1e682a28bcef7e75f19a6lmrfs4_op_delegpurge(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__delegpurge__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DELEGPURGE4args *, &argop->nfs_argop4_u.opdelegpurge);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__delegpurge__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*ARGSUSED*/
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_delegreturn(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DELEGRETURN4args *args = &argop->nfs_argop4_u.opdelegreturn;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DELEGRETURN4res *resp = &resop->nfs_resop4_u.opdelegreturn;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__delegreturn__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = rfs4_get_deleg_state(&args->deleg_stateid, &dsp);
7636cb21f250f0485ca6052ffadc80ace93e6358lm /* Ensure specified filehandle matches */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__delegreturn__done, struct compound_state *, cs,
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * Check to see if a given "flavor" is an explicitly shared flavor.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The assumption of this routine is the "flavor" is already a valid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * flavor in the secinfo list of "exi".
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * # share -o sec=flavor1 /export
3af08d828975d7e2581b6829e0eecff14d87a483lm * # share -o sec=flavor2 /export/home
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * flavor2 is not an explicitly shared flavor for /export,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * however it is in the secinfo list for /export thru the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * server namespace setup.
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Should not reach this point based on the assumption */
3af08d828975d7e2581b6829e0eecff14d87a483lm return (0);
3af08d828975d7e2581b6829e0eecff14d87a483lm * Check if the security flavor used in the request matches what is
3af08d828975d7e2581b6829e0eecff14d87a483lm * required at the export point or at the root pseudo node (exi_root).
3af08d828975d7e2581b6829e0eecff14d87a483lm * returns 1 if there's a match or if exported with AUTH_NONE; 0 otherwise.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Check cs->nfsflavor (from the request) against
3af08d828975d7e2581b6829e0eecff14d87a483lm * the current export data in cs->exi.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (1);
7636cb21f250f0485ca6052ffadc80ace93e6358lm return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check the access authority for the client and return the correct error.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppocall_checkauth4(struct compound_state *cs, struct svc_req *req)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * First, check if the security flavor used in the request
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * are among the flavors set in the server namespace.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (authres == 0) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * bitmap4_to_attrmask is called by getattr and readdir.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * It sets up the vattr mask and determines whether vfsstat call is needed
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * based on the input bitmap.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Returns nfsv4 status.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayanbitmap4_to_attrmask(bitmap4 breq, struct nfs4_svgetit_arg *sargp)
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Set rdattr_error_req to true if return error per
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * failed entry rather than fail the readdir.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * generate the va_mask
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle the easy cases first
8e6a2a040587479821d1e682a28bcef7e75f19a6lm for (i = 0; i < nfs4_ntov_map_size; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check is vfsstat is needed
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* NOTREACHED */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * bitmap4_get_sysattrs is called by getattr and readdir.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * It calls both VOP_GETATTR and VFS_STATVFS calls to get the attrs.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * Returns nfsv4 status.
8e6a2a040587479821d1e682a28bcef7e75f19a6lmstatic void
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ntovp->na = kmem_zalloc(sizeof (union nfs4_attr_u) * nfs4_ntov_map_size,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * XXX Should do the same checks for whether the bit is set
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((sargp->op == NFS4ATTR_SETIT) || (sargp->op == NFS4ATTR_VERIT)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * xdr_free for getattr will be done later
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ntovp->na, sizeof (union nfs4_attr_u) * nfs4_ntov_map_size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * do_rfs4_op_getattr gets the system attrs and converts into fattr4.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* if no bits requested, then return empty fattr4 */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (breq == 0) {
7636cb21f250f0485ca6052ffadc80ace93e6358lm * return NFS4ERR_INVAL when client requests write-only attrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (breq & (FATTR4_TIME_ACCESS_SET_MASK | FATTR4_TIME_MODIFY_SET_MASK))
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Now loop to get or verify the attrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < nfs4_ntov_map_size; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Possible error values:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * >0 if sv_getit failed to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * get the attr; 0 if succeeded;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * <0 if rdattr_error and the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * attribute cannot be returned.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If error then just for entry
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error == 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan } else if ((error > 0) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If rdattr_error was set after the return value for it was assigned,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * update it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo xdr_size += xdr_sizeof(nfs4_ntov_map[*amap].xfunc, na);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* freed by rfs4_op_getattr_free() */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo fattrp->attrlist4 = xdr_attrs = kmem_zalloc(xdr_size, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_getattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__getattr__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = bitmap4_to_attrmask(args->attr_request, &sarg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Is this a referral? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Older V4 Solaris client sees a link */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__getattr__done, struct compound_state *, cs,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb/* ARGSUSED */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebrfs4_op_getfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb DTRACE_NFSV4_1(op__getfh__start, struct compound_state *, cs);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* check for reparse point at the share point */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if (cs->exi->exi_moved || vn_is_nfs_reparse(cs->exi->exi_vp, cs->cr)) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* it's all bad */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* check for reparse point at vp */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if (vn_is_nfs_reparse(cs->vp, cs->cr) && !client_is_downrev(req)) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* it's not all bad */
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_2(op__getfh__done, struct compound_state *, cs,
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
3af08d828975d7e2581b6829e0eecff14d87a483lm kmem_free(resp->object.nfs_fh4_val, resp->object.nfs_fh4_len);
3af08d828975d7e2581b6829e0eecff14d87a483lm * illegal: args: void
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * res : status (NFS4ERR_OP_ILLEGAL)
3af08d828975d7e2581b6829e0eecff14d87a483lm/* ARGSUSED */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
3af08d828975d7e2581b6829e0eecff14d87a483lm * link: args: SAVED_FH: file, CURRENT_FH: target directory
3af08d828975d7e2581b6829e0eecff14d87a483lm * res: status. If success - CURRENT_FH unchanged, return change_info
3af08d828975d7e2581b6829e0eecff14d87a483lm/* ARGSUSED */
3af08d828975d7e2581b6829e0eecff14d87a483lmrfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_2(op__link__start, struct compound_state *, cs,
3af08d828975d7e2581b6829e0eecff14d87a483lm /* SAVED_FH: source object */
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3af08d828975d7e2581b6829e0eecff14d87a483lm /* CURRENT_FH: target directory */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3af08d828975d7e2581b6829e0eecff14d87a483lm * If there is a non-shared filesystem mounted on this vnode,
3af08d828975d7e2581b6829e0eecff14d87a483lm * do not allow to link any file in this directory.
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Check source object's type validity */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Check target directory's type */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Get "before" change value */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
3af08d828975d7e2581b6829e0eecff14d87a483lm NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Get the initial "after" sequence number, if it fails, set to zero
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Force modified data and metadata out to stable storage.
3af08d828975d7e2581b6829e0eecff14d87a483lm * Get "after" change value, if it fails, simply return the
3af08d828975d7e2581b6829e0eecff14d87a483lm * before value.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * The cinfo.atomic = TRUE only if we have
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * non-zero va_seq's, and it has incremented by exactly one
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * during the VOP_LINK and it didn't change during the VOP_FSYNC.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__link__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Used by rfs4_op_lookup and rfs4_op_lookupp to do the actual work.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramdo_rfs4_op_lookup(char *nm, uint_t buflen, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If dotdotting, then need to check whether it's
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * above the root of a filesystem, or above an
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * export point.
3af08d828975d7e2581b6829e0eecff14d87a483lm * If dotdotting at the root of a filesystem, then
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * need to traverse back to the mounted-on filesystem
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and do the dotdot lookup there.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If at the system root, then can
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * go up no further.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Traverse back to the mounted-on filesystem
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Set the different_export flag so we remember
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to pick up a new exportinfo entry for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * this new filesystem.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If dotdotting above an export point then set
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the different_export to get new export info.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_LOOKUP(cs->vp, nm, &vp, NULL, 0, NULL, cs->cr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If the vnode is in a pseudo filesystem, check whether it is visible.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * XXX if the vnode is a symlink and it is not visible in
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * a pseudo filesystem, return ENOENT (not following symlink).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * V4 client can not mount such symlink. This is a regression
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * In the same exported filesystem, if the security flavor used
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is not an explicitly shared flavor, limit the view to the visible
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * list entries only. This is not a WRONGSEC case because it's already
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * checked via PUTROOTFH/PUTPUBFH or PUTFH.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (! nfs_visible(cs->exi, vp, &different_export)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If it's a mountpoint, then traverse it.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram pre_exi = cs->exi; /* save pre-traversed exportinfo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * hold pre_tvp to counteract rele by traverse. We will
3af08d828975d7e2581b6829e0eecff14d87a483lm * need pre_tvp below if checkexport4 fails
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * The vfsp comparison is to handle the case where
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * a LOFS mount is shared. lo_lookup traverses mount points,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * and NFS is unaware of local fs transistions because
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * v_vfsmountedhere isn't set. For this special LOFS case,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * the dir and the obj returned by lookup will have different
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * vfs ptrs.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If this vnode is a mounted-on vnode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * but the mounted-on file system is not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * exported, send back the filehandle for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the mounted-on vnode, not the root of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the mounted-on file system.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (pre_tvp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* we're done with pre_tvp now. release extra hold */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Now we do a checkauth4. The reason is that
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * this client/user may not have access to the new
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * exported file system, and if he does,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * the client/user may be mapped to a different uid.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We start with a new cr, because the checkauth4 done
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in the PUT*FH operation over wrote the cred's uid,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * gid, etc, and we want the real thing before calling
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * checkauth4()
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * After various NFS checks, do a label check on the path
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * component. The label on this path should either be the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * global zone's label or a zone's label. We are only
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * interested in the zone's label because exported files
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in global zone is accessible (though read-only) to
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * clients. The exportability/visibility check is already
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * done before reaching this code.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "got client label from request(1)", struct svc_req *, req);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We grant access to admin_low label clients
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * only if the client is trusted, i.e. also
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * running Solaris Trusted Extension.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (oldvp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * if did lookup on attrdir and didn't lookup .., set named
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * attr fh flag
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Assume false for now, open proc will set this */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__lookup__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* If necessary, convert to UTF-8 for illbehaved clients */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *cs->statusp = resp->status = do_rfs4_op_lookup(name, len, req, cs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__lookup__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_lookupp(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_1(op__lookupp__start, struct compound_state *, cs);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram *cs->statusp = resp->status = do_rfs4_op_lookup("..", 3, req, cs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * From NFSV4 Specification, LOOKUPP should not check for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * NFS4ERR_WRONGSEC. Retrun NFS4_OK instead.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__lookupp__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*ARGSUSED2*/
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo OPENATTR4args *args = &argop->nfs_argop4_u.opopenattr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__openattr__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo !vfs_has_feature(cs->vp->v_vfsp, VFSFT_SYSATTR_VIEWS)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If file system supports passing ACE mask to VOP_ACCESS then
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * check for ACE_READ_NAMED_ATTRS, otherwise do legacy checks
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vfs_has_feature(cs->vp->v_vfsp, VFSFT_ACEMASKONACCESS))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = ((VOP_ACCESS(cs->vp, VREAD, 0, cs->cr, NULL) != 0) &&
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan (VOP_ACCESS(cs->vp, VWRITE, 0, cs->cr, NULL) != 0) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The CREATE_XATTR_DIR VOP flag cannot be specified if
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the file system is exported read-only -- regardless of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * createdir flag. Otherwise the attrdir would be created
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * (assuming server fs isn't mounted readonly locally). If
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * VOP_LOOKUP returns ENOENT in this case, the error will
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * be translated into EROFS. ENOSYS is mapped to ENOTSUP
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * because specfs has no VOP_LOOKUP op, so the macro would
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * return ENOSYS. EINVAL is returned by all (current)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Solaris file system implementations when any of their
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * restrictions are violated (xattr(dir) can't have xattrdir).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Returning NOTSUPP is more appropriate in this case
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * because the object will never be able to have an attrdir.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (args->createdir && ! (exp_ro = rdonly4(cs->exi, cs->vp, req)))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_LOOKUP(cs->vp, "", &avp, NULL, lookup_flags, NULL, cs->cr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * There is no requirement for an attrdir fh flag
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * because the attrdir has a vnode flag to distinguish
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it from regular (non-xattr) directories. The
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * FH4_ATTRDIR flag is set for future sanity checks.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__openattr__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramdo_io(int direction, vnode_t *vp, struct uio *uio, int ioflag, cred_t *cred,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Don't block on mandatory locks. If this routine returns
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * EAGAIN, the caller should return NFS4ERR_LOCKED.
3af08d828975d7e2581b6829e0eecff14d87a483lm for (i = 0; i < rfs4_maxlock_tries; i++) {
3af08d828975d7e2581b6829e0eecff14d87a483lm/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_read(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__read__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
3af08d828975d7e2581b6829e0eecff14d87a483lm * Enter the critical region before calling VOP_RWLOCK
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * to avoid a deadlock with write requests.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If we can't get the attributes, then we can't do the
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * right access checking. So, we'll fail the request.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ((vp->v_type == VDIR) ? NFS4ERR_ISDIR : NFS4ERR_INVAL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (MANDLOCK(vp, va.va_mode)) { /* XXX - V4 supports mand locking */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* RDMA */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* RDMA */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Do not allocate memory more than maximum allowed
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * transfer size
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If returning data via RDMA Write, then grab the chunk list. If we
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * aren't returning READ data w/RDMA_WRITE, then grab a mblk.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * mp will contain the data to be sent out in the read reply.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * It will be freed after the reply has been sent. Let's
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * roundup the data to a BYTES_PER_XDR_UNIT multiple, so that
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the call to xdrmblk_putmblk() never fails. If the first
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * alloc of the requested size fails, then decrease the size to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * something more reasonable and wait for the allocation to
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_2(op__read__done, struct compound_state *, cs,
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_putpubfh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram PUTPUBFH4res *resp = &resop->nfs_resop4_u.opputpubfh;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_1(op__putpubfh__start, struct compound_state *, cs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * No filesystem is actually shared public, so we default
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to exi_root. In this case, we must check whether root
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is exported.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * if root filesystem is exported, the exportinfo struct that we
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * should use is what checkexport4 returns, because root_exi is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * actually a mostly empty struct.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it's a properly shared filesystem
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_PROBE2(tx__rfs4__log__info__opputpubfh__clabel, char *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "got client label from request(1)",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__putpubfh__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * XXX - issue with put*fh operations. Suppose /export/home is exported.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Suppose an NFS client goes to mount /export/home/joe. If /export, home,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * or joe have restrictive search permissions, then we shouldn't let
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the client get a file handle. This is easy to enforce. However, we
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * don't know what security flavor should be used until we resolve the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * path name. Another complication is uid mapping. If root is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the user, then it will be mapped to the anonymous user by default,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * but we won't know that till we've resolved the path name. And we won't
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * know what the anonymous user is.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Luckily, SECINFO is specified to take a full filename.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * So what we will have to in rfs4_op_lookup is check that flavor of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the target object matches that of the request, and if root was the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * caller, check for the root= and anon= options, and if necessary,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * repeat the lookup using the right cred_t. But that's not done yet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_putfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__putfh__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cs->exi = checkexport4(&fh_fmtp->fh4_fsid, (fid_t *)&fh_fmtp->fh4_xlen,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (! (cs->vp = nfs4_fhtovp(&args->object, cs->exi, &resp->status))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__putfh__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_putrootfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo PUTROOTFH4res *resp = &resop->nfs_resop4_u.opputrootfh;
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_1(op__putrootfh__start, struct compound_state *, cs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Using rootdir, the system root vnode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * get its fid.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Then use the root fsid & fid it to find out if it's exported
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If the server root isn't exported directly, then
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it should at least be a pseudo export based on
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * one or more exports further down in the server's
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * file tree.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo exi = checkexport4(&rootdir->v_vfsp->vfs_fsid, &fid, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (exi == NULL || exi->exi_export.ex_flags & EX_PUBLIC) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (CE_WARN, "rfs4_op_putrootfh: export check failure"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Now make a filehandle based on the root
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * export and root vnode.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DTRACE_NFSV4_2(op__putrootfh__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * A directory entry is a valid nfsv4 entry if
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * - it has a non-zero ino
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * - it is not a dot or dotdot name
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * - it is visible in a pseudo export or in a real export that can
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * only have a limited view.
3af08d828975d7e2581b6829e0eecff14d87a483lmvalid_nfs4_entry(struct exportinfo *exi, struct dirent64 *dp,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram return (nfs_visible_inode(exi, dp->d_ino, expseudo));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * set_rdattr_params sets up the variables used to manage what information
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to get for each directory entry.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * could not even figure attr mask
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * dirent's d_ino is always correct value for mounted_on_fileid.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * mntdfid_set is set once here, but mounted_on_fileid is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * set in main dirent processing loop for each dirent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The mntdfid_set is a simple optimization that lets the
3af08d828975d7e2581b6829e0eecff14d87a483lm * server attr code avoid work when caller is readdir.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Lookup entry only if client asked for any of the following:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * a) vattr attrs
3af08d828975d7e2581b6829e0eecff14d87a483lm * b) vfs attrs
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * c) attrs w/per-object scope requested (change, filehandle, etc)
3af08d828975d7e2581b6829e0eecff14d87a483lm * other than mounted_on_fileid (which we can take from dirent)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (va_mask || sargp->sbp || (objbits & ~FATTR4_MOUNTED_ON_FILEID_MASK))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If filesystem attrs are requested, get them now from the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * directory vp, as most entries will have same filesystem. The only
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * exception are mounted over entries but we handle
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * those as we go (XXX mounted over detection not yet implemented).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Failed to get filesystem attributes.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Return a rdattr_error for each entry, but don't fail.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * However, don't get any obj-dependent attrs.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * At least get fileid for regular readdir output
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * readlink: args: CURRENT_FH.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * res: status. If success - CURRENT_FH unchanged, return linktext.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_readlink(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_1(op__readlink__start, struct compound_state *, cs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* CURRENT_FH: directory */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Is it a referral? */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (vn_is_nfs_reparse(vp, cs->cr) && client_is_downrev(req)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Get an artificial symlink based on a referral */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo name = nfscmd_convname(ca, cs->exi, data, NFSCMD_CONV_OUTBOUND,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Even though the conversion failed, we return
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * something. We just don't translate it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * treat link name as data
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__readlink__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * release_lockowner:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Release any state associated with the supplied
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * lockowner. Note if any lo_state is holding locks we will not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * rele that lo_state and thus the lockowner will not be destroyed.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * A client using lock after the lock owner stateid has been released
3af08d828975d7e2581b6829e0eecff14d87a483lm * will suffer the consequence of NFS4ERR_BAD_STATEID and would have
3af08d828975d7e2581b6829e0eecff14d87a483lm * to reissue the lock with new_lock_owner set to TRUE.
3af08d828975d7e2581b6829e0eecff14d87a483lm * args: lock_owner
3af08d828975d7e2581b6829e0eecff14d87a483lm * res: status
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_release_lockowner(nfs_argop4 *argop, nfs_resop4 *resop,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram RELEASE_LOCKOWNER4args *ap = &argop->nfs_argop4_u.oprelease_lockowner;
3af08d828975d7e2581b6829e0eecff14d87a483lm RELEASE_LOCKOWNER4res *resp = &resop->nfs_resop4_u.oprelease_lockowner;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__release__lockowner__start, struct compound_state *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Make sure there is a clientid around for this request */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cp = rfs4_findclient_by_id(ap->lock_owner.clientid, FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check for EXPIRED client. If so will reap state with in a lease
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * period or on next set_clientid_confirm step
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If no sysid has been assigned, then no locks exist; just return.
3af08d828975d7e2581b6829e0eecff14d87a483lm * Mark the lockowner invalid.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * sysid-pid pair should now not be used since the lockowner is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * invalid. If the client were to instantiate the lockowner again
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it would be assigned a new pid. Thus we can get the list of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * current locks.
3af08d828975d7e2581b6829e0eecff14d87a483lm /* If we are still holding locks fail */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We need to unhide the lockowner so the client can
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * try it again. The bad thing here is if the client
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * has a logic error that took it here in the first place
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * he probably has lost accounting of the locks that it
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is holding. So we may have dangling state until the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * open owner state is reaped via close. One scenario
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * that could possibly occur is that the client has
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sent the unlock request(s) in separate threads
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and has not waited for the replies before sending the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * RELEASE_LOCKOWNER request. Presumably, it would expect
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and deal appropriately with NFS4ERR_LOCKS_HELD, by
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * reissuing the request.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * For the corresponding client we need to check each open
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * owner for any opens that have lockowner state associated
3af08d828975d7e2581b6829e0eecff14d87a483lm * with this lockowner.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (oo = list_head(&lo->rl_client->rc_openownerlist); oo != NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo oo = list_next(&lo->rl_client->rc_openownerlist, oo)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__release__lockowner__done, struct compound_state *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * short utility function to lookup a file and recall the delegation
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_lookup_and_findfile(vnode_t *dvp, char *nm, vnode_t **vpp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cr, NULL, NULL,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * remove: args: CURRENT_FH: directory; name.
3af08d828975d7e2581b6829e0eecff14d87a483lm * res: status. If success - CURRENT_FH unchanged, return change_info
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * for directory.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__remove__start, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* CURRENT_FH: directory */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If there is an unshared filesystem mounted on this vnode,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Do not allow to remove anything in this directory.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Lookup the file so that we can check if it's a directory
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* If necessary, convert to UTF-8 for illbehaved clients */
3af08d828975d7e2581b6829e0eecff14d87a483lm ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Lookup the file to determine type and while we are see if
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * there is a file struct around and check for delegation.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * We don't need to acquire va_seq before this lookup, if
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * it causes an update, cinfo.before will not match, which will
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * trigger a cache flush even if atomic is TRUE.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (fp = rfs4_lookup_and_findfile(dvp, name, &vp, &error, cs->cr)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Didn't find anything to remove */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* check label before allowing removal */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "got client label from request(1)",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Get dir "before" change value */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Actually do the REMOVE operation */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Can't remove a directory that has a mounted-on filesystem.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * System V defines rmdir to return EEXIST,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * not * ENOTEMPTY, if the directory is not
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * empty. A System V NFS server needs to map
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * NFS4ERR_EXIST to NFS4ERR_NOTEMPTY to
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * transmit over the wire.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((error = VOP_REMOVE(dvp, name, cs->cr, NULL, 0)) == 0 &&
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * This is va_seq safe because we are not
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * manipulating dvp.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Remove state on file remove */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Get the initial "after" sequence number, if it fails, set to zero
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Force modified data and metadata out to stable storage.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get "after" change value, if it fails, simply return the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * before value.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * The cinfo.atomic = TRUE only if we have
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * non-zero va_seq's, and it has incremented by exactly one
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * during the VOP_REMOVE/RMDIR and it didn't change during
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * the VOP_FSYNC.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__remove__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * rename: args: SAVED_FH: from directory, CURRENT_FH: target directory,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * oldname and newname.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * res: status. If success - CURRENT_FH unchanged, return change_info
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * for both from and target directories.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DTRACE_NFSV4_2(op__rename__start, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* CURRENT_FH: target directory */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* SAVED_FH: from directory */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If there is an unshared filesystem mounted on this vnode,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * do not allow to rename objects in this directory.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If there is an unshared filesystem mounted on this vnode,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * do not allow to rename to this directory.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (odvp->v_type != VDIR || ndvp->v_type != VDIR) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram converted_onm = nfscmd_convname(ca, cs->exi, onm, NFSCMD_CONV_INBOUND,
3af08d828975d7e2581b6829e0eecff14d87a483lm converted_nnm = nfscmd_convname(ca, cs->exi, nnm, NFSCMD_CONV_INBOUND,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* check label of the target dir */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE2(tx__rfs4__log__info__oprename__clabel, char *,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "got client label from request(1)",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Is the source a file and have a delegation?
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * We don't need to acquire va_seq before these lookups, if
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * it causes an update, cinfo.before will not match, which will
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * trigger a cache flush even if atomic is TRUE.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (sfp = rfs4_lookup_and_findfile(odvp, converted_onm, &srcvp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rfs4_check_delegated_byfp(FWRITE, sfp, TRUE, TRUE, TRUE,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Does the destination exist and a file and have a delegation? */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (fp = rfs4_lookup_and_findfile(ndvp, converted_nnm, &targvp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Check for NBMAND lock on both source and target */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Get source "before" change value */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram error = VOP_GETATTR(odvp, &obdva, 0, cs->cr, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram error = VOP_GETATTR(ndvp, &nbdva, 0, cs->cr, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.before, obdva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.before, nbdva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((error = VOP_RENAME(odvp, converted_onm, ndvp, converted_nnm,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* The file is gone and so should the state */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Get the initial "after" sequence number, if it fails, set to zero
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Force modified data and metadata out to stable storage.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Get "after" change values, if it fails, simply return the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * before value.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.after, oadva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.after, nadva.va_ctime)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * The cinfo.atomic = TRUE only if we have
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * non-zero va_seq's, and it has incremented by exactly one
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * during the VOP_RENAME and it didn't change during the VOP_FSYNC.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram oidva.va_seq == (obdva.va_seq + 1) && oidva.va_seq == oadva.va_seq)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (nbdva.va_seq && nidva.va_seq && nadva.va_seq &&
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram nidva.va_seq == (nbdva.va_seq + 1) && nidva.va_seq == nadva.va_seq)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram extern void add_volrnm_fh(struct exportinfo *, vnode_t *);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Add the renamed file handle to the volatile rename list
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* file handles may expire on rename */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Already know that nnm will be a valid string
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram error = VOP_LOOKUP(ndvp, nnm, &vp, NULL, 0, NULL, cs->cr,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#endif /* VOLATILE_FH_TEST */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (sfp_rele_grant_hold) rfs4_clear_dont_grant(sfp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_renew(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__renew__start, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((cp = rfs4_findclient_by_id(args->clientid, FALSE)) == NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (cp->rc_cbinfo.cb_notified_of_cb_path_down == FALSE) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__renew__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_restorefh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram RESTOREFH4res *resp = &resop->nfs_resop4_u.oprestorefh;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_1(op__restorefh__start, struct compound_state *, cs);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* No need to check cs->access - we are not accessing any object */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((cs->saved_vp == NULL) || (cs->saved_fh.nfs_fh4_val == NULL)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__restorefh__done, struct compound_state *, cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* ARGSUSED */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fhepporfs4_op_savefh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_1(op__savefh__start, struct compound_state *, cs);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* No need to check cs->access - we are not accessing any object */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * since SAVEFH is fairly rare, don't alloc space for its fh
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * unless necessary.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cs->saved_fh.nfs_fh4_val = kmem_alloc(NFS4_FHSIZE, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DTRACE_NFSV4_2(op__savefh__done, struct compound_state *, cs,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * rfs4_verify_attr is called when nfsv4 Setattr failed, but we wish to
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * return the bitmap of attrs that were set successfully. It is also
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * called by Verify/Nverify to test the vattr/vfsstat attrs. It should
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * always be called only after rfs4_do_set_attrs().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Verify that the attributes are same as the expected ones. sargp->vap
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and sargp->sbp contain the input attributes as translated from fattr4.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This function verifies only the attrs that correspond to a vattr or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vfsstat struct. That is because of the extra step needed to get the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * corresponding system structs. Other attributes have already been set or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * verified by do_rfs4_set_attrs.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Return 0 if all attrs match, -1 if some don't, error if error processing.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Okay to overwrite sargp->vap because we verify based
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * on the incoming values.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Must return bitmap of successful attrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Some file systems clobber va_mask. it is probably
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * wrong of them to do so, nonethless we practice
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * defensive coding.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * See bug id 4276830.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Now get the superblock and loop on the bitmap, as there is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * no simple way of translating from superblock to bitmap4.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ret_error = VFS_STATVFS(sargp->cs->vp->v_vfsp, sargp->sbp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Now loop and verify each attribute which getattr returned
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * whether it's the same as the input.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If vattr attribute but VOP_GETATTR failed, or it's
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * superblock attribute but VFS_STATVFS failed, skip
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram error = (*nfs4_ntov_map[k].sv_getit)(NFS4ATTR_VERIT, sargp, na);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else /* update response bitmap */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Decode the attribute to be set/verified. If the attr requires a sys op
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * (VOP_GETATTR, VFS_VFSSTAT), and the request is to verify, then don't
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * call the sv_getit function for it, because the sys op hasn't yet been done.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Return 0 for success, error code if failed.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Note: the decoded arg is not freed here but in nfs4_ntov_table_free.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppodecode_fattr4_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sargp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int k, XDR *xdrp, bitmap4 *resp_bval, union nfs4_attr_u *nap)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo set_later = nfs4_ntov_map[k].vbit || nfs4_ntov_map[k].vfsstat;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * don't verify yet if a vattr or sb dependent attr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * because we don't have their sys values yet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Will be done later.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * ACLs are a special case, since setting the MODE
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * conflicts with setting the ACL. We delay setting
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the ACL until all other attributes have been set.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The ACL gets set in do_rfs4_op_setattr().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "decoding attribute %d\n", k);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Set vattr based on incoming fattr4 attrs - used by setattr.
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * Set response mask. Ignore any values that are not writable vattr attrs.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppodo_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram struct nfs4_svgetit_arg *sargp, struct nfs4_ntov_table *ntovp,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * Make sure that maximum attribute number can be expressed as an
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * 8 bit quantity.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* sargp->sbp is set by the caller */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * The following loop iterates on the nfs4_ntov_map checking
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram * if the fbit is set in the requested bitmap.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If set then we process the arguments using the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * rfs4_fattr4 conversion functions to populate the setattr
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vattr and va_mask. Any settable attrs that are not using vattr
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * will be set in this loop.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < nfs4_ntov_map_size; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If setattr, must be a writable attr.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If verify/nverify, must be a readable attr.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Client tries to set/verify an
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * unsupported attribute, tries to set
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * a read only attr or verify a write
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * only one - error!
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Decode the attribute to set/verify
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = decode_fattr4_attr(cmd, sargp, nfs4_ntov_map[i].nval,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppodo_rfs4_op_setattr(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = do_rfs4_set_attrs(resp, fattrp, cs, &sarg, &ntov,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * failed set attrs
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * no further work to be done
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If we got a request to set the ACL and the MODE, only
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * allow changing VSUID, VSGID, and VSVTX. Attempting
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to change any other bits, along with setting an ACL,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * gives NFS4ERR_INVAL.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Check stateid only if size has been set */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram status = rfs4_check_stateid(FWRITE, cs->vp, stateid,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* XXX start of possible race with delegations */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We need to specially handle size changes because it is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * possible for the client to create a file with read-only
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * modes, but with the file opened for writing. If the client
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * then tries to set the file size, e.g. ftruncate(3C),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fcntl(F_FREESP), the normal access checking done in
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * VOP_SETATTR would prevent the client from doing it even though
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it should be allowed to do so. To get around this, we do the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * access checking for ourselves and use VOP_SPACE which doesn't
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * do the access checking.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Also the client should not be allowed to change the file
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * size if there is a conflicting non-blocking mandatory lock in
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the region of the change.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vp->v_type == VREG && (sarg.vap->va_mask & AT_SIZE)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * ufs_setattr clears AT_SIZE from vap->va_mask, but
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * before returning, sarg.vap->va_mask is used to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * generate the setattr reply bitmap. We also clear
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * AT_SIZE below before calling VOP_SPACE. For both
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * of these cases, the va_mask needs to be saved here
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and restored after calling VOP_SETATTR.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check any possible conflict due to NBMAND locks.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Get into critical region before VOP_GETATTR, so the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * size attribute is valid when checking conflicts.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo error = VOP_SETATTR(vp, sarg.vap, sarg.flag, cr, &ct);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* restore va_mask -- ufs_setattr clears AT_SIZE */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If an ACL was being set, it has been delayed until now,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in order to set the mode (via the VOP_SETATTR() above) first.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((! error) && (fattrp->attrmask & FATTR4_ACL_MASK)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < NFS4_MAXNUM_ATTRS; i++)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (error == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "unable to find ACL in fattr4"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check if a monitor detected a delegation conflict */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK))
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Set the response bitmap when setattr failed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If VOP_SETATTR partially succeeded, test by doing a
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * VOP_GETATTR on the object and comparing the data
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * to the setattr arguments.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Force modified metadata out to stable storage.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Set response bitmap
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* Return early and already have a NFSv4 error */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Except for nfs4_vmask_to_nmask_set(), vattr --> fattr
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * conversion sets both readable and writeable NFS4 attrs
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * for AT_MTIME and AT_ATIME. The line below masks out
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * unrequested attrs from the setattr result bitmap. This
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * is placed after the done: label to catch the ATTRNOTSUP
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_setattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram SETATTR4args *args = &argop->nfs_argop4_u.opsetattr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram SETATTR4res *resp = &resop->nfs_resop4_u.opsetattr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__setattr__start, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If there is an unshared filesystem mounted on this vnode,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * do not allow to setattr on this vnode.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* check label before setting attributes */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE2(tx__rfs4__log__info__opsetattr__clabel, char *,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "got client label from request(1)",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__setattr__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_verify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * verify and nverify are exactly the same, except that nverify
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * succeeds when some argument changed, and verify succeeds when
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * when none changed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__verify__start, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * do_rfs4_set_attrs will try to verify systemwide attrs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * so could return -1 for "no match".
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_NFSV4_2(op__verify__done, struct compound_state *, cs,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* ARGSUSED */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramrfs4_op_nverify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * verify and nverify are exactly the same, except that nverify
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * succeeds when some argument changed, and verify succeeds when
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * when none changed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NVERIFY4args *args = &argop->nfs_argop4_u.opnverify;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram NVERIFY4res *resp = &resop->nfs_resop4_u.opnverify;
goto done;
switch (error) {
done:
int error;
int iovcnt;
int ioflag;
int in_crit = 0;
goto out;
goto out;
goto out;
goto out;
if (error) {
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
mblk_t *m;
iovcnt = 0;
bytes = 0;
m = m->b_cont) {
iovcnt++;
#ifdef DEBUG
ioflag = 0;
goto out;
if (error) {
goto out;
if (ioflag == 0)
out:
if (in_crit)
uint_t i;
*rv = 0;
KM_SLEEP);
if (rfs4_seen_first_compound == 0) {
uint_t i;
flag = 0;
nfsstat4 e;
e = NFS4_OK;
e = NFS4_OK;
e = NFS4ERR_DELAY;
switch (operation) {
#define LOCK_PRINT(d, s, t, f)
static bool_t
return (TRUE);
static nfsstat4
char *nm;
return (NFS4ERR_NOFILEHANDLE);
return (NFS4ERR_NOTDIR);
return (NFS4ERR_INVAL);
return (NFS4ERR_INVAL);
return (NFS4ERR_NAMETOOLONG);
return (status);
static nfsstat4
int error;
if (error)
return (status);
if (error)
return (NFS4ERR_ISDIR);
return (NFS4ERR_SYMLINK);
return (NFS4ERR_INVAL);
static nfsstat4
int error;
if (error) {
return (status);
if (error) {
goto tryagain;
return (status);
return (status);
return (NFS4_OK);
if (!error) {
return (NFS4ERR_EXIST);
return (NFS4_OK);
return (NFS4ERR_EXIST);
return (NFS4_OK);
static nfsstat4
int error;
return (NFS4ERR_ACCESS);
return (NFS4ERR_ROFS);
return (NFS4ERR_ACCESS);
if (error)
return (NFS4ERR_ACCESS);
return (NFS4_OK);
static nfsstat4
int error;
return (NFS4ERR_ROFS);
if (is_system_labeled()) {
return (NFS4ERR_ACCESS);
return (NFS4ERR_INVAL);
return (NFS4ERR_RESOURCE);
return (NFS4ERR_NAMETOOLONG);
if (error) {
return (NFS4ERR_NOTDIR);
case GUARDED4:
case UNCHECKED4:
*attrset = 0;
*attrset = 0;
return (status);
*attrset = 0;
return (NFS4ERR_INVAL);
case EXCLUSIVE4:
*attrset = 0;
return (NFS4ERR_INVAL);
return (NFS4ERR_SERVERFAULT);
if (ntov_table_init)
*attrset = 0;
return (status);
if (created) {
*attrset = 0;
if (trunc)
if (ntov_table_init)
if (!created) {
if (setsize)
if (trunc) {
int in_crit = 0;
*attrset = 0;
return (NFS4ERR_DELAY);
in_crit = 0;
*attrset = 0;
return (NFS4ERR_ACCESS);
if (in_crit)
if (error) {
*attrset = 0;
if (!created) {
if (setsize)
*attrset = 0;
return (status);
int fflags = 0;
int recall = 0;
int err;
int first_open;
if (err) {
fflags = 0;
if (dsp) {
int error = 0;
if (error) {
int error;
NFS4_CHKSEQ_OKAY = 0,
static rfs4_chkseq_t
return (NFS4_CHKSEQ_REPLAY);
return (NFS4_CHKSEQ_BAD);
return (NFS4_CHKSEQ_BAD);
return (NFS4_CHKSEQ_OKAY);
static rfs4_chkseq_t
TRUE);
return (rc);
static rfs4_chkseq_t
return (rc);
static rfs4_chkseq_t
return (rc);
int can_reclaim;
goto end;
goto end;
goto end;
goto end;
case NFS4_CHKSEQ_BAD:
goto retry;
goto out;
goto out;
goto retry;
goto out;
goto out;
goto out;
goto out;
goto out;
switch (claim) {
case CLAIM_NULL:
case CLAIM_PREVIOUS:
case CLAIM_DELEGATE_CUR:
case CLAIM_DELEGATE_PREV:
out:
case NFS4ERR_BADXDR:
case NFS4ERR_BAD_SEQID:
case NFS4ERR_BAD_STATEID:
case NFS4ERR_NOFILEHANDLE:
case NFS4ERR_RESOURCE:
case NFS4ERR_STALE_CLIENTID:
case NFS4ERR_STALE_STATEID:
if (!replay)
* current filehandle/vp to that of what was
goto finish;
goto finish;
end:
goto out;
goto out;
goto out;
case NFS4_CHECK_STATEID_OKAY:
resop) != 0) {
case NFS4_CHECK_STATEID_OLD:
case NFS4_CHECK_STATEID_BAD:
resop)) {
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
case NFS4_CHKSEQ_REPLAY:
out:
int fflags = 0;
goto out;
goto out;
goto out;
case NFS4_CHECK_STATEID_OKAY:
goto end;
case NFS4_CHECK_STATEID_OLD:
goto end;
case NFS4_CHECK_STATEID_BAD:
goto end;
goto end;
goto end;
goto end;
resop)) {
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_REPLAY:
goto end;
goto end;
(access &
goto end;
goto end;
end:
out:
int len;
goto out;
if (create) {
goto out;
goto retry;
if (cp_confirmed) {
goto out;
if (cp_unconfirmed) {
if (cp_confirmed)
goto retry;
goto out;
if (cp_confirmed)
goto retry;
out:
goto out;
goto out;
goto out;
if (cptoclose)
out:
goto out;
goto out;
goto out;
case NFS4_CHECK_STATEID_OKAY:
goto end;
case NFS4_CHECK_STATEID_OLD:
goto end;
case NFS4_CHECK_STATEID_BAD:
goto end;
goto end;
goto end;
goto end;
resop)) {
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_REPLAY:
goto end;
end:
out:
int fflags = 0;
if (close_of_client) {
int new_sysid;
new_sysid));
if (!close_of_client &&
static nfsstat4
return (NFS4ERR_EXPIRED);
goto finish;
return (NFS4_OK);
int error;
int cmd;
for (i = 0; i < rfs4_maxlock_tries; i++) {
goto retry;
return (error);
static nfsstat4
int flag;
int error;
return (NFS4ERR_EXPIRED);
return (status);
if (length == 0)
return (NFS4ERR_INVAL);
return (NFS4ERR_OLD_STATEID);
switch (locktype) {
case READ_LT:
case READW_LT:
& OPEN4_SHARE_ACCESS_READ) == 0) {
return (NFS4ERR_OPENMODE);
case WRITE_LT:
case WRITEW_LT:
& OPEN4_SHARE_ACCESS_WRITE) == 0) {
return (NFS4ERR_OPENMODE);
return (NFS4ERR_INVAL);
if (error == 0) {
switch (error) {
case EAGAIN:
== NFS4ERR_EXPIRED)
goto retry;
case ENOLCK:
case EOVERFLOW:
case EINVAL:
return (status);
int rc;
case NFS4_CHECK_STATEID_OLD:
goto end;
case NFS4_CHECK_STATEID_BAD:
goto end;
goto end;
goto end;
goto end;
case NFS4_CHECK_STATEID_OKAY:
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_REPLAY:
goto end;
goto end;
* lock_owner/state association already exists and a
goto end;
goto end;
!= NFS4_OK) {
case NFS4_CHECK_STATEID_OKAY:
switch (rfs4_check_lock_seqid(
case NFS4_CHKSEQ_REPLAY:
goto end;
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_OKAY:
case NFS4_CHECK_STATEID_OLD:
goto end;
case NFS4_CHECK_STATEID_BAD:
goto end;
goto end;
goto end;
switch (rfs4_check_lock_seqid(
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_REPLAY:
goto end;
goto out;
goto out;
goto out;
goto out;
out:
if (sp)
end:
if (lsp) {
if (ls_sw_held)
if (sp) {
case OP_LOCK:
case OP_LOCKT:
if (dp)
case NFS4_CHECK_STATEID_OKAY:
!= NFS4_CHKSEQ_OKAY) {
goto end;
case NFS4_CHECK_STATEID_OLD:
goto end;
case NFS4_CHECK_STATEID_BAD:
goto end;
goto end;
goto end;
case NFS4_CHKSEQ_OKAY:
case NFS4_CHKSEQ_BAD:
goto end;
case NFS4_CHKSEQ_REPLAY:
goto end;
goto out;
goto out;
out:
end:
int error;
int ltype;
goto out;
goto out;
== NULL) {
goto out;
goto out;
goto out;
case READ_LT:
case READW_LT:
case WRITE_LT:
case WRITEW_LT:
if (posix_length == 0) {
goto out;
if (lo) {
goto err;
pid = 0;
goto err;
switch (error) {
goto retry;
case EOVERFLOW:
case EINVAL:
error);
err:
if (lo)
out:
int err;
int cmd;
int fflags = 0;
return (NFS4ERR_OLD_STATEID);
if (err != 0) {
return (err);
int err;
NULL);
if (err != 0) {
return (err);
int wlist_len;
return (FALSE);
return (TRUE);
int rfs4_no_referrals = 0;
int err;
return (err);
if (rfs4_no_referrals != 0)
return (B_FALSE);
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
* There is a user-level copy of this routine in ref_subr.c.
ncomp = 0;
return (ncomp);
* There is a user-level copy of this routine in ref_subr.c.
int ncomp;
return (ncomp);
int err;
return (NULL);
return (NULL);
if (err) {
err);
return (NULL);
int, err);
return (NULL);
return (result);
return (NULL);
return (NULL);
npaths = 0;
npaths++;
return (symbuf);
int is_downrev;
return (is_downrev);