Release 4.10 fs/nfsd/nfs4proc.c
/*
* Server-side procedures for NFSv4.
*
* Copyright (c) 2002 The Regents of the University of Michigan.
* All rights reserved.
*
* Kendrick Smith <kmsmith@umich.edu>
* Andy Adamson <andros@umich.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/file.h>
#include <linux/falloc.h>
#include <linux/slab.h>
#include "idmap.h"
#include "cache.h"
#include "xdr4.h"
#include "vfs.h"
#include "current_stateid.h"
#include "netns.h"
#include "acl.h"
#include "pnfs.h"
#include "trace.h"
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
#include <linux/security.h>
static inline void
nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
{
struct inode *inode = d_inode(resfh->fh_dentry);
int status;
inode_lock(inode);
status = security_inode_setsecctx(resfh->fh_dentry,
label->data, label->len);
inode_unlock(inode);
if (status)
/*
* XXX: We should really fail the whole open, but we may
* already have created a new file, so it may be too
* late. For now this seems the least of evils:
*/
bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
return;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david quigley | david quigley | 72 | 93.51% | 1 | 33.33% |
david howells | david howells | 3 | 3.90% | 1 | 33.33% |
al viro | al viro | 2 | 2.60% | 1 | 33.33% |
| Total | 77 | 100.00% | 3 | 100.00% |
#else
static inline void
nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
{ }
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david quigley | david quigley | 20 | 100.00% | 1 | 100.00% |
| Total | 20 | 100.00% | 1 | 100.00% |
#endif
#define NFSDDBG_FACILITY NFSDDBG_PROC
static u32 nfsd_attrmask[] = {
NFSD_WRITEABLE_ATTRS_WORD0,
NFSD_WRITEABLE_ATTRS_WORD1,
NFSD_WRITEABLE_ATTRS_WORD2
};
static u32 nfsd41_ex_attrmask[] = {
NFSD_SUPPATTR_EXCLCREAT_WORD0,
NFSD_SUPPATTR_EXCLCREAT_WORD1,
NFSD_SUPPATTR_EXCLCREAT_WORD2
};
static __be32
check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
u32 *bmval, u32 *writable)
{
struct dentry *dentry = cstate->current_fh.fh_dentry;
if (!nfsd_attrs_supported(cstate->minorversion, bmval))
return nfserr_attrnotsupp;
if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
return nfserr_attrnotsupp;
if (writable && !bmval_is_subset(bmval, writable))
return nfserr_inval;
if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) &&
(bmval[1] & FATTR4_WORD1_MODE))
return nfserr_inval;
return nfs_ok;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
yu zhiguo | yu zhiguo | 76 | 65.52% | 1 | 25.00% |
andreas gruenbacher | andreas gruenbacher | 25 | 21.55% | 1 | 25.00% |
j. bruce fields | j. bruce fields | 12 | 10.34% | 1 | 25.00% |
david howells | david howells | 3 | 2.59% | 1 | 25.00% |
| Total | 116 | 100.00% | 4 | 100.00% |
static __be32
nfsd4_check_open_attributes(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
{
__be32 status = nfs_ok;
if (open->op_create == NFS4_OPEN_CREATE) {
if (open->op_createmode == NFS4_CREATE_UNCHECKED
|| open->op_createmode == NFS4_CREATE_GUARDED)
status = check_attr_support(rqstp, cstate,
open->op_bmval, nfsd_attrmask);
else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
status = check_attr_support(rqstp, cstate,
open->op_bmval, nfsd41_ex_attrmask);
}
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
yu zhiguo | yu zhiguo | 92 | 100.00% | 1 | 100.00% |
| Total | 92 | 100.00% | 1 | 100.00% |
static int
is_create_with_attrs(struct nfsd4_open *open)
{
return open->op_create == NFS4_OPEN_CREATE
&& (open->op_createmode == NFS4_CREATE_UNCHECKED
|| open->op_createmode == NFS4_CREATE_GUARDED
|| open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
yu zhiguo | yu zhiguo | 37 | 97.37% | 1 | 50.00% |
neil brown | neil brown | 1 | 2.63% | 1 | 50.00% |
| Total | 38 | 100.00% | 2 | 100.00% |
/*
* if error occurs when setting the acl, just clear the acl bit
* in the returned attr bitmap.
*/
static void
do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct nfs4_acl *acl, u32 *bmval)
{
__be32 status;
status = nfsd4_set_nfs4_acl(rqstp, fhp, acl);
if (status)
/*
* We should probably fail the whole open at this point,
* but we've already created the file, so it's too late;
* So this seems the least of evils:
*/
bmval[0] &= ~FATTR4_WORD0_ACL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
yu zhiguo | yu zhiguo | 52 | 100.00% | 1 | 100.00% |
| Total | 52 | 100.00% | 1 | 100.00% |
static inline void
fh_dup2(struct svc_fh *dst, struct svc_fh *src)
{
fh_put(dst);
dget(src->fh_dentry);
if (src->fh_export)
exp_get(src->fh_export);
*dst = *src;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
andrew morton | andrew morton | 46 | 95.83% | 1 | 33.33% |
yu zhiguo | yu zhiguo | 1 | 2.08% | 1 | 33.33% |
kinglong mee | kinglong mee | 1 | 2.08% | 1 | 33.33% |
| Total | 48 | 100.00% | 3 | 100.00% |
static __be32
do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
{
__be32 status;
if (open->op_truncate &&
!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
return nfserr_inval;
accmode |= NFSD_MAY_READ_IF_EXEC;
if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
accmode |= NFSD_MAY_READ;
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
if (open->op_share_deny & NFS4_SHARE_DENY_READ)
accmode |= NFSD_MAY_WRITE;
status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
andrew morton | andrew morton | 79 | 75.24% | 2 | 25.00% |
j. bruce fields | j. bruce fields | 20 | 19.05% | 4 | 50.00% |
miklos szeredi | miklos szeredi | 4 | 3.81% | 1 | 12.50% |
al viro | al viro | 2 | 1.90% | 1 | 12.50% |
| Total | 105 | 100.00% | 8 | 100.00% |
static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
{
umode_t mode = d_inode(fh->fh_dentry)->i_mode;
if (S_ISREG(mode))
return nfs_ok;
if (S_ISDIR(mode))
return nfserr_isdir;
/*
* Using err_symlink as our catch-all case may look odd; but
* there's no other obvious error for this case in 4.0, and we
* happen to know that it will cause the linux v4 client to do
* the right thing on attempts to open something other than a
* regular file.
*/
return nfserr_symlink;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
j. bruce fields | j. bruce fields | 44 | 93.62% | 1 | 50.00% |
david howells | david howells | 3 | 6.38% | 1 | 50.00% |
| Total | 47 | 100.00% | 2 | 100.00% |
static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh *resfh)
{
if (nfsd4_has_session(cstate))
return;
fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
&resfh->fh_handle);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
j. bruce fields | j. bruce fields | 48 | 100.00% | 1 | 100.00% |
| Total | 48 | 100.00% | 1 | 100.00% |
static __be32
do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh)
{
struct svc_fh *current_fh = &cstate->current_fh;
int accmode;
__be32 status;
*resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
if (!*resfh)
return nfserr_jukebox;
fh_init(*resfh, NFS4_FHSIZE);
open->op_truncate = 0;
if (open->op_create) {
/* FIXME: check session persistence and pnfs flags.
* The nfsv4.1 spec requires the following semantics:
*
* Persistent | pNFS | Server REQUIRED | Client Allowed
* Reply Cache | server | |
* -------------+--------+-----------------+--------------------
* no | no | EXCLUSIVE4_1 | EXCLUSIVE4_1
* | | | (SHOULD)
* | | and EXCLUSIVE4 | or EXCLUSIVE4
* | | | (SHOULD NOT)
* no | yes | EXCLUSIVE4_1 | EXCLUSIVE4_1
* yes | no | GUARDED4 | GUARDED4
* yes | yes | GUARDED4 | GUARDED4
*/
/*
* Note: create modes (UNCHECKED,GUARDED...) are the same
* in NFSv4 as in v3 except EXCLUSIVE4_1.
*/
status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
open->op_fname.len, &open->op_iattr,
*resfh, open->op_createmode,
(u32 *)open->op_verf.data,
&open->op_truncate, &open->op_created);
if (!status && open->op_label.len)
nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
/*
* Following rfc 3530 14.2.16, and rfc 5661 18.16.4
* use the returned bitmask to indicate which attributes
* we used to store the verifier:
*/
if (nfsd_create_is_exclusive(open->op_createmode) && status == 0)
open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
FATTR4_WORD1_TIME_MODIFY);
} else
/*
* Note this may exit with the parent still locked.
* We will hold the lock until nfsd4_open's final
* lookup, to prevent renames or unlinks until we've had
* a chance to an acquire a delegation if appropriate.
*/
status = nfsd_lookup(rqstp, current_fh,
open->op_fname.data, open->op_fname.len, *resfh);
if (status)
goto out;
status = nfsd_check_obj_isreg(*resfh);
if (status)
goto out;
if (is_create_with_attrs(open) && open->op_acl != NULL)
do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval);
nfsd4_set_open_owner_reply_cache(cstate, open, *resfh);
accmode = NFSD_MAY_NOP;
if (open->op_created ||
open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
accmode |= NFSD_MAY_OWNER_OVERRIDE;
status = do_open_permission(rqstp, *resfh, open, accmode);
set_change_info(&open->op_cinfo, current_fh);
out:
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 127 | 38.25% | 3 | 12.50% |
j. bruce fields | j. bruce fields | 99 | 29.82% | 11 | 45.83% |
yu zhiguo | yu zhiguo | 28 | 8.43% | 1 | 4.17% |
david quigley | david quigley | 25 | 7.53% | 1 | 4.17% |
jeff layton | jeff layton | 22 | 6.63% | 1 | 4.17% |
andrew morton | andrew morton | 19 | 5.72% | 2 | 8.33% |
kinglong mee | kinglong mee | 5 | 1.51% | 1 | 4.17% |
al viro | al viro | 2 | 0.60% | 1 | 4.17% |
trond myklebust | trond myklebust | 2 | 0.60% | 1 | 4.17% |
mi jinlong | mi jinlong | 2 | 0.60% | 1 | 4.17% |
benny halevy | benny halevy | 1 | 0.30% | 1 | 4.17% |
| Total | 332 | 100.00% | 24 | 100.00% |
static __be32
do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
{
struct svc_fh *current_fh = &cstate->current_fh;
__be32 status;
int accmode = 0;
/* We don't know the target directory, and therefore can not
* set the change info
*/
memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
nfsd4_set_open_owner_reply_cache(cstate, open, current_fh);
open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
(open->op_iattr.ia_size == 0);
/*
* In the delegation case, the client is telling us about an
* open that it *already* performed locally, some time ago. We
* should let it succeed now if possible.
*
* In the case of a CLAIM_FH open, on the other hand, the client
* may be counting on us to enforce permissions (the Linux 4.1
* client uses this for normal opens, for example).
*/
if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH)
accmode = NFSD_MAY_OWNER_OVERRIDE;
status = do_open_permission(rqstp, current_fh, open, accmode);
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
andrew morton | andrew morton | 58 | 49.15% | 2 | 22.22% |
j. bruce fields | j. bruce fields | 35 | 29.66% | 3 | 33.33% |
neil brown | neil brown | 23 | 19.49% | 3 | 33.33% |
al viro | al viro | 2 | 1.69% | 1 | 11.11% |
| Total | 118 | 100.00% | 9 | 100.00% |
static void
copy_clientid(clientid_t *clid, struct nfsd4_session *session)
{
struct nfsd4_sessionid *sid =
(struct nfsd4_sessionid *)session->se_sessionid.data;
clid->cl_boot = sid->clientid.cl_boot;
clid->cl_id = sid->clientid.cl_id;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
andy adamson | andy adamson | 50 | 98.04% | 1 | 50.00% |
neil brown | neil brown | 1 | 1.96% | 1 | 50.00% |
| Total | 51 | 100.00% | 2 | 100.00% |
static __be32
nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_open *open)
{
__be32 status;
struct svc_fh *resfh = NULL;
struct net *net = SVC_NET(rqstp);
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
(int)open->op_fname.len, open->op_fname.data,
open->op_openowner);
/* This check required by spec. */
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
return nfserr_inval;
open->op_created = 0;
/*
* RFC5661 18.51.3
* Before RECLAIM_COMPLETE done, server should deny new lock
*/
if (nfsd4_has_session(cstate) &&
!test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
&cstate->session->se_client->cl_flags) &&
open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
return nfserr_grace;
if (nfsd4_has_session(cstate))
copy_clientid(&open->op_clientid, cstate->session);
/* check seqid for replay. set nfs4_owner */
status = nfsd4_process_open1(cstate, open, nn);
if (status == nfserr_replay_me) {
struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
fh_put(&cstate->current_fh);
fh_copy_shallow(&cstate->current_fh.fh_handle,
&rp->rp_openfh);
status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
if (status)
dprintk("nfsd4_open: replay failed"
" restoring previous filehandle\n");
else
status = nfserr_replay_me;
}
if (status)
goto out;
if (open->op_xdr_error) {
status = open->op_xdr_error;
goto out;
}
status = nfsd4_check_open_attributes(rqstp, cstate, open);
if (status)
goto out;
/* Openowner is now set, so sequence id will get bumped. Now we need
* these checks before we do any creates: */
status = nfserr_grace;
if (opens_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
status = nfserr_no_grace;
if (!opens_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
switch (open->op_claim_type) {
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
case NFS4_OPEN_CLAIM_NULL:
status = do_open_lookup(rqstp, cstate, open, &resfh);
if (status)
goto out;
break;
case NFS4_OPEN_CLAIM_PREVIOUS:
status = nfs4_check_open_reclaim(&open->op_clientid,
cstate, nn);
if (status)
goto out;
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
case NFS4_OPEN_CLAIM_FH:
case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
status = do_open_fhandle(rqstp, cstate, open);
if (status)
goto out;
resfh = &cstate->current_fh;
break;
case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
dprintk("NFSD: unsupported OPEN claim type %d\n",
open->op_claim_type);
status = nfserr_notsupp;
goto out;
default:
dprintk("NFSD: Invalid OPEN claim type %d\n",
open->op_claim_type);
status = nfserr_inval;
goto out;
}
/*
* nfsd4_process_open2() does the actual opening of the file. If
* successful, it (1) truncates the file if open->op_truncate was
* set, (2) sets open->op_stateid, (3) sets open->op_delegation.
*/
status = nfsd4_process_open2(rqstp, resfh, open);
WARN(status && open->op_created,
"nfsd4_process_open2 failed to open newly-created file! status=%u\n",
be32_to_cpu(status));
out:
if (resfh && resfh != &cstate->current_fh) {
fh_dup2(&cstate->current_fh, resfh);
fh_put(resfh);
kfree(resfh);
}
nfsd4_cleanup_open_state(cstate, open);
nfsd4_bump_seqid(cstate, status);
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
j. bruce fields | j. bruce fields | 163 | 30.13% | 14 | 37.84% |
neil brown | neil brown | 143 | 26.43% | 5 | 13.51% |
andrew morton | andrew morton | 91 | 16.82% | 4 | 10.81% |
mi jinlong | mi jinlong | 42 | 7.76% | 2 | 5.41% |
stanislav kinsbursky | stanislav kinsbursky | 31 | 5.73% | 2 | 5.41% |
jeff layton | jeff layton | 25 | 4.62% | 4 | 10.81% |
andy adamson | andy adamson | 23 | 4.25% | 2 | 5.41% |
yu zhiguo | yu zhiguo | 18 | 3.33% | 1 | 2.70% |
al viro | al viro | 4 | 0.74% | 2 | 5.41% |
miklos szeredi | miklos szeredi | 1 | 0.18% | 1 | 2.70% |
| Total | 541 | 100.00% | 37 | 100.00% |
/*
* OPEN is the only seqid-mutating operation whose decoding can fail
* with a seqid-mutating error (specifically, decoding of user names in
* the attributes). Therefore we have to do some processing to look up
* the stateowner so that we can bump the seqid.
*/
static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op)
{
struct nfsd4_open *open = (struct nfsd4_open *)&op->u;
if (!seqid_mutating_err(ntohl(op->status)))
return op->status;
if (nfsd4_has_session(cstate))
return op->status;
open->op_xdr_error = op->status;
return nfsd4_open(rqstp, cstate, open);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
j. bruce fields | j. bruce fields | 84 | 100.00% | 1 | 100.00% |
| Total | 84 | 100.00% | 1 | 100.00% |
/*
* filehandle-manipulating ops.
*/
static __be32
nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct svc_fh **getfh)
{
if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
*getfh = &cstate->current_fh;
return nfs_ok;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 31 | 68.89% | 1 | 25.00% |
j. bruce fields | j. bruce fields | 13 | 28.89% | 2 | 50.00% |
al viro | al viro | 1 | 2.22% | 1 | 25.00% |
| Total | 45 | 100.00% | 4 | 100.00% |
static __be32
nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_putfh *putfh)
{
fh_put(&cstate->current_fh);
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
putfh->pf_fhlen);
return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 60 | 78.95% | 1 | 25.00% |
j. bruce fields | j. bruce fields | 15 | 19.74% | 2 | 50.00% |
al viro | al viro | 1 | 1.32% | 1 | 25.00% |
| Total | 76 | 100.00% | 4 | 100.00% |
static __be32
nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
void *arg)
{
__be32 status;
fh_put(&cstate->current_fh);
status = exp_pseudoroot(rqstp, &cstate->current_fh);
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 25 | 54.35% | 1 | 20.00% |
j. bruce fields | j. bruce fields | 12 | 26.09% | 2 | 40.00% |
andrew morton | andrew morton | 7 | 15.22% | 1 | 20.00% |
al viro | al viro | 2 | 4.35% | 1 | 20.00% |
| Total | 46 | 100.00% | 5 | 100.00% |
static __be32
nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
void *arg)
{
if (!cstate->save_fh.fh_dentry)
return nfserr_restorefh;
fh_dup2(&cstate->current_fh, &cstate->save_fh);
if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) {
memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
}
return nfs_ok;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tigran mkrtchyan | tigran mkrtchyan | 36 | 42.86% | 2 | 28.57% |
neil brown | neil brown | 26 | 30.95% | 1 | 14.29% |
j. bruce fields | j. bruce fields | 20 | 23.81% | 2 | 28.57% |
andrew morton | andrew morton | 1 | 1.19% | 1 | 14.29% |
al viro | al viro | 1 | 1.19% | 1 | 14.29% |
| Total | 84 | 100.00% | 7 | 100.00% |
static __be32
nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
void *arg)
{
if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
fh_dup2(&cstate->save_fh, &cstate->current_fh);
if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) {
memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG);
}
return nfs_ok;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tigran mkrtchyan | tigran mkrtchyan | 36 | 42.86% | 2 | 33.33% |
neil brown | neil brown | 27 | 32.14% | 1 | 16.67% |
j. bruce fields | j. bruce fields | 20 | 23.81% | 2 | 33.33% |
al viro | al viro | 1 | 1.19% | 1 | 16.67% |
| Total | 84 | 100.00% | 6 | 100.00% |
/*
* misc nfsv4 ops
*/
static __be32
nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_access *access)
{
if (access->ac_req_access & ~NFS3_ACCESS_FULL)
return nfserr_inval;
access->ac_resp_access = access->ac_req_access;
return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
&access->ac_supported);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 56 | 90.32% | 1 | 33.33% |
j. bruce fields | j. bruce fields | 5 | 8.06% | 1 | 33.33% |
al viro | al viro | 1 | 1.61% | 1 | 33.33% |
| Total | 62 | 100.00% | 3 | 100.00% |
static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
{
__be32 verf[2];
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
/*
* This is opaque to client, so no need to byte-swap. Use
* __force to keep sparse happy
*/
verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec;
verf[1] = (__force __be32)nn->nfssvc_boot.tv_usec;
memcpy(verifier->data, verf, sizeof(verifier->data));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
chuck lever | chuck lever | 56 | 70.00% | 1 | 33.33% |
stanislav kinsbursky | stanislav kinsbursky | 21 | 26.25% | 1 | 33.33% |
jeff layton | jeff layton | 3 | 3.75% | 1 | 33.33% |
| Total | 80 | 100.00% | 3 | 100.00% |
static __be32
nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_commit *commit)
{
gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp));
return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
commit->co_count);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
neil brown | neil brown | 37 | 69.81% | 1 | 16.67% |
j. bruce fields | j. bruce fields | 6 | 11.32% | 2 | 33.33% |
stanislav kinsbursky | stanislav kinsbursky | 5 | 9.43% | 1 | 16.67% |
chuck lever | chuck lever | 4 | 7.55% | 1 | 16.67% |
al viro | al viro | 1 | 1.89% | 1 | 16.67% |
| Total | 53 | 100.00% | 6 | 100.00% |
static __be32
nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_create *create)
{
struct svc_fh resfh;
__be32 status;
dev_t rdev;
fh_init(&resfh, NFS4_FHSIZE);
status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
if (status)
return status;
status = check_attr_support(rqstp, cstate, create->cr_bmval,
nfsd_attrmask);
if (status)
return status;
switch (create->cr_type) {
case NF4LNK:
status = nfsd_symlink(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
create->cr_data, &resfh);
break;
case NF4BLK:
rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
status = nfsd_create(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
&create->cr_iattr, S_IFBLK, rdev, &resfh);
break;
case NF4CHR:
rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
status = nfsd_create(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
&create->cr_iattr,S_IFCHR, rdev, &resfh);
break;
case NF4SOCK:
status = nfsd_create(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
&create->cr_iattr, S_IFSOCK, 0, &resfh);
break;
case NF4FIFO:
status = nfsd_create(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
&create->cr_iattr, S_IFIFO, 0, &resfh);
break;
case NF4DIR:
create->cr_iattr.ia_valid &= ~ATTR_SIZE;
status = nfsd_create(rqstp, &cstate->current_fh,
create->cr_name, create->cr_namelen,
&create->cr_iattr, S_IFDIR, 0, &resfh);
break;
default:
status = nfserr_badtype;
}
if (status)
goto out;
if (create->cr_label.len)
nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
if (create->cr_acl != NULL)
do_set_nfs4_acl(rqstp, &resfh,