nfs3_srv.c revision 2007c08f9799ffdd411bdfb139620e810813c068
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * CDDL HEADER START
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * The contents of this file are subject to the terms of the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Common Development and Distribution License (the "License").
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * You may not use this file except in compliance with the License.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * See the License for the specific language governing permissions
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * and limitations under the License.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * When distributing Covered Code, include this CDDL HEADER in each
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * If applicable, add the following below this CDDL HEADER, with the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * fields enclosed by brackets "[]" replaced with your own identifying
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * information: Portions Copyright [yyyy] [name of copyright owner]
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * CDDL HEADER END
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri/* All Rights Reserved */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * These are the interface routines for the server side of the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Network File System. See the NFS version 3 protocol specification
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * for a description of this interface.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiristatic int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiristatic void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiristatic void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic int rdma_setup_read_data3(READ3args *, READ3resok *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* ARGSUSED */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemrfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /* Lie about the object type for a referral */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /* overflow error if time or size is out of range */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemrfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri "got client label from request(1)", struct svc_req *, req);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * We need to specially handle size changes because of
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * possible conflicting NBMAND locks. Get into critical
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * region before VOP_GETATTR, so the size attribute is
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * valid when checking conflicts.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Also, check to see if the v4 side of the server has
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * delegated this file. If so, then we return JUKEBOX to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * allow the client to retrasmit its request.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If we can't get the attributes, then we can't do the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * right access checking. So, we'll fail the request.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * If the filesystem is exported with nosuid, then mask off
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * the setuid and setgid bits.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * We need to specially handle size changes because it is
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * possible for the client to create a file with modes
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * which indicate read-only, but with the file opened for
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * writing. If the client then tries to set the size of
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * the file, then the normal access checking done in
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * VOP_SETATTR would prevent the client from doing so,
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * although it should be legal for it to do so. To get
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * around this, we do the access checking for ourselves
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * and then use VOP_SPACE which doesn't do the access
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * checking which VOP_SETATTR does. VOP_SPACE can only
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * operate on VREG files, let VOP_SETATTR handle the other
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * extremely rare cases.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Also the client should not be allowed to change the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * size of the file if there is a conflicting non-blocking
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * mandatory lock in the region the change.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri /* check if a monitor detected a delegation conflict */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Force modified metadata out to stable storage.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* ARGSUSED */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirirfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
int error;
goto out;
goto out1;
goto out1;
goto out1;
goto out1;
if (error == 0) {
int addr_type;
void *ipaddr;
SUN_CIPSO) {
if (error)
goto out;
if (error) {
goto out;
if (auth_weak)
out:
out1:
int error;
int checkwriteperm;
goto out;
checkwriteperm = 0;
if (error)
goto out;
if (is_system_labeled()) {
if (error) {
goto out;
if (error) {
goto out;
if (checkwriteperm &&
if (error) {
goto out;
if (checkwriteperm &&
if (error) {
goto out;
if (error) {
goto out;
out:
int error;
char *data;
int is_referral = 0;
goto out;
if (error)
goto out;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
if (is_referral) {
if (s == NULL)
error = 0;
if (!error)
if (error) {
goto out;
out:
out1:
int error;
int alloc_err = 0;
int in_crit = 0;
int need_rwunlock = 0;
int rdma_used = 0;
int loaned_buffers;
goto out;
goto out;
if (is_system_labeled()) {
exi)) {
goto out1;
NULL)) {
goto out;
goto out1;
if (error)
goto out;
goto out1;
if (error) {
goto out;
if (error)
goto out;
goto out1;
if (in_crit)
goto done;
if (in_crit)
goto done;
if (loaned_buffers) {
goto doio_read;
loaned_buffers = 0;
* If we aren't returning READ data w/RDMA_WRITE, then grab
if (rdma_used) {
&alloc_err);
if (error) {
if (mp)
goto out1;
goto out;
if (loaned_buffers) {
if (error)
if (in_crit)
if (mp)
if (rdma_used) {
done:
out:
out1:
if (need_rwunlock)
if (in_crit)
#ifdef DEBUG
static int rfs3_write_hits = 0;
static int rfs3_write_misses = 0;
int error;
mblk_t *m;
int iovcnt;
int ioflag;
int in_crit = 0;
goto err;
if (is_system_labeled()) {
exi)) {
goto err1;
NULL)) {
goto err;
goto err1;
if (error)
goto err;
goto err1;
goto err1;
goto err1;
goto err;
goto err1;
goto out;
iovcnt = 0;
iovcnt++;
#ifdef DEBUG
#ifdef DEBUG
ioflag = 0;
goto err1;
goto err1;
if (error)
goto err;
goto out;
err:
err1:
out:
if (in_crit)
int error;
int in_crit = 0;
goto out;
goto out1;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out1;
&va);
if (error)
goto out;
if (!error &&
goto out1;
NULL);
if (error)
goto out;
goto out;
} else if (tvp) {
goto out1;
if (error) {
goto out;
if (error) {
goto tryagain;
goto out;
goto out1;
goto out;
goto out1;
if (error)
if (in_crit)
out:
out1:
if (in_crit)
int error;
goto out;
goto out1;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
if (error)
goto out;
goto out1;
goto out1;
if (error)
goto out;
if (error)
out:
out1:
int error;
goto err;
goto err1;
goto err1;
goto err1;
if (is_system_labeled()) {
exi)) {
goto err1;
if (error)
goto err;
goto err1;
goto err1;
goto err1;
goto err1;
if (error)
goto err;
if (error) {
goto out;
if (error)
goto out;
err:
err1:
out:
int error;
int mode;
goto out;
goto out1;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
case NF3CHR:
case NF3BLK:
if (error)
goto out;
goto out1;
case NF3SOCK:
if (error)
goto out;
case NF3FIFO:
if (error)
goto out;
goto out1;
goto out1;
goto out1;
mode = 0;
if (error)
goto out;
if (error)
out:
out1:
int error = 0;
goto err;
goto err1;
goto err1;
goto err1;
goto err1;
if (is_system_labeled()) {
exi)) {
goto err1;
goto err1;
if (error != 0)
goto err;
goto err1;
if (error)
goto err;
goto out;
err:
err1:
out:
int error;
goto err;
goto err1;
goto err1;
goto err1;
goto err1;
if (is_system_labeled()) {
exi)) {
goto err1;
goto err1;
if (error) {
goto err;
goto out;
err:
err1:
out:
int error = 0;
goto err;
if (is_system_labeled()) {
exi)) {
goto err1;
goto err1;
goto err1;
goto err;
goto err1;
goto err1;
goto err1;
goto err1;
if (is_system_labeled()) {
exi)) {
goto err1;
goto err1;
goto err1;
if (error != 0)
goto err;
goto err1;
goto err1;
if (error == 0)
if (error)
goto err;
goto out;
err:
err1:
out:
int error;
goto out;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out;
goto out1;
goto out1;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out1;
if (error)
goto out;
out:
out1:
int error;
char *data;
int iseof;
int bufsize;
int namlen;
goto out;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out1;
if (error)
goto out;
if (error) {
goto out;
goto out1;
out:
out1:
#ifdef nextdp
int error;
char *data;
int iseof;
int size = 0;
int nents = 0;
int bufsize = 0;
int entrysize = 0;
int tofit = 0;
int prev_len;
int space_left;
goto out;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out;
if (error)
goto out;
if (error) {
goto out;
if (nents == 0) {
goto out1;
goto good;
size > 0;
nents++;
if (nents == 0) {
goto out1;
goto good;
nents++;
if (!iseof &&
goto getmoredents;
good:
for (i = 0; i < nents; i++) {
if (error) {
if (!error)
if (ret > 0) {
if (iseof)
out:
out1:
int error;
goto out;
if (is_system_labeled()) {
exi)) {
goto out1;
if (error)
goto out;
out:
out1:
ulong_t l = 0;
int error;
goto out;
if (is_system_labeled()) {
exi)) {
goto out;
if (error) {
goto out;
out:
int error;
goto out;
if (is_system_labeled()) {
exi)) {
goto out1;
if (error)
goto out;
if (error)
goto out;
if (error)
goto out;
if (error)
goto out;
out:
out1:
int error;
goto out;
if (error)
goto out;
goto out1;
goto out1;
if (is_system_labeled()) {
exi)) {
goto out1;
goto out;
if (error)
goto out;
out:
out1:
return (EINVAL);
#ifndef _LP64
return (EOVERFLOW);
#ifndef _LP64
return (EOVERFLOW);
return (EOVERFLOW);
return (EOVERFLOW);
rfs3_srvrinit(void)
struct rfs3_verf_overlay {
} *verfp;
#ifndef lint
int wlist_len;
return (FALSE);
return (TRUE);
rfs3_srvrfini(void)