Merge branch 'for-2.6.33' of git://linux-nfs.org/~bfields/linux

* 'for-2.6.33' of git://linux-nfs.org/~bfields/linux: (42 commits)
  nfsd: remove pointless paths in file headers
  nfsd: move most of nfsfh.h to fs/nfsd
  nfsd: remove unused field rq_reffh
  nfsd: enable V4ROOT exports
  nfsd: make V4ROOT exports read-only
  nfsd: restrict filehandles accepted in V4ROOT case
  nfsd: allow exports of symlinks
  nfsd: filter readdir results in V4ROOT case
  nfsd: filter lookup results in V4ROOT case
  nfsd4: don't continue "under" mounts in V4ROOT case
  nfsd: introduce export flag for v4 pseudoroot
  nfsd: let "insecure" flag vary by pseudoflavor
  nfsd: new interface to advertise export features
  nfsd: Move private headers to source directory
  vfs: nfsctl.c un-used nfsd #includes
  lockd: Remove un-used nfsd headers #includes
  s390: remove un-used nfsd #includes
  sparc: remove un-used nfsd #includes
  parsic: remove un-used nfsd #includes
  compat.c: Remove dependence on nfsd private headers
  ...
This commit is contained in:
Linus Torvalds 2009-12-16 10:43:34 -08:00
commit 37c24b37fb
63 changed files with 721 additions and 865 deletions

View file

@ -1,7 +1,5 @@
00-INDEX 00-INDEX
- this file (info on some of the filesystems supported by linux). - this file (info on some of the filesystems supported by linux).
Exporting
- explanation of how to make filesystems exportable.
Locking Locking
- info on locking rules as they pertain to Linux VFS. - info on locking rules as they pertain to Linux VFS.
9p.txt 9p.txt
@ -68,12 +66,8 @@ mandatory-locking.txt
- info on the Linux implementation of Sys V mandatory file locking. - info on the Linux implementation of Sys V mandatory file locking.
ncpfs.txt ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol. - info on Novell Netware(tm) filesystem using NCP protocol.
nfs41-server.txt nfs/
- info on the Linux server implementation of NFSv4 minor version 1. - nfs-related documentation.
nfs-rdma.txt
- how to install and setup the Linux NFS/RDMA client and server software.
nfsroot.txt
- short guide on setting up a diskless box with NFS root filesystem.
nilfs2.txt nilfs2.txt
- info and mount options for the NILFS2 filesystem. - info and mount options for the NILFS2 filesystem.
ntfs.txt ntfs.txt
@ -92,8 +86,6 @@ relay.txt
- info on relay, for efficient streaming from kernel to user space. - info on relay, for efficient streaming from kernel to user space.
romfs.txt romfs.txt
- description of the ROMFS filesystem. - description of the ROMFS filesystem.
rpc-cache.txt
- introduction to the caching mechanisms in the sunrpc layer.
seq_file.txt seq_file.txt
- how to use the seq_file API - how to use the seq_file API
sharedsubtree.txt sharedsubtree.txt

View file

@ -0,0 +1,16 @@
00-INDEX
- this file (nfs-related documentation).
Exporting
- explanation of how to make filesystems exportable.
knfsd-stats.txt
- statistics which the NFS server makes available to user space.
nfs.txt
- nfs client, and DNS resolution for fs_locations.
nfs41-server.txt
- info on the Linux server implementation of NFSv4 minor version 1.
nfs-rdma.txt
- how to install and setup the Linux NFS/RDMA client and server software
nfsroot.txt
- short guide on setting up a diskless box with NFS root filesystem.
rpc-cache.txt
- introduction to the caching mechanisms in the sunrpc layer.

View file

@ -41,7 +41,7 @@ interoperability problems with future clients. Known issues:
conformant with the spec (for example, we don't use kerberos conformant with the spec (for example, we don't use kerberos
on the backchannel correctly). on the backchannel correctly).
- no trunking support: no clients currently take advantage of - no trunking support: no clients currently take advantage of
trunking, but this is a mandatory failure, and its use is trunking, but this is a mandatory feature, and its use is
recommended to clients in a number of places. (E.g. to ensure recommended to clients in a number of places. (E.g. to ensure
timely renewal in case an existing connection's retry timeouts timely renewal in case an existing connection's retry timeouts
have gotten too long; see section 8.3 of the draft.) have gotten too long; see section 8.3 of the draft.)
@ -213,3 +213,10 @@ The following cases aren't supported yet:
DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID. DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
* DESTROY_SESSION MUST be the final operation in the COMPOUND request. * DESTROY_SESSION MUST be the final operation in the COMPOUND request.
Nonstandard compound limitations:
* No support for a sessions fore channel RPC compound that requires both a
ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
fail to live up to the promise we made in CREATE_SESSION fore channel
negotiation.
* No more than one IO operation (read, write, readdir) allowed per
compound.

View file

@ -140,7 +140,7 @@ Callers of notify_change() need ->i_mutex now.
New super_block field "struct export_operations *s_export_op" for New super_block field "struct export_operations *s_export_op" for
explicit support for exporting, e.g. via NFS. The structure is fully explicit support for exporting, e.g. via NFS. The structure is fully
documented at its declaration in include/linux/fs.h, and in documented at its declaration in include/linux/fs.h, and in
Documentation/filesystems/Exporting. Documentation/filesystems/nfs/Exporting.
Briefly it allows for the definition of decode_fh and encode_fh operations Briefly it allows for the definition of decode_fh and encode_fh operations
to encode and decode filehandles, and allows the filesystem to use to encode and decode filehandles, and allows the filesystem to use

View file

@ -1032,7 +1032,7 @@ and is between 256 and 4096 characters. It is defined in the file
No delay No delay
ip= [IP_PNP] ip= [IP_PNP]
See Documentation/filesystems/nfsroot.txt. See Documentation/filesystems/nfs/nfsroot.txt.
ip2= [HW] Set IO/IRQ pairs for up to 4 IntelliPort boards ip2= [HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
See comment before ip2_setup() in See comment before ip2_setup() in
@ -1553,10 +1553,10 @@ and is between 256 and 4096 characters. It is defined in the file
going to be removed in 2.6.29. going to be removed in 2.6.29.
nfsaddrs= [NFS] nfsaddrs= [NFS]
See Documentation/filesystems/nfsroot.txt. See Documentation/filesystems/nfs/nfsroot.txt.
nfsroot= [NFS] nfs root filesystem for disk-less boxes. nfsroot= [NFS] nfs root filesystem for disk-less boxes.
See Documentation/filesystems/nfsroot.txt. See Documentation/filesystems/nfs/nfsroot.txt.
nfs.callback_tcpport= nfs.callback_tcpport=
[NFS] set the TCP port on which the NFSv4 callback [NFS] set the TCP port on which the NFSv4 callback

View file

@ -26,13 +26,7 @@
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/nfs_fs.h>
#include <linux/ncp_fs.h> #include <linux/ncp_fs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/stat.h> #include <linux/stat.h>

View file

@ -24,7 +24,7 @@
*/ */
/* /*
* See Documentation/filesystems/Exporting * See Documentation/filesystems/nfs/Exporting
* and examples in fs/exportfs * and examples in fs/exportfs
* *
* Since cifs is a network file system, an "fsid" must be included for * Since cifs is a network file system, an "fsid" must be included for

View file

@ -38,8 +38,6 @@
#include <linux/dirent.h> #include <linux/dirent.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/highuid.h> #include <linux/highuid.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/syscall.h> #include <linux/nfsd/syscall.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>

View file

@ -6,7 +6,7 @@
* and for mapping back from file handles to dentries. * and for mapping back from file handles to dentries.
* *
* For details on why we do all the strange and hairy things in here * For details on why we do all the strange and hairy things in here
* take a look at Documentation/filesystems/Exporting. * take a look at Documentation/filesystems/nfs/Exporting.
*/ */
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/fs.h> #include <linux/fs.h>

View file

@ -9,7 +9,7 @@
* *
* The following files are helpful: * The following files are helpful:
* *
* Documentation/filesystems/Exporting * Documentation/filesystems/nfs/Exporting
* fs/exportfs/expfs.c. * fs/exportfs/expfs.c.
*/ */

View file

@ -11,10 +11,6 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/in.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfsd/nfsd.h>
#include <linux/lockd/lockd.h> #include <linux/lockd/lockd.h>
#include <linux/lockd/share.h> #include <linux/lockd/share.h>

View file

@ -11,10 +11,6 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/in.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfsd/nfsd.h>
#include <linux/lockd/lockd.h> #include <linux/lockd/lockd.h>
#include <linux/lockd/share.h> #include <linux/lockd/share.h>

View file

@ -90,7 +90,7 @@ config ROOT_NFS
If you want your system to mount its root file system via NFS, If you want your system to mount its root file system via NFS,
choose Y here. This is common practice for managing systems choose Y here. This is common practice for managing systems
without local permanent storage. For details, read without local permanent storage. For details, read
<file:Documentation/filesystems/nfsroot.txt>. <file:Documentation/filesystems/nfs/nfsroot.txt>.
Most people say N here. Most people say N here.

View file

@ -7,8 +7,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/syscall.h> #include <linux/nfsd/syscall.h>
#include <linux/cred.h> #include <linux/cred.h>
#include <linux/sched.h> #include <linux/sched.h>

View file

@ -1,15 +1,7 @@
/* /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */
* linux/fs/nfsd/auth.c
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sunrpc/svc.h> #include "nfsd.h"
#include <linux/sunrpc/svcauth.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/export.h>
#include "auth.h" #include "auth.h"
int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)

View file

@ -1,6 +1,4 @@
/* /*
* include/linux/nfsd/cache.h
*
* Request reply cache. This was heavily inspired by the * Request reply cache. This was heavily inspired by the
* implementation in 4.3BSD/4.4BSD. * implementation in 4.3BSD/4.4BSD.
* *
@ -10,8 +8,7 @@
#ifndef NFSCACHE_H #ifndef NFSCACHE_H
#define NFSCACHE_H #define NFSCACHE_H
#include <linux/in.h> #include <linux/sunrpc/svc.h>
#include <linux/uio.h>
/* /*
* Representation of a reply cache entry. * Representation of a reply cache entry.

View file

@ -1,7 +1,5 @@
#define MSNFS /* HACK HACK */ #define MSNFS /* HACK HACK */
/* /*
* linux/fs/nfsd/export.c
*
* NFS exporting and validation. * NFS exporting and validation.
* *
* We maintain a list of clients, each of which has a list of * We maintain a list of clients, each of which has a list of
@ -14,29 +12,16 @@
* Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
*/ */
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/in.h>
#include <linux/seq_file.h>
#include <linux/syscalls.h>
#include <linux/rwsem.h>
#include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/mount.h>
#include <linux/hash.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/nfsfh.h>
#include <linux/nfsd/syscall.h> #include <linux/nfsd/syscall.h>
#include <linux/lockd/bind.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/gss_api.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include "nfsd.h"
#include "nfsfh.h"
#define NFSDDBG_FACILITY NFSDDBG_EXPORT #define NFSDDBG_FACILITY NFSDDBG_EXPORT
typedef struct auth_domain svc_client; typedef struct auth_domain svc_client;
@ -369,16 +354,25 @@ static struct svc_export *svc_export_update(struct svc_export *new,
struct svc_export *old); struct svc_export *old);
static struct svc_export *svc_export_lookup(struct svc_export *); static struct svc_export *svc_export_lookup(struct svc_export *);
static int check_export(struct inode *inode, int flags, unsigned char *uuid) static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
{ {
/* We currently export only dirs and regular files. /*
* This is what umountd does. * We currently export only dirs, regular files, and (for v4
* pseudoroot) symlinks.
*/ */
if (!S_ISDIR(inode->i_mode) && if (!S_ISDIR(inode->i_mode) &&
!S_ISLNK(inode->i_mode) &&
!S_ISREG(inode->i_mode)) !S_ISREG(inode->i_mode))
return -ENOTDIR; return -ENOTDIR;
/*
* Mountd should never pass down a writeable V4ROOT export, but,
* just to make sure:
*/
if (*flags & NFSEXP_V4ROOT)
*flags |= NFSEXP_READONLY;
/* There are two requirements on a filesystem to be exportable. /* There are two requirements on a filesystem to be exportable.
* 1: We must be able to identify the filesystem from a number. * 1: We must be able to identify the filesystem from a number.
* either a device number (so FS_REQUIRES_DEV needed) * either a device number (so FS_REQUIRES_DEV needed)
@ -387,7 +381,7 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
* This means that s_export_op must be set. * This means that s_export_op must be set.
*/ */
if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
!(flags & NFSEXP_FSID) && !(*flags & NFSEXP_FSID) &&
uuid == NULL) { uuid == NULL) {
dprintk("exp_export: export of non-dev fs without fsid\n"); dprintk("exp_export: export of non-dev fs without fsid\n");
return -EINVAL; return -EINVAL;
@ -602,7 +596,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
goto out4; goto out4;
} }
err = check_export(exp.ex_path.dentry->d_inode, exp.ex_flags, err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
exp.ex_uuid); exp.ex_uuid);
if (err) if (err)
goto out4; goto out4;
@ -1041,7 +1035,7 @@ exp_export(struct nfsctl_export *nxp)
goto finish; goto finish;
} }
err = check_export(path.dentry->d_inode, nxp->ex_flags, NULL); err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
if (err) goto finish; if (err) goto finish;
err = -ENOMEM; err = -ENOMEM;
@ -1320,6 +1314,23 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
return exp; return exp;
} }
static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
{
struct svc_export *exp;
u32 fsidv[2];
mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
/*
* We shouldn't have accepting an nfsv4 request at all if we
* don't have a pseudoexport!:
*/
if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT)
exp = ERR_PTR(-ESERVERFAULT);
return exp;
}
/* /*
* Called when we need the filehandle for the root of the pseudofs, * Called when we need the filehandle for the root of the pseudofs,
* for a given NFSv4 client. The root is defined to be the * for a given NFSv4 client. The root is defined to be the
@ -1330,11 +1341,8 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
{ {
struct svc_export *exp; struct svc_export *exp;
__be32 rv; __be32 rv;
u32 fsidv[2];
mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); exp = find_fsidzero_export(rqstp);
exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
if (IS_ERR(exp)) if (IS_ERR(exp))
return nfserrno(PTR_ERR(exp)); return nfserrno(PTR_ERR(exp));
rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
@ -1425,6 +1433,7 @@ static struct flags {
{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}}, { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
{ NFSEXP_V4ROOT, {"v4root", ""}},
#ifdef MSNFS #ifdef MSNFS
{ NFSEXP_MSNFS, {"msnfs", ""}}, { NFSEXP_MSNFS, {"msnfs", ""}},
#endif #endif

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/lockd.c
*
* This file contains all the stubs needed when communicating with lockd. * This file contains all the stubs needed when communicating with lockd.
* This level of indirection is necessary so we can run nfsd+lockd without * This level of indirection is necessary so we can run nfsd+lockd without
* requiring the nfs client to be compiled in/loaded, and vice versa. * requiring the nfs client to be compiled in/loaded, and vice versa.
@ -8,14 +6,10 @@
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mount.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/lockd/bind.h> #include <linux/lockd/bind.h>
#include "nfsd.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_LOCKD #define NFSDDBG_FACILITY NFSDDBG_LOCKD

View file

@ -1,19 +1,15 @@
/* /*
* linux/fs/nfsd/nfs2acl.c
*
* Process version 2 NFSACL requests. * Process version 2 NFSACL requests.
* *
* Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de> * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
*/ */
#include <linux/sunrpc/svc.h> #include "nfsd.h"
#include <linux/nfs.h> /* FIXME: nfsacl.h is a broken header */
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/xdr3.h>
#include <linux/posix_acl.h>
#include <linux/nfsacl.h> #include <linux/nfsacl.h>
#include "cache.h"
#include "xdr3.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC
#define RETURN_STATUS(st) { resp->status = (st); return (st); } #define RETURN_STATUS(st) { resp->status = (st); return (st); }
@ -217,6 +213,16 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
* XDR encode functions * XDR encode functions
*/ */
/*
* There must be an encoding function for void results so svc_process
* will work properly.
*/
int
nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
{
return xdr_ressize_check(rqstp, p);
}
/* GETACL */ /* GETACL */
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
struct nfsd3_getaclres *resp) struct nfsd3_getaclres *resp)
@ -308,7 +314,6 @@ static int nfsaclsvc_release_access(struct svc_rqst *rqstp, __be32 *p,
} }
#define nfsaclsvc_decode_voidargs NULL #define nfsaclsvc_decode_voidargs NULL
#define nfsaclsvc_encode_voidres NULL
#define nfsaclsvc_release_void NULL #define nfsaclsvc_release_void NULL
#define nfsd3_fhandleargs nfsd_fhandle #define nfsd3_fhandleargs nfsd_fhandle
#define nfsd3_attrstatres nfsd_attrstat #define nfsd3_attrstatres nfsd_attrstat
@ -346,5 +351,5 @@ struct svc_version nfsd_acl_version2 = {
.vs_proc = nfsd_acl_procedures2, .vs_proc = nfsd_acl_procedures2,
.vs_dispatch = nfsd_dispatch, .vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE, .vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 1, .vs_hidden = 0,
}; };

View file

@ -1,18 +1,15 @@
/* /*
* linux/fs/nfsd/nfs3acl.c
*
* Process version 3 NFSACL requests. * Process version 3 NFSACL requests.
* *
* Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de> * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
*/ */
#include <linux/sunrpc/svc.h> #include "nfsd.h"
#include <linux/nfs3.h> /* FIXME: nfsacl.h is a broken header */
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr3.h>
#include <linux/posix_acl.h>
#include <linux/nfsacl.h> #include <linux/nfsacl.h>
#include "cache.h"
#include "xdr3.h"
#include "vfs.h"
#define RETURN_STATUS(st) { resp->status = (st); return (st); } #define RETURN_STATUS(st) { resp->status = (st); return (st); }
@ -264,6 +261,6 @@ struct svc_version nfsd_acl_version3 = {
.vs_proc = nfsd_acl_procedures3, .vs_proc = nfsd_acl_procedures3,
.vs_dispatch = nfsd_dispatch, .vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE, .vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 1, .vs_hidden = 0,
}; };

View file

@ -1,30 +1,16 @@
/* /*
* linux/fs/nfsd/nfs3proc.c
*
* Process version 3 NFS requests. * Process version 3 NFS requests.
* *
* Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/linkage.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/major.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/sunrpc/svc.h> #include "cache.h"
#include <linux/nfsd/nfsd.h> #include "xdr3.h"
#include <linux/nfsd/cache.h> #include "vfs.h"
#include <linux/nfsd/xdr3.h>
#include <linux/nfs3.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfs3xdr.c
*
* XDR support for nfsd/protocol version 3. * XDR support for nfsd/protocol version 3.
* *
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
@ -8,19 +6,8 @@
* 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()! * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
*/ */
#include <linux/types.h>
#include <linux/time.h>
#include <linux/nfs3.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/mm.h> #include "xdr3.h"
#include <linux/vfs.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/xdr3.h>
#include "auth.h" #include "auth.h"
#define NFSDDBG_FACILITY NFSDDBG_XDR #define NFSDDBG_FACILITY NFSDDBG_XDR

View file

@ -1,6 +1,4 @@
/* /*
* fs/nfs4acl/acl.c
*
* Common NFSv4 ACL handling code. * Common NFSv4 ACL handling code.
* *
* Copyright (c) 2002, 2003 The Regents of the University of Michigan. * Copyright (c) 2002, 2003 The Regents of the University of Michigan.
@ -36,15 +34,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/posix_acl.h>
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h> #include <linux/nfs4_acl.h>
@ -389,7 +379,7 @@ sort_pacl(struct posix_acl *pacl)
sort_pacl_range(pacl, 1, i-1); sort_pacl_range(pacl, 1, i-1);
BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ); BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
j = i++; j = ++i;
while (pacl->a_entries[j].e_tag == ACL_GROUP) while (pacl->a_entries[j].e_tag == ACL_GROUP)
j++; j++;
sort_pacl_range(pacl, i, j-1); sort_pacl_range(pacl, i, j-1);

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfs4callback.c
*
* Copyright (c) 2001 The Regents of the University of Michigan. * Copyright (c) 2001 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
@ -33,22 +31,9 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <linux/module.h>
#include <linux/list.h>
#include <linux/inet.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svcsock.h> #include "nfsd.h"
#include <linux/nfsd/nfsd.h> #include "state.h"
#include <linux/nfsd/state.h>
#include <linux/sunrpc/sched.h>
#include <linux/nfs4.h>
#include <linux/sunrpc/xprtsock.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC

View file

@ -1,6 +1,4 @@
/* /*
* fs/nfsd/nfs4idmap.c
*
* Mapping of UID/GIDs to name and vice versa. * Mapping of UID/GIDs to name and vice versa.
* *
* Copyright (c) 2002, 2003 The Regents of the University of * Copyright (c) 2002, 2003 The Regents of the University of
@ -35,22 +33,9 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/sunrpc/cache.h>
#include <linux/nfsd_idmap.h> #include <linux/nfsd_idmap.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sunrpc/svcauth.h> #include <linux/sched.h>
/* /*
* Cache entry * Cache entry

View file

@ -1,6 +1,4 @@
/* /*
* fs/nfsd/nfs4proc.c
*
* Server-side procedures for NFSv4. * Server-side procedures for NFSv4.
* *
* Copyright (c) 2002 The Regents of the University of Michigan. * Copyright (c) 2002 The Regents of the University of Michigan.
@ -34,20 +32,11 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <linux/param.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/sunrpc/svc.h> #include "cache.h"
#include <linux/nfsd/nfsd.h> #include "xdr4.h"
#include <linux/nfsd/cache.h> #include "vfs.h"
#include <linux/nfs4.h>
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/nfs4_acl.h>
#include <linux/sunrpc/gss_api.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC
@ -170,7 +159,7 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
accmode |= NFSD_MAY_READ; accmode |= NFSD_MAY_READ;
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC); accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
if (open->op_share_deny & NFS4_SHARE_DENY_WRITE) if (open->op_share_deny & NFS4_SHARE_DENY_READ)
accmode |= NFSD_MAY_WRITE; accmode |= NFSD_MAY_WRITE;
status = fh_verify(rqstp, current_fh, S_IFREG, accmode); status = fh_verify(rqstp, current_fh, S_IFREG, accmode);

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfs4recover.c
*
* Copyright (c) 2004 The Regents of the University of Michigan. * Copyright (c) 2004 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
@ -33,20 +31,14 @@
* *
*/ */
#include <linux/err.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfs4.h>
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/param.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <asm/uaccess.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mount.h>
#include "nfsd.h"
#include "state.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfs4state.c
*
* Copyright (c) 2001 The Regents of the University of Michigan. * Copyright (c) 2001 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
@ -34,28 +32,14 @@
* *
*/ */
#include <linux/param.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mount.h>
#include <linux/workqueue.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/kthread.h>
#include <linux/nfs4.h>
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/mutex.h>
#include <linux/lockd/bind.h>
#include <linux/module.h>
#include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include "xdr4.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC #define NFSDDBG_FACILITY NFSDDBG_PROC
@ -477,13 +461,14 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
/* /*
* fchan holds the client values on input, and the server values on output * fchan holds the client values on input, and the server values on output
* sv_max_mesg is the maximum payload plus one page for overhead.
*/ */
static int init_forechannel_attrs(struct svc_rqst *rqstp, static int init_forechannel_attrs(struct svc_rqst *rqstp,
struct nfsd4_channel_attrs *session_fchan, struct nfsd4_channel_attrs *session_fchan,
struct nfsd4_channel_attrs *fchan) struct nfsd4_channel_attrs *fchan)
{ {
int status = 0; int status = 0;
__u32 maxcount = svc_max_payload(rqstp); __u32 maxcount = nfsd_serv->sv_max_mesg;
/* headerpadsz set to zero in encode routine */ /* headerpadsz set to zero in encode routine */
@ -523,6 +508,15 @@ free_session_slots(struct nfsd4_session *ses)
kfree(ses->se_slots[i]); kfree(ses->se_slots[i]);
} }
/*
* We don't actually need to cache the rpc and session headers, so we
* can allocate a little less for each slot:
*/
static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
{
return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
}
static int static int
alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
struct nfsd4_create_session *cses) struct nfsd4_create_session *cses)
@ -554,7 +548,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
memcpy(new, &tmp, sizeof(*new)); memcpy(new, &tmp, sizeof(*new));
/* allocate each struct nfsd4_slot and data cache in one piece */ /* allocate each struct nfsd4_slot and data cache in one piece */
cachesize = new->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; cachesize = slot_bytes(&new->se_fchannel);
for (i = 0; i < new->se_fchannel.maxreqs; i++) { for (i = 0; i < new->se_fchannel.maxreqs; i++) {
sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL); sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
if (!sp) if (!sp)
@ -628,10 +622,12 @@ void
free_session(struct kref *kref) free_session(struct kref *kref)
{ {
struct nfsd4_session *ses; struct nfsd4_session *ses;
int mem;
ses = container_of(kref, struct nfsd4_session, se_ref); ses = container_of(kref, struct nfsd4_session, se_ref);
spin_lock(&nfsd_drc_lock); spin_lock(&nfsd_drc_lock);
nfsd_drc_mem_used -= ses->se_fchannel.maxreqs * NFSD_SLOT_CACHE_SIZE; mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
nfsd_drc_mem_used -= mem;
spin_unlock(&nfsd_drc_lock); spin_unlock(&nfsd_drc_lock);
free_session_slots(ses); free_session_slots(ses);
kfree(ses); kfree(ses);
@ -2404,11 +2400,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
dprintk("NFSD: delegation stateid=(%08x/%08x/%08x/%08x)\n\n", dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
dp->dl_stateid.si_boot, STATEID_VAL(&dp->dl_stateid));
dp->dl_stateid.si_stateownerid,
dp->dl_stateid.si_fileid,
dp->dl_stateid.si_generation);
out: out:
if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
&& flag == NFS4_OPEN_DELEGATE_NONE && flag == NFS4_OPEN_DELEGATE_NONE
@ -2498,9 +2491,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
status = nfs_ok; status = nfs_ok;
dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n", dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, STATEID_VAL(&stp->st_stateid));
stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
out: out:
if (fp) if (fp)
put_nfs4_file(fp); put_nfs4_file(fp);
@ -2666,9 +2658,8 @@ STALE_STATEID(stateid_t *stateid)
{ {
if (time_after((unsigned long)boot_time, if (time_after((unsigned long)boot_time,
(unsigned long)stateid->si_boot)) { (unsigned long)stateid->si_boot)) {
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
stateid->si_boot, stateid->si_stateownerid, STATEID_VAL(stateid));
stateid->si_fileid, stateid->si_generation);
return 1; return 1;
} }
return 0; return 0;
@ -2680,9 +2671,8 @@ EXPIRED_STATEID(stateid_t *stateid)
if (time_before((unsigned long)boot_time, if (time_before((unsigned long)boot_time,
((unsigned long)stateid->si_boot)) && ((unsigned long)stateid->si_boot)) &&
time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) { time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n", dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
stateid->si_boot, stateid->si_stateownerid, STATEID_VAL(stateid));
stateid->si_fileid, stateid->si_generation);
return 1; return 1;
} }
return 0; return 0;
@ -2696,9 +2686,8 @@ stateid_error_map(stateid_t *stateid)
if (EXPIRED_STATEID(stateid)) if (EXPIRED_STATEID(stateid))
return nfserr_expired; return nfserr_expired;
dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n", dprintk("NFSD: bad stateid " STATEID_FMT "!\n",
stateid->si_boot, stateid->si_stateownerid, STATEID_VAL(stateid));
stateid->si_fileid, stateid->si_generation);
return nfserr_bad_stateid; return nfserr_bad_stateid;
} }
@ -2884,10 +2873,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
struct svc_fh *current_fh = &cstate->current_fh; struct svc_fh *current_fh = &cstate->current_fh;
__be32 status; __be32 status;
dprintk("NFSD: preprocess_seqid_op: seqid=%d " dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__,
"stateid = (%08x/%08x/%08x/%08x)\n", seqid, seqid, STATEID_VAL(stateid));
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
*stpp = NULL; *stpp = NULL;
*sopp = NULL; *sopp = NULL;
@ -3019,12 +3006,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
sop->so_confirmed = 1; sop->so_confirmed = 1;
update_stateid(&stp->st_stateid); update_stateid(&stp->st_stateid);
memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t)); memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d " dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
"stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid, __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stateid));
stp->st_stateid.si_boot,
stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid,
stp->st_stateid.si_generation);
nfsd4_create_clid_dir(sop->so_client); nfsd4_create_clid_dir(sop->so_client);
out: out:
@ -3283,9 +3266,8 @@ find_delegation_stateid(struct inode *ino, stateid_t *stid)
struct nfs4_file *fp; struct nfs4_file *fp;
struct nfs4_delegation *dl; struct nfs4_delegation *dl;
dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", dprintk("NFSD: %s: stateid=" STATEID_FMT "\n", __func__,
stid->si_boot, stid->si_stateownerid, STATEID_VAL(stid));
stid->si_fileid, stid->si_generation);
fp = find_file(ino); fp = find_file(ino);
if (!fp) if (!fp)

View file

