Commit 37c24b37 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 5ac4d630 7663dacd
00-INDEX
- this file (info on some of the filesystems supported by linux).
Exporting
- explanation of how to make filesystems exportable.
Locking
- info on locking rules as they pertain to Linux VFS.
9p.txt
......@@ -68,12 +66,8 @@ mandatory-locking.txt
- info on the Linux implementation of Sys V mandatory file locking.
ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
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.
nfs/
- nfs-related documentation.
nilfs2.txt
- info and mount options for the NILFS2 filesystem.
ntfs.txt
......@@ -92,8 +86,6 @@ relay.txt
- info on relay, for efficient streaming from kernel to user space.
romfs.txt
- description of the ROMFS filesystem.
rpc-cache.txt
- introduction to the caching mechanisms in the sunrpc layer.
seq_file.txt
- how to use the seq_file API
sharedsubtree.txt
......
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.
......@@ -41,7 +41,7 @@ interoperability problems with future clients. Known issues:
conformant with the spec (for example, we don't use kerberos
on the backchannel correctly).
- 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
timely renewal in case an existing connection's retry timeouts
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_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.
......@@ -140,7 +140,7 @@ Callers of notify_change() need ->i_mutex now.
New super_block field "struct export_operations *s_export_op" for
explicit support for exporting, e.g. via NFS. The structure is fully
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
to encode and decode filehandles, and allows the filesystem to use
......
......@@ -1032,7 +1032,7 @@ and is between 256 and 4096 characters. It is defined in the file
No delay
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
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.
nfsaddrs= [NFS]
See Documentation/filesystems/nfsroot.txt.
See Documentation/filesystems/nfs/nfsroot.txt.
nfsroot= [NFS] nfs root filesystem for disk-less boxes.
See Documentation/filesystems/nfsroot.txt.
See Documentation/filesystems/nfs/nfsroot.txt.
nfs.callback_tcpport=
[NFS] set the TCP port on which the NFSv4 callback
......
......@@ -26,13 +26,7 @@
#include <linux/shm.h>
#include <linux/slab.h>
#include <linux/uio.h>
#include <linux/nfs_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/personality.h>
#include <linux/stat.h>
......
......@@ -24,7 +24,7 @@
*/
/*
* See Documentation/filesystems/Exporting
* See Documentation/filesystems/nfs/Exporting
* and examples in fs/exportfs
*
* Since cifs is a network file system, an "fsid" must be included for
......
......@@ -38,8 +38,6 @@
#include <linux/dirent.h>
#include <linux/fsnotify.h>
#include <linux/highuid.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/syscall.h>
#include <linux/personality.h>
#include <linux/rwsem.h>
......
......@@ -6,7 +6,7 @@
* and for mapping back from file handles to dentries.
*
* 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/fs.h>
......
......@@ -9,7 +9,7 @@
*
* The following files are helpful:
*
* Documentation/filesystems/Exporting
* Documentation/filesystems/nfs/Exporting
* fs/exportfs/expfs.c.
*/
......
......@@ -11,10 +11,6 @@
#include <linux/time.h>
#include <linux/slab.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/share.h>
......
......@@ -11,10 +11,6 @@
#include <linux/time.h>
#include <linux/slab.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/share.h>
......
......@@ -90,7 +90,7 @@ config ROOT_NFS
If you want your system to mount its root file system via NFS,
choose Y here. This is common practice for managing systems
without local permanent storage. For details, read
<file:Documentation/filesystems/nfsroot.txt>.
<file:Documentation/filesystems/nfs/nfsroot.txt>.
Most people say N here.
......
......@@ -7,8 +7,6 @@
#include <linux/types.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/syscall.h>
#include <linux/cred.h>
#include <linux/sched.h>
......
/*
* linux/fs/nfsd/auth.c
*
* 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 <linux/sched.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/export.h>
#include "nfsd.h"
#include "auth.h"
int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
......
/*
* include/linux/nfsd/cache.h
*
* Request reply cache. This was heavily inspired by the
* implementation in 4.3BSD/4.4BSD.
*
......@@ -10,8 +8,7 @@
#ifndef NFSCACHE_H
#define NFSCACHE_H
#include <linux/in.h>
#include <linux/uio.h>
#include <linux/sunrpc/svc.h>
/*
* Representation of a reply cache entry.
......
#define MSNFS /* HACK HACK */
/*
* linux/fs/nfsd/export.c
*
* NFS exporting and validation.
*
* 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>
*/
#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/mount.h>
#include <linux/hash.h>
#include <linux/module.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/lockd/bind.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/gss_api.h>
#include <net/ipv6.h>
#include "nfsd.h"
#include "nfsfh.h"
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
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);
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) &&
!S_ISLNK(inode->i_mode) &&
!S_ISREG(inode->i_mode))
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.
* 1: We must be able to identify the filesystem from a number.
* 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.
*/
if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
!(flags & NFSEXP_FSID) &&
!(*flags & NFSEXP_FSID) &&
uuid == NULL) {
dprintk("exp_export: export of non-dev fs without fsid\n");
return -EINVAL;
......@@ -602,7 +596,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
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);
if (err)
goto out4;
......@@ -1041,7 +1035,7 @@ exp_export(struct nfsctl_export *nxp)
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;
err = -ENOMEM;
......@@ -1320,6 +1314,23 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
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,
* 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;
__be32 rv;
u32 fsidv[2];
mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
exp = find_fsidzero_export(rqstp);
if (IS_ERR(exp))
return nfserrno(PTR_ERR(exp));
rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
......@@ -1425,6 +1433,7 @@ static struct flags {
{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
{ NFSEXP_V4ROOT, {"v4root", ""}},
#ifdef MSNFS
{ NFSEXP_MSNFS, {"msnfs", ""}},
#endif
......
/*
* linux/fs/nfsd/lockd.c
*
* This file contains all the stubs needed when communicating with lockd.
* 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.
......@@ -8,14 +6,10 @@
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.h>
#include <linux/fs.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 "nfsd.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_LOCKD
......
/*
* linux/fs/nfsd/nfs2acl.c
*
* Process version 2 NFSACL requests.
*
* Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
*/
#include <linux/sunrpc/svc.h>
#include <linux/nfs.h>
#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 "nfsd.h"
/* FIXME: nfsacl.h is a broken header */
#include <linux/nfsacl.h>
#include "cache.h"
#include "xdr3.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC
#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
*/
/*
* 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 */
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
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_encode_voidres NULL
#define nfsaclsvc_release_void NULL
#define nfsd3_fhandleargs nfsd_fhandle
#define nfsd3_attrstatres nfsd_attrstat
......@@ -346,5 +351,5 @@ struct svc_version nfsd_acl_version2 = {
.vs_proc = nfsd_acl_procedures2,
.vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 1,
.vs_hidden = 0,
};
/*
* linux/fs/nfsd/nfs3acl.c
*
* Process version 3 NFSACL requests.
*
* Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
*/
#include <linux/sunrpc/svc.h>
#include <linux/nfs3.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr3.h>
#include <linux/posix_acl.h>
#include "nfsd.h"
/* FIXME: nfsacl.h is a broken header */
#include <linux/nfsacl.h>
#include "cache.h"
#include "xdr3.h"
#include "vfs.h"
#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_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 1,
.vs_hidden = 0,
};
/*
* linux/fs/nfsd/nfs3proc.c
*
* Process version 3 NFS requests.
*
* 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/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/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr3.h>
#include <linux/nfs3.h>
#include "cache.h"
#include "xdr3.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC
......
/*
* linux/fs/nfsd/nfs3xdr.c
*
* XDR support for nfsd/protocol version 3.
*
* 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()!
*/
#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/mm.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 "xdr3.h"
#include "auth.h"
#define NFSDDBG_FACILITY NFSDDBG_XDR
......
/*
* fs/nfs4acl/acl.c
*
* Common NFSv4 ACL handling code.
*
* 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.
*/
#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/posix_acl.h>
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
......@@ -389,7 +379,7 @@ sort_pacl(struct posix_acl *pacl)
sort_pacl_range(pacl, 1, i-1);
BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
j = i++;
j = ++i;
while (pacl->a_entries[j].e_tag == ACL_GROUP)
j++;
sort_pacl_range(pacl, i, j-1);
......
/*
* linux/fs/nfsd/nfs4callback.c
*
* Copyright (c) 2001 The Regents of the University of Michigan.
* All rights reserved.
*
......@@ -33,22 +31,9 @@
* 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/svcsock.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/state.h>
#include <linux/sunrpc/sched.h>
#include <linux/nfs4.h>
#include <linux/sunrpc/xprtsock.h>
#include "nfsd.h"
#include "state.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC
......
/*
* fs/nfsd/nfs4idmap.c
*
* Mapping of UID/GIDs to name and vice versa.
*
* Copyright (c) 2002, 2003 The Regents of the University of
......@@ -35,22 +33,9 @@
*/
#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/list.h>
#include <linux/time.h>
#include <linux/seq_file.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/sched.h>
/*
* Cache entry
......
/*
* fs/nfsd/nfs4proc.c
*
* Server-side procedures for NFSv4.
*
* 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
* 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/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.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>
#include "cache.h"
#include "xdr4.h"
#include "vfs.h"
#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;
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
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;
status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
......
/*
* linux/fs/nfsd/nfs4recover.c
*
* Copyright (c) 2004 The Regents of the University of Michigan.
* 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/namei.h>
#include <asm/uaccess.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <linux/sched.h>
#include <linux/mount.h>
#include "nfsd.h"
#include "state.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_PROC
......
/*
* linux/fs/nfsd/nfs4state.c
*
* Copyright (c) 2001 The Regents of the University of Michigan.
* 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/mount.h>
#include <linux/workqueue.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/swap.h>
#include <linux/mutex.h>
#include <linux/lockd/bind.h>
#include <linux/module.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/clnt.h>
#include "xdr4.h"
#include "vfs.h"
#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
* sv_max_mesg is the maximum payload plus one page for overhead.
*/
static int init_forechannel_attrs(struct svc_rqst *rqstp,
struct nfsd4_channel_attrs *session_fchan,
struct nfsd4_channel_attrs *fchan)
{
int status = 0;
__u32 maxcount = svc_max_payload(rqstp);
__u32 maxcount = nfsd_serv->sv_max_mesg;
/* headerpadsz set to zero in encode routine */
......@@ -523,6 +508,15 @@ free_session_slots(struct nfsd4_session *ses)
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
alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
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));
/* 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++) {
sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
if (!sp)
......@@ -628,10 +622,12 @@ void
free_session(struct kref *kref)
{
struct nfsd4_session *ses;
int mem;
ses = container_of(kref, struct nfsd4_session, se_ref);
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);
free_session_slots(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));
dprintk("NFSD: delegation stateid=(%08x/%08x/%08x/%08x)\n\n",
dp->dl_stateid.si_boot,
dp->dl_stateid.si_stateownerid,
dp->dl_stateid.si_fileid,
dp->dl_stateid.si_generation);
dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
STATEID_VAL(&dp->dl_stateid));
out:
if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
&& 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;
dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n",
stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
STATEID_VAL(&stp->st_stateid));
out:
if (fp)
put_nfs4_file(fp);
......@@ -2666,9 +2658,8 @@ STALE_STATEID(stateid_t *stateid)
{
if (time_after((unsigned long)boot_time,
(unsigned long)stateid->si_boot)) {
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
STATEID_VAL(stateid));
return 1;
}
return 0;
......@@ -2680,9 +2671,8 @@ EXPIRED_STATEID(stateid_t *stateid)
if (time_before((unsigned long)boot_time,
((unsigned long)stateid->si_boot)) &&
time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
STATEID_VAL(stateid));
return 1;
}
return 0;
......@@ -2696,9 +2686,8 @@ stateid_error_map(stateid_t *stateid)
if (EXPIRED_STATEID(stateid))
return nfserr_expired;
dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
dprintk("NFSD: bad stateid " STATEID_FMT "!\n",
STATEID_VAL(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;
__be32 status;
dprintk("NFSD: preprocess_seqid_op: seqid=%d "
"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__,
seqid, STATEID_VAL(stateid));
*stpp = NULL;
*sopp = NULL;
......@@ -3019,12 +3006,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
sop->so_confirmed = 1;
update_stateid(&stp->st_stateid);
memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d "
"stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
stp->st_stateid.si_boot,
stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid,
stp->st_stateid.si_generation);
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stateid));
nfsd4_create_clid_dir(sop->so_client);
out:
......@@ -3283,9 +3266,8 @@ find_delegation_stateid(struct inode *ino, stateid_t *stid)
struct nfs4_file *fp;
struct nfs4_delegation *dl;
dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
stid->si_boot, stid->si_stateownerid,
stid->si_fileid, stid->si_generation);
dprintk("NFSD: %s: stateid=" STATEID_FMT "\n", __func__,
STATEID_VAL(stid));
fp = find_file(ino);
if (!fp)
......
......@@ -40,24 +40,16 @@
* 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/vfs.h>
#include <linux/statfs.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/nfs4.h>
#include <linux/nfs4_acl.h>
#include <linux/sunrpc/gss_api.h>
#include <linux/sunrpc/svcauth_gss.h>
#include "xdr4.h"
#include "vfs.h"
#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
* directly from the mountpoint dentry.
*/
if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
ignore_crossmnt = 1;
else if (d_mountpoint(dentry)) {
if (nfsd_mountpoint(dentry, exp)) {
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??
* Different "."/".." handling? Something else?
......@@ -2224,6 +2219,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
goto out_put;
}
out_encode:
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
cd->rd_rqstp, ignore_crossmnt);
out_put:
......
/*
* linux/fs/nfsd/nfscache.c
*
* Request reply cache. This is currently a global cache, but this may
* change in the future and be a per-client cache.
*
......@@ -10,16 +8,8 @@
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/kernel.h>
#include <linux/time.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>
#include "nfsd.h"
#include "cache.h"
/* Size of reply cache. Common values are:
* 4.3BSD: 128
......
/*
* linux/fs/nfsd/nfsctl.c
*
* Syscall interface to knfsd.
*
* 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/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/nfs.h>
#include <linux/nfsd_idmap.h>
#include <linux/lockd/bind.h>
#include <linux/sunrpc/svc.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/lockd/lockd.h>
#include <linux/sunrpc/clnt.h>
#include <asm/uaccess.h>
#include <net/ipv6.h>
#include "nfsd.h"
#include "cache.h"
/*
* We have a single directory with 9 nodes in it.
......@@ -55,6 +29,7 @@ enum {
NFSD_Getfd,
NFSD_Getfs,
NFSD_List,
NFSD_Export_features,
NFSD_Fh,
NFSD_FO_UnlockIP,
NFSD_FO_UnlockFS,
......@@ -173,6 +148,24 @@ static const struct file_operations exports_operations = {
.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_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_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_Export_features] = {"export_features",
&export_features_operations, S_IRUGO},
[NFSD_FO_UnlockIP] = {"unlock_ip",
&transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_FO_UnlockFS] = {"unlock_filesystem",
......
/*
* linux/include/linux/nfsd/nfsd.h
*
* Hodge-podge collection of knfsd-related stuff.
* I will sort this out later.
*
......@@ -11,13 +9,9 @@
#define LINUX_NFSD_NFSD_H
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/fs.h>
#include <linux/posix_acl.h>
#include <linux/mount.h>
#include <linux/nfsd/debug.h>
#include <linux/nfsd/nfsfh.h>
#include <linux/nfsd/export.h>
#include <linux/nfsd/stats.h>
/*
......@@ -25,30 +19,10 @@
*/
#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 {
__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_version nfsd_version2, nfsd_version3,
......@@ -73,69 +47,6 @@ int nfsd_nrpools(void);
int nfsd_get_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)
#ifdef CONFIG_NFSD_V2_ACL
extern struct svc_version nfsd_acl_version2;
......@@ -147,8 +58,6 @@ extern struct svc_version nfsd_acl_version3;
#else
#define nfsd_acl_version3 NULL
#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
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;
static inline int nfsd_v4client(struct svc_rqst *rq)
{
return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
}
/*
* NFSv4 State
*/
......
/*
* linux/fs/nfsd/nfsfh.c
*
* NFS server file handle treatment.
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
......@@ -9,19 +7,11 @@
* ... 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/mount.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/nfsd/nfsd.h>
#include "nfsd.h"
#include "vfs.h"
#include "auth.h"
#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,
struct svc_export *exp)
{
int flags = nfsexp_flags(rqstp, exp);
/* 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]);
dprintk(KERN_WARNING
"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));
}
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
* 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;
}
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) &&
(dentry->d_flags & DCACHE_DISCONNECTED)) {
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);
if (error)
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);
if (error)
......
/* 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 */
/*
* nfsproc2.c Process version 2 NFS requests.
* linux/fs/nfsd/nfs2proc.c
*
* Process version 2 NFS requests.
*
* 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/unistd.h>
#include <linux/slab.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include "cache.h"
#include "xdr.h"
#include "vfs.h"
typedef struct svc_rqst svc_rqst;
typedef struct svc_buf svc_buf;
......@@ -758,6 +743,7 @@ nfserrno (int errno)
{ nfserr_io, -ETXTBSY },
{ nfserr_notsupp, -EOPNOTSUPP },
{ nfserr_toosmall, -ETOOSMALL },
{ nfserr_serverfault, -ESERVERFAULT },
};
int i;
......
/*
* linux/fs/nfsd/nfssvc.c
*
* Central processing for nfsd.
*
* Authors: Olaf Kirch (okir@monad.swb.de)
......@@ -8,33 +6,19 @@
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/module.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/fs_struct.h>
#include <linux/kthread.h>
#include <linux/swap.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svc.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/nfsacl.h>
#include <linux/seq_file.h>
#include "nfsd.h"
#include "cache.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_SVC
......
/*
* linux/fs/nfsd/nfsxdr.c
*
* XDR support for nfsd
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.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 "xdr.h"
#include "auth.h"
#define NFSDDBG_FACILITY NFSDDBG_XDR
......
/*
* linux/include/nfsd/state.h
*
* Copyright (c) 2001 The Regents of the University of Michigan.
* All rights reserved.
*
......@@ -37,9 +35,8 @@
#ifndef _NFSD4_STATE_H
#define _NFSD4_STATE_H
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfsd/nfsfh.h>
#include "nfsfh.h"
typedef struct {
u32 cl_boot;
......@@ -60,6 +57,13 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid
#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 {
/* args/res */
u32 cbs_minorversion;
......
/*
* linux/fs/nfsd/stats.c
*
* procfs-based user access to knfsd statistics
*
* /proc/net/rpc/nfsd
......@@ -23,18 +21,13 @@
* 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/stat.h>
#include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/stats.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/stats.h>
#include "nfsd.h"
struct nfsd_stats nfsdstats;
struct svc_stat nfsd_svcstats = {
.program = &nfsd_program,
......
#define MSNFS /* HACK HACK */
/*
* linux/fs/nfsd/vfs.c
*
* File operations used by nfsd. Some of these have been ripped from
* other parts of the kernel because they weren't exported, others
* are partial duplicates with added or changed functionality.
......@@ -16,48 +14,31 @@
* 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/file.h>
#include <linux/mount.h>
#include <linux/major.h>
#include <linux/splice.h>
#include <linux/proc_fs.h>
#include <linux/stat.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/vfs.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/fsnotify.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
#include <linux/xattr.h>
#include <linux/jhash.h>
#include <linux/ima.h>
#include <asm/uaccess.h>
#ifdef CONFIG_NFSD_V3
#include "xdr3.h"
#endif /* CONFIG_NFSD_V3 */
#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/ima.h>
#include <asm/uaccess.h>
#include "nfsd.h"
#include "vfs.h"
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
......@@ -89,12 +70,6 @@ struct raparm_hbucket {
#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
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
* 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);
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);
goto out;
}
......@@ -141,6 +124,53 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
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
nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
const char *name, unsigned int len,
......@@ -169,35 +199,13 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = dget(dparent);
else if (dparent != exp->ex_path.dentry)
dentry = dget_parent(dparent);
else if (!EX_NOHIDE(exp))
else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp))
dentry = dget(dparent); /* .. == . just like at / */
else {
/* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL;
struct dentry *dp;
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);
host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry);
if (host_err)
goto out_nfserr;
} else {
dentry = dget(path.dentry);
exp_put(exp);
exp = exp2;
}
path_put(&path);
}
} else {
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 ...
*/
if (d_mountpoint(dentry)) {
if (nfsd_mountpoint(dentry, exp)) {
if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
dput(dentry);
goto out_nfserr;
......
/*
* 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 */
/*
* linux/include/linux/nfsd/xdr.h
*
* XDR types for nfsd. This is mainly a typing exercise.
*/
/* XDR types for nfsd. This is mainly a typing exercise. */
#ifndef LINUX_NFSD_H
#define LINUX_NFSD_H
#include <linux/fs.h>
#include <linux/vfs.h>
#include <linux/nfs.h>
#include "nfsd.h"
#include "nfsfh.h"
struct nfsd_fhandle {
struct svc_fh fh;
......
/*
* linux/include/linux/nfsd/xdr3.h
*
* XDR types for NFSv3 in nfsd.
*
* Copyright (C) 1996-1998, Olaf Kirch <okir@monad.swb.de>
......@@ -9,7 +7,7 @@
#ifndef _LINUX_NFSD_XDR3_H
#define _LINUX_NFSD_XDR3_H
#include <linux/nfsd/xdr.h>
#include "xdr.h"
struct nfsd3_sattrargs {
struct svc_fh fh;
......
/*
* include/linux/nfsd/xdr4.h
*
* Server-side types for NFSv4.
*
* Copyright (c) 2002 The Regents of the University of Michigan.
......@@ -39,7 +37,8 @@
#ifndef _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 XDR_LEN(n) (((n) + 3) & ~3)
......
......@@ -97,7 +97,7 @@ struct fid {
* @get_name: find the name for a given inode in 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.
*
* encode_fh:
......
......@@ -2,6 +2,7 @@
#define _LINUX_NFS_XDR_H
#include <linux/nfsacl.h>
#include <linux/nfs3.h>
/*
* To change the maximum rsize and wsize supported by the NFS client, adjust
......
......@@ -29,6 +29,7 @@
#ifdef __KERNEL__
#include <linux/posix_acl.h>
#include <linux/sunrpc/xdr.h>
/* Maximum number of ACL entries over NFS */
#define NFS_ACL_MAX_ENTRIES 1024
......
......@@ -12,7 +12,7 @@
# include <linux/types.h>
#ifdef __KERNEL__
# include <linux/in.h>
# include <linux/nfsd/nfsfh.h>
#endif
/*
......@@ -39,11 +39,23 @@
#define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000
#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: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
| NFSEXP_ALLSQUASH)
| NFSEXP_ALLSQUASH \
| NFSEXP_INSECURE_PORT)
#ifdef __KERNEL__
......@@ -108,7 +120,6 @@ struct svc_expkey {
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_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
......
......@@ -16,11 +16,9 @@
# include <linux/types.h>
#ifdef __KERNEL__
# include <linux/string.h>
# include <linux/fs.h>
# include <linux/sunrpc/svc.h>
#endif
#include <linux/nfsd/const.h>
#include <linux/nfsd/debug.h>
/*
* This is the old "dentry style" Linux NFSv2 file handle.
......@@ -164,208 +162,6 @@ typedef struct 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__ */
......
......@@ -9,14 +9,8 @@
#ifndef NFSD_SYSCALL_H
#define NFSD_SYSCALL_H
# include <linux/types.h>
#ifdef __KERNEL__
# include <linux/in.h>
#endif
#include <linux/posix_types.h>
#include <linux/nfsd/const.h>
#include <linux/types.h>
#include <linux/nfsd/export.h>
#include <linux/nfsd/nfsfh.h>
/*
* Version of the syscall interface
......
......@@ -28,9 +28,6 @@
#ifdef __KERNEL__
#include <linux/timer.h>
#include <linux/workqueue.h>
/*
* Enable RPC debugging/profiling.
*/
......
......@@ -40,6 +40,8 @@
#ifndef _LINUX_SUNRPC_RPC_RDMA_H
#define _LINUX_SUNRPC_RPC_RDMA_H
#include <linux/types.h>
struct rpcrdma_segment {
__be32 rs_handle; /* Registered memory handle */
__be32 rs_length; /* Length of the chunk in bytes */
......
......@@ -29,7 +29,6 @@ struct svc_pool_stats {
unsigned long packets;
unsigned long sockets_queued;
unsigned long threads_woken;
unsigned long overloads_avoided;
unsigned long threads_timedout;
};
......@@ -50,7 +49,6 @@ struct svc_pool {
struct list_head sp_sockets; /* pending sockets */
unsigned int sp_nrthreads; /* # of threads in pool */
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 */
} ____cacheline_aligned_in_smp;
......@@ -275,16 +273,11 @@ struct svc_rqst {
struct auth_domain * rq_client; /* RPC peer info */
struct auth_domain * rq_gssclient; /* "gss/"-style peer 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
* to prevent encrypting page
* cache pages */
wait_queue_head_t rq_wait; /* synchronization */
struct task_struct *rq_task; /* service thread */
int rq_waking; /* 1 if thread is being woken */
};
/*
......
......@@ -166,7 +166,7 @@ config IP_PNP_DHCP
If unsure, say Y. Note that if you want to use DHCP, a DHCP server
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
bool "IP: BOOTP support"
......@@ -181,7 +181,7 @@ config IP_PNP_BOOTP
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
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
bool "IP: RARP support"
......@@ -194,7 +194,7 @@ config IP_PNP_RARP
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
operating on your network. Read
<file:Documentation/filesystems/nfsroot.txt> for details.
<file:Documentation/filesystems/nfs/nfsroot.txt> for details.
# not yet ready..
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP
......
......@@ -1446,7 +1446,7 @@ late_initcall(ip_auto_config);
/*
* 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)
{
......
......@@ -16,8 +16,6 @@
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
#define SVC_MAX_WAKING 5
static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
static int svc_deferred_recv(struct svc_rqst *rqstp);
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_rqst *rqstp;
int cpu;
int thread_avail;
if (!(xprt->xpt_flags &
((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);
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)) {
/* Don't enqueue dead transports */
dprintk("svc: transport %p is dead, not enqueued\n", xprt);
......@@ -358,15 +361,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
}
process:
/* Work out whether threads are available */
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) {
if (!list_empty(&pool->sp_threads)) {
rqstp = list_entry(pool->sp_threads.next,
struct svc_rqst,
rq_list);
......@@ -381,8 +376,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
svc_xprt_get(xprt);
rqstp->rq_reserved = serv->sv_max_mesg;
atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
rqstp->rq_waking = 1;
pool->sp_nwaking++;
pool->sp_stats.threads_woken++;
BUG_ON(xprt->xpt_pool != pool);
wake_up(&rqstp->rq_wait);
......@@ -651,11 +644,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
return -EINTR;
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);
if (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;
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;
}
seq_printf(m, "%u %lu %lu %lu %lu %lu\n",
seq_printf(m, "%u %lu %lu %lu %lu\n",
pool->sp_id,
pool->sp_stats.packets,
pool->sp_stats.sockets_queued,
pool->sp_stats.threads_woken,
pool->sp_stats.overloads_avoided,
pool->sp_stats.threads_timedout);
return 0;
......
......@@ -655,23 +655,25 @@ static struct unix_gid *unix_gid_lookup(uid_t uid)
return NULL;
}
static int unix_gid_find(uid_t uid, struct group_info **gip,
struct svc_rqst *rqstp)
static struct group_info *unix_gid_find(uid_t uid, 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)
return -EAGAIN;
switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
return ERR_PTR(-EAGAIN);
ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
switch (ret) {
case -ENOENT:
*gip = NULL;
return 0;
return ERR_PTR(-ENOENT);
case 0:
*gip = ug->gi;
get_group_info(*gip);
gi = get_group_info(ug->gi);
cache_put(&ug->h, &unix_gid_cache);
return 0;
return gi;
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_in6 *sin6, sin6_storage;
struct ip_map *ipm;
struct group_info *gi;
struct svc_cred *cred = &rqstp->rq_cred;
switch (rqstp->rq_addr.ss_family) {
case AF_INET:
......@@ -721,6 +725,17 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
ip_map_cached_put(rqstp, ipm);
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;
}
......@@ -817,19 +832,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
slen = svc_getnl(argv); /* gids length */
if (slen > 16 || (len -= (slen + 2)*4) < 0)
goto badcred;
if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
== -EAGAIN)
cred->cr_group_info = groups_alloc(slen);
if (cred->cr_group_info == NULL)
return SVC_DROP;
if (cred->cr_group_info == NULL) {
cred->cr_group_info = groups_alloc(slen);
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);
}
for (i = 0; i < slen; i++)
GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
*authp = rpc_autherr_badverf;
return SVC_DENIED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment