]> git.hungrycats.org Git - linux/commitdiff
NFSv4: Fix a bug which was causing Oopses if the client was
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 16:02:21 +0000 (17:02 +0100)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 16:02:21 +0000 (17:02 +0100)
mounting more than one partition from the same server.

fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_idmap.h

index bd1d1335561cae682af3e2a8b8b38823d15bfc53..1d5d8a9dba1e8c07ade34e91b1c403a89f3bf891 100644 (file)
@@ -88,23 +88,27 @@ static struct rpc_pipe_ops idmap_upcall_ops = {
         .destroy_msg    = idmap_pipe_destroy_msg,
 };
 
-void *
-nfs_idmap_new(struct nfs_server *server)
+void
+nfs_idmap_new(struct nfs4_client *clp)
 {
        struct idmap *idmap;
 
+       if (clp->cl_idmap != NULL)
+               return;
         if ((idmap = kmalloc(sizeof(*idmap), GFP_KERNEL)) == NULL)
-                return (NULL);
+                return;
 
        memset(idmap, 0, sizeof(*idmap));
 
        snprintf(idmap->idmap_path, sizeof(idmap->idmap_path),
-           "%s/idmap", server->client->cl_pathname);
+           "%s/idmap", clp->cl_rpcclient->cl_pathname);
 
         idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
            idmap, &idmap_upcall_ops, 0);
-        if (IS_ERR(idmap->idmap_dentry))
-               goto err_free;
+        if (IS_ERR(idmap->idmap_dentry)) {
+               kfree(idmap);
+               return;
+       }
 
         init_MUTEX(&idmap->idmap_lock);
         init_MUTEX(&idmap->idmap_im_lock);
@@ -112,22 +116,18 @@ nfs_idmap_new(struct nfs_server *server)
        idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER;
        idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP;
 
-       return (idmap);
-
- err_free:
-       kfree(idmap);
-       return (NULL);
+       clp->cl_idmap = idmap;
 }
 
 void
-nfs_idmap_delete(struct nfs_server *server)
+nfs_idmap_delete(struct nfs4_client *clp)
 {
-       struct idmap *idmap = server->idmap;
+       struct idmap *idmap = clp->cl_idmap;
 
        if (!idmap)
                return;
        rpc_unlink(idmap->idmap_path);
-       server->idmap = NULL;
+       clp->cl_idmap = NULL;
        kfree(idmap);
 }
 
@@ -468,29 +468,29 @@ static unsigned int fnvhash32(const void *buf, size_t buflen)
        return (hash);
 }
 
-int nfs_map_name_to_uid(struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_name_to_uid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid)
 {
-       struct idmap *idmap = server->idmap;
+       struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid);
 }
 
-int nfs_map_group_to_gid(struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_group_to_gid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid)
 {
-       struct idmap *idmap = server->idmap;
+       struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
 }
 
-int nfs_map_uid_to_name(struct nfs_server *server, __u32 uid, char *buf)
+int nfs_map_uid_to_name(struct nfs4_client *clp, __u32 uid, char *buf)
 {
-       struct idmap *idmap = server->idmap;
+       struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
 }
-int nfs_map_gid_to_group(struct nfs_server *server, __u32 uid, char *buf)
+int nfs_map_gid_to_group(struct nfs4_client *clp, __u32 uid, char *buf)
 {
-       struct idmap *idmap = server->idmap;
+       struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
 }
index 276f3a10298b5d670e53f0bde6a6761b5b3cc8ca..f23707e5ecb264db626c3cd046f1ec02222327ef 100644 (file)
@@ -158,11 +158,6 @@ nfs_put_super(struct super_block *sb)
 {
        struct nfs_server *server = NFS_SB(sb);
 
-#ifdef CONFIG_NFS_V4
-       if (server->idmap != NULL)
-               nfs_idmap_delete(server);
-#endif /* CONFIG_NFS_V4 */
-
        nfs4_renewd_prepare_shutdown(server);
 
        if (server->client != NULL)
@@ -1494,6 +1489,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                clp->cl_rpcclient = clnt;
                clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
                memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
+               nfs_idmap_new(clp);
        }
        if (list_empty(&clp->cl_superblocks))
                clear_bit(NFS4CLNT_OK, &clp->cl_state);
@@ -1507,6 +1503,10 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                printk(KERN_WARNING "NFS: cannot create RPC client.\n");
                goto out_remove_list;
        }
+       if (server->nfs4_state->cl_idmap == NULL) {
+               printk(KERN_WARNING "NFS: failed to create idmapper.\n");
+               goto out_shutdown;
+       }
 
        clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
        clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
@@ -1525,16 +1525,11 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                goto out_shutdown;
        }
 
