NFS: DNS resolver cache per network namespace context introduced
[deliverable/linux.git] / fs / nfs / inode.c
index 50a15fa8cf985e41e21b786f4f6d9d9ed96cf37e..0335f6e4ff7e3f545bec561bd00c46139dd06f2e 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/nfs_xdr.h>
 #include <linux/slab.h>
 #include <linux/compat.h>
+#include <linux/freezer.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include "fscache.h"
 #include "dns_resolve.h"
 #include "pnfs.h"
+#include "netns.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
 #define NFS_64_BIT_INODE_NUMBERS_ENABLED       1
 
 /* Default is to see 64-bit inode numbers */
-static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;
+static bool enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;
 
 static void nfs_invalidate_inode(struct inode *);
 static int nfs_update_inode(struct inode *, struct nfs_fattr *);
@@ -77,7 +79,7 @@ int nfs_wait_bit_killable(void *word)
 {
        if (fatal_signal_pending(current))
                return -ERESTARTSYS;
-       schedule();
+       freezable_schedule();
        return 0;
 }
 
@@ -629,23 +631,28 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
        nfs_revalidate_inode(server, inode);
 }
 
-struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred, fmode_t f_mode)
+struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode)
 {
        struct nfs_open_context *ctx;
+       struct rpc_cred *cred = rpc_lookup_cred();
+       if (IS_ERR(cred))
+               return ERR_CAST(cred);
 
        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-       if (ctx != NULL) {
-               nfs_sb_active(dentry->d_sb);
-               ctx->dentry = dget(dentry);
-               ctx->cred = get_rpccred(cred);
-               ctx->state = NULL;
-               ctx->mode = f_mode;
-               ctx->flags = 0;
-               ctx->error = 0;
-               nfs_init_lock_context(&ctx->lock_context);
-               ctx->lock_context.open_context = ctx;
-               INIT_LIST_HEAD(&ctx->list);
+       if (!ctx) {
+               put_rpccred(cred);
+               return ERR_PTR(-ENOMEM);
        }
+       nfs_sb_active(dentry->d_sb);
+       ctx->dentry = dget(dentry);
+       ctx->cred = cred;
+       ctx->state = NULL;
+       ctx->mode = f_mode;
+       ctx->flags = 0;
+       ctx->error = 0;
+       nfs_init_lock_context(&ctx->lock_context);
+       ctx->lock_context.open_context = ctx;
+       INIT_LIST_HEAD(&ctx->list);
        return ctx;
 }
 
@@ -738,15 +745,10 @@ static void nfs_file_clear_open_context(struct file *filp)
 int nfs_open(struct inode *inode, struct file *filp)
 {
        struct nfs_open_context *ctx;
-       struct rpc_cred *cred;
 
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(filp->f_path.dentry, cred, filp->f_mode);
-       put_rpccred(cred);
-       if (ctx == NULL)
-               return -ENOMEM;
+       ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
        nfs_file_set_open_context(filp, ctx);
        put_nfs_open_context(ctx);
        nfs_fscache_set_inode_cookie(inode, filp);
@@ -1019,6 +1021,8 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
        fattr->valid = 0;
        fattr->time_start = jiffies;
        fattr->gencount = nfs_inc_attr_generation_counter();
+       fattr->owner_name = NULL;
+       fattr->group_name = NULL;
 }
 
 struct nfs_fattr *nfs_alloc_fattr(void)
@@ -1464,7 +1468,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
 static void nfs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(nfs_inode_cachep, NFS_I(inode));
 }
 
@@ -1550,6 +1553,25 @@ static void nfsiod_stop(void)
        destroy_workqueue(wq);
 }
 
+int nfs_net_id;
+
+static int nfs_net_init(struct net *net)
+{
+       return nfs_dns_resolver_cache_init(net);
+}
+
+static void nfs_net_exit(struct net *net)
+{
+       nfs_dns_resolver_cache_destroy(net);
+}
+
+static struct pernet_operations nfs_net_ops = {
+       .init = nfs_net_init,
+       .exit = nfs_net_exit,
+       .id   = &nfs_net_id,
+       .size = sizeof(struct nfs_net),
+};
+
 /*
  * Initialize NFS
  */
@@ -1559,9 +1581,13 @@ static int __init init_nfs_fs(void)
 
        err = nfs_idmap_init();
        if (err < 0)
-               goto out9;
+               goto out10;
 
        err = nfs_dns_resolver_init();
+       if (err < 0)
+               goto out9;
+
+       err = register_pernet_subsys(&nfs_net_ops);
        if (err < 0)
                goto out8;
 
@@ -1623,10 +1649,12 @@ out5:
 out6:
        nfs_fscache_unregister();
 out7:
-       nfs_dns_resolver_destroy();
+       unregister_pernet_subsys(&nfs_net_ops);
 out8:
-       nfs_idmap_quit();
+       nfs_dns_resolver_destroy();
 out9:
+       nfs_idmap_quit();
+out10:
        return err;
 }
 
@@ -1638,6 +1666,7 @@ static void __exit exit_nfs_fs(void)
        nfs_destroy_inodecache();
        nfs_destroy_nfspagecache();
        nfs_fscache_unregister();
+       unregister_pernet_subsys(&nfs_net_ops);
        nfs_dns_resolver_destroy();
        nfs_idmap_quit();
 #ifdef CONFIG_PROC_FS
This page took 0.032407 seconds and 5 git commands to generate.