Commit b064eca2cf6440bf9d5843b24cc4010624031694

Authored by Trond Myklebust
1 parent 3ddeb7c5c6

NFSv4: Send unmapped uid/gids to the server when using auth_sys

The new behaviour is enabled using the new module parameter
'nfs4_disable_idmapping'.

Note that if the server rejects an unmapped uid or gid, then
the client will automatically switch back to using the idmapper.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 5 changed files with 55 additions and 9 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1580,6 +1580,14 @@
1580 1580 of returning the full 64-bit number.
1581 1581 The default is to return 64-bit inode numbers.
1582 1582  
  1583 + nfs.nfs4_disable_idmapping=
  1584 + [NFSv4] When set, this option disables the NFSv4
  1585 + idmapper on the client, but only if the mount
  1586 + is using the 'sec=sys' security flavour. This may
  1587 + make migration from legacy NFSv2/v3 systems easier
  1588 + provided that the server has the appropriate support.
  1589 + The default is to always enable NFSv4 idmapping.
  1590 +
1583 1591 nmi_debug= [KNL,AVR32,SH] Specify one or more actions to take
1584 1592 when a NMI is triggered.
1585 1593 Format: [state][,regs][,debounce][,die]
... ... @@ -82,6 +82,11 @@
82 82 #endif /* CONFIG_NFS_V4 */
83 83  
84 84 /*
  85 + * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
  86 + */
  87 +static int nfs4_disable_idmapping = 0;
  88 +
  89 +/*
85 90 * RPC cruft for NFS
86 91 */
87 92 static struct rpc_version *nfs_version[5] = {
... ... @@ -1567,6 +1572,13 @@
1567 1572 if (error < 0)
1568 1573 goto error;
1569 1574  
  1575 + /*
  1576 + * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
  1577 + * authentication.
  1578 + */
  1579 + if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
  1580 + server->caps |= NFS_CAP_UIDGID_NOMAP;
  1581 +
1570 1582 if (data->rsize)
1571 1583 server->rsize = nfs_block_size(data->rsize, NULL);
1572 1584 if (data->wsize)
... ... @@ -1984,4 +1996,8 @@
1984 1996 }
1985 1997  
1986 1998 #endif /* CONFIG_PROC_FS */
  1999 +
  2000 +module_param(nfs4_disable_idmapping, bool, 0644);
  2001 +MODULE_PARM_DESC(nfs4_disable_idmapping,
  2002 + "Turn off NFSv4 idmapping when using 'sec=sys'");
... ... @@ -61,6 +61,9 @@
61 61  
62 62 #include <linux/slab.h>
63 63 #include <linux/cred.h>
  64 +#include <linux/sunrpc/sched.h>
  65 +#include <linux/nfs4.h>
  66 +#include <linux/nfs_fs_sb.h>
64 67 #include <linux/nfs_idmap.h>
65 68 #include <linux/keyctl.h>
66 69 #include <linux/key-type.h>
67 70  
68 71  
... ... @@ -257,17 +260,20 @@
257 260  
258 261 int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
259 262 {
260   - int ret;
261   - ret = nfs_idmap_lookup_name(uid, "user", buf, buflen);
  263 + int ret = -EINVAL;
  264 +
  265 + if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
  266 + ret = nfs_idmap_lookup_name(uid, "user", buf, buflen);
262 267 if (ret < 0)
263 268 ret = nfs_map_numeric_to_string(uid, buf, buflen);
264 269 return ret;
265 270 }
266 271 int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
267 272 {
268   - int ret;
  273 + int ret = -EINVAL;
269 274  
270   - ret = nfs_idmap_lookup_name(gid, "group", buf, buflen);
  275 + if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
  276 + ret = nfs_idmap_lookup_name(gid, "group", buf, buflen);
271 277 if (ret < 0)
272 278 ret = nfs_map_numeric_to_string(gid, buf, buflen);
273 279 return ret;
274 280  
... ... @@ -750,9 +756,10 @@
750 756 int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
751 757 {
752 758 struct idmap *idmap = server->nfs_client->cl_idmap;
753   - int ret;
  759 + int ret = -EINVAL;
754 760  
755   - ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
  761 + if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
  762 + ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
756 763 if (ret < 0)
757 764 ret = nfs_map_numeric_to_string(uid, buf, buflen);
758 765 return ret;
759 766  
... ... @@ -760,9 +767,10 @@
760 767 int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
761 768 {
762 769 struct idmap *idmap = server->nfs_client->cl_idmap;
763   - int ret;
  770 + int ret = -EINVAL;
764 771  
765   - ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
  772 + if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
  773 + ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
766 774 if (ret < 0)
767 775 ret = nfs_map_numeric_to_string(uid, buf, buflen);
768 776 return ret;
... ... @@ -244,7 +244,7 @@
244 244 /* This is the error handling routine for processes that are allowed
245 245 * to sleep.
246 246 */
247   -static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
  247 +static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
248 248 {
249 249 struct nfs_client *clp = server->nfs_client;
250 250 struct nfs4_state *state = exception->state;
... ... @@ -296,6 +296,19 @@
296 296 break;
297 297 case -NFS4ERR_OLD_STATEID:
298 298 exception->retry = 1;
  299 + break;
  300 + case -NFS4ERR_BADOWNER:
  301 + /* The following works around a Linux server bug! */
  302 + case -NFS4ERR_BADNAME:
  303 + if (server->caps & NFS_CAP_UIDGID_NOMAP) {
  304 + server->caps &= ~NFS_CAP_UIDGID_NOMAP;
  305 + exception->retry = 1;
  306 + printk(KERN_WARNING "NFS: v4 server %s "
  307 + "does not accept raw "
  308 + "uid/gids. "
  309 + "Reenabling the idmapper.\n",
  310 + server->nfs_client->cl_hostname);
  311 + }
299 312 }
300 313 /* We failed to handle the error */
301 314 return nfs4_map_errors(ret);
include/linux/nfs_fs_sb.h
... ... @@ -177,6 +177,7 @@
177 177 #define NFS_CAP_CTIME (1U << 12)
178 178 #define NFS_CAP_MTIME (1U << 13)
179 179 #define NFS_CAP_POSIX_LOCK (1U << 14)
  180 +#define NFS_CAP_UIDGID_NOMAP (1U << 15)
180 181  
181 182  
182 183 /* maximum number of slots to use */