diff options
-rw-r--r-- | Documentation/filesystems/nfs/nfs41-server.txt | 42 | ||||
-rw-r--r-- | fs/nfsd/acl.h | 2 | ||||
-rw-r--r-- | fs/nfsd/cache.h | 8 | ||||
-rw-r--r-- | fs/nfsd/idmap.h | 4 | ||||
-rw-r--r-- | fs/nfsd/netns.h | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 20 | ||||
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 50 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 57 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 40 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 178 | ||||
-rw-r--r-- | fs/nfsd/nfscache.c | 36 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 30 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 40 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 2 | ||||
-rw-r--r-- | fs/nfsd/xdr3.h | 3 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 4 | ||||
-rw-r--r-- | include/linux/sunrpc/svc.h | 6 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_keys.c | 17 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_upcall.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 82 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 4 | ||||
-rw-r--r-- | net/sunrpc/netns.h | 1 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 25 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 7 |
26 files changed, 284 insertions, 393 deletions
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt index 01c2db769791..b930ad087780 100644 --- a/Documentation/filesystems/nfs/nfs41-server.txt +++ b/Documentation/filesystems/nfs/nfs41-server.txt | |||
@@ -5,11 +5,11 @@ Server support for minorversion 1 can be controlled using the | |||
5 | by reading this file will contain either "+4.1" or "-4.1" | 5 | by reading this file will contain either "+4.1" or "-4.1" |
6 | correspondingly. | 6 | correspondingly. |
7 | 7 | ||
8 | Currently, server support for minorversion 1 is disabled by default. | 8 | Currently, server support for minorversion 1 is enabled by default. |
9 | It can be enabled at run time by writing the string "+4.1" to | 9 | It can be disabled at run time by writing the string "-4.1" to |
10 | the /proc/fs/nfsd/versions control file. Note that to write this | 10 | the /proc/fs/nfsd/versions control file. Note that to write this |
11 | control file, the nfsd service must be taken down. Use your user-mode | 11 | control file, the nfsd service must be taken down. You can use rpc.nfsd |
12 | nfs-utils to set this up; see rpc.nfsd(8) | 12 | for this; see rpc.nfsd(8). |
13 | 13 | ||
14 | (Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and | 14 | (Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and |
15 | "-4", respectively. Therefore, code meant to work on both new and old | 15 | "-4", respectively. Therefore, code meant to work on both new and old |
@@ -29,29 +29,6 @@ are still under development out of tree. | |||
29 | See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design | 29 | See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design |
30 | for more information. | 30 | for more information. |
31 | 31 | ||
32 | The current implementation is intended for developers only: while it | ||
33 | does support ordinary file operations on clients we have tested against | ||
34 | (including the linux client), it is incomplete in ways which may limit | ||
35 | features unexpectedly, cause known bugs in rare cases, or cause | ||
36 | interoperability problems with future clients. Known issues: | ||
37 | |||
38 | - gss support is questionable: currently mounts with kerberos | ||
39 | from a linux client are possible, but we aren't really | ||
40 | conformant with the spec (for example, we don't use kerberos | ||
41 | on the backchannel correctly). | ||
42 | - We do not support SSV, which provides security for shared | ||
43 | client-server state (thus preventing unauthorized tampering | ||
44 | with locks and opens, for example). It is mandatory for | ||
45 | servers to support this, though no clients use it yet. | ||
46 | |||
47 | In addition, some limitations are inherited from the current NFSv4 | ||
48 | implementation: | ||
49 | |||
50 | - Incomplete delegation enforcement: if a file is renamed or | ||
51 | unlinked by a local process, a client holding a delegation may | ||
52 | continue to indefinitely allow opens of the file under the old | ||
53 | name. | ||
54 | |||
55 | The table below, taken from the NFSv4.1 document, lists | 32 | The table below, taken from the NFSv4.1 document, lists |
56 | the operations that are mandatory to implement (REQ), optional | 33 | the operations that are mandatory to implement (REQ), optional |
57 | (OPT), and NFSv4.0 operations that are required not to implement (MNI) | 34 | (OPT), and NFSv4.0 operations that are required not to implement (MNI) |
@@ -169,6 +146,16 @@ NS*| CB_WANTS_CANCELLED | OPT | FDELG, | Section 20.10 | | |||
169 | 146 | ||
170 | Implementation notes: | 147 | Implementation notes: |
171 | 148 | ||
149 | SSV: | ||
150 | * The spec claims this is mandatory, but we don't actually know of any | ||
151 | implementations, so we're ignoring it for now. The server returns | ||
152 | NFS4ERR_ENCR_ALG_UNSUPP on EXCHANGE_ID, which should be future-proof. | ||
153 | |||
154 | GSS on the backchannel: | ||
155 | * Again, theoretically required but not widely implemented (in | ||
156 | particular, the current Linux client doesn't request it). We return | ||
157 | NFS4ERR_ENCR_ALG_UNSUPP on CREATE_SESSION. | ||
158 | |||
172 | DELEGPURGE: | 159 | DELEGPURGE: |
173 | * mandatory only for servers that support CLAIM_DELEGATE_PREV and/or | 160 | * mandatory only for servers that support CLAIM_DELEGATE_PREV and/or |
174 | CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that | 161 | CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that |
@@ -176,7 +163,6 @@ DELEGPURGE: | |||
176 | now. | 163 | now. |
177 | 164 | ||
178 | EXCHANGE_ID: | 165 | EXCHANGE_ID: |
179 | * only SP4_NONE state protection supported | ||
180 | * implementation ids are ignored | 166 | * implementation ids are ignored |
181 | 167 | ||
182 | CREATE_SESSION: | 168 | CREATE_SESSION: |
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h index 8b68218e2c1c..a812fd1b92a4 100644 --- a/fs/nfsd/acl.h +++ b/fs/nfsd/acl.h | |||
@@ -45,7 +45,7 @@ struct svc_rqst; | |||
45 | 45 | ||
46 | struct nfs4_acl *nfs4_acl_new(int); | 46 | struct nfs4_acl *nfs4_acl_new(int); |
47 | int nfs4_acl_get_whotype(char *, u32); | 47 | int nfs4_acl_get_whotype(char *, u32); |
48 | int nfs4_acl_write_who(int who, char *p); | 48 | __be32 nfs4_acl_write_who(int who, __be32 **p, int *len); |
49 | 49 | ||
50 | int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, | 50 | int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, |
51 | struct nfs4_acl **acl); | 51 | struct nfs4_acl **acl); |
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h index d5c5b3e00266..b582f9ab6b2a 100644 --- a/fs/nfsd/cache.h +++ b/fs/nfsd/cache.h | |||
@@ -84,12 +84,4 @@ int nfsd_cache_lookup(struct svc_rqst *); | |||
84 | void nfsd_cache_update(struct svc_rqst *, int, __be32 *); | 84 | void nfsd_cache_update(struct svc_rqst *, int, __be32 *); |
85 | int nfsd_reply_cache_stats_open(struct inode *, struct file *); | 85 | int nfsd_reply_cache_stats_open(struct inode *, struct file *); |
86 | 86 | ||
87 | #ifdef CONFIG_NFSD_V4 | ||
88 | void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp); | ||
89 | #else /* CONFIG_NFSD_V4 */ | ||
90 | static inline void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp) | ||
91 | { | ||
92 | } | ||
93 | #endif /* CONFIG_NFSD_V4 */ | ||
94 | |||
95 | #endif /* NFSCACHE_H */ | 87 | #endif /* NFSCACHE_H */ |
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h index bf95f6b817a4..66e58db01936 100644 --- a/fs/nfsd/idmap.h +++ b/fs/nfsd/idmap.h | |||
@@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net) | |||
56 | 56 | ||
57 | __be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); | 57 | __be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); |
58 | __be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); | 58 | __be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); |
59 | int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *); | 59 | __be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *); |
60 | int nfsd_map_gid_to_name(struct svc_rqst *, kgid_t, char *); | 60 | __be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *); |
61 | 61 | ||
62 | #endif /* LINUX_NFSD_IDMAP_H */ | 62 | #endif /* LINUX_NFSD_IDMAP_H */ |
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 849a7c3ced22..d32b3aa6600d 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -95,6 +95,7 @@ struct nfsd_net { | |||
95 | time_t nfsd4_grace; | 95 | time_t nfsd4_grace; |
96 | 96 | ||
97 | bool nfsd_net_up; | 97 | bool nfsd_net_up; |
98 | bool lockd_up; | ||
98 | 99 | ||
99 | /* | 100 | /* |
100 | * Time of server startup | 101 | * Time of server startup |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 14d9ecb96cff..de6e39e12cb3 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -168,7 +168,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
168 | struct kstat *stat) | 168 | struct kstat *stat) |
169 | { | 169 | { |
170 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); | 170 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); |
171 | *p++ = htonl((u32) stat->mode); | 171 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); |
172 | *p++ = htonl((u32) stat->nlink); | 172 | *p++ = htonl((u32) stat->nlink); |
173 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); | 173 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
174 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); | 174 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
@@ -842,21 +842,21 @@ out: | |||
842 | 842 | ||
843 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) | 843 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) |
844 | { | 844 | { |
845 | struct svc_fh fh; | 845 | struct svc_fh *fh = &cd->scratch; |
846 | __be32 err; | 846 | __be32 err; |
847 | 847 | ||
848 | fh_init(&fh, NFS3_FHSIZE); | 848 | fh_init(fh, NFS3_FHSIZE); |
849 | err = compose_entry_fh(cd, &fh, name, namlen); | 849 | err = compose_entry_fh(cd, fh, name, namlen); |
850 | if (err) { | 850 | if (err) { |
851 | *p++ = 0; | 851 | *p++ = 0; |
852 | *p++ = 0; | 852 | *p++ = 0; |
853 | goto out; | 853 | goto out; |
854 | } | 854 | } |
855 | p = encode_post_op_attr(cd->rqstp, p, &fh); | 855 | p = encode_post_op_attr(cd->rqstp, p, fh); |
856 | *p++ = xdr_one; /* yes, a file handle follows */ | 856 | *p++ = xdr_one; /* yes, a file handle follows */ |
857 | p = encode_fh(p, &fh); | 857 | p = encode_fh(p, fh); |
858 | out: | 858 | out: |
859 | fh_put(&fh); | 859 | fh_put(fh); |
860 | return p; | 860 | return p; |
861 | } | 861 | } |
862 | 862 | ||
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 649ad7cf2204..d3a587144222 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/nfs_fs.h> | 38 | #include <linux/nfs_fs.h> |
39 | #include <linux/export.h> | 39 | #include <linux/export.h> |
40 | #include "nfsfh.h" | 40 | #include "nfsfh.h" |
41 | #include "nfsd.h" | ||
41 | #include "acl.h" | 42 | #include "acl.h" |
42 | #include "vfs.h" | 43 | #include "vfs.h" |
43 | 44 | ||
@@ -916,17 +917,22 @@ nfs4_acl_get_whotype(char *p, u32 len) | |||
916 | return NFS4_ACL_WHO_NAMED; | 917 | return NFS4_ACL_WHO_NAMED; |
917 | } | 918 | } |
918 | 919 | ||
919 | int | 920 | __be32 nfs4_acl_write_who(int who, __be32 **p, int *len) |
920 | nfs4_acl_write_who(int who, char *p) | ||
921 | { | 921 | { |
922 | int i; | 922 | int i; |
923 | int bytes; | ||
923 | 924 | ||
924 | for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { | 925 | for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { |
925 | if (s2t_map[i].type == who) { | 926 | if (s2t_map[i].type != who) |
926 | memcpy(p, s2t_map[i].string, s2t_map[i].stringlen); | 927 | continue; |
927 | return s2t_map[i].stringlen; | 928 | bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2); |
928 | } | 929 | if (bytes > *len) |
930 | return nfserr_resource; | ||
931 | *p = xdr_encode_opaque(*p, s2t_map[i].string, | ||
932 | s2t_map[i].stringlen); | ||
933 | *len -= bytes; | ||
934 | return 0; | ||
929 | } | 935 | } |
930 | BUG(); | 936 | WARN_ON_ONCE(1); |
931 | return -1; | 937 | return -1; |
932 | } | 938 | } |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 4832fd819f88..c0dfde68742e 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -551,27 +551,46 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
551 | return 0; | 551 | return 0; |
552 | } | 552 | } |
553 | 553 | ||
554 | static int | 554 | static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen) |
555 | idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name) | 555 | { |
556 | char buf[11]; | ||
557 | int len; | ||
558 | int bytes; | ||
559 | |||
560 | len = sprintf(buf, "%u", id); | ||
561 | bytes = 4 + (XDR_QUADLEN(len) << 2); | ||
562 | if (bytes > *buflen) | ||
563 | return nfserr_resource; | ||
564 | *p = xdr_encode_opaque(*p, buf, len); | ||
565 | *buflen -= bytes; | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) | ||
556 | { | 570 | { |
557 | struct ent *item, key = { | 571 | struct ent *item, key = { |
558 | .id = id, | 572 | .id = id, |
559 | .type = type, | 573 | .type = type, |
560 | }; | 574 | }; |
561 | int ret; | 575 | int ret; |
576 | int bytes; | ||
562 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); | 577 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
563 | 578 | ||
564 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); | 579 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); |
565 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); | 580 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); |
566 | if (ret == -ENOENT) | 581 | if (ret == -ENOENT) |
567 | return sprintf(name, "%u", id); | 582 | return encode_ascii_id(id, p, buflen); |
568 | if (ret) | 583 | if (ret) |
569 | return ret; | 584 | return nfserrno(ret); |
570 | ret = strlen(item->name); | 585 | ret = strlen(item->name); |
571 | BUG_ON(ret > IDMAP_NAMESZ); | 586 | WARN_ON_ONCE(ret > IDMAP_NAMESZ); |
572 | memcpy(name, item->name, ret); | 587 | bytes = 4 + (XDR_QUADLEN(ret) << 2); |
588 | if (bytes > *buflen) | ||
589 | return nfserr_resource; | ||
590 | *p = xdr_encode_opaque(*p, item->name, ret); | ||
591 | *buflen -= bytes; | ||
573 | cache_put(&item->h, nn->idtoname_cache); | 592 | cache_put(&item->h, nn->idtoname_cache); |
574 | return ret; | 593 | return 0; |
575 | } | 594 | } |
576 | 595 | ||
577 | static bool | 596 | static bool |
@@ -603,12 +622,11 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u | |||
603 | return idmap_name_to_id(rqstp, type, name, namelen, id); | 622 | return idmap_name_to_id(rqstp, type, name, namelen, id); |
604 | } | 623 | } |
605 | 624 | ||
606 | static int | 625 | static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) |
607 | do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name) | ||
608 | { | 626 | { |
609 | if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) | 627 | if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) |
610 | return sprintf(name, "%u", id); | 628 | return encode_ascii_id(id, p, buflen); |
611 | return idmap_id_to_name(rqstp, type, id, name); | 629 | return idmap_id_to_name(rqstp, type, id, p, buflen); |
612 | } | 630 | } |
613 | 631 | ||
614 | __be32 | 632 | __be32 |
@@ -637,16 +655,14 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, | |||
637 | return status; | 655 | return status; |
638 | } | 656 | } |
639 | 657 | ||
640 | int | 658 | __be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen) |
641 | nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name) | ||
642 | { | 659 | { |
643 | u32 id = from_kuid(&init_user_ns, uid); | 660 | u32 id = from_kuid(&init_user_ns, uid); |
644 | return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); | 661 | return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen); |
645 | } | 662 | } |
646 | 663 | ||
647 | int | 664 | __be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen) |
648 | nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name) | ||
649 | { | 665 | { |
650 | u32 id = from_kgid(&init_user_ns, gid); | 666 | u32 id = from_kgid(&init_user_ns, gid); |
651 | return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); | 667 | return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen); |
652 | } | 668 | } |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 825b8a99b99b..82189b208af3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -231,17 +231,16 @@ static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate | |||
231 | } | 231 | } |
232 | 232 | ||
233 | static __be32 | 233 | static __be32 |
234 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open) | 234 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh) |
235 | { | 235 | { |
236 | struct svc_fh *current_fh = &cstate->current_fh; | 236 | struct svc_fh *current_fh = &cstate->current_fh; |
237 | struct svc_fh *resfh; | ||
238 | int accmode; | 237 | int accmode; |
239 | __be32 status; | 238 | __be32 status; |
240 | 239 | ||
241 | resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); | 240 | *resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); |
242 | if (!resfh) | 241 | if (!*resfh) |
243 | return nfserr_jukebox; | 242 | return nfserr_jukebox; |
244 | fh_init(resfh, NFS4_FHSIZE); | 243 | fh_init(*resfh, NFS4_FHSIZE); |
245 | open->op_truncate = 0; | 244 | open->op_truncate = 0; |
246 | 245 | ||
247 | if (open->op_create) { | 246 | if (open->op_create) { |
@@ -266,12 +265,12 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
266 | */ | 265 | */ |
267 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, | 266 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, |
268 | open->op_fname.len, &open->op_iattr, | 267 | open->op_fname.len, &open->op_iattr, |
269 | resfh, open->op_createmode, | 268 | *resfh, open->op_createmode, |
270 | (u32 *)open->op_verf.data, | 269 | (u32 *)open->op_verf.data, |
271 | &open->op_truncate, &open->op_created); | 270 | &open->op_truncate, &open->op_created); |
272 | 271 | ||
273 | if (!status && open->op_label.len) | 272 | if (!status && open->op_label.len) |
274 | nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval); | 273 | nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval); |
275 | 274 | ||
276 | /* | 275 | /* |
277 | * Following rfc 3530 14.2.16, use the returned bitmask | 276 | * Following rfc 3530 14.2.16, use the returned bitmask |
@@ -281,31 +280,32 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
281 | if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) | 280 | if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) |
282 | open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | | 281 | open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | |
283 | FATTR4_WORD1_TIME_MODIFY); | 282 | FATTR4_WORD1_TIME_MODIFY); |
284 | } else { | 283 | } else |
284 | /* | ||
285 | * Note this may exit with the parent still locked. | ||
286 | * We will hold the lock until nfsd4_open's final | ||
287 | * lookup, to prevent renames or unlinks until we've had | ||
288 | * a chance to an acquire a delegation if appropriate. | ||
289 | */ | ||
285 | status = nfsd_lookup(rqstp, current_fh, | 290 | status = nfsd_lookup(rqstp, current_fh, |
286 | open->op_fname.data, open->op_fname.len, resfh); | 291 | open->op_fname.data, open->op_fname.len, *resfh); |
287 | fh_unlock(current_fh); | ||
288 | } | ||
289 | if (status) | 292 | if (status) |
290 | goto out; | 293 | goto out; |
291 | status = nfsd_check_obj_isreg(resfh); | 294 | status = nfsd_check_obj_isreg(*resfh); |
292 | if (status) | 295 | if (status) |
293 | goto out; | 296 | goto out; |
294 | 297 | ||
295 | if (is_create_with_attrs(open) && open->op_acl != NULL) | 298 | if (is_create_with_attrs(open) && open->op_acl != NULL) |
296 | do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); | 299 | do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval); |
297 | 300 | ||
298 | nfsd4_set_open_owner_reply_cache(cstate, open, resfh); | 301 | nfsd4_set_open_owner_reply_cache(cstate, open, *resfh); |
299 | accmode = NFSD_MAY_NOP; | 302 | accmode = NFSD_MAY_NOP; |
300 | if (open->op_created || | 303 | if (open->op_created || |
301 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) | 304 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) |
302 | accmode |= NFSD_MAY_OWNER_OVERRIDE; | 305 | accmode |= NFSD_MAY_OWNER_OVERRIDE; |
303 | status = do_open_permission(rqstp, resfh, open, accmode); | 306 | status = do_open_permission(rqstp, *resfh, open, accmode); |
304 | set_change_info(&open->op_cinfo, current_fh); | 307 | set_change_info(&open->op_cinfo, current_fh); |
305 | fh_dup2(current_fh, resfh); | ||
306 | out: | 308 | out: |
307 | fh_put(resfh); | ||
308 | kfree(resfh); | ||
309 | return status; | 309 | return status; |
310 | } | 310 | } |
311 | 311 | ||
@@ -358,6 +358,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
358 | struct nfsd4_open *open) | 358 | struct nfsd4_open *open) |
359 | { | 359 | { |
360 | __be32 status; | 360 | __be32 status; |
361 | struct svc_fh *resfh = NULL; | ||
361 | struct nfsd4_compoundres *resp; | 362 | struct nfsd4_compoundres *resp; |
362 | struct net *net = SVC_NET(rqstp); | 363 | struct net *net = SVC_NET(rqstp); |
363 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 364 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
@@ -424,7 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
424 | switch (open->op_claim_type) { | 425 | switch (open->op_claim_type) { |
425 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | 426 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: |
426 | case NFS4_OPEN_CLAIM_NULL: | 427 | case NFS4_OPEN_CLAIM_NULL: |
427 | status = do_open_lookup(rqstp, cstate, open); | 428 | status = do_open_lookup(rqstp, cstate, open, &resfh); |
428 | if (status) | 429 | if (status) |
429 | goto out; | 430 | goto out; |
430 | break; | 431 | break; |
@@ -440,6 +441,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
440 | status = do_open_fhandle(rqstp, cstate, open); | 441 | status = do_open_fhandle(rqstp, cstate, open); |
441 | if (status) | 442 | if (status) |
442 | goto out; | 443 | goto out; |
444 | resfh = &cstate->current_fh; | ||
443 | break; | 445 | break; |
444 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: | 446 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: |
445 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: | 447 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: |
@@ -459,9 +461,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
459 | * successful, it (1) truncates the file if open->op_truncate was | 461 | * successful, it (1) truncates the file if open->op_truncate was |
460 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. | 462 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. |
461 | */ | 463 | */ |
462 | status = nfsd4_process_open2(rqstp, &cstate->current_fh, open); | 464 | status = nfsd4_process_open2(rqstp, resfh, open); |
463 | WARN_ON(status && open->op_created); | 465 | WARN_ON(status && open->op_created); |
464 | out: | 466 | out: |
467 | if (resfh && resfh != &cstate->current_fh) { | ||
468 | fh_dup2(&cstate->current_fh, resfh); | ||
469 | fh_put(resfh); | ||
470 | kfree(resfh); | ||
471 | } | ||
465 | nfsd4_cleanup_open_state(open, status); | 472 | nfsd4_cleanup_open_state(open, status); |
466 | if (open->op_openowner && !nfsd4_has_session(cstate)) | 473 | if (open->op_openowner && !nfsd4_has_session(cstate)) |
467 | cstate->replay_owner = &open->op_openowner->oo_owner; | 474 | cstate->replay_owner = &open->op_openowner->oo_owner; |
@@ -1070,8 +1077,10 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1070 | cstate->current_fh.fh_dentry, &p, | 1077 | cstate->current_fh.fh_dentry, &p, |
1071 | count, verify->ve_bmval, | 1078 | count, verify->ve_bmval, |
1072 | rqstp, 0); | 1079 | rqstp, 0); |
1073 | 1080 | /* | |
1074 | /* this means that nfsd4_encode_fattr() ran out of space */ | 1081 | * If nfsd4_encode_fattr() ran out of space, assume that's because |
1082 | * the attributes are longer (hence different) than those given: | ||
1083 | */ | ||
1075 | if (status == nfserr_resource) | 1084 | if (status == nfserr_resource) |
1076 | status = nfserr_not_same; | 1085 | status = nfserr_not_same; |
1077 | if (status) | 1086 | if (status) |
@@ -1525,7 +1534,8 @@ static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | |||
1525 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1534 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
1526 | { | 1535 | { |
1527 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ | 1536 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ |
1528 | 1 + 1 + 2 + /* eir_flags, spr_how, spo_must_enforce & _allow */\ | 1537 | 1 + 1 + /* eir_flags, spr_how */\ |
1538 | 4 + /* spo_must_enforce & _allow with bitmap */\ | ||
1529 | 2 + /*eir_server_owner.so_minor_id */\ | 1539 | 2 + /*eir_server_owner.so_minor_id */\ |
1530 | /* eir_server_owner.so_major_id<> */\ | 1540 | /* eir_server_owner.so_major_id<> */\ |
1531 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ | 1541 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ |
@@ -1882,6 +1892,7 @@ struct svc_version nfsd_version4 = { | |||
1882 | .vs_proc = nfsd_procedures4, | 1892 | .vs_proc = nfsd_procedures4, |
1883 | .vs_dispatch = nfsd_dispatch, | 1893 | .vs_dispatch = nfsd_dispatch, |
1884 | .vs_xdrsize = NFS4_SVC_XDRSIZE, | 1894 | .vs_xdrsize = NFS4_SVC_XDRSIZE, |
1895 | .vs_rpcb_optnl = 1, | ||
1885 | }; | 1896 | }; |
1886 | 1897 | ||
1887 | /* | 1898 | /* |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 105d6fa7c514..d5d070fbeb35 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -832,10 +832,11 @@ static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca) | |||
832 | spin_unlock(&nfsd_drc_lock); | 832 | spin_unlock(&nfsd_drc_lock); |
833 | } | 833 | } |
834 | 834 | ||
835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | 835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, |
836 | struct nfsd4_channel_attrs *battrs) | ||
836 | { | 837 | { |
837 | int numslots = attrs->maxreqs; | 838 | int numslots = fattrs->maxreqs; |
838 | int slotsize = slot_bytes(attrs); | 839 | int slotsize = slot_bytes(fattrs); |
839 | struct nfsd4_session *new; | 840 | struct nfsd4_session *new; |
840 | int mem, i; | 841 | int mem, i; |
841 | 842 | ||
@@ -852,6 +853,10 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | |||
852 | if (!new->se_slots[i]) | 853 | if (!new->se_slots[i]) |
853 | goto out_free; | 854 | goto out_free; |
854 | } | 855 | } |
856 | |||
857 | memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); | ||
858 | memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs)); | ||
859 | |||
855 | return new; | 860 | return new; |
856 | out_free: | 861 | out_free: |
857 | while (i--) | 862 | while (i--) |
@@ -997,8 +1002,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru | |||
997 | list_add(&new->se_perclnt, &clp->cl_sessions); | 1002 | list_add(&new->se_perclnt, &clp->cl_sessions); |
998 | spin_unlock(&clp->cl_lock); | 1003 | spin_unlock(&clp->cl_lock); |
999 | spin_unlock(&nn->client_lock); | 1004 | spin_unlock(&nn->client_lock); |
1000 | memcpy(&new->se_fchannel, &cses->fore_channel, | 1005 | |
1001 | sizeof(struct nfsd4_channel_attrs)); | ||
1002 | if (cses->flags & SESSION4_BACK_CHAN) { | 1006 | if (cses->flags & SESSION4_BACK_CHAN) { |
1003 | struct sockaddr *sa = svc_addr(rqstp); | 1007 | struct sockaddr *sa = svc_addr(rqstp); |
1004 | /* | 1008 | /* |
@@ -1851,6 +1855,11 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs | |||
1851 | return nfs_ok; | 1855 | return nfs_ok; |
1852 | } | 1856 | } |
1853 | 1857 | ||
1858 | #define NFSD_CB_MAX_REQ_SZ ((NFS4_enc_cb_recall_sz + \ | ||
1859 | RPC_MAX_HEADER_WITH_AUTH) * sizeof(__be32)) | ||
1860 | #define NFSD_CB_MAX_RESP_SZ ((NFS4_dec_cb_recall_sz + \ | ||
1861 | RPC_MAX_REPHEADER_WITH_AUTH) * sizeof(__be32)) | ||
1862 | |||
1854 | static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) | 1863 | static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) |
1855 | { | 1864 | { |
1856 | ca->headerpadsz = 0; | 1865 | ca->headerpadsz = 0; |
@@ -1861,9 +1870,9 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) | |||
1861 | * less than 1k. Tighten up this estimate in the unlikely event | 1870 | * less than 1k. Tighten up this estimate in the unlikely event |
1862 | * it turns out to be a problem for some client: | 1871 | * it turns out to be a problem for some client: |
1863 | */ | 1872 | */ |
1864 | if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH) | 1873 | if (ca->maxreq_sz < NFSD_CB_MAX_REQ_SZ) |
1865 | return nfserr_toosmall; | 1874 | return nfserr_toosmall; |
1866 | if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH) | 1875 | if (ca->maxresp_sz < NFSD_CB_MAX_RESP_SZ) |
1867 | return nfserr_toosmall; | 1876 | return nfserr_toosmall; |
1868 | ca->maxresp_cached = 0; | 1877 | ca->maxresp_cached = 0; |
1869 | if (ca->maxops < 2) | 1878 | if (ca->maxops < 2) |
@@ -1913,9 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
1913 | return status; | 1922 | return status; |
1914 | status = check_backchannel_attrs(&cr_ses->back_channel); | 1923 | status = check_backchannel_attrs(&cr_ses->back_channel); |
1915 | if (status) | 1924 | if (status) |
1916 | return status; | 1925 | goto out_release_drc_mem; |
1917 | status = nfserr_jukebox; | 1926 | status = nfserr_jukebox; |
1918 | new = alloc_session(&cr_ses->fore_channel); | 1927 | new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel); |
1919 | if (!new) | 1928 | if (!new) |
1920 | goto out_release_drc_mem; | 1929 | goto out_release_drc_mem; |
1921 | conn = alloc_conn_from_crses(rqstp, cr_ses); | 1930 | conn = alloc_conn_from_crses(rqstp, cr_ses); |
@@ -3034,18 +3043,18 @@ static int nfs4_setlease(struct nfs4_delegation *dp) | |||
3034 | if (!fl) | 3043 | if (!fl) |
3035 | return -ENOMEM; | 3044 | return -ENOMEM; |
3036 | fl->fl_file = find_readable_file(fp); | 3045 | fl->fl_file = find_readable_file(fp); |
3037 | list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); | ||
3038 | status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); | 3046 | status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); |
3039 | if (status) { | 3047 | if (status) |
3040 | list_del_init(&dp->dl_perclnt); | 3048 | goto out_free; |
3041 | locks_free_lock(fl); | 3049 | list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); |
3042 | return status; | ||
3043 | } | ||
3044 | fp->fi_lease = fl; | 3050 | fp->fi_lease = fl; |
3045 | fp->fi_deleg_file = get_file(fl->fl_file); | 3051 | fp->fi_deleg_file = get_file(fl->fl_file); |
3046 | atomic_set(&fp->fi_delegees, 1); | 3052 | atomic_set(&fp->fi_delegees, 1); |
3047 | list_add(&dp->dl_perfile, &fp->fi_delegations); | 3053 | list_add(&dp->dl_perfile, &fp->fi_delegations); |
3048 | return 0; | 3054 | return 0; |
3055 | out_free: | ||
3056 | locks_free_lock(fl); | ||
3057 | return status; | ||
3049 | } | 3058 | } |
3050 | 3059 | ||
3051 | static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) | 3060 | static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) |
@@ -3125,6 +3134,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, | |||
3125 | goto out_no_deleg; | 3134 | goto out_no_deleg; |
3126 | break; | 3135 | break; |
3127 | case NFS4_OPEN_CLAIM_NULL: | 3136 | case NFS4_OPEN_CLAIM_NULL: |
3137 | case NFS4_OPEN_CLAIM_FH: | ||
3128 | /* | 3138 | /* |
3129 | * Let's not give out any delegations till everyone's | 3139 | * Let's not give out any delegations till everyone's |
3130 | * had the chance to reclaim theirs.... | 3140 | * had the chance to reclaim theirs.... |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index ee7237f99f54..63f2395c57ed 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -103,11 +103,6 @@ xdr_error: \ | |||
103 | (x) = (u64)ntohl(*p++) << 32; \ | 103 | (x) = (u64)ntohl(*p++) << 32; \ |
104 | (x) |= ntohl(*p++); \ | 104 | (x) |= ntohl(*p++); \ |
105 | } while (0) | 105 | } while (0) |
106 | #define READTIME(x) do { \ | ||
107 | p++; \ | ||
108 | (x) = ntohl(*p++); \ | ||
109 | p++; \ | ||
110 | } while (0) | ||
111 | #define READMEM(x,nbytes) do { \ | 106 | #define READMEM(x,nbytes) do { \ |
112 | x = (char *)p; \ | 107 | x = (char *)p; \ |
113 | p += XDR_QUADLEN(nbytes); \ | 108 | p += XDR_QUADLEN(nbytes); \ |
@@ -190,6 +185,15 @@ static int zero_clientid(clientid_t *clid) | |||
190 | return (clid->cl_boot == 0) && (clid->cl_id == 0); | 185 | return (clid->cl_boot == 0) && (clid->cl_id == 0); |
191 | } | 186 | } |
192 | 187 | ||
188 | /** | ||
189 | * defer_free - mark an allocation as deferred freed | ||
190 | * @argp: NFSv4 compound argument structure to be freed with | ||
191 | * @release: release callback to free @p, typically kfree() | ||
192 | * @p: pointer to be freed | ||
193 | * | ||
194 | * Marks @p to be freed when processing the compound operation | ||
195 | * described in @argp finishes. | ||
196 | */ | ||
193 | static int | 197 | static int |
194 | defer_free(struct nfsd4_compoundargs *argp, | 198 | defer_free(struct nfsd4_compoundargs *argp, |
195 | void (*release)(const void *), void *p) | 199 | void (*release)(const void *), void *p) |
@@ -206,6 +210,16 @@ defer_free(struct nfsd4_compoundargs *argp, | |||
206 | return 0; | 210 | return 0; |
207 | } | 211 | } |
208 | 212 | ||
213 | /** | ||
214 | * savemem - duplicate a chunk of memory for later processing | ||
215 | * @argp: NFSv4 compound argument structure to be freed with | ||
216 | * @p: pointer to be duplicated | ||
217 | * @nbytes: length to be duplicated | ||
218 | * | ||
219 | * Returns a pointer to a copy of @nbytes bytes of memory at @p | ||
220 | * that are preserved until processing of the NFSv4 compound | ||
221 | * operation described by @argp finishes. | ||
222 | */ | ||
209 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) | 223 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) |
210 | { | 224 | { |
211 | if (p == argp->tmp) { | 225 | if (p == argp->tmp) { |
@@ -257,7 +271,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
257 | int expected_len, len = 0; | 271 | int expected_len, len = 0; |
258 | u32 dummy32; | 272 | u32 dummy32; |
259 | char *buf; | 273 | char *buf; |
260 | int host_err; | ||
261 | 274 | ||
262 | DECODE_HEAD; | 275 | DECODE_HEAD; |
263 | iattr->ia_valid = 0; | 276 | iattr->ia_valid = 0; |
@@ -284,10 +297,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
284 | return nfserr_resource; | 297 | return nfserr_resource; |
285 | 298 | ||
286 | *acl = nfs4_acl_new(nace); | 299 | *acl = nfs4_acl_new(nace); |
287 | if (*acl == NULL) { | 300 | if (*acl == NULL) |
288 | host_err = -ENOMEM; | 301 | return nfserr_jukebox; |
289 | goto out_nfserr; | 302 | |
290 | } | ||
291 | defer_free(argp, kfree, *acl); | 303 | defer_free(argp, kfree, *acl); |
292 | 304 | ||
293 | (*acl)->naces = nace; | 305 | (*acl)->naces = nace; |
@@ -425,10 +437,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
425 | goto xdr_error; | 437 | goto xdr_error; |
426 | 438 | ||
427 | DECODE_TAIL; | 439 | DECODE_TAIL; |
428 | |||
429 | out_nfserr: | ||
430 | status = nfserrno(host_err); | ||
431 | goto out; | ||
432 | } | 440 | } |
433 | 441 | ||
434 | static __be32 | 442 | static __be32 |
@@ -1957,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode) | |||
1957 | }; | 1965 | }; |
1958 | } | 1966 | } |
1959 | 1967 | ||
1960 | static __be32 | ||
1961 | nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid, | ||
1962 | __be32 **p, int *buflen) | ||
1963 | { | ||
1964 | int status; | ||
1965 | |||
1966 | if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) | ||
1967 | return nfserr_resource; | ||
1968 | if (whotype != NFS4_ACL_WHO_NAMED) | ||
1969 | status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1)); | ||
1970 | else if (gid_valid(gid)) | ||
1971 | status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1)); | ||
1972 | else | ||
1973 | status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1)); | ||
1974 | if (status < 0) | ||
1975 | return nfserrno(status); | ||
1976 | *p = xdr_encode_opaque(*p, NULL, status); | ||
1977 | *buflen -= (XDR_QUADLEN(status) << 2) + 4; | ||
1978 | BUG_ON(*buflen < 0); | ||
1979 | return 0; | ||
1980 | } | ||
1981 | |||
1982 | static inline __be32 | ||
1983 | nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen) | ||
1984 | { | ||
1985 | return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID, | ||
1986 | p, buflen); | ||
1987 | } | ||
1988 | |||
1989 | static inline __be32 | ||
1990 | nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen) | ||
1991 | { | ||
1992 | return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group, | ||
1993 | p, buflen); | ||
1994 | } | ||
1995 | |||
1996 | static inline __be32 | 1968 | static inline __be32 |
1997 | nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, | 1969 | nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, |
1998 | __be32 **p, int *buflen) | 1970 | __be32 **p, int *buflen) |
1999 | { | 1971 | { |
2000 | kuid_t uid = INVALID_UID; | 1972 | if (ace->whotype != NFS4_ACL_WHO_NAMED) |
2001 | kgid_t gid = INVALID_GID; | 1973 | return nfs4_acl_write_who(ace->whotype, p, buflen); |
2002 | 1974 | else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) | |
2003 | if (ace->whotype == NFS4_ACL_WHO_NAMED) { | 1975 | return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen); |
2004 | if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) | 1976 | else |
2005 | gid = ace->who_gid; | 1977 | return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen); |
2006 | else | ||
2007 | uid = ace->who_uid; | ||
2008 | } | ||
2009 | return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen); | ||
2010 | } | 1978 | } |
2011 | 1979 | ||
2012 | #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ | 1980 | #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ |
@@ -2090,7 +2058,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2090 | u32 bmval1 = bmval[1]; | 2058 | u32 bmval1 = bmval[1]; |
2091 | u32 bmval2 = bmval[2]; | 2059 | u32 bmval2 = bmval[2]; |
2092 | struct kstat stat; | 2060 | struct kstat stat; |
2093 | struct svc_fh tempfh; | 2061 | struct svc_fh *tempfh = NULL; |
2094 | struct kstatfs statfs; | 2062 | struct kstatfs statfs; |
2095 | int buflen = count << 2; | 2063 | int buflen = count << 2; |
2096 | __be32 *attrlenp; | 2064 | __be32 *attrlenp; |
@@ -2137,11 +2105,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2137 | goto out_nfserr; | 2105 | goto out_nfserr; |
2138 | } | 2106 | } |
2139 | if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { | 2107 | if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { |
2140 | fh_init(&tempfh, NFS4_FHSIZE); | 2108 | tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); |
2141 | status = fh_compose(&tempfh, exp, dentry, NULL); | 2109 | status = nfserr_jukebox; |
2110 | if (!tempfh) | ||
2111 | goto out; | ||
2112 | fh_init(tempfh, NFS4_FHSIZE); | ||
2113 | status = fh_compose(tempfh, exp, dentry, NULL); | ||
2142 | if (status) | 2114 | if (status) |
2143 | goto out; | 2115 | goto out; |
2144 | fhp = &tempfh; | 2116 | fhp = tempfh; |
2145 | } | 2117 | } |
2146 | if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT | 2118 | if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT |
2147 | | FATTR4_WORD0_SUPPORTED_ATTRS)) { | 2119 | | FATTR4_WORD0_SUPPORTED_ATTRS)) { |
@@ -2222,8 +2194,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2222 | if ((buflen -= 4) < 0) | 2194 | if ((buflen -= 4) < 0) |
2223 | goto out_resource; | 2195 | goto out_resource; |
2224 | dummy = nfs4_file_type(stat.mode); | 2196 | dummy = nfs4_file_type(stat.mode); |
2225 | if (dummy == NF4BAD) | 2197 | if (dummy == NF4BAD) { |
2226 | goto out_serverfault; | 2198 | status = nfserr_serverfault; |
2199 | goto out; | ||
2200 | } | ||
2227 | WRITE32(dummy); | 2201 | WRITE32(dummy); |
2228 | } | 2202 | } |
2229 | if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { | 2203 | if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { |
@@ -2317,8 +2291,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
2317 | WRITE32(ace->flag); | 2291 | WRITE32(ace->flag); |
2318 | WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); | 2292 | WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); |
2319 | status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); | 2293 | status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); |
2320 | if (status == nfserr_resource) | ||
2321 | goto out_resource; | ||
2322 | if (status) | 2294 | if (status) |
2323 | goto out; | 2295 | goto out; |
2324 | } | 2296 | } |
@@ -2379,8 +2351,6 @@ out_acl: | |||
2379 | } | 2351 | } |
2380 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { | 2352 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { |
2381 | status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); | 2353 | status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); |
2382 | if (status == nfserr_resource) | ||
2383 | goto out_resource; | ||
2384 | if (status) | 2354 | if (status) |
2385 | goto out; | 2355 | goto out; |
2386 | } | 2356 | } |
@@ -2431,15 +2401,11 @@ out_acl: | |||
2431 | } | 2401 | } |
2432 | if (bmval1 & FATTR4_WORD1_OWNER) { | 2402 | if (bmval1 & FATTR4_WORD1_OWNER) { |
2433 | status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); | 2403 | status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); |
2434 | if (status == nfserr_resource) | ||
2435 | goto out_resource; | ||
2436 | if (status) | 2404 | if (status) |
2437 | goto out; | 2405 | goto out; |
2438 | } | 2406 | } |
2439 | if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { | 2407 | if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { |
2440 | status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); | 2408 | status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); |
2441 | if (status == nfserr_resource) | ||
2442 | goto out_resource; | ||
2443 | if (status) | 2409 | if (status) |
2444 | goto out; | 2410 | goto out; |
2445 | } | 2411 | } |
@@ -2533,8 +2499,8 @@ out: | |||
2533 | security_release_secctx(context, contextlen); | 2499 | security_release_secctx(context, contextlen); |
2534 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ | 2500 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ |
2535 | kfree(acl); | 2501 | kfree(acl); |
2536 | if (fhp == &tempfh) | 2502 | if (tempfh) |
2537 | fh_put(&tempfh); | 2503 | fh_put(tempfh); |
2538 | return status; | 2504 | return status; |
2539 | out_nfserr: | 2505 | out_nfserr: |
2540 | status = nfserrno(err); | 2506 | status = nfserrno(err); |
@@ -2542,9 +2508,6 @@ out_nfserr: | |||
2542 | out_resource: | 2508 | out_resource: |
2543 | status = nfserr_resource; | 2509 | status = nfserr_resource; |
2544 | goto out; | 2510 | goto out; |
2545 | out_serverfault: | ||
2546 | status = nfserr_serverfault; | ||
2547 | goto out; | ||
2548 | } | 2511 | } |
2549 | 2512 | ||
2550 | static inline int attributes_need_mount(u32 *bmval) | 2513 | static inline int attributes_need_mount(u32 *bmval) |
@@ -2621,17 +2584,14 @@ out_put: | |||
2621 | static __be32 * | 2584 | static __be32 * |
2622 | nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) | 2585 | nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) |
2623 | { | 2586 | { |
2624 | __be32 *attrlenp; | ||
2625 | |||
2626 | if (buflen < 6) | 2587 | if (buflen < 6) |
2627 | return NULL; | 2588 | return NULL; |
2628 | *p++ = htonl(2); | 2589 | *p++ = htonl(2); |
2629 | *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ | 2590 | *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ |
2630 | *p++ = htonl(0); /* bmval1 */ | 2591 | *p++ = htonl(0); /* bmval1 */ |
2631 | 2592 | ||
2632 | attrlenp = p++; | 2593 | *p++ = htonl(4); /* attribute length */ |
2633 | *p++ = nfserr; /* no htonl */ | 2594 | *p++ = nfserr; /* no htonl */ |
2634 | *attrlenp = htonl((char *)p - (char *)attrlenp - 4); | ||
2635 | return p; | 2595 | return p; |
2636 | } | 2596 | } |
2637 | 2597 | ||
@@ -3244,7 +3204,7 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3244 | 3204 | ||
3245 | if (rpcauth_get_gssinfo(pf, &info) == 0) { | 3205 | if (rpcauth_get_gssinfo(pf, &info) == 0) { |
3246 | supported++; | 3206 | supported++; |
3247 | RESERVE_SPACE(4 + 4 + info.oid.len + 4 + 4); | 3207 | RESERVE_SPACE(4 + 4 + XDR_LEN(info.oid.len) + 4 + 4); |
3248 | WRITE32(RPC_AUTH_GSS); | 3208 | WRITE32(RPC_AUTH_GSS); |
3249 | WRITE32(info.oid.len); | 3209 | WRITE32(info.oid.len); |
3250 | WRITEMEM(info.oid.data, info.oid.len); | 3210 | WRITEMEM(info.oid.data, info.oid.len); |
@@ -3379,35 +3339,43 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3379 | 8 /* eir_clientid */ + | 3339 | 8 /* eir_clientid */ + |
3380 | 4 /* eir_sequenceid */ + | 3340 | 4 /* eir_sequenceid */ + |
3381 | 4 /* eir_flags */ + | 3341 | 4 /* eir_flags */ + |
3382 | 4 /* spr_how */ + | 3342 | 4 /* spr_how */); |
3383 | 8 /* spo_must_enforce, spo_must_allow */ + | ||
3384 | 8 /* so_minor_id */ + | ||
3385 | 4 /* so_major_id.len */ + | ||
3386 | (XDR_QUADLEN(major_id_sz) * 4) + | ||
3387 | 4 /* eir_server_scope.len */ + | ||
3388 | (XDR_QUADLEN(server_scope_sz) * 4) + | ||
3389 | 4 /* eir_server_impl_id.count (0) */); | ||
3390 | 3343 | ||
3391 | WRITEMEM(&exid->clientid, 8); | 3344 | WRITEMEM(&exid->clientid, 8); |
3392 | WRITE32(exid->seqid); | 3345 | WRITE32(exid->seqid); |
3393 | WRITE32(exid->flags); | 3346 | WRITE32(exid->flags); |
3394 | 3347 | ||
3395 | WRITE32(exid->spa_how); | 3348 | WRITE32(exid->spa_how); |
3349 | ADJUST_ARGS(); | ||
3350 | |||
3396 | switch (exid->spa_how) { | 3351 | switch (exid->spa_how) { |
3397 | case SP4_NONE: | 3352 | case SP4_NONE: |
3398 | break; | 3353 | break; |
3399 | case SP4_MACH_CRED: | 3354 | case SP4_MACH_CRED: |
3355 | /* spo_must_enforce, spo_must_allow */ | ||
3356 | RESERVE_SPACE(16); | ||
3357 | |||
3400 | /* spo_must_enforce bitmap: */ | 3358 | /* spo_must_enforce bitmap: */ |
3401 | WRITE32(2); | 3359 | WRITE32(2); |
3402 | WRITE32(nfs4_minimal_spo_must_enforce[0]); | 3360 | WRITE32(nfs4_minimal_spo_must_enforce[0]); |
3403 | WRITE32(nfs4_minimal_spo_must_enforce[1]); | 3361 | WRITE32(nfs4_minimal_spo_must_enforce[1]); |
3404 | /* empty spo_must_allow bitmap: */ | 3362 | /* empty spo_must_allow bitmap: */ |
3405 | WRITE32(0); | 3363 | WRITE32(0); |
3364 | |||
3365 | ADJUST_ARGS(); | ||
3406 | break; | 3366 | break; |
3407 | default: | 3367 | default: |
3408 | WARN_ON_ONCE(1); | 3368 | WARN_ON_ONCE(1); |
3409 | } | 3369 | } |
3410 | 3370 | ||
3371 | RESERVE_SPACE( | ||
3372 | 8 /* so_minor_id */ + | ||
3373 | 4 /* so_major_id.len */ + | ||
3374 | (XDR_QUADLEN(major_id_sz) * 4) + | ||
3375 | 4 /* eir_server_scope.len */ + | ||
3376 | (XDR_QUADLEN(server_scope_sz) * 4) + | ||
3377 | 4 /* eir_server_impl_id.count (0) */); | ||
3378 | |||
3411 | /* The server_owner struct */ | 3379 | /* The server_owner struct */ |
3412 | WRITE64(minor_id); /* Minor id */ | 3380 | WRITE64(minor_id); /* Minor id */ |
3413 | /* major id */ | 3381 | /* major id */ |
@@ -3474,28 +3442,6 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3474 | } | 3442 | } |
3475 | 3443 | ||
3476 | static __be32 | 3444 | static __be32 |
3477 | nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
3478 | struct nfsd4_destroy_session *destroy_session) | ||
3479 | { | ||
3480 | return nfserr; | ||
3481 | } | ||
3482 | |||
3483 | static __be32 | ||
3484 | nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
3485 | struct nfsd4_free_stateid *free_stateid) | ||
3486 | { | ||
3487 | __be32 *p; | ||
3488 | |||
3489 | if (nfserr) | ||
3490 | return nfserr; | ||
3491 | |||
3492 | RESERVE_SPACE(4); | ||
3493 | *p++ = nfserr; | ||
3494 | ADJUST_ARGS(); | ||
3495 | return nfserr; | ||
3496 | } | ||
3497 | |||
3498 | static __be32 | ||
3499 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, | 3445 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, |
3500 | struct nfsd4_sequence *seq) | 3446 | struct nfsd4_sequence *seq) |
3501 | { | 3447 | { |
@@ -3593,8 +3539,8 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
3593 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, | 3539 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, |
3594 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, | 3540 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, |
3595 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, | 3541 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, |
3596 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, | 3542 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_noop, |
3597 | [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid, | 3543 | [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop, |
3598 | [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, | 3544 | [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, |
3599 | [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, | 3545 | [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, |
3600 | [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, | 3546 | [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, |
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index b6af150c96b8..f8f060ffbf4f 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c | |||
@@ -132,13 +132,6 @@ nfsd_reply_cache_alloc(void) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | static void | 134 | static void |
135 | nfsd_reply_cache_unhash(struct svc_cacherep *rp) | ||
136 | { | ||
137 | hlist_del_init(&rp->c_hash); | ||
138 | list_del_init(&rp->c_lru); | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | nfsd_reply_cache_free_locked(struct svc_cacherep *rp) | 135 | nfsd_reply_cache_free_locked(struct svc_cacherep *rp) |
143 | { | 136 | { |
144 | if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) { | 137 | if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) { |
@@ -416,22 +409,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) | |||
416 | 409 | ||
417 | /* | 410 | /* |
418 | * Since the common case is a cache miss followed by an insert, | 411 | * Since the common case is a cache miss followed by an insert, |
419 | * preallocate an entry. First, try to reuse the first entry on the LRU | 412 | * preallocate an entry. |
420 | * if it works, then go ahead and prune the LRU list. | ||
421 | */ | 413 | */ |
422 | spin_lock(&cache_lock); | ||
423 | if (!list_empty(&lru_head)) { | ||
424 | rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru); | ||
425 | if (nfsd_cache_entry_expired(rp) || | ||
426 | num_drc_entries >= max_drc_entries) { | ||
427 | nfsd_reply_cache_unhash(rp); | ||
428 | prune_cache_entries(); | ||
429 | goto search_cache; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | /* No expired ones available, allocate a new one. */ | ||
434 | spin_unlock(&cache_lock); | ||
435 | rp = nfsd_reply_cache_alloc(); | 414 | rp = nfsd_reply_cache_alloc(); |
436 | spin_lock(&cache_lock); | 415 | spin_lock(&cache_lock); |
437 | if (likely(rp)) { | 416 | if (likely(rp)) { |
@@ -439,7 +418,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) | |||
439 | drc_mem_usage += sizeof(*rp); | 418 | drc_mem_usage += sizeof(*rp); |
440 | } | 419 | } |
441 | 420 | ||
442 | search_cache: | 421 | /* go ahead and prune the cache */ |
422 | prune_cache_entries(); | ||
423 | |||
443 | found = nfsd_cache_search(rqstp, csum); | 424 | found = nfsd_cache_search(rqstp, csum); |
444 | if (found) { | 425 | if (found) { |
445 | if (likely(rp)) | 426 | if (likely(rp)) |
@@ -453,15 +434,6 @@ search_cache: | |||
453 | goto out; | 434 | goto out; |
454 | } | 435 | } |
455 | 436 | ||
456 | /* | ||
457 | * We're keeping the one we just allocated. Are we now over the | ||
458 | * limit? Prune one off the tip of the LRU in trade for the one we | ||
459 | * just allocated if so. | ||
460 | */ | ||
461 | if (num_drc_entries >= max_drc_entries) | ||
462 | nfsd_reply_cache_free_locked(list_first_entry(&lru_head, | ||
463 | struct svc_cacherep, c_lru)); | ||
464 | |||
465 | nfsdstats.rcmisses++; | 437 | nfsdstats.rcmisses++; |
466 | rqstp->rq_cacherep = rp; | 438 | rqstp->rq_cacherep = rp; |
467 | rp->c_state = RC_INPROG; | 439 | rp->c_state = RC_INPROG; |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 760c85a6f534..9a4a5f9e7468 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -241,6 +241,15 @@ static void nfsd_shutdown_generic(void) | |||
241 | nfsd_racache_shutdown(); | 241 | nfsd_racache_shutdown(); |
242 | } | 242 | } |
243 | 243 | ||
244 | static bool nfsd_needs_lockd(void) | ||
245 | { | ||
246 | #if defined(CONFIG_NFSD_V3) | ||
247 | return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL); | ||
248 | #else | ||
249 | return (nfsd_versions[2] != NULL); | ||
250 | #endif | ||
251 | } | ||
252 | |||
244 | static int nfsd_startup_net(int nrservs, struct net *net) | 253 | static int nfsd_startup_net(int nrservs, struct net *net) |
245 | { | 254 | { |
246 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 255 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
@@ -255,9 +264,14 @@ static int nfsd_startup_net(int nrservs, struct net *net) | |||
255 | ret = nfsd_init_socks(net); | 264 | ret = nfsd_init_socks(net); |
256 | if (ret) | 265 | if (ret) |
257 | goto out_socks; | 266 | goto out_socks; |
258 | ret = lockd_up(net); | 267 | |
259 | if (ret) | 268 | if (nfsd_needs_lockd() && !nn->lockd_up) { |
260 | goto out_socks; | 269 | ret = lockd_up(net); |
270 | if (ret) | ||
271 | goto out_socks; | ||
272 | nn->lockd_up = 1; | ||
273 | } | ||
274 | |||
261 | ret = nfs4_state_start_net(net); | 275 | ret = nfs4_state_start_net(net); |
262 | if (ret) | 276 | if (ret) |
263 | goto out_lockd; | 277 | goto out_lockd; |
@@ -266,7 +280,10 @@ static int nfsd_startup_net(int nrservs, struct net *net) | |||
266 | return 0; | 280 | return 0; |
267 | 281 | ||
268 | out_lockd: | 282 | out_lockd: |
269 | lockd_down(net); | 283 | if (nn->lockd_up) { |
284 | lockd_down(net); | ||
285 | nn->lockd_up = 0; | ||
286 | } | ||
270 | out_socks: | 287 | out_socks: |
271 | nfsd_shutdown_generic(); | 288 | nfsd_shutdown_generic(); |
272 | return ret; | 289 | return ret; |
@@ -277,7 +294,10 @@ static void nfsd_shutdown_net(struct net *net) | |||
277 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 294 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
278 | 295 | ||
279 | nfs4_state_shutdown_net(net); | 296 | nfs4_state_shutdown_net(net); |
280 | lockd_down(net); | 297 | if (nn->lockd_up) { |
298 | lockd_down(net); | ||
299 | nn->lockd_up = 0; | ||
300 | } | ||
281 | nn->nfsd_net_up = false; | 301 | nn->nfsd_net_up = false; |
282 | nfsd_shutdown_generic(); | 302 | nfsd_shutdown_generic(); |
283 | } | 303 | } |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 9c769a47ac5a..b17d93214d01 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
152 | type = (stat->mode & S_IFMT); | 152 | type = (stat->mode & S_IFMT); |
153 | 153 | ||
154 | *p++ = htonl(nfs_ftypes[type >> 12]); | 154 | *p++ = htonl(nfs_ftypes[type >> 12]); |
155 | *p++ = htonl((u32) stat->mode); | 155 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); |
156 | *p++ = htonl((u32) stat->nlink); | 156 | *p++ = htonl((u32) stat->nlink); |
157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); | 157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); | 158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1426eb66c8c6..017d3cb5e99b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -207,7 +207,12 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
207 | goto out_nfserr; | 207 | goto out_nfserr; |
208 | } | 208 | } |
209 | } else { | 209 | } else { |
210 | fh_lock(fhp); | 210 | /* |
211 | * In the nfsd4_open() case, this may be held across | ||
212 | * subsequent open and delegation acquisition which may | ||
213 | * need to take the child's i_mutex: | ||
214 | */ | ||
215 | fh_lock_nested(fhp, I_MUTEX_PARENT); | ||
211 | dentry = lookup_one_len(name, dparent, len); | 216 | dentry = lookup_one_len(name, dparent, len); |
212 | host_err = PTR_ERR(dentry); | 217 | host_err = PTR_ERR(dentry); |
213 | if (IS_ERR(dentry)) | 218 | if (IS_ERR(dentry)) |
@@ -273,13 +278,6 @@ out: | |||
273 | return err; | 278 | return err; |
274 | } | 279 | } |
275 | 280 | ||
276 | static int nfsd_break_lease(struct inode *inode) | ||
277 | { | ||
278 | if (!S_ISREG(inode->i_mode)) | ||
279 | return 0; | ||
280 | return break_lease(inode, O_WRONLY | O_NONBLOCK); | ||
281 | } | ||
282 | |||
283 | /* | 281 | /* |
284 | * Commit metadata changes to stable storage. | 282 | * Commit metadata changes to stable storage. |
285 | */ | 283 | */ |
@@ -348,8 +346,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) | |||
348 | 346 | ||
349 | /* Revoke setuid/setgid on chown */ | 347 | /* Revoke setuid/setgid on chown */ |
350 | if (!S_ISDIR(inode->i_mode) && | 348 | if (!S_ISDIR(inode->i_mode) && |
351 | (((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) || | 349 | ((iap->ia_valid & ATTR_UID) || (iap->ia_valid & ATTR_GID))) { |
352 | ((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) { | ||
353 | iap->ia_valid |= ATTR_KILL_PRIV; | 350 | iap->ia_valid |= ATTR_KILL_PRIV; |
354 | if (iap->ia_valid & ATTR_MODE) { | 351 | if (iap->ia_valid & ATTR_MODE) { |
355 | /* we're setting mode too, just clear the s*id bits */ | 352 | /* we're setting mode too, just clear the s*id bits */ |
@@ -449,16 +446,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
449 | goto out_put_write_access; | 446 | goto out_put_write_access; |
450 | } | 447 | } |
451 | 448 | ||
452 | host_err = nfsd_break_lease(inode); | ||
453 | if (host_err) | ||
454 | goto out_put_write_access_nfserror; | ||
455 | |||
456 | fh_lock(fhp); | 449 | fh_lock(fhp); |
457 | host_err = notify_change(dentry, iap, NULL); | 450 | host_err = notify_change(dentry, iap, NULL); |
458 | fh_unlock(fhp); | 451 | fh_unlock(fhp); |
459 | 452 | ||
460 | out_put_write_access_nfserror: | ||
461 | err = nfserrno(host_err); | ||
462 | out_put_write_access: | 453 | out_put_write_access: |
463 | if (size_change) | 454 | if (size_change) |
464 | put_write_access(inode); | 455 | put_write_access(inode); |
@@ -1609,11 +1600,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1609 | err = nfserr_noent; | 1600 | err = nfserr_noent; |
1610 | if (!dold->d_inode) | 1601 | if (!dold->d_inode) |
1611 | goto out_dput; | 1602 | goto out_dput; |
1612 | host_err = nfsd_break_lease(dold->d_inode); | ||
1613 | if (host_err) { | ||
1614 | err = nfserrno(host_err); | ||
1615 | goto out_dput; | ||
1616 | } | ||
1617 | host_err = vfs_link(dold, dirp, dnew, NULL); | 1603 | host_err = vfs_link(dold, dirp, dnew, NULL); |
1618 | if (!host_err) { | 1604 | if (!host_err) { |
1619 | err = nfserrno(commit_metadata(ffhp)); | 1605 | err = nfserrno(commit_metadata(ffhp)); |
@@ -1707,14 +1693,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1707 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) | 1693 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) |
1708 | goto out_dput_new; | 1694 | goto out_dput_new; |
1709 | 1695 | ||
1710 | host_err = nfsd_break_lease(odentry->d_inode); | ||
1711 | if (host_err) | ||
1712 | goto out_dput_new; | ||
1713 | if (ndentry->d_inode) { | ||
1714 | host_err = nfsd_break_lease(ndentry->d_inode); | ||
1715 | if (host_err) | ||
1716 | goto out_dput_new; | ||
1717 | } | ||
1718 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); | 1696 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); |
1719 | if (!host_err) { | 1697 | if (!host_err) { |
1720 | host_err = commit_metadata(tfhp); | 1698 | host_err = commit_metadata(tfhp); |
@@ -1784,16 +1762,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1784 | if (!type) | 1762 | if (!type) |
1785 | type = rdentry->d_inode->i_mode & S_IFMT; | 1763 | type = rdentry->d_inode->i_mode & S_IFMT; |
1786 | 1764 | ||
1787 | host_err = nfsd_break_lease(rdentry->d_inode); | ||
1788 | if (host_err) | ||
1789 | goto out_put; | ||
1790 | if (type != S_IFDIR) | 1765 | if (type != S_IFDIR) |
1791 | host_err = vfs_unlink(dirp, rdentry, NULL); | 1766 | host_err = vfs_unlink(dirp, rdentry, NULL); |
1792 | else | 1767 | else |
1793 | host_err = vfs_rmdir(dirp, rdentry); | 1768 | host_err = vfs_rmdir(dirp, rdentry); |
1794 | if (!host_err) | 1769 | if (!host_err) |
1795 | host_err = commit_metadata(fhp); | 1770 | host_err = commit_metadata(fhp); |
1796 | out_put: | ||
1797 | dput(rdentry); | 1771 | dput(rdentry); |
1798 | 1772 | ||
1799 | out_nfserr: | 1773 | out_nfserr: |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 1bc1d440a1a5..fbe90bdb2214 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -86,8 +86,6 @@ __be32 nfsd_link(struct svc_rqst *, struct svc_fh *, | |||
86 | __be32 nfsd_rename(struct svc_rqst *, | 86 | __be32 nfsd_rename(struct svc_rqst *, |
87 | struct svc_fh *, char *, int, | 87 | struct svc_fh *, char *, int, |
88 | struct svc_fh *, char *, int); | 88 | struct svc_fh *, char *, int); |
89 | __be32 nfsd_remove(struct svc_rqst *, | ||
90 | struct svc_fh *, char *, int); | ||
91 | __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, | 89 | __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, |
92 | char *name, int len); | 90 | char *name, int len); |
93 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, | 91 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, |
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h index b6d5542a4ac8..335e04aaf7db 100644 --- a/fs/nfsd/xdr3.h +++ b/fs/nfsd/xdr3.h | |||
@@ -174,6 +174,9 @@ struct nfsd3_linkres { | |||
174 | struct nfsd3_readdirres { | 174 | struct nfsd3_readdirres { |
175 | __be32 status; | 175 | __be32 status; |
176 | struct svc_fh fh; | 176 | struct svc_fh fh; |
177 | /* Just to save kmalloc on every readdirplus entry (svc_fh is a | ||
178 | * little large for the stack): */ | ||
179 | struct svc_fh scratch; | ||
177 | int count; | 180 | int count; |
178 | __be32 verf[2]; | 181 | __be32 verf[2]; |
179 | 182 | ||
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index b3ed6446ed8e..d278a0d03496 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -228,7 +228,7 @@ struct nfsd4_open { | |||
228 | u32 op_create; /* request */ | 228 | u32 op_create; /* request */ |
229 | u32 op_createmode; /* request */ | 229 | u32 op_createmode; /* request */ |
230 | u32 op_bmval[3]; /* request */ | 230 | u32 op_bmval[3]; /* request */ |
231 | struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ | 231 | struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ |
232 | nfs4_verifier op_verf __attribute__((aligned(32))); | 232 | nfs4_verifier op_verf __attribute__((aligned(32))); |
233 | /* EXCLUSIVE4 */ | 233 | /* EXCLUSIVE4 */ |
234 | clientid_t op_clientid; /* request */ | 234 | clientid_t op_clientid; /* request */ |
@@ -250,7 +250,6 @@ struct nfsd4_open { | |||
250 | struct nfs4_acl *op_acl; | 250 | struct nfs4_acl *op_acl; |
251 | struct xdr_netobj op_label; | 251 | struct xdr_netobj op_label; |
252 | }; | 252 | }; |
253 | #define op_iattr iattr | ||
254 | 253 | ||
255 | struct nfsd4_open_confirm { | 254 | struct nfsd4_open_confirm { |
256 | stateid_t oc_req_stateid /* request */; | 255 | stateid_t oc_req_stateid /* request */; |
@@ -374,7 +373,6 @@ struct nfsd4_test_stateid { | |||
374 | 373 | ||
375 | struct nfsd4_free_stateid { | 374 | struct nfsd4_free_stateid { |
376 | stateid_t fr_stateid; /* request */ | 375 | stateid_t fr_stateid; /* request */ |
377 | __be32 fr_status; /* response */ | ||
378 | }; | 376 | }; |
379 | 377 | ||
380 | /* also used for NVERIFY */ | 378 | /* also used for NVERIFY */ |
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 6eecfc2e4f98..04e763221246 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h | |||
@@ -368,7 +368,7 @@ struct svc_program { | |||
368 | struct svc_program * pg_next; /* other programs (same xprt) */ | 368 | struct svc_program * pg_next; /* other programs (same xprt) */ |
369 | u32 pg_prog; /* program number */ | 369 | u32 pg_prog; /* program number */ |
370 | unsigned int pg_lovers; /* lowest version */ | 370 | unsigned int pg_lovers; /* lowest version */ |
371 | unsigned int pg_hivers; /* lowest version */ | 371 | unsigned int pg_hivers; /* highest version */ |
372 | unsigned int pg_nvers; /* number of versions */ | 372 | unsigned int pg_nvers; /* number of versions */ |
373 | struct svc_version ** pg_vers; /* version array */ | 373 | struct svc_version ** pg_vers; /* version array */ |
374 | char * pg_name; /* service name */ | 374 | char * pg_name; /* service name */ |
@@ -386,8 +386,10 @@ struct svc_version { | |||
386 | struct svc_procedure * vs_proc; /* per-procedure info */ | 386 | struct svc_procedure * vs_proc; /* per-procedure info */ |
387 | u32 vs_xdrsize; /* xdrsize needed for this version */ | 387 | u32 vs_xdrsize; /* xdrsize needed for this version */ |
388 | 388 | ||
389 | unsigned int vs_hidden : 1; /* Don't register with portmapper. | 389 | unsigned int vs_hidden : 1, /* Don't register with portmapper. |
390 | * Only used for nfsacl so far. */ | 390 | * Only used for nfsacl so far. */ |
391 | vs_rpcb_optnl:1;/* Don't care the result of register. | ||
392 | * Only used for nfsv4. */ | ||
391 | 393 | ||
392 | /* Override dispatch function (e.g. when caching replies). | 394 | /* Override dispatch function (e.g. when caching replies). |
393 | * A return value of 0 means drop the request. | 395 | * A return value of 0 means drop the request. |
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index 76e42e6be755..24589bd2a4b6 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/crypto.h> | 59 | #include <linux/crypto.h> |
60 | #include <linux/sunrpc/gss_krb5.h> | 60 | #include <linux/sunrpc/gss_krb5.h> |
61 | #include <linux/sunrpc/xdr.h> | 61 | #include <linux/sunrpc/xdr.h> |
62 | #include <linux/lcm.h> | ||
62 | 63 | ||
63 | #ifdef RPC_DEBUG | 64 | #ifdef RPC_DEBUG |
64 | # define RPCDBG_FACILITY RPCDBG_AUTH | 65 | # define RPCDBG_FACILITY RPCDBG_AUTH |
@@ -72,7 +73,7 @@ | |||
72 | static void krb5_nfold(u32 inbits, const u8 *in, | 73 | static void krb5_nfold(u32 inbits, const u8 *in, |
73 | u32 outbits, u8 *out) | 74 | u32 outbits, u8 *out) |
74 | { | 75 | { |
75 | int a, b, c, lcm; | 76 | unsigned long ulcm; |
76 | int byte, i, msbit; | 77 | int byte, i, msbit; |
77 | 78 | ||
78 | /* the code below is more readable if I make these bytes | 79 | /* the code below is more readable if I make these bytes |
@@ -82,17 +83,7 @@ static void krb5_nfold(u32 inbits, const u8 *in, | |||
82 | outbits >>= 3; | 83 | outbits >>= 3; |
83 | 84 | ||
84 | /* first compute lcm(n,k) */ | 85 | /* first compute lcm(n,k) */ |
85 | 86 | ulcm = lcm(inbits, outbits); | |
86 | a = outbits; | ||
87 | b = inbits; | ||
88 | |||
89 | while (b != 0) { | ||
90 | c = b; | ||
91 | b = a%b; | ||
92 | a = c; | ||
93 | } | ||
94 | |||
95 | lcm = outbits*inbits/a; | ||
96 | 87 | ||
97 | /* now do the real work */ | 88 | /* now do the real work */ |
98 | 89 | ||
@@ -101,7 +92,7 @@ static void krb5_nfold(u32 inbits, const u8 *in, | |||
101 | 92 | ||
102 | /* this will end up cycling through k lcm(k,n)/k times, which | 93 | /* this will end up cycling through k lcm(k,n)/k times, which |
103 | is correct */ | 94 | is correct */ |
104 | for (i = lcm-1; i >= 0; i--) { | 95 | for (i = ulcm-1; i >= 0; i--) { |
105 | /* compute the msbit in k which gets added into this byte */ | 96 | /* compute the msbit in k which gets added into this byte */ |
106 | msbit = ( | 97 | msbit = ( |
107 | /* first, start with the msbit in the first, | 98 | /* first, start with the msbit in the first, |
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index 458f85e9b0ba..abbb7dcd1689 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c | |||
@@ -137,7 +137,6 @@ void init_gssp_clnt(struct sunrpc_net *sn) | |||
137 | { | 137 | { |
138 | mutex_init(&sn->gssp_lock); | 138 | mutex_init(&sn->gssp_lock); |
139 | sn->gssp_clnt = NULL; | 139 | sn->gssp_clnt = NULL; |
140 | init_waitqueue_head(&sn->gssp_wq); | ||
141 | } | 140 | } |
142 | 141 | ||
143 | int set_gssp_clnt(struct net *net) | 142 | int set_gssp_clnt(struct net *net) |
@@ -154,7 +153,6 @@ int set_gssp_clnt(struct net *net) | |||
154 | sn->gssp_clnt = clnt; | 153 | sn->gssp_clnt = clnt; |
155 | } | 154 | } |
156 | mutex_unlock(&sn->gssp_lock); | 155 | mutex_unlock(&sn->gssp_lock); |
157 | wake_up(&sn->gssp_wq); | ||
158 | return ret; | 156 | return ret; |
159 | } | 157 | } |
160 | 158 | ||
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 008cdade5aae..0f73f4507746 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1263,65 +1263,34 @@ out: | |||
1263 | return ret; | 1263 | return ret; |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | DEFINE_SPINLOCK(use_gssp_lock); | 1266 | /* |
1267 | 1267 | * Try to set the sn->use_gss_proxy variable to a new value. We only allow | |
1268 | static bool use_gss_proxy(struct net *net) | 1268 | * it to be changed if it's currently undefined (-1). If it's any other value |
1269 | { | 1269 | * then return -EBUSY unless the type wouldn't have changed anyway. |
1270 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1270 | */ |
1271 | |||
1272 | if (sn->use_gss_proxy != -1) | ||
1273 | return sn->use_gss_proxy; | ||
1274 | spin_lock(&use_gssp_lock); | ||
1275 | /* | ||
1276 | * If you wanted gss-proxy, you should have said so before | ||
1277 | * starting to accept requests: | ||
1278 | */ | ||
1279 | sn->use_gss_proxy = 0; | ||
1280 | spin_unlock(&use_gssp_lock); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | #ifdef CONFIG_PROC_FS | ||
1285 | |||
1286 | static int set_gss_proxy(struct net *net, int type) | 1271 | static int set_gss_proxy(struct net *net, int type) |
1287 | { | 1272 | { |
1288 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1273 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1289 | int ret = 0; | 1274 | int ret; |
1290 | 1275 | ||
1291 | WARN_ON_ONCE(type != 0 && type != 1); | 1276 | WARN_ON_ONCE(type != 0 && type != 1); |
1292 | spin_lock(&use_gssp_lock); | 1277 | ret = cmpxchg(&sn->use_gss_proxy, -1, type); |
1293 | if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type) | 1278 | if (ret != -1 && ret != type) |
1294 | sn->use_gss_proxy = type; | 1279 | return -EBUSY; |
1295 | else | 1280 | return 0; |
1296 | ret = -EBUSY; | ||
1297 | spin_unlock(&use_gssp_lock); | ||
1298 | wake_up(&sn->gssp_wq); | ||
1299 | return ret; | ||
1300 | } | ||
1301 | |||
1302 | static inline bool gssp_ready(struct sunrpc_net *sn) | ||
1303 | { | ||
1304 | switch (sn->use_gss_proxy) { | ||
1305 | case -1: | ||
1306 | return false; | ||
1307 | case 0: | ||
1308 | return true; | ||
1309 | case 1: | ||
1310 | return sn->gssp_clnt; | ||
1311 | } | ||
1312 | WARN_ON_ONCE(1); | ||
1313 | return false; | ||
1314 | } | 1281 | } |
1315 | 1282 | ||
1316 | static int wait_for_gss_proxy(struct net *net, struct file *file) | 1283 | static bool use_gss_proxy(struct net *net) |
1317 | { | 1284 | { |
1318 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1285 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1319 | 1286 | ||
1320 | if (file->f_flags & O_NONBLOCK && !gssp_ready(sn)) | 1287 | /* If use_gss_proxy is still undefined, then try to disable it */ |
1321 | return -EAGAIN; | 1288 | if (sn->use_gss_proxy == -1) |
1322 | return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); | 1289 | set_gss_proxy(net, 0); |
1290 | return sn->use_gss_proxy; | ||
1323 | } | 1291 | } |
1324 | 1292 | ||
1293 | #ifdef CONFIG_PROC_FS | ||
1325 | 1294 | ||
1326 | static ssize_t write_gssp(struct file *file, const char __user *buf, | 1295 | static ssize_t write_gssp(struct file *file, const char __user *buf, |
1327 | size_t count, loff_t *ppos) | 1296 | size_t count, loff_t *ppos) |
@@ -1342,10 +1311,10 @@ static ssize_t write_gssp(struct file *file, const char __user *buf, | |||
1342 | return res; | 1311 | return res; |
1343 | if (i != 1) | 1312 | if (i != 1) |
1344 | return -EINVAL; | 1313 | return -EINVAL; |
1345 | res = set_gss_proxy(net, 1); | 1314 | res = set_gssp_clnt(net); |
1346 | if (res) | 1315 | if (res) |
1347 | return res; | 1316 | return res; |
1348 | res = set_gssp_clnt(net); | 1317 | res = set_gss_proxy(net, 1); |
1349 | if (res) | 1318 | if (res) |
1350 | return res; | 1319 | return res; |
1351 | return count; | 1320 | return count; |
@@ -1355,16 +1324,12 @@ static ssize_t read_gssp(struct file *file, char __user *buf, | |||
1355 | size_t count, loff_t *ppos) | 1324 | size_t count, loff_t *ppos) |
1356 | { | 1325 | { |
1357 | struct net *net = PDE_DATA(file_inode(file)); | 1326 | struct net *net = PDE_DATA(file_inode(file)); |
1327 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1358 | unsigned long p = *ppos; | 1328 | unsigned long p = *ppos; |
1359 | char tbuf[10]; | 1329 | char tbuf[10]; |
1360 | size_t len; | 1330 | size_t len; |
1361 | int ret; | ||
1362 | 1331 | ||
1363 | ret = wait_for_gss_proxy(net, file); | 1332 | snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy); |
1364 | if (ret) | ||
1365 | return ret; | ||
1366 | |||
1367 | snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net)); | ||
1368 | len = strlen(tbuf); | 1333 | len = strlen(tbuf); |
1369 | if (p >= len) | 1334 | if (p >= len) |
1370 | return 0; | 1335 | return 0; |
@@ -1626,8 +1591,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) | |||
1626 | BUG_ON(integ_len % 4); | 1591 | BUG_ON(integ_len % 4); |
1627 | *p++ = htonl(integ_len); | 1592 | *p++ = htonl(integ_len); |
1628 | *p++ = htonl(gc->gc_seq); | 1593 | *p++ = htonl(gc->gc_seq); |
1629 | if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, | 1594 | if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) |
1630 | integ_len)) | ||
1631 | BUG(); | 1595 | BUG(); |
1632 | if (resbuf->tail[0].iov_base == NULL) { | 1596 | if (resbuf->tail[0].iov_base == NULL) { |
1633 | if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) | 1597 | if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) |
@@ -1635,10 +1599,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) | |||
1635 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base | 1599 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base |
1636 | + resbuf->head[0].iov_len; | 1600 | + resbuf->head[0].iov_len; |
1637 | resbuf->tail[0].iov_len = 0; | 1601 | resbuf->tail[0].iov_len = 0; |
1638 | resv = &resbuf->tail[0]; | ||
1639 | } else { | ||
1640 | resv = &resbuf->tail[0]; | ||
1641 | } | 1602 | } |
1603 | resv = &resbuf->tail[0]; | ||
1642 | mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; | 1604 | mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; |
1643 | if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) | 1605 | if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) |
1644 | goto out_err; | 1606 | goto out_err; |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e521d20e1970..ae333c1845bb 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -1111,9 +1111,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen) | |||
1111 | *bp++ = 'x'; | 1111 | *bp++ = 'x'; |
1112 | len -= 2; | 1112 | len -= 2; |
1113 | while (blen && len >= 2) { | 1113 | while (blen && len >= 2) { |
1114 | unsigned char c = *buf++; | 1114 | bp = hex_byte_pack(bp, *buf++); |
1115 | *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); | ||
1116 | *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); | ||
1117 | len -= 2; | 1115 | len -= 2; |
1118 | blen--; | 1116 | blen--; |
1119 | } | 1117 | } |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 94e506f9d72b..df5826876535 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -27,7 +27,6 @@ struct sunrpc_net { | |||
27 | unsigned int rpcb_is_af_local : 1; | 27 | unsigned int rpcb_is_af_local : 1; |
28 | 28 | ||
29 | struct mutex gssp_lock; | 29 | struct mutex gssp_lock; |
30 | wait_queue_head_t gssp_wq; | ||
31 | struct rpc_clnt *gssp_clnt; | 30 | struct rpc_clnt *gssp_clnt; |
32 | int use_gss_proxy; | 31 | int use_gss_proxy; |
33 | int pipe_version; | 32 | int pipe_version; |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e7fbe368b4a3..5de6801cd924 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -916,9 +916,6 @@ static int __svc_register(struct net *net, const char *progname, | |||
916 | #endif | 916 | #endif |
917 | } | 917 | } |
918 | 918 | ||
919 | if (error < 0) | ||
920 | printk(KERN_WARNING "svc: failed to register %sv%u RPC " | ||
921 | "service (errno %d).\n", progname, version, -error); | ||
922 | return error; | 919 | return error; |
923 | } | 920 | } |
924 | 921 | ||
@@ -937,6 +934,7 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
937 | const unsigned short port) | 934 | const unsigned short port) |
938 | { | 935 | { |
939 | struct svc_program *progp; | 936 | struct svc_program *progp; |
937 | struct svc_version *vers; | ||
940 | unsigned int i; | 938 | unsigned int i; |
941 | int error = 0; | 939 | int error = 0; |
942 | 940 | ||
@@ -946,7 +944,8 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
946 | 944 | ||
947 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | 945 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { |
948 | for (i = 0; i < progp->pg_nvers; i++) { | 946 | for (i = 0; i < progp->pg_nvers; i++) { |
949 | if (progp->pg_vers[i] == NULL) | 947 | vers = progp->pg_vers[i]; |
948 | if (vers == NULL) | ||
950 | continue; | 949 | continue; |
951 | 950 | ||
952 | dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", | 951 | dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", |
@@ -955,16 +954,26 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
955 | proto == IPPROTO_UDP? "udp" : "tcp", | 954 | proto == IPPROTO_UDP? "udp" : "tcp", |
956 | port, | 955 | port, |
957 | family, | 956 | family, |
958 | progp->pg_vers[i]->vs_hidden? | 957 | vers->vs_hidden ? |
959 | " (but not telling portmap)" : ""); | 958 | " (but not telling portmap)" : ""); |
960 | 959 | ||
961 | if (progp->pg_vers[i]->vs_hidden) | 960 | if (vers->vs_hidden) |
962 | continue; | 961 | continue; |
963 | 962 | ||
964 | error = __svc_register(net, progp->pg_name, progp->pg_prog, | 963 | error = __svc_register(net, progp->pg_name, progp->pg_prog, |
965 | i, family, proto, port); | 964 | i, family, proto, port); |
966 | if (error < 0) | 965 | |
966 | if (vers->vs_rpcb_optnl) { | ||
967 | error = 0; | ||
968 | continue; | ||
969 | } | ||
970 | |||
971 | if (error < 0) { | ||
972 | printk(KERN_WARNING "svc: failed to register " | ||
973 | "%sv%u RPC service (errno %d).\n", | ||
974 | progp->pg_name, i, -error); | ||
967 | break; | 975 | break; |
976 | } | ||
968 | } | 977 | } |
969 | } | 978 | } |
970 | 979 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 2a7ca8ffe83a..817a1e523969 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2964,10 +2964,9 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2964 | 2964 | ||
2965 | /* | 2965 | /* |
2966 | * Once we've associated a backchannel xprt with a connection, | 2966 | * Once we've associated a backchannel xprt with a connection, |
2967 | * we want to keep it around as long as long as the connection | 2967 | * we want to keep it around as long as the connection lasts, |
2968 | * lasts, in case we need to start using it for a backchannel | 2968 | * in case we need to start using it for a backchannel again; |
2969 | * again; this reference won't be dropped until bc_xprt is | 2969 | * this reference won't be dropped until bc_xprt is destroyed. |
2970 | * destroyed. | ||
2971 | */ | 2970 | */ |
2972 | xprt_get(xprt); | 2971 | xprt_get(xprt); |
2973 | args->bc_xprt->xpt_bc_xprt = xprt; | 2972 | args->bc_xprt->xpt_bc_xprt = xprt; |