@ -40,24 +40,16 @@
* at the end of nfs4svc_decode_compoundargs. * at the end of nfs4svc_decode_compoundargs.
*/ */
#include <linux/param.h>
#include <linux/smp.h>
#include <linux/fs.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/vfs.h> #include <linux/statfs.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/nfsd_idmap.h> #include <linux/nfsd_idmap.h>
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h> #include <linux/nfs4_acl.h>
#include <linux/sunrpc/gss_api.h>
#include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/svcauth_gss.h>
#include "xdr4.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_XDR #define NFSDDBG_FACILITY NFSDDBG_XDR
/* /*
@ -2204,11 +2196,14 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
* we will not follow the cross mount and will fill the attribtutes * we will not follow the cross mount and will fill the attribtutes
* directly from the mountpoint dentry. * directly from the mountpoint dentry.
*/ */
if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval)) if (nfsd_mountpoint(dentry, exp)) {
ignore_crossmnt = 1;
else if (d_mountpoint(dentry)) {
int err; int err;
if (!(exp->ex_flags & NFSEXP_V4ROOT)
&& !attributes_need_mount(cd->rd_bmval)) {
ignore_crossmnt = 1;
goto out_encode;
}
/* /*
* Why the heck aren't we just using nfsd_lookup?? * Why the heck aren't we just using nfsd_lookup??
* Different "."/".." handling? Something else? * Different "."/".." handling? Something else?
@ -2224,6 +2219,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
goto out_put; goto out_put;
} }
out_encode:
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
cd->rd_rqstp, ignore_crossmnt); cd->rd_rqstp, ignore_crossmnt);
out_put: out_put:

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfscache.c
*
* Request reply cache. This is currently a global cache, but this may * Request reply cache. This is currently a global cache, but this may
* change in the future and be a per-client cache. * change in the future and be a per-client cache.
* *
@ -10,16 +8,8 @@
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/kernel.h> #include "nfsd.h"
#include <linux/time.h> #include "cache.h"
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
/* Size of reply cache. Common values are: /* Size of reply cache. Common values are:
* 4.3BSD: 128 * 4.3BSD: 128

View file

@ -1,46 +1,20 @@
/* /*
* linux/fs/nfsd/nfsctl.c
*
* Syscall interface to knfsd. * Syscall interface to knfsd.
* *
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/module.h>
#include <linux/linkage.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/fcntl.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/inet.h>
#include <linux/string.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/nfs.h>
#include <linux/nfsd_idmap.h> #include <linux/nfsd_idmap.h>
#include <linux/lockd/bind.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/svcsock.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h> #include <linux/nfsd/syscall.h>
#include <linux/lockd/lockd.h> #include <linux/lockd/lockd.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <asm/uaccess.h> #include "nfsd.h"
#include <net/ipv6.h> #include "cache.h"
/* /*
* We have a single directory with 9 nodes in it. * We have a single directory with 9 nodes in it.
@ -55,6 +29,7 @@ enum {
NFSD_Getfd, NFSD_Getfd,
NFSD_Getfs, NFSD_Getfs,
NFSD_List, NFSD_List,
NFSD_Export_features,
NFSD_Fh, NFSD_Fh,
NFSD_FO_UnlockIP, NFSD_FO_UnlockIP,
NFSD_FO_UnlockFS, NFSD_FO_UnlockFS,
@ -173,6 +148,24 @@ static const struct file_operations exports_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int export_features_show(struct seq_file *m, void *v)
{
seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
return 0;
}
static int export_features_open(struct inode *inode, struct file *file)
{
return single_open(file, export_features_show, NULL);
}
static struct file_operations export_features_operations = {
.open = export_features_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
@ -1330,6 +1323,8 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_Export_features] = {"export_features",
&export_features_operations, S_IRUGO},
[NFSD_FO_UnlockIP] = {"unlock_ip", [NFSD_FO_UnlockIP] = {"unlock_ip",
&transaction_ops, S_IWUSR|S_IRUSR}, &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_FO_UnlockFS] = {"unlock_filesystem", [NFSD_FO_UnlockFS] = {"unlock_filesystem",

View file

@ -1,6 +1,4 @@
/* /*
* linux/include/linux/nfsd/nfsd.h
*
* Hodge-podge collection of knfsd-related stuff. * Hodge-podge collection of knfsd-related stuff.
* I will sort this out later. * I will sort this out later.
* *
@ -11,13 +9,9 @@
#define LINUX_NFSD_NFSD_H #define LINUX_NFSD_NFSD_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/unistd.h>
#include <linux/fs.h>
#include <linux/posix_acl.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/nfsd/debug.h> #include <linux/nfsd/debug.h>
#include <linux/nfsd/nfsfh.h>
#include <linux/nfsd/export.h> #include <linux/nfsd/export.h>
#include <linux/nfsd/stats.h> #include <linux/nfsd/stats.h>
/* /*
@ -25,30 +19,10 @@
*/ */
#define NFSD_SUPPORTED_MINOR_VERSION 1 #define NFSD_SUPPORTED_MINOR_VERSION 1
/*
* Flags for nfsd_permission
*/
#define NFSD_MAY_NOP 0
#define NFSD_MAY_EXEC 1 /* == MAY_EXEC */
#define NFSD_MAY_WRITE 2 /* == MAY_WRITE */
#define NFSD_MAY_READ 4 /* == MAY_READ */
#define NFSD_MAY_SATTR 8
#define NFSD_MAY_TRUNC 16
#define NFSD_MAY_LOCK 32
#define NFSD_MAY_OWNER_OVERRIDE 64
#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
/*
* Callback function for readdir
*/
struct readdir_cd { struct readdir_cd {
__be32 err; /* 0, nfserr, or nfserr_eof */ __be32 err; /* 0, nfserr, or nfserr_eof */
}; };
typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
extern struct svc_program nfsd_program; extern struct svc_program nfsd_program;
extern struct svc_version nfsd_version2, nfsd_version3, extern struct svc_version nfsd_version2, nfsd_version3,
@ -73,69 +47,6 @@ int nfsd_nrpools(void);
int nfsd_get_nrthreads(int n, int *); int nfsd_get_nrthreads(int n, int *);
int nfsd_set_nrthreads(int n, int *); int nfsd_set_nrthreads(int n, int *);
/* nfsd/vfs.c */
int fh_lock_parent(struct svc_fh *, struct dentry *);
int nfsd_racache_init(int);
void nfsd_racache_shutdown(void);
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
struct svc_export **expp);
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
const char *, unsigned int, struct svc_fh *);
__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
const char *, unsigned int,
struct svc_export **, struct dentry **);
__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
struct iattr *, int, time_t);
#ifdef CONFIG_NFSD_V4
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
struct nfs4_acl *);
int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
#endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
int type, dev_t rdev, struct svc_fh *res);
#ifdef CONFIG_NFSD_V3
__be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
__be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
struct svc_fh *res, int createmode,
u32 *verifier, int *truncp, int *created);
__be32 nfsd_commit(struct svc_rqst *, struct svc_fh *,
loff_t, unsigned long);
#endif /* CONFIG_NFSD_V3 */
__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int,
int, struct file **);
void nfsd_close(struct file *);
__be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
loff_t, struct kvec *, int, unsigned long *);
__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
loff_t, struct kvec *,int, unsigned long *, int *);
__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *,
char *, int *);
__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
char *name, int len, char *path, int plen,
struct svc_fh *res, struct iattr *);
__be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
char *, int, struct svc_fh *);
__be32 nfsd_rename(struct svc_rqst *,
struct svc_fh *, char *, int,
struct svc_fh *, char *, int);
__be32 nfsd_remove(struct svc_rqst *,
struct svc_fh *, char *, int);
__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
char *name, int len);
int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
unsigned long size);
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
loff_t *, struct readdir_cd *, filldir_t);
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct kstatfs *, int access);
int nfsd_notify_change(struct inode *, struct iattr *);
__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
struct dentry *, int);
int nfsd_sync_dir(struct dentry *dp);
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
#ifdef CONFIG_NFSD_V2_ACL #ifdef CONFIG_NFSD_V2_ACL
extern struct svc_version nfsd_acl_version2; extern struct svc_version nfsd_acl_version2;
@ -147,8 +58,6 @@ extern struct svc_version nfsd_acl_version3;
#else #else
#define nfsd_acl_version3 NULL #define nfsd_acl_version3 NULL
#endif #endif
struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
#endif #endif
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
@ -159,6 +68,11 @@ int nfsd_create_serv(void);
extern int nfsd_max_blksize; extern int nfsd_max_blksize;
static inline int nfsd_v4client(struct svc_rqst *rq)
{
return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
}
/* /*
* NFSv4 State * NFSv4 State
*/ */

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfsfh.c
*
* NFS server file handle treatment. * NFS server file handle treatment.
* *
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
@ -9,19 +7,11 @@
* ... and again Southern-Winter 2001 to support export_operations * ... and again Southern-Winter 2001 to support export_operations
*/ */
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/dcache.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/mount.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/svcauth_gss.h>
#include <linux/nfsd/nfsd.h> #include "nfsd.h"
#include "vfs.h"
#include "auth.h" #include "auth.h"
#define NFSDDBG_FACILITY NFSDDBG_FH #define NFSDDBG_FACILITY NFSDDBG_FH
@ -96,8 +86,10 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
struct svc_export *exp) struct svc_export *exp)
{ {
int flags = nfsexp_flags(rqstp, exp);
/* Check if the request originated from a secure port. */ /* Check if the request originated from a secure port. */
if (!rqstp->rq_secure && EX_SECURE(exp)) { if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
dprintk(KERN_WARNING dprintk(KERN_WARNING
"nfsd: request from insecure port %s!\n", "nfsd: request from insecure port %s!\n",
@ -109,6 +101,36 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
return nfserrno(nfsd_setuser(rqstp, exp)); return nfserrno(nfsd_setuser(rqstp, exp));
} }
static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
struct dentry *dentry, struct svc_export *exp)
{
if (!(exp->ex_flags & NFSEXP_V4ROOT))
return nfs_ok;
/*
* v2/v3 clients have no need for the V4ROOT export--they use
* the mount protocl instead; also, further V4ROOT checks may be
* in v4-specific code, in which case v2/v3 clients could bypass
* them.
*/
if (!nfsd_v4client(rqstp))
return nfserr_stale;
/*
* We're exposing only the directories and symlinks that have to be
* traversed on the way to real exports:
*/
if (unlikely(!S_ISDIR(dentry->d_inode->i_mode) &&
!S_ISLNK(dentry->d_inode->i_mode)))
return nfserr_stale;
/*
* A pseudoroot export gives permission to access only one
* single directory; the kernel has to make another upcall
* before granting access to anything else under it:
*/
if (unlikely(dentry != exp->ex_path.dentry))
return nfserr_stale;
return nfs_ok;
}
/* /*
* Use the given filehandle to look up the corresponding export and * Use the given filehandle to look up the corresponding export and
* dentry. On success, the results are used to set fh_export and * dentry. On success, the results are used to set fh_export and
@ -232,14 +254,6 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
goto out; goto out;
} }
if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) {
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error) {
dput(dentry);
goto out;
}
}
if (S_ISDIR(dentry->d_inode->i_mode) && if (S_ISDIR(dentry->d_inode->i_mode) &&
(dentry->d_flags & DCACHE_DISCONNECTED)) { (dentry->d_flags & DCACHE_DISCONNECTED)) {
printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n", printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
@ -294,28 +308,32 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
error = nfsd_set_fh_dentry(rqstp, fhp); error = nfsd_set_fh_dentry(rqstp, fhp);
if (error) if (error)
goto out; goto out;
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
} else {
/*
* just rechecking permissions
* (e.g. nfsproc_create calls fh_verify, then nfsd_create
* does as well)
*/
dprintk("nfsd: fh_verify - just checking\n");
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
/*
* Set user creds for this exportpoint; necessary even
* in the "just checking" case because this may be a
* filehandle that was created by fh_compose, and that
* is about to be used in another nfsv4 compound
* operation.
*/
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
} }
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
/*
* We still have to do all these permission checks, even when
* fh_dentry is already set:
* - fh_verify may be called multiple times with different
* "access" arguments (e.g. nfsd_proc_create calls
* fh_verify(...,NFSD_MAY_EXEC) first, then later (in
* nfsd_create) calls fh_verify(...,NFSD_MAY_CREATE).
* - in the NFSv4 case, the filehandle may have been filled
* in by fh_compose, and given a dentry, but further
* compound operations performed with that filehandle
* still need permissions checks. In the worst case, a
* mountpoint crossing may have changed the export
* options, and we may now need to use a different uid
* (for example, if different id-squashing options are in
* effect on the new filesystem).
*/
error = check_pseudo_root(rqstp, dentry, exp);
if (error)
goto out;
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
if (error) if (error)

208
fs/nfsd/nfsfh.h Normal file
View file

@ -0,0 +1,208 @@
/* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */
#ifndef _LINUX_NFSD_FH_INT_H
#define _LINUX_NFSD_FH_INT_H
#include <linux/nfsd/nfsfh.h>
enum nfsd_fsid {
FSID_DEV = 0,
FSID_NUM,
FSID_MAJOR_MINOR,
FSID_ENCODE_DEV,
FSID_UUID4_INUM,
FSID_UUID8,
FSID_UUID16,
FSID_UUID16_INUM,
};
enum fsid_source {
FSIDSOURCE_DEV,
FSIDSOURCE_FSID,
FSIDSOURCE_UUID,
};
extern enum fsid_source fsid_source(struct svc_fh *fhp);
/* This might look a little large to "inline" but in all calls except
* one, 'vers' is constant so moste of the function disappears.
*/
static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
u32 fsid, unsigned char *uuid)
{
u32 *up;
switch(vers) {
case FSID_DEV:
fsidv[0] = htonl((MAJOR(dev)<<16) |
MINOR(dev));
fsidv[1] = ino_t_to_u32(ino);
break;
case FSID_NUM:
fsidv[0] = fsid;
break;
case FSID_MAJOR_MINOR:
fsidv[0] = htonl(MAJOR(dev));
fsidv[1] = htonl(MINOR(dev));
fsidv[2] = ino_t_to_u32(ino);
break;
case FSID_ENCODE_DEV:
fsidv[0] = new_encode_dev(dev);
fsidv[1] = ino_t_to_u32(ino);
break;
case FSID_UUID4_INUM:
/* 4 byte fsid and inode number */
up = (u32*)uuid;
fsidv[0] = ino_t_to_u32(ino);
fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
break;
case FSID_UUID8:
/* 8 byte fsid */
up = (u32*)uuid;
fsidv[0] = up[0] ^ up[2];
fsidv[1] = up[1] ^ up[3];
break;
case FSID_UUID16:
/* 16 byte fsid - NFSv3+ only */
memcpy(fsidv, uuid, 16);
break;
case FSID_UUID16_INUM:
/* 8 byte inode and 16 byte fsid */
*(u64*)fsidv = (u64)ino;
memcpy(fsidv+2, uuid, 16);
break;
default: BUG();
}
}
static inline int key_len(int type)
{
switch(type) {
case FSID_DEV: return 8;
case FSID_NUM: return 4;
case FSID_MAJOR_MINOR: return 12;
case FSID_ENCODE_DEV: return 8;
case FSID_UUID4_INUM: return 8;
case FSID_UUID8: return 8;
case FSID_UUID16: return 16;
case FSID_UUID16_INUM: return 24;
default: return 0;
}
}
/*
* Shorthand for dprintk()'s
*/
extern char * SVCFH_fmt(struct svc_fh *fhp);
/*
* Function prototypes
*/
__be32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
__be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
__be32 fh_update(struct svc_fh *);
void fh_put(struct svc_fh *);
static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
WARN_ON(src->fh_dentry || src->fh_locked);
*dst = *src;
return dst;
}
static inline void
fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
{
dst->fh_size = src->fh_size;
memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
}
static __inline__ struct svc_fh *
fh_init(struct svc_fh *fhp, int maxsize)
{
memset(fhp, 0, sizeof(*fhp));
fhp->fh_maxsize = maxsize;
return fhp;
}
#ifdef CONFIG_NFSD_V3
/*
* Fill in the pre_op attr for the wcc data
*/
static inline void
fill_pre_wcc(struct svc_fh *fhp)
{
struct inode *inode;
inode = fhp->fh_dentry->d_inode;
if (!fhp->fh_pre_saved) {
fhp->fh_pre_mtime = inode->i_mtime;
fhp->fh_pre_ctime = inode->i_ctime;
fhp->fh_pre_size = inode->i_size;
fhp->fh_pre_change = inode->i_version;
fhp->fh_pre_saved = 1;
}
}
extern void fill_post_wcc(struct svc_fh *);
#else
#define fill_pre_wcc(ignored)
#define fill_post_wcc(notused)
#endif /* CONFIG_NFSD_V3 */
/*
* Lock a file handle/inode
* NOTE: both fh_lock and fh_unlock are done "by hand" in
* vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
* so, any changes here should be reflected there.
*/
static inline void
fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
{
struct dentry *dentry = fhp->fh_dentry;
struct inode *inode;
BUG_ON(!dentry);
if (fhp->fh_locked) {
printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
return;
}
inode = dentry->d_inode;
mutex_lock_nested(&inode->i_mutex, subclass);
fill_pre_wcc(fhp);
fhp->fh_locked = 1;
}
static inline void
fh_lock(struct svc_fh *fhp)
{
fh_lock_nested(fhp, I_MUTEX_NORMAL);
}
/*
* Unlock a file handle/inode
*/
static inline void
fh_unlock(struct svc_fh *fhp)
{
BUG_ON(!fhp->fh_dentry);
if (fhp->fh_locked) {
fill_post_wcc(fhp);
mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
fhp->fh_locked = 0;
}
}
#endif /* _LINUX_NFSD_FH_INT_H */

View file

@ -1,29 +1,14 @@
/* /*
* nfsproc2.c Process version 2 NFS requests.
* linux/fs/nfsd/nfs2proc.c
*
* Process version 2 NFS requests. * Process version 2 NFS requests.
* *
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/linkage.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/sunrpc/clnt.h> #include "cache.h"
#include <linux/sunrpc/svc.h> #include "xdr.h"
#include <linux/nfsd/nfsd.h> #include "vfs.h"
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
typedef struct svc_rqst svc_rqst; typedef struct svc_rqst svc_rqst;
typedef struct svc_buf svc_buf; typedef struct svc_buf svc_buf;
@ -758,6 +743,7 @@ nfserrno (int errno)
{ nfserr_io, -ETXTBSY }, { nfserr_io, -ETXTBSY },
{ nfserr_notsupp, -EOPNOTSUPP }, { nfserr_notsupp, -EOPNOTSUPP },
{ nfserr_toosmall, -ETOOSMALL }, { nfserr_toosmall, -ETOOSMALL },
{ nfserr_serverfault, -ESERVERFAULT },
}; };
int i; int i;

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/nfssvc.c
*
* Central processing for nfsd. * Central processing for nfsd.
* *
* Authors: Olaf Kirch (okir@monad.swb.de) * Authors: Olaf Kirch (okir@monad.swb.de)
@ -8,33 +6,19 @@
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/nfs.h>
#include <linux/in.h>
#include <linux/uio.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/fs_struct.h> #include <linux/fs_struct.h>
#include <linux/kthread.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h> #include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/cache.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/stats.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/syscall.h>
#include <linux/lockd/bind.h> #include <linux/lockd/bind.h>
#include <linux/nfsacl.h> #include <linux/nfsacl.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include "nfsd.h"
#include "cache.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_SVC #define NFSDDBG_FACILITY NFSDDBG_SVC

View file

@ -1,20 +1,10 @@
/* /*
* linux/fs/nfsd/nfsxdr.c
*
* XDR support for nfsd * XDR support for nfsd
* *
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/types.h> #include "xdr.h"
#include <linux/time.h>
#include <linux/nfs.h>
#include <linux/vfs.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/xdr.h>
#include <linux/mm.h>
#include "auth.h" #include "auth.h"
#define NFSDDBG_FACILITY NFSDDBG_XDR #define NFSDDBG_FACILITY NFSDDBG_XDR

View file

@ -1,6 +1,4 @@
/* /*
* linux/include/nfsd/state.h
*
* Copyright (c) 2001 The Regents of the University of Michigan. * Copyright (c) 2001 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
@ -37,9 +35,8 @@
#ifndef _NFSD4_STATE_H #ifndef _NFSD4_STATE_H
#define _NFSD4_STATE_H #define _NFSD4_STATE_H
#include <linux/list.h> #include <linux/nfsd/nfsfh.h>
#include <linux/kref.h> #include "nfsfh.h"
#include <linux/sunrpc/clnt.h>
typedef struct { typedef struct {
u32 cl_boot; u32 cl_boot;
@ -60,6 +57,13 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid #define si_stateownerid si_opaque.so_stateownerid
#define si_fileid si_opaque.so_fileid #define si_fileid si_opaque.so_fileid
#define STATEID_FMT "(%08x/%08x/%08x/%08x)"
#define STATEID_VAL(s) \
(s)->si_boot, \
(s)->si_stateownerid, \
(s)->si_fileid, \
(s)->si_generation
struct nfsd4_cb_sequence { struct nfsd4_cb_sequence {
/* args/res */ /* args/res */
u32 cbs_minorversion; u32 cbs_minorversion;

View file

@ -1,6 +1,4 @@
/* /*
* linux/fs/nfsd/stats.c
*
* procfs-based user access to knfsd statistics * procfs-based user access to knfsd statistics
* *
* /proc/net/rpc/nfsd * /proc/net/rpc/nfsd
@ -23,18 +21,13 @@
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/stats.h> #include <linux/sunrpc/stats.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/stats.h> #include <linux/nfsd/stats.h>
#include "nfsd.h"
struct nfsd_stats nfsdstats; struct nfsd_stats nfsdstats;
struct svc_stat nfsd_svcstats = { struct svc_stat nfsd_svcstats = {
.program = &nfsd_program, .program = &nfsd_program,

View file

@ -1,7 +1,5 @@
#define MSNFS /* HACK HACK */ #define MSNFS /* HACK HACK */
/* /*
* linux/fs/nfsd/vfs.c
*
* File operations used by nfsd. Some of these have been ripped from * File operations used by nfsd. Some of these have been ripped from
* other parts of the kernel because they weren't exported, others * other parts of the kernel because they weren't exported, others
* are partial duplicates with added or changed functionality. * are partial duplicates with added or changed functionality.
@ -16,49 +14,32 @@
* Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp> * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp>
*/ */
#include <linux/string.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mount.h>
#include <linux/major.h>
#include <linux/splice.h> #include <linux/splice.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/net.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/in.h>
#include <linux/module.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/vfs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#ifdef CONFIG_NFSD_V3
#include <linux/nfs3.h>
#include <linux/nfsd/xdr3.h>
#endif /* CONFIG_NFSD_V3 */
#include <linux/nfsd/nfsfh.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h> #include <linux/posix_acl_xattr.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#ifdef CONFIG_NFSD_V4
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
#include <linux/nfsd_idmap.h>
#include <linux/security.h>
#endif /* CONFIG_NFSD_V4 */
#include <linux/jhash.h> #include <linux/jhash.h>
#include <linux/ima.h> #include <linux/ima.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#ifdef CONFIG_NFSD_V3
#include "xdr3.h"
#endif /* CONFIG_NFSD_V3 */
#ifdef CONFIG_NFSD_V4
#include <linux/nfs4_acl.h>
#include <linux/nfsd_idmap.h>
#endif /* CONFIG_NFSD_V4 */
#include "nfsd.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_FILEOP #define NFSDDBG_FACILITY NFSDDBG_FILEOP
@ -89,12 +70,6 @@ struct raparm_hbucket {
#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1) #define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE]; static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
static inline int
nfsd_v4client(struct svc_rqst *rq)
{
return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
}
/* /*
* Called from nfsd_lookup and encode_dirent. Check if we have crossed * Called from nfsd_lookup and encode_dirent. Check if we have crossed
* a mount point. * a mount point.
@ -116,8 +91,16 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
exp2 = rqst_exp_get_by_name(rqstp, &path); exp2 = rqst_exp_get_by_name(rqstp, &path);
if (IS_ERR(exp2)) { if (IS_ERR(exp2)) {
if (PTR_ERR(exp2) != -ENOENT) err = PTR_ERR(exp2);
err = PTR_ERR(exp2); /*
* We normally allow NFS clients to continue
* "underneath" a mountpoint that is not exported.
* The exception is V4ROOT, where no traversal is ever
* allowed without an explicit export of the new
* directory.
*/
if (err == -ENOENT && !(exp->ex_flags & NFSEXP_V4ROOT))
err = 0;
path_put(&path); path_put(&path);
goto out; goto out;
} }
@ -141,6 +124,53 @@ out:
return err; return err;
} }
static void follow_to_parent(struct path *path)
{
struct dentry *dp;
while (path->dentry == path->mnt->mnt_root && follow_up(path))
;
dp = dget_parent(path->dentry);
dput(path->dentry);
path->dentry = dp;
}
static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp)
{
struct svc_export *exp2;
struct path path = {.mnt = mntget((*exp)->ex_path.mnt),
.dentry = dget(dparent)};
follow_to_parent(&path);
exp2 = rqst_exp_parent(rqstp, &path);
if (PTR_ERR(exp2) == -ENOENT) {
*dentryp = dget(dparent);
} else if (IS_ERR(exp2)) {
path_put(&path);
return PTR_ERR(exp2);
} else {
*dentryp = dget(path.dentry);
exp_put(*exp);
*exp = exp2;
}
path_put(&path);
return 0;
}
/*
* For nfsd purposes, we treat V4ROOT exports as though there was an
* export at *every* directory.
*/
int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
{
if (d_mountpoint(dentry))
return 1;
if (!(exp->ex_flags & NFSEXP_V4ROOT))
return 0;
return dentry->d_inode != NULL;
}
__be32 __be32
nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
const char *name, unsigned int len, const char *name, unsigned int len,
@ -169,35 +199,13 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = dget(dparent); dentry = dget(dparent);
else if (dparent != exp->ex_path.dentry) else if (dparent != exp->ex_path.dentry)
dentry = dget_parent(dparent); dentry = dget_parent(dparent);
else if (!EX_NOHIDE(exp)) else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp))
dentry = dget(dparent); /* .. == . just like at / */ dentry = dget(dparent); /* .. == . just like at / */
else { else {
/* checking mountpoint crossing is very different when stepping up */ /* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL; host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry);
struct dentry *dp; if (host_err)
struct path path = {.mnt = mntget(exp->ex_path.mnt),
.dentry = dget(dparent)};
while (path.dentry == path.mnt->mnt_root &&
follow_up(&path))
;
dp = dget_parent(path.dentry);
dput(path.dentry);
path.dentry = dp;
exp2 = rqst_exp_parent(rqstp, &path);
if (PTR_ERR(exp2) == -ENOENT) {
dentry = dget(dparent);
} else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2);
path_put(&path);
goto out_nfserr; goto out_nfserr;
} else {
dentry = dget(path.dentry);
exp_put(exp);
exp = exp2;
}
path_put(&path);
} }
} else { } else {
fh_lock(fhp); fh_lock(fhp);
@ -208,7 +216,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
/* /*
* check if we have crossed a mount point ... * check if we have crossed a mount point ...
*/ */
if (d_mountpoint(dentry)) { if (nfsd_mountpoint(dentry, exp)) {
if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
dput(dentry); dput(dentry);
goto out_nfserr; goto out_nfserr;

101
fs/nfsd/vfs.h Normal file
View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef LINUX_NFSD_VFS_H
#define LINUX_NFSD_VFS_H
#include "nfsfh.h"
/*
* Flags for nfsd_permission
*/
#define NFSD_MAY_NOP 0
#define NFSD_MAY_EXEC 1 /* == MAY_EXEC */
#define NFSD_MAY_WRITE 2 /* == MAY_WRITE */
#define NFSD_MAY_READ 4 /* == MAY_READ */
#define NFSD_MAY_SATTR 8
#define NFSD_MAY_TRUNC 16
#define NFSD_MAY_LOCK 32
#define NFSD_MAY_OWNER_OVERRIDE 64
#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
/*
* Callback function for readdir
*/
typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
/* nfsd/vfs.c */
int fh_lock_parent(struct svc_fh *, struct dentry *);
int nfsd_racache_init(int);
void nfsd_racache_shutdown(void);
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
struct svc_export **expp);
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
const char *, unsigned int, struct svc_fh *);
__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
const char *, unsigned int,
struct svc_export **, struct dentry **);
__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
struct iattr *, int, time_t);
int nfsd_mountpoint(struct dentry *, struct svc_export *);
#ifdef CONFIG_NFSD_V4
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
struct nfs4_acl *);
int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
#endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
int type, dev_t rdev, struct svc_fh *res);
#ifdef CONFIG_NFSD_V3
__be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
__be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
struct svc_fh *res, int createmode,
u32 *verifier, int *truncp, int *created);
__be32 nfsd_commit(struct svc_rqst *, struct svc_fh *,
loff_t, unsigned long);
#endif /* CONFIG_NFSD_V3 */
__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int,
int, struct file **);
void nfsd_close(struct file *);
__be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
loff_t, struct kvec *, int, unsigned long *);
__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
loff_t, struct kvec *,int, unsigned long *, int *);
__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *,
char *, int *);
__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
char *name, int len, char *path, int plen,
struct svc_fh *res, struct iattr *);
__be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
char *, int, struct svc_fh *);
__be32 nfsd_rename(struct svc_rqst *,
struct svc_fh *, char *, int,
struct svc_fh *, char *, int);
__be32 nfsd_remove(struct svc_rqst *,
struct svc_fh *, char *, int);
__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
char *name, int len);
int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
unsigned long size);
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
loff_t *, struct readdir_cd *, filldir_t);
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct kstatfs *, int access);
int nfsd_notify_change(struct inode *, struct iattr *);
__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
struct dentry *, int);
int nfsd_sync_dir(struct dentry *dp);
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
#endif
#endif /* LINUX_NFSD_VFS_H */

View file

