diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 11:53:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 11:53:47 -0400 |
commit | f63d395d47f37a4fe771e6d4b1db9d2cdae5ffc5 (patch) | |
tree | 3448a14ae965802adb963762cadeb9989ce4caa2 /fs/nfs/idmap.c | |
parent | 643ac9fc5429e85b8b7f534544b80bcc4f34c367 (diff) | |
parent | 5a7c9eec9fde1da0e3adf0a4ddb64ff2a324a492 (diff) |
Merge tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates for Linux 3.4 from Trond Myklebust:
"New features include:
- Add NFS client support for containers.
This should enable most of the necessary functionality, including
lockd support, and support for rpc.statd, NFSv4 idmapper and
RPCSEC_GSS upcalls into the correct network namespace from which
the mount system call was issued.
- NFSv4 idmapper scalability improvements
Base the idmapper cache on the keyring interface to allow
concurrent access to idmapper entries. Start the process of
migrating users from the single-threaded daemon-based approach to
the multi-threaded request-key based approach.
- NFSv4.1 implementation id.
Allows the NFSv4.1 client and server to mutually identify each
other for logging and debugging purposes.
- Support the 'vers=4.1' mount option for mounting NFSv4.1 instead of
having to use the more counterintuitive 'vers=4,minorversion=1'.
- SUNRPC tracepoints.
Start the process of adding tracepoints in order to improve
debugging of the RPC layer.
- pNFS object layout support for autologin.
Important bugfixes include:
- Fix a bug in rpc_wake_up/rpc_wake_up_status that caused them to
fail to wake up all tasks when applied to priority waitqueues.
- Ensure that we handle read delegations correctly, when we try to
truncate a file.
- A number of fixes for NFSv4 state manager loops (mostly to do with
delegation recovery)."
* tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (224 commits)
NFS: fix sb->s_id in nfs debug prints
xprtrdma: Remove assumption that each segment is <= PAGE_SIZE
xprtrdma: The transport should not bug-check when a dup reply is received
pnfs-obj: autologin: Add support for protocol autologin
NFS: Remove nfs4_setup_sequence from generic rename code
NFS: Remove nfs4_setup_sequence from generic unlink code
NFS: Remove nfs4_setup_sequence from generic read code
NFS: Remove nfs4_setup_sequence from generic write code
NFS: Fix more NFS debug related build warnings
SUNRPC/LOCKD: Fix build warnings when CONFIG_SUNRPC_DEBUG is undefined
nfs: non void functions must return a value
SUNRPC: Kill compiler warning when RPC_DEBUG is unset
SUNRPC/NFS: Add Kbuild dependencies for NFS_DEBUG/RPC_DEBUG
NFS: Use cond_resched_lock() to reduce latencies in the commit scans
NFSv4: It is not safe to dereference lsp->ls_state in release_lockowner
NFS: ncommit count is being double decremented
SUNRPC: We must not use list_for_each_entry_safe() in rpc_wake_up()
Try using machine credentials for RENEW calls
NFSv4.1: Fix a few issues in filelayout_commit_pagelist
NFSv4.1: Clean ups and bugfixes for the pNFS read/writeback/commit code
...
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r-- | fs/nfs/idmap.c | 733 |
1 files changed, 344 insertions, 389 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index a1bbf7780dfc..b7f348bb618b 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -34,11 +34,29 @@ | |||
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/string.h> | 37 | #include <linux/parser.h> |
38 | #include <linux/kernel.h> | 38 | #include <linux/fs.h> |
39 | #include <linux/slab.h> | ||
40 | #include <linux/nfs_idmap.h> | 39 | #include <linux/nfs_idmap.h> |
40 | #include <net/net_namespace.h> | ||
41 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
41 | #include <linux/nfs_fs.h> | 42 | #include <linux/nfs_fs.h> |
43 | #include <linux/nfs_fs_sb.h> | ||
44 | #include <linux/key.h> | ||
45 | #include <linux/keyctl.h> | ||
46 | #include <linux/key-type.h> | ||
47 | #include <keys/user-type.h> | ||
48 | #include <linux/module.h> | ||
49 | |||
50 | #include "internal.h" | ||
51 | #include "netns.h" | ||
52 | |||
53 | #define NFS_UINT_MAXLEN 11 | ||
54 | |||
55 | /* Default cache timeout is 10 minutes */ | ||
56 | unsigned int nfs_idmap_cache_timeout = 600; | ||
57 | static const struct cred *id_resolver_cache; | ||
58 | static struct key_type key_type_id_resolver_legacy; | ||
59 | |||
42 | 60 | ||
43 | /** | 61 | /** |
44 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields | 62 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields |
@@ -142,24 +160,7 @@ static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen) | |||
142 | return snprintf(buf, buflen, "%u", id); | 160 | return snprintf(buf, buflen, "%u", id); |
143 | } | 161 | } |
144 | 162 | ||
145 | #ifdef CONFIG_NFS_USE_NEW_IDMAPPER | 163 | static struct key_type key_type_id_resolver = { |
146 | |||
147 | #include <linux/cred.h> | ||
148 | #include <linux/sunrpc/sched.h> | ||
149 | #include <linux/nfs4.h> | ||
150 | #include <linux/nfs_fs_sb.h> | ||
151 | #include <linux/keyctl.h> | ||
152 | #include <linux/key-type.h> | ||
153 | #include <linux/rcupdate.h> | ||
154 | #include <linux/err.h> | ||
155 | |||
156 | #include <keys/user-type.h> | ||
157 | |||
158 | #define NFS_UINT_MAXLEN 11 | ||
159 | |||
160 | const struct cred *id_resolver_cache; | ||
161 | |||
162 | struct key_type key_type_id_resolver = { | ||
163 | .name = "id_resolver", | 164 | .name = "id_resolver", |
164 | .instantiate = user_instantiate, | 165 | .instantiate = user_instantiate, |
165 | .match = user_match, | 166 | .match = user_match, |
@@ -169,13 +170,14 @@ struct key_type key_type_id_resolver = { | |||
169 | .read = user_read, | 170 | .read = user_read, |
170 | }; | 171 | }; |
171 | 172 | ||
172 | int nfs_idmap_init(void) | 173 | static int nfs_idmap_init_keyring(void) |
173 | { | 174 | { |
174 | struct cred *cred; | 175 | struct cred *cred; |
175 | struct key *keyring; | 176 | struct key *keyring; |
176 | int ret = 0; | 177 | int ret = 0; |
177 | 178 | ||
178 | printk(KERN_NOTICE "Registering the %s key type\n", key_type_id_resolver.name); | 179 | printk(KERN_NOTICE "NFS: Registering the %s key type\n", |
180 | key_type_id_resolver.name); | ||
179 | 181 | ||
180 | cred = prepare_kernel_cred(NULL); | 182 | cred = prepare_kernel_cred(NULL); |
181 | if (!cred) | 183 | if (!cred) |
@@ -211,7 +213,7 @@ failed_put_cred: | |||
211 | return ret; | 213 | return ret; |
212 | } | 214 | } |
213 | 215 | ||
214 | void nfs_idmap_quit(void) | 216 | static void nfs_idmap_quit_keyring(void) |
215 | { | 217 | { |
216 | key_revoke(id_resolver_cache->thread_keyring); | 218 | key_revoke(id_resolver_cache->thread_keyring); |
217 | unregister_key_type(&key_type_id_resolver); | 219 | unregister_key_type(&key_type_id_resolver); |
@@ -246,8 +248,10 @@ static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen, | |||
246 | return desclen; | 248 | return desclen; |
247 | } | 249 | } |
248 | 250 | ||
249 | static ssize_t nfs_idmap_request_key(const char *name, size_t namelen, | 251 | static ssize_t nfs_idmap_request_key(struct key_type *key_type, |
250 | const char *type, void *data, size_t data_size) | 252 | const char *name, size_t namelen, |
253 | const char *type, void *data, | ||
254 | size_t data_size, struct idmap *idmap) | ||
251 | { | 255 | { |
252 | const struct cred *saved_cred; | 256 | const struct cred *saved_cred; |
253 | struct key *rkey; | 257 | struct key *rkey; |
@@ -260,8 +264,12 @@ static ssize_t nfs_idmap_request_key(const char *name, size_t namelen, | |||
260 | goto out; | 264 | goto out; |
261 | 265 | ||
262 | saved_cred = override_creds(id_resolver_cache); | 266 | saved_cred = override_creds(id_resolver_cache); |
263 | rkey = request_key(&key_type_id_resolver, desc, ""); | 267 | if (idmap) |
268 | rkey = request_key_with_auxdata(key_type, desc, "", 0, idmap); | ||
269 | else | ||
270 | rkey = request_key(&key_type_id_resolver, desc, ""); | ||
264 | revert_creds(saved_cred); | 271 | revert_creds(saved_cred); |
272 | |||
265 | kfree(desc); | 273 | kfree(desc); |
266 | if (IS_ERR(rkey)) { | 274 | if (IS_ERR(rkey)) { |
267 | ret = PTR_ERR(rkey); | 275 | ret = PTR_ERR(rkey); |
@@ -294,31 +302,46 @@ out: | |||
294 | return ret; | 302 | return ret; |
295 | } | 303 | } |
296 | 304 | ||
305 | static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | ||
306 | const char *type, void *data, | ||
307 | size_t data_size, struct idmap *idmap) | ||
308 | { | ||
309 | ssize_t ret = nfs_idmap_request_key(&key_type_id_resolver, | ||
310 | name, namelen, type, data, | ||
311 | data_size, NULL); | ||
312 | if (ret < 0) { | ||
313 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | ||
314 | name, namelen, type, data, | ||
315 | data_size, idmap); | ||
316 | } | ||
317 | return ret; | ||
318 | } | ||
297 | 319 | ||
298 | /* ID -> Name */ | 320 | /* ID -> Name */ |
299 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, size_t buflen) | 321 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, |
322 | size_t buflen, struct idmap *idmap) | ||
300 | { | 323 | { |
301 | char id_str[NFS_UINT_MAXLEN]; | 324 | char id_str[NFS_UINT_MAXLEN]; |
302 | int id_len; | 325 | int id_len; |
303 | ssize_t ret; | 326 | ssize_t ret; |
304 | 327 | ||
305 | id_len = snprintf(id_str, sizeof(id_str), "%u", id); | 328 | id_len = snprintf(id_str, sizeof(id_str), "%u", id); |
306 | ret = nfs_idmap_request_key(id_str, id_len, type, buf, buflen); | 329 | ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap); |
307 | if (ret < 0) | 330 | if (ret < 0) |
308 | return -EINVAL; | 331 | return -EINVAL; |
309 | return ret; | 332 | return ret; |
310 | } | 333 | } |
311 | 334 | ||
312 | /* Name -> ID */ | 335 | /* Name -> ID */ |
313 | static int nfs_idmap_lookup_id(const char *name, size_t namelen, | 336 | static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *type, |
314 | const char *type, __u32 *id) | 337 | __u32 *id, struct idmap *idmap) |
315 | { | 338 | { |
316 | char id_str[NFS_UINT_MAXLEN]; | 339 | char id_str[NFS_UINT_MAXLEN]; |
317 | long id_long; | 340 | long id_long; |
318 | ssize_t data_size; | 341 | ssize_t data_size; |
319 | int ret = 0; | 342 | int ret = 0; |
320 | 343 | ||
321 | data_size = nfs_idmap_request_key(name, namelen, type, id_str, NFS_UINT_MAXLEN); | 344 | data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap); |
322 | if (data_size <= 0) { | 345 | if (data_size <= 0) { |
323 | ret = -EINVAL; | 346 | ret = -EINVAL; |
324 | } else { | 347 | } else { |
@@ -328,114 +351,103 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, | |||
328 | return ret; | 351 | return ret; |
329 | } | 352 | } |
330 | 353 | ||
331 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 354 | /* idmap classic begins here */ |
332 | { | 355 | module_param(nfs_idmap_cache_timeout, int, 0644); |
333 | if (nfs_map_string_to_numeric(name, namelen, uid)) | ||
334 | return 0; | ||
335 | return nfs_idmap_lookup_id(name, namelen, "uid", uid); | ||
336 | } | ||
337 | |||
338 | int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid) | ||
339 | { | ||
340 | if (nfs_map_string_to_numeric(name, namelen, gid)) | ||
341 | return 0; | ||
342 | return nfs_idmap_lookup_id(name, namelen, "gid", gid); | ||
343 | } | ||
344 | |||
345 | int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) | ||
346 | { | ||
347 | int ret = -EINVAL; | ||
348 | |||
349 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | ||
350 | ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); | ||
351 | if (ret < 0) | ||
352 | ret = nfs_map_numeric_to_string(uid, buf, buflen); | ||
353 | return ret; | ||
354 | } | ||
355 | int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen) | ||
356 | { | ||
357 | int ret = -EINVAL; | ||
358 | 356 | ||
359 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | 357 | struct idmap { |
360 | ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); | 358 | struct rpc_pipe *idmap_pipe; |
361 | if (ret < 0) | 359 | struct key_construction *idmap_key_cons; |
362 | ret = nfs_map_numeric_to_string(gid, buf, buflen); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | #else /* CONFIG_NFS_USE_NEW_IDMAPPER not defined */ | ||
367 | |||
368 | #include <linux/module.h> | ||
369 | #include <linux/mutex.h> | ||
370 | #include <linux/init.h> | ||
371 | #include <linux/socket.h> | ||
372 | #include <linux/in.h> | ||
373 | #include <linux/sched.h> | ||
374 | #include <linux/sunrpc/clnt.h> | ||
375 | #include <linux/workqueue.h> | ||
376 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
377 | |||
378 | #include <linux/nfs_fs.h> | ||
379 | |||
380 | #include "nfs4_fs.h" | ||
381 | |||
382 | #define IDMAP_HASH_SZ 128 | ||
383 | |||
384 | /* Default cache timeout is 10 minutes */ | ||
385 | unsigned int nfs_idmap_cache_timeout = 600 * HZ; | ||
386 | |||
387 | static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) | ||
388 | { | ||
389 | char *endp; | ||
390 | int num = simple_strtol(val, &endp, 0); | ||
391 | int jif = num * HZ; | ||
392 | if (endp == val || *endp || num < 0 || jif < num) | ||
393 | return -EINVAL; | ||
394 | *((int *)kp->arg) = jif; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, | ||
399 | &nfs_idmap_cache_timeout, 0644); | ||
400 | |||
401 | struct idmap_hashent { | ||
402 | unsigned long ih_expires; | ||
403 | __u32 ih_id; | ||
404 | size_t ih_namelen; | ||
405 | char ih_name[IDMAP_NAMESZ]; | ||
406 | }; | 360 | }; |
407 | 361 | ||
408 | struct idmap_hashtable { | 362 | enum { |
409 | __u8 h_type; | 363 | Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err |
410 | struct idmap_hashent h_entries[IDMAP_HASH_SZ]; | ||
411 | }; | 364 | }; |
412 | 365 | ||
413 | struct idmap { | 366 | static const match_table_t nfs_idmap_tokens = { |
414 | struct dentry *idmap_dentry; | 367 | { Opt_find_uid, "uid:%s" }, |
415 | wait_queue_head_t idmap_wq; | 368 | { Opt_find_gid, "gid:%s" }, |
416 | struct idmap_msg idmap_im; | 369 | { Opt_find_user, "user:%s" }, |
417 | struct mutex idmap_lock; /* Serializes upcalls */ | 370 | { Opt_find_group, "group:%s" }, |
418 | struct mutex idmap_im_lock; /* Protects the hashtable */ | 371 | { Opt_find_err, NULL } |
419 | struct idmap_hashtable idmap_user_hash; | ||
420 | struct idmap_hashtable idmap_group_hash; | ||
421 | }; | 372 | }; |
422 | 373 | ||
374 | static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); | ||
423 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, | 375 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, |
424 | size_t); | 376 | size_t); |
425 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | 377 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); |
426 | 378 | ||
427 | static unsigned int fnvhash32(const void *, size_t); | ||
428 | |||
429 | static const struct rpc_pipe_ops idmap_upcall_ops = { | 379 | static const struct rpc_pipe_ops idmap_upcall_ops = { |
430 | .upcall = rpc_pipe_generic_upcall, | 380 | .upcall = rpc_pipe_generic_upcall, |
431 | .downcall = idmap_pipe_downcall, | 381 | .downcall = idmap_pipe_downcall, |
432 | .destroy_msg = idmap_pipe_destroy_msg, | 382 | .destroy_msg = idmap_pipe_destroy_msg, |
433 | }; | 383 | }; |
434 | 384 | ||
385 | static struct key_type key_type_id_resolver_legacy = { | ||
386 | .name = "id_resolver", | ||
387 | .instantiate = user_instantiate, | ||
388 | .match = user_match, | ||
389 | .revoke = user_revoke, | ||
390 | .destroy = user_destroy, | ||
391 | .describe = user_describe, | ||
392 | .read = user_read, | ||
393 | .request_key = nfs_idmap_legacy_upcall, | ||
394 | }; | ||
395 | |||
396 | static void __nfs_idmap_unregister(struct rpc_pipe *pipe) | ||
397 | { | ||
398 | if (pipe->dentry) | ||
399 | rpc_unlink(pipe->dentry); | ||
400 | } | ||
401 | |||
402 | static int __nfs_idmap_register(struct dentry *dir, | ||
403 | struct idmap *idmap, | ||
404 | struct rpc_pipe *pipe) | ||
405 | { | ||
406 | struct dentry *dentry; | ||
407 | |||
408 | dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe); | ||
409 | if (IS_ERR(dentry)) | ||
410 | return PTR_ERR(dentry); | ||
411 | pipe->dentry = dentry; | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void nfs_idmap_unregister(struct nfs_client *clp, | ||
416 | struct rpc_pipe *pipe) | ||
417 | { | ||
418 | struct net *net = clp->net; | ||
419 | struct super_block *pipefs_sb; | ||
420 | |||
421 | pipefs_sb = rpc_get_sb_net(net); | ||
422 | if (pipefs_sb) { | ||
423 | __nfs_idmap_unregister(pipe); | ||
424 | rpc_put_sb_net(net); | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static int nfs_idmap_register(struct nfs_client *clp, | ||
429 | struct idmap *idmap, | ||
430 | struct rpc_pipe *pipe) | ||
431 | { | ||
432 | struct net *net = clp->net; | ||
433 | struct super_block *pipefs_sb; | ||
434 | int err = 0; | ||
435 | |||
436 | pipefs_sb = rpc_get_sb_net(net); | ||
437 | if (pipefs_sb) { | ||
438 | if (clp->cl_rpcclient->cl_dentry) | ||
439 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, | ||
440 | idmap, pipe); | ||
441 | rpc_put_sb_net(net); | ||
442 | } | ||
443 | return err; | ||
444 | } | ||
445 | |||
435 | int | 446 | int |
436 | nfs_idmap_new(struct nfs_client *clp) | 447 | nfs_idmap_new(struct nfs_client *clp) |
437 | { | 448 | { |
438 | struct idmap *idmap; | 449 | struct idmap *idmap; |
450 | struct rpc_pipe *pipe; | ||
439 | int error; | 451 | int error; |
440 | 452 | ||
441 | BUG_ON(clp->cl_idmap != NULL); | 453 | BUG_ON(clp->cl_idmap != NULL); |
@@ -444,19 +456,19 @@ nfs_idmap_new(struct nfs_client *clp) | |||
444 | if (idmap == NULL) | 456 | if (idmap == NULL) |
445 | return -ENOMEM; | 457 | return -ENOMEM; |
446 | 458 | ||
447 | idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_path.dentry, | 459 | pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0); |
448 | "idmap", idmap, &idmap_upcall_ops, 0); | 460 | if (IS_ERR(pipe)) { |
449 | if (IS_ERR(idmap->idmap_dentry)) { | 461 | error = PTR_ERR(pipe); |
450 | error = PTR_ERR(idmap->idmap_dentry); | ||
451 | kfree(idmap); | 462 | kfree(idmap); |
452 | return error; | 463 | return error; |
453 | } | 464 | } |
454 | 465 | error = nfs_idmap_register(clp, idmap, pipe); | |
455 | mutex_init(&idmap->idmap_lock); | 466 | if (error) { |
456 | mutex_init(&idmap->idmap_im_lock); | 467 | rpc_destroy_pipe_data(pipe); |
457 | init_waitqueue_head(&idmap->idmap_wq); | 468 | kfree(idmap); |
458 | idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER; | 469 | return error; |
459 | idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; | 470 | } |
471 | idmap->idmap_pipe = pipe; | ||
460 | 472 | ||
461 | clp->cl_idmap = idmap; | 473 | clp->cl_idmap = idmap; |
462 | return 0; | 474 | return 0; |
@@ -469,211 +481,220 @@ nfs_idmap_delete(struct nfs_client *clp) | |||
469 | 481 | ||
470 | if (!idmap) | 482 | if (!idmap) |
471 | return; | 483 | return; |
472 | rpc_unlink(idmap->idmap_dentry); | 484 | nfs_idmap_unregister(clp, idmap->idmap_pipe); |
485 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
473 | clp->cl_idmap = NULL; | 486 | clp->cl_idmap = NULL; |
474 | kfree(idmap); | 487 | kfree(idmap); |
475 | } | 488 | } |
476 | 489 | ||
477 | /* | 490 | static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event, |
478 | * Helper routines for manipulating the hashtable | 491 | struct super_block *sb) |
479 | */ | ||
480 | static inline struct idmap_hashent * | ||
481 | idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) | ||
482 | { | ||
483 | return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; | ||
484 | } | ||
485 | |||
486 | static struct idmap_hashent * | ||
487 | idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len) | ||
488 | { | 492 | { |
489 | struct idmap_hashent *he = idmap_name_hash(h, name, len); | 493 | int err = 0; |
490 | 494 | ||
491 | if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) | 495 | switch (event) { |
492 | return NULL; | 496 | case RPC_PIPEFS_MOUNT: |
493 | if (time_after(jiffies, he->ih_expires)) | 497 | BUG_ON(clp->cl_rpcclient->cl_dentry == NULL); |
494 | return NULL; | 498 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, |
495 | return he; | 499 | clp->cl_idmap, |
500 | clp->cl_idmap->idmap_pipe); | ||
501 | break; | ||
502 | case RPC_PIPEFS_UMOUNT: | ||
503 | if (clp->cl_idmap->idmap_pipe) { | ||
504 | struct dentry *parent; | ||
505 | |||
506 | parent = clp->cl_idmap->idmap_pipe->dentry->d_parent; | ||
507 | __nfs_idmap_unregister(clp->cl_idmap->idmap_pipe); | ||
508 | /* | ||
509 | * Note: This is a dirty hack. SUNRPC hook has been | ||
510 | * called already but simple_rmdir() call for the | ||
511 | * directory returned with error because of idmap pipe | ||
512 | * inside. Thus now we have to remove this directory | ||
513 | * here. | ||
514 | */ | ||
515 | if (rpc_rmdir(parent)) | ||
516 | printk(KERN_ERR "NFS: %s: failed to remove " | ||
517 | "clnt dir!\n", __func__); | ||
518 | } | ||
519 | break; | ||
520 | default: | ||
521 | printk(KERN_ERR "NFS: %s: unknown event: %ld\n", __func__, | ||
522 | event); | ||
523 | return -ENOTSUPP; | ||
524 | } | ||
525 | return err; | ||
526 | } | ||
527 | |||
528 | static struct nfs_client *nfs_get_client_for_event(struct net *net, int event) | ||
529 | { | ||
530 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
531 | struct dentry *cl_dentry; | ||
532 | struct nfs_client *clp; | ||
533 | |||
534 | spin_lock(&nn->nfs_client_lock); | ||
535 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | ||
536 | if (clp->rpc_ops != &nfs_v4_clientops) | ||
537 | continue; | ||
538 | cl_dentry = clp->cl_idmap->idmap_pipe->dentry; | ||
539 | if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) || | ||
540 | ((event == RPC_PIPEFS_UMOUNT) && !cl_dentry)) | ||
541 | continue; | ||
542 | atomic_inc(&clp->cl_count); | ||
543 | spin_unlock(&nn->nfs_client_lock); | ||
544 | return clp; | ||
545 | } | ||
546 | spin_unlock(&nn->nfs_client_lock); | ||
547 | return NULL; | ||
496 | } | 548 | } |
497 | 549 | ||
498 | static inline struct idmap_hashent * | 550 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, |
499 | idmap_id_hash(struct idmap_hashtable* h, __u32 id) | 551 | void *ptr) |
500 | { | 552 | { |
501 | return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; | 553 | struct super_block *sb = ptr; |
502 | } | 554 | struct nfs_client *clp; |
555 | int error = 0; | ||
503 | 556 | ||
504 | static struct idmap_hashent * | 557 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { |
505 | idmap_lookup_id(struct idmap_hashtable *h, __u32 id) | 558 | error = __rpc_pipefs_event(clp, event, sb); |
506 | { | 559 | nfs_put_client(clp); |
507 | struct idmap_hashent *he = idmap_id_hash(h, id); | 560 | if (error) |
508 | if (he->ih_id != id || he->ih_namelen == 0) | 561 | break; |
509 | return NULL; | 562 | } |
510 | if (time_after(jiffies, he->ih_expires)) | 563 | return error; |
511 | return NULL; | ||
512 | return he; | ||
513 | } | 564 | } |
514 | 565 | ||
515 | /* | 566 | #define PIPEFS_NFS_PRIO 1 |
516 | * Routines for allocating new entries in the hashtable. | 567 | |
517 | * For now, we just have 1 entry per bucket, so it's all | 568 | static struct notifier_block nfs_idmap_block = { |
518 | * pretty trivial. | 569 | .notifier_call = rpc_pipefs_event, |
519 | */ | 570 | .priority = SUNRPC_PIPEFS_NFS_PRIO, |
520 | static inline struct idmap_hashent * | 571 | }; |
521 | idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) | ||
522 | { | ||
523 | return idmap_name_hash(h, name, len); | ||
524 | } | ||
525 | 572 | ||
526 | static inline struct idmap_hashent * | 573 | int nfs_idmap_init(void) |
527 | idmap_alloc_id(struct idmap_hashtable *h, __u32 id) | ||
528 | { | 574 | { |
529 | return idmap_id_hash(h, id); | 575 | int ret; |
576 | ret = nfs_idmap_init_keyring(); | ||
577 | if (ret != 0) | ||
578 | goto out; | ||
579 | ret = rpc_pipefs_notifier_register(&nfs_idmap_block); | ||
580 | if (ret != 0) | ||
581 | nfs_idmap_quit_keyring(); | ||
582 | out: | ||
583 | return ret; | ||
530 | } | 584 | } |
531 | 585 | ||
532 | static void | 586 | void nfs_idmap_quit(void) |
533 | idmap_update_entry(struct idmap_hashent *he, const char *name, | ||
534 | size_t namelen, __u32 id) | ||
535 | { | 587 | { |
536 | he->ih_id = id; | 588 | rpc_pipefs_notifier_unregister(&nfs_idmap_block); |
537 | memcpy(he->ih_name, name, namelen); | 589 | nfs_idmap_quit_keyring(); |
538 | he->ih_name[namelen] = '\0'; | ||
539 | he->ih_namelen = namelen; | ||
540 | he->ih_expires = jiffies + nfs_idmap_cache_timeout; | ||
541 | } | 590 | } |
542 | 591 | ||
543 | /* | 592 | static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, |
544 | * Name -> ID | 593 | struct rpc_pipe_msg *msg) |
545 | */ | ||
546 | static int | ||
547 | nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h, | ||
548 | const char *name, size_t namelen, __u32 *id) | ||
549 | { | 594 | { |
550 | struct rpc_pipe_msg msg; | 595 | substring_t substr; |
551 | struct idmap_msg *im; | 596 | int token, ret; |
552 | struct idmap_hashent *he; | ||
553 | DECLARE_WAITQUEUE(wq, current); | ||
554 | int ret = -EIO; | ||
555 | |||
556 | im = &idmap->idmap_im; | ||
557 | |||
558 | /* | ||
559 | * String sanity checks | ||
560 | * Note that the userland daemon expects NUL terminated strings | ||
561 | */ | ||
562 | for (;;) { | ||
563 | if (namelen == 0) | ||
564 | return -EINVAL; | ||
565 | if (name[namelen-1] != '\0') | ||
566 | break; | ||
567 | namelen--; | ||
568 | } | ||
569 | if (namelen >= IDMAP_NAMESZ) | ||
570 | return -EINVAL; | ||
571 | 597 | ||
572 | mutex_lock(&idmap->idmap_lock); | 598 | memset(im, 0, sizeof(*im)); |
573 | mutex_lock(&idmap->idmap_im_lock); | 599 | memset(msg, 0, sizeof(*msg)); |
574 | |||
575 | he = idmap_lookup_name(h, name, namelen); | ||
576 | if (he != NULL) { | ||
577 | *id = he->ih_id; | ||
578 | ret = 0; | ||
579 | goto out; | ||
580 | } | ||
581 | 600 | ||
582 | memset(im, 0, sizeof(*im)); | 601 | im->im_type = IDMAP_TYPE_GROUP; |
583 | memcpy(im->im_name, name, namelen); | 602 | token = match_token(desc, nfs_idmap_tokens, &substr); |
584 | 603 | ||
585 | im->im_type = h->h_type; | 604 | switch (token) { |
586 | im->im_conv = IDMAP_CONV_NAMETOID; | 605 | case Opt_find_uid: |
606 | im->im_type = IDMAP_TYPE_USER; | ||
607 | case Opt_find_gid: | ||
608 | im->im_conv = IDMAP_CONV_NAMETOID; | ||
609 | ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ); | ||
610 | break; | ||
587 | 611 | ||
588 | memset(&msg, 0, sizeof(msg)); | 612 | case Opt_find_user: |
589 | msg.data = im; | 613 | im->im_type = IDMAP_TYPE_USER; |
590 | msg.len = sizeof(*im); | 614 | case Opt_find_group: |
615 | im->im_conv = IDMAP_CONV_IDTONAME; | ||
616 | ret = match_int(&substr, &im->im_id); | ||
617 | break; | ||
591 | 618 | ||
592 | add_wait_queue(&idmap->idmap_wq, &wq); | 619 | default: |
593 | if (rpc_queue_upcall(idmap->idmap_dentry->d_inode, &msg) < 0) { | 620 | ret = -EINVAL; |
594 | remove_wait_queue(&idmap->idmap_wq, &wq); | ||
595 | goto out; | 621 | goto out; |
596 | } | 622 | } |
597 | 623 | ||
598 | set_current_state(TASK_UNINTERRUPTIBLE); | 624 | msg->data = im; |
599 | mutex_unlock(&idmap->idmap_im_lock); | 625 | msg->len = sizeof(struct idmap_msg); |
600 | schedule(); | ||
601 | __set_current_state(TASK_RUNNING); | ||
602 | remove_wait_queue(&idmap->idmap_wq, &wq); | ||
603 | mutex_lock(&idmap->idmap_im_lock); | ||
604 | 626 | ||
605 | if (im->im_status & IDMAP_STATUS_SUCCESS) { | 627 | out: |
606 | *id = im->im_id; | ||
607 | ret = 0; | ||
608 | } | ||
609 | |||
610 | out: | ||
611 | memset(im, 0, sizeof(*im)); | ||
612 | mutex_unlock(&idmap->idmap_im_lock); | ||
613 | mutex_unlock(&idmap->idmap_lock); | ||
614 | return ret; | 628 | return ret; |
615 | } | 629 | } |
616 | 630 | ||
617 | /* | 631 | static int nfs_idmap_legacy_upcall(struct key_construction *cons, |
618 | * ID -> Name | 632 | const char *op, |
619 | */ | 633 | void *aux) |
620 | static int | ||
621 | nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h, | ||
622 | __u32 id, char *name) | ||
623 | { | 634 | { |
624 | struct rpc_pipe_msg msg; | 635 | struct rpc_pipe_msg *msg; |
625 | struct idmap_msg *im; | 636 | struct idmap_msg *im; |
626 | struct idmap_hashent *he; | 637 | struct idmap *idmap = (struct idmap *)aux; |
627 | DECLARE_WAITQUEUE(wq, current); | 638 | struct key *key = cons->key; |
628 | int ret = -EIO; | 639 | int ret; |
629 | unsigned int len; | ||
630 | |||
631 | im = &idmap->idmap_im; | ||
632 | 640 | ||
633 | mutex_lock(&idmap->idmap_lock); | 641 | /* msg and im are freed in idmap_pipe_destroy_msg */ |
634 | mutex_lock(&idmap->idmap_im_lock); | 642 | msg = kmalloc(sizeof(*msg), GFP_KERNEL); |
643 | if (IS_ERR(msg)) { | ||
644 | ret = PTR_ERR(msg); | ||
645 | goto out0; | ||
646 | } | ||
635 | 647 | ||
636 | he = idmap_lookup_id(h, id); | 648 | im = kmalloc(sizeof(*im), GFP_KERNEL); |
637 | if (he) { | 649 | if (IS_ERR(im)) { |
638 | memcpy(name, he->ih_name, he->ih_namelen); | 650 | ret = PTR_ERR(im); |
639 | ret = he->ih_namelen; | 651 | goto out1; |
640 | goto out; | ||
641 | } | 652 | } |
642 | 653 | ||
643 | memset(im, 0, sizeof(*im)); | 654 | ret = nfs_idmap_prepare_message(key->description, im, msg); |
644 | im->im_type = h->h_type; | 655 | if (ret < 0) |
645 | im->im_conv = IDMAP_CONV_IDTONAME; | 656 | goto out2; |
646 | im->im_id = id; | ||
647 | 657 | ||
648 | memset(&msg, 0, sizeof(msg)); | 658 | idmap->idmap_key_cons = cons; |
649 | msg.data = im; | ||
650 | msg.len = sizeof(*im); | ||
651 | 659 | ||
652 | add_wait_queue(&idmap->idmap_wq, &wq); | 660 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); |
661 | if (ret < 0) | ||
662 | goto out2; | ||
653 | 663 | ||
654 | if (rpc_queue_upcall(idmap->idmap_dentry->d_inode, &msg) < 0) { | 664 | return ret; |
655 | remove_wait_queue(&idmap->idmap_wq, &wq); | 665 | |
656 | goto out; | 666 | out2: |
657 | } | 667 | kfree(im); |
668 | out1: | ||
669 | kfree(msg); | ||
670 | out0: | ||
671 | key_revoke(cons->key); | ||
672 | key_revoke(cons->authkey); | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data) | ||
677 | { | ||
678 | return key_instantiate_and_link(key, data, strlen(data) + 1, | ||
679 | id_resolver_cache->thread_keyring, | ||
680 | authkey); | ||
681 | } | ||
658 | 682 | ||
659 | set_current_state(TASK_UNINTERRUPTIBLE); | 683 | static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey) |
660 | mutex_unlock(&idmap->idmap_im_lock); | 684 | { |
661 | schedule(); | 685 | char id_str[NFS_UINT_MAXLEN]; |
662 | __set_current_state(TASK_RUNNING); | 686 | int ret = -EINVAL; |
663 | remove_wait_queue(&idmap->idmap_wq, &wq); | 687 | |
664 | mutex_lock(&idmap->idmap_im_lock); | 688 | switch (im->im_conv) { |
665 | 689 | case IDMAP_CONV_NAMETOID: | |
666 | if (im->im_status & IDMAP_STATUS_SUCCESS) { | 690 | sprintf(id_str, "%d", im->im_id); |
667 | if ((len = strnlen(im->im_name, IDMAP_NAMESZ)) == 0) | 691 | ret = nfs_idmap_instantiate(key, authkey, id_str); |
668 | goto out; | 692 | break; |
669 | memcpy(name, im->im_name, len); | 693 | case IDMAP_CONV_IDTONAME: |
670 | ret = len; | 694 | ret = nfs_idmap_instantiate(key, authkey, im->im_name); |
695 | break; | ||
671 | } | 696 | } |
672 | 697 | ||
673 | out: | ||
674 | memset(im, 0, sizeof(*im)); | ||
675 | mutex_unlock(&idmap->idmap_im_lock); | ||
676 | mutex_unlock(&idmap->idmap_lock); | ||
677 | return ret; | 698 | return ret; |
678 | } | 699 | } |
679 | 700 | ||
@@ -682,115 +703,51 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
682 | { | 703 | { |
683 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); | 704 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); |
684 | struct idmap *idmap = (struct idmap *)rpci->private; | 705 | struct idmap *idmap = (struct idmap *)rpci->private; |
685 | struct idmap_msg im_in, *im = &idmap->idmap_im; | 706 | struct key_construction *cons = idmap->idmap_key_cons; |
686 | struct idmap_hashtable *h; | 707 | struct idmap_msg im; |
687 | struct idmap_hashent *he = NULL; | ||
688 | size_t namelen_in; | 708 | size_t namelen_in; |
689 | int ret; | 709 | int ret; |
690 | 710 | ||
691 | if (mlen != sizeof(im_in)) | 711 | if (mlen != sizeof(im)) { |
692 | return -ENOSPC; | 712 | ret = -ENOSPC; |
693 | |||
694 | if (copy_from_user(&im_in, src, mlen) != 0) | ||
695 | return -EFAULT; | ||
696 | |||
697 | mutex_lock(&idmap->idmap_im_lock); | ||
698 | |||
699 | ret = mlen; | ||
700 | im->im_status = im_in.im_status; | ||
701 | /* If we got an error, terminate now, and wake up pending upcalls */ | ||
702 | if (!(im_in.im_status & IDMAP_STATUS_SUCCESS)) { | ||
703 | wake_up(&idmap->idmap_wq); | ||
704 | goto out; | 713 | goto out; |
705 | } | 714 | } |
706 | 715 | ||
707 | /* Sanity checking of strings */ | 716 | if (copy_from_user(&im, src, mlen) != 0) { |
708 | ret = -EINVAL; | 717 | ret = -EFAULT; |
709 | namelen_in = strnlen(im_in.im_name, IDMAP_NAMESZ); | ||
710 | if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) | ||
711 | goto out; | 718 | goto out; |
719 | } | ||
712 | 720 | ||
713 | switch (im_in.im_type) { | 721 | if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { |
714 | case IDMAP_TYPE_USER: | 722 | ret = mlen; |
715 | h = &idmap->idmap_user_hash; | 723 | complete_request_key(idmap->idmap_key_cons, -ENOKEY); |
716 | break; | 724 | goto out_incomplete; |
717 | case IDMAP_TYPE_GROUP: | ||
718 | h = &idmap->idmap_group_hash; | ||
719 | break; | ||
720 | default: | ||
721 | goto out; | ||
722 | } | 725 | } |
723 | 726 | ||
724 | switch (im_in.im_conv) { | 727 | namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); |
725 | case IDMAP_CONV_IDTONAME: | 728 | if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) { |
726 | /* Did we match the current upcall? */ | 729 | ret = -EINVAL; |
727 | if (im->im_conv == IDMAP_CONV_IDTONAME | ||
728 | && im->im_type == im_in.im_type | ||
729 | && im->im_id == im_in.im_id) { | ||
730 | /* Yes: copy string, including the terminating '\0' */ | ||
731 | memcpy(im->im_name, im_in.im_name, namelen_in); | ||
732 | im->im_name[namelen_in] = '\0'; | ||
733 | wake_up(&idmap->idmap_wq); | ||
734 | } | ||
735 | he = idmap_alloc_id(h, im_in.im_id); | ||
736 | break; | ||
737 | case IDMAP_CONV_NAMETOID: | ||
738 | /* Did we match the current upcall? */ | ||
739 | if (im->im_conv == IDMAP_CONV_NAMETOID | ||
740 | && im->im_type == im_in.im_type | ||
741 | && strnlen(im->im_name, IDMAP_NAMESZ) == namelen_in | ||
742 | && memcmp(im->im_name, im_in.im_name, namelen_in) == 0) { | ||
743 | im->im_id = im_in.im_id; | ||
744 | wake_up(&idmap->idmap_wq); | ||
745 | } | ||
746 | he = idmap_alloc_name(h, im_in.im_name, namelen_in); | ||
747 | break; | ||
748 | default: | ||
749 | goto out; | 730 | goto out; |
750 | } | 731 | } |
751 | 732 | ||
752 | /* If the entry is valid, also copy it to the cache */ | 733 | ret = nfs_idmap_read_message(&im, cons->key, cons->authkey); |
753 | if (he != NULL) | 734 | if (ret >= 0) { |
754 | idmap_update_entry(he, im_in.im_name, namelen_in, im_in.im_id); | 735 | key_set_timeout(cons->key, nfs_idmap_cache_timeout); |
755 | ret = mlen; | 736 | ret = mlen; |
737 | } | ||
738 | |||
756 | out: | 739 | out: |
757 | mutex_unlock(&idmap->idmap_im_lock); | 740 | complete_request_key(idmap->idmap_key_cons, ret); |
741 | out_incomplete: | ||
758 | return ret; | 742 | return ret; |
759 | } | 743 | } |
760 | 744 | ||
761 | static void | 745 | static void |
762 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) | 746 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) |
763 | { | 747 | { |
764 | struct idmap_msg *im = msg->data; | 748 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ |
765 | struct idmap *idmap = container_of(im, struct idmap, idmap_im); | 749 | kfree(msg->data); |
766 | 750 | kfree(msg); | |
767 | if (msg->errno >= 0) | ||
768 | return; | ||
769 | mutex_lock(&idmap->idmap_im_lock); | ||
770 | im->im_status = IDMAP_STATUS_LOOKUPFAIL; | ||
771 | wake_up(&idmap->idmap_wq); | ||
772 | mutex_unlock(&idmap->idmap_im_lock); | ||
773 | } | ||
774 | |||
775 | /* | ||
776 | * Fowler/Noll/Vo hash | ||
777 | * http://www.isthe.com/chongo/tech/comp/fnv/ | ||
778 | */ | ||
779 | |||
780 | #define FNV_P_32 ((unsigned int)0x01000193) /* 16777619 */ | ||
781 | #define FNV_1_32 ((unsigned int)0x811c9dc5) /* 2166136261 */ | ||
782 | |||
783 | static unsigned int fnvhash32(const void *buf, size_t buflen) | ||
784 | { | ||
785 | const unsigned char *p, *end = (const unsigned char *)buf + buflen; | ||
786 | unsigned int hash = FNV_1_32; | ||
787 | |||
788 | for (p = buf; p < end; p++) { | ||
789 | hash *= FNV_P_32; | ||
790 | hash ^= (unsigned int)*p; | ||
791 | } | ||
792 | |||
793 | return hash; | ||
794 | } | 751 | } |
795 | 752 | ||
796 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 753 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) |
@@ -799,16 +756,16 @@ int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_ | |||
799 | 756 | ||
800 | if (nfs_map_string_to_numeric(name, namelen, uid)) | 757 | if (nfs_map_string_to_numeric(name, namelen, uid)) |
801 | return 0; | 758 | return 0; |
802 | return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); | 759 | return nfs_idmap_lookup_id(name, namelen, "uid", uid, idmap); |
803 | } | 760 | } |
804 | 761 | ||
805 | int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 762 | int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid) |
806 | { | 763 | { |
807 | struct idmap *idmap = server->nfs_client->cl_idmap; | 764 | struct idmap *idmap = server->nfs_client->cl_idmap; |
808 | 765 | ||
809 | if (nfs_map_string_to_numeric(name, namelen, uid)) | 766 | if (nfs_map_string_to_numeric(name, namelen, gid)) |
810 | return 0; | 767 | return 0; |
811 | return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); | 768 | return nfs_idmap_lookup_id(name, namelen, "gid", gid, idmap); |
812 | } | 769 | } |
813 | 770 | ||
814 | int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) | 771 | int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) |
@@ -817,21 +774,19 @@ int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, s | |||
817 | int ret = -EINVAL; | 774 | int ret = -EINVAL; |
818 | 775 | ||
819 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | 776 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) |
820 | ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); | 777 | ret = nfs_idmap_lookup_name(uid, "user", buf, buflen, idmap); |
821 | if (ret < 0) | 778 | if (ret < 0) |
822 | ret = nfs_map_numeric_to_string(uid, buf, buflen); | 779 | ret = nfs_map_numeric_to_string(uid, buf, buflen); |
823 | return ret; | 780 | return ret; |
824 | } | 781 | } |
825 | int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) | 782 | int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen) |
826 | { | 783 | { |
827 | struct idmap *idmap = server->nfs_client->cl_idmap; | 784 | struct idmap *idmap = server->nfs_client->cl_idmap; |
828 | int ret = -EINVAL; | 785 | int ret = -EINVAL; |
829 | 786 | ||
830 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | 787 | if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) |
831 | ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); | 788 | ret = nfs_idmap_lookup_name(gid, "group", buf, buflen, idmap); |
832 | if (ret < 0) | 789 | if (ret < 0) |
833 | ret = nfs_map_numeric_to_string(uid, buf, buflen); | 790 | ret = nfs_map_numeric_to_string(gid, buf, buflen); |
834 | return ret; | 791 | return ret; |
835 | } | 792 | } |
836 | |||
837 | #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ | ||