Commit b26ef9fe authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Bugfixes and cleanups for the NFSv4 client

name to uid mapper. Includes a fix by Tim Woods to
deal with a caching bug in the case where a user
and a group share the same numerical id and/or name.
parent 066a0e3d
...@@ -52,14 +52,16 @@ ...@@ -52,14 +52,16 @@
#include <linux/nfs_idmap.h> #include <linux/nfs_idmap.h>
#define IDMAP_HASH_SZ 128 #define IDMAP_HASH_SZ 128
#define IDMAP_HASH_TYPE_NAME 0x01
#define IDMAP_HASH_TYPE_ID 0x02
#define IDMAP_HASH_TYPE_INSERT 0x04
struct idmap_hashent { struct idmap_hashent {
uid_t ih_id; __u32 ih_id;
char ih_name[IDMAP_NAMESZ]; int ih_namelen;
u_int32_t ih_namelen; char ih_name[IDMAP_NAMESZ];
};
struct idmap_hashtable {
__u8 h_type;
struct idmap_hashent h_entries[IDMAP_HASH_SZ];
}; };
struct idmap { struct idmap {
...@@ -67,12 +69,10 @@ struct idmap { ...@@ -67,12 +69,10 @@ struct idmap {
struct dentry *idmap_dentry; struct dentry *idmap_dentry;
wait_queue_head_t idmap_wq; wait_queue_head_t idmap_wq;
struct idmap_msg idmap_im; struct idmap_msg idmap_im;
struct nfs_server *idmap_server; struct semaphore idmap_lock; /* Serializes upcalls */
struct semaphore idmap_lock; struct semaphore idmap_im_lock; /* Protects the hashtable */
struct semaphore idmap_im_lock; struct idmap_hashtable idmap_user_hash;
struct semaphore idmap_hash_lock; struct idmap_hashtable idmap_group_hash;
struct idmap_hashent idmap_id_hash[IDMAP_HASH_SZ];
struct idmap_hashent idmap_name_hash[IDMAP_HASH_SZ];
}; };
static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char *, static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char *,
...@@ -80,10 +80,7 @@ static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char *, ...@@ -80,10 +80,7 @@ static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char *,
static ssize_t idmap_pipe_downcall(struct file *, const char *, size_t); static ssize_t idmap_pipe_downcall(struct file *, const char *, size_t);
void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
static int validate_ascii(char *, u_int32_t); static unsigned int fnvhash32(const void *, size_t);
static u_int32_t fnvhash32(void *, u_int32_t);
static int idmap_cache_lookup(struct idmap *, int, char *, u_int32_t *, uid_t *);
static struct rpc_pipe_ops idmap_upcall_ops = { static struct rpc_pipe_ops idmap_upcall_ops = {
.upcall = idmap_pipe_upcall, .upcall = idmap_pipe_upcall,
...@@ -101,20 +98,19 @@ nfs_idmap_new(struct nfs_server *server) ...@@ -101,20 +98,19 @@ nfs_idmap_new(struct nfs_server *server)
memset(idmap, 0, sizeof(*idmap)); memset(idmap, 0, sizeof(*idmap));
idmap->idmap_server = server;
snprintf(idmap->idmap_path, sizeof(idmap->idmap_path), snprintf(idmap->idmap_path, sizeof(idmap->idmap_path),
"%s/idmap", idmap->idmap_server->client->cl_pathname); "%s/idmap", server->client->cl_pathname);
idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
idmap->idmap_server, &idmap_upcall_ops, 0); idmap, &idmap_upcall_ops, 0);
if (IS_ERR(idmap->idmap_dentry)) if (IS_ERR(idmap->idmap_dentry))
goto err_free; goto err_free;
init_MUTEX(&idmap->idmap_lock); init_MUTEX(&idmap->idmap_lock);
init_MUTEX(&idmap->idmap_im_lock); init_MUTEX(&idmap->idmap_im_lock);
init_MUTEX(&idmap->idmap_hash_lock);
init_waitqueue_head(&idmap->idmap_wq); init_waitqueue_head(&idmap->idmap_wq);
idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER;
idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP;
return (idmap); return (idmap);
...@@ -135,35 +131,102 @@ nfs_idmap_delete(struct nfs_server *server) ...@@ -135,35 +131,102 @@ nfs_idmap_delete(struct nfs_server *server)
kfree(idmap); kfree(idmap);
} }
/*
* Helper routines for manipulating the hashtable
*/
static inline struct idmap_hashent *
idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len)
{
return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ];
}
static struct idmap_hashent *
idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
{
struct idmap_hashent *he = idmap_name_hash(h, name, len);
if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0)
return NULL;
return he;
}
static inline struct idmap_hashent *
idmap_id_hash(struct idmap_hashtable* h, __u32 id)
{
return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ];
}
static struct idmap_hashent *
idmap_lookup_id(struct idmap_hashtable *h, __u32 id)
{
struct idmap_hashent *he = idmap_id_hash(h, id);
if (he->ih_id != id || he->ih_namelen == 0)
return NULL;
return he;
}
/*
* Routines for allocating new entries in the hashtable.
* For now, we just have 1 entry per bucket, so it's all
* pretty trivial.
*/
static inline struct idmap_hashent *
idmap_alloc_name(struct idmap_hashtable *h, char *name, unsigned len)
{
return idmap_name_hash(h, name, len);
}
static inline struct idmap_hashent *
idmap_alloc_id(struct idmap_hashtable *h, __u32 id)
{
return idmap_id_hash(h, id);
}
static void
idmap_update_entry(struct idmap_hashent *he, const char *name,
size_t namelen, __u32 id)
{
he->ih_id = id;
memcpy(he->ih_name, name, namelen);
he->ih_name[namelen] = '\0';
he->ih_namelen = namelen;
}
/* /*
* Name -> ID * Name -> ID
*/ */
int static int
nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name, nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
u_int namelen, uid_t *id) const char *name, size_t namelen, __u32 *id)
{ {
struct rpc_pipe_msg msg; struct rpc_pipe_msg msg;
struct idmap *idmap = server->idmap;
struct idmap_msg *im; struct idmap_msg *im;
struct idmap_hashent *he;
DECLARE_WAITQUEUE(wq, current); DECLARE_WAITQUEUE(wq, current);
int ret = -1, hashtype = IDMAP_HASH_TYPE_NAME; int ret = -EIO;
u_int xnamelen = namelen;
if (idmap == NULL)
return (-1);
im = &idmap->idmap_im; im = &idmap->idmap_im;
if (namelen > IDMAP_NAMESZ || namelen == 0) /*
return (-1); * String sanity checks
* Note that the userland daemon expects NUL terminated strings
*/
for (;;) {
if (namelen == 0)
return -EINVAL;
if (name[namelen-1] != '\0')
break;
namelen--;
}
if (namelen >= IDMAP_NAMESZ)
return -EINVAL;
down(&idmap->idmap_lock); down(&idmap->idmap_lock);
down(&idmap->idmap_im_lock); down(&idmap->idmap_im_lock);
if (name[xnamelen - 1] == '\0') he = idmap_lookup_name(h, name, namelen);
xnamelen--; if (he != NULL) {
*id = he->ih_id;
if (idmap_cache_lookup(idmap, hashtype, name, &xnamelen, id) == 0) {
ret = 0; ret = 0;
goto out; goto out;
} }
...@@ -171,7 +234,7 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name, ...@@ -171,7 +234,7 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name,
memset(im, 0, sizeof(*im)); memset(im, 0, sizeof(*im));
memcpy(im->im_name, name, namelen); memcpy(im->im_name, name, namelen);
im->im_type = type; im->im_type = h->h_type;
im->im_conv = IDMAP_CONV_NAMETOID; im->im_conv = IDMAP_CONV_NAMETOID;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
...@@ -191,16 +254,9 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name, ...@@ -191,16 +254,9 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name,
remove_wait_queue(&idmap->idmap_wq, &wq); remove_wait_queue(&idmap->idmap_wq, &wq);
down(&idmap->idmap_im_lock); down(&idmap->idmap_im_lock);
/*
* XXX Race condition here, with testing for status. Go ahead
* and and do the cace lookup anyway.
*/
if (im->im_status & IDMAP_STATUS_SUCCESS) { if (im->im_status & IDMAP_STATUS_SUCCESS) {
ret = 0;
*id = im->im_id; *id = im->im_id;
ret = 0;
hashtype |= IDMAP_HASH_TYPE_INSERT;
ret = idmap_cache_lookup(idmap, hashtype, name, &xnamelen, id);
} }
out: out:
...@@ -213,35 +269,31 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name, ...@@ -213,35 +269,31 @@ nfs_idmap_id(struct nfs_server *server, u_int8_t type, char *name,
/* /*
* ID -> Name * ID -> Name
*/ */
int static int
nfs_idmap_name(struct nfs_server *server, u_int8_t type, uid_t id, nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
char *name, u_int *namelen) __u32 id, char *name)
{ {
struct rpc_pipe_msg msg; struct rpc_pipe_msg msg;
struct idmap *idmap = server->idmap;
struct idmap_msg *im; struct idmap_msg *im;
struct idmap_hashent *he;
DECLARE_WAITQUEUE(wq, current); DECLARE_WAITQUEUE(wq, current);
int ret = -1, hashtype = IDMAP_HASH_TYPE_ID; int ret = -EIO;
u_int len; unsigned int len;
if (idmap == NULL)
return (-1);
im = &idmap->idmap_im; im = &idmap->idmap_im;
if (*namelen < IDMAP_NAMESZ || *namelen == 0)
return (-1);
down(&idmap->idmap_lock); down(&idmap->idmap_lock);
down(&idmap->idmap_im_lock); down(&idmap->idmap_im_lock);
if (idmap_cache_lookup(idmap, hashtype, name, namelen, &id) == 0) { he = idmap_lookup_id(h, id);
ret = 0; if (he != 0) {
memcpy(name, he->ih_name, he->ih_namelen);
ret = he->ih_namelen;
goto out; goto out;
} }
memset(im, 0, sizeof(*im)); memset(im, 0, sizeof(*im));
im->im_type = type; im->im_type = h->h_type;
im->im_conv = IDMAP_CONV_IDTONAME; im->im_conv = IDMAP_CONV_IDTONAME;
im->im_id = id; im->im_id = id;
...@@ -256,9 +308,6 @@ nfs_idmap_name(struct nfs_server *server, u_int8_t type, uid_t id, ...@@ -256,9 +308,6 @@ nfs_idmap_name(struct nfs_server *server, u_int8_t type, uid_t id,
goto out; goto out;
} }
/*
* XXX add timeouts here
*/
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
up(&idmap->idmap_im_lock); up(&idmap->idmap_im_lock);
schedule(); schedule();
...@@ -267,23 +316,20 @@ nfs_idmap_name(struct nfs_server *server, u_int8_t type, uid_t id, ...@@ -267,23 +316,20 @@ nfs_idmap_name(struct nfs_server *server, u_int8_t type, uid_t id,
down(&idmap->idmap_im_lock); down(&idmap->idmap_im_lock);
if (im->im_status & IDMAP_STATUS_SUCCESS) { if (im->im_status & IDMAP_STATUS_SUCCESS) {
if ((len = validate_ascii(im->im_name, IDMAP_NAMESZ)) == -1) if ((len = strnlen(im->im_name, IDMAP_NAMESZ)) == 0)
goto out; goto out;
ret = 0;
memcpy(name, im->im_name, len); memcpy(name, im->im_name, len);
*namelen = len; ret = len;
hashtype |= IDMAP_HASH_TYPE_INSERT;
ret = idmap_cache_lookup(idmap, hashtype, name, namelen, &id);
} }
out: out:
memset(im, 0, sizeof(*im)); memset(im, 0, sizeof(*im));
up(&idmap->idmap_im_lock); up(&idmap->idmap_im_lock);
up(&idmap->idmap_lock); up(&idmap->idmap_lock);
return (ret); return ret;
} }
/* RPC pipefs upcall/downcall routines */
static ssize_t static ssize_t
idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
char *dst, size_t buflen) char *dst, size_t buflen)
...@@ -310,10 +356,12 @@ static ssize_t ...@@ -310,10 +356,12 @@ static ssize_t
idmap_pipe_downcall(struct file *filp, const char *src, size_t mlen) idmap_pipe_downcall(struct file *filp, const char *src, size_t mlen)
{ {
struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode); struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
struct nfs_server *server = rpci->private; struct idmap *idmap = (struct idmap *)rpci->private;
struct idmap *idmap = server->idmap;
struct idmap_msg im_in, *im = &idmap->idmap_im; struct idmap_msg im_in, *im = &idmap->idmap_im;
int match = 0, hashtype, badmsg = 0, namelen_in, namelen; struct idmap_hashtable *h;
struct idmap_hashent *he = NULL;
int namelen_in;
int ret;
if (mlen != sizeof(im_in)) if (mlen != sizeof(im_in))
return (-ENOSPC); return (-ENOSPC);
...@@ -323,39 +371,66 @@ idmap_pipe_downcall(struct file *filp, const char *src, size_t mlen) ...@@ -323,39 +371,66 @@ idmap_pipe_downcall(struct file *filp, const char *src, size_t mlen)
down(&idmap->idmap_im_lock); down(&idmap->idmap_im_lock);
namelen_in = validate_ascii(im_in.im_name, IDMAP_NAMESZ); ret = mlen;
namelen = validate_ascii(im->im_name, IDMAP_NAMESZ); im->im_status = im_in.im_status;
/* If we got an error, terminate now, and wake up pending upcalls */
if (!(im_in.im_status & IDMAP_STATUS_SUCCESS)) {
wake_up(&idmap->idmap_wq);
goto out;
}
/* Sanity checking of strings */
ret = -EINVAL;
namelen_in = strnlen(im_in.im_name, IDMAP_NAMESZ);
if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ)
goto out;
badmsg = !(im_in.im_status & IDMAP_STATUS_SUCCESS) || namelen_in <= 0; switch (im_in.im_type) {
case IDMAP_TYPE_USER:
h = &idmap->idmap_user_hash;
break;
case IDMAP_TYPE_GROUP:
h = &idmap->idmap_group_hash;
break;
default:
goto out;
}
switch (im_in.im_conv) { switch (im_in.im_conv) {
case IDMAP_CONV_IDTONAME: case IDMAP_CONV_IDTONAME:
match = im->im_id == im_in.im_id; /* Did we match the current upcall? */
if (im->im_conv == IDMAP_CONV_IDTONAME
&& im->im_type == im_in.im_type
&& im->im_id == im_in.im_id) {
/* Yes: copy string, including the terminating '\0' */
memcpy(im->im_name, im_in.im_name, namelen_in);
im->im_name[namelen_in] = '\0';
wake_up(&idmap->idmap_wq);
}
he = idmap_alloc_id(h, im_in.im_id);
break; break;
case IDMAP_CONV_NAMETOID: case IDMAP_CONV_NAMETOID:
match = namelen == namelen_in && /* Did we match the current upcall? */
memcmp(im->im_name, im_in.im_name, namelen) == 0; if (im->im_conv == IDMAP_CONV_NAMETOID
&& im->im_type == im_in.im_type
&& strnlen(im->im_name, IDMAP_NAMESZ) == namelen_in
&& memcmp(im->im_name, im_in.im_name, namelen_in) == 0) {
im->im_id = im_in.im_id;
wake_up(&idmap->idmap_wq);
}
he = idmap_alloc_name(h, im_in.im_name, namelen_in);
break; break;
default: default:
badmsg = 1; goto out;
break;
}
match = match && im->im_type == im_in.im_type;
if (match) {
memcpy(im, &im_in, sizeof(*im));
wake_up(&idmap->idmap_wq);
} else if (!badmsg) {
hashtype = im_in.im_conv == IDMAP_CONV_IDTONAME ?
IDMAP_HASH_TYPE_ID : IDMAP_HASH_TYPE_NAME;
hashtype |= IDMAP_HASH_TYPE_INSERT;
idmap_cache_lookup(idmap, hashtype, im_in.im_name, &namelen_in,
&im_in.im_id);
} }
/* If the entry is valid, also copy it to the cache */
if (he != NULL)
idmap_update_entry(he, im_in.im_name, namelen_in, im_in.im_id);
ret = mlen;
out:
up(&idmap->idmap_im_lock); up(&idmap->idmap_im_lock);
return (mlen); return ret;
} }
void void
...@@ -372,108 +447,51 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) ...@@ -372,108 +447,51 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
up(&idmap->idmap_im_lock); up(&idmap->idmap_im_lock);
} }
static int
validate_ascii(char *string, u_int32_t len)
{
int i;
for (i = 0; i < len; i++) {
if (string[i] == '\0')
break;
if (string[i] & 0x80)
return (-1);
}
if (string[i] != '\0')
return (-1);
return (i);
}
/* /*
* Fowler/Noll/Vo hash * Fowler/Noll/Vo hash
* http://www.isthe.com/chongo/tech/comp/fnv/ * http://www.isthe.com/chongo/tech/comp/fnv/
*/ */
#define FNV_P_32 ((u_int32_t)0x01000193) /* 16777619 */ #define FNV_P_32 ((unsigned int)0x01000193) /* 16777619 */
#define FNV_1_32 ((u_int32_t)0x811c9dc5) /* 2166136261 */ #define FNV_1_32 ((unsigned int)0x811c9dc5) /* 2166136261 */
static u_int32_t static unsigned int fnvhash32(const void *buf, size_t buflen)
fnvhash32(void *buf, u_int32_t buflen)
{ {
u_char *p, *end = (u_char *)buf + buflen; const unsigned char *p, *end = (const unsigned char *)buf + buflen;
u_int32_t hash = FNV_1_32; unsigned int hash = FNV_1_32;
for (p = buf; p < end; p++) { for (p = buf; p < end; p++) {
hash *= FNV_P_32; hash *= FNV_P_32;
hash ^= (u_int32_t)*p; hash ^= (unsigned int)*p;
} }
return (hash); return (hash);
} }
/* int nfs_map_name_to_uid(struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
* ->ih_namelen == 0 indicates negative entry
*/
static int
idmap_cache_lookup(struct idmap *idmap, int type, char *name, u_int32_t *namelen,
uid_t *id)
{ {
u_int32_t hash; struct idmap *idmap = server->idmap;
struct idmap_hashent *he = NULL;
int insert = type & IDMAP_HASH_TYPE_INSERT;
int ret = -1;
/*
* XXX technically, this is not needed, since we will always
* hold idmap_im_lock when altering the hash tables. but
* semantically that just hurts.
*
* XXX cache negative responses
*/
down(&idmap->idmap_hash_lock);
if (*namelen > IDMAP_NAMESZ || *namelen == 0) return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid);
goto out; }
if (type & IDMAP_HASH_TYPE_NAME) { int nfs_map_group_to_gid(struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
hash = fnvhash32(name, *namelen) % IDMAP_HASH_SZ; {
he = &idmap->idmap_name_hash[hash]; struct idmap *idmap = server->idmap;
/*
* Testing he->ih_namelen == *namelen implicitly tests
* namelen != 0, and thus a non-negative entry.
*/
if (!insert && he->ih_namelen == *namelen &&
memcmp(he->ih_name, name, *namelen) == 0) {
*id = he->ih_id;
ret = 0;
goto out;
}
}
if (type & IDMAP_HASH_TYPE_ID) { return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
hash = fnvhash32(id, sizeof(*id)) % IDMAP_HASH_SZ; }
he = &idmap->idmap_id_hash[hash];
if (!insert && *id == he->ih_id && he->ih_namelen != 0 && int nfs_map_uid_to_name(struct nfs_server *server, __u32 uid, char *buf)
*namelen >= he->ih_namelen) { {
memcpy(name, he->ih_name, he->ih_namelen); struct idmap *idmap = server->idmap;
*namelen = he->ih_namelen;
ret = 0;
goto out;
}
}
if (insert && he != NULL) { return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
he->ih_id = *id; }
memcpy(he->ih_name, name, *namelen); int nfs_map_gid_to_group(struct nfs_server *server, __u32 uid, char *buf)
he->ih_namelen = *namelen; {
ret = 0; struct idmap *idmap = server->idmap;
}
out: return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
up(&idmap->idmap_hash_lock);
return (ret);
} }
...@@ -239,10 +239,10 @@ static int ...@@ -239,10 +239,10 @@ static int
encode_attrs(struct xdr_stream *xdr, struct iattr *iap, encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
struct nfs_server *server) struct nfs_server *server)
{ {
char owner_name[256]; char owner_name[IDMAP_NAMESZ];
char owner_group[256]; char owner_group[IDMAP_NAMESZ];
int owner_namelen = sizeof(owner_name); int owner_namelen = 0;
int owner_grouplen = sizeof(owner_group); int owner_grouplen = 0;
uint32_t *p; uint32_t *p;
uint32_t *q; uint32_t *q;
int len; int len;
...@@ -265,9 +265,8 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap, ...@@ -265,9 +265,8 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
if (iap->ia_valid & ATTR_MODE) if (iap->ia_valid & ATTR_MODE)
len += 4; len += 4;
if (iap->ia_valid & ATTR_UID) { if (iap->ia_valid & ATTR_UID) {
status = nfs_idmap_name(server, IDMAP_TYPE_USER, owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name);
iap->ia_uid, owner_name, &owner_namelen); if (owner_namelen < 0) {
if (status < 0) {
printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n",
iap->ia_uid); iap->ia_uid);
/* XXX */ /* XXX */
...@@ -278,9 +277,8 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap, ...@@ -278,9 +277,8 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
len += 4 + (XDR_QUADLEN(owner_namelen) << 2); len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
} }
if (iap->ia_valid & ATTR_GID) { if (iap->ia_valid & ATTR_GID) {
status = nfs_idmap_name(server, IDMAP_TYPE_GROUP, owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group);
iap->ia_gid, owner_group, &owner_grouplen); if (owner_grouplen < 0) {
if (status < 0) {
printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n",
iap->ia_gid); iap->ia_gid);
strcpy(owner_group, "nobody"); strcpy(owner_group, "nobody");
...@@ -1475,10 +1473,9 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr, ...@@ -1475,10 +1473,9 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
} }
READ_BUF(dummy32); READ_BUF(dummy32);
len += (XDR_QUADLEN(dummy32) << 2); len += (XDR_QUADLEN(dummy32) << 2);
if ((status = nfs_idmap_id(server, IDMAP_TYPE_USER, if ((status = nfs_map_name_to_uid(server, (char *)p, dummy32,
(char *)p, dummy32, &nfp->uid)) == -1) { &nfp->uid)) < 0) {
dprintk("read_attrs: gss_get_num failed!\n"); dprintk("read_attrs: name-to-uid mapping failed!\n");
/* goto out; */
nfp->uid = -2; nfp->uid = -2;
} }
dprintk("read_attrs: uid=%d\n", (int)nfp->uid); dprintk("read_attrs: uid=%d\n", (int)nfp->uid);
...@@ -1493,11 +1490,10 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr, ...@@ -1493,11 +1490,10 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
} }
READ_BUF(dummy32); READ_BUF(dummy32);
len += (XDR_QUADLEN(dummy32) << 2); len += (XDR_QUADLEN(dummy32) << 2);
if ((status = nfs_idmap_id(server, IDMAP_TYPE_GROUP, if ((status = nfs_map_group_to_gid(server, (char *)p, dummy32,
(char *)p, dummy32, &nfp->gid)) == -1) { &nfp->gid)) < 0) {
dprintk("read_attrs: gss_get_num failed!\n"); dprintk("read_attrs: group-to-gid mapping failed!\n");
nfp->gid = -2; nfp->gid = -2;
/* goto out; */
} }
dprintk("read_attrs: gid=%d\n", (int)nfp->gid); dprintk("read_attrs: gid=%d\n", (int)nfp->gid);
} }
......
...@@ -52,18 +52,21 @@ ...@@ -52,18 +52,21 @@
#define IDMAP_STATUS_SUCCESS 0x08 #define IDMAP_STATUS_SUCCESS 0x08
struct idmap_msg { struct idmap_msg {
u_int8_t im_type; __u8 im_type;
u_int8_t im_conv; __u8 im_conv;
char im_name[IDMAP_NAMESZ]; char im_name[IDMAP_NAMESZ];
u_int32_t im_id; __u32 im_id;
u_int8_t im_status; __u8 im_status;
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
void *nfs_idmap_new(struct nfs_server *); void *nfs_idmap_new(struct nfs_server *);
void nfs_idmap_delete(struct nfs_server *); void nfs_idmap_delete(struct nfs_server *);
int nfs_idmap_id(struct nfs_server *, u_int8_t, char *, u_int, uid_t *);
int nfs_idmap_name(struct nfs_server *, u_int8_t, uid_t, char *, u_int *); int nfs_map_name_to_uid(struct nfs_server *, const char *, size_t, __u32 *);
int nfs_map_group_to_gid(struct nfs_server *, const char *, size_t, __u32 *);
int nfs_map_uid_to_name(struct nfs_server *, __u32, char *);
int nfs_map_gid_to_group(struct nfs_server *, __u32, char *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* NFS_IDMAP_H */ #endif /* NFS_IDMAP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment