Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[firefly-linux-kernel-4.4.55.git] / fs / nfs / client.c
index 1d09289c8f0e370dd3f45a17a7c077246b23d7da..1c5ff6d5838585c4b6b0806aa64b579e58a64bc0 100644 (file)
@@ -110,8 +110,8 @@ struct nfs_subversion *get_nfs_version(unsigned int version)
                mutex_unlock(&nfs_version_mutex);
        }
 
-       if (!IS_ERR(nfs))
-               try_module_get(nfs->owner);
+       if (!IS_ERR(nfs) && !try_module_get(nfs->owner))
+               return ERR_PTR(-EAGAIN);
        return nfs;
 }
 
@@ -158,7 +158,8 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
                goto error_0;
 
        clp->cl_nfs_mod = cl_init->nfs_mod;
-       try_module_get(clp->cl_nfs_mod->owner);
+       if (!try_module_get(clp->cl_nfs_mod->owner))
+               goto error_dealloc;
 
        clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
 
@@ -190,6 +191,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 
 error_cleanup:
        put_nfs_version(clp->cl_nfs_mod);
+error_dealloc:
        kfree(clp);
 error_0:
        return ERR_PTR(err);
@@ -252,6 +254,7 @@ void nfs_free_client(struct nfs_client *clp)
        put_net(clp->cl_net);
        put_nfs_version(clp->cl_nfs_mod);
        kfree(clp->cl_hostname);
+       kfree(clp->cl_acceptor);
        kfree(clp);
 
        dprintk("<-- nfs_free_client()\n");
@@ -482,8 +485,13 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
        struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
        const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
 
+       if (cl_init->hostname == NULL) {
+               WARN_ON(1);
+               return NULL;
+       }
+
        dprintk("--> nfs_get_client(%s,v%u)\n",
-               cl_init->hostname ?: "", rpc_ops->version);
+               cl_init->hostname, rpc_ops->version);
 
        /* see if the client already exists */
        do {
@@ -510,7 +518,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
        } while (!IS_ERR(new));
 
        dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
-               cl_init->hostname ?: "", PTR_ERR(new));
+               cl_init->hostname, PTR_ERR(new));
        return new;
 }
 EXPORT_SYMBOL_GPL(nfs_get_client);
@@ -1205,7 +1213,7 @@ static const struct file_operations nfs_server_list_fops = {
        .open           = nfs_server_list_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_net,
        .owner          = THIS_MODULE,
 };
 
@@ -1226,7 +1234,7 @@ static const struct file_operations nfs_volume_list_fops = {
        .open           = nfs_volume_list_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_net,
        .owner          = THIS_MODULE,
 };
 
@@ -1236,19 +1244,8 @@ static const struct file_operations nfs_volume_list_fops = {
  */
 static int nfs_server_list_open(struct inode *inode, struct file *file)
 {
-       struct seq_file *m;
-       int ret;
-       struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
-       struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
-
-       ret = seq_open(file, &nfs_server_list_ops);
-       if (ret < 0)
-               return ret;
-
-       m = file->private_data;
-       m->private = net;
-
-       return 0;
+       return seq_open_net(inode, file, &nfs_server_list_ops,
+                          sizeof(struct seq_net_private));
 }
 
 /*
@@ -1256,7 +1253,7 @@ static int nfs_server_list_open(struct inode *inode, struct file *file)
  */
 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
 {
-       struct nfs_net *nn = net_generic(m->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
 
        /* lock the list against modification */
        spin_lock(&nn->nfs_client_lock);
@@ -1268,7 +1265,7 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
  */
 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-       struct nfs_net *nn = net_generic(p->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
 
        return seq_list_next(v, &nn->nfs_client_list, pos);
 }
@@ -1278,7 +1275,7 @@ static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
  */
 static void nfs_server_list_stop(struct seq_file *p, void *v)
 {
-       struct nfs_net *nn = net_generic(p->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
 
        spin_unlock(&nn->nfs_client_lock);
 }
@@ -1289,7 +1286,7 @@ static void nfs_server_list_stop(struct seq_file *p, void *v)
 static int nfs_server_list_show(struct seq_file *m, void *v)
 {
        struct nfs_client *clp;
-       struct nfs_net *nn = net_generic(m->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
 
        /* display header on line 1 */
        if (v == &nn->nfs_client_list) {
@@ -1321,19 +1318,8 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
  */
 static int nfs_volume_list_open(struct inode *inode, struct file *file)
 {
-       struct seq_file *m;
-       int ret;
-       struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
-       struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
-
-       ret = seq_open(file, &nfs_volume_list_ops);
-       if (ret < 0)
-               return ret;
-
-       m = file->private_data;
-       m->private = net;
-
-       return 0;
+       return seq_open_net(inode, file, &nfs_server_list_ops,
+                          sizeof(struct seq_net_private));
 }
 
 /*
@@ -1341,7 +1327,7 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file)
  */
 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
 {
-       struct nfs_net *nn = net_generic(m->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
 
        /* lock the list against modification */
        spin_lock(&nn->nfs_client_lock);
@@ -1353,7 +1339,7 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
  */
 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-       struct nfs_net *nn = net_generic(p->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
 
        return seq_list_next(v, &nn->nfs_volume_list, pos);
 }
@@ -1363,7 +1349,7 @@ static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
  */
 static void nfs_volume_list_stop(struct seq_file *p, void *v)
 {
-       struct nfs_net *nn = net_generic(p->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
 
        spin_unlock(&nn->nfs_client_lock);
 }
@@ -1376,7 +1362,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
        struct nfs_server *server;
        struct nfs_client *clp;
        char dev[8], fsid[17];
-       struct nfs_net *nn = net_generic(m->private, nfs_net_id);
+       struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
 
        /* display header on line 1 */
        if (v == &nn->nfs_volume_list) {
@@ -1407,6 +1393,45 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
        return 0;
 }
 
+int nfs_fs_proc_net_init(struct net *net)
+{
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
+       struct proc_dir_entry *p;
+
+       nn->proc_nfsfs = proc_net_mkdir(net, "nfsfs", net->proc_net);
+       if (!nn->proc_nfsfs)
+               goto error_0;
+
+       /* a file of servers with which we're dealing */
+       p = proc_create("servers", S_IFREG|S_IRUGO,
+                       nn->proc_nfsfs, &nfs_server_list_fops);
+       if (!p)
+               goto error_1;
+
+       /* a file of volumes that we have mounted */
+       p = proc_create("volumes", S_IFREG|S_IRUGO,
+                       nn->proc_nfsfs, &nfs_volume_list_fops);
+       if (!p)
+               goto error_2;
+       return 0;
+
+error_2:
+       remove_proc_entry("servers", nn->proc_nfsfs);
+error_1:
+       remove_proc_entry("fs/nfsfs", NULL);
+error_0:
+       return -ENOMEM;
+}
+
+void nfs_fs_proc_net_exit(struct net *net)
+{
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+       remove_proc_entry("volumes", nn->proc_nfsfs);
+       remove_proc_entry("servers", nn->proc_nfsfs);
+       remove_proc_entry("fs/nfsfs", NULL);
+}
+
 /*
  * initialise the /proc/fs/nfsfs/ directory
  */
@@ -1419,14 +1444,12 @@ int __init nfs_fs_proc_init(void)
                goto error_0;
 
        /* a file of servers with which we're dealing */
-       p = proc_create("servers", S_IFREG|S_IRUGO,
-                       proc_fs_nfs, &nfs_server_list_fops);
+       p = proc_symlink("servers", proc_fs_nfs, "../../net/nfsfs/servers");
        if (!p)
                goto error_1;
 
        /* a file of volumes that we have mounted */
-       p = proc_create("volumes", S_IFREG|S_IRUGO,
-                       proc_fs_nfs, &nfs_volume_list_fops);
+       p = proc_symlink("volumes", proc_fs_nfs, "../../net/nfsfs/volumes");
        if (!p)
                goto error_2;
        return 0;