Skip to contentSkip to conversation

kNFSd - 0 of 34 - Introduction

PATCH New NeilBrown 1 participant 35 messages Feb 23, 2004

Subsystems (3)
lore
Share & tools
lore

NeilBrown

author
#0 lore raw

PATCH 1/1 kNFSd - 0 of 34 - Introduction

The following pile of 34 patches address assorted large and small issues with the NFSv4 server. They all come from the NFSv4 team at umich.edu.

NeilBrown

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#1 lore raw

PATCH 1/1 kNFSd - 4 of 34 - Nfsdv4 pointer cleanup

From: "William A.(Andy) Adamson" <[email protected]>

Compare inode pointers instead of dentry pointers when checking an inode refered to by a stateid against an inode refered to by a file handle.

Set st_vfs_set to 0 if the stateid/file handle check fails to avoid referencing bad state when reaping stateid's.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletion(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +4 -1
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1303,7 +1303,8 @@ find_openstateowner_id(u32 st_id) {
 static inline int
 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
 {
-	return (fhp->fh_dentry != stp->st_vfs_file.f_dentry);
+	return (stp->st_vfs_set == 0 ||
+		fhp->fh_dentry->d_inode != stp->st_vfs_file.f_dentry->d_inode);
 }
 
 static int
@@ -1346,6 +1347,7 @@ nfs4_preprocess_stateid_op(struct svc_fh
 	}
 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
 		dprintk("NFSD: preprocess_stateid_op: fh-stateid mismatch!\n");
+		stp->st_vfs_set = 0;
 		goto out;
 	}
 	if (!stp->st_stateowner->so_confirmed) {
@@ -1414,6 +1416,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *
 
 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
 		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+		stp->st_vfs_set = 0;
 		goto out;
 	}
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#2 lore raw

PATCH 1/1 kNFSd - 14 of 34 - Fix for lookup-parent at pseudo root

In reply to NeilBrown

tests if current_fh is the pseudo root for the client and returns nfserr_noent if so. need to call exp_pseudoroot because different clients can have different pseudo filesystems.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +12 -8
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -349,14 +349,18 @@ nfsd4_link(struct svc_rqst *rqstp, struc
 static inline int
 nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
 {
-	/*
-	 * XXX: We currently violate the spec in one small respect
-	 * here.  If LOOKUPP is done at the root of the pseudofs,
-	 * the spec requires us to return NFSERR_NOENT.  Personally,
-	 * I think that leaving the filehandle unchanged is more
-	 * logical, but this is an academic question anyway, since
-	 * no clients actually use LOOKUPP.
-	 */
+	struct svc_fh tmp_fh;
+	int ret;
+
+	fh_init(&tmp_fh, NFS4_FHSIZE);
+	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
+			      &rqstp->rq_chandle)) != 0)
+		return ret;
+	if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
+		fh_put(&tmp_fh);
+		return nfserr_noent;
+	}
+	fh_put(&tmp_fh);
 	return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
 }
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#3 lore raw

PATCH 1/1 kNFSd - 7 of 34 - Use higher-resolution time for the changeinfo, instead of using time and filesize.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c         |   31 +++++++------------------------
 ./include/linux/nfsd/xdr4.h |   16 ++++++++--------
 2 files changed, 15 insertions(+), 32 deletions(-)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +7 -24
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -1183,10 +1183,10 @@ nfsd4_decode_compound(struct nfsd4_compo
 } while (0)
 #define WRITECINFO(c)		do {				\
 	*p++ = htonl(c.atomic);					\
-	*p++ = htonl(c.before_size);				\
-	*p++ = htonl(c.before_ctime);				\
-	*p++ = htonl(c.after_size);				\
-	*p++ = htonl(c.after_ctime);				\
+	*p++ = htonl(c.before_ctime_sec);				\
+	*p++ = htonl(c.before_ctime_nsec);				\
+	*p++ = htonl(c.after_ctime_sec);				\
+	*p++ = htonl(c.after_ctime_nsec);				\
 } while (0)
 
 #define RESERVE_SPACE(nbytes)	do {				\