@ -1,15 +1,11 @@
/* /* XDR types for nfsd. This is mainly a typing exercise. */
* linux/include/linux/nfsd/xdr.h
*
* XDR types for nfsd. This is mainly a typing exercise.
*/
#ifndef LINUX_NFSD_H #ifndef LINUX_NFSD_H
#define LINUX_NFSD_H #define LINUX_NFSD_H
#include <linux/fs.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/nfs.h> #include "nfsd.h"
#include "nfsfh.h"
struct nfsd_fhandle { struct nfsd_fhandle {
struct svc_fh fh; struct svc_fh fh;

View file

@ -1,6 +1,4 @@
/* /*
* linux/include/linux/nfsd/xdr3.h
*
* XDR types for NFSv3 in nfsd. * XDR types for NFSv3 in nfsd.
* *
* Copyright (C) 1996-1998, Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1996-1998, Olaf Kirch <okir@monad.swb.de>
@ -9,7 +7,7 @@
#ifndef _LINUX_NFSD_XDR3_H #ifndef _LINUX_NFSD_XDR3_H
#define _LINUX_NFSD_XDR3_H #define _LINUX_NFSD_XDR3_H
#include <linux/nfsd/xdr.h> #include "xdr.h"
struct nfsd3_sattrargs { struct nfsd3_sattrargs {
struct svc_fh fh; struct svc_fh fh;

View file

@ -1,6 +1,4 @@
/* /*
* include/linux/nfsd/xdr4.h
*
* Server-side types for NFSv4. * Server-side types for NFSv4.
* *
* Copyright (c) 2002 The Regents of the University of Michigan. * Copyright (c) 2002 The Regents of the University of Michigan.
@ -39,7 +37,8 @@
#ifndef _LINUX_NFSD_XDR4_H #ifndef _LINUX_NFSD_XDR4_H
#define _LINUX_NFSD_XDR4_H #define _LINUX_NFSD_XDR4_H
#include <linux/nfs4.h> #include "state.h"
#include "nfsd.h"
#define NFSD4_MAX_TAGLEN 128 #define NFSD4_MAX_TAGLEN 128
#define XDR_LEN(n) (((n) + 3) & ~3) #define XDR_LEN(n) (((n) + 3) & ~3)

View file

@ -97,7 +97,7 @@ struct fid {
* @get_name: find the name for a given inode in a given directory * @get_name: find the name for a given inode in a given directory
* @get_parent: find the parent of a given directory * @get_parent: find the parent of a given directory
* *
* See Documentation/filesystems/Exporting for details on how to use * See Documentation/filesystems/nfs/Exporting for details on how to use
* this interface correctly. * this interface correctly.
* *
* encode_fh: * encode_fh:

View file

@ -2,6 +2,7 @@
#define _LINUX_NFS_XDR_H #define _LINUX_NFS_XDR_H
#include <linux/nfsacl.h> #include <linux/nfsacl.h>
#include <linux/nfs3.h>
/* /*
* To change the maximum rsize and wsize supported by the NFS client, adjust * To change the maximum rsize and wsize supported by the NFS client, adjust

View file

@ -29,6 +29,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
#include <linux/sunrpc/xdr.h>
/* Maximum number of ACL entries over NFS */ /* Maximum number of ACL entries over NFS */
#define NFS_ACL_MAX_ENTRIES 1024 #define NFS_ACL_MAX_ENTRIES 1024

View file

@ -12,7 +12,7 @@
# include <linux/types.h> # include <linux/types.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
# include <linux/in.h> # include <linux/nfsd/nfsfh.h>
#endif #endif
/* /*
@ -39,11 +39,23 @@
#define NFSEXP_FSID 0x2000 #define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000 #define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
#define NFSEXP_ALLFLAGS 0xFE3F /*
* The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
* clients, and only to the single directory that is the root of the
* export; further lookup and readdir operations are treated as if every
* subdirectory was a mountpoint, and ignored if they are not themselves
* exported. This is used by nfsd and mountd to construct the NFSv4
* pseudofilesystem, which provides access only to paths leading to each
* exported filesystem.
*/
#define NFSEXP_V4ROOT 0x10000
/* All flags that we claim to support. (Note we don't support NOACL.) */
#define NFSEXP_ALLFLAGS 0x17E3F
/* The flags that may vary depending on security flavor: */ /* The flags that may vary depending on security flavor: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ #define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
| NFSEXP_ALLSQUASH) | NFSEXP_ALLSQUASH \
| NFSEXP_INSECURE_PORT)
#ifdef __KERNEL__ #ifdef __KERNEL__
@ -108,7 +120,6 @@ struct svc_expkey {
struct path ek_path; struct path ek_path;
}; };
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) #define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) #define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)

View file

@ -16,11 +16,9 @@
# include <linux/types.h> # include <linux/types.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
# include <linux/string.h> # include <linux/sunrpc/svc.h>
# include <linux/fs.h>
#endif #endif
#include <linux/nfsd/const.h> #include <linux/nfsd/const.h>
#include <linux/nfsd/debug.h>
/* /*
* This is the old "dentry style" Linux NFSv2 file handle. * This is the old "dentry style" Linux NFSv2 file handle.
@ -164,208 +162,6 @@ typedef struct svc_fh {
} svc_fh; } svc_fh;
enum nfsd_fsid {
FSID_DEV = 0,
FSID_NUM,
FSID_MAJOR_MINOR,
FSID_ENCODE_DEV,
FSID_UUID4_INUM,
FSID_UUID8,
FSID_UUID16,
FSID_UUID16_INUM,
};
enum fsid_source {
FSIDSOURCE_DEV,
FSIDSOURCE_FSID,
FSIDSOURCE_UUID,
};
extern enum fsid_source fsid_source(struct svc_fh *fhp);
/* This might look a little large to "inline" but in all calls except
* one, 'vers' is constant so moste of the function disappears.
*/
static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
u32 fsid, unsigned char *uuid)
{
u32 *up;
switch(vers) {
case FSID_DEV:
fsidv[0] = htonl((MAJOR(dev)<<16) |
MINOR(dev));
fsidv[1] = ino_t_to_u32(ino);
break;
case FSID_NUM:
fsidv[0] = fsid;
break;
case FSID_MAJOR_MINOR:
fsidv[0] = htonl(MAJOR(dev));
fsidv[1] = htonl(MINOR(dev));
fsidv[2] = ino_t_to_u32(ino);
break;
case FSID_ENCODE_DEV:
fsidv[0] = new_encode_dev(dev);
fsidv[1] = ino_t_to_u32(ino);
break;
case FSID_UUID4_INUM:
/* 4 byte fsid and inode number */
up = (u32*)uuid;
fsidv[0] = ino_t_to_u32(ino);
fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
break;
case FSID_UUID8:
/* 8 byte fsid */
up = (u32*)uuid;
fsidv[0] = up[0] ^ up[2];
fsidv[1] = up[1] ^ up[3];
break;
case FSID_UUID16:
/* 16 byte fsid - NFSv3+ only */
memcpy(fsidv, uuid, 16);
break;
case FSID_UUID16_INUM:
/* 8 byte inode and 16 byte fsid */
*(u64*)fsidv = (u64)ino;
memcpy(fsidv+2, uuid, 16);
break;
default: BUG();
}
}
static inline int key_len(int type)
{
switch(type) {
case FSID_DEV: return 8;
case FSID_NUM: return 4;
case FSID_MAJOR_MINOR: return 12;
case FSID_ENCODE_DEV: return 8;
case FSID_UUID4_INUM: return 8;
case FSID_UUID8: return 8;
case FSID_UUID16: return 16;
case FSID_UUID16_INUM: return 24;
default: return 0;
}
}
/*
* Shorthand for dprintk()'s
*/
extern char * SVCFH_fmt(struct svc_fh *fhp);
/*
* Function prototypes
*/
__be32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
__be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
__be32 fh_update(struct svc_fh *);
void fh_put(struct svc_fh *);
static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
WARN_ON(src->fh_dentry || src->fh_locked);
*dst = *src;
return dst;
}
static inline void
fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
{
dst->fh_size = src->fh_size;
memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
}
static __inline__ struct svc_fh *
fh_init(struct svc_fh *fhp, int maxsize)
{
memset(fhp, 0, sizeof(*fhp));
fhp->fh_maxsize = maxsize;
return fhp;
}
#ifdef CONFIG_NFSD_V3
/*
* Fill in the pre_op attr for the wcc data
*/
static inline void
fill_pre_wcc(struct svc_fh *fhp)
{
struct inode *inode;
inode = fhp->fh_dentry->d_inode;
if (!fhp->fh_pre_saved) {
fhp->fh_pre_mtime = inode->i_mtime;
fhp->fh_pre_ctime = inode->i_ctime;
fhp->fh_pre_size = inode->i_size;
fhp->fh_pre_change = inode->i_version;
fhp->fh_pre_saved = 1;
}
}
extern void fill_post_wcc(struct svc_fh *);
#else
#define fill_pre_wcc(ignored)
#define fill_post_wcc(notused)
#endif /* CONFIG_NFSD_V3 */
/*
* Lock a file handle/inode
* NOTE: both fh_lock and fh_unlock are done "by hand" in
* vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
* so, any changes here should be reflected there.
*/
static inline void
fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
{
struct dentry *dentry = fhp->fh_dentry;
struct inode *inode;
dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
SVCFH_fmt(fhp), fhp->fh_locked);
BUG_ON(!dentry);
if (fhp->fh_locked) {
printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
return;
}
inode = dentry->d_inode;
mutex_lock_nested(&inode->i_mutex, subclass);
fill_pre_wcc(fhp);
fhp->fh_locked = 1;
}
static inline void
fh_lock(struct svc_fh *fhp)
{
fh_lock_nested(fhp, I_MUTEX_NORMAL);
}
/*
* Unlock a file handle/inode
*/
static inline void
fh_unlock(struct svc_fh *fhp)
{
BUG_ON(!fhp->fh_dentry);
if (fhp->fh_locked) {
fill_post_wcc(fhp);
mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
fhp->fh_locked = 0;
}
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View file

@ -9,14 +9,8 @@
#ifndef NFSD_SYSCALL_H #ifndef NFSD_SYSCALL_H
#define NFSD_SYSCALL_H #define NFSD_SYSCALL_H
# include <linux/types.h> #include <linux/types.h>
#ifdef __KERNEL__
# include <linux/in.h>
#endif
#include <linux/posix_types.h>
#include <linux/nfsd/const.h>
#include <linux/nfsd/export.h> #include <linux/nfsd/export.h>
#include <linux/nfsd/nfsfh.h>
/* /*
* Version of the syscall interface * Version of the syscall interface

View file

@ -28,9 +28,6 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/timer.h>
#include <linux/workqueue.h>
/* /*
* Enable RPC debugging/profiling. * Enable RPC debugging/profiling.
*/ */

View file

@ -40,6 +40,8 @@
#ifndef _LINUX_SUNRPC_RPC_RDMA_H #ifndef _LINUX_SUNRPC_RPC_RDMA_H
#define _LINUX_SUNRPC_RPC_RDMA_H #define _LINUX_SUNRPC_RPC_RDMA_H
#include <linux/types.h>
struct rpcrdma_segment { struct rpcrdma_segment {
__be32 rs_handle; /* Registered memory handle */ __be32 rs_handle; /* Registered memory handle */
__be32 rs_length; /* Length of the chunk in bytes */ __be32 rs_length; /* Length of the chunk in bytes */

View file

@ -29,7 +29,6 @@ struct svc_pool_stats {
unsigned long packets; unsigned long packets;
unsigned long sockets_queued; unsigned long sockets_queued;
unsigned long threads_woken; unsigned long threads_woken;
unsigned long overloads_avoided;
unsigned long threads_timedout; unsigned long threads_timedout;
}; };
@ -50,7 +49,6 @@ struct svc_pool {
struct list_head sp_sockets; /* pending sockets */ struct list_head sp_sockets; /* pending sockets */
unsigned int sp_nrthreads; /* # of threads in pool */ unsigned int sp_nrthreads; /* # of threads in pool */
struct list_head sp_all_threads; /* all server threads */ struct list_head sp_all_threads; /* all server threads */
int sp_nwaking; /* number of threads woken but not yet active */
struct svc_pool_stats sp_stats; /* statistics on pool operation */ struct svc_pool_stats sp_stats; /* statistics on pool operation */
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
@ -275,16 +273,11 @@ struct svc_rqst {
struct auth_domain * rq_client; /* RPC peer info */ struct auth_domain * rq_client; /* RPC peer info */
struct auth_domain * rq_gssclient; /* "gss/"-style peer info */ struct auth_domain * rq_gssclient; /* "gss/"-style peer info */
struct svc_cacherep * rq_cacherep; /* cache info */ struct svc_cacherep * rq_cacherep; /* cache info */
struct knfsd_fh * rq_reffh; /* Referrence filehandle, used to
* determine what device number
* to report (real or virtual)
*/
int rq_splice_ok; /* turned off in gss privacy int rq_splice_ok; /* turned off in gss privacy
* to prevent encrypting page * to prevent encrypting page
* cache pages */ * cache pages */
wait_queue_head_t rq_wait; /* synchronization */ wait_queue_head_t rq_wait; /* synchronization */
struct task_struct *rq_task; /* service thread */ struct task_struct *rq_task; /* service thread */
int rq_waking; /* 1 if thread is being woken */
}; };
/* /*

View file

@ -166,7 +166,7 @@ config IP_PNP_DHCP
If unsure, say Y. Note that if you want to use DHCP, a DHCP server If unsure, say Y. Note that if you want to use DHCP, a DHCP server
must be operating on your network. Read must be operating on your network. Read
<file:Documentation/filesystems/nfsroot.txt> for details. <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
config IP_PNP_BOOTP config IP_PNP_BOOTP
bool "IP: BOOTP support" bool "IP: BOOTP support"
@ -181,7 +181,7 @@ config IP_PNP_BOOTP
does BOOTP itself, providing all necessary information on the kernel does BOOTP itself, providing all necessary information on the kernel
command line, you can say N here. If unsure, say Y. Note that if you command line, you can say N here. If unsure, say Y. Note that if you
want to use BOOTP, a BOOTP server must be operating on your network. want to use BOOTP, a BOOTP server must be operating on your network.
Read <file:Documentation/filesystems/nfsroot.txt> for details. Read <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
config IP_PNP_RARP config IP_PNP_RARP
bool "IP: RARP support" bool "IP: RARP support"
@ -194,7 +194,7 @@ config IP_PNP_RARP
older protocol which is being obsoleted by BOOTP and DHCP), say Y older protocol which is being obsoleted by BOOTP and DHCP), say Y
here. Note that if you want to use RARP, a RARP server must be here. Note that if you want to use RARP, a RARP server must be
operating on your network. Read operating on your network. Read
<file:Documentation/filesystems/nfsroot.txt> for details. <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
# not yet ready.. # not yet ready..
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP # bool ' IP: ARP support' CONFIG_IP_PNP_ARP

View file

@ -1446,7 +1446,7 @@ late_initcall(ip_auto_config);
/* /*
* Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
* command line parameter. See Documentation/filesystems/nfsroot.txt. * command line parameter. See Documentation/filesystems/nfs/nfsroot.txt.
*/ */
static int __init ic_proto_name(char *name) static int __init ic_proto_name(char *name)
{ {

View file

@ -16,8 +16,6 @@
#define RPCDBG_FACILITY RPCDBG_SVCXPRT #define RPCDBG_FACILITY RPCDBG_SVCXPRT
#define SVC_MAX_WAKING 5
static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
static int svc_deferred_recv(struct svc_rqst *rqstp); static int svc_deferred_recv(struct svc_rqst *rqstp);
static struct cache_deferred_req *svc_defer(struct cache_req *req); static struct cache_deferred_req *svc_defer(struct cache_req *req);
@ -306,7 +304,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
struct svc_pool *pool; struct svc_pool *pool;
struct svc_rqst *rqstp; struct svc_rqst *rqstp;
int cpu; int cpu;
int thread_avail;
if (!(xprt->xpt_flags & if (!(xprt->xpt_flags &
((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED)))) ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED))))
@ -318,6 +315,12 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
spin_lock_bh(&pool->sp_lock); spin_lock_bh(&pool->sp_lock);
if (!list_empty(&pool->sp_threads) &&
!list_empty(&pool->sp_sockets))
printk(KERN_ERR
"svc_xprt_enqueue: "
"threads and transports both waiting??\n");
if (test_bit(XPT_DEAD, &xprt->xpt_flags)) { if (test_bit(XPT_DEAD, &xprt->xpt_flags)) {
/* Don't enqueue dead transports */ /* Don't enqueue dead transports */
dprintk("svc: transport %p is dead, not enqueued\n", xprt); dprintk("svc: transport %p is dead, not enqueued\n", xprt);
@ -358,15 +361,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
} }
process: process:
/* Work out whether threads are available */ if (!list_empty(&pool->sp_threads)) {
thread_avail = !list_empty(&pool->sp_threads); /* threads are asleep */
if (pool->sp_nwaking >= SVC_MAX_WAKING) {
/* too many threads are runnable and trying to wake up */
thread_avail = 0;
pool->sp_stats.overloads_avoided++;
}
if (thread_avail) {
rqstp = list_entry(pool->sp_threads.next, rqstp = list_entry(pool->sp_threads.next,
struct svc_rqst, struct svc_rqst,
rq_list); rq_list);
@ -381,8 +376,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
svc_xprt_get(xprt); svc_xprt_get(xprt);
rqstp->rq_reserved = serv->sv_max_mesg; rqstp->rq_reserved = serv->sv_max_mesg;
atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
rqstp->rq_waking = 1;
pool->sp_nwaking++;
pool->sp_stats.threads_woken++; pool->sp_stats.threads_woken++;
BUG_ON(xprt->xpt_pool != pool); BUG_ON(xprt->xpt_pool != pool);
wake_up(&rqstp->rq_wait); wake_up(&rqstp->rq_wait);
@ -651,11 +644,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
return -EINTR; return -EINTR;
spin_lock_bh(&pool->sp_lock); spin_lock_bh(&pool->sp_lock);
if (rqstp->rq_waking) {
rqstp->rq_waking = 0;
pool->sp_nwaking--;
BUG_ON(pool->sp_nwaking < 0);
}
xprt = svc_xprt_dequeue(pool); xprt = svc_xprt_dequeue(pool);
if (xprt) { if (xprt) {
rqstp->rq_xprt = xprt; rqstp->rq_xprt = xprt;
@ -1204,16 +1192,15 @@ static int svc_pool_stats_show(struct seq_file *m, void *p)
struct svc_pool *pool = p; struct svc_pool *pool = p;
if (p == SEQ_START_TOKEN) { if (p == SEQ_START_TOKEN) {
seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken overloads-avoided threads-timedout\n"); seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken threads-timedout\n");
return 0; return 0;
} }
seq_printf(m, "%u %lu %lu %lu %lu %lu\n", seq_printf(m, "%u %lu %lu %lu %lu\n",
pool->sp_id, pool->sp_id,
pool->sp_stats.packets, pool->sp_stats.packets,
pool->sp_stats.sockets_queued, pool->sp_stats.sockets_queued,
pool->sp_stats.threads_woken, pool->sp_stats.threads_woken,
pool->sp_stats.overloads_avoided,
pool->sp_stats.threads_timedout); pool->sp_stats.threads_timedout);
return 0; return 0;

View file

@ -655,23 +655,25 @@ static struct unix_gid *unix_gid_lookup(uid_t uid)
return NULL; return NULL;
} }
static int unix_gid_find(uid_t uid, struct group_info **gip, static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
struct svc_rqst *rqstp)
{ {
struct unix_gid *ug = unix_gid_lookup(uid); struct unix_gid *ug;
struct group_info *gi;
int ret;
ug = unix_gid_lookup(uid);
if (!ug) if (!ug)
return -EAGAIN; return ERR_PTR(-EAGAIN);
switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) { ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
switch (ret) {
case -ENOENT: case -ENOENT:
*gip = NULL; return ERR_PTR(-ENOENT);
return 0;
case 0: case 0:
*gip = ug->gi; gi = get_group_info(ug->gi);
get_group_info(*gip);
cache_put(&ug->h, &unix_gid_cache); cache_put(&ug->h, &unix_gid_cache);
return 0; return gi;
default: default:
return -EAGAIN; return ERR_PTR(-EAGAIN);
} }
} }
@ -681,6 +683,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
struct sockaddr_in *sin; struct sockaddr_in *sin;
struct sockaddr_in6 *sin6, sin6_storage; struct sockaddr_in6 *sin6, sin6_storage;
struct ip_map *ipm; struct ip_map *ipm;
struct group_info *gi;
struct svc_cred *cred = &rqstp->rq_cred;
switch (rqstp->rq_addr.ss_family) { switch (rqstp->rq_addr.ss_family) {
case AF_INET: case AF_INET:
@ -721,6 +725,17 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
ip_map_cached_put(rqstp, ipm); ip_map_cached_put(rqstp, ipm);
break; break;
} }
gi = unix_gid_find(cred->cr_uid, rqstp);
switch (PTR_ERR(gi)) {
case -EAGAIN:
return SVC_DROP;
case -ENOENT:
break;
default:
put_group_info(cred->cr_group_info);
cred->cr_group_info = gi;
}
return SVC_OK; return SVC_OK;
} }
@ -817,19 +832,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
slen = svc_getnl(argv); /* gids length */ slen = svc_getnl(argv); /* gids length */
if (slen > 16 || (len -= (slen + 2)*4) < 0) if (slen > 16 || (len -= (slen + 2)*4) < 0)
goto badcred; goto badcred;
if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp) cred->cr_group_info = groups_alloc(slen);
== -EAGAIN) if (cred->cr_group_info == NULL)
return SVC_DROP; return SVC_DROP;
if (cred->cr_group_info == NULL) { for (i = 0; i < slen; i++)
cred->cr_group_info = groups_alloc(slen); GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
if (cred->cr_group_info == NULL)
return SVC_DROP;
for (i = 0; i < slen; i++)
GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
} else {
for (i = 0; i < slen ; i++)
svc_getnl(argv);
}
if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
*authp = rpc_autherr_badverf; *authp = rpc_autherr_badverf;
return SVC_DENIED; return SVC_DENIED;