-       if ((server->idmap = nfs_idmap_new(server)) == NULL)
-               printk(KERN_WARNING "NFS: couldn't start IDmap\n");
-
        sb->s_op = &nfs4_sops;
        err = nfs_sb_init(sb, authflavour);
        if (err == 0)
                return 0;
        rpciod_down();
-       if (server->idmap != NULL)
-               nfs_idmap_delete(server);
 out_shutdown:
        rpc_shutdown_client(server->client);
 out_remove_list:
index 7a078a42eec3c5408e79bfc89c655f77a7bd4fad..0b391c7f4ce49ab6f7a6a1900070b642d6e09aa5 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/nfs_fs.h>
+#include <linux/nfs_idmap.h>
 #include <linux/workqueue.h>
 
 #define OPENOWNER_POOL_SIZE    8
@@ -124,6 +125,7 @@ nfs4_free_client(struct nfs4_client *clp)
        BUG_ON(!list_empty(&clp->cl_state_owners));
        if (clp->cl_cred)
                put_rpccred(clp->cl_cred);
+       nfs_idmap_delete(clp);
        if (clp->cl_rpcclient)
                rpc_shutdown_client(clp->cl_rpcclient);
        kfree(clp);
index 7a2d241e50e8466e72379cb90c0d997f3ddc8d74..3a372266bb037fe5c7a54ea88accfa7869b263fe 100644 (file)
@@ -328,7 +328,7 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
        if (iap->ia_valid & ATTR_MODE)
                len += 4;
        if (iap->ia_valid & ATTR_UID) {
-               owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name);
+               owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name);
                if (owner_namelen < 0) {
                        printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n",
                               iap->ia_uid);
@@ -340,7 +340,7 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
                len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
        }
        if (iap->ia_valid & ATTR_GID) {
-               owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group);
+               owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group);
                if (owner_grouplen < 0) {
                        printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n",
                               iap->ia_gid);
@@ -1677,7 +1677,7 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
                }
                READ_BUF(dummy32);
                len += (XDR_QUADLEN(dummy32) << 2);
-               if ((status = nfs_map_name_to_uid(server, (char *)p, dummy32,
+               if ((status = nfs_map_name_to_uid(server->nfs4_state, (char *)p, dummy32,
                                                &nfp->uid)) < 0) {
                        dprintk("read_attrs: name-to-uid mapping failed!\n");
                        nfp->uid = -2;
@@ -1694,7 +1694,7 @@ decode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr,
                }
                READ_BUF(dummy32);
                len += (XDR_QUADLEN(dummy32) << 2);
-               if ((status = nfs_map_group_to_gid(server, (char *)p, dummy32,
+               if ((status = nfs_map_group_to_gid(server->nfs4_state, (char *)p, dummy32,
                                                &nfp->gid)) < 0) {
                        dprintk("read_attrs: group-to-gid mapping failed!\n");
                        nfp->gid = -2;
index cfbb7ff1aa8945b172aa8420f75e7678fd2751f7..512d9203905fcc6b1b0d2391f3c2aa0206d6249a 100644 (file)
@@ -438,6 +438,8 @@ extern void * nfs_root_data(void);
 
 #ifdef CONFIG_NFS_V4
 
+struct idmap;
+
 /*
  * In a seqid-mutating op, this macro controls which error return
  * values trigger incrementation of the seqid.
@@ -506,6 +508,9 @@ struct nfs4_client {
        wait_queue_head_t       cl_waitq;
        struct rpc_wait_queue   cl_rpcwaitq;
 
+       /* idmapper */
+       struct idmap *          cl_idmap;
+
        /* Our own IP address, as a null-terminated string.
         * This is used to generate the clientid, and the callback address.
         */
index 5f0b0ce3aa2c0de9bc84c32b2cf2be81ebe6c0be..1b5f7e1305026fef880ab814b6114831b1ee7e66 100644 (file)
@@ -38,7 +38,6 @@ struct nfs_server {
        struct list_head        nfs4_siblings;  /* List of other nfs_server structs
                                                 * that share the same clientid
                                                 */
-       void                   *idmap;
 #endif
 };
 
index c95076e5941b4b9e2ae4cd82c7beb2cf65fb0910..50df56b5a01e09fbfac93a0059593dadff78edcc 100644 (file)
@@ -60,13 +60,13 @@ struct idmap_msg {
 };
 
 #ifdef __KERNEL__
-void      *nfs_idmap_new(struct nfs_server *);
-void       nfs_idmap_delete(struct nfs_server *);
+void nfs_idmap_new(struct nfs4_client *);
+void nfs_idmap_delete(struct nfs4_client *);
 
-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 *);
+int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *);
+int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *);
+int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *);
+int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *);
 #endif /* __KERNEL__ */
 
 #endif /* NFS_IDMAP_H */