@@ -1326,32 +1326,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
 	}
 	if (bmval0 & FATTR4_WORD0_CHANGE) {
 		/*
-		 * XXX: We currently use the inode ctime as the nfsv4 "changeid"
-		 * attribute.  This violates the spec, which says
-		 *
-		 *    The server may return the object's time_modify attribute
-		 *    for this attribute, but only if the file system object
-		 *    can not be updated more frequently than the resolution
-		 *    of time_modify.
-		 *
-		 * Since we only have 1-second ctime resolution, this is a pretty
-		 * serious violation.  Indeed, 1-second ctime resolution is known
-		 * to be a problem in practice in the NFSv3 world.
-		 *
-		 * The real solution to this problem is probably to work on
-		 * adding high-resolution mtimes to the VFS layer.
-		 *
-		 * Note: Started using i_size for the high 32 bits of the changeid.
-		 *
-		 * Note 2: This _must_ be consistent with the scheme for writing
+		 * Note: This _must_ be consistent with the scheme for writing
 		 * change_info, so any changes made here must be reflected there
 		 * as well.  (See xdr4.h:set_change_info() and the WRITECINFO()
 		 * macro above.)
 		 */
 		if ((buflen -= 8) < 0)
 			goto out_resource;
-		WRITE32(stat.size);
-		WRITE32(stat.mtime.tv_sec); /* AK: nsec dropped? */
+		WRITE32(stat.ctime.tv_sec);
+		WRITE32(stat.ctime.tv_nsec);
 	}
 	if (bmval0 & FATTR4_WORD0_SIZE) {
 		if ((buflen -= 8) < 0)
include/linux/nfsd/xdr4.h renamed from include/linux/nfsd/xdr4.h~current~ +8 -8
diff ./include/linux/nfsd/xdr4.h~current~ ./include/linux/nfsd/xdr4.h
@@ -54,10 +54,10 @@ typedef struct {
 
 struct nfsd4_change_info {
 	u32		atomic;
-	u32		before_size;
-	u32		before_ctime;
-	u32		after_size;
-	u32		after_ctime;
+	u32		before_ctime_sec;
+	u32		before_ctime_nsec;
+	u32		after_ctime_sec;
+	u32		after_ctime_nsec;
 };
 
 struct nfsd4_access {
@@ -406,10 +406,10 @@ set_change_info(struct nfsd4_change_info
 {
 	BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
 	cinfo->atomic = 1;
-	cinfo->before_size = fhp->fh_pre_size;
-	cinfo->before_ctime = fhp->fh_pre_ctime.tv_sec;
-	cinfo->after_size = fhp->fh_post_size;
-	cinfo->after_ctime = fhp->fh_post_ctime.tv_sec;
+	cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+	cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+	cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec;
+	cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec;
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#4 lore raw

PATCH 1/1 kNFSd - 8 of 34 - When looking for a shareowner in the nfsd open, make sure we don't get a lockowner instead.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    3 +++
 1 files changed, 3 insertions(+)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +3 -0
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1119,6 +1119,9 @@ nfsd4_process_open2(struct svc_rqst *rqs
 				stp = stq;
 				continue;
 			}
+			/* ignore lock owners */
+			if (stq->st_stateowner->so_is_open_owner == 0) 
+				continue;
 			if (!test_share(stq,open))	
 				goto out;
 		}

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#5 lore raw

PATCH 1/1 kNFSd - 12 of 34 - readdir error code fix

In reply to NeilBrown

changes nfserr_readdir_nospc to nfserr_toosmall, following rfc3530 which has no nfserr_readdir_nospc.

error 10030 which was nfserr_readdir_nospc is actually nfserr_restorefh.

----------- Diffstat output ------------

 ./fs/nfsd/nfs3xdr.c         |    2 +-
 ./fs/nfsd/nfs4xdr.c         |    8 ++++----
 ./fs/nfsd/nfsxdr.c          |    2 +-
 ./fs/nfsd/vfs.c             |    2 +-
 ./include/linux/nfs.h       |    2 +-
 ./include/linux/nfsd/nfsd.h |    2 +-
 6 files changed, 9 insertions(+), 9 deletions(-)
fs/nfsd/nfs3xdr.c renamed from fs/nfsd/nfs3xdr.c~current~ +1 -1
diff ./fs/nfsd/nfs3xdr.c~current~ ./fs/nfsd/nfs3xdr.c
@@ -796,7 +796,7 @@ encode_entry(struct readdir_cd *ccd, con
 	elen = slen + NFS3_ENTRY_BAGGAGE
 		+ (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
 	if (cd->buflen < elen) {
-		cd->common.err = nfserr_readdir_nospc;
+		cd->common.err = nfserr_toosmall;
 		return -EINVAL;
 	}
 	*p++ = xdr_one;				 /* mark entry present */
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +4 -4
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -1688,7 +1688,7 @@ out:
 	return 0;
 
 nospc:
-	cd->common.err = nfserr_readdir_nospc;
+	cd->common.err = nfserr_toosmall;
 	return -EINVAL;
 }
 
@@ -2097,7 +2097,7 @@ nfsd4_encode_readdir(struct nfsd4_compou
 	 */
 	maxcount = (maxcount >> 2) - 4;
 	if (maxcount < 0)
-		return nfserr_readdir_nospc;
+		return nfserr_toosmall;
 
 	svc_take_page(resp->rqstp);
 	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
@@ -2111,9 +2111,9 @@ nfsd4_encode_readdir(struct nfsd4_compou
 			      &offset,
 			      &readdir->common, nfsd4_encode_dirent);
 	if (nfserr == nfs_ok &&
-	    readdir->common.err == nfserr_readdir_nospc &&
+	    readdir->common.err == nfserr_toosmall &&
 	    readdir->buffer == page) 
-		nfserr = nfserr_readdir_nospc;
+		nfserr = nfserr_toosmall;
 	if (nfserr)
 		return nfserr;
 
fs/nfsd/nfsxdr.c renamed from fs/nfsd/nfsxdr.c~current~ +1 -1
diff ./fs/nfsd/nfsxdr.c~current~ ./fs/nfsd/nfsxdr.c
@@ -484,7 +484,7 @@ nfssvc_encode_entry(struct readdir_cd *c
 
 	slen = XDR_QUADLEN(namlen);
 	if ((buflen = cd->buflen - slen - 4) < 0) {
-		cd->common.err = nfserr_readdir_nospc;
+		cd->common.err = nfserr_toosmall;
 		return -EINVAL;
 	}
 	*p++ = xdr_one;				/* mark entry present */
fs/nfsd/vfs.c renamed from fs/nfsd/vfs.c~current~ +1 -1
diff ./fs/nfsd/vfs.c~current~ ./fs/nfsd/vfs.c
@@ -1494,7 +1494,7 @@ nfsd_readdir(struct svc_rqst *rqstp, str
 		err = cdp->err;
 	*offsetp = file.f_pos;
 
-	if (err == nfserr_eof || err == nfserr_readdir_nospc)
+	if (err == nfserr_eof || err == nfserr_toosmall)
 		err = nfs_ok; /* can still be found in ->err */
 out_close:
 	nfsd_close(&file);
include/linux/nfs.h renamed from include/linux/nfs.h~current~ +1 -1
diff ./include/linux/nfs.h~current~ ./include/linux/nfs.h
@@ -92,7 +92,7 @@
 	NFSERR_NOT_SAME = 10027,	/*       v4 */
 	NFSERR_LOCK_RANGE = 10028,	/*       v4 */
 	NFSERR_SYMLINK = 10029,		/*       v4 */
-	NFSERR_READDIR_NOSPC = 10030,	/*       v4 */
+	NFSERR_RESTOREFH = 10030,	/*       v4 */
 	NFSERR_LEASE_MOVED = 10031,	/*       v4 */
 	NFSERR_ATTRNOTSUPP = 10032,	/*       v4 */
 	NFSERR_NO_GRACE = 10033,	/*       v4 */
include/linux/nfsd/nfsd.h renamed from include/linux/nfsd/nfsd.h~current~ +1 -1
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
@@ -190,7 +190,7 @@ void		nfsd_lockd_shutdown(void);
 #define nfserr_bad_seqid	__constant_htonl(NFSERR_BAD_SEQID)
 #define	nfserr_symlink		__constant_htonl(NFSERR_SYMLINK)
 #define	nfserr_not_same		__constant_htonl(NFSERR_NOT_SAME)
-#define	nfserr_readdir_nospc	__constant_htonl(NFSERR_READDIR_NOSPC)
+#define	nfserr_restorefh	__constant_htonl(NFSERR_RESTOREFH)
 #define	nfserr_bad_xdr		__constant_htonl(NFSERR_BAD_XDR)
 #define	nfserr_openmode		__constant_htonl(NFSERR_OPENMODE)
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#6 lore raw

PATCH 1/1 kNFSd - 1 of 34 - Add minimal server-side support for rpcsec_gss.

In reply to NeilBrown

From: "J. Bruce Fields" <[email protected]>

Note that the user (or exportfs, on the user's behalf) allows a gss pseudoflavor to be used to access an export by exporting to a special client named "gss/pseudoflavor-name", e.g., "gss/krb5" or "gss/lipkey-i".

----------- Diffstat output ------------

 ./include/linux/sunrpc/auth_gss.h       |    2 
 ./include/linux/sunrpc/gss_api.h        |    3 
 ./include/linux/sunrpc/svc.h            |    1 
 ./include/linux/sunrpc/svcauth.h        |    5 
 ./include/linux/sunrpc/svcauth_gss.h    |   35 +
 ./net/sunrpc/auth_gss/Makefile          |    2 
 ./net/sunrpc/auth_gss/auth_gss.c        |   10 
 ./net/sunrpc/auth_gss/gss_krb5_mech.c   |    4 
 ./net/sunrpc/auth_gss/gss_mech_switch.c |   17 
 ./net/sunrpc/auth_gss/sunrpcgss_syms.c  |    2 
 ./net/sunrpc/auth_gss/svcauth_gss.c     |  885 ++++++++++++++++++++++++++++++++
 ./net/sunrpc/sunrpc_syms.c              |    2 
 ./net/sunrpc/svc.c                      |    4 
 13 files changed, 969 insertions(+), 3 deletions(-)
include/linux/sunrpc/auth_gss.h renamed from include/linux/sunrpc/auth_gss.h~current~ +0 -2
diff ./include/linux/sunrpc/auth_gss.h~current~ ./include/linux/sunrpc/auth_gss.h
@@ -62,8 +62,6 @@ struct rpc_gss_init_res {
 	struct xdr_netobj	gr_token;	/* token */
 };
 
-#define GSS_SEQ_WIN	5
-
 /* The gss_cl_ctx struct holds all the information the rpcsec_gss client
  * code needs to know about a single security context.  In particular,
  * gc_gss_ctx is the context handle that is used to do gss-api calls, while
include/linux/sunrpc/gss_api.h renamed from include/linux/sunrpc/gss_api.h~current~ +3 -0
diff ./include/linux/sunrpc/gss_api.h~current~ ./include/linux/sunrpc/gss_api.h
@@ -120,6 +120,9 @@ int gss_mech_unregister_all(void);
  * reference count. */
 struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *);
 
+/* Similar, but get by name like "krb5", "spkm", etc., instead of OID. */
+struct gss_api_mech *gss_mech_get_by_name(char *);
+
 /* Just increments the mechanism's reference count and returns its input: */
 struct gss_api_mech * gss_mech_get(struct gss_api_mech *);
 
include/linux/sunrpc/svc.h renamed from include/linux/sunrpc/svc.h~current~ +1 -0
diff ./include/linux/sunrpc/svc.h~current~ ./include/linux/sunrpc/svc.h
@@ -135,6 +135,7 @@ struct svc_rqst {
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
+	void *			rq_auth_data;	/* flavor-specific data */
 
 	int			rq_reserved;	/* space on socket outq
 						 * reserved for this request
include/linux/sunrpc/svcauth.h renamed from include/linux/sunrpc/svcauth.h~current~ +5 -0
diff ./include/linux/sunrpc/svcauth.h~current~ ./include/linux/sunrpc/svcauth.h
@@ -66,6 +66,10 @@ struct auth_domain {
  *      GARBAGE - rpc garbage_args error
  *      SYSERR - rpc system_err error
  *      DENIED - authp holds reason for denial.
+ *      COMPLETE - the reply is encoded already and ready to be sent; no
+ *		further processing is necessary.  (This is used for processing
+ *		null procedure calls which are used to set up encryption
+ *		contexts.)
  *
  *   accept is passed the proc number so that it can accept NULL rpc requests
  *   even if it cannot authenticate the client (as is sometimes appropriate).
@@ -98,6 +102,7 @@ extern struct auth_ops	*authtab[RPC_AUTH
 #define	SVC_DROP	6
 #define	SVC_DENIED	7
 #define	SVC_PENDING	8
+#define	SVC_COMPLETE	9
 
 
 extern int	svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
include/linux/sunrpc/svcauth_gss.h renamed from include/linux/sunrpc/svcauth_gss.h~current~ +35 -0
diff ./include/linux/sunrpc/svcauth_gss.h~current~ ./include/linux/sunrpc/svcauth_gss.h
@@ -0,0 +1,35 @@
+/*
+ * linux/include/linux/svcauth_gss.h
+ *
+ * Bruce Fields <[email protected]>
+ * Copyright (c) 2002 The Regents of the Unviersity of Michigan
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _LINUX_SUNRPC_SVCAUTH_GSS_H
+#define _LINUX_SUNRPC_SVCAUTH_GSS_H
+
+#ifdef __KERNEL__
+#include <linux/sched.h>
+#include <linux/sunrpc/types.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/svcauth.h>
+#include <linux/sunrpc/svcsock.h>
+#include <linux/sunrpc/auth_gss.h>
+
+int gss_svc_init(void);
+int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+
+
+struct gss_svc_data {
+	/* decoded gss client cred: */
+	struct rpc_gss_wire_cred	clcred;
+	/* pointer to the beginning of the procedure-specific results, which
+	 * may be encrypted/checksummed in svcauth_gss_release: */
+	u32				*body_start;
+};
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
net/sunrpc/auth_gss/Makefile renamed from net/sunrpc/auth_gss/Makefile~current~ +1 -1
diff ./net/sunrpc/auth_gss/Makefile~current~ ./net/sunrpc/auth_gss/Makefile
@@ -5,7 +5,7 @@
 obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o
 
 auth_rpcgss-objs := auth_gss.o gss_pseudoflavors.o gss_generic_token.o \
-	sunrpcgss_syms.o gss_mech_switch.o
+	sunrpcgss_syms.o gss_mech_switch.o svcauth_gss.o
 
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
net/sunrpc/auth_gss/auth_gss.c renamed from net/sunrpc/auth_gss/auth_gss.c~current~ +10 -0
diff ./net/sunrpc/auth_gss/auth_gss.c~current~ ./net/sunrpc/auth_gss/auth_gss.c
@@ -48,6 +48,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth_gss.h>
+#include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/gss_err.h>
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
@@ -972,6 +973,15 @@ static int __init init_rpcsec_gss(void)
 	int err = 0;
 
 	err = rpcauth_register(&authgss_ops);
+	if (err)
+		goto out;
+	err = gss_svc_init();
+	if (err)
+		goto out_unregister;
+	return 0;
+out_unregister:
+	rpcauth_unregister(&authgss_ops);
+out:
 	return err;
 }
 
net/sunrpc/auth_gss/gss_krb5_mech.c renamed from net/sunrpc/auth_gss/gss_krb5_mech.c~current~ +4 -0
diff ./net/sunrpc/auth_gss/gss_krb5_mech.c~current~ ./net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -39,6 +39,8 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/auth.h>
+#include <linux/in.h>
+#include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/crypto.h>
@@ -232,6 +234,8 @@ static int __init init_kerberos_module(v
 	gm = gss_mech_get_by_OID(&gss_mech_krb5_oid);
 	gss_register_triple(RPC_AUTH_GSS_KRB5 , gm, 0, RPC_GSS_SVC_NONE);
 	gss_register_triple(RPC_AUTH_GSS_KRB5I, gm, 0, RPC_GSS_SVC_INTEGRITY);
+	if (svcauth_gss_register_pseudoflavor(RPC_AUTH_GSS_KRB5, "krb5"))
+		printk("Failed to register %s with server!\n", "krb5");
 	gss_mech_put(gm);
 	return 0;
 }
net/sunrpc/auth_gss/gss_mech_switch.c renamed from net/sunrpc/auth_gss/gss_mech_switch.c~current~ +17 -0
diff ./net/sunrpc/auth_gss/gss_mech_switch.c~current~ ./net/sunrpc/auth_gss/gss_mech_switch.c
@@ -162,6 +162,23 @@ gss_mech_get_by_OID(struct xdr_netobj *m
 	return gm;
 }
 
+struct gss_api_mech *
+gss_mech_get_by_name(char *name)
+{
+	struct gss_api_mech	*pos, *gm = NULL;
+
+	spin_lock(&registered_mechs_lock);
+	list_for_each_entry(pos, &registered_mechs, gm_list) {
+		if (0 == strcmp(name, pos->gm_ops->name)) {
+			gm = gss_mech_get(pos);
+			break;
+		}
+	}
+	spin_unlock(&registered_mechs_lock);
+	return gm;
+
+}
+
 int
 gss_mech_put(struct gss_api_mech * gm)
 {
net/sunrpc/auth_gss/sunrpcgss_syms.c renamed from net/sunrpc/auth_gss/sunrpcgss_syms.c~current~ +2 -0
diff ./net/sunrpc/auth_gss/sunrpcgss_syms.c~current~ ./net/sunrpc/auth_gss/sunrpcgss_syms.c
@@ -8,6 +8,7 @@
 #include <linux/unistd.h>
 
 #include <linux/sunrpc/auth_gss.h>
+#include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/gss_asn1.h>
 
 /* sec_triples: */
@@ -17,6 +18,7 @@ EXPORT_SYMBOL(gss_cmp_triples);
 EXPORT_SYMBOL(gss_pseudoflavor_to_mechOID);
 EXPORT_SYMBOL(gss_pseudoflavor_supported);
 EXPORT_SYMBOL(gss_pseudoflavor_to_service);
+EXPORT_SYMBOL(svcauth_gss_register_pseudoflavor);
 
 /* registering gss mechanisms to the mech switching code: */
 EXPORT_SYMBOL(gss_mech_register);
net/sunrpc/auth_gss/svcauth_gss.c renamed from net/sunrpc/auth_gss/svcauth_gss.c~current~ +885 -0

885 lines not on this page · raw message

net/sunrpc/sunrpc_syms.c renamed from net/sunrpc/sunrpc_syms.c~current~ +2 -0
diff ./net/sunrpc/sunrpc_syms.c~current~ ./net/sunrpc/sunrpc_syms.c
@@ -85,6 +85,8 @@ EXPORT_SYMBOL(svc_recv);
 EXPORT_SYMBOL(svc_wake_up);
 EXPORT_SYMBOL(svc_makesock);
 EXPORT_SYMBOL(svc_reserve);
+EXPORT_SYMBOL(svc_auth_register);
+EXPORT_SYMBOL(auth_domain_lookup);
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
net/sunrpc/svc.c renamed from net/sunrpc/svc.c~current~ +4 -0
diff ./net/sunrpc/svc.c~current~ ./net/sunrpc/svc.c
@@ -200,6 +200,8 @@ svc_exit_thread(struct svc_rqst *rqstp)
 		kfree(rqstp->rq_resp);
 	if (rqstp->rq_argp)
 		kfree(rqstp->rq_argp);
+	if (rqstp->rq_auth_data)
+		kfree(rqstp->rq_auth_data);
 	kfree(rqstp);
 
 	/* Release the server */
@@ -322,6 +324,8 @@ svc_process(struct svc_serv *serv, struc
 		goto err_bad_auth;
 	case SVC_DROP:
 		goto dropit;
+	case SVC_COMPLETE:
+		goto sendit;
 	}
 		
 	progp = serv->sv_program;

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#7 lore raw

PATCH 1/1 kNFSd - 3 of 34 - IDmap support for the NFSv4 server.

In reply to NeilBrown

Updated version which uses ascii-encoding of messages, from
http://www.citi.umich.edu/u/marius/linux-2.5.70-idmap-server-new.diff
as of October 14, 2003.

----------- Diffstat output ------------

 ./fs/nfsd/Makefile                      |    2 
 ./fs/nfsd/nfs4idmap.c                   |  569 ++++++++++++++++++++++++++++++++
 ./fs/nfsd/nfs4proc.c                    |    3 
 ./fs/nfsd/nfs4xdr.c                     |   54 +--
 ./fs/nfsd/nfsctl.c                      |    7 
 ./fs/nfsd/nfsproc.c                     |    1 
 ./include/linux/nfsd/xdr4.h             |    6 
 ./include/linux/nfsd_idmap.h            |   54 +++
 ./net/sunrpc/auth_gss/gss_mech_switch.c |    1 
 9 files changed, 668 insertions(+), 29 deletions(-)
fs/nfsd/Makefile renamed from fs/nfsd/Makefile~current~ +1 -1
diff ./fs/nfsd/Makefile~current~ ./fs/nfsd/Makefile
@@ -7,5 +7,5 @@ obj-$(CONFIG_NFSD)	+= nfsd.o
 nfsd-y 			:= nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
 			   export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
 nfsd-$(CONFIG_NFSD_V3)	+= nfs3proc.o nfs3xdr.o
-nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o
+nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o
 nfsd-objs		:= $(nfsd-y)
fs/nfsd/nfs4idmap.c renamed from fs/nfsd/nfs4idmap.c~current~ +569 -0

569 lines not on this page · raw message

fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +2 -1
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -568,7 +568,8 @@ nfsd4_verify(struct svc_rqst *rqstp, str
 
 	status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
 				    current_fh->fh_dentry, buf,
-				    &count, verify->ve_bmval);
+				    &count, verify->ve_bmval,
+				    rqstp);
 
 	/* this means that nfsd4_encode_fattr() ran out of space */
 	if (status == nfserr_resource && count == 0)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +30 -24

131 lines not on this page · raw message

fs/nfsd/nfsctl.c renamed from fs/nfsd/nfsctl.c~current~ +7 -0
diff ./fs/nfsd/nfsctl.c~current~ ./fs/nfsd/nfsctl.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 
 #include <linux/nfs.h>
+#include <linux/nfsd_idmap.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
@@ -436,6 +437,9 @@ static int __init init_nfsd(void)
 	nfsd_cache_init();	/* RPC reply cache */
 	nfsd_export_init();	/* Exports table */
 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+#ifdef CONFIG_NFSD_V4
+	nfsd_idmap_init();      /* Name to ID mapping */
+#endif /* CONFIG_NFSD_V4 */
 	if (proc_mkdir("fs/nfs", 0)) {
 		struct proc_dir_entry *entry;
 		entry = create_proc_entry("fs/nfs/exports", 0, NULL);
@@ -462,6 +466,9 @@ static void __exit exit_nfsd(void)
 	remove_proc_entry("fs/nfs", NULL);
 	nfsd_stat_shutdown();
 	nfsd_lockd_shutdown();
+#ifdef CONFIG_NFSD_V4
+	nfsd_idmap_shutdown();
+#endif /* CONFIG_NFSD_V4 */
 	unregister_filesystem(&nfsd_fs_type);
 }
 
fs/nfsd/nfsproc.c renamed from fs/nfsd/nfsproc.c~current~ +1 -0
diff ./fs/nfsd/nfsproc.c~current~ ./fs/nfsd/nfsproc.c
@@ -585,6 +585,7 @@ nfserrno (int errno)
 		{ nfserr_dquot, -EDQUOT },
 #endif
 		{ nfserr_stale, -ESTALE },
+		{ nfserr_jukebox, -ETIMEDOUT },
 		{ nfserr_dropit, -EAGAIN },
 		{ nfserr_dropit, -ENOMEM },
 		{ -1, -EIO }
include/linux/nfsd/xdr4.h renamed from include/linux/nfsd/xdr4.h~current~ +4 -2
diff ./include/linux/nfsd/xdr4.h~current~ ./include/linux/nfsd/xdr4.h
@@ -375,7 +375,9 @@ struct nfsd4_compoundargs {
 		struct tmpbuf *next;
 		void *buf;
 	}				*to_free;
-	
+
+	struct svc_rqst			*rqstp;
+
 	u32				taglen;
 	char *				tag;
 	u32				minorversion;
@@ -419,7 +421,7 @@ void nfsd4_encode_operation(struct nfsd4
 void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
 int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 		       struct dentry *dentry, u32 *buffer, int *countp, 
-		       u32 *bmval);
+		       u32 *bmval, struct svc_rqst *);
 extern int nfsd4_setclientid(struct svc_rqst *rqstp, 
 		struct nfsd4_setclientid *setclid);
 extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, 
include/linux/nfsd_idmap.h renamed from include/linux/nfsd_idmap.h~current~ +54 -0

54 lines not on this page · raw message

net/sunrpc/auth_gss/gss_mech_switch.c renamed from net/sunrpc/auth_gss/gss_mech_switch.c~current~ +0 -1
diff ./net/sunrpc/auth_gss/gss_mech_switch.c~current~ ./net/sunrpc/auth_gss/gss_mech_switch.c
@@ -43,7 +43,6 @@
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/gss_api.h>
 #include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/name_lookup.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY        RPCDBG_AUTH

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#8 lore raw

PATCH 1/1 kNFSd - 2 of 34 - gss api changes for integrity checking.

In reply to NeilBrown

Doesn't actually add integrity support on the server yet; just adapts server-side code to the gss api changes necessary to get integrity working on the client.

----------- Diffstat output ------------

 ./net/sunrpc/auth_gss/gss_krb5_seal.c |    3 ---
 ./net/sunrpc/auth_gss/svcauth_gss.c   |   16 ++++++++++------
 2 files changed, 10 insertions(+), 9 deletions(-)
net/sunrpc/auth_gss/gss_krb5_seal.c renamed from net/sunrpc/auth_gss/gss_krb5_seal.c~current~ +0 -3
diff ./net/sunrpc/auth_gss/gss_krb5_seal.c~current~ ./net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -169,8 +169,5 @@ krb5_make_token(struct krb5_ctx *ctx, in
 	return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
 out_err:
 	if (md5cksum.data) kfree(md5cksum.data);
-	if (token->data) kfree(token->data);
-	token->data = 0;
-	token->len = 0;
 	return GSS_S_FAILURE;
 }
net/sunrpc/auth_gss/svcauth_gss.c renamed from net/sunrpc/auth_gss/svcauth_gss.c~current~ +10 -6
diff ./net/sunrpc/auth_gss/svcauth_gss.c~current~ ./net/sunrpc/auth_gss/svcauth_gss.c
@@ -531,14 +531,16 @@ gss_verify_header(struct svc_rqst *rqstp
 		  u32 *rpcstart, struct rpc_gss_wire_cred *gc, u32 *authp)
 {
 	struct gss_ctx		*ctx_id = rsci->mechctx;
-	struct xdr_netobj	rpchdr;
+	struct xdr_buf		rpchdr;
 	struct xdr_netobj	checksum;
 	u32			flavor = 0;
 	struct iovec		*argv = &rqstp->rq_arg.head[0];
+	struct iovec		iov;
 
 	/* data to compute the checksum over: */
-	rpchdr.data = (u8 *)rpcstart;
-	rpchdr.len = (u8 *)argv->iov_base - (u8 *)rpcstart;
+	iov.iov_base = rpcstart;
+	iov.iov_len = (u8 *)argv->iov_base - (u8 *)rpcstart;
+	xdr_buf_from_iov(&iov, &rpchdr);
 
 	*authp = rpc_autherr_badverf;
 	if (argv->iov_len < 4)
@@ -576,15 +578,17 @@ gss_write_verf(struct svc_rqst *rqstp, s
 {
 	u32			xdr_seq;
 	u32			maj_stat;
-	struct xdr_netobj	verf_data;
+	struct xdr_buf		verf_data;
 	struct xdr_netobj	mic;
 	u32			*p;
+	struct iovec		iov;
 
 	svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_GSS));
 	xdr_seq = htonl(seq);
 
-	verf_data.data = (u8 *)&xdr_seq;
-	verf_data.len = sizeof(xdr_seq);
+	iov.iov_base = &xdr_seq;
+	iov.iov_len = sizeof(xdr_seq);
+	xdr_buf_from_iov(&iov, &verf_data);
 	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
 	maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
 	if (maj_stat != GSS_S_COMPLETE)

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#9 lore raw

PATCH 1/1 kNFSd - 6 of 34 - v4 exclusive open fix.

In reply to NeilBrown

Exclusive creates were failing with permission errors, because they don't set the mode on the newly created file, and the permission check in fh_verify (called at the end of do_open_lookup) was failing. So pass in the MAY_OWNER_OVERRIDE flag to allow the owner of the file to override the permission check.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |    1 +
 1 files changed, 1 insertion(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +1 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -95,6 +95,7 @@ do_open_lookup(struct svc_rqst *rqstp, s
 			accmode = MAY_READ;
 		if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
 			accmode |= (MAY_WRITE | MAY_TRUNC);
+		accmode |= MAY_OWNER_OVERRIDE;
 		status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
 	}
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#10 lore raw

PATCH 1/1 kNFSd - 9 of 34 - NFSdV4 fixes for replaying open requests.

In reply to NeilBrown

Since the open op changes the current filehandle, we can't correctly replay compounds containing opens unless we save the filehandle resulting from the open as well as the encoded reply.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c         |   19 +++++++++++++++++++
 ./fs/nfsd/nfs4xdr.c          |    1 +
 ./include/linux/nfsd/state.h |    2 ++
 3 files changed, 22 insertions(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +19 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -89,6 +89,12 @@ do_open_lookup(struct svc_rqst *rqstp, s
 	if (!status) {
 		set_change_info(&open->op_cinfo, current_fh);
 		fh_dup2(current_fh, &resfh);
+		/* XXXJBF: keep a saved svc_fh struct instead?? */
+		open->op_stateowner->so_replay.rp_openfh_len =
+			resfh.fh_handle.fh_size;
+		memcpy(open->op_stateowner->so_replay.rp_openfh,
+				&resfh.fh_handle.fh_base,
+				resfh.fh_handle.fh_size);
 
 		accmode = MAY_NOP;
 		if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
@@ -116,6 +122,19 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 
 	/* check seqid for replay. set nfs4_owner */
 	status = nfsd4_process_open1(open);
+	if (status == NFSERR_REPLAY_ME) {
+		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
+		fh_put(current_fh);
+		current_fh->fh_handle.fh_size = rp->rp_openfh_len;
+		memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
+				rp->rp_openfh_len);
+		status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+		if (status)
+			dprintk("nfsd4_open: replay failed"
+				" restoring previous filehandle\n");
+		else
+			status = NFSERR_REPLAY_ME;
+	}
 	if (status)
 		return status;
 	/*
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +1 -0
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -1913,6 +1913,7 @@ nfsd4_encode_open(struct nfsd4_compoundr
 	default:
 		BUG();
 	}
+	/* XXX save filehandle here */
 
 	ENCODE_SEQID_OP_TAIL(open->op_stateowner);
 }
include/linux/nfsd/state.h renamed from include/linux/nfsd/state.h~current~ +2 -0
diff ./include/linux/nfsd/state.h~current~ ./include/linux/nfsd/state.h
@@ -113,6 +113,8 @@ struct nfs4_replay {
 	unsigned int		rp_buflen;
 	char			*rp_buf;
 	unsigned		intrp_allocated;
+	int			rp_openfh_len;
+	char			rp_openfh[NFS4_FHSIZE];
 	char			rp_ibuf[NFSD4_REPLAY_ISIZE];
 };
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#11 lore raw

PATCH 1/1 kNFSd - 10 of 34 - Use only the uid when deciding whether a setclientid is being done with the "same principal".

In reply to NeilBrown

I would have assumed that we should also check for the same security (pseudo)flavor, but that doesn't seem to be how Solaris does it, and since the spec doesn't suggest including such information in the clientid, that would make it impossible to switch pseudoflavors.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    3 +--
 1 files changed, 1 insertion(+), 2 deletions(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +1 -2
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -269,8 +269,7 @@ cmp_clid(clientid_t * cl1, clientid_t * 
 /* XXX what about NGROUP */
 static int
 cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){
-	return((cr1->cr_uid == cr2->cr_uid) &&
-	   	(cr1->cr_gid == cr2->cr_gid));
+	return(cr1->cr_uid == cr2->cr_uid);
 
 }
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#12 lore raw

PATCH 1/1 kNFSd - 15 of 34 - Correct error returns.

In reply to NeilBrown

Call decode_fattr on writable attributes to check for xdr errors, incorrect utf8, etc.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c        |    5 +++--
 ./fs/nfsd/nfs4xdr.c         |   21 +++++++++++++++++++++
 ./include/linux/nfsd/nfsd.h |    1 +
 3 files changed, 25 insertions(+), 2 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +3 -2
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -584,8 +584,9 @@ nfsd4_verify(struct svc_rqst *rqstp, str
 
 	if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
 	    || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
-		return nfserr_notsupp;
-	if (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
+		return nfserr_attrnotsupp;
+	if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
+	    || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
 		return nfserr_inval;
 	if (verify->ve_attrlen & 3)
 		return nfserr_inval;
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +21 -0
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -908,10 +908,31 @@ nfsd4_decode_setclientid_confirm(struct 
 static int
 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
 {
+#if 0
+	struct nfsd4_compoundargs save = {
+		.p = argp->p,
+		.end = argp->end,
+		.rqstp = argp->rqstp,
+	};
+	u32             ve_bmval[2];
+	struct iattr    ve_iattr;           /* request */
+	struct nfs4_acl *ve_acl;            /* request */
+#endif
 	DECODE_HEAD;
 
 	if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
 		goto out;
+
+	/* For convenience's sake, we compare raw xdr'd attributes in
+	 * nfsd4_proc_verify; however we still decode here just to return
+	 * correct error in case of bad xdr. */
+#if 0
+	status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
+	if (status == nfserr_inval) {
+		status = nfserrno(status);
+		goto out;
+	}
+#endif	
 	READ_BUF(4);
 	READ32(verify->ve_attrlen);
 	READ_BUF(verify->ve_attrlen);
include/linux/nfsd/nfsd.h renamed from include/linux/nfsd/nfsd.h~current~ +1 -0
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
@@ -191,6 +191,7 @@ void		nfsd_lockd_shutdown(void);
 #define	nfserr_symlink		__constant_htonl(NFSERR_SYMLINK)
 #define	nfserr_not_same		__constant_htonl(NFSERR_NOT_SAME)
 #define	nfserr_restorefh	__constant_htonl(NFSERR_RESTOREFH)
+#define	nfserr_attrnotsupp	__constant_htonl(NFSERR_ATTRNOTSUPP)
 #define	nfserr_bad_xdr		__constant_htonl(NFSERR_BAD_XDR)
 #define	nfserr_openmode		__constant_htonl(NFSERR_OPENMODE)
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#13 lore raw

PATCH 1/1 kNFSd - 5 of 34 - NFSv4 locking state fix

In reply to NeilBrown

It's OK for the find_lockstateowner_str to fail; that just means we haven't seen the lockowner, and will compare the request range to all locks on the file.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +2 -6
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1993,13 +1993,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
 	strhashval = lock_ownerstr_hashval(inode, 
 			lockt->lt_clientid.cl_id, lockt->lt_owner);
 
-	if (find_lockstateowner_str(strhashval, &lockt->lt_owner, 
+	find_lockstateowner_str(strhashval, &lockt->lt_owner, 
 					&lockt->lt_clientid, 
-					&lockt->lt_stateowner)) {
-		printk("NFSD: nsfd4_lockt: lookup_lockowner() failed!\n");
-		goto out;
-	}
-
+					&lockt->lt_stateowner);
 	sop = lockt->lt_stateowner;
 	if (sop) {
 		file_lock.fl_owner = (fl_owner_t) sop;

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#14 lore raw

PATCH 1/1 kNFSd - 11 of 34 - When looking for a shareowner in the nfsd open, make sure we don't get a lockowner instead.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +1 -1
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1139,7 +1139,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
 						GFP_KERNEL)) == NULL)
 			goto out;
 
-		if (open->op_share_access && NFS4_SHARE_ACCESS_WRITE)
+		if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
 			flags = MAY_WRITE;
 		else
 			flags = MAY_READ;

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#15 lore raw

PATCH 1/1 kNFSd - 13 of 34 - correctly tests and sets nfserr_nofilehandle for current and save fh.

In reply to NeilBrown

nfsd4_restore_fh() returns nfserr_restorefh instead of nfserr_nofilehandle

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |   32 ++++++++++++++++++++++++++++----
 ./fs/nfsd/nfs4xdr.c  |   10 ++++++++--
 2 files changed, 36 insertions(+), 6 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +28 -4
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -192,7 +192,7 @@ static inline int
 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
 {
 	if (!save_fh->fh_dentry)
-		return nfserr_nofilehandle;
+		return nfserr_restorefh;
 
 	fh_dup2(current_fh, save_fh);
 	return nfs_ok;
@@ -336,8 +336,10 @@ static inline int
 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	   struct svc_fh *save_fh, struct nfsd4_link *link)
 {
-	int status;
+	int status = nfserr_nofilehandle;
 
+	if (!save_fh->fh_dentry)
+		return status;
 	status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
 	if (!status)
 		set_change_info(&link->li_cinfo, current_fh);
@@ -458,8 +460,10 @@ static inline int
 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	     struct svc_fh *save_fh, struct nfsd4_rename *rename)
 {
-	int status;
+	int status = nfserr_nofilehandle;
 
+	if (!save_fh->fh_dentry)
+		return status;
 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
 			     rename->rn_snamelen, current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
@@ -474,8 +478,12 @@ static inline int
 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
 {
 	struct nfs4_stateid *stp;
-	int status = nfs_ok;
+	int status = nfserr_nofilehandle;
+
+	if (!current_fh->fh_dentry)
+		goto out;
 
+	status = nfs_ok;
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 
 		status = nfserr_bad_stateid;
@@ -679,6 +687,22 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			goto encode_op;
 		}
 
+		/* All operations except RENEW, SETCLIENTID, RESTOREFH
+		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 
+		* require a valid current filehandle 
+		*
+		* SETATTR NOFILEHANDLE error handled in nfsd4_setattr
+		* due to required returned bitmap argument
+		*/ 
+		if ((!current_fh.fh_dentry) && 
+		   !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
+		   (op->opnum == OP_SETCLIENTID) ||
+		   (op->opnum == OP_SETCLIENTID_CONFIRM) ||
+		   (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
+		   (op->opnum == OP_SETATTR))) {
+			op->status = nfserr_nofilehandle;
+			goto encode_op;
+		}
 		switch (op->opnum) {
 		case OP_ACCESS:
 			op->status = nfsd4_access(rqstp, &current_fh, &op->u.access);
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +8 -2
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -2226,8 +2226,14 @@ nfsd4_encode_operation(struct nfsd4_comp
 
 	RESERVE_SPACE(8);
 	WRITE32(op->opnum);
-	statp = p++;                  /* to be backfilled at the end */
-	ADJUST_ARGS();
+	if ((op->opnum != OP_SETATTR) && (op->opnum != OP_LOCK) && (op->opnum != OP_LOCKT) && (op->opnum != OP_SETCLIENTID) && (op->status)) { 
+		*p++ = op->status;              
+		ADJUST_ARGS();
+		return;
+	} else {
+		statp = p++;        /* to be backfilled at the end */
+		ADJUST_ARGS();
+	}
 
 	switch (op->opnum) {
 	case OP_ACCESS:

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#16 lore raw

PATCH 1/1 kNFSd - 16 of 34 - fixes an xdr error by removing the verifier from error return.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +11 -4
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -2091,7 +2091,7 @@ nfsd4_encode_readdir(struct nfsd4_compou
 {
 	int maxcount;
 	loff_t offset;
-	u32 *page;
+	u32 *page, *savep;
 	ENCODE_HEAD;
 
 	if (nfserr)
@@ -2100,6 +2100,7 @@ nfsd4_encode_readdir(struct nfsd4_compou
 		return nfserr_resource;
 
 	RESERVE_SPACE(8);  /* verifier */
+	savep = p;
 
 	/* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
 	WRITE32(0);
@@ -2117,8 +2118,10 @@ nfsd4_encode_readdir(struct nfsd4_compou
 	 * pointer and eof field.
 	 */
 	maxcount = (maxcount >> 2) - 4;
-	if (maxcount < 0)
-		return nfserr_toosmall;
+	if (maxcount < 0) {
+		nfserr =  nfserr_toosmall;
+		goto err_no_verf;
+	}
 
 	svc_take_page(resp->rqstp);
 	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
@@ -2136,7 +2139,7 @@ nfsd4_encode_readdir(struct nfsd4_compou
 	    readdir->buffer == page) 
 		nfserr = nfserr_toosmall;
 	if (nfserr)
-		return nfserr;
+		goto err_no_verf;
 
 	if (readdir->offset)
 		xdr_encode_hyper(readdir->offset, offset);
@@ -2156,6 +2159,10 @@ nfsd4_encode_readdir(struct nfsd4_compou
 	resp->end = resp->p + PAGE_SIZE/4;
 
 	return 0;
+err_no_verf:
+	p = savep;
+	ADJUST_ARGS();
+	return nfserr;
 }
 
 static void

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#17 lore raw

PATCH 1/1 kNFSd - 17 of 34 - correct symlink related error returns.

In reply to NeilBrown

unlike v2/v3, nfsv4 returns nfserr_inval when attempting to read, write, commit or test lock a symlink. nfsv4 does return nfserr_symlink on lookup and open, so a simple fix in fh_verify() will not work.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c  |   14 +++++++++++---
 ./fs/nfsd/nfs4state.c |    2 ++
 ./fs/nfsd/nfs4xdr.c   |    2 ++
 3 files changed, 15 insertions(+), 3 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +11 -3
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -224,11 +224,16 @@ nfsd4_access(struct svc_rqst *rqstp, str
 static inline int
 nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
 {
+	int status;
+
 	u32 *p = (u32 *)commit->co_verf.data;
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	return nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+	status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+	if (status == nfserr_symlink)
+		status = nfserr_inval;
+	return status;
 }
 
 static inline int
@@ -558,9 +563,12 @@ zero_stateid:
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	return (nfsd_write(rqstp, current_fh, write->wr_offset,
+	status =  nfsd_write(rqstp, current_fh, write->wr_offset,
 			  write->wr_vec, write->wr_vlen, write->wr_buflen,
-			  &write->wr_how_written));
+			  &write->wr_how_written);
+	if (status == nfserr_symlink)
+		status = nfserr_inval;
+	return status;
 out:
 	nfs4_unlock_state();
 	return status;
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +2 -0
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1973,6 +1973,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
 
 	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
 		printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
+		if (status == nfserr_symlink)
+			status = nfserr_inval;
 		goto out;
 	}
 
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +2 -0
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -2005,6 +2005,8 @@ nfsd4_encode_read(struct nfsd4_compoundr
 			   read->rd_offset,
 			   read->rd_iov, read->rd_vlen,
 			   &maxcount);
+	if (nfserr == nfserr_symlink)
+		nfserr = nfserr_inval;
 	if (nfserr)
 		return nfserr;
 	eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#18 lore raw

PATCH 1/1 kNFSd - 18 of 34 - check lock length, return appropriate error

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +17 -0
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1783,6 +1783,13 @@ out:
 	return stp;
 }
 
+int
+check_lock_length(u64 offset, u64 length)
+{
+	return ((length == 0)  || ((length != ~(u64)0) && 
+ 	     LOFF_OVERFLOW(offset, length)));
+}
+
 /*
  *  LOCK operation 
  */
@@ -1801,6 +1808,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 		(long long) lock->lk_offset,
 		(long long) lock->lk_length);
 
+	if (check_lock_length(lock->lk_offset, lock->lk_length))
+		 return nfserr_inval;
+
 	lock->lk_stateowner = NULL;
 	nfs4_lock_state();
 
@@ -1962,6 +1972,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
 	unsigned int strhashval;
 	int status;
 
+	if (check_lock_length(lockt->lt_offset, lockt->lt_length))
+		 return nfserr_inval;
+
 	lockt->lt_stateowner = NULL;
 	nfs4_lock_state();
 
@@ -2048,6 +2061,10 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
 		(long long) locku->lu_offset,
 		(long long) locku->lu_length);
+
+	if (check_lock_length(locku->lu_offset, locku->lu_length))
+		 return nfserr_inval;
+
 	nfs4_lock_state();
 									        
 	if ((status = nfs4_preprocess_seqid_op(current_fh, 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#19 lore raw

PATCH 1/1 kNFSd - 19 of 34 - correct rename error returns.

In reply to NeilBrown

unlike v2/v3, nfsv4 returns nfserr_exist in some situations where the underlying filesystem returns nfserr_isdir, nfserr_notdir.

on rename, nfsv4 returns nfserr_notdir instead of nfserr_symlink.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |   12 ++++++++++++
 1 files changed, 12 insertions(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +12 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -476,6 +476,18 @@ nfsd4_rename(struct svc_rqst *rqstp, str
 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
 			     rename->rn_snamelen, current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
+
+	/* the underlying filesystem returns different error's than required
+	 * by NFSv4. both save_fh and current_fh have been verified.. */
+	if (status == nfserr_isdir) 
+		status = nfserr_exist;
+	else if ((status == nfserr_notdir) && 
+                  (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) && 
+                   S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+		status = nfserr_exist;
+	else if (status == nfserr_symlink)
+		status = nfserr_notdir;
+
 	if (!status) {
 		set_change_info(&rename->rn_sinfo, current_fh);
 		set_change_info(&rename->rn_tinfo, save_fh);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#20 lore raw

PATCH 1/1 kNFSd - 20 of 34 - unlock-on-close fix

In reply to NeilBrown

add the bookeeping necessary to remove all locks held by an nfsv4 lockowner upon CLOSE, or upon state expiration. calls locks_remove_posix().

replace list_del_init() with list_del on nfsv4 state structures that are being reaped.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c        |   46 +++++++++++++++++++++++++++++++------------
 ./include/linux/nfsd/state.h |    5 ++++
 2 files changed, 39 insertions(+), 12 deletions(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +34 -12
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -771,6 +771,7 @@ alloc_init_open_stateowner(unsigned int 
 	INIT_LIST_HEAD(&sop->so_strhash);
 	INIT_LIST_HEAD(&sop->so_perclient);
 	INIT_LIST_HEAD(&sop->so_perfilestate);
+	INIT_LIST_HEAD(&sop->so_perlockowner);  /* not used */
 	list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
 	list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
 	list_add(&sop->so_perclient, &clp->cl_perclient);
@@ -789,13 +790,28 @@ alloc_init_open_stateowner(unsigned int 
 }
 
 static void
+release_stateid_lockowner(struct nfs4_stateid *open_stp)
+{
+	struct nfs4_stateowner *lock_sop;	
+	
+	while (!list_empty(&open_stp->st_perlockowner)) {
+		lock_sop = list_entry(open_stp->st_perlockowner.next,
+				struct nfs4_stateowner, so_perlockowner);
+		/* list_del(&open_stp->st_perlockowner);  */
+		BUG_ON(lock_sop->so_is_open_owner);
+		release_stateowner(lock_sop);
+	}
+}
+
+static void
 release_stateowner(struct nfs4_stateowner *sop)
 {
 	struct nfs4_stateid *stp;
 
-	list_del_init(&sop->so_idhash);
-	list_del_init(&sop->so_strhash);
-	list_del_init(&sop->so_perclient);
+	list_del(&sop->so_idhash);
+	list_del(&sop->so_strhash);
+	list_del(&sop->so_perclient);
+	list_del(&sop->so_perlockowner);
 	del_perclient++;
 	while (!list_empty(&sop->so_perfilestate)) {
 		stp = list_entry(sop->so_perfilestate.next, 
@@ -814,6 +830,7 @@ init_stateid(struct nfs4_stateid *stp, s
 
 	INIT_LIST_HEAD(&stp->st_hash);
 	INIT_LIST_HEAD(&stp->st_perfilestate);
+	INIT_LIST_HEAD(&stp->st_perlockowner);
 	INIT_LIST_HEAD(&stp->st_perfile);
 	list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
@@ -832,17 +849,21 @@ init_stateid(struct nfs4_stateid *stp, s
 static void
 release_stateid(struct nfs4_stateid *stp, int flags) {
 
-	list_del_init(&stp->st_hash);
+	list_del(&stp->st_hash);
 	list_del_perfile++;
-	list_del_init(&stp->st_perfile);
-	list_del_init(&stp->st_perfilestate);
+	list_del(&stp->st_perfile);
+	list_del(&stp->st_perfilestate);
 	if((stp->st_vfs_set) && (flags & OPEN_STATE)) {
+		release_stateid_lockowner(stp);
 		nfsd_close(&stp->st_vfs_file);
 		vfsclose++;
 		dput(stp->st_vfs_file.f_dentry);
 		mntput(stp->st_vfs_file.f_vfsmnt);
+	} else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
+		struct file *filp = &stp->st_vfs_file;
+
+		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
 	}
-	/* should use a slab cache */
 	kfree(stp);
 	stp = NULL;
 }
@@ -851,7 +872,7 @@ static void
 release_file(struct nfs4_file *fp)
 {
 	free_file++;
-	list_del_init(&fp->fi_hash);
+	list_del(&fp->fi_hash);
 	iput(fp->fi_inode);
 	kfree(fp);
 }	
@@ -1722,7 +1743,7 @@ find_lockstateowner_str(unsigned int has
  */
 
 static struct nfs4_stateowner *
-alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_lock *lock) {
+alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_stateid *open_stp, struct nfsd4_lock *lock) {
 	struct nfs4_stateowner *sop;
 	struct nfs4_replay *rp;
 	unsigned int idhashval;
@@ -1734,9 +1755,11 @@ alloc_init_lock_stateowner(unsigned int 
 	INIT_LIST_HEAD(&sop->so_strhash);
 	INIT_LIST_HEAD(&sop->so_perclient);
 	INIT_LIST_HEAD(&sop->so_perfilestate);
+	INIT_LIST_HEAD(&sop->so_perlockowner);
 	list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
 	list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
 	list_add(&sop->so_perclient, &clp->cl_perclient);
+	list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
 	add_perclient++;
 	sop->so_is_open_owner = 0;
 	sop->so_id = current_ownerid++;
@@ -1760,10 +1783,10 @@ alloc_init_lock_stateid(struct nfs4_stat
 	if ((stp = kmalloc(sizeof(struct nfs4_stateid), 
 					GFP_KERNEL)) == NULL)
 		goto out;
-
 	INIT_LIST_HEAD(&stp->st_hash);
 	INIT_LIST_HEAD(&stp->st_perfile);
 	INIT_LIST_HEAD(&stp->st_perfilestate);
+	INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
 	list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
 	list_add(&stp->st_perfile, &fp->fi_perfile);
 	list_add_perfile++;
@@ -1852,8 +1875,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 					&lock->v.new.clientid, &lock_sop))
 			goto out;
 		status = nfserr_resource;
-		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, 
-						open_sop->so_client, lock)))
+		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
 			goto out;
 		if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, 
 						fp, open_stp)) == NULL)
include/linux/nfsd/state.h renamed from include/linux/nfsd/state.h~current~ +5 -0
diff ./include/linux/nfsd/state.h~current~ ./include/linux/nfsd/state.h
@@ -130,12 +130,15 @@ struct nfs4_replay {
 *    so_perfilestate: heads the list of nfs4_stateid (either open or lock) 
 *         and is used to ensure no dangling nfs4_stateid references when we 
 *         release a stateowner.
+*    so_perlockowner: (open) nfs4_stateid->st_perlockowner entry - used when 
+*         close is called to reap associated byte-range locks
 */
 struct nfs4_stateowner {
 	struct list_head        so_idhash;   /* hash by so_id */
 	struct list_head        so_strhash;   /* hash by op_name */
 	struct list_head        so_perclient; /* nfs4_client->cl_perclient */
 	struct list_head        so_perfilestate; /* list: nfs4_stateid */
+	struct list_head        so_perlockowner; /* nfs4_stateid->st_perlockowner */
 	int			so_is_open_owner; /* 1=openowner,0=lockowner */
 	u32                     so_id;
 	struct nfs4_client *    so_client;
@@ -166,6 +169,7 @@ struct nfs4_file {
 * 	st_hash: stateid_hashtbl[] entry or lockstateid_hashtbl entry
 * 	st_perfile: file_hashtbl[] entry.
 * 	st_perfile_state: nfs4_stateowner->so_perfilestate
+*       st_perlockowner: (open stateid) list of lock nfs4_stateowners
 * 	st_share_access: used only for open stateid
 * 	st_share_deny: used only for open stateid
 */
@@ -174,6 +178,7 @@ struct nfs4_stateid {
 	struct list_head              st_hash; 
 	struct list_head              st_perfile;
 	struct list_head              st_perfilestate; 
+	struct list_head              st_perlockowner;
 	struct nfs4_stateowner      * st_stateowner;
 	struct nfs4_file            * st_file;
 	stateid_t                     st_stateid;

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#21 lore raw

PATCH 1/1 kNFSd - 21 of 34 - Remove a comment that is no longer accurate

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |    6 ------
 1 files changed, 6 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +0 -6
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -55,12 +55,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-/* Note: The organization of the OPEN code seems a little strange; it
- * has been superfluously split into three routines, one of which is named
- * nfsd4_process_open2() even though there is no nfsd4_process_open1()!
- * This is because the code has been organized in anticipation of a
- * subsequent patch which will implement more of the NFSv4 state model.
- */
 static int
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#22 lore raw

PATCH 1/1 kNFSd - 22 of 34 - move fh_dup2 and fix it

In reply to NeilBrown

fh_dup2 duplicates an entire svc_fh structure, so in addition to dget()'ing the dentry, it also needs to bump the reference count on fh_export.

Moved it out of the header file into nfsfh.c for the simple reason that I couldn't figure out how to reorganize the headers files right so that the fh_dup2 could use the definition of svc_fh. Since fh_dup2 is never actually used outside of nfs4proc.c, it could just as well be moved there....

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c         |   10 ++++++++++
 ./include/linux/nfsd/nfsfh.h |    8 --------
 2 files changed, 10 insertions(+), 8 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +10 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -55,6 +55,16 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
+static inline void
+fh_dup2(struct svc_fh *dst, struct svc_fh *src)
+{
+	fh_put(dst);
+	dget(src->fh_dentry);
+	if (src->fh_export)
+		cache_get(&src->fh_export->h);
+	*dst = *src;
+}
+
 static int
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
include/linux/nfsd/nfsfh.h renamed from include/linux/nfsd/nfsfh.h~current~ +0 -8
diff ./include/linux/nfsd/nfsfh.h~current~ ./include/linux/nfsd/nfsfh.h
@@ -209,14 +209,6 @@ fh_copy(struct svc_fh *dst, struct svc_f
 	return dst;
 }
 
-static __inline__ void
-fh_dup2(struct svc_fh *dst, struct svc_fh *src)
-{
-	fh_put(dst);
-	dget(src->fh_dentry);
-	*dst = *src;
-}
-
 static __inline__ struct svc_fh *
 fh_init(struct svc_fh *fhp, int maxsize)
 {

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#23 lore raw

PATCH 1/1 kNFSd - 23 of 34 - Implement the nfsv4 RELEASE_LOCKOWNER operation.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c        |    4 ++
 ./fs/nfsd/nfs4state.c       |   79 ++++++++++++++++++++++++++++++++++++++++++++
 ./fs/nfsd/nfs4xdr.c         |   19 ++++++++++
 ./include/linux/nfs4.h      |    1 
 ./include/linux/nfsd/nfsd.h |    1 
 ./include/linux/nfsd/xdr4.h |    8 ++++
 6 files changed, 112 insertions(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +4 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -728,6 +728,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		   (op->opnum == OP_SETCLIENTID) ||
 		   (op->opnum == OP_SETCLIENTID_CONFIRM) ||
 		   (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
+		   (op->opnum == OP_RELEASE_LOCKOWNER) || 
 		   (op->opnum == OP_SETATTR))) {
 			op->status = nfserr_nofilehandle;
 			goto encode_op;
@@ -834,6 +835,9 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		case OP_WRITE:
 			op->status = nfsd4_write(rqstp, &current_fh, &op->u.write);
 			break;
+		case OP_RELEASE_LOCKOWNER:
+			op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
+			break;
 		default:
 			BUG_ON(op->status == nfs_ok);
 			break;
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +79 -0

91 lines not on this page · raw message

fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +19 -0
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -993,6 +993,20 @@ nfsd4_decode_write(struct nfsd4_compound
 }
 
 static int
+nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
+{
+	DECODE_HEAD;
+
+	READ_BUF(12);	
+	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
+	READ32(rlockowner->rl_owner.len);
+	READ_BUF(rlockowner->rl_owner.len);
+	READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
+	
+	DECODE_TAIL;
+}
+
+static int
 nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 {
 	DECODE_HEAD;
@@ -1157,6 +1171,9 @@ nfsd4_decode_compound(struct nfsd4_compo
 		case OP_WRITE:
 			op->status = nfsd4_decode_write(argp, &op->u.write);
 			break;
+		case OP_RELEASE_LOCKOWNER:
+			op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
+			break;
 		default:
 			/*
 			 * According to spec, anything greater than OP_WRITE
@@ -2349,6 +2366,8 @@ nfsd4_encode_operation(struct nfsd4_comp
 	case OP_WRITE:
 		nfsd4_encode_write(resp, op->status, &op->u.write);
 		break;
+	case OP_RELEASE_LOCKOWNER:
+		break;
 	default:
 		break;
 	}
include/linux/nfs4.h renamed from include/linux/nfs4.h~current~ +1 -0
diff ./include/linux/nfs4.h~current~ ./include/linux/nfs4.h
@@ -86,6 +86,7 @@ enum nfs_opnum4 {
 	OP_SETCLIENTID_CONFIRM = 36,
 	OP_VERIFY = 37,
 	OP_WRITE = 38,
+	OP_RELEASE_LOCKOWNER = 39,
 };
 
 enum nfsstat4 {
include/linux/nfsd/nfsd.h renamed from include/linux/nfsd/nfsd.h~current~ +1 -0
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
@@ -194,6 +194,7 @@ void		nfsd_lockd_shutdown(void);
 #define	nfserr_attrnotsupp	__constant_htonl(NFSERR_ATTRNOTSUPP)
 #define	nfserr_bad_xdr		__constant_htonl(NFSERR_BAD_XDR)
 #define	nfserr_openmode		__constant_htonl(NFSERR_OPENMODE)
+#define	nfserr_locks_held	__constant_htonl(NFSERR_LOCKS_HELD)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.
include/linux/nfsd/xdr4.h renamed from include/linux/nfsd/xdr4.h~current~ +8 -0
diff ./include/linux/nfsd/xdr4.h~current~ ./include/linux/nfsd/xdr4.h
@@ -263,6 +263,10 @@ struct nfsd4_readdir {
 	u32 *			offset;
 };
 
+struct nfsd4_release_lockowner {
+	clientid_t        rl_clientid;
+	struct xdr_netobj rl_owner;
+};
 struct nfsd4_readlink {
 	struct svc_rqst *rl_rqstp;          /* request */
 	struct svc_fh *	rl_fhp;             /* request */
@@ -359,6 +363,7 @@ struct nfsd4_op {
 		struct nfsd4_setclientid_confirm setclientid_confirm;
 		struct nfsd4_verify		verify;
 		struct nfsd4_write		write;
+		struct nfsd4_release_lockowner	release_lockowner;
 	} u;
 	struct nfs4_replay *			replay;
 };
@@ -441,6 +446,9 @@ extern int nfsd4_lockt(struct svc_rqst *
 		struct nfsd4_lockt *lockt);
 extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
 		struct nfsd4_locku *locku);
+extern int
+nfsd4_release_lockowner(struct svc_rqst *rqstp, 
+		struct nfsd4_release_lockowner *rlockowner);
 #endif
 
 /*

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#24 lore raw

PATCH 1/1 kNFSd - 24 of 34 - add OP_ILLEGAL, and fix processing of compounds with out of bounds op numbers.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c         |   16 +++++++++-------
 ./include/linux/nfs4.h      |    1 +
 ./include/linux/nfsd/nfsd.h |    1 +
 3 files changed, 11 insertions(+), 7 deletions(-)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +9 -7
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -1078,6 +1078,13 @@ nfsd4_decode_compound(struct nfsd4_compo
 		op->opnum = ntohl(*argp->p++);
 
 		switch (op->opnum) {
+		case 2: /* Reserved operation */
+			op->opnum = OP_ILLEGAL;
+			if (argp->minorversion == 0)
+				op->status = nfserr_op_illegal;
+			else 
+				op->status = nfserr_minor_vers_mismatch;
+			break;
 		case OP_ACCESS:
 			op->status = nfsd4_decode_access(argp, &op->u.access);
 			break;
@@ -1175,13 +1182,8 @@ nfsd4_decode_compound(struct nfsd4_compo
 			op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
 			break;
 		default:
-			/*
-			 * According to spec, anything greater than OP_WRITE
-			 * is treated as OP_WRITE+1 in the response.
-			 */
-			if (op->opnum > OP_WRITE)
-			op->opnum = OP_WRITE + 1;
-			op->status = nfserr_notsupp;
+			op->opnum = OP_ILLEGAL;
+			op->status = nfserr_op_illegal;
 			break;
 		}
 
include/linux/nfs4.h renamed from include/linux/nfs4.h~current~ +1 -0
diff ./include/linux/nfs4.h~current~ ./include/linux/nfs4.h
@@ -87,6 +87,7 @@ enum nfs_opnum4 {
 	OP_VERIFY = 37,
 	OP_WRITE = 38,
 	OP_RELEASE_LOCKOWNER = 39,
+	OP_ILLEGAL = 10044,
 };
 
 enum nfsstat4 {
include/linux/nfsd/nfsd.h renamed from include/linux/nfsd/nfsd.h~current~ +1 -0
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
@@ -195,6 +195,7 @@ void		nfsd_lockd_shutdown(void);
 #define	nfserr_bad_xdr		__constant_htonl(NFSERR_BAD_XDR)
 #define	nfserr_openmode		__constant_htonl(NFSERR_OPENMODE)
 #define	nfserr_locks_held	__constant_htonl(NFSERR_LOCKS_HELD)
+#define	nfserr_op_illegal	__constant_htonl(NFSERR_OP_ILLEGAL)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#25 lore raw

PATCH 1/1 kNFSd - 25 of 34 - fix an error return for OP_CREATE

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |    2 ++
 1 files changed, 2 insertions(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +2 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -250,6 +250,8 @@ nfsd4_create(struct svc_rqst *rqstp, str
 	fh_init(&resfh, NFS4_FHSIZE);
 
 	status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
+	if (status == nfserr_symlink)
+		status = nfserr_notdir;
 	if (status)
 		return status;
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#26 lore raw

PATCH 1/1 kNFSd - 26 of 34 - Add a check in OP_LOCK for new lockowners to ensure that the open stateid is

In reply to NeilBrown

owned by the lockowner clientid.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |   32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +25 -7
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1401,7 +1401,7 @@ out:
  * Checks for sequence id mutating operations. 
  */
 int
-nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp)
+nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
 {
 	int status;
 	struct nfs4_stateid *stp;
@@ -1438,6 +1438,21 @@ nfs4_preprocess_seqid_op(struct svc_fh *
 
 	status = nfserr_bad_stateid;
 
+	/* for new lock stateowners, check that the lock->v.new.open_stateid
+	 * refers to an open stateowner, and that the lockclid 
+	 * (nfs4_lock->v.new.clientid) is the same as the 
+	 * open_stateid->st_stateowner->so_client->clientid
+	 */
+	if (lockclid) {
+		struct nfs4_stateowner *sop = stp->st_stateowner;	
+		struct nfs4_client *clp = sop->so_client;
+
+		if (!sop->so_is_open_owner)
+			goto out;
+		if (!cmp_clid(&clp->cl_clientid, lockclid))
+			goto out;
+	}
+
 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
 		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
 		stp->st_vfs_set = 0;
@@ -1524,7 +1539,7 @@ nfsd4_open_confirm(struct svc_rqst *rqst
 	if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
 					&oc->oc_req_stateid,
 					CHECK_FH | CONFIRM | OPEN_STATE,
-					&oc->oc_stateowner, &stp)))
+					&oc->oc_stateowner, &stp, NULL)))
 		goto out; 
 
 	sop = oc->oc_stateowner;
@@ -1556,7 +1571,7 @@ nfsd4_open_downgrade(struct svc_rqst *rq
 	if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 
 					&od->od_stateid, 
 					CHECK_FH | OPEN_STATE, 
-					&od->od_stateowner, &stp)))
+					&od->od_stateowner, &stp, NULL)))
 		goto out; 
 
 	status = nfserr_inval;
@@ -1596,7 +1611,7 @@ nfsd4_close(struct svc_rqst *rqstp, stru
 	if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 
 					&close->cl_stateid, 
 					CHECK_FH | OPEN_STATE, 
-					&close->cl_stateowner, &stp)))
+					&close->cl_stateowner, &stp, NULL)))
 		goto out; 
 	/*
 	*  Return success, but first update the stateid.
@@ -1852,12 +1867,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 			printk("NFSD: nfsd4_lock: clientid is stale!\n");
 			goto out;
 		}
+		/* does the clientid in the lock owner own the open stateid? */
+
 		/* validate and update open stateid and open seqid */
 		status = nfs4_preprocess_seqid_op(current_fh, 
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
-		                        &open_sop, &open_stp);
+		                        &open_sop, &open_stp,
+					&lock->v.new.clientid);
 		if (status)
 			goto out;
 		/* create lockowner and lock stateid */
@@ -1889,7 +1907,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 				       lock->lk_old_lock_seqid, 
 				       &lock->lk_old_lock_stateid, 
 				       CHECK_FH | LOCK_STATE, 
-				       &lock->lk_stateowner, &lock_stp);
+				       &lock->lk_stateowner, &lock_stp, NULL);
 		if (status)
 			goto out;
 	}
@@ -2094,7 +2112,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 					locku->lu_seqid, 
 					&locku->lu_stateid, 
 					CHECK_FH | LOCK_STATE, 
-					&locku->lu_stateowner, &stp)))
+					&locku->lu_stateowner, &stp, NULL)))
 		goto out;
 
 	filp = &stp->st_vfs_file;

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#27 lore raw

PATCH 1/1 kNFSd - 27 of 34 - Corrects an error return for OP_OPEN_CONFIRM.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4state.c |    4 ++++
 1 files changed, 4 insertions(+)
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +4 -0
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
@@ -1533,6 +1533,10 @@ nfsd4_open_confirm(struct svc_rqst *rqst
 	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
 			(int)current_fh->fh_dentry->d_name.len,
 			current_fh->fh_dentry->d_name.name);
+
+	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) 
+		goto out;
+
 	oc->oc_stateowner = NULL;
 	nfs4_lock_state();
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#28 lore raw

PATCH 1/1 kNFSd - 29 of 34 - Fix an out-of-spec readlink error return.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c |    2 ++
 1 files changed, 2 insertions(+)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +2 -0
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -2083,6 +2083,8 @@ nfsd4_encode_readlink(struct nfsd4_compo
 	 * assume that truncation occurred, and return NFS4ERR_RESOURCE.
 	 */
 	nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
+	if (nfserr == nfserr_isdir)
+		return nfserr_inval;
 	if (nfserr)
 		return nfserr;
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#29 lore raw

PATCH 1/1 kNFSd - 31 of 34 - Miscellaneous fixes to stateid-based replay

In reply to NeilBrown

Save replays for LOCK operations,
make sure errors are replayed correctly.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |    3 ++-
 ./fs/nfsd/nfs4xdr.c  |    2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +2 -1
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -776,6 +776,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			break;
 		case OP_LOCK:
 			op->status = nfsd4_lock(rqstp, &current_fh, &op->u.lock);
+			op->replay = &op->u.lock.lk_stateowner->so_replay;
 			break;
 		case OP_LOCKT:
 			op->status = nfsd4_lockt(rqstp, &current_fh, &op->u.lockt);
@@ -864,7 +865,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 encode_op:
 		if (op->status == NFSERR_REPLAY_ME) {
 			nfsd4_encode_replay(resp, op);
-			status = op->status = NFS_OK;
+			status = op->status = op->replay->rp_status;
 		} else {
 			nfsd4_encode_operation(resp, op);
 			status = op->status;
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +1 -1
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -2399,7 +2399,7 @@ nfsd4_encode_replay(struct nfsd4_compoun
 
 	RESERVE_SPACE(8);
 	WRITE32(op->opnum);
-	WRITE32(NFS_OK);
+	*p++ = rp->rp_status;  /* already xdr'ed */
 	ADJUST_ARGS();
 
 	RESERVE_SPACE(rp->rp_buflen);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#30 lore raw

PATCH 1/1 kNFSd - 32 of 34 - Fix out-of-spec error return in attribute decoding.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +1 -1
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -344,7 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compound
 	 * read-only attributes return ERR_INVAL.
 	 */
 	if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
-		return nfserr_notsupp;
+		return nfserr_attrnotsupp;
 	if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1))
 		return nfserr_inval;
 

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#31 lore raw

PATCH 1/1 kNFSd - 33 of 34 - Make the calculation in the first READ_BUF easier to understand.

In reply to NeilBrown

Don't rely on the assumption that

    sizeof(stateid_t) == sizeof(stateid_opaque_t) + 4. 

----------- Diffstat output ------------

 ./fs/nfsd/nfs4xdr.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c renamed from fs/nfsd/nfs4xdr.c~current~ +1 -1
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
@@ -949,7 +949,7 @@ nfsd4_decode_write(struct nfsd4_compound
 	int len;
 	DECODE_HEAD;
 
-	READ_BUF(sizeof(stateid_t) + 16);
+	READ_BUF(sizeof(stateid_opaque_t) + 20);
 	READ32(write->wr_stateid.si_generation);
 	COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
 	READ64(write->wr_offset);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#32 lore raw

PATCH 1/1 kNFSd - 30 of 34 - Fix an out-of-spec error in nfsd4_remove.

In reply to NeilBrown

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c |    2 ++
 1 files changed, 2 insertions(+)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +2 -0
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -478,6 +478,8 @@ nfsd4_remove(struct svc_rqst *rqstp, str
 	int status;
 
 	status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+	if (status == nfserr_symlink)
+		return nfserr_notdir;
 	if (!status) {
 		fh_unlock(current_fh);
 		set_change_info(&remove->rm_cinfo, current_fh);

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#33 lore raw

PATCH 1/1 kNFSd - 28 of 34 - Enforce open_downgrade requirement

In reply to NeilBrown

The spec requires that the access and deny bits requested in open_downgrade represent the union of the bits for some subset of the OPENS for the given open_owner and file. Enforce that requirement.

----------- Diffstat output ------------

 ./fs/nfsd/nfs4proc.c         |   20 ++++++-
 ./fs/nfsd/nfs4state.c        |  121 +++++++++++++++++++++++++++++++++++--------
 ./include/linux/nfs4.h       |    1 
 ./include/linux/nfsd/state.h |    8 +-
 4 files changed, 121 insertions(+), 29 deletions(-)
fs/nfsd/nfs4proc.c renamed from fs/nfsd/nfs4proc.c~current~ +17 -3
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
@@ -382,6 +382,20 @@ nfsd4_lookup(struct svc_rqst *rqstp, str
 }
 
 static inline int
+access_bits_permit_read(unsigned long access_bmap)
+{
+	return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
+		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+}
+
+static inline int
+access_bits_permit_write(unsigned long access_bmap)
+{
+	return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
+		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+}
+
+static inline int
 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
 {
 	struct nfs4_stateid *stp;
@@ -419,7 +433,7 @@ nfsd4_read(struct svc_rqst *rqstp, struc
 		goto out;
 	}
 	status = nfserr_openmode;
-	if (!(stp->st_share_access & NFS4_SHARE_ACCESS_READ)) {
+	if (!access_bits_permit_read(stp->st_access_bmap)) {
 		dprintk("NFSD: nfsd4_read: file not opened for read!\n");
 		goto out;
 	}
@@ -527,7 +541,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 			goto out;
 		}
 		status = nfserr_openmode;
-		if (!(stp->st_share_access & NFS4_SHARE_ACCESS_WRITE)) {
+		if (!access_bits_permit_write(stp->st_access_bmap)) {
 			dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
 			goto out;
 		}
@@ -568,7 +582,7 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 	}
 
 	status = nfserr_openmode;
-	if (!(stp->st_share_access & NFS4_SHARE_ACCESS_WRITE)) {
+	if (!access_bits_permit_write(stp->st_access_bmap)) {
 		dprintk("NFSD: nfsd4_write: file not open for write!\n");
 		goto out;
 	}
fs/nfsd/nfs4state.c renamed from fs/nfsd/nfs4state.c~current~ +99 -22

204 lines not on this page · raw message

include/linux/nfs4.h renamed from include/linux/nfs4.h~current~ +1 -0
diff ./include/linux/nfs4.h~current~ ./include/linux/nfs4.h
@@ -37,6 +37,7 @@
 #define NFS4_SHARE_ACCESS_BOTH	0x0003
 #define NFS4_SHARE_DENY_READ	0x0001
 #define NFS4_SHARE_DENY_WRITE	0x0002
+#define NFS4_SHARE_DENY_BOTH	0x0003
 
 #define NFS4_SET_TO_SERVER_TIME	0
 #define NFS4_SET_TO_CLIENT_TIME	1
include/linux/nfsd/state.h renamed from include/linux/nfsd/state.h~current~ +4 -4
diff ./include/linux/nfsd/state.h~current~ ./include/linux/nfsd/state.h
@@ -170,8 +170,8 @@ struct nfs4_file {
 * 	st_perfile: file_hashtbl[] entry.
 * 	st_perfile_state: nfs4_stateowner->so_perfilestate
 *       st_perlockowner: (open stateid) list of lock nfs4_stateowners
-* 	st_share_access: used only for open stateid
-* 	st_share_deny: used only for open stateid
+* 	st_access_bmap: used only for open stateid
+* 	st_deny_bmap: used only for open stateid
 */
 
 struct nfs4_stateid {
@@ -184,8 +184,8 @@ struct nfs4_stateid {
 	stateid_t                     st_stateid;
 	struct file                   st_vfs_file;
 	int                           st_vfs_set;
-	unsigned int                  st_share_access;
-	unsigned int                  st_share_deny;
+	unsigned long                 st_access_bmap;
+	unsigned long                 st_deny_bmap;
 };
 
 /* flags for preprocess_seqid_op() */

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#34 lore raw

PATCH 1/1 kNFSd - 34 of 34 - make sure sunrpc init routines called before gss init routines.

In reply to NeilBrown

----------- Diffstat output ------------

 ./net/sunrpc/Makefile |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
net/sunrpc/Makefile renamed from net/sunrpc/Makefile~current~ +1 -1
diff ./net/sunrpc/Makefile~current~ ./net/sunrpc/Makefile
@@ -2,9 +2,9 @@
 # Makefile for Linux kernel SUN RPC
 #
 
-obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
 obj-$(CONFIG_SUNRPC) += sunrpc.o
+obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
 sunrpc-y := clnt.o xprt.o sched.o \
 	    auth.o auth_null.o auth_unix.o \

-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs