From: Bryan Schumaker <[email protected]>
This patch series turns NFS v2, v3 and v4 into loadable kernel modules that
need to be loaded before using. This should eventually help clean up all of
the NFS code by giving us a chance to remove most of the ifdefs that check
for CONFIG_NFS_V3 and CONFIG_NFS_V4.
I move as much code as I needed to get everything to compile, so removing
all the ifdefs will still require a bit more work. I'm hoping that this is
a good start, however. Whenever I created a new file with copy and pasted
code I copied the copyright line from the original file. If somebody else
has the copyright let me know and I'll change the copyright line in a future
version of these patches.
Parts of NFS 4.1 are still compiled into the generic client but other parts
have migrated into the nfs4.ko module. Therefore, to use v4.1 you will need
to run `modprobe nfs4`.
Patch Map
---------
- Patches 01 and 02 do basic preparations
- Patch 03 make NFS v2 a Kconfig option
- Patch 04 adds in the NFS version registering framework
- Patches 05 - 07 turn NFS v2 into a loadable module, note that v2 is directly
compiled into nfs.ko until patch 07.
- Patches 08 - 12 do the setup and conversion of v3 into a loadable module
with updates to the v2 module happening in patch 08. v3 isn't a module until
patch 12.
- Patch 13 is a small cleanup patch to remove code that is no longer used once
v2 and v3 are turned into modules.
- Patch 14 - 44 do the necessary preperations and conversion of v4 into a
kernel module. Updates to the v2 and v3 modules happen througout the
preparation patches. v4 is moved into its own subdirectory in patch 14
and I gradually move code over throughout the rest of the patches to avoid
a huge "copy everything at once" patch. v4 is still compiled into nfs.ko
until patch 44 is applied.
Is there a `git diff` shortcut for moving a large chunk of code from one file
to another? Patch 37 and 41 move #ifdef CONFIG_NFS_V4 blocks into the nfs4/
subdirectory, but so much needed to be moved to keep everything bisectable
that both patches are 1300+ lines. The patches leading up to both of these
do the necessary work so I could cut and paste code without having to do much
else to get it to compile.
I use a function pointer set in an nfs_subversion structure to determine if
a v2, v3, or v4 implementation should be called in various places. Most of
these function pointers had to be addid in places where NFS v4 did something
slighly differently. I would eventually like to see if any of the function
pointers can be removed by defining new nfs4 functions in any of the nfs4
structures (file_system_type, super_operations, inode_operations, ...).
Comments and suggestions are appreciated. Thanks!
- Bryan
From: Bryan Schumaker <[email protected]>
Still compiled as part of the nfs module, this prepares for making it
its own module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/{ => nfs2}/proc.c | 2 +-
fs/nfs/{nfs2xdr.c => nfs2/xdr.c} | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
rename fs/nfs/{ => nfs2}/proc.c (99%)
rename fs/nfs/{nfs2xdr.c => nfs2/xdr.c} (99%)
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7ddd45d..44db87d 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,7 +9,7 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o
+nfs-$(CONFIG_NFS_V2) += nfs2/proc.o nfs2/xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
diff --git a/fs/nfs/proc.c b/fs/nfs/nfs2/proc.c
similarity index 99%
rename from fs/nfs/proc.c
rename to fs/nfs/nfs2/proc.c
index f48125d..65eafa3 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/nfs2/proc.c
@@ -41,7 +41,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
-#include "internal.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2/xdr.c
similarity index 99%
rename from fs/nfs/nfs2xdr.c
rename to fs/nfs/nfs2/xdr.c
index 61df96d..4b052a2 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2/xdr.c
@@ -21,7 +21,7 @@
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs_fs.h>
-#include "internal.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_XDR
--
1.7.8.3
On Fri Jan 13 15:48:38 2012, Chuck Lever wrote:
>
> On Jan 13, 2012, at 3:10 PM, [email protected] wrote:
>
>> From: Bryan Schumaker <[email protected]>
>>
>> The v4 code uses these functions in the generic client, so they need to
>> be available to modules.
>
> If you add the EXPORT_SYMBOL() macros in separate patches, is that bisect-able? Seems like you should add the macros when you move functions.
I thought it was since it would detect namespace collisions... I can
fix it if I need to.
>
> It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
Not that I know of. I found examples for compiling directories as
modules, but not specific files or parts of files.
>
>> Signed-off-by: Bryan Schumaker <[email protected]>
>> ---
>> fs/nfs/client.c | 2 ++
>> fs/nfs/dir.c | 2 ++
>> fs/nfs/dns_resolve.c | 4 ++++
>> fs/nfs/fscache.c | 4 ++++
>> fs/nfs/inode.c | 9 +++++++++
>> fs/nfs/namespace.c | 1 +
>> fs/nfs/super.c | 2 ++
>> fs/nfs/unlink.c | 3 +++
>> fs/nfs/write.c | 2 ++
>> 9 files changed, 29 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>> index 2c3f50e..0e4ddbe 100644
>> --- a/fs/nfs/client.c
>> +++ b/fs/nfs/client.c
>> @@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
>> spin_unlock(&nfs_client_lock);
>>
>> }
>> +EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
>>
>> static void nfs_server_remove_lists(struct nfs_server *server)
>> {
>> @@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
>> nfs_release_automount_timer();
>> dprintk("<-- nfs_free_server()\n");
>> }
>> +EXPORT_SYMBOL_GPL(nfs_free_server);
>>
>> /*
>> * Create a version 2 or 3 volume record
>> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
>> index 210284f..909f8de 100644
>> --- a/fs/nfs/dir.c
>> +++ b/fs/nfs/dir.c
>> @@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
>> {
>> NFS_I(dir)->cache_change_attribute++;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
>>
>> /*
>> * A check for whether or not the parent directory has changed.
>> @@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
>> {
>> return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
>> }
>> +EXPORT_SYMBOL_GPL(nfs_may_open);
>>
>> int nfs_permission(struct inode *inode, int mask)
>> {
>> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
>> index a6e711a..8b9aeba 100644
>> --- a/fs/nfs/dns_resolve.c
>> +++ b/fs/nfs/dns_resolve.c
>> @@ -6,6 +6,8 @@
>> * Resolves DNS hostnames into valid ip addresses
>> */
>>
>> +#include <linux/module.h>
>> +
>> #ifdef CONFIG_NFS_USE_KERNEL_DNS
>>
>> #include <linux/sunrpc/clnt.h>
>> @@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>> kfree(ip_addr);
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>
>> #else
>>
>> @@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>> ret = -ESRCH;
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>
>> int nfs_dns_resolver_init(void)
>> {
>> diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
>> index 419119c..94e2d51 100644
>> --- a/fs/nfs/fscache.c
>> +++ b/fs/nfs/fscache.c
>> @@ -9,6 +9,7 @@
>> * 2 of the Licence, or (at your option) any later version.
>> */
>>
>> +#include <linux/module.h>
>> #include <linux/init.h>
>> #include <linux/kernel.h>
>> #include <linux/sched.h>
>> @@ -163,6 +164,7 @@ non_unique:
>> printk(KERN_WARNING "NFS:"
>> " Cache request denied due to non-unique superblock keys\n");
>> }
>> +EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
>>
>> /*
>> * release a per-superblock cookie
>> @@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
>> nfss->fscache_key = NULL;
>> }
>> }
>> +EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
>>
>> /*
>> * Initialise the per-inode cache cookie pointer for an NFS inode.
>> @@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
>> nfs_fscache_inode_unlock(inode);
>> }
>> }
>> +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
>>
>> /*
>> * Replace a per-inode cookie due to revalidation detecting a file having
>> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
>> index 57a68b8..d7afc2b 100644
>> --- a/fs/nfs/inode.c
>> +++ b/fs/nfs/inode.c
>> @@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
>> schedule();
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
>>
>> /**
>> * nfs_compat_user_ino64 - returns the user-visible inode number
>> @@ -421,6 +422,7 @@ out_no_inode:
>> dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
>> goto out;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_fhget);
>>
>> #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
>>
>> @@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
>> }
>> return ctx;
>> }
>> +EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
>>
>> struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>> {
>> @@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>> atomic_inc(&ctx->lock_context.count);
>> return ctx;
>> }
>> +EXPORT_SYMBOL_GPL(get_nfs_open_context);
>>
>> static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
>> {
>> @@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
>> {
>> __put_nfs_open_context(ctx, 0);
>> }
>> +EXPORT_SYMBOL_GPL(put_nfs_open_context);
>>
>> /*
>> * Ensure that mmap has a recent RPC credential for use when writing out
>> @@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
>> list_add(&ctx->list, &nfsi->open_files);
>> spin_unlock(&inode->i_lock);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
>>
>> /*
>> * Given an inode, search for an open context with the desired characteristics
>> @@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
>> #endif /* CONFIG_NFS_V4 */
>> return &nfsi->vfs_inode;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_alloc_inode);
>>
>> static void nfs_i_callback(struct rcu_head *head)
>> {
>> @@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
>> {
>> call_rcu(&inode->i_rcu, nfs_i_callback);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_destroy_inode);
>>
>> static inline void nfs4_init_once(struct nfs_inode *nfsi)
>> {
>> @@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
>> }
>>
>> struct workqueue_struct *nfsiod_workqueue;
>> +EXPORT_SYMBOL_GPL(nfsiod_workqueue);
>>
>> /*
>> * start up the nfsiod workqueue
>> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
>> index 203b4b3..d311128 100644
>> --- a/fs/nfs/namespace.c
>> +++ b/fs/nfs/namespace.c
>> @@ -114,6 +114,7 @@ Elong_unlock:
>> Elong:
>> return ERR_PTR(-ENAMETOOLONG);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_path);
>>
>> #if IS_ENABLED(CONFIG_NFS_V4)
>> rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>> index 2c8ed6f..d2d1b6b 100644
>> --- a/fs/nfs/super.c
>> +++ b/fs/nfs/super.c
>> @@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
>> if (atomic_inc_return(&server->active) == 1)
>> atomic_inc(&sb->s_active);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_sb_active);
>>
>> void nfs_sb_deactive(struct super_block *sb)
>> {
>> @@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
>> if (atomic_dec_and_test(&server->active))
>> deactivate_super(sb);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_sb_deactive);
>>
>> /*
>> * Deliver file system statistics to userspace
>> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
>> index 9f04700..32c1d70 100644
>> --- a/fs/nfs/unlink.c
>> +++ b/fs/nfs/unlink.c
>> @@ -5,6 +5,7 @@
>> *
>> */
>>
>> +#include <linux/module.h>
>> #include <linux/slab.h>
>> #include <linux/string.h>
>> #include <linux/dcache.h>
>> @@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
>>
>> wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
>>
>> void nfs_unblock_sillyrename(struct dentry *dentry)
>> {
>> @@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
>> }
>> spin_unlock(&dir->i_lock);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
>>
>> /**
>> * nfs_async_unlink - asynchronous unlinking of a file
>> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
>> index f9ca30c..0750ebb 100644
>> --- a/fs/nfs/write.c
>> +++ b/fs/nfs/write.c
>> @@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
>> }
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(nfs_write_inode);
>>
>> /*
>> * flush the inode to disk.
>> @@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
>>
>> return sync_inode(inode, &wbc);
>> }
>> +EXPORT_SYMBOL_GPL(nfs_wb_all);
>>
>> int nfs_wb_page_cancel(struct inode *inode, struct page *page)
>> {
>> --
>> 1.7.8.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
From: Bryan Schumaker <[email protected]>
I moved the sysctls from the generic NFS client to the v4 subdirectory
and then changed the v4 startup function to register sysctls when it is
run.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/nfs.h | 2 --
fs/nfs/nfs4/module.c | 9 +++++++++
fs/nfs/nfs4/nfs4.h | 3 +++
fs/nfs/{ => nfs4}/sysctl.c | 27 +++------------------------
fs/nfs/sysctl.c | 28 ----------------------------
6 files changed, 16 insertions(+), 55 deletions(-)
copy fs/nfs/{ => nfs4}/sysctl.c (69%)
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 3850b1f..87213a8 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/delegation.o nfs4/idmap.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
- nfs4/client.o nfs4/module.o
+ nfs4/client.o nfs4/module.o nfs4/sysctl.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 455bacf..7b40e24 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -51,8 +51,6 @@ struct nfs_subversion {
struct nfs_clone_mount *);
};
-void nfs_register_versions(void);
-
struct nfs_subversion *get_nfs_version(unsigned int);
struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
diff --git a/fs/nfs/nfs4/module.c b/fs/nfs/nfs4/module.c
index 4ac3069..9edd174 100644
--- a/fs/nfs/nfs4/module.c
+++ b/fs/nfs/nfs4/module.c
@@ -43,11 +43,20 @@ static struct nfs_subversion nfs_v4 = {
int __init init_nfs_v4(void)
{
+ int ret;
+
+ ret = nfs4_register_sysctl();
+ if (ret < 0)
+ goto error_0;
register_nfs_version(&nfs_v4);
return 0;
+
+error_0:
+ return ret;
}
void exit_nfs_v4(void)
{
unregister_nfs_version(&nfs_v4);
+ nfs4_unregister_sysctl();
}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 227a617..5f69528 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -20,4 +20,7 @@ int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
int nfs4_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
void nfs4_put_client(struct nfs_client *);
+int nfs4_register_sysctl(void);
+void nfs4_unregister_sysctl(void);
+
#endif /* __LINUX_FS_NFS_NFS4_H */
diff --git a/fs/nfs/sysctl.c b/fs/nfs/nfs4/sysctl.c
similarity index 69%
copy from fs/nfs/sysctl.c
copy to fs/nfs/nfs4/sysctl.c
index d839b40d..8250314 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/nfs4/sysctl.c
@@ -13,16 +13,13 @@
#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>
-#include "nfs4/callback.h"
+#include "callback.h"
-#ifdef CONFIG_NFS_V4
static const int nfs_set_port_min = 0;
static const int nfs_set_port_max = 65535;
-#endif
static struct ctl_table_header *nfs_callback_sysctl_table;
static ctl_table nfs_cb_sysctls[] = {
-#ifdef CONFIG_NFS_V4
{
.procname = "nfs_callback_tcpport",
.data = &nfs_callback_set_tcpport,
@@ -32,7 +29,6 @@ static ctl_table nfs_cb_sysctls[] = {
.extra1 = (int *)&nfs_set_port_min,
.extra2 = (int *)&nfs_set_port_max,
},
-#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
{
.procname = "idmap_cache_timeout",
.data = &nfs_idmap_cache_timeout,
@@ -40,23 +36,6 @@ static ctl_table nfs_cb_sysctls[] = {
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
-#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
-#endif
- {
- .procname = "nfs_mountpoint_timeout",
- .data = &nfs_mountpoint_expiry_timeout,
- .maxlen = sizeof(nfs_mountpoint_expiry_timeout),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
- {
- .procname = "nfs_congestion_kb",
- .data = &nfs_congestion_kb,
- .maxlen = sizeof(nfs_congestion_kb),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- { }
};
static ctl_table nfs_cb_sysctl_dir[] = {
@@ -77,7 +56,7 @@ static ctl_table nfs_cb_sysctl_root[] = {
{ }
};
-int nfs_register_sysctl(void)
+int nfs4_register_sysctl(void)
{
nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root);
if (nfs_callback_sysctl_table == NULL)
@@ -85,7 +64,7 @@ int nfs_register_sysctl(void)
return 0;
}
-void nfs_unregister_sysctl(void)
+void nfs4_unregister_sysctl(void)
{
unregister_sysctl_table(nfs_callback_sysctl_table);
nfs_callback_sysctl_table = NULL;
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index d839b40d..6b3f253 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -9,39 +9,11 @@
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/module.h>
-#include <linux/nfs4.h>
-#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>
-#include "nfs4/callback.h"
-
-#ifdef CONFIG_NFS_V4
-static const int nfs_set_port_min = 0;
-static const int nfs_set_port_max = 65535;
-#endif
static struct ctl_table_header *nfs_callback_sysctl_table;
static ctl_table nfs_cb_sysctls[] = {
-#ifdef CONFIG_NFS_V4
- {
- .procname = "nfs_callback_tcpport",
- .data = &nfs_callback_set_tcpport,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = (int *)&nfs_set_port_min,
- .extra2 = (int *)&nfs_set_port_max,
- },
-#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
- {
- .procname = "idmap_cache_timeout",
- .data = &nfs_idmap_cache_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
-#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
-#endif
{
.procname = "nfs_mountpoint_timeout",
.data = &nfs_mountpoint_expiry_timeout,
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
These structures and functions are no longer needed in the generic
client since they are defined in the NFS v2 and v3 modules.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 8 --------
fs/nfs/dir.c | 23 -----------------------
fs/nfs/file.c | 19 -------------------
include/linux/nfs_fs.h | 26 --------------------------
4 files changed, 0 insertions(+), 76 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ffb5994..1e1bbf8 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -803,19 +803,11 @@ static int nfs_start_lockd(struct nfs_server *server)
/*
* Initialise an NFSv3 ACL client connection
*/
-#ifdef CONFIG_NFS_V3_ACL
static void nfs_init_server_aclclient(struct nfs_server *server)
{
server->flags &= ~NFS_MOUNT_NOACL;
server->caps &= ~NFS_CAP_ACLS;
}
-#else
-static inline void nfs_init_server_aclclient(struct nfs_server *server)
-{
- server->flags &= ~NFS_MOUNT_NOACL;
- server->caps &= ~NFS_CAP_ACLS;
-}
-#endif
/*
* Create a general RPC client
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 41a5161..0348727 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -61,21 +61,6 @@ const struct file_operations nfs_dir_operations = {
.fsync = nfs_fsync_dir,
};
-const struct inode_operations nfs_dir_inode_operations = {
- .create = nfs_create,
- .lookup = nfs_lookup,
- .link = nfs_link,
- .unlink = nfs_unlink,
- .symlink = nfs_symlink,
- .mkdir = nfs_mkdir,
- .rmdir = nfs_rmdir,
- .mknod = nfs_mknod,
- .rename = nfs_rename,
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
-};
-
const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};
@@ -1230,14 +1215,6 @@ void nfs_d_release(struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(nfs_d_release);
-const struct dentry_operations nfs_dentry_operations = {
- .d_revalidate = nfs_lookup_revalidate,
- .d_delete = nfs_dentry_delete,
- .d_iput = nfs_dentry_iput,
- .d_automount = nfs_d_automount,
- .d_release = nfs_d_release,
-};
-
struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *res;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 74c47eb..d9f11c5 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -845,25 +845,6 @@ int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
}
EXPORT_SYMBOL_GPL(nfs_setlease);
-const struct file_operations nfs_file_operations = {
- .llseek = nfs_file_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
- .mmap = nfs_file_mmap,
- .open = nfs_file_open,
- .flush = nfs_file_flush,
- .release = nfs_file_release,
- .fsync = nfs_file_fsync,
- .lock = nfs_lock,
- .flock = nfs_flock,
- .splice_read = nfs_file_splice_read,
- .splice_write = nfs_file_splice_write,
- .check_flags = nfs_check_flags,
- .setlease = nfs_setlease,
-};
-
#ifdef CONFIG_NFS_V4
static int
nfs4_file_open(struct inode *inode, struct file *filp)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 666ebea..4814fcc 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -405,11 +405,6 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
/*
* linux/fs/nfs/file.c
*/
-extern const struct inode_operations nfs_file_inode_operations;
-#if IS_ENABLED(CONFIG_NFS_V3)
-extern const struct inode_operations nfs3_file_inode_operations;
-#endif /* CONFIG_NFS_V3 */
-extern const struct file_operations nfs_file_operations;
#ifdef CONFIG_NFS_V4
extern const struct file_operations nfs4_file_operations;
#endif /* CONFIG_NFS_V4 */
@@ -433,22 +428,6 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
}
/*
- * linux/fs/nfs/xattr.c
- */
-#ifdef CONFIG_NFS_V3_ACL
-extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
-extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
-extern int nfs3_setxattr(struct dentry *, const char *,
- const void *, size_t, int);
-extern int nfs3_removexattr (struct dentry *, const char *name);
-#else
-# define nfs3_listxattr NULL
-# define nfs3_getxattr NULL
-# define nfs3_setxattr NULL
-# define nfs3_removexattr NULL
-#endif
-
-/*
* linux/fs/nfs/direct.c
*/
extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
@@ -463,12 +442,7 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
/*
* linux/fs/nfs/dir.c
*/
-extern const struct inode_operations nfs_dir_inode_operations;
-#if IS_ENABLED(CONFIG_NFS_V3)
-extern const struct inode_operations nfs3_dir_inode_operations;
-#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_dir_operations;
-extern const struct dentry_operations nfs_dentry_operations;
extern void nfs_force_lookup_revalidate(struct inode *dir);
extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
v4 isn't a module yet, but this puts the structure in the correct place.
I also modified super.c to call the future module's init and exit
functions. This will let me gradually fill out the functions with the
necessary code in smaller steps.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 51 ------------------------------------------------
fs/nfs/inode.c | 1 -
fs/nfs/nfs4/module.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4/nfs4.h | 3 ++
fs/nfs/super.c | 10 +++++++-
6 files changed, 65 insertions(+), 55 deletions(-)
create mode 100644 fs/nfs/nfs4/module.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 16e3489..3850b1f 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/delegation.o nfs4/idmap.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
- nfs4/client.o
+ nfs4/client.o nfs4/module.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 1b84962..dd6453b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -42,7 +42,6 @@
#include <asm/system.h>
-#include "nfs4/nfs4.h"
#include "nfs4/nfs4_fs.h"
#include "nfs4/callback.h"
#include "nfs4/delegation.h"
@@ -113,44 +112,6 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};
-/*
- * Default function for referencing and unreferencing
- * nfs_version_module structures to prevent dereferencing
- * a null pointer by the framework code. A functional
- * version will be implemented by individual nfs versions
- * as they are converted into modules.
- *
- * Once everything has been converted this function will
- * be removed.
- */
-#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
-static void nfs_module_null_function(void)
-{
-}
-#endif
-
-#ifdef CONFIG_NFS_V4
-static struct nfs_subversion nfs_v4_mod = {
- .version = 4,
- .rpc_vers = &nfs_version4,
- .rpc_ops = &nfs_v4_clientops,
-
- .reference = nfs_module_null_function,
- .unreference = nfs_module_null_function,
- .validate_mount_data = nfs4_validate_text_mount_data,
- .init_aclclient = nfs4_init_aclclient,
- .alloc_client = nfs4_alloc_client,
- .put_client = nfs4_put_client,
- .try_mount = nfs4_try_mount,
- .shutdown_client = nfs4_shutdown_client,
- .have_delegation = nfs4_have_delegation,
- .have_delegated_attributes = nfs4_have_delegated_attributes,
- .return_delegation = nfs4_inode_return_delegation,
- .do_submount = nfs4_do_submount,
- .do_clone_mount = nfs4_do_clone_mount,
-};
-#endif /* CONFIG_NFS_V4 */
-
struct nfs_subversion *get_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs;
@@ -205,18 +166,6 @@ void unregister_nfs_version(struct nfs_subversion *nfs)
}
EXPORT_SYMBOL_GPL(unregister_nfs_version);
-/*
- * Preload all configured NFS versions during module init.
- * This function should be edited after each protocol is converted,
- * and eventually removed.
- */
-void __init nfs_register_versions(void)
-{
-#ifdef CONFIG_NFS_V4
- register_nfs_version(&nfs_v4_mod);
-#endif
-}
-
#ifdef CONFIG_NFS_V4
int nfs4_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
{
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 1bea5b7..29673ac 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1635,7 +1635,6 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
- nfs_register_versions();
return 0;
out:
#ifdef CONFIG_PROC_FS
diff --git a/fs/nfs/nfs4/module.c b/fs/nfs/nfs4/module.c
new file mode 100644
index 0000000..4ac3069
--- /dev/null
+++ b/fs/nfs/nfs4/module.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Initialize the NFS v4 module
+ */
+
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+
+#include "../nfs.h"
+#include "nfs4.h"
+#include "delegation.h"
+
+static void nfs4_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs4_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+static struct nfs_subversion nfs_v4 = {
+ .version = 4,
+ .rpc_vers = &nfs_version4,
+ .rpc_ops = &nfs_v4_clientops,
+
+ .reference = nfs4_reference,
+ .unreference = nfs4_unreference,
+ .validate_mount_data = nfs4_validate_text_mount_data,
+ .init_aclclient = nfs4_init_aclclient,
+ .alloc_client = nfs4_alloc_client,
+ .put_client = nfs4_put_client,
+ .try_mount = nfs4_try_mount,
+ .shutdown_client = nfs4_shutdown_client,
+ .have_delegation = nfs4_have_delegation,
+ .have_delegated_attributes = nfs4_have_delegated_attributes,
+ .return_delegation = nfs4_inode_return_delegation,
+ .do_submount = nfs4_do_submount,
+ .do_clone_mount = nfs4_do_clone_mount,
+};
+
+int __init init_nfs_v4(void)
+{
+ register_nfs_version(&nfs_v4);
+ return 0;
+}
+
+void exit_nfs_v4(void)
+{
+ unregister_nfs_version(&nfs_v4);
+}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 0b1cf87..227a617 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -3,6 +3,9 @@
#include "../nfs.h"
+int init_nfs_v4(void);
+void exit_nfs_v4(void);
+
void nfs4_init_aclclient(struct nfs_server *);
void nfs4_shutdown_client(struct nfs_client *);
struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e1ea351..3306c43 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -397,16 +397,21 @@ int __init register_nfs_fs(void)
if (ret < 0)
goto error_1;
#ifdef CONFIG_NFS_V4
- ret = register_filesystem(&nfs4_fs_type);
+ ret = init_nfs_v4();
if (ret < 0)
goto error_2;
+ ret = register_filesystem(&nfs4_fs_type);
+ if (ret < 0)
+ goto error_3;
#endif
register_shrinker(&acl_shrinker);
return 0;
#ifdef CONFIG_NFS_V4
-error_2:
+error_3:
nfs_unregister_sysctl();
+error_2:
+ exit_nfs_v4();
#endif
error_1:
unregister_filesystem(&nfs_fs_type);
@@ -422,6 +427,7 @@ void __exit unregister_nfs_fs(void)
unregister_shrinker(&acl_shrinker);
#ifdef CONFIG_NFS_V4
unregister_filesystem(&nfs4_fs_type);
+ exit_nfs_v4();
#endif
nfs_unregister_sysctl();
unregister_filesystem(&nfs_fs_type);
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
You need to run `modprobe nfs4` before you can use it.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 1 +
fs/nfs/inode.c | 1 -
fs/nfs/nfs4/module.c | 9 +++++++--
fs/nfs/nfs4/nfs4.h | 2 --
fs/nfs/super.c | 12 ------------
6 files changed, 9 insertions(+), 18 deletions(-)
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 57c4b19..608b84a 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -70,7 +70,7 @@ config NFS_V3_ACL
If unsure, say N.
config NFS_V4
- bool "NFS client support for NFS version 4"
+ tristate "NFS client support for NFS version 4"
depends on NFS_FS
select SUNRPC_GSS
help
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 34f752d..2a88234 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -25,5 +25,6 @@ nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
obj-$(CONFIG_NFS_V2) += nfs2/
obj-$(CONFIG_NFS_V3) += nfs3/
+obj-$(CONFIG_NFS_V4) += nfs4/
obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d7afc2b..d5f1b5c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1665,7 +1665,6 @@ static void __exit exit_nfs_fs(void)
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
- nfs_cleanup_cb_ident_idr();
unregister_nfs_fs();
nfs_fs_proc_exit();
nfsiod_stop();
diff --git a/fs/nfs/nfs4/module.c b/fs/nfs/nfs4/module.c
index c57b642..80f77c8 100644
--- a/fs/nfs/nfs4/module.c
+++ b/fs/nfs/nfs4/module.c
@@ -41,7 +41,7 @@ static struct nfs_subversion nfs_v4 = {
.do_clone_mount = nfs4_do_clone_mount,
};
-int __init init_nfs_v4(void)
+static int __init init_nfs_v4(void)
{
int ret;
@@ -60,9 +60,14 @@ error_0:
return ret;
}
-void exit_nfs_v4(void)
+static void __exit exit_nfs_v4(void)
{
unregister_nfs_version(&nfs_v4);
unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl();
}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v4);
+module_exit(exit_nfs_v4);
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 111ba82..dd8f94b 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -5,8 +5,6 @@
extern struct file_system_type nfs4_fs_type;
-int init_nfs_v4(void);
-void exit_nfs_v4(void);
struct nfs_server *nfs4_alloc_server(void);
struct nfs_server *nfs4_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d2d1b6b..c4c5244 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -318,18 +318,9 @@ int __init register_nfs_fs(void)
ret = nfs_register_sysctl();
if (ret < 0)
goto error_1;
-#if IS_ENABLED(CONFIG_NFS_V4)
- ret = init_nfs_v4();
- if (ret < 0)
- goto error_2;
-#endif
register_shrinker(&acl_shrinker);
return 0;
-#if IS_ENABLED(CONFIG_NFS_V4)
-error_2:
- nfs_unregister_sysctl();
-#endif
error_1:
unregister_filesystem(&nfs_fs_type);
error_0:
@@ -342,9 +333,6 @@ error_0:
void __exit unregister_nfs_fs(void)
{
unregister_shrinker(&acl_shrinker);
-#if IS_ENABLED(CONFIG_NFS_V4)
- exit_nfs_v4();
-#endif
nfs_unregister_sysctl();
unregister_filesystem(&nfs_fs_type);
}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This gives v4 a chance to check if we are doing a normal submount or a
referral.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/namespace.c | 32 +++++++++++++++++---------------
fs/nfs/nfs.h | 4 ++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs4/namespace.c | 11 +++++++++++
fs/nfs/nfs4/nfs4.h | 2 ++
7 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 6c19290..b4e13be 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -137,6 +137,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
+ .do_submount = nfs4_do_submount,
};
#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 18c5e4f..5fedb66 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -18,6 +18,7 @@
#include <linux/vfs.h>
#include <linux/sunrpc/gss_api.h>
#include "internal.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -27,11 +28,6 @@ static LIST_HEAD(nfs_automount_list);
static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
int nfs_mountpoint_expiry_timeout = 500 * HZ;
-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
- struct nfs_fh *fh,
- struct nfs_fattr *fattr,
- rpc_authflavor_t authflavor);
-
/*
* nfs_path - reconstruct the path given an arbitrary dentry
* @base - used to return pointer to the end of devname part of path
@@ -212,6 +208,16 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server,
}
#endif /* CONFIG_NFS_V4 */
+static struct vfsmount *nfs_version_submount(struct nfs_server *server,
+ struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+ return nfs_mod->do_submount(dentry, fh, fattr, authflavor);
+}
+
/*
* nfs_d_automount - Handle crossing a mountpoint on the server
* @path - The mountpoint
@@ -261,12 +267,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
goto out;
}
- if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
- mnt = nfs_do_refmount(path->dentry);
- else
- mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
- if (IS_ERR(mnt))
- goto out;
+ mnt = nfs_version_submount(server, path->dentry, fh, fattr, flavor);
dprintk("%s: done, success\n", __func__);
mntget(mnt); /* prevent immediate expiration */
@@ -335,10 +336,10 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
* @authflavor - security flavor to use when performing the mount
*
*/
-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
- struct nfs_fh *fh,
- struct nfs_fattr *fattr,
- rpc_authflavor_t authflavor)
+struct vfsmount *nfs_do_submount(struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
{
struct nfs_clone_mount mountdata = {
.sb = dentry->d_sb,
@@ -371,3 +372,4 @@ out:
dprintk("<-- nfs_do_submount() = %p\n", mnt);
return mnt;
}
+EXPORT_SYMBOL_GPL(nfs_do_submount);
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 6b746d7..181b3b3 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -20,6 +20,8 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
void (*init_aclclient)(struct nfs_server *);
+ struct vfsmount *(*do_submount)(struct dentry *, struct nfs_fh *,
+ struct nfs_fattr *, rpc_authflavor_t);
};
void nfs_register_versions(void);
@@ -70,5 +72,7 @@ int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
/* Exported in namespace.c */
struct vfsmount *nfs_d_automount(struct path *);
+struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
+ struct nfs_fattr *, rpc_authflavor_t);
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 60302c7..ffdee2b 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -27,6 +27,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
+ .do_submount = nfs_do_submount,
};
static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 4c097a5..0eb8124 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -27,6 +27,7 @@ struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
+ .do_submount = nfs_do_submount,
};
static int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4/namespace.c b/fs/nfs/nfs4/namespace.c
index 6a21d95..0ec675e 100644
--- a/fs/nfs/nfs4/namespace.c
+++ b/fs/nfs/nfs4/namespace.c
@@ -19,6 +19,7 @@
#include "../internal.h"
#include "nfs4_fs.h"
#include "../dns_resolve.h"
+#include "../nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -263,3 +264,13 @@ out:
dprintk("%s: done\n", __func__);
return mnt;
}
+
+struct vfsmount *nfs4_do_submount(struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
+ return nfs_do_refmount(dentry);
+ return nfs_do_submount(dentry, fh, fattr, authflavor);
+}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 8ed9951..4640a95 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -2,5 +2,7 @@
#define __LINUX_FS_NFS_NFS4_H
void nfs4_init_aclclient(struct nfs_server *);
+struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
+ struct nfs_fattr *, rpc_authflavor_t);
#endif /* __LINUX_FS_NFS_NFS4_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This allows v4 to use its own xdev type when doing clone mounts.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/namespace.c | 30 +++++++++++++-----------------
fs/nfs/nfs.h | 6 ++++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs4/namespace.c | 7 +++++++
fs/nfs/nfs4/nfs4.h | 4 ++++
7 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b4e13be..6091414 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -138,6 +138,7 @@ static struct nfs_subversion nfs_v4_mod = {
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
.do_submount = nfs4_do_submount,
+ .do_clone_mount = nfs4_do_clone_mount,
};
#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 5fedb66..721d882 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -305,27 +305,23 @@ void nfs_release_automount_timer(void)
cancel_delayed_work(&nfs_automount_task);
}
+struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
+ const char *devname,
+ struct nfs_clone_mount *mountdata)
+{
+ return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
+}
+EXPORT_SYMBOL_GPL(nfs_do_clone_mount);
+
/*
* Clone a mountpoint of the appropriate type
*/
-static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
- const char *devname,
- struct nfs_clone_mount *mountdata)
+struct vfsmount *nfs_version_clone_mount(struct nfs_server *server,
+ const char *devname,
+ struct nfs_clone_mount *mountdata)
{
-#ifdef CONFIG_NFS_V4
- struct vfsmount *mnt = ERR_PTR(-EINVAL);
- switch (server->nfs_client->rpc_ops->version) {
- case 2:
- case 3:
- mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
- break;
- case 4:
- mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata);
- }
- return mnt;
-#else
- return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
-#endif
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+ return nfs_mod->do_clone_mount(server, devname, mountdata);
}
/**
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 181b3b3..0f119ab 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -11,6 +11,8 @@
#include <linux/sunrpc/sched.h>
#include <linux/nfs_xdr.h>
+struct nfs_clone_mount;
+
struct nfs_subversion {
unsigned int version; /* Protocol number */
struct rpc_version *rpc_vers; /* NFS version information */
@@ -22,6 +24,8 @@ struct nfs_subversion {
void (*init_aclclient)(struct nfs_server *);
struct vfsmount *(*do_submount)(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
+ struct vfsmount *(*do_clone_mount)(struct nfs_server *, const char *,
+ struct nfs_clone_mount *);
};
void nfs_register_versions(void);
@@ -74,5 +78,7 @@ int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
struct vfsmount *nfs_d_automount(struct path *);
struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
+struct vfsmount *nfs_do_clone_mount(struct nfs_server *, const char *,
+ struct nfs_clone_mount *);
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index ffdee2b..768c375 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -28,6 +28,7 @@ struct nfs_subversion nfs_v2 = {
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
.do_submount = nfs_do_submount,
+ .do_clone_mount = nfs_do_clone_mount,
};
static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 0eb8124..0898339 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -28,6 +28,7 @@ struct nfs_subversion nfs_v3 = {
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
.do_submount = nfs_do_submount,
+ .do_clone_mount = nfs_do_clone_mount,
};
static int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4/namespace.c b/fs/nfs/nfs4/namespace.c
index 0ec675e..11bda77 100644
--- a/fs/nfs/nfs4/namespace.c
+++ b/fs/nfs/nfs4/namespace.c
@@ -274,3 +274,10 @@ struct vfsmount *nfs4_do_submount(struct dentry *dentry,
return nfs_do_refmount(dentry);
return nfs_do_submount(dentry, fh, fattr, authflavor);
}
+
+struct vfsmount *nfs4_do_clone_mount(struct nfs_server *server,
+ const char *devname,
+ struct nfs_clone_mount *mountdata)
+{
+ return vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata);
+}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 4640a95..f6694b9 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -1,8 +1,12 @@
#ifndef __LINUX_FS_NFS_NFS4_H
#define __LINUX_FS_NFS_NFS4_H
+#include "../nfs.h"
+
void nfs4_init_aclclient(struct nfs_server *);
struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
+struct vfsmount *nfs4_do_clone_mount(struct nfs_server *, const char *,
+ struct nfs_clone_mount *);
#endif /* __LINUX_FS_NFS_NFS4_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This is for use with v4 delegations, so once again v2 and v3 can leave
it empty.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/inode.c | 6 ++++++
fs/nfs/nfs.h | 2 ++
fs/nfs/nfs2/module.c | 6 ++++++
fs/nfs/nfs3/module.c | 6 ++++++
fs/nfs/nfs4/delegation.c | 6 ++++++
fs/nfs/nfs4/delegation.h | 6 ------
fs/nfs/nfs4/nfs4.h | 1 +
8 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e00f268..368aa7e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -138,6 +138,7 @@ static struct nfs_subversion nfs_v4_mod = {
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
.have_delegation = nfs4_have_delegation,
+ .have_delegated_attributes = nfs4_have_delegated_attributes,
.do_submount = nfs4_do_submount,
.do_clone_mount = nfs4_do_clone_mount,
};
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 1c7e24f..5328b68 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -130,6 +130,12 @@ int nfs_have_delegation(struct inode *inode, fmode_t flags)
return nfs_mod->have_delegation(inode, flags);
}
+int nfs_have_delegated_attributes(struct inode *inode)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ return nfs_mod->have_delegated_attributes(inode);
+}
+
/**
* nfs_sync_mapping - helper to flush all mmapped dirty data to disk
*/
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 7be27f4..08950a2 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -23,6 +23,7 @@ struct nfs_subversion {
void (*unreference)(void); /* Also for reference counting */
void (*init_aclclient)(struct nfs_server *);
int (*have_delegation)(struct inode *, fmode_t);
+ int (*have_delegated_attributes)(struct inode *);
struct vfsmount *(*do_submount)(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
struct vfsmount *(*do_clone_mount)(struct nfs_server *, const char *,
@@ -75,6 +76,7 @@ int nfs_setlease(struct file *, long, struct file_lock **);
int nfs_setattr(struct dentry *, struct iattr *);
int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int nfs_have_delegation(struct inode *, fmode_t);
+int nfs_have_delegated_attributes(struct inode *);
/* Exported in namespace.c */
struct vfsmount *nfs_d_automount(struct path *);
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index ccbb759..ef6dbb4 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -24,6 +24,11 @@ static int nfs2_no_delegation(struct inode *inode, fmode_t flags)
return 0;
}
+static int nfs2_no_delegation2(struct inode *inode)
+{
+ return 0;
+}
+
struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -33,6 +38,7 @@ struct nfs_subversion nfs_v2 = {
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
.have_delegation = nfs2_no_delegation,
+ .have_delegated_attributes = nfs2_no_delegation2,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 10cfab8..bdd2e33 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -24,6 +24,11 @@ static int nfs3_no_delegation(struct inode *inode, fmode_t flags)
return 0;
}
+static int nfs3_no_delegation2(struct inode *inode)
+{
+ return 0;
+}
+
struct nfs_subversion nfs_v3 = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -33,6 +38,7 @@ struct nfs_subversion nfs_v3 = {
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
.have_delegation = nfs3_no_delegation,
+ .have_delegated_attributes = nfs3_no_delegation2,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs4/delegation.c b/fs/nfs/nfs4/delegation.c
index 800f44e..272e735 100644
--- a/fs/nfs/nfs4/delegation.c
+++ b/fs/nfs/nfs4/delegation.c
@@ -63,6 +63,12 @@ int nfs4_have_delegation(struct inode *inode, fmode_t flags)
return ret;
}
+int nfs4_have_delegated_attributes(struct inode *inode)
+{
+ return nfs4_have_delegation(inode, FMODE_READ) &&
+ !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
+}
+
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct inode *inode = state->inode;
diff --git a/fs/nfs/nfs4/delegation.h b/fs/nfs/nfs4/delegation.h
index 675ceea..2c45cb6 100644
--- a/fs/nfs/nfs4/delegation.h
+++ b/fs/nfs/nfs4/delegation.h
@@ -65,10 +65,4 @@ static inline int nfs_inode_return_delegation(struct inode *inode)
}
#endif
-static inline int nfs_have_delegated_attributes(struct inode *inode)
-{
- return nfs4_have_delegation(inode, FMODE_READ) &&
- !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
-}
-
#endif
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index f6694b9..6d5cf57 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -8,5 +8,6 @@ struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
struct vfsmount *nfs4_do_clone_mount(struct nfs_server *, const char *,
struct nfs_clone_mount *);
+int nfs4_have_delegated_attributes(struct inode *);
#endif /* __LINUX_FS_NFS_NFS4_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This keeps all the v3 code together and separate from the rest of the
NFS code.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 4 ++--
fs/nfs/{nfs3acl.c => nfs3/acl.c} | 2 +-
fs/nfs/{nfs3proc.c => nfs3/proc.c} | 4 ++--
fs/nfs/{nfs3xdr.c => nfs3/xdr.c} | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
rename fs/nfs/{nfs3acl.c => nfs3/acl.c} (99%)
rename fs/nfs/{nfs3proc.c => nfs3/proc.c} (99%)
rename fs/nfs/{nfs3xdr.c => nfs3/xdr.c} (99%)
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 5733451..7d674a0 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,8 +9,8 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
-nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
+nfs-$(CONFIG_NFS_V3) += nfs3/proc.o nfs3/xdr.o
+nfs-$(CONFIG_NFS_V3_ACL) += nfs3/acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3/acl.c
similarity index 99%
rename from fs/nfs/nfs3acl.c
rename to fs/nfs/nfs3/acl.c
index 7ef2397..ac589ff 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3/acl.c
@@ -6,7 +6,7 @@
#include <linux/posix_acl_xattr.h>
#include <linux/nfsacl.h>
-#include "internal.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3/proc.c
similarity index 99%
rename from fs/nfs/nfs3proc.c
rename to fs/nfs/nfs3/proc.c
index d4bc9ed9..f37ddb9 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3/proc.c
@@ -18,8 +18,8 @@
#include <linux/lockd/bind.h>
#include <linux/nfs_mount.h>
-#include "iostat.h"
-#include "internal.h"
+#include "../iostat.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3/xdr.c
similarity index 99%
rename from fs/nfs/nfs3xdr.c
rename to fs/nfs/nfs3/xdr.c
index 183c6b1..be27fb8 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3/xdr.c
@@ -20,7 +20,7 @@
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/nfsacl.h>
-#include "internal.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_XDR
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This gives v4 a chance to clean up the client idr structure.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 10 +++++++++-
fs/nfs/nfs.h | 1 +
fs/nfs/nfs2/client.c | 4 ++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs2/nfs2.h | 1 +
fs/nfs/nfs3/client.c | 4 ++++
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs3/nfs3.h | 1 +
fs/nfs/nfs4/nfs4.h | 1 +
9 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a4b7634..1b84962 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -140,6 +140,7 @@ static struct nfs_subversion nfs_v4_mod = {
.validate_mount_data = nfs4_validate_text_mount_data,
.init_aclclient = nfs4_init_aclclient,
.alloc_client = nfs4_alloc_client,
+ .put_client = nfs4_put_client,
.try_mount = nfs4_try_mount,
.shutdown_client = nfs4_shutdown_client,
.have_delegation = nfs4_have_delegation,
@@ -314,6 +315,11 @@ static void nfs4_destroy_server(struct nfs_server *server)
nfs4_purge_state_owners(server);
}
+void nfs4_put_client(struct nfs_client *clp)
+{
+ nfs_cb_idr_remove(clp);
+}
+
#else
void nfs_cleanup_cb_ident_idr(void)
@@ -363,6 +369,7 @@ static void nfs_free_client(struct nfs_client *clp)
*/
void nfs_put_client(struct nfs_client *clp)
{
+ struct nfs_subversion *nfs_mod;
if (!clp)
return;
@@ -370,7 +377,8 @@ void nfs_put_client(struct nfs_client *clp)
if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
list_del(&clp->cl_share_link);
- nfs_cb_idr_remove(clp);
+ nfs_mod = get_nfs_client_version(clp);
+ nfs_mod->put_client(clp);
spin_unlock(&nfs_client_lock);
BUG_ON(!list_empty(&clp->cl_superblocks));
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index b2a930d..455bacf 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -37,6 +37,7 @@ struct nfs_subversion {
const char *);
void (*init_aclclient)(struct nfs_server *);
int (*alloc_client)(struct nfs_client *, const struct nfs_client_initdata *);
+ void (*put_client)(struct nfs_client *);
struct dentry *(*try_mount)(struct file_system_type *, int,
const char *, struct nfs_fh *,
struct nfs_parsed_mount_data *);
diff --git a/fs/nfs/nfs2/client.c b/fs/nfs/nfs2/client.c
index 36d6499..935473f 100644
--- a/fs/nfs/nfs2/client.c
+++ b/fs/nfs/nfs2/client.c
@@ -16,3 +16,7 @@ int nfs2_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *
{
return 0;
}
+
+void nfs2_put_client(struct nfs_client *clp)
+{
+}
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index e527001..1d68721 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -43,6 +43,7 @@ struct nfs_subversion nfs_v2 = {
.validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs2_init_aclclient,
.alloc_client = nfs2_alloc_client,
+ .put_client = nfs2_put_client,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs2_shutdown_client,
.have_delegation = nfs2_no_delegation,
diff --git a/fs/nfs/nfs2/nfs2.h b/fs/nfs/nfs2/nfs2.h
index 2ce1245..838d6f1 100644
--- a/fs/nfs/nfs2/nfs2.h
+++ b/fs/nfs/nfs2/nfs2.h
@@ -11,6 +11,7 @@ extern const struct nfs_rpc_ops nfs_v2_clientops;
void nfs2_init_aclclient(struct nfs_server *);
int nfs2_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
+void nfs2_put_client(struct nfs_client *);
extern const struct inode_operations nfs_file_inode_operations;
extern const struct file_operations nfs_file_operations;
diff --git a/fs/nfs/nfs3/client.c b/fs/nfs/nfs3/client.c
index 4aa2024..1e9ac0e 100644
--- a/fs/nfs/nfs3/client.c
+++ b/fs/nfs/nfs3/client.c
@@ -60,3 +60,7 @@ int nfs3_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *
{
return 0;
}
+
+void nfs3_put_client(struct nfs_client *clp)
+{
+}
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index a63dbe7..a6b62b2 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -43,6 +43,7 @@ struct nfs_subversion nfs_v3 = {
.validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs3_init_aclclient,
.alloc_client = nfs3_alloc_client,
+ .put_client = nfs3_put_client,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs3_shutdown_client,
.have_delegation = nfs3_no_delegation,
diff --git a/fs/nfs/nfs3/nfs3.h b/fs/nfs/nfs3/nfs3.h
index d43df84..091cf79 100644
--- a/fs/nfs/nfs3/nfs3.h
+++ b/fs/nfs/nfs3/nfs3.h
@@ -11,6 +11,7 @@ extern struct nfs_rpc_ops nfs_v3_clientops;
void nfs3_init_aclclient(struct nfs_server *);
int nfs3_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
+void nfs3_put_client(struct nfs_client *);
extern const struct inode_operations nfs3_file_inode_operations;
extern const struct file_operations nfs3_file_operations;
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 37f12d6..0b1cf87 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -15,5 +15,6 @@ struct dentry *nfs4_try_mount(struct file_system_type *, int, const char *,
int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
struct nfs_fh *, const char *);
int nfs4_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
+void nfs4_put_client(struct nfs_client *);
#endif /* __LINUX_FS_NFS_NFS4_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
Otherwise there would be a bunch of "symbol not defined" errors.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/dir.c | 1 +
fs/nfs/inode.c | 3 +++
2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 6b2813b..a5e3a36 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2138,6 +2138,7 @@ void nfs_access_zap_cache(struct inode *inode)
spin_unlock(&nfs_access_lru_lock);
nfs_access_free_list(&head);
}
+EXPORT_SYMBOL_GPL(nfs_access_zap_cache);
static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred)
{
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 35db7b8..cf2bab9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -185,6 +185,7 @@ void nfs_zap_acl_cache(struct inode *inode)
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;
spin_unlock(&inode->i_lock);
}
+EXPORT_SYMBOL_GPL(nfs_zap_acl_cache);
void nfs_invalidate_atime(struct inode *inode)
{
@@ -850,6 +851,7 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
return NFS_STALE(inode) ? -ESTALE : 0;
return __nfs_revalidate_inode(server, inode);
}
+EXPORT_SYMBOL_GPL(nfs_revalidate_inode);
static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
{
@@ -1146,6 +1148,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
spin_unlock(&inode->i_lock);
return status;
}
+EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
/**
* nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This code is all nfs v4-only, so it shouldn't need to exist in the
generic nfs client. I move it to the v4 subdirectory so it can
eventually compile as part of the v4 module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 632 --------------------------------------------------
fs/nfs/nfs4/client.c | 617 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 617 insertions(+), 632 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 8e053a4..2c3f50e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -60,36 +60,6 @@ static LIST_HEAD(nfs_versions);
static LIST_HEAD(nfs_client_list);
static LIST_HEAD(nfs_volume_list);
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
-#ifdef CONFIG_NFS_V4
-static DEFINE_SPINLOCK(nfs_idr_lock);
-static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_idr_lock */
-
-/*
- * Get a unique NFSv4.0 callback identifier which will be used
- * by the V4.0 callback service to lookup the nfs_client struct
- */
-static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
-{
- int ret = 0;
-
- if (clp->rpc_ops->version != 4 || minorversion != 0)
- return ret;
-retry:
- if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL))
- return -ENOMEM;
- spin_lock(&nfs_idr_lock);
- ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident);
- spin_unlock(&nfs_idr_lock);
- if (ret == -EAGAIN)
- goto retry;
- return ret;
-}
-#endif /* CONFIG_NFS_V4 */
-
-/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static int nfs4_disable_idmapping = 0;
/*
* RPC cruft for NFS
@@ -167,25 +137,6 @@ void unregister_nfs_version(struct nfs_subversion *nfs)
}
EXPORT_SYMBOL_GPL(unregister_nfs_version);
-#ifdef CONFIG_NFS_V4
-int nfs4_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
-{
- int err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
- if (err)
- return err;
-
- spin_lock_init(&clp->cl_lock);
- INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
- clp->cl_boot_time = CURRENT_TIME;
- clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
- clp->cl_minorversion = cl_init->minorversion;
- clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
-
- return 0;
-}
-#endif
-
/*
* Allocate a shared client record
*
@@ -240,43 +191,6 @@ error_0:
return ERR_PTR(err);
}
-#ifdef CONFIG_NFS_V4
-/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
-void nfs_cleanup_cb_ident_idr(void)
-{
- idr_destroy(&cb_ident_idr);
-}
-
-static void nfs_cb_idr_remove(struct nfs_client *clp)
-{
- spin_lock(&nfs_idr_lock);
- if (clp->cl_cb_ident)
- idr_remove(&cb_ident_idr, clp->cl_cb_ident);
- spin_unlock(&nfs_idr_lock);
-}
-
-static void nfs4_destroy_server(struct nfs_server *server)
-{
- nfs4_purge_state_owners(server);
-}
-
-void nfs4_put_client(struct nfs_client *clp)
-{
- nfs_cb_idr_remove(clp);
-}
-
-#else
-
-void nfs_cleanup_cb_ident_idr(void)
-{
-}
-
-static void nfs_cb_idr_remove(struct nfs_client *clp)
-{
-}
-
-#endif /* CONFIG_NFS_V4 */
-
/*
* Destroy a shared client record
*/
@@ -437,30 +351,6 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
return 0;
}
-/* Common match routine for v4.0 and v4.1 callback services */
-bool
-nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp,
- u32 minorversion)
-{
- struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
-
- /* Don't match clients that failed to initialise */
- if (!(clp->cl_cons_state == NFS_CS_READY ||
- clp->cl_cons_state == NFS_CS_SESSION_INITING))
- return false;
-
- /* Match the version and minorversion */
- if (clp->rpc_ops->version != 4 ||
- clp->cl_minorversion != minorversion)
- return false;
-
- /* Match only the IP address, not the port number */
- if (!nfs_sockaddr_match_ipaddr(addr, clap))
- return false;
-
- return true;
-}
-
/*
* Find an nfs_client on the list that matches the initialisation data
* that is supplied.
@@ -1170,524 +1060,6 @@ error:
return ERR_PTR(error);
}
-#ifdef CONFIG_NFS_V4
-/*
- * NFSv4.0 callback thread helper
- *
- * Find a client by IP address, protocol version, and minorversion
- *
- * Called from the pg_authenticate method. The callback identifier
- * is not used as it has not been decoded.
- *
- * Returns NULL if no such client
- */
-struct nfs_client *
-nfs4_find_client_no_ident(const struct sockaddr *addr)
-{
- struct nfs_client *clp;
- struct list_head *cl_list = nfs_client_list_start();
-
- list_for_each_entry(clp, cl_list, cl_share_link) {
- if (nfs4_cb_match_client(addr, clp, 0) == false)
- continue;
- atomic_inc(&clp->cl_count);
- goto out;
- }
- clp = NULL;
-out:
- nfs_client_list_end();
- return clp;
-}
-
-/*
- * NFSv4.0 callback thread helper
- *
- * Find a client by callback identifier
- */
-struct nfs_client *
-nfs4_find_client_ident(int cb_ident)
-{
- struct nfs_client *clp;
-
- spin_lock(&nfs_idr_lock);
- clp = idr_find(&cb_ident_idr, cb_ident);
- if (clp) {
- if (!atomic_inc_not_zero(&clp->cl_count))
- clp = NULL;
- }
- spin_unlock(&nfs_idr_lock);
- return clp;
-}
-
-#if defined(CONFIG_NFS_V4_1)
-/*
- * NFSv4.1 callback thread helper
- * For CB_COMPOUND calls, find a client by IP address, protocol version,
- * minorversion, and sessionID
- *
- * Returns NULL if no such client
- */
-struct nfs_client *
-nfs4_find_client_sessionid(const struct sockaddr *addr,
- struct nfs4_sessionid *sid)
-{
- struct nfs_client *clp;
-
- spin_lock(&nfs_client_lock);
- list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
- if (nfs4_cb_match_client(addr, clp, 1) == false)
- continue;
-
- if (!nfs4_has_session(clp))
- continue;
-
- /* Match sessionid*/
- if (memcmp(clp->cl_session->sess_id.data,
- sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
- continue;
-
- atomic_inc(&clp->cl_count);
- spin_unlock(&nfs_client_lock);
- return clp;
- }
- spin_unlock(&nfs_client_lock);
- return NULL;
-}
-
-#else /* CONFIG_NFS_V4_1 */
-
-struct nfs_client *
-nfs4_find_client_sessionid(const struct sockaddr *addr,
- struct nfs4_sessionid *sid)
-{
- return NULL;
-}
-#endif /* CONFIG_NFS_V4_1 */
-
-/*
- * Initialize the NFS4 callback service
- */
-static int nfs4_init_callback(struct nfs_client *clp)
-{
- int error;
-
- if (clp->rpc_ops->version == 4) {
- if (nfs4_has_session(clp)) {
- error = xprt_setup_backchannel(
- clp->cl_rpcclient->cl_xprt,
- NFS41_BC_MIN_CALLBACKS);
- if (error < 0)
- return error;
- }
-
- error = nfs_callback_up(clp->cl_mvops->minor_version,
- clp->cl_rpcclient->cl_xprt);
- if (error < 0) {
- dprintk("%s: failed to start callback. Error = %d\n",
- __func__, error);
- return error;
- }
- __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
- }
- return 0;
-}
-
-/*
- * Initialize the minor version specific parts of an NFS4 client record
- */
-static int nfs4_init_client_minor_version(struct nfs_client *clp)
-{
-#if defined(CONFIG_NFS_V4_1)
- if (clp->cl_mvops->minor_version) {
- struct nfs4_session *session = NULL;
- /*
- * Create the session and mark it expired.
- * When a SEQUENCE operation encounters the expired session
- * it will do session recovery to initialize it.
- */
- session = nfs4_alloc_session(clp);
- if (!session)
- return -ENOMEM;
-
- clp->cl_session = session;
- /*
- * The create session reply races with the server back
- * channel probe. Mark the client NFS_CS_SESSION_INITING
- * so that the client back channel can find the
- * nfs_client struct
- */
- clp->cl_cons_state = NFS_CS_SESSION_INITING;
- }
-#endif /* CONFIG_NFS_V4_1 */
-
- return nfs4_init_callback(clp);
-}
-
-/*
- * Initialise an NFS4 client record
- */
-int nfs4_init_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- const char *ip_addr,
- rpc_authflavor_t authflavour,
- int noresvport)
-{
- int error;
-
- if (clp->cl_cons_state == NFS_CS_READY) {
- /* the client is initialised already */
- dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
- return 0;
- }
-
- /* Check NFS protocol revision and initialize RPC op vector */
- clp->rpc_ops = &nfs_v4_clientops;
-
- error = nfs_create_rpc_client(clp, timeparms, authflavour,
- 1, noresvport);
- if (error < 0)
- goto error;
- strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
-
- error = nfs_idmap_new(clp);
- if (error < 0) {
- dprintk("%s: failed to create idmapper. Error = %d\n",
- __func__, error);
- goto error;
- }
- __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
-
- error = nfs4_init_client_minor_version(clp);
- if (error < 0)
- goto error;
-
- if (!nfs4_has_session(clp))
- nfs_mark_client_ready(clp, NFS_CS_READY);
- return 0;
-
-error:
- nfs_mark_client_ready(clp, error);
- dprintk("<-- nfs4_init_client() = xerror %d\n", error);
- return error;
-}
-
-/*
- * Set up an NFS4 client
- */
-static int nfs4_set_client(struct nfs_server *server,
- const char *hostname,
- const struct sockaddr *addr,
- const size_t addrlen,
- const char *ip_addr,
- rpc_authflavor_t authflavour,
- int proto, const struct rpc_timeout *timeparms,
- u32 minorversion)
-{
- struct nfs_client_initdata cl_init = {
- .hostname = hostname,
- .addr = addr,
- .addrlen = addrlen,
- .rpc_ops = &nfs_v4_clientops,
- .proto = proto,
- .minorversion = minorversion,
- };
- struct nfs_client *clp;
- int error;
-
- dprintk("--> nfs4_set_client()\n");
-
- /* Allocate or find a client reference we can use */
- clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
- server->flags & NFS_MOUNT_NORESVPORT);
- if (IS_ERR(clp)) {
- error = PTR_ERR(clp);
- goto error;
- }
-
- /*
- * Query for the lease time on clientid setup or renewal
- *
- * Note that this will be set on nfs_clients that were created
- * only for the DS role and did not set this bit, but now will
- * serve a dual role.
- */
- set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
-
- server->nfs_client = clp;
- dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
- return 0;
-error:
- dprintk("<-- nfs4_set_client() = xerror %d\n", error);
- return error;
-}
-
-/*
- * Set up a pNFS Data Server client.
- *
- * Return any existing nfs_client that matches server address,port,version
- * and minorversion.
- *
- * For a new nfs_client, use a soft mount (default), a low retrans and a
- * low timeout interval so that if a connection is lost, we retry through
- * the MDS.
- */
-struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
- const struct sockaddr *ds_addr,
- int ds_addrlen, int ds_proto)
-{
- struct nfs_client_initdata cl_init = {
- .addr = ds_addr,
- .addrlen = ds_addrlen,
- .rpc_ops = &nfs_v4_clientops,
- .proto = ds_proto,
- .minorversion = mds_clp->cl_minorversion,
- };
- struct rpc_timeout ds_timeout = {
- .to_initval = 15 * HZ,
- .to_maxval = 15 * HZ,
- .to_retries = 1,
- .to_exponential = 1,
- };
- struct nfs_client *clp;
-
- /*
- * Set an authflavor equual to the MDS value. Use the MDS nfs_client
- * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
- * (section 13.1 RFC 5661).
- */
- clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
- mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
-
- dprintk("<-- %s %p\n", __func__, clp);
- return clp;
-}
-EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
-
-/*
- * Session has been established, and the client marked ready.
- * Set the mount rsize and wsize with negotiated fore channel
- * attributes which will be bound checked in nfs_server_set_fsinfo.
- */
-static void nfs4_session_set_rwsize(struct nfs_server *server)
-{
-#ifdef CONFIG_NFS_V4_1
- struct nfs4_session *sess;
- u32 server_resp_sz;
- u32 server_rqst_sz;
-
- if (!nfs4_has_session(server->nfs_client))
- return;
- sess = server->nfs_client->cl_session;
- server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
- server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
-
- if (server->rsize > server_resp_sz)
- server->rsize = server_resp_sz;
- if (server->wsize > server_rqst_sz)
- server->wsize = server_rqst_sz;
-#endif /* CONFIG_NFS_V4_1 */
-}
-
-static int nfs4_server_common_setup(struct nfs_server *server,
- struct nfs_fh *mntfh)
-{
- struct nfs_fattr *fattr;
- int error;
-
- BUG_ON(!server->nfs_client);
- BUG_ON(!server->nfs_client->rpc_ops);
- BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
- /* data servers support only a subset of NFSv4.1 */
- if (is_ds_only_client(server->nfs_client))
- return -EPROTONOSUPPORT;
-
- fattr = nfs_alloc_fattr();
- if (fattr == NULL)
- return -ENOMEM;
-
- /* We must ensure the session is initialised first */
- error = nfs4_init_session(server);
- if (error < 0)
- goto out;
-
- /* Probe the root fh to retrieve its FSID and filehandle */
- error = nfs4_get_rootfh(server, mntfh);
- if (error < 0)
- goto out;
-
- dprintk("Server FSID: %llx:%llx\n",
- (unsigned long long) server->fsid.major,
- (unsigned long long) server->fsid.minor);
- dprintk("Mount FH: %d\n", mntfh->size);
-
- nfs4_session_set_rwsize(server);
-
- error = nfs_probe_fsinfo(server, mntfh, fattr);
- if (error < 0)
- goto out;
-
- if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
- server->namelen = NFS4_MAXNAMLEN;
-
- nfs_server_insert_lists(server);
- server->mount_time = jiffies;
- server->destroy = nfs4_destroy_server;
-out:
- nfs_free_fattr(fattr);
- return error;
-}
-
-/*
- * Create a version 4 volume record
- */
-static int nfs4_init_server(struct nfs_server *server,
- const struct nfs_parsed_mount_data *data)
-{
- struct rpc_timeout timeparms;
- int error;
-
- dprintk("--> nfs4_init_server()\n");
-
- nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
- data->timeo, data->retrans);
-
- /* Initialise the client representation from the mount data */
- server->flags = data->flags;
- server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
- if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
- server->caps |= NFS_CAP_READDIRPLUS;
- server->options = data->options;
-
- /* Get a client record */
- error = nfs4_set_client(server,
- data->nfs_server.hostname,
- (const struct sockaddr *)&data->nfs_server.address,
- data->nfs_server.addrlen,
- data->client_address,
- data->auth_flavors[0],
- data->nfs_server.protocol,
- &timeparms,
- data->minorversion);
- if (error < 0)
- goto error;
-
- /*
- * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
- * authentication.
- */
- if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
- server->caps |= NFS_CAP_UIDGID_NOMAP;
-
- if (data->rsize)
- server->rsize = nfs_block_size(data->rsize, NULL);
- if (data->wsize)
- server->wsize = nfs_block_size(data->wsize, NULL);
-
- server->acregmin = data->acregmin * HZ;
- server->acregmax = data->acregmax * HZ;
- server->acdirmin = data->acdirmin * HZ;
- server->acdirmax = data->acdirmax * HZ;
-
- server->port = data->nfs_server.port;
-
- error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
-
-error:
- /* Done */
- dprintk("<-- nfs4_init_server() = %d\n", error);
- return error;
-}
-
-/*
- * Create a version 4 volume record
- * - keyed on server and FSID
- */
-struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
- struct nfs_fh *mntfh)
-{
- struct nfs_server *server;
- int error;
-
- dprintk("--> nfs4_create_server()\n");
-
- server = nfs4_alloc_server();
- if (!server)
- return ERR_PTR(-ENOMEM);
-
- /* set up the general RPC client */
- error = nfs4_init_server(server, data);
- if (error < 0)
- goto error;
-
- error = nfs4_server_common_setup(server, mntfh);
- if (error < 0)
- goto error;
-
- dprintk("<-- nfs4_create_server() = %p\n", server);
- return server;
-
-error:
- nfs_free_server(server);
- dprintk("<-- nfs4_create_server() = error %d\n", error);
- return ERR_PTR(error);
-}
-
-/*
- * Create an NFS4 referral server record
- */
-struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
- struct nfs_fh *mntfh)
-{
- struct nfs_client *parent_client;
- struct nfs_server *server, *parent_server;
- int error;
-
- dprintk("--> nfs4_create_referral_server()\n");
-
- server = nfs4_alloc_server();
- if (!server)
- return ERR_PTR(-ENOMEM);
-
- parent_server = NFS_SB(data->sb);
- parent_client = parent_server->nfs_client;
-
- /* Initialise the client representation from the parent server */
- nfs_server_copy_userdata(server, parent_server);
- server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
-
- /* Get a client representation.
- * Note: NFSv4 always uses TCP, */
- error = nfs4_set_client(server, data->hostname,
- data->addr,
- data->addrlen,
- parent_client->cl_ipaddr,
- data->authflavor,
- parent_server->client->cl_xprt->prot,
- parent_server->client->cl_timeout,
- parent_client->cl_mvops->minor_version);
- if (error < 0)
- goto error;
-
- error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
- if (error < 0)
- goto error;
-
- error = nfs4_server_common_setup(server, mntfh);
- if (error < 0)
- goto error;
-
- dprintk("<-- nfs_create_referral_server() = %p\n", server);
- return server;
-
-error:
- nfs_free_server(server);
- dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
- return ERR_PTR(error);
-}
-
-#endif /* CONFIG_NFS_V4 */
-
struct nfs_server *do_nfs_clone_server(struct nfs_server *source,
struct nfs_server *server,
struct nfs_fh *fh,
@@ -2092,7 +1464,3 @@ int nfs_stat_to_errno(enum nfs_stat status)
return nfs_errtbl[i].errno;
}
EXPORT_SYMBOL_GPL(nfs_stat_to_errno);
-
-module_param(nfs4_disable_idmapping, bool, 0644);
-MODULE_PARM_DESC(nfs4_disable_idmapping,
- "Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/nfs4/client.c b/fs/nfs/nfs4/client.c
index 130c6a6..dd40936 100644
--- a/fs/nfs/nfs4/client.c
+++ b/fs/nfs/nfs4/client.c
@@ -1,7 +1,9 @@
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*/
+#include <linux/module.h>
#include <linux/sunrpc/sched.h>
+#include <linux/sunrpc/bc_xprt.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
#include <linux/nfs_idmap.h>
@@ -10,10 +12,19 @@
#include "nfs4_fs.h"
#include "delegation.h"
#include "callback.h"
+#include "../internal.h"
#include "../nfs.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT
+static DEFINE_SPINLOCK(nfs_idr_lock);
+static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_idr_lock */
+
+/*
+ * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
+ */
+static int nfs4_disable_idmapping = 0;
+
void nfs4_init_aclclient(struct nfs_server *server)
{
server->flags &= ~NFS_MOUNT_NOACL;
@@ -33,6 +44,44 @@ static void nfs4_shutdown_session(struct nfs_client *clp)
#endif /* CONFIG_NFS_V4_1 */
/*
+ * Get a unique NFSv4.0 callback identifier which will be used
+ * by the V4.0 callback service to lookup the nfs_client struct
+ */
+static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
+{
+ int ret = 0;
+
+ if (clp->rpc_ops->version != 4 || minorversion != 0)
+ return ret;
+retry:
+ if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL))
+ return -ENOMEM;
+ spin_lock(&nfs_idr_lock);
+ ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident);
+ spin_unlock(&nfs_idr_lock);
+ if (ret == -EAGAIN)
+ goto retry;
+ return ret;
+}
+
+int nfs4_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
+{
+ int err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ if (err)
+ return err;
+
+ spin_lock_init(&clp->cl_lock);
+ INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+ clp->cl_boot_time = CURRENT_TIME;
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
+ clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+
+ return 0;
+}
+
+/*
* Destroy the NFS4 callback service
*/
static void nfs4_destroy_callback(struct nfs_client *clp)
@@ -53,11 +102,36 @@ void nfs4_shutdown_client(struct nfs_client *clp)
rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
}
+/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
+void nfs_cleanup_cb_ident_idr(void)
+{
+ idr_destroy(&cb_ident_idr);
+}
+
+static void nfs_cb_idr_remove(struct nfs_client *clp)
+{
+ spin_lock(&nfs_idr_lock);
+ if (clp->cl_cb_ident)
+ idr_remove(&cb_ident_idr, clp->cl_cb_ident);
+ spin_unlock(&nfs_idr_lock);
+}
+
static void pnfs_init_server(struct nfs_server *server)
{
rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
}
+static void nfs4_destroy_server(struct nfs_server *server)
+{
+ nfs4_purge_state_owners(server);
+}
+
+void nfs4_put_client(struct nfs_client *clp)
+{
+ nfs_cb_idr_remove(clp);
+}
+
+
struct nfs_server *nfs4_alloc_server(void)
{
struct nfs_server *server = nfs_alloc_server();
@@ -81,3 +155,546 @@ struct nfs_server *nfs4_clone_server(struct nfs_server *source,
return ERR_PTR(-ENOMEM);
return do_nfs_clone_server(source, server, fh, fattr);
}
+
+/* Common match routine for v4.0 and v4.1 callback services */
+bool
+nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp,
+ u32 minorversion)
+{
+ struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
+
+ /* Don't match clients that failed to initialise */
+ if (!(clp->cl_cons_state == NFS_CS_READY ||
+ clp->cl_cons_state == NFS_CS_SESSION_INITING))
+ return false;
+
+ /* Match the version and minorversion */
+ if (clp->rpc_ops->version != 4 ||
+ clp->cl_minorversion != minorversion)
+ return false;
+
+ /* Match only the IP address, not the port number */
+ if (!nfs_sockaddr_match_ipaddr(addr, clap))
+ return false;
+
+ return true;
+}
+
+/*
+ * NFSv4.0 callback thread helper
+ *
+ * Find a client by IP address, protocol version, and minorversion
+ *
+ * Called from the pg_authenticate method. The callback identifier
+ * is not used as it has not been decoded.
+ *
+ * Returns NULL if no such client
+ */
+struct nfs_client *
+nfs4_find_client_no_ident(const struct sockaddr *addr)
+{
+ struct nfs_client *clp;
+ struct list_head *cl_list = nfs_client_list_start();
+
+ list_for_each_entry(clp, cl_list, cl_share_link) {
+ if (nfs4_cb_match_client(addr, clp, 0) == false)
+ continue;
+ atomic_inc(&clp->cl_count);
+ goto out;
+ }
+ clp = NULL;
+out:
+ nfs_client_list_end();
+ return clp;
+}
+
+/*
+ * NFSv4.0 callback thread helper
+ *
+ * Find a client by callback identifier
+ */
+struct nfs_client *
+nfs4_find_client_ident(int cb_ident)
+{
+ struct nfs_client *clp;
+
+ spin_lock(&nfs_idr_lock);
+ clp = idr_find(&cb_ident_idr, cb_ident);
+ if (clp) {
+ if (!atomic_inc_not_zero(&clp->cl_count))
+ clp = NULL;
+ }
+ spin_unlock(&nfs_idr_lock);
+ return clp;
+}
+
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * NFSv4.1 callback thread helper
+ * For CB_COMPOUND calls, find a client by IP address, protocol version,
+ * minorversion, and sessionID
+ *
+ * Returns NULL if no such client
+ */
+struct nfs_client *
+nfs4_find_client_sessionid(const struct sockaddr *addr,
+ struct nfs4_sessionid *sid)
+{
+ struct nfs_client *clp;
+
+ spin_lock(&nfs_client_lock);
+ list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+ if (nfs4_cb_match_client(addr, clp, 1) == false)
+ continue;
+
+ if (!nfs4_has_session(clp))
+ continue;
+
+ /* Match sessionid*/
+ if (memcmp(clp->cl_session->sess_id.data,
+ sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
+ continue;
+
+ atomic_inc(&clp->cl_count);
+ spin_unlock(&nfs_client_lock);
+ return clp;
+ }
+ spin_unlock(&nfs_client_lock);
+ return NULL;
+}
+
+#else /* CONFIG_NFS_V4_1 */
+
+struct nfs_client *
+nfs4_find_client_sessionid(const struct sockaddr *addr,
+ struct nfs4_sessionid *sid)
+{
+ return NULL;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * Initialize the NFS4 callback service
+ */
+static int nfs4_init_callback(struct nfs_client *clp)
+{
+ int error;
+
+ if (clp->rpc_ops->version == 4) {
+ if (nfs4_has_session(clp)) {
+ error = xprt_setup_backchannel(
+ clp->cl_rpcclient->cl_xprt,
+ NFS41_BC_MIN_CALLBACKS);
+ if (error < 0)
+ return error;
+ }
+
+ error = nfs_callback_up(clp->cl_mvops->minor_version,
+ clp->cl_rpcclient->cl_xprt);
+ if (error < 0) {
+ dprintk("%s: failed to start callback. Error = %d\n",
+ __func__, error);
+ return error;
+ }
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+ }
+ return 0;
+}
+
+/*
+ * Initialize the minor version specific parts of an NFS4 client record
+ */
+static int nfs4_init_client_minor_version(struct nfs_client *clp)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_mvops->minor_version) {
+ struct nfs4_session *session = NULL;
+ /*
+ * Create the session and mark it expired.
+ * When a SEQUENCE operation encounters the expired session
+ * it will do session recovery to initialize it.
+ */
+ session = nfs4_alloc_session(clp);
+ if (!session)
+ return -ENOMEM;
+
+ clp->cl_session = session;
+ /*
+ * The create session reply races with the server back
+ * channel probe. Mark the client NFS_CS_SESSION_INITING
+ * so that the client back channel can find the
+ * nfs_client struct
+ */
+ clp->cl_cons_state = NFS_CS_SESSION_INITING;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+
+ return nfs4_init_callback(clp);
+}
+
+/*
+ * Initialise an NFS4 client record
+ */
+int nfs4_init_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour,
+ int noresvport)
+{
+ int error;
+
+ if (clp->cl_cons_state == NFS_CS_READY) {
+ /* the client is initialised already */
+ dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
+ return 0;
+ }
+
+ /* Check NFS protocol revision and initialize RPC op vector */
+ clp->rpc_ops = &nfs_v4_clientops;
+
+ error = nfs_create_rpc_client(clp, timeparms, authflavour,
+ 1, noresvport);
+ if (error < 0)
+ goto error;
+ strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+
+ error = nfs_idmap_new(clp);
+ if (error < 0) {
+ dprintk("%s: failed to create idmapper. Error = %d\n",
+ __func__, error);
+ goto error;
+ }
+ __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+
+ error = nfs4_init_client_minor_version(clp);
+ if (error < 0)
+ goto error;
+
+ if (!nfs4_has_session(clp))
+ nfs_mark_client_ready(clp, NFS_CS_READY);
+ return 0;
+
+error:
+ nfs_mark_client_ready(clp, error);
+ dprintk("<-- nfs4_init_client() = xerror %d\n", error);
+ return error;
+}
+
+/*
+ * Set up an NFS4 client
+ */
+static int nfs4_set_client(struct nfs_server *server,
+ const char *hostname,
+ const struct sockaddr *addr,
+ const size_t addrlen,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour,
+ int proto, const struct rpc_timeout *timeparms,
+ u32 minorversion)
+{
+ struct nfs_client_initdata cl_init = {
+ .hostname = hostname,
+ .addr = addr,
+ .addrlen = addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = proto,
+ .minorversion = minorversion,
+ };
+ struct nfs_client *clp;
+ int error;
+
+ dprintk("--> nfs4_set_client()\n");
+
+ /* Allocate or find a client reference we can use */
+ clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
+ server->flags & NFS_MOUNT_NORESVPORT);
+ if (IS_ERR(clp)) {
+ error = PTR_ERR(clp);
+ goto error;
+ }
+
+ /*
+ * Query for the lease time on clientid setup or renewal
+ *
+ * Note that this will be set on nfs_clients that were created
+ * only for the DS role and did not set this bit, but now will
+ * serve a dual role.
+ */
+ set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
+
+ server->nfs_client = clp;
+ dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
+ return 0;
+error:
+ dprintk("<-- nfs4_set_client() = xerror %d\n", error);
+ return error;
+}
+
+/*
+ * Set up a pNFS Data Server client.
+ *
+ * Return any existing nfs_client that matches server address,port,version
+ * and minorversion.
+ *
+ * For a new nfs_client, use a soft mount (default), a low retrans and a
+ * low timeout interval so that if a connection is lost, we retry through
+ * the MDS.
+ */
+struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+ const struct sockaddr *ds_addr,
+ int ds_addrlen, int ds_proto)
+{
+ struct nfs_client_initdata cl_init = {
+ .addr = ds_addr,
+ .addrlen = ds_addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = ds_proto,
+ .minorversion = mds_clp->cl_minorversion,
+ };
+ struct rpc_timeout ds_timeout = {
+ .to_initval = 15 * HZ,
+ .to_maxval = 15 * HZ,
+ .to_retries = 1,
+ .to_exponential = 1,
+ };
+ struct nfs_client *clp;
+
+ /*
+ * Set an authflavor equual to the MDS value. Use the MDS nfs_client
+ * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
+ * (section 13.1 RFC 5661).
+ */
+ clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
+ mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
+
+ dprintk("<-- %s %p\n", __func__, clp);
+ return clp;
+}
+EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
+
+/*
+ * Session has been established, and the client marked ready.
+ * Set the mount rsize and wsize with negotiated fore channel
+ * attributes which will be bound checked in nfs_server_set_fsinfo.
+ */
+static void nfs4_session_set_rwsize(struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ struct nfs4_session *sess;
+ u32 server_resp_sz;
+ u32 server_rqst_sz;
+
+ if (!nfs4_has_session(server->nfs_client))
+ return;
+ sess = server->nfs_client->cl_session;
+ server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
+ server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
+
+ if (server->rsize > server_resp_sz)
+ server->rsize = server_resp_sz;
+ if (server->wsize > server_rqst_sz)
+ server->wsize = server_rqst_sz;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+static int nfs4_server_common_setup(struct nfs_server *server,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_fattr *fattr;
+ int error;
+
+ BUG_ON(!server->nfs_client);
+ BUG_ON(!server->nfs_client->rpc_ops);
+ BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+ /* data servers support only a subset of NFSv4.1 */
+ if (is_ds_only_client(server->nfs_client))
+ return -EPROTONOSUPPORT;
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL)
+ return -ENOMEM;
+
+ /* We must ensure the session is initialised first */
+ error = nfs4_init_session(server);
+ if (error < 0)
+ goto out;
+
+ /* Probe the root fh to retrieve its FSID and filehandle */
+ error = nfs4_get_rootfh(server, mntfh);
+ if (error < 0)
+ goto out;
+
+ dprintk("Server FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+ dprintk("Mount FH: %d\n", mntfh->size);
+
+ nfs4_session_set_rwsize(server);
+
+ error = nfs_probe_fsinfo(server, mntfh, fattr);
+ if (error < 0)
+ goto out;
+
+ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+ server->namelen = NFS4_MAXNAMLEN;
+
+ nfs_server_insert_lists(server);
+ server->mount_time = jiffies;
+ server->destroy = nfs4_destroy_server;
+out:
+ nfs_free_fattr(fattr);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ */
+static int nfs4_init_server(struct nfs_server *server,
+ const struct nfs_parsed_mount_data *data)
+{
+ struct rpc_timeout timeparms;
+ int error;
+
+ dprintk("--> nfs4_init_server()\n");
+
+ nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
+ data->timeo, data->retrans);
+
+ /* Initialise the client representation from the mount data */
+ server->flags = data->flags;
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+ if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+ server->caps |= NFS_CAP_READDIRPLUS;
+ server->options = data->options;
+
+ /* Get a client record */
+ error = nfs4_set_client(server,
+ data->nfs_server.hostname,
+ (const struct sockaddr *)&data->nfs_server.address,
+ data->nfs_server.addrlen,
+ data->client_address,
+ data->auth_flavors[0],
+ data->nfs_server.protocol,
+ &timeparms,
+ data->minorversion);
+ if (error < 0)
+ goto error;
+
+ /*
+ * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
+ * authentication.
+ */
+ if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
+ server->caps |= NFS_CAP_UIDGID_NOMAP;
+
+ if (data->rsize)
+ server->rsize = nfs_block_size(data->rsize, NULL);
+ if (data->wsize)
+ server->wsize = nfs_block_size(data->wsize, NULL);
+
+ server->acregmin = data->acregmin * HZ;
+ server->acregmax = data->acregmax * HZ;
+ server->acdirmin = data->acdirmin * HZ;
+ server->acdirmax = data->acdirmax * HZ;
+
+ server->port = data->nfs_server.port;
+
+ error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+
+error:
+ /* Done */
+ dprintk("<-- nfs4_init_server() = %d\n", error);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_server *server;
+ int error;
+
+ dprintk("--> nfs4_create_server()\n");
+
+ server = nfs4_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ /* set up the general RPC client */
+ error = nfs4_init_server(server, data);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs4_create_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 referral server record
+ */
+struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_client *parent_client;
+ struct nfs_server *server, *parent_server;
+ int error;
+
+ dprintk("--> nfs4_create_referral_server()\n");
+
+ server = nfs4_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ parent_server = NFS_SB(data->sb);
+ parent_client = parent_server->nfs_client;
+
+ /* Initialise the client representation from the parent server */
+ nfs_server_copy_userdata(server, parent_server);
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
+
+ /* Get a client representation.
+ * Note: NFSv4 always uses TCP, */
+ error = nfs4_set_client(server, data->hostname,
+ data->addr,
+ data->addrlen,
+ parent_client->cl_ipaddr,
+ data->authflavor,
+ parent_server->client->cl_xprt->prot,
+ parent_server->client->cl_timeout,
+ parent_client->cl_mvops->minor_version);
+ if (error < 0)
+ goto error;
+
+ error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs_create_referral_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+ "Turn off NFSv4 idmapping when using 'sec=sys'");
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
These functions are needed by the nfs4_fs_type object, so move them into
the v4 subdirectory to compile it all together.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/nfs4/super.c | 731 +++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/super.c | 724 --------------------------------------------------
3 files changed, 732 insertions(+), 725 deletions(-)
create mode 100644 fs/nfs/nfs4/super.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 6bb7470..34f752d 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/callback_proc.o nfs4/namespace.o \
nfs4/client.o nfs4/module.o nfs4/sysctl.o \
nfs4/getroot.o nfs4/inode.o nfs4/file.o \
- nfs4/dir.o
+ nfs4/dir.o nfs4/super.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/nfs4/super.c b/fs/nfs/nfs4/super.c
new file mode 100644
index 0000000..12efb65
--- /dev/null
+++ b/fs/nfs/nfs4/super.c
@@ -0,0 +1,731 @@
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/nfs_fs.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs_sb.h>
+
+#include "delegation.h"
+#include "../internal.h"
+#include "../fscache.h"
+#include "../nfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_VFS
+
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+static void nfs4_kill_super(struct super_block *sb);
+
+struct file_system_type nfs4_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct file_system_type nfs4_remote_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_remote_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs4_xdev_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_xdev_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct file_system_type nfs4_remote_referral_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_remote_referral_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs4_referral_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_referral_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static const struct super_operations nfs4_sops = {
+ .alloc_inode = nfs_alloc_inode,
+ .destroy_inode = nfs_destroy_inode,
+ .write_inode = nfs_write_inode,
+ .put_super = nfs_put_super,
+ .statfs = nfs_statfs,
+ .evict_inode = nfs4_evict_inode,
+ .umount_begin = nfs_umount_begin,
+ .show_options = nfs_show_options,
+ .show_devname = nfs_show_devname,
+ .show_path = nfs_show_path,
+ .show_stats = nfs_show_stats,
+ .remount_fs = nfs_remount,
+};
+
+/*
+ * Finish setting up a cloned NFS4 superblock
+ */
+static void nfs4_clone_super(struct super_block *sb,
+ const struct super_block *old_sb)
+{
+ sb->s_blocksize_bits = old_sb->s_blocksize_bits;
+ sb->s_blocksize = old_sb->s_blocksize;
+ sb->s_maxbytes = old_sb->s_maxbytes;
+ sb->s_time_gran = 1;
+ sb->s_op = old_sb->s_op;
+ /*
+ * The VFS shouldn't apply the umask to mode bits. We will do
+ * so ourselves when necessary.
+ */
+ sb->s_flags |= MS_POSIXACL;
+ sb->s_xattr = old_sb->s_xattr;
+ nfs_initialise_sb(sb);
+}
+
+/*
+ * Set up an NFS4 superblock
+ */
+static void nfs4_fill_super(struct super_block *sb)
+{
+ sb->s_time_gran = 1;
+ sb->s_op = &nfs4_sops;
+ /*
+ * The VFS shouldn't apply the umask to mode bits. We will do
+ * so ourselves when necessary.
+ */
+ sb->s_flags |= MS_POSIXACL;
+ sb->s_xattr = nfs4_xattr_handlers;
+ nfs_initialise_sb(sb);
+}
+
+static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
+{
+ args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
+ NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
+}
+
+int nfs4_validate_text_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ struct nfs_fh *mntfh,
+ const char *dev_name)
+{
+ struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+
+ nfs_set_port(sap, &args->nfs_server.port, NFS_PORT);
+
+ nfs_validate_transport_protocol(args);
+
+ nfs4_validate_mount_flags(args);
+
+ if (args->version != 4) {
+ dfprintk(MOUNT,
+ "NFS4: Illegal mount version\n");
+ return -EINVAL;
+ }
+
+ if (args->auth_flavor_len > 1) {
+ dfprintk(MOUNT,
+ "NFS4: Too many RPC auth flavours specified\n");
+ return -EINVAL;
+ }
+
+ if (args->client_address == NULL) {
+ dfprintk(MOUNT,
+ "NFS4: mount program didn't pass callback address\n");
+ return -EINVAL;
+ }
+
+ return nfs_parse_devname(dev_name,
+ &args->nfs_server.hostname,
+ NFS4_MAXNAMLEN,
+ &args->nfs_server.export_path,
+ NFS4_MAXPATHLEN);
+}
+
+/*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ const char *dev_name)
+{
+ struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+ struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
+ char *c;
+
+ if (data == NULL)
+ goto out_no_data;
+
+ switch (data->version) {
+ case 1:
+ if (data->host_addrlen > sizeof(args->nfs_server.address))
+ goto out_no_address;
+ if (data->host_addrlen == 0)
+ goto out_no_address;
+ args->nfs_server.addrlen = data->host_addrlen;
+ if (copy_from_user(sap, data->host_addr, data->host_addrlen))
+ return -EFAULT;
+ if (!nfs_verify_server_address(sap))
+ goto out_no_address;
+
+ if (data->auth_flavourlen) {
+ if (data->auth_flavourlen > 1)
+ goto out_inval_auth;
+ if (copy_from_user(&args->auth_flavors[0],
+ data->auth_flavours,
+ sizeof(args->auth_flavors[0])))
+ return -EFAULT;
+ }
+
+ c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->nfs_server.hostname = c;
+
+ c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->nfs_server.export_path = c;
+ dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);
+
+ c = strndup_user(data->client_addr.data, 16);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->client_address = c;
+
+ /*
+ * Translate to nfs_parsed_mount_data, which nfs4_fill_super
+ * can deal with.
+ */
+
+ args->flags = data->flags & NFS4_MOUNT_FLAGMASK;
+ args->rsize = data->rsize;
+ args->wsize = data->wsize;
+ args->timeo = data->timeo;
+ args->retrans = data->retrans;
+ args->acregmin = data->acregmin;
+ args->acregmax = data->acregmax;
+ args->acdirmin = data->acdirmin;
+ args->acdirmax = data->acdirmax;
+ args->nfs_server.protocol = data->proto;
+ nfs_validate_transport_protocol(args);
+
+ break;
+ default:
+ if (nfs_parse_mount_options((char *)options, args) == 0)
+ return -EINVAL;
+
+ if (!nfs_verify_server_address(sap))
+ return -EINVAL;
+
+ return nfs4_validate_text_mount_data(options, args, NULL, dev_name);
+ }
+
+ return 0;
+
+out_no_data:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+ return -EINVAL;
+
+out_inval_auth:
+ dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+ data->auth_flavourlen);
+ return -EINVAL;
+
+out_no_address:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+ return -EINVAL;
+}
+
+/*
+ * Get the superblock for the NFS4 root partition
+ */
+static struct dentry *
+nfs4_remote_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data = raw_data;
+ struct super_block *s;
+ struct nfs_server *server;
+ struct nfs_fh *mntfh;
+ struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
+ int error = -ENOMEM;
+
+ mntfh = nfs_alloc_fhandle();
+ if (data == NULL || mntfh == NULL)
+ goto out;
+
+ /* Get a volume representation */
+ server = nfs4_create_server(data, mntfh);
+ if (IS_ERR(server)) {
+ error = PTR_ERR(server);
+ goto out;
+ }
+ sb_mntdata.server = server;
+
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
+ /* -o noac implies -o sync */
+ if (server->flags & NFS_MOUNT_NOAC)
+ sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
+ /* Get a superblock - note that we may end up sharing one that already exists */
+ s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto out_free;
+ }
+
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
+ } else {
+ error = nfs_bdi_register(server);
+ if (error)
+ goto error_splat_bdi;
+ }
+
+ if (!s->s_root) {
+ /* initial superblock/root creation */
+ nfs4_fill_super(s);
+ nfs_fscache_get_super_cookie(
+ s, data ? data->fscache_uniq : NULL, NULL);
+ }
+
+ mntroot = nfs4_get_root(s, mntfh, dev_name);
+ if (IS_ERR(mntroot)) {
+ error = PTR_ERR(mntroot);
+ goto error_splat_super;
+ }
+
+ error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+ if (error)
+ goto error_splat_root;
+
+ s->s_flags |= MS_ACTIVE;
+
+ nfs_free_fhandle(mntfh);
+ return mntroot;
+
+out:
+ nfs_free_fhandle(mntfh);
+ return ERR_PTR(error);
+
+out_free:
+ nfs_free_server(server);
+ goto out;
+
+error_splat_root:
+ dput(mntroot);
+error_splat_super:
+ if (server && !s->s_root)
+ bdi_unregister(&server->backing_dev_info);
+error_splat_bdi:
+ deactivate_locked_super(s);
+ goto out;
+}
+
+static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
+ int flags, void *data, const char *hostname)
+{
+ struct vfsmount *root_mnt;
+ char *root_devname;
+ size_t len;
+
+ len = strlen(hostname) + 3;
+ root_devname = kmalloc(len, GFP_KERNEL);
+ if (root_devname == NULL)
+ return ERR_PTR(-ENOMEM);
+ snprintf(root_devname, len, "%s:/", hostname);
+ root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
+ kfree(root_devname);
+ return root_mnt;
+}
+
+struct nfs_referral_count {
+ struct list_head list;
+ const struct task_struct *task;
+ unsigned int referral_count;
+};
+
+static LIST_HEAD(nfs_referral_count_list);
+static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
+
+static struct nfs_referral_count *nfs_find_referral_count(void)
+{
+ struct nfs_referral_count *p;
+
+ list_for_each_entry(p, &nfs_referral_count_list, list) {
+ if (p->task == current)
+ return p;
+ }
+ return NULL;
+}
+
+#define NFS_MAX_NESTED_REFERRALS 2
+
+static int nfs_referral_loop_protect(void)
+{
+ struct nfs_referral_count *p, *new;
+ int ret = -ENOMEM;
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ goto out;
+ new->task = current;
+ new->referral_count = 1;
+
+ ret = 0;
+ spin_lock(&nfs_referral_count_list_lock);
+ p = nfs_find_referral_count();
+ if (p != NULL) {
+ if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
+ ret = -ELOOP;
+ else
+ p->referral_count++;
+ } else {
+ list_add(&new->list, &nfs_referral_count_list);
+ new = NULL;
+ }
+ spin_unlock(&nfs_referral_count_list_lock);
+ kfree(new);
+out:
+ return ret;
+}
+
+static void nfs_referral_loop_unprotect(void)
+{
+ struct nfs_referral_count *p;
+
+ spin_lock(&nfs_referral_count_list_lock);
+ p = nfs_find_referral_count();
+ p->referral_count--;
+ if (p->referral_count == 0)
+ list_del(&p->list);
+ else
+ p = NULL;
+ spin_unlock(&nfs_referral_count_list_lock);
+ kfree(p);
+}
+
+static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
+ const char *export_path)
+{
+ struct dentry *dentry;
+ int ret = nfs_referral_loop_protect();
+
+ if (ret) {
+ mntput(root_mnt);
+ return ERR_PTR(ret);
+ }
+
+ dentry = mount_subtree(root_mnt, export_path);
+ nfs_referral_loop_unprotect();
+
+ return dentry;
+}
+
+struct dentry *nfs4_try_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
+{
+ char *export_path;
+ struct vfsmount *root_mnt;
+ struct dentry *res;
+
+ dfprintk(MOUNT, "--> nfs4_try_mount()\n");
+
+ export_path = data->nfs_server.export_path;
+ data->nfs_server.export_path = "/";
+ root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, data,
+ data->nfs_server.hostname);
+ data->nfs_server.export_path = export_path;
+
+ res = ERR_CAST(root_mnt);
+ if (!IS_ERR(root_mnt))
+ res = nfs_follow_remote_path(root_mnt, export_path);
+
+ dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
+ IS_ERR(res) ? PTR_ERR(res) : 0,
+ IS_ERR(res) ? " [error]" : "");
+ return res;
+}
+
+/*
+ * Get the superblock for an NFS4 mountpoint
+ */
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data;
+ int error = -ENOMEM;
+ struct dentry *res = ERR_PTR(-ENOMEM);
+
+ data = nfs_alloc_parsed_mount_data(4);
+ if (data == NULL)
+ goto out;
+
+ /* Validate the mount data */
+ error = nfs4_validate_mount_data(raw_data, data, dev_name);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out;
+ }
+
+ res = nfs4_try_mount(fs_type, flags, dev_name, NULL, data);
+ if (IS_ERR(res))
+ error = PTR_ERR(res);
+
+out:
+ nfs_free_parsed_mount_data(data);
+ dprintk("<-- nfs4_mount() = %d%s\n", error,
+ error != 0 ? " [error]" : "");
+ return res;
+}
+
+static void nfs4_kill_super(struct super_block *sb)
+{
+ struct nfs_server *server = NFS_SB(sb);
+
+ dprintk("--> %s\n", __func__);
+ nfs_super_return_all_delegations(sb);
+ kill_anon_super(sb);
+ nfs_fscache_release_super_cookie(sb);
+ nfs_free_server(server);
+ dprintk("<-- %s\n", __func__);
+}
+
+/*
+ * Clone an NFS4 server record on xdev traversal (FSID-change)
+ */
+static struct dentry *
+nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ struct super_block *s;
+ struct nfs_server *server;
+ struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
+ int error;
+
+ dprintk("--> nfs4_xdev_mount()\n");
+
+ /* create a new volume representation */
+ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ if (IS_ERR(server)) {
+ error = PTR_ERR(server);
+ goto out_err_noserver;
+ }
+ sb_mntdata.server = server;
+
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
+ /* -o noac implies -o sync */
+ if (server->flags & NFS_MOUNT_NOAC)
+ sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
+ /* Get a superblock - note that we may end up sharing one that already exists */
+ s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto out_err_nosb;
+ }
+
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
+ } else {
+ error = nfs_bdi_register(server);
+ if (error)
+ goto error_splat_bdi;
+ }
+
+ if (!s->s_root) {
+ /* initial superblock/root creation */
+ nfs4_clone_super(s, data->sb);
+ nfs_fscache_get_super_cookie(s, NULL, data);
+ }
+
+ mntroot = nfs4_get_root(s, data->fh, dev_name);
+ if (IS_ERR(mntroot)) {
+ error = PTR_ERR(mntroot);
+ goto error_splat_super;
+ }
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
+ dput(mntroot);
+ error = -ESTALE;
+ goto error_splat_super;
+ }
+
+ s->s_flags |= MS_ACTIVE;
+
+ security_sb_clone_mnt_opts(data->sb, s);
+
+ dprintk("<-- nfs4_xdev_mount() = 0\n");
+ return mntroot;
+
+out_err_nosb:
+ nfs_free_server(server);
+out_err_noserver:
+ dprintk("<-- nfs4_xdev_mount() = %d [error]\n", error);
+ return ERR_PTR(error);
+
+error_splat_super:
+ if (server && !s->s_root)
+ bdi_unregister(&server->backing_dev_info);
+error_splat_bdi:
+ deactivate_locked_super(s);
+ dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error);
+ return ERR_PTR(error);
+}
+
+static struct dentry *
+nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ struct super_block *s;
+ struct nfs_server *server;
+ struct dentry *mntroot;
+ struct nfs_fh *mntfh;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
+ int error = -ENOMEM;
+
+ dprintk("--> nfs4_referral_get_sb()\n");
+
+ mntfh = nfs_alloc_fhandle();
+ if (mntfh == NULL)
+ goto out_err_nofh;
+
+ /* create a new volume representation */
+ server = nfs4_create_referral_server(data, mntfh);
+ if (IS_ERR(server)) {
+ error = PTR_ERR(server);
+ goto out_err_noserver;
+ }
+ sb_mntdata.server = server;
+
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
+ /* -o noac implies -o sync */
+ if (server->flags & NFS_MOUNT_NOAC)
+ sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
+ /* Get a superblock - note that we may end up sharing one that already exists */
+ s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto out_err_nosb;
+ }
+
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
+ } else {
+ error = nfs_bdi_register(server);
+ if (error)
+ goto error_splat_bdi;
+ }
+
+ if (!s->s_root) {
+ /* initial superblock/root creation */
+ nfs4_fill_super(s);
+ nfs_fscache_get_super_cookie(s, NULL, data);
+ }
+
+ mntroot = nfs4_get_root(s, mntfh, dev_name);
+ if (IS_ERR(mntroot)) {
+ error = PTR_ERR(mntroot);
+ goto error_splat_super;
+ }
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
+ dput(mntroot);
+ error = -ESTALE;
+ goto error_splat_super;
+ }
+
+ s->s_flags |= MS_ACTIVE;
+
+ security_sb_clone_mnt_opts(data->sb, s);
+
+ nfs_free_fhandle(mntfh);
+ dprintk("<-- nfs4_referral_get_sb() = 0\n");
+ return mntroot;
+
+out_err_nosb:
+ nfs_free_server(server);
+out_err_noserver:
+ nfs_free_fhandle(mntfh);
+out_err_nofh:
+ dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
+ return ERR_PTR(error);
+
+error_splat_super:
+ if (server && !s->s_root)
+ bdi_unregister(&server->backing_dev_info);
+error_splat_bdi:
+ deactivate_locked_super(s);
+ nfs_free_fhandle(mntfh);
+ dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
+ return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 server record on referral traversal
+ */
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ char *export_path;
+ struct vfsmount *root_mnt;
+ struct dentry *res;
+
+ dprintk("--> nfs4_referral_mount()\n");
+
+ export_path = data->mnt_path;
+ data->mnt_path = "/";
+
+ root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
+ flags, data, data->hostname);
+ data->mnt_path = export_path;
+
+ res = ERR_CAST(root_mnt);
+ if (!IS_ERR(root_mnt))
+ res = nfs_follow_remote_path(root_mnt, export_path);
+ dprintk("<-- nfs4_referral_mount() = %ld%s\n",
+ IS_ERR(res) ? PTR_ERR(res) : 0,
+ IS_ERR(res) ? " [error]" : "");
+ return res;
+}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a06347d..7bab19e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -299,75 +299,6 @@ static const struct super_operations nfs_sops = {
.remount_fs = nfs_remount,
};
-#ifdef CONFIG_NFS_V4
-static struct dentry *nfs4_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static void nfs4_kill_super(struct super_block *sb);
-
-struct file_system_type nfs4_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static struct file_system_type nfs4_remote_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-struct file_system_type nfs4_xdev_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_xdev_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static struct file_system_type nfs4_remote_referral_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_referral_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-struct file_system_type nfs4_referral_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_referral_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static const struct super_operations nfs4_sops = {
- .alloc_inode = nfs_alloc_inode,
- .destroy_inode = nfs_destroy_inode,
- .write_inode = nfs_write_inode,
- .put_super = nfs_put_super,
- .statfs = nfs_statfs,
- .evict_inode = nfs4_evict_inode,
- .umount_begin = nfs_umount_begin,
- .show_options = nfs_show_options,
- .show_devname = nfs_show_devname,
- .show_path = nfs_show_path,
- .show_stats = nfs_show_stats,
- .remount_fs = nfs_remount,
-};
-#endif
-
static struct shrinker acl_shrinker = {
.shrink = nfs_access_cache_shrinker,
.seeks = DEFAULT_SEEKS,
@@ -2456,658 +2387,3 @@ error_splat_bdi:
dprintk("<-- nfs_xdev_mount() = %d [splat]\n", error);
return ERR_PTR(error);
}
-
-#ifdef CONFIG_NFS_V4
-
-/*
- * Finish setting up a cloned NFS4 superblock
- */
-static void nfs4_clone_super(struct super_block *sb,
- const struct super_block *old_sb)
-{
- sb->s_blocksize_bits = old_sb->s_blocksize_bits;
- sb->s_blocksize = old_sb->s_blocksize;
- sb->s_maxbytes = old_sb->s_maxbytes;
- sb->s_time_gran = 1;
- sb->s_op = old_sb->s_op;
- /*
- * The VFS shouldn't apply the umask to mode bits. We will do
- * so ourselves when necessary.
- */
- sb->s_flags |= MS_POSIXACL;
- sb->s_xattr = old_sb->s_xattr;
- nfs_initialise_sb(sb);
-}
-
-/*
- * Set up an NFS4 superblock
- */
-static void nfs4_fill_super(struct super_block *sb)
-{
- sb->s_time_gran = 1;
- sb->s_op = &nfs4_sops;
- /*
- * The VFS shouldn't apply the umask to mode bits. We will do
- * so ourselves when necessary.
- */
- sb->s_flags |= MS_POSIXACL;
- sb->s_xattr = nfs4_xattr_handlers;
- nfs_initialise_sb(sb);
-}
-
-static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
-{
- args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
- NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
-}
-
-int nfs4_validate_text_mount_data(void *options,
- struct nfs_parsed_mount_data *args,
- struct nfs_fh *mntfh,
- const char *dev_name)
-{
- struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
-
- nfs_set_port(sap, &args->nfs_server.port, NFS_PORT);
-
- nfs_validate_transport_protocol(args);
-
- nfs4_validate_mount_flags(args);
-
- if (args->version != 4) {
- dfprintk(MOUNT,
- "NFS4: Illegal mount version\n");
- return -EINVAL;
- }
-
- if (args->auth_flavor_len > 1) {
- dfprintk(MOUNT,
- "NFS4: Too many RPC auth flavours specified\n");
- return -EINVAL;
- }
-
- if (args->client_address == NULL) {
- dfprintk(MOUNT,
- "NFS4: mount program didn't pass callback address\n");
- return -EINVAL;
- }
-
- return nfs_parse_devname(dev_name,
- &args->nfs_server.hostname,
- NFS4_MAXNAMLEN,
- &args->nfs_server.export_path,
- NFS4_MAXPATHLEN);
-}
-
-/*
- * Validate NFSv4 mount options
- */
-static int nfs4_validate_mount_data(void *options,
- struct nfs_parsed_mount_data *args,
- const char *dev_name)
-{
- struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
- struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
- char *c;
-
- if (data == NULL)
- goto out_no_data;
-
- switch (data->version) {
- case 1:
- if (data->host_addrlen > sizeof(args->nfs_server.address))
- goto out_no_address;
- if (data->host_addrlen == 0)
- goto out_no_address;
- args->nfs_server.addrlen = data->host_addrlen;
- if (copy_from_user(sap, data->host_addr, data->host_addrlen))
- return -EFAULT;
- if (!nfs_verify_server_address(sap))
- goto out_no_address;
-
- if (data->auth_flavourlen) {
- if (data->auth_flavourlen > 1)
- goto out_inval_auth;
- if (copy_from_user(&args->auth_flavors[0],
- data->auth_flavours,
- sizeof(args->auth_flavors[0])))
- return -EFAULT;
- }
-
- c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->nfs_server.hostname = c;
-
- c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->nfs_server.export_path = c;
- dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);
-
- c = strndup_user(data->client_addr.data, 16);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->client_address = c;
-
- /*
- * Translate to nfs_parsed_mount_data, which nfs4_fill_super
- * can deal with.
- */
-
- args->flags = data->flags & NFS4_MOUNT_FLAGMASK;
- args->rsize = data->rsize;
- args->wsize = data->wsize;
- args->timeo = data->timeo;
- args->retrans = data->retrans;
- args->acregmin = data->acregmin;
- args->acregmax = data->acregmax;
- args->acdirmin = data->acdirmin;
- args->acdirmax = data->acdirmax;
- args->nfs_server.protocol = data->proto;
- nfs_validate_transport_protocol(args);
-
- break;
- default:
- if (nfs_parse_mount_options((char *)options, args) == 0)
- return -EINVAL;
-
- if (!nfs_verify_server_address(sap))
- return -EINVAL;
-
- return nfs4_validate_text_mount_data(options, args, NULL, dev_name);
- }
-
- return 0;
-
-out_no_data:
- dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
- return -EINVAL;
-
-out_inval_auth:
- dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
- data->auth_flavourlen);
- return -EINVAL;
-
-out_no_address:
- dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
- return -EINVAL;
-}
-
-/*
- * Get the superblock for the NFS4 root partition
- */
-static struct dentry *
-nfs4_remote_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_parsed_mount_data *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct nfs_fh *mntfh;
- struct dentry *mntroot;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error = -ENOMEM;
-
- mntfh = nfs_alloc_fhandle();
- if (data == NULL || mntfh == NULL)
- goto out;
-
- /* Get a volume representation */
- server = nfs4_create_server(data, mntfh);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_free;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_bdi_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs4_fill_super(s);
- nfs_fscache_get_super_cookie(
- s, data ? data->fscache_uniq : NULL, NULL);
- }
-
- mntroot = nfs4_get_root(s, mntfh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
-
- error = security_sb_set_mnt_opts(s, &data->lsm_opts);
- if (error)
- goto error_splat_root;
-
- s->s_flags |= MS_ACTIVE;
-
- nfs_free_fhandle(mntfh);
- return mntroot;
-
-out:
- nfs_free_fhandle(mntfh);
- return ERR_PTR(error);
-
-out_free:
- nfs_free_server(server);
- goto out;
-
-error_splat_root:
- dput(mntroot);
-error_splat_super:
- if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
-error_splat_bdi:
- deactivate_locked_super(s);
- goto out;
-}
-
-static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
- int flags, void *data, const char *hostname)
-{
- struct vfsmount *root_mnt;
- char *root_devname;
- size_t len;
-
- len = strlen(hostname) + 3;
- root_devname = kmalloc(len, GFP_KERNEL);
- if (root_devname == NULL)
- return ERR_PTR(-ENOMEM);
- snprintf(root_devname, len, "%s:/", hostname);
- root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
- kfree(root_devname);
- return root_mnt;
-}
-
-struct nfs_referral_count {
- struct list_head list;
- const struct task_struct *task;
- unsigned int referral_count;
-};
-
-static LIST_HEAD(nfs_referral_count_list);
-static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
-
-static struct nfs_referral_count *nfs_find_referral_count(void)
-{
- struct nfs_referral_count *p;
-
- list_for_each_entry(p, &nfs_referral_count_list, list) {
- if (p->task == current)
- return p;
- }
- return NULL;
-}
-
-#define NFS_MAX_NESTED_REFERRALS 2
-
-static int nfs_referral_loop_protect(void)
-{
- struct nfs_referral_count *p, *new;
- int ret = -ENOMEM;
-
- new = kmalloc(sizeof(*new), GFP_KERNEL);
- if (!new)
- goto out;
- new->task = current;
- new->referral_count = 1;
-
- ret = 0;
- spin_lock(&nfs_referral_count_list_lock);
- p = nfs_find_referral_count();
- if (p != NULL) {
- if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
- ret = -ELOOP;
- else
- p->referral_count++;
- } else {
- list_add(&new->list, &nfs_referral_count_list);
- new = NULL;
- }
- spin_unlock(&nfs_referral_count_list_lock);
- kfree(new);
-out:
- return ret;
-}
-
-static void nfs_referral_loop_unprotect(void)
-{
- struct nfs_referral_count *p;
-
- spin_lock(&nfs_referral_count_list_lock);
- p = nfs_find_referral_count();
- p->referral_count--;
- if (p->referral_count == 0)
- list_del(&p->list);
- else
- p = NULL;
- spin_unlock(&nfs_referral_count_list_lock);
- kfree(p);
-}
-
-static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
- const char *export_path)
-{
- struct dentry *dentry;
- int ret = nfs_referral_loop_protect();
-
- if (ret) {
- mntput(root_mnt);
- return ERR_PTR(ret);
- }
-
- dentry = mount_subtree(root_mnt, export_path);
- nfs_referral_loop_unprotect();
-
- return dentry;
-}
-
-struct dentry *nfs4_try_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, struct nfs_fh *mntfh,
- struct nfs_parsed_mount_data *data)
-{
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
-
- dfprintk(MOUNT, "--> nfs4_try_mount()\n");
-
- export_path = data->nfs_server.export_path;
- data->nfs_server.export_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, data,
- data->nfs_server.hostname);
- data->nfs_server.export_path = export_path;
-
- res = ERR_CAST(root_mnt);
- if (!IS_ERR(root_mnt))
- res = nfs_follow_remote_path(root_mnt, export_path);
-
- dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
- IS_ERR(res) ? PTR_ERR(res) : 0,
- IS_ERR(res) ? " [error]" : "");
- return res;
-}
-
-/*
- * Get the superblock for an NFS4 mountpoint
- */
-static struct dentry *nfs4_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
-{
- struct nfs_parsed_mount_data *data;
- int error = -ENOMEM;
- struct dentry *res = ERR_PTR(-ENOMEM);
-
- data = nfs_alloc_parsed_mount_data(4);
- if (data == NULL)
- goto out;
-
- /* Validate the mount data */
- error = nfs4_validate_mount_data(raw_data, data, dev_name);
- if (error < 0) {
- res = ERR_PTR(error);
- goto out;
- }
-
- res = nfs4_try_mount(fs_type, flags, dev_name, NULL, data);
- if (IS_ERR(res))
- error = PTR_ERR(res);
-
-out:
- nfs_free_parsed_mount_data(data);
- dprintk("<-- nfs4_mount() = %d%s\n", error,
- error != 0 ? " [error]" : "");
- return res;
-}
-
-static void nfs4_kill_super(struct super_block *sb)
-{
- struct nfs_server *server = NFS_SB(sb);
-
- dprintk("--> %s\n", __func__);
- nfs_super_return_all_delegations(sb);
- kill_anon_super(sb);
- nfs_fscache_release_super_cookie(sb);
- nfs_free_server(server);
- dprintk("<-- %s\n", __func__);
-}
-
-/*
- * Clone an NFS4 server record on xdev traversal (FSID-change)
- */
-static struct dentry *
-nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct dentry *mntroot;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error;
-
- dprintk("--> nfs4_xdev_mount()\n");
-
- /* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out_err_noserver;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_err_nosb;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_bdi_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs4_clone_super(s, data->sb);
- nfs_fscache_get_super_cookie(s, NULL, data);
- }
-
- mntroot = nfs4_get_root(s, data->fh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
- if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
- dput(mntroot);
- error = -ESTALE;
- goto error_splat_super;
- }
-
- s->s_flags |= MS_ACTIVE;
-
- security_sb_clone_mnt_opts(data->sb, s);
-
- dprintk("<-- nfs4_xdev_mount() = 0\n");
- return mntroot;
-
-out_err_nosb:
- nfs_free_server(server);
-out_err_noserver:
- dprintk("<-- nfs4_xdev_mount() = %d [error]\n", error);
- return ERR_PTR(error);
-
-error_splat_super:
- if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
-error_splat_bdi:
- deactivate_locked_super(s);
- dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error);
- return ERR_PTR(error);
-}
-
-static struct dentry *
-nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct dentry *mntroot;
- struct nfs_fh *mntfh;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error = -ENOMEM;
-
- dprintk("--> nfs4_referral_get_sb()\n");
-
- mntfh = nfs_alloc_fhandle();
- if (mntfh == NULL)
- goto out_err_nofh;
-
- /* create a new volume representation */
- server = nfs4_create_referral_server(data, mntfh);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out_err_noserver;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_err_nosb;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_bdi_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs4_fill_super(s);
- nfs_fscache_get_super_cookie(s, NULL, data);
- }
-
- mntroot = nfs4_get_root(s, mntfh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
- if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
- dput(mntroot);
- error = -ESTALE;
- goto error_splat_super;
- }
-
- s->s_flags |= MS_ACTIVE;
-
- security_sb_clone_mnt_opts(data->sb, s);
-
- nfs_free_fhandle(mntfh);
- dprintk("<-- nfs4_referral_get_sb() = 0\n");
- return mntroot;
-
-out_err_nosb:
- nfs_free_server(server);
-out_err_noserver:
- nfs_free_fhandle(mntfh);
-out_err_nofh:
- dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
- return ERR_PTR(error);
-
-error_splat_super:
- if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
-error_splat_bdi:
- deactivate_locked_super(s);
- nfs_free_fhandle(mntfh);
- dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
- return ERR_PTR(error);
-}
-
-/*
- * Create an NFS4 server record on referral traversal
- */
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
-
- dprintk("--> nfs4_referral_mount()\n");
-
- export_path = data->mnt_path;
- data->mnt_path = "/";
-
- root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
- flags, data, data->hostname);
- data->mnt_path = export_path;
-
- res = ERR_CAST(root_mnt);
- if (!IS_ERR(root_mnt))
- res = nfs_follow_remote_path(root_mnt, export_path);
- dprintk("<-- nfs4_referral_mount() = %ld%s\n",
- IS_ERR(res) ? PTR_ERR(res) : 0,
- IS_ERR(res) ? " [error]" : "");
- return res;
-}
-
-#endif /* CONFIG_NFS_V4 */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
v2 and v3 don't have pnfs, so I can move the pnfs_init_server() function
to the nfs4 client code to keep it separate from the generic client.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 61 ++++++++++++++++++++++++-------------------------
fs/nfs/nfs.h | 5 ++++
fs/nfs/nfs4/client.c | 32 ++++++++++++++++++++++++++
fs/nfs/nfs4/nfs4.h | 2 +
fs/nfs/nfs4/super.c | 3 +-
5 files changed, 71 insertions(+), 32 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index dd6453b..778ef62 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -42,6 +42,7 @@
#include <asm/system.h>
+#include "nfs4/nfs4.h"
#include "nfs4/nfs4_fs.h"
#include "nfs4/callback.h"
#include "nfs4/delegation.h"
@@ -254,11 +255,6 @@ static void nfs_cb_idr_remove(struct nfs_client *clp)
spin_unlock(&nfs_idr_lock);
}
-static void pnfs_init_server(struct nfs_server *server)
-{
- rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
-}
-
static void nfs4_destroy_server(struct nfs_server *server)
{
nfs4_purge_state_owners(server);
@@ -279,10 +275,6 @@ static void nfs_cb_idr_remove(struct nfs_client *clp)
{
}
-static void pnfs_init_server(struct nfs_server *server)
-{
-}
-
#endif /* CONFIG_NFS_V4 */
/*
@@ -1041,7 +1033,7 @@ static void nfs_server_remove_lists(struct nfs_server *server)
/*
* Allocate and initialise a server record
*/
-static struct nfs_server *nfs_alloc_server(void)
+struct nfs_server *nfs_alloc_server(void)
{
struct nfs_server *server;
@@ -1072,10 +1064,9 @@ static struct nfs_server *nfs_alloc_server(void)
return NULL;
}
- pnfs_init_server(server);
-
return server;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_server);
/*
* Free up a server record
@@ -1611,7 +1602,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
dprintk("--> nfs4_create_server()\n");
- server = nfs_alloc_server();
+ server = nfs4_alloc_server();
if (!server)
return ERR_PTR(-ENOMEM);
@@ -1645,7 +1636,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
dprintk("--> nfs4_create_referral_server()\n");
- server = nfs_alloc_server();
+ server = nfs4_alloc_server();
if (!server)
return ERR_PTR(-ENOMEM);
@@ -1688,27 +1679,15 @@ error:
#endif /* CONFIG_NFS_V4 */
-/*
- * Clone an NFS2, NFS3 or NFS4 server record
- */
-struct nfs_server *nfs_clone_server(struct nfs_server *source,
- struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+struct nfs_server *do_nfs_clone_server(struct nfs_server *source,
+ struct nfs_server *server,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr)
{
- struct nfs_server *server;
struct nfs_fattr *fattr_fsinfo;
struct nfs_subversion *nfs_mod;
- int error;
-
- dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
- (unsigned long long) fattr->fsid.major,
- (unsigned long long) fattr->fsid.minor);
-
- server = nfs_alloc_server();
- if (!server)
- return ERR_PTR(-ENOMEM);
+ int error = -ENOMEM;
- error = -ENOMEM;
fattr_fsinfo = nfs_alloc_fattr();
if (fattr_fsinfo == NULL)
goto out_free_server;
@@ -1760,6 +1739,26 @@ out_free_server:
dprintk("<-- nfs_clone_server() = error %d\n", error);
return ERR_PTR(error);
}
+EXPORT_SYMBOL_GPL(do_nfs_clone_server);
+
+/*
+ * Clone an NFS2 or NFS3 server record
+ */
+struct nfs_server *nfs_clone_server(struct nfs_server *source,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr)
+{
+ struct nfs_server *server;
+ dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
+ (unsigned long long) fattr->fsid.major,
+ (unsigned long long) fattr->fsid.minor);
+
+ server = nfs_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+ return do_nfs_clone_server(source, server, fh, fattr);
+}
+
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_fs_nfs;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 55ea4d7..13321fd 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -62,6 +62,11 @@ struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);
+/* Exported in client.c */
+struct nfs_server *nfs_alloc_server(void);
+struct nfs_server *do_nfs_clone_server(struct nfs_server *, struct nfs_server *,
+ struct nfs_fh *, struct nfs_fattr *);
+
/* Exported in dir.c */
int nfs_lookup_revalidate(struct dentry *, struct nameidata *);
int nfs_dentry_delete(const struct dentry *);
diff --git a/fs/nfs/nfs4/client.c b/fs/nfs/nfs4/client.c
index 9f53f3f..130c6a6 100644
--- a/fs/nfs/nfs4/client.c
+++ b/fs/nfs/nfs4/client.c
@@ -10,6 +10,9 @@
#include "nfs4_fs.h"
#include "delegation.h"
#include "callback.h"
+#include "../nfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_CLIENT
void nfs4_init_aclclient(struct nfs_server *server)
{
@@ -49,3 +52,32 @@ void nfs4_shutdown_client(struct nfs_client *clp)
rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
}
+
+static void pnfs_init_server(struct nfs_server *server)
+{
+ rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
+}
+
+struct nfs_server *nfs4_alloc_server(void)
+{
+ struct nfs_server *server = nfs_alloc_server();
+ if (server)
+ pnfs_init_server(server);
+ return server;
+}
+
+struct nfs_server *nfs4_clone_server(struct nfs_server *source,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr)
+{
+ struct nfs_server *server;
+
+ dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
+ (unsigned long long) fattr->fsid.major,
+ (unsigned long long) fattr->fsid.minor);
+
+ server = nfs4_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+ return do_nfs_clone_server(source, server, fh, fattr);
+}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index c24fb13..111ba82 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -7,6 +7,8 @@ extern struct file_system_type nfs4_fs_type;
int init_nfs_v4(void);
void exit_nfs_v4(void);
+struct nfs_server *nfs4_alloc_server(void);
+struct nfs_server *nfs4_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
void nfs4_init_aclclient(struct nfs_server *);
void nfs4_shutdown_client(struct nfs_client *);
diff --git a/fs/nfs/nfs4/super.c b/fs/nfs/nfs4/super.c
index 12efb65..a8aa3f3 100644
--- a/fs/nfs/nfs4/super.c
+++ b/fs/nfs/nfs4/super.c
@@ -5,6 +5,7 @@
#include <linux/sunrpc/sched.h>
#include <linux/nfs_fs_sb.h>
+#include "nfs4.h"
#include "delegation.h"
#include "../internal.h"
#include "../fscache.h"
@@ -537,7 +538,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
dprintk("--> nfs4_xdev_mount()\n");
/* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ server = nfs4_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
if (IS_ERR(server)) {
error = PTR_ERR(server);
goto out_err_noserver;
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
So it can be used by the module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/file.c | 32 --------------------------------
fs/nfs/nfs4/file.c | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 39 insertions(+), 33 deletions(-)
create mode 100644 fs/nfs/nfs4/file.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 94d8631..041f947 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -14,7 +14,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
nfs4/client.o nfs4/module.o nfs4/sysctl.o \
- nfs4/getroot.o nfs4/inode.o
+ nfs4/getroot.o nfs4/inode.o nfs4/file.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index a691996..2728f4e 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -844,35 +844,3 @@ int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
return -EINVAL;
}
EXPORT_SYMBOL_GPL(nfs_setlease);
-
-#ifdef CONFIG_NFS_V4
-static int
-nfs4_file_open(struct inode *inode, struct file *filp)
-{
- /*
- * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
- * this point, then something is very wrong
- */
- dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
- return -ENOTDIR;
-}
-
-const struct file_operations nfs4_file_operations = {
- .llseek = nfs_file_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
- .mmap = nfs_file_mmap,
- .open = nfs4_file_open,
- .flush = nfs_file_flush,
- .release = nfs_file_release,
- .fsync = nfs_file_fsync,
- .lock = nfs_lock,
- .flock = nfs_flock,
- .splice_read = nfs_file_splice_read,
- .splice_write = nfs_file_splice_write,
- .check_flags = nfs_check_flags,
- .setlease = nfs_setlease,
-};
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs4/file.c b/fs/nfs/nfs4/file.c
new file mode 100644
index 0000000..6b6a4c8
--- /dev/null
+++ b/fs/nfs/nfs4/file.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include <linux/fs.h>
+#include <linux/nfs_fs.h>
+#include "../nfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_FILE
+
+static int
+nfs4_file_open(struct inode *inode, struct file *filp)
+{
+ /*
+ * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
+ * this point, then something is very wrong
+ */
+ dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
+ return -ENOTDIR;
+}
+
+const struct file_operations nfs4_file_operations = {
+ .llseek = nfs_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
+ .mmap = nfs_file_mmap,
+ .open = nfs4_file_open,
+ .flush = nfs_file_flush,
+ .release = nfs_file_release,
+ .fsync = nfs_file_fsync,
+ .lock = nfs_lock,
+ .flock = nfs_flock,
+ .splice_read = nfs_file_splice_read,
+ .splice_write = nfs_file_splice_write,
+ .check_flags = nfs_check_flags,
+ .setlease = nfs_setlease,
+};
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
You need to run `modprobe nfs3` before you can use it.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 3 +-
fs/nfs/client.c | 43 +----------------------------------
fs/nfs/dir.c | 21 -----------------
fs/nfs/file.c | 12 ---------
fs/nfs/nfs3/Makefile | 6 +++++
fs/nfs/nfs3/acl.c | 3 ++
fs/nfs/nfs3/client.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs3/dir.c | 34 +++++++++++++++++++++++++++
fs/nfs/nfs3/file.c | 34 +++++++++++++++++++++++++++
fs/nfs/nfs3/module.c | 46 +++++++++++++++++++++++++++++++++++++
fs/nfs/nfs3/nfs3.h | 32 ++++++++++++++++++++++++++
fs/nfs/nfs3/proc.c | 7 +++--
include/linux/nfs_xdr.h | 3 --
14 files changed, 220 insertions(+), 84 deletions(-)
create mode 100644 fs/nfs/nfs3/Makefile
create mode 100644 fs/nfs/nfs3/client.c
create mode 100644 fs/nfs/nfs3/dir.c
create mode 100644 fs/nfs/nfs3/file.c
create mode 100644 fs/nfs/nfs3/module.c
create mode 100644 fs/nfs/nfs3/nfs3.h
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index b28e56f..57c4b19 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -39,7 +39,7 @@ config NFS_V2
If unsure, say Y.
config NFS_V3
- bool "NFS client support for NFS version 3"
+ tristate "NFS client support for NFS version 3"
depends on NFS_FS
help
This option enables support for version 3 of the NFS protocol
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7d674a0..cfd238e 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,8 +9,6 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V3) += nfs3/proc.o nfs3/xdr.o
-nfs-$(CONFIG_NFS_V3_ACL) += nfs3/acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
@@ -23,5 +21,6 @@ obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
obj-$(CONFIG_NFS_V2) += nfs2/
+obj-$(CONFIG_NFS_V3) += nfs3/
obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 20cfc99..ffb5994 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -129,18 +129,6 @@ static void nfs_module_null_function(void)
}
#endif
-#if IS_ENABLED(CONFIG_NFS_V3)
-static struct nfs_subversion nfs_v3_mod = {
- .version = 3,
- .rpc_vers = &nfs_version3,
- .rpc_ops = &nfs_v3_clientops,
-
- .reference = nfs_module_null_function,
- .unreference = nfs_module_null_function,
- .init_aclclient = nfs_init_server_aclclient,
-};
-#endif /* CONFIG_NFS_V3 */
-
#ifdef CONFIG_NFS_V4
static struct nfs_subversion nfs_v4_mod = {
.version = 4,
@@ -153,21 +141,6 @@ static struct nfs_subversion nfs_v4_mod = {
};
#endif /* CONFIG_NFS_V4 */
-#ifdef CONFIG_NFS_V3_ACL
-static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
-static struct rpc_version * nfsacl_version[] = {
- [3] = &nfsacl_version3,
-};
-
-struct rpc_program nfsacl_program = {
- .name = "nfsacl",
- .number = NFS_ACL_PROGRAM,
- .nrvers = ARRAY_SIZE(nfsacl_version),
- .version = nfsacl_version,
- .stats = &nfsacl_rpcstat,
-};
-#endif /* CONFIG_NFS_V3_ACL */
-
struct nfs_client_initdata {
const char *hostname;
const struct sockaddr *addr;
@@ -238,9 +211,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
*/
void __init nfs_register_versions(void)
{
-#if IS_ENABLED(CONFIG_NFS_V3)
- register_nfs_version(&nfs_v3_mod);
-#endif
#ifdef CONFIG_NFS_V4
register_nfs_version(&nfs_v4_mod);
#endif
@@ -836,18 +806,7 @@ static int nfs_start_lockd(struct nfs_server *server)
#ifdef CONFIG_NFS_V3_ACL
static void nfs_init_server_aclclient(struct nfs_server *server)
{
- if (server->flags & NFS_MOUNT_NOACL)
- goto out_noacl;
-
- server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
- if (IS_ERR(server->client_acl))
- goto out_noacl;
-
- /* No errors! Assume that Sun nfsacls are supported */
- server->caps |= NFS_CAP_ACLS;
- return;
-
-out_noacl:
+ server->flags &= ~NFS_MOUNT_NOACL;
server->caps &= ~NFS_CAP_ACLS;
}
#else
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 96bcfa3..41a5161 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -80,27 +80,6 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};
-#if IS_ENABLED(CONFIG_NFS_V3)
-const struct inode_operations nfs3_dir_inode_operations = {
- .create = nfs_create,
- .lookup = nfs_lookup,
- .link = nfs_link,
- .unlink = nfs_unlink,
- .symlink = nfs_symlink,
- .mkdir = nfs_mkdir,
- .rmdir = nfs_rmdir,
- .mknod = nfs_mknod,
- .rename = nfs_rename,
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
- .listxattr = nfs3_listxattr,
- .getxattr = nfs3_getxattr,
- .setxattr = nfs3_setxattr,
- .removexattr = nfs3_removexattr,
-};
-#endif /* CONFIG_NFS_V3 */
-
#ifdef CONFIG_NFS_V4
static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d11bb90..74c47eb 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -44,18 +44,6 @@
static const struct vm_operations_struct nfs_file_vm_ops;
-#if IS_ENABLED(CONFIG_NFS_V3)
-const struct inode_operations nfs3_file_inode_operations = {
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
- .listxattr = nfs3_listxattr,
- .getxattr = nfs3_getxattr,
- .setxattr = nfs3_setxattr,
- .removexattr = nfs3_removexattr,
-};
-#endif /* CONFIG_NFS_v3 */
-
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
diff --git a/fs/nfs/nfs3/Makefile b/fs/nfs/nfs3/Makefile
new file mode 100644
index 0000000..9b1c539
--- /dev/null
+++ b/fs/nfs/nfs3/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for NFS v3
+#
+obj-$(CONFIG_NFS_V3) += nfs3.o
+nfs3-y := module.o client.o dir.o file.o proc.o xdr.o
+nfs3-$(CONFIG_NFS_V3_ACL) += acl.o
diff --git a/fs/nfs/nfs3/acl.c b/fs/nfs/nfs3/acl.c
index ac589ff..dcf2259 100644
--- a/fs/nfs/nfs3/acl.c
+++ b/fs/nfs/nfs3/acl.c
@@ -1,3 +1,6 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/nfs.h>
diff --git a/fs/nfs/nfs3/client.c b/fs/nfs/nfs3/client.c
new file mode 100644
index 0000000..9f7e997
--- /dev/null
+++ b/fs/nfs/nfs3/client.c
@@ -0,0 +1,58 @@
+/* client.c: NFS client sharing and management code
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/sunrpc/sched.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+#include "nfs3.h"
+
+/*
+ * Initialise an NFSv3 ACL client connection
+ */
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
+static struct rpc_version *nfsacl_version[] = {
+ [3] = &nfsacl_version3,
+};
+
+struct rpc_program nfsacl_program = {
+ .name = "nfsacl",
+ .number = NFS_ACL_PROGRAM,
+ .nrvers = ARRAY_SIZE(nfsacl_version),
+ .version = nfsacl_version,
+ .stats = &nfsacl_rpcstat,
+};
+
+void nfs3_init_aclclient(struct nfs_server *server)
+{
+ if (server->flags & NFS_MOUNT_NOACL)
+ goto out_noacl;
+
+ server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+ if (IS_ERR(server->client_acl))
+ goto out_noacl;
+
+ /* No errors! Assume that Sun nfsacls are supported */
+ server->caps |= NFS_CAP_ACLS;
+ return;
+
+out_noacl:
+ server->caps &= ~NFS_CAP_ACLS;
+}
+#else
+void nfs3_init_aclclient(struct nfs_server *server)
+{
+ server->flags &= ~NFS_MOUNT_NOACL;
+ server->caps &= ~NFS_CAP_ACLS;
+}
+#endif
+
diff --git a/fs/nfs/nfs3/dir.c b/fs/nfs/nfs3/dir.c
new file mode 100644
index 0000000..99a38f1
--- /dev/null
+++ b/fs/nfs/nfs3/dir.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+
+#include "../nfs.h"
+#include "nfs3.h"
+
+const struct inode_operations nfs3_dir_inode_operations = {
+ .create = nfs_create,
+ .lookup = nfs_lookup,
+ .link = nfs_link,
+ .unlink = nfs_unlink,
+ .symlink = nfs_symlink,
+ .mkdir = nfs_mkdir,
+ .rmdir = nfs_rmdir,
+ .mknod = nfs_mknod,
+ .rename = nfs_rename,
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+
+const struct dentry_operations nfs3_dentry_operations = {
+ .d_revalidate = nfs_lookup_revalidate,
+ .d_delete = nfs_dentry_delete,
+ .d_iput = nfs_dentry_iput,
+ .d_automount = nfs_d_automount,
+ .d_release = nfs_d_release,
+};
+
diff --git a/fs/nfs/nfs3/file.c b/fs/nfs/nfs3/file.c
new file mode 100644
index 0000000..8afdaa0
--- /dev/null
+++ b/fs/nfs/nfs3/file.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include "../nfs.h"
+#include "nfs3.h"
+
+const struct inode_operations nfs3_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+
+const struct file_operations nfs3_file_operations = {
+ .llseek = nfs_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
+ .mmap = nfs_file_mmap,
+ .open = nfs_file_open,
+ .flush = nfs_file_flush,
+ .release = nfs_file_release,
+ .fsync = nfs_file_fsync,
+ .lock = nfs_lock,
+ .flock = nfs_flock,
+ .splice_read = nfs_file_splice_read,
+ .splice_write = nfs_file_splice_write,
+ .check_flags = nfs_check_flags,
+ .setlease = nfs_setlease,
+};
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
new file mode 100644
index 0000000..4c097a5
--- /dev/null
+++ b/fs/nfs/nfs3/module.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Initialize the NFS v3 module
+ */
+
+#include <linux/module.h>
+#include "../nfs.h"
+
+#include "nfs3.h"
+
+static void nfs3_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs3_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+struct nfs_subversion nfs_v3 = {
+ .version = 3,
+ .rpc_vers = &nfs_version3,
+ .rpc_ops = &nfs_v3_clientops,
+
+ .reference = nfs3_reference,
+ .unreference = nfs3_unreference,
+ .init_aclclient = nfs3_init_aclclient,
+};
+
+static int __init init_nfs_v3(void)
+{
+ register_nfs_version(&nfs_v3);
+ return 0;
+}
+
+static void __exit exit_nfs_v3(void)
+{
+ unregister_nfs_version(&nfs_v3);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v3);
+module_exit(exit_nfs_v3);
diff --git a/fs/nfs/nfs3/nfs3.h b/fs/nfs/nfs3/nfs3.h
new file mode 100644
index 0000000..5ed7efa
--- /dev/null
+++ b/fs/nfs/nfs3/nfs3.h
@@ -0,0 +1,32 @@
+#ifndef __LINUX_FS_NFS_NFS3_H
+#define __LINUX_FS_NFS_NFS3_H
+
+#include <linux/fs.h>
+#include <linux/sunrpc/clnt.h>
+
+extern struct rpc_version nfs_version3;
+extern struct nfs_rpc_ops nfs_v3_clientops;
+
+void nfs3_init_aclclient(struct nfs_server *);
+
+extern const struct inode_operations nfs3_file_inode_operations;
+extern const struct file_operations nfs3_file_operations;
+
+extern const struct inode_operations nfs3_dir_inode_operations;
+extern const struct dentry_operations nfs3_dentry_operations;
+
+#ifdef CONFIG_NFS_V3_ACL
+extern struct rpc_version nfsacl_version3;
+
+ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
+ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
+int nfs3_setxattr(struct dentry *, const char *, const void *, size_t, int);
+int nfs3_removexattr(struct dentry *, const char *);
+#else
+#define nfs3_listxattr NULL
+#define nfs3_getxattr NULL
+#define nfs3_setxattr NULL
+#define nfs3_removexattr NULL
+#endif /* CONFIG_NFS_V3_ACL */
+
+#endif /* __LINUX_FS_NFS_NFS3_H */
diff --git a/fs/nfs/nfs3/proc.c b/fs/nfs/nfs3/proc.c
index f37ddb9..5118096 100644
--- a/fs/nfs/nfs3/proc.c
+++ b/fs/nfs/nfs3/proc.c
@@ -20,6 +20,7 @@
#include "../iostat.h"
#include "../internal.h"
+#include "nfs3.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -848,12 +849,12 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
}
-const struct nfs_rpc_ops nfs_v3_clientops = {
+struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
- .dentry_ops = &nfs_dentry_operations,
+ .dentry_ops = &nfs3_dentry_operations,
.dir_inode_ops = &nfs3_dir_inode_operations,
.file_inode_ops = &nfs3_file_inode_operations,
- .file_ops = &nfs_file_operations,
+ .file_ops = &nfs3_file_operations,
.getroot = nfs3_proc_get_root,
.getattr = nfs3_proc_getattr,
.setattr = nfs3_proc_setattr,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 0ca9f10..afa36f8 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1273,12 +1273,9 @@ struct nfs_rpc_ops {
/*
* Function vectors etc. for the NFS client
*/
-extern const struct nfs_rpc_ops nfs_v3_clientops;
extern const struct nfs_rpc_ops nfs_v4_clientops;
-extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
-extern struct rpc_version nfsacl_version3;
extern struct rpc_program nfsacl_program;
#endif
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This patch adds in the code to track multiple versions of the NFS
protocol. I created default structures for v2, v3 and v4 so that each
version can continue to work while I convert them into kernel modules.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++-------
fs/nfs/inode.c | 2 +
fs/nfs/nfs.h | 73 +++++++++++++++++++++++++++
fs/nfs/super.c | 13 +++++
4 files changed, 216 insertions(+), 20 deletions(-)
create mode 100644 fs/nfs/nfs.h
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 01cb068..ee63d6a 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -49,10 +49,13 @@
#include "internal.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT
static DEFINE_SPINLOCK(nfs_client_lock);
+static DEFINE_SPINLOCK(nfs_version_lock);
+static LIST_HEAD(nfs_versions);
static LIST_HEAD(nfs_client_list);
static LIST_HEAD(nfs_volume_list);
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
@@ -90,15 +93,9 @@ static int nfs4_disable_idmapping = 0;
* RPC cruft for NFS
*/
static struct rpc_version *nfs_version[5] = {
-#ifdef CONFIG_NFS_V2
- [2] = &nfs_version2,
-#endif
-#ifdef CONFIG_NFS_V3
- [3] = &nfs_version3,
-#endif
-#ifdef CONFIG_NFS_V4
- [4] = &nfs_version4,
-#endif
+ [2] = NULL,
+ [3] = NULL,
+ [4] = NULL,
};
struct rpc_program nfs_program = {
@@ -114,6 +111,51 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};
+/*
+ * Default function for referencing and unreferencing
+ * nfs_version_module structures to prevent dereferencing
+ * a null pointer by the framework code. A functional
+ * version will be implemented by individual nfs versions
+ * as they are converted into modules.
+ *
+ * Once everything has been converted this function will
+ * be removed.
+ */
+#if defined(CONFIG_NFS_V2) || defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+static void nfs_module_null_function(void)
+{
+}
+#endif
+
+#ifdef CONFIG_NFS_V2
+static struct nfs_subversion nfs_v2_mod = {
+ .version = 2,
+ .rpc_vers = &nfs_version2,
+ .rpc_ops = &nfs_v2_clientops,
+ .reference = nfs_module_null_function,
+ .unreference = nfs_module_null_function,
+};
+#endif /* CONFIG_NFS_V2 */
+
+#ifdef CONFIG_NFS_V3
+static struct nfs_subversion nfs_v3_mod = {
+ .version = 3,
+ .rpc_vers = &nfs_version3,
+ .rpc_ops = &nfs_v3_clientops,
+ .reference = nfs_module_null_function,
+ .unreference = nfs_module_null_function,
+};
+#endif /* CONFIG_NFS_V3 */
+
+#ifdef CONFIG_NFS_V4
+static struct nfs_subversion nfs_v4_mod = {
+ .version = 4,
+ .rpc_vers = &nfs_version4,
+ .rpc_ops = &nfs_v4_clientops,
+ .reference = nfs_module_null_function,
+ .unreference = nfs_module_null_function,
+};
+#endif /* CONFIG_NFS_V4 */
#ifdef CONFIG_NFS_V3_ACL
static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
@@ -139,6 +181,78 @@ struct nfs_client_initdata {
u32 minorversion;
};
+struct nfs_subversion *get_nfs_version(unsigned int version)
+{
+ struct nfs_subversion *nfs;
+
+ spin_lock(&nfs_version_lock);
+
+ list_for_each_entry(nfs, &nfs_versions, list) {
+ if (nfs->version == version) {
+ /* Keep track of the most recently used version */
+ list_move(&nfs->list, &nfs_versions);
+ goto out;
+ }
+ };
+
+ nfs = ERR_PTR(-EPROTONOSUPPORT);
+
+out:
+ spin_unlock(&nfs_version_lock);
+ return nfs;
+}
+
+inline struct nfs_subversion *get_nfs_client_version(struct nfs_client *clp)
+{
+ return get_nfs_version(clp->rpc_ops->version);
+}
+
+inline struct nfs_subversion *get_nfs_server_version(struct nfs_server *srv)
+{
+ return get_nfs_client_version(srv->nfs_client);
+}
+
+void register_nfs_version(struct nfs_subversion *nfs)
+{
+ spin_lock(&nfs_version_lock);
+
+ INIT_LIST_HEAD(&nfs->list);
+ list_add(&nfs->list, &nfs_versions);
+ nfs_version[nfs->version] = nfs->rpc_vers;
+
+ spin_unlock(&nfs_version_lock);
+}
+EXPORT_SYMBOL_GPL(register_nfs_version);
+
+void unregister_nfs_version(struct nfs_subversion *nfs)
+{
+ spin_lock(&nfs_version_lock);
+
+ nfs_version[nfs->version] = NULL;
+ list_del(&nfs->list);
+
+ spin_unlock(&nfs_version_lock);
+}
+EXPORT_SYMBOL_GPL(unregister_nfs_version);
+
+/*
+ * Preload all configured NFS versions during module init.
+ * This function should be edited after each protocol is converted,
+ * and eventually removed.
+ */
+void __init nfs_register_versions(void)
+{
+#ifdef CONFIG_NFS_V2
+ register_nfs_version(&nfs_v2_mod);
+#endif
+#ifdef CONFIG_NFS_V3
+ register_nfs_version(&nfs_v3_mod);
+#endif
+#ifdef CONFIG_NFS_V4
+ register_nfs_version(&nfs_v4_mod);
+#endif
+}
+
/*
* Allocate a shared client record
*
@@ -836,21 +950,15 @@ static int nfs_init_server(struct nfs_server *server,
};
struct rpc_timeout timeparms;
struct nfs_client *clp;
+ struct nfs_subversion *nfs_mod;
int error;
dprintk("--> nfs_init_server()\n");
-
-#ifdef CONFIG_NFS_V2
- if (data->version == 2)
- cl_init.rpc_ops = &nfs_v2_clientops;
-#endif
-#ifdef CONFIG_NFS_V3
- if (data->version == 3)
- cl_init.rpc_ops = &nfs_v3_clientops;
-#endif
- if (cl_init.rpc_ops == NULL)
- return -EPROTONOSUPPORT;
+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod))
+ return PTR_ERR(nfs_mod);
+ cl_init.rpc_ops = nfs_mod->rpc_ops;
nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f59cab1..3c81a32 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -50,6 +50,7 @@
#include "fscache.h"
#include "dns_resolve.h"
#include "pnfs.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -1604,6 +1605,7 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
+ nfs_register_versions();
return 0;
out:
#ifdef CONFIG_PROC_FS
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
new file mode 100644
index 0000000..b1fe653
--- /dev/null
+++ b/fs/nfs/nfs.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Function and structures exported by the NFS module
+ * for use by NFS version-specific modules.
+ */
+#ifndef __LINUX_INTERNAL_NFS_H
+#define __LINUX_INTERNAL_NFS_H
+
+#include <linux/fs.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_xdr.h>
+
+struct nfs_subversion {
+ unsigned int version; /* Protocol number */
+ struct rpc_version *rpc_vers; /* NFS version information */
+ const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
+ struct list_head list; /* List of NFS versions */
+
+ void (*reference)(void); /* For reference counting */
+ void (*unreference)(void); /* Also for reference counting */
+};
+
+void nfs_register_versions(void);
+
+struct nfs_subversion *get_nfs_version(unsigned int);
+struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
+struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
+void register_nfs_version(struct nfs_subversion *);
+void unregister_nfs_version(struct nfs_subversion *);
+
+/* Exported in dir.c */
+int nfs_lookup_revalidate(struct dentry *, struct nameidata *);
+int nfs_dentry_delete(const struct dentry *);
+void nfs_dentry_iput(struct dentry *, struct inode *);
+void nfs_d_release(struct dentry *);
+struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
+int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
+int nfs_mkdir(struct inode *, struct dentry *, int);
+int nfs_rmdir(struct inode *, struct dentry *);
+int nfs_unlink(struct inode *, struct dentry *);
+int nfs_symlink(struct inode *, struct dentry *, const char *);
+int nfs_link(struct dentry *, struct inode *, struct dentry *);
+int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+int nfs_permission(struct inode *, int);
+
+/* Exported in file.c */
+int nfs_check_flags(int);
+int nfs_file_open(struct inode *, struct file *);
+int nfs_file_release(struct inode *, struct file *);
+loff_t nfs_file_llseek(struct file *, loff_t, int);
+int nfs_file_flush(struct file *, fl_owner_t);
+ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
+ size_t, unsigned int);
+int nfs_file_mmap(struct file *, struct vm_area_struct *);
+int nfs_file_fsync(struct file *, loff_t, loff_t, int);
+ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int);
+int nfs_lock(struct file *, int, struct file_lock *);
+int nfs_flock(struct file *, int, struct file_lock *);
+int nfs_setlease(struct file *, long, struct file_lock **);
+
+/* Exported in inode.c */
+int nfs_setattr(struct dentry *, struct iattr *);
+int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+
+/* Exported in namespace.c */
+struct vfsmount *nfs_d_automount(struct path *);
+
+#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 3ada13c..aee7b00 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -64,6 +64,7 @@
#include "internal.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -2229,6 +2230,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
};
+ struct nfs_subversion *nfs_mod;
int error;
data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
@@ -2243,6 +2245,12 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
goto out;
}
+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod)) {
+ mntroot = (struct dentry *)nfs_mod;
+ goto out;
+ }
+
#ifdef CONFIG_NFS_V4
if (data->version == 4) {
mntroot = nfs4_try_mount(flags, dev_name, data);
@@ -2297,6 +2305,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
if (error)
goto error_splat_root;
+ nfs_mod->reference();
s->s_flags |= MS_ACTIVE;
out:
@@ -2326,6 +2335,10 @@ error_splat_bdi:
static void nfs_put_super(struct super_block *s)
{
struct nfs_server *server = NFS_SB(s);
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+
+ if (!IS_ERR(nfs_mod))
+ nfs_mod->unreference();
bdi_unregister(&server->backing_dev_info);
}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
I eventually plan to move the code protecting the cb_ident_idr to a file
in the nfs4/ directory. This patch creates a new lock to prepare for
the move.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 26 +++++++++++++++-----------
1 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 998c3be..dc10b2e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -61,7 +61,8 @@ static LIST_HEAD(nfs_client_list);
static LIST_HEAD(nfs_volume_list);
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
#ifdef CONFIG_NFS_V4
-static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */
+static DEFINE_SPINLOCK(nfs_idr_lock);
+static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_idr_lock */
/*
* Get a unique NFSv4.0 callback identifier which will be used
@@ -76,9 +77,9 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
retry:
if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL))
return -ENOMEM;
- spin_lock(&nfs_client_lock);
+ spin_lock(&nfs_idr_lock);
ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident);
- spin_unlock(&nfs_client_lock);
+ spin_unlock(&nfs_idr_lock);
if (ret == -EAGAIN)
goto retry;
return ret;
@@ -291,11 +292,12 @@ void nfs_cleanup_cb_ident_idr(void)
idr_destroy(&cb_ident_idr);
}
-/* nfs_client_lock held */
-static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+static void nfs_cb_idr_remove(struct nfs_client *clp)
{
+ spin_lock(&nfs_idr_lock);
if (clp->cl_cb_ident)
idr_remove(&cb_ident_idr, clp->cl_cb_ident);
+ spin_unlock(&nfs_idr_lock);
}
static void pnfs_init_server(struct nfs_server *server)
@@ -314,7 +316,7 @@ void nfs_cleanup_cb_ident_idr(void)
{
}
-static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+static void nfs_cb_idr_remove(struct nfs_client *clp)
{
}
@@ -364,7 +366,7 @@ void nfs_put_client(struct nfs_client *clp)
if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
list_del(&clp->cl_share_link);
- nfs_cb_idr_remove_locked(clp);
+ nfs_cb_idr_remove(clp);
spin_unlock(&nfs_client_lock);
BUG_ON(!list_empty(&clp->cl_superblocks));
@@ -1246,11 +1248,13 @@ nfs4_find_client_ident(int cb_ident)
{
struct nfs_client *clp;
- spin_lock(&nfs_client_lock);
+ spin_lock(&nfs_idr_lock);
clp = idr_find(&cb_ident_idr, cb_ident);
- if (clp)
- atomic_inc(&clp->cl_count);
- spin_unlock(&nfs_client_lock);
+ if (clp) {
+ if (!atomic_inc_not_zero(&clp->cl_count))
+ clp = NULL;
+ }
+ spin_unlock(&nfs_idr_lock);
return clp;
}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
v2 and v3 don't have delegations, so this is an empty function in those
cases and only defined for v4.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/inode.c | 6 ++++++
fs/nfs/nfs.h | 2 ++
fs/nfs/nfs2/module.c | 6 ++++++
fs/nfs/nfs3/module.c | 6 ++++++
fs/nfs/nfs4/delegation.c | 2 +-
fs/nfs/nfs4/delegation.h | 9 ++-------
fs/nfs/write.c | 1 +
8 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 6091414..e00f268 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -137,6 +137,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
+ .have_delegation = nfs4_have_delegation,
.do_submount = nfs4_do_submount,
.do_clone_mount = nfs4_do_clone_mount,
};
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3588727..1c7e24f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -124,6 +124,12 @@ void nfs_evict_inode(struct inode *inode)
nfs_clear_inode(inode);
}
+int nfs_have_delegation(struct inode *inode, fmode_t flags)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ return nfs_mod->have_delegation(inode, flags);
+}
+
/**
* nfs_sync_mapping - helper to flush all mmapped dirty data to disk
*/
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 0f119ab..7be27f4 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -22,6 +22,7 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
void (*init_aclclient)(struct nfs_server *);
+ int (*have_delegation)(struct inode *, fmode_t);
struct vfsmount *(*do_submount)(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
struct vfsmount *(*do_clone_mount)(struct nfs_server *, const char *,
@@ -73,6 +74,7 @@ int nfs_setlease(struct file *, long, struct file_lock **);
/* Exported in inode.c */
int nfs_setattr(struct dentry *, struct iattr *);
int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+int nfs_have_delegation(struct inode *, fmode_t);
/* Exported in namespace.c */
struct vfsmount *nfs_d_automount(struct path *);
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 768c375..ccbb759 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -19,6 +19,11 @@ static void nfs2_unreference(void)
module_put(THIS_MODULE);
}
+static int nfs2_no_delegation(struct inode *inode, fmode_t flags)
+{
+ return 0;
+}
+
struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -27,6 +32,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
+ .have_delegation = nfs2_no_delegation,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 0898339..10cfab8 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -19,6 +19,11 @@ static void nfs3_unreference(void)
module_put(THIS_MODULE);
}
+static int nfs3_no_delegation(struct inode *inode, fmode_t flags)
+{
+ return 0;
+}
+
struct nfs_subversion nfs_v3 = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -27,6 +32,7 @@ struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
+ .have_delegation = nfs3_no_delegation,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs4/delegation.c b/fs/nfs/nfs4/delegation.c
index 2f3dc3e..800f44e 100644
--- a/fs/nfs/nfs4/delegation.c
+++ b/fs/nfs/nfs4/delegation.c
@@ -47,7 +47,7 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
*
* Returns one if inode has the indicated delegation, otherwise zero.
*/
-int nfs_have_delegation(struct inode *inode, fmode_t flags)
+int nfs4_have_delegation(struct inode *inode, fmode_t flags)
{
struct nfs_delegation *delegation;
int ret = 0;
diff --git a/fs/nfs/nfs4/delegation.h b/fs/nfs/nfs4/delegation.h
index d9322e4..675ceea 100644
--- a/fs/nfs/nfs4/delegation.h
+++ b/fs/nfs/nfs4/delegation.h
@@ -56,14 +56,9 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
-int nfs_have_delegation(struct inode *inode, fmode_t flags);
+int nfs4_have_delegation(struct inode *inode, fmode_t flags);
#else
-static inline int nfs_have_delegation(struct inode *inode, fmode_t flags)
-{
- return 0;
-}
-
static inline int nfs_inode_return_delegation(struct inode *inode)
{
return 0;
@@ -72,7 +67,7 @@ static inline int nfs_inode_return_delegation(struct inode *inode)
static inline int nfs_have_delegated_attributes(struct inode *inode)
{
- return nfs_have_delegation(inode, FMODE_READ) &&
+ return nfs4_have_delegation(inode, FMODE_READ) &&
!(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d5f61af..f9ca30c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -30,6 +30,7 @@
#include "nfs4/nfs4_fs.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
I am about to move over nfs v4-only code from client.c to nfs4/client.c.
These functions will be needed by that code, so they cannot be declared
static.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 34 +++++++++++++++++++++-------------
fs/nfs/nfs.h | 11 +++++++++++
2 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 56da3b6..8e053a4 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -402,8 +402,8 @@ static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
* Test if two socket addresses represent the same actual socket,
* by comparing (only) relevant fields, excluding the port number.
*/
-static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
- const struct sockaddr *sa2)
+int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
+ const struct sockaddr *sa2)
{
if (sa1->sa_family != sa2->sa_family)
return 0;
@@ -416,6 +416,7 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
}
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr);
/*
* Test if two socket addresses represent the same actual socket,
@@ -498,7 +499,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
* Look up a client by IP address and protocol version
* - creates a new record if one doesn't yet exist
*/
-static struct nfs_client *
+struct nfs_client *
nfs_get_client(const struct nfs_client_initdata *cl_init,
const struct rpc_timeout *timeparms,
const char *ip_addr,
@@ -571,6 +572,7 @@ found_client:
dprintk("--> nfs_get_client() = %p [share]\n", clp);
return clp;
}
+EXPORT_SYMBOL_GPL(nfs_get_client);
/*
* Mark a server as ready or failed
@@ -580,6 +582,7 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state)
clp->cl_cons_state = state;
wake_up_all(&nfs_client_active_wq);
}
+EXPORT_SYMBOL_GPL(nfs_mark_client_ready);
/*
* With sessions, the client is not marked ready until after a
@@ -600,8 +603,8 @@ int nfs4_check_client_ready(struct nfs_client *clp)
/*
* Initialise the timeout values for a connection
*/
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
- unsigned int timeo, unsigned int retrans)
+void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
+ unsigned int timeo, unsigned int retrans)
{
to->to_initval = timeo * HZ / 10;
to->to_retries = retrans;
@@ -637,14 +640,15 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
BUG();
}
}
+EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
/*
* Create an RPC client handle
*/
-static int nfs_create_rpc_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- rpc_authflavor_t flavor,
- int discrtry, int noresvport)
+int nfs_create_rpc_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ rpc_authflavor_t flavor,
+ int discrtry, int noresvport)
{
struct rpc_clnt *clnt = NULL;
struct rpc_create_args args = {
@@ -677,6 +681,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
clp->cl_rpcclient = clnt;
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_create_rpc_client);
/*
* Version 2 or 3 client destruction
@@ -730,7 +735,7 @@ static int nfs_start_lockd(struct nfs_server *server)
/*
* Create a general RPC client
*/
-static int nfs_init_server_rpcclient(struct nfs_server *server,
+int nfs_init_server_rpcclient(struct nfs_server *server,
const struct rpc_timeout *timeo,
rpc_authflavor_t pseudoflavour)
{
@@ -762,6 +767,7 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
/*
* Initialise an NFS2 or NFS3 client
@@ -947,7 +953,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
/*
* Probe filesystem information, including the FSID on v2/v3
*/
-static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
{
struct nfs_fsinfo fsinfo;
struct nfs_client *clp = server->nfs_client;
@@ -987,11 +993,12 @@ out_error:
dprintk("nfs_probe_fsinfo: error = %d\n", -error);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_probe_fsinfo);
/*
* Copy useful information when duplicating a server record
*/
-static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
{
target->flags = source->flags;
target->rsize = source->rsize;
@@ -1003,8 +1010,9 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
target->caps = source->caps;
target->options = source->options;
}
+EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
-static void nfs_server_insert_lists(struct nfs_server *server)
+void nfs_server_insert_lists(struct nfs_server *server)
{
struct nfs_client *clp = server->nfs_client;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 5f2d632..464c64a 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -68,6 +68,17 @@ struct nfs_server *do_nfs_clone_server(struct nfs_server *, struct nfs_server *,
struct nfs_fh *, struct nfs_fattr *);
struct list_head *nfs_client_list_start(void);
void nfs_client_list_end(void);
+int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
+int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *,
+ rpc_authflavor_t, int, int);
+struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
+ const struct rpc_timeout *, const char *,
+ rpc_authflavor_t, int);
+int nfs_probe_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
+void nfs_server_insert_lists(struct nfs_server *);
+void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
+int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *, rpc_authflavor_t);
+void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *);
/* Exported in dir.c */
int nfs_lookup_revalidate(struct dentry *, struct nameidata *);
--
1.7.8.3
On Jan 13, 2012, at 3:10 PM, [email protected] wrote:
> From: Bryan Schumaker <[email protected]>
>
> The v4 code uses these functions in the generic client, so they need to
> be available to modules.
If you add the EXPORT_SYMBOL() macros in separate patches, is that bisect-able? Seems like you should add the macros when you move functions.
It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
> Signed-off-by: Bryan Schumaker <[email protected]>
> ---
> fs/nfs/client.c | 2 ++
> fs/nfs/dir.c | 2 ++
> fs/nfs/dns_resolve.c | 4 ++++
> fs/nfs/fscache.c | 4 ++++
> fs/nfs/inode.c | 9 +++++++++
> fs/nfs/namespace.c | 1 +
> fs/nfs/super.c | 2 ++
> fs/nfs/unlink.c | 3 +++
> fs/nfs/write.c | 2 ++
> 9 files changed, 29 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 2c3f50e..0e4ddbe 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
> spin_unlock(&nfs_client_lock);
>
> }
> +EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
>
> static void nfs_server_remove_lists(struct nfs_server *server)
> {
> @@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
> nfs_release_automount_timer();
> dprintk("<-- nfs_free_server()\n");
> }
> +EXPORT_SYMBOL_GPL(nfs_free_server);
>
> /*
> * Create a version 2 or 3 volume record
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 210284f..909f8de 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
> {
> NFS_I(dir)->cache_change_attribute++;
> }
> +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
>
> /*
> * A check for whether or not the parent directory has changed.
> @@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
> {
> return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
> }
> +EXPORT_SYMBOL_GPL(nfs_may_open);
>
> int nfs_permission(struct inode *inode, int mask)
> {
> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
> index a6e711a..8b9aeba 100644
> --- a/fs/nfs/dns_resolve.c
> +++ b/fs/nfs/dns_resolve.c
> @@ -6,6 +6,8 @@
> * Resolves DNS hostnames into valid ip addresses
> */
>
> +#include <linux/module.h>
> +
> #ifdef CONFIG_NFS_USE_KERNEL_DNS
>
> #include <linux/sunrpc/clnt.h>
> @@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
> kfree(ip_addr);
> return ret;
> }
> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>
> #else
>
> @@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
> ret = -ESRCH;
> return ret;
> }
> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>
> int nfs_dns_resolver_init(void)
> {
> diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
> index 419119c..94e2d51 100644
> --- a/fs/nfs/fscache.c
> +++ b/fs/nfs/fscache.c
> @@ -9,6 +9,7 @@
> * 2 of the Licence, or (at your option) any later version.
> */
>
> +#include <linux/module.h>
> #include <linux/init.h>
> #include <linux/kernel.h>
> #include <linux/sched.h>
> @@ -163,6 +164,7 @@ non_unique:
> printk(KERN_WARNING "NFS:"
> " Cache request denied due to non-unique superblock keys\n");
> }
> +EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
>
> /*
> * release a per-superblock cookie
> @@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
> nfss->fscache_key = NULL;
> }
> }
> +EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
>
> /*
> * Initialise the per-inode cache cookie pointer for an NFS inode.
> @@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
> nfs_fscache_inode_unlock(inode);
> }
> }
> +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
>
> /*
> * Replace a per-inode cookie due to revalidation detecting a file having
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index 57a68b8..d7afc2b 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
> schedule();
> return 0;
> }
> +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
>
> /**
> * nfs_compat_user_ino64 - returns the user-visible inode number
> @@ -421,6 +422,7 @@ out_no_inode:
> dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
> goto out;
> }
> +EXPORT_SYMBOL_GPL(nfs_fhget);
>
> #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
>
> @@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
> }
> return ctx;
> }
> +EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
>
> struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
> {
> @@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
> atomic_inc(&ctx->lock_context.count);
> return ctx;
> }
> +EXPORT_SYMBOL_GPL(get_nfs_open_context);
>
> static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
> {
> @@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
> {
> __put_nfs_open_context(ctx, 0);
> }
> +EXPORT_SYMBOL_GPL(put_nfs_open_context);
>
> /*
> * Ensure that mmap has a recent RPC credential for use when writing out
> @@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
> list_add(&ctx->list, &nfsi->open_files);
> spin_unlock(&inode->i_lock);
> }
> +EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
>
> /*
> * Given an inode, search for an open context with the desired characteristics
> @@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
> #endif /* CONFIG_NFS_V4 */
> return &nfsi->vfs_inode;
> }
> +EXPORT_SYMBOL_GPL(nfs_alloc_inode);
>
> static void nfs_i_callback(struct rcu_head *head)
> {
> @@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
> {
> call_rcu(&inode->i_rcu, nfs_i_callback);
> }
> +EXPORT_SYMBOL_GPL(nfs_destroy_inode);
>
> static inline void nfs4_init_once(struct nfs_inode *nfsi)
> {
> @@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
> }
>
> struct workqueue_struct *nfsiod_workqueue;
> +EXPORT_SYMBOL_GPL(nfsiod_workqueue);
>
> /*
> * start up the nfsiod workqueue
> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
> index 203b4b3..d311128 100644
> --- a/fs/nfs/namespace.c
> +++ b/fs/nfs/namespace.c
> @@ -114,6 +114,7 @@ Elong_unlock:
> Elong:
> return ERR_PTR(-ENAMETOOLONG);
> }
> +EXPORT_SYMBOL_GPL(nfs_path);
>
> #if IS_ENABLED(CONFIG_NFS_V4)
> rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index 2c8ed6f..d2d1b6b 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
> if (atomic_inc_return(&server->active) == 1)
> atomic_inc(&sb->s_active);
> }
> +EXPORT_SYMBOL_GPL(nfs_sb_active);
>
> void nfs_sb_deactive(struct super_block *sb)
> {
> @@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
> if (atomic_dec_and_test(&server->active))
> deactivate_super(sb);
> }
> +EXPORT_SYMBOL_GPL(nfs_sb_deactive);
>
> /*
> * Deliver file system statistics to userspace
> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
> index 9f04700..32c1d70 100644
> --- a/fs/nfs/unlink.c
> +++ b/fs/nfs/unlink.c
> @@ -5,6 +5,7 @@
> *
> */
>
> +#include <linux/module.h>
> #include <linux/slab.h>
> #include <linux/string.h>
> #include <linux/dcache.h>
> @@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
>
> wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
> }
> +EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
>
> void nfs_unblock_sillyrename(struct dentry *dentry)
> {
> @@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
> }
> spin_unlock(&dir->i_lock);
> }
> +EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
>
> /**
> * nfs_async_unlink - asynchronous unlinking of a file
> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
> index f9ca30c..0750ebb 100644
> --- a/fs/nfs/write.c
> +++ b/fs/nfs/write.c
> @@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
> }
> return ret;
> }
> +EXPORT_SYMBOL_GPL(nfs_write_inode);
>
> /*
> * flush the inode to disk.
> @@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
>
> return sync_inode(inode, &wbc);
> }
> +EXPORT_SYMBOL_GPL(nfs_wb_all);
>
> int nfs_wb_page_cancel(struct inode *inode, struct page *page)
> {
> --
> 1.7.8.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
From: Bryan Schumaker <[email protected]>
I change these functions to be non-static and then export them for the
v4 module to use.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs.h | 24 +++++++++++++++++
fs/nfs/super.c | 76 +++++++++++++++++++++++++++++--------------------------
2 files changed, 64 insertions(+), 36 deletions(-)
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 2cdcbcf..55ea4d7 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -51,6 +51,11 @@ struct nfs_subversion {
struct nfs_clone_mount *);
};
+struct nfs_sb_mountdata {
+ struct nfs_server *server;
+ int mntflags;
+};
+
struct nfs_subversion *get_nfs_version(unsigned int);
struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
@@ -117,5 +122,24 @@ struct dentry *generic_nfs_fs_mount(struct file_system_type *, int,
struct nfs_parsed_mount_data *);
int nfs_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
struct nfs_fh *, const char *);
+void nfs_umount_begin(struct super_block *);
+int nfs_statfs(struct dentry *, struct kstatfs *);
+int nfs_show_options(struct seq_file *, struct vfsmount *);
+int nfs_show_devname(struct seq_file *, struct vfsmount *);
+int nfs_show_path(struct seq_file *, struct vfsmount *);
+int nfs_show_stats(struct seq_file *, struct vfsmount *);
+void nfs_put_super(struct super_block *);
+int nfs_remount(struct super_block *, int *, char *);
+void nfs_initialise_sb(struct super_block *);
+void nfs_set_port(struct sockaddr *, int *, const unsigned short);
+void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *);
+int nfs_parse_devname(const char *, char **, size_t, char **, size_t);
+int nfs_verify_server_address(struct sockaddr *);
+int nfs_parse_mount_options(char *, struct nfs_parsed_mount_data *);
+int nfs_compare_super(struct super_block *, void *);
+int nfs_bdi_register(struct nfs_server *);
+int nfs_set_super(struct super_block *, void *);
+struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int);
+void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *);
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f5c5cd9..a06347d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -262,20 +262,11 @@ static match_table_t nfs_local_lock_tokens = {
{ Opt_local_lock_err, NULL }
};
-
-static void nfs_umount_begin(struct super_block *);
-static int nfs_statfs(struct dentry *, struct kstatfs *);
-static int nfs_show_options(struct seq_file *, struct vfsmount *);
-static int nfs_show_devname(struct seq_file *, struct vfsmount *);
-static int nfs_show_path(struct seq_file *, struct vfsmount *);
-static int nfs_show_stats(struct seq_file *, struct vfsmount *);
static struct dentry *nfs_fs_mount(struct file_system_type *,
int, const char *, void *);
static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
-static void nfs_put_super(struct super_block *);
static void nfs_kill_super(struct super_block *);
-static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
static struct file_system_type nfs_fs_type = {
.owner = THIS_MODULE,
@@ -446,7 +437,7 @@ void nfs_sb_deactive(struct super_block *sb)
/*
* Deliver file system statistics to userspace
*/
-static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct nfs_server *server = NFS_SB(dentry->d_sb);
unsigned char blockbits;
@@ -507,6 +498,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
dprintk("%s: statfs error = %d\n", __func__, -error);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_statfs);
/*
* Map the security flavour number to a name
@@ -719,7 +711,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
/*
* Describe the mount options on this VFS mountpoint
*/
-static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
{
struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
@@ -731,6 +723,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_show_options);
#ifdef CONFIG_NFS_V4
#ifdef CONFIG_NFS_V4_1
@@ -759,7 +752,7 @@ static void show_pnfs(struct seq_file *m, struct nfs_server *server) {}
#endif
#endif
-static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
+int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
{
char *page = (char *) __get_free_page(GFP_KERNEL);
char *devname, *dummy;
@@ -774,17 +767,19 @@ static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
free_page((unsigned long)page);
return err;
}
+EXPORT_SYMBOL_GPL(nfs_show_devname);
-static int nfs_show_path(struct seq_file *m, struct vfsmount *mnt)
+int nfs_show_path(struct seq_file *m, struct vfsmount *mnt)
{
seq_puts(m, "/");
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_show_path);
/*
* Present statistical information for this VFS mountpoint
*/
-static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
{
int i, cpu;
struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
@@ -870,12 +865,13 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_show_stats);
/*
* Begin unmount by attempting to remove all automounted mountpoints we added
* in response to xdev traversals and referrals
*/
-static void nfs_umount_begin(struct super_block *sb)
+void nfs_umount_begin(struct super_block *sb)
{
struct nfs_server *server;
struct rpc_clnt *rpc;
@@ -889,8 +885,9 @@ static void nfs_umount_begin(struct super_block *sb)
if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
}
+EXPORT_SYMBOL_GPL(nfs_umount_begin);
-static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
+struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
{
struct nfs_parsed_mount_data *data;
@@ -911,8 +908,9 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
}
return data;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_parsed_mount_data);
-static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
+void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
{
if (data) {
kfree(data->client_address);
@@ -924,6 +922,7 @@ static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
kfree(data);
}
}
+EXPORT_SYMBOL_GPL(nfs_free_parsed_mount_data);
/*
* Sanity-check a server address provided by the mount command.
@@ -931,7 +930,7 @@ static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
* Address family must be initialized, and address must not be
* the ANY address for that family.
*/
-static int nfs_verify_server_address(struct sockaddr *addr)
+int nfs_verify_server_address(struct sockaddr *addr)
{
switch (addr->sa_family) {
case AF_INET: {
@@ -947,12 +946,13 @@ static int nfs_verify_server_address(struct sockaddr *addr)
dfprintk(MOUNT, "NFS: Invalid IP address specified\n");
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_verify_server_address);
/*
* Select between a default port value and a user-specified port value.
* If a zero value is set, then autobind will be used.
*/
-static void nfs_set_port(struct sockaddr *sap, int *port,
+void nfs_set_port(struct sockaddr *sap, int *port,
const unsigned short default_port)
{
if (*port == NFS_UNSPEC_PORT)
@@ -960,12 +960,13 @@ static void nfs_set_port(struct sockaddr *sap, int *port,
rpc_set_port(sap, *port);
}
+EXPORT_SYMBOL_GPL(nfs_set_port);
/*
* Sanity check the NFS transport protocol.
*
*/
-static void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
+void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
{
switch (mnt->nfs_server.protocol) {
case XPRT_TRANSPORT_UDP:
@@ -976,6 +977,7 @@ static void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
}
}
+EXPORT_SYMBOL_GPL(nfs_validate_transport_protocol);
/*
* For text based NFSv2/v3 mounts, the mount protocol transport default
@@ -1078,8 +1080,7 @@ static int nfs_get_option_ul(substring_t args[], unsigned long *option)
* skipped as they are encountered. If there were no errors, return 1;
* otherwise return 0 (zero).
*/
-static int nfs_parse_mount_options(char *raw,
- struct nfs_parsed_mount_data *mnt)
+int nfs_parse_mount_options(char *raw, struct nfs_parsed_mount_data *mnt)
{
char *p, *string, *secdata;
int rc, sloppy = 0, invalid_option = 0;
@@ -1556,6 +1557,7 @@ out_security_failure:
printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_parse_mount_options);
/*
* Match the requested auth flavors with the list returned by
@@ -1679,9 +1681,9 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
*
* Note: caller frees hostname and export path, even on error.
*/
-static int nfs_parse_devname(const char *dev_name,
- char **hostname, size_t maxnamlen,
- char **export_path, size_t maxpathlen)
+int nfs_parse_devname(const char *dev_name,
+ char **hostname, size_t maxnamlen,
+ char **export_path, size_t maxpathlen)
{
size_t len;
char *end;
@@ -1741,6 +1743,7 @@ out_path:
dfprintk(MOUNT, "NFS: export pathname too long\n");
return -ENAMETOOLONG;
}
+EXPORT_SYMBOL_GPL(nfs_parse_devname);
int nfs_validate_text_mount_data(void *options,
struct nfs_parsed_mount_data *args,
@@ -1974,7 +1977,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
return 0;
}
-static int
+int
nfs_remount(struct super_block *sb, int *flags, char *raw_data)
{
int error;
@@ -2035,11 +2038,12 @@ out:
kfree(data);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_remount);
/*
* Initialise the common bits of the superblock
*/
-static inline void nfs_initialise_sb(struct super_block *sb)
+inline void nfs_initialise_sb(struct super_block *sb)
{
struct nfs_server *server = NFS_SB(sb);
@@ -2057,6 +2061,7 @@ static inline void nfs_initialise_sb(struct super_block *sb)
nfs_super_set_maxbytes(sb, server->maxfilesize);
}
+EXPORT_SYMBOL_GPL(nfs_initialise_sb);
/*
* Finish setting up an NFS2/3 superblock
@@ -2138,12 +2143,7 @@ Ebusy:
return 0;
}
-struct nfs_sb_mountdata {
- struct nfs_server *server;
- int mntflags;
-};
-
-static int nfs_set_super(struct super_block *s, void *data)
+int nfs_set_super(struct super_block *s, void *data)
{
struct nfs_sb_mountdata *sb_mntdata = data;
struct nfs_server *server = sb_mntdata->server;
@@ -2157,6 +2157,7 @@ static int nfs_set_super(struct super_block *s, void *data)
server->s_dev = s->s_dev;
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_set_super);
static int nfs_compare_super_address(struct nfs_server *server1,
struct nfs_server *server2)
@@ -2195,7 +2196,7 @@ static int nfs_compare_super_address(struct nfs_server *server1,
return 1;
}
-static int nfs_compare_super(struct super_block *sb, void *data)
+int nfs_compare_super(struct super_block *sb, void *data)
{
struct nfs_sb_mountdata *sb_mntdata = data;
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
@@ -2210,11 +2211,13 @@ static int nfs_compare_super(struct super_block *sb, void *data)
return 0;
return nfs_compare_mount_options(sb, server, mntflags);
}
+EXPORT_SYMBOL_GPL(nfs_compare_super);
-static int nfs_bdi_register(struct nfs_server *server)
+int nfs_bdi_register(struct nfs_server *server)
{
return bdi_register_dev(&server->backing_dev_info, server->s_dev);
}
+EXPORT_SYMBOL_GPL(nfs_bdi_register);
struct dentry *generic_nfs_fs_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, struct nfs_fh *mntfh,
@@ -2340,7 +2343,7 @@ out:
* Ensure that we unregister the bdi before kill_anon_super
* releases the device name
*/
-static void nfs_put_super(struct super_block *s)
+void nfs_put_super(struct super_block *s)
{
struct nfs_server *server = NFS_SB(s);
struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
@@ -2350,6 +2353,7 @@ static void nfs_put_super(struct super_block *s)
bdi_unregister(&server->backing_dev_info);
}
+EXPORT_SYMBOL_GPL(nfs_put_super);
/*
* Destroy an NFS2/3 superblock
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
I keep the generic setup stuff where it already is. Then it calls one
function if v4 and another for v2 and v3. Finally, it references the
module and exits. This patch prepares for calling the approriate
function through the struct nfs_subversion.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/super.c | 81 +++++++++++++++++++++++++++++++++-----------------------
1 files changed, 48 insertions(+), 33 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d7cdc50..60d065f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2218,46 +2218,19 @@ static int nfs_bdi_register(struct nfs_server *server)
return bdi_register_dev(&server->backing_dev_info, server->s_dev);
}
-static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
+struct dentry *generic_nfs_fs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
{
struct nfs_server *server = NULL;
struct super_block *s;
- struct nfs_parsed_mount_data *data;
- struct nfs_fh *mntfh;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
};
- struct nfs_subversion *nfs_mod;
int error;
- data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
- mntfh = nfs_alloc_fhandle();
- if (data == NULL || mntfh == NULL)
- goto out;
-
- /* Validate the mount data */
- error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
- if (error < 0) {
- mntroot = ERR_PTR(error);
- goto out;
- }
-
- nfs_mod = get_nfs_version(data->version);
- if (IS_ERR(nfs_mod)) {
- mntroot = (struct dentry *)nfs_mod;
- goto out;
- }
-
-#ifdef CONFIG_NFS_V4
- if (data->version == 4) {
- mntroot = nfs4_try_mount(flags, dev_name, data);
- goto out;
- }
-#endif /* CONFIG_NFS_V4 */
-
/* Get a volume representation */
server = nfs_create_server(data, mntfh);
if (IS_ERR(server)) {
@@ -2305,12 +2278,9 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
if (error)
goto error_splat_root;
- nfs_mod->reference();
s->s_flags |= MS_ACTIVE;
out:
- nfs_free_parsed_mount_data(data);
- nfs_free_fhandle(mntfh);
return mntroot;
out_err_nosb:
@@ -2326,6 +2296,51 @@ error_splat_super:
error_splat_bdi:
deactivate_locked_super(s);
goto out;
+
+}
+
+static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data;
+ struct nfs_fh *mntfh;
+ struct dentry *mntroot = ERR_PTR(-ENOMEM);
+ struct nfs_subversion *nfs_mod;
+ int error;
+
+ data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
+ mntfh = nfs_alloc_fhandle();
+ if (data == NULL || mntfh == NULL)
+ goto out;
+
+ /* Validate the mount data */
+ error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
+ if (error < 0) {
+ mntroot = ERR_PTR(error);
+ goto out;
+ }
+
+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod)) {
+ mntroot = (struct dentry *)nfs_mod;
+ goto out;
+ }
+
+#ifdef CONFIG_NFS_V4
+ if (data->version == 4)
+ mntroot = nfs4_try_mount(flags, dev_name, data);
+ else
+#endif /* CONFIG_NFS_V4 */
+ mntroot = generic_nfs_fs_mount(fs_type, flags, dev_name, mntfh, data);
+
+ if (!IS_ERR(mntroot))
+ nfs_mod->reference();
+
+out:
+ nfs_free_parsed_mount_data(data);
+ nfs_free_fhandle(mntfh);
+ return mntroot;
+
}
/*
--
1.7.8.3
On Jan 13, 2012, at 4:12 PM, Bryan Schumaker wrote:
> On Fri Jan 13 16:05:29 2012, Bryan Schumaker wrote:
>> On Fri Jan 13 15:48:38 2012, Chuck Lever wrote:
>>>
>>> On Jan 13, 2012, at 3:10 PM, [email protected] wrote:
>>>
>>>> From: Bryan Schumaker <[email protected]>
>>>>
>>>> The v4 code uses these functions in the generic client, so they need to
>>>> be available to modules.
>>>
>>> If you add the EXPORT_SYMBOL() macros in separate patches, is that bisect-able? Seems like you should add the macros when you move functions.
>>
>> I thought it was since it would detect namespace collisions... I can
>> fix it if I need to.
>>
>>>
>>> It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
>>
>> Not that I know of. I found examples for compiling directories as
>> modules, but not specific files or parts of files.
>
> I should have looked at how obj-$(CONFIG_PNFS_FILE_LAYOUT) is done, so
> it is possible. I would still need to split out a lot of the code into
> nfs4 specific files to get the module to compile.
Do you have specific examples of what needs to be split?
> This would create a
> lot more files in fs/nfs/ directory, especially for NFS v4. I figured
> subdirectories might be easier to work with, especially if we're going
> to name everything with nfs3 or nfs4 as a prefix anyway.
Moving existing code around like this makes it harder to forward and back-port patches, and it truncates the "git blame" history on all these files. Ideally we might want subdirectories, if we were starting from scratch, but that's not where we are today.
I vote for starting with something simpler, for example modularizing just NFSv2 and NFSv3. We might want to split this work over more than one kernel release anyway, to avoid introducing a lot of churn and bugs all at once, and that's one way to divide the effort.
> - Bryan
>
>>
>>>
>>>> Signed-off-by: Bryan Schumaker <[email protected]>
>>>> ---
>>>> fs/nfs/client.c | 2 ++
>>>> fs/nfs/dir.c | 2 ++
>>>> fs/nfs/dns_resolve.c | 4 ++++
>>>> fs/nfs/fscache.c | 4 ++++
>>>> fs/nfs/inode.c | 9 +++++++++
>>>> fs/nfs/namespace.c | 1 +
>>>> fs/nfs/super.c | 2 ++
>>>> fs/nfs/unlink.c | 3 +++
>>>> fs/nfs/write.c | 2 ++
>>>> 9 files changed, 29 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>>>> index 2c3f50e..0e4ddbe 100644
>>>> --- a/fs/nfs/client.c
>>>> +++ b/fs/nfs/client.c
>>>> @@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
>>>> spin_unlock(&nfs_client_lock);
>>>>
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
>>>>
>>>> static void nfs_server_remove_lists(struct nfs_server *server)
>>>> {
>>>> @@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
>>>> nfs_release_automount_timer();
>>>> dprintk("<-- nfs_free_server()\n");
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_free_server);
>>>>
>>>> /*
>>>> * Create a version 2 or 3 volume record
>>>> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
>>>> index 210284f..909f8de 100644
>>>> --- a/fs/nfs/dir.c
>>>> +++ b/fs/nfs/dir.c
>>>> @@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
>>>> {
>>>> NFS_I(dir)->cache_change_attribute++;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
>>>>
>>>> /*
>>>> * A check for whether or not the parent directory has changed.
>>>> @@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
>>>> {
>>>> return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_may_open);
>>>>
>>>> int nfs_permission(struct inode *inode, int mask)
>>>> {
>>>> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
>>>> index a6e711a..8b9aeba 100644
>>>> --- a/fs/nfs/dns_resolve.c
>>>> +++ b/fs/nfs/dns_resolve.c
>>>> @@ -6,6 +6,8 @@
>>>> * Resolves DNS hostnames into valid ip addresses
>>>> */
>>>>
>>>> +#include <linux/module.h>
>>>> +
>>>> #ifdef CONFIG_NFS_USE_KERNEL_DNS
>>>>
>>>> #include <linux/sunrpc/clnt.h>
>>>> @@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>>> kfree(ip_addr);
>>>> return ret;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>>
>>>> #else
>>>>
>>>> @@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>>> ret = -ESRCH;
>>>> return ret;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>>
>>>> int nfs_dns_resolver_init(void)
>>>> {
>>>> diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
>>>> index 419119c..94e2d51 100644
>>>> --- a/fs/nfs/fscache.c
>>>> +++ b/fs/nfs/fscache.c
>>>> @@ -9,6 +9,7 @@
>>>> * 2 of the Licence, or (at your option) any later version.
>>>> */
>>>>
>>>> +#include <linux/module.h>
>>>> #include <linux/init.h>
>>>> #include <linux/kernel.h>
>>>> #include <linux/sched.h>
>>>> @@ -163,6 +164,7 @@ non_unique:
>>>> printk(KERN_WARNING "NFS:"
>>>> " Cache request denied due to non-unique superblock keys\n");
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
>>>>
>>>> /*
>>>> * release a per-superblock cookie
>>>> @@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
>>>> nfss->fscache_key = NULL;
>>>> }
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
>>>>
>>>> /*
>>>> * Initialise the per-inode cache cookie pointer for an NFS inode.
>>>> @@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
>>>> nfs_fscache_inode_unlock(inode);
>>>> }
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
>>>>
>>>> /*
>>>> * Replace a per-inode cookie due to revalidation detecting a file having
>>>> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
>>>> index 57a68b8..d7afc2b 100644
>>>> --- a/fs/nfs/inode.c
>>>> +++ b/fs/nfs/inode.c
>>>> @@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
>>>> schedule();
>>>> return 0;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
>>>>
>>>> /**
>>>> * nfs_compat_user_ino64 - returns the user-visible inode number
>>>> @@ -421,6 +422,7 @@ out_no_inode:
>>>> dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
>>>> goto out;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_fhget);
>>>>
>>>> #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
>>>>
>>>> @@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
>>>> }
>>>> return ctx;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
>>>>
>>>> struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>>> {
>>>> @@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>>> atomic_inc(&ctx->lock_context.count);
>>>> return ctx;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(get_nfs_open_context);
>>>>
>>>> static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
>>>> {
>>>> @@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
>>>> {
>>>> __put_nfs_open_context(ctx, 0);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(put_nfs_open_context);
>>>>
>>>> /*
>>>> * Ensure that mmap has a recent RPC credential for use when writing out
>>>> @@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
>>>> list_add(&ctx->list, &nfsi->open_files);
>>>> spin_unlock(&inode->i_lock);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
>>>>
>>>> /*
>>>> * Given an inode, search for an open context with the desired characteristics
>>>> @@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
>>>> #endif /* CONFIG_NFS_V4 */
>>>> return &nfsi->vfs_inode;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_alloc_inode);
>>>>
>>>> static void nfs_i_callback(struct rcu_head *head)
>>>> {
>>>> @@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
>>>> {
>>>> call_rcu(&inode->i_rcu, nfs_i_callback);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_destroy_inode);
>>>>
>>>> static inline void nfs4_init_once(struct nfs_inode *nfsi)
>>>> {
>>>> @@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
>>>> }
>>>>
>>>> struct workqueue_struct *nfsiod_workqueue;
>>>> +EXPORT_SYMBOL_GPL(nfsiod_workqueue);
>>>>
>>>> /*
>>>> * start up the nfsiod workqueue
>>>> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
>>>> index 203b4b3..d311128 100644
>>>> --- a/fs/nfs/namespace.c
>>>> +++ b/fs/nfs/namespace.c
>>>> @@ -114,6 +114,7 @@ Elong_unlock:
>>>> Elong:
>>>> return ERR_PTR(-ENAMETOOLONG);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_path);
>>>>
>>>> #if IS_ENABLED(CONFIG_NFS_V4)
>>>> rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
>>>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>>>> index 2c8ed6f..d2d1b6b 100644
>>>> --- a/fs/nfs/super.c
>>>> +++ b/fs/nfs/super.c
>>>> @@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
>>>> if (atomic_inc_return(&server->active) == 1)
>>>> atomic_inc(&sb->s_active);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_sb_active);
>>>>
>>>> void nfs_sb_deactive(struct super_block *sb)
>>>> {
>>>> @@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
>>>> if (atomic_dec_and_test(&server->active))
>>>> deactivate_super(sb);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_sb_deactive);
>>>>
>>>> /*
>>>> * Deliver file system statistics to userspace
>>>> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
>>>> index 9f04700..32c1d70 100644
>>>> --- a/fs/nfs/unlink.c
>>>> +++ b/fs/nfs/unlink.c
>>>> @@ -5,6 +5,7 @@
>>>> *
>>>> */
>>>>
>>>> +#include <linux/module.h>
>>>> #include <linux/slab.h>
>>>> #include <linux/string.h>
>>>> #include <linux/dcache.h>
>>>> @@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
>>>>
>>>> wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
>>>>
>>>> void nfs_unblock_sillyrename(struct dentry *dentry)
>>>> {
>>>> @@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
>>>> }
>>>> spin_unlock(&dir->i_lock);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
>>>>
>>>> /**
>>>> * nfs_async_unlink - asynchronous unlinking of a file
>>>> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
>>>> index f9ca30c..0750ebb 100644
>>>> --- a/fs/nfs/write.c
>>>> +++ b/fs/nfs/write.c
>>>> @@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
>>>> }
>>>> return ret;
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_write_inode);
>>>>
>>>> /*
>>>> * flush the inode to disk.
>>>> @@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
>>>>
>>>> return sync_inode(inode, &wbc);
>>>> }
>>>> +EXPORT_SYMBOL_GPL(nfs_wb_all);
>>>>
>>>> int nfs_wb_page_cancel(struct inode *inode, struct page *page)
>>>> {
>>>> --
>>>> 1.7.8.3
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>>>> the body of a message to [email protected]
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
From: Bryan Schumaker <[email protected]>
v4 has a callback socket that needs to be closed, and v4.1 has sessions
that should be cleaned up before exiting. This function provides a
chance to do that.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 40 +++-------------------------------------
fs/nfs/nfs.h | 1 +
fs/nfs/nfs2/module.c | 5 +++++
fs/nfs/nfs3/module.c | 5 +++++
fs/nfs/nfs4/client.c | 39 +++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4/nfs4.h | 1 +
6 files changed, 54 insertions(+), 37 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ca6ebe5..d7470fa 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -137,6 +137,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
+ .shutdown_client = nfs4_shutdown_client,
.have_delegation = nfs4_have_delegation,
.have_delegated_attributes = nfs4_have_delegated_attributes,
.return_delegation = nfs4_inode_return_delegation,
@@ -282,39 +283,6 @@ error_0:
}
#ifdef CONFIG_NFS_V4
-#ifdef CONFIG_NFS_V4_1
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
- if (nfs4_has_session(clp))
- nfs4_destroy_session(clp->cl_session);
-}
-#else /* CONFIG_NFS_V4_1 */
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
-}
-#endif /* CONFIG_NFS_V4_1 */
-
-/*
- * Destroy the NFS4 callback service
- */
-static void nfs4_destroy_callback(struct nfs_client *clp)
-{
- if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down(clp->cl_mvops->minor_version);
-}
-
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
- if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
- nfs4_kill_renewd(clp);
- nfs4_shutdown_session(clp);
- nfs4_destroy_callback(clp);
- if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
- nfs_idmap_delete(clp);
-
- rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
-}
-
/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
void nfs_cleanup_cb_ident_idr(void)
{
@@ -339,9 +307,6 @@ static void nfs4_destroy_server(struct nfs_server *server)
}
#else
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-}
void nfs_cleanup_cb_ident_idr(void)
{
@@ -362,9 +327,10 @@ static void pnfs_init_server(struct nfs_server *server)
*/
static void nfs_free_client(struct nfs_client *clp)
{
+ struct nfs_subversion *nfs_mod = get_nfs_client_version(clp);
dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
- nfs4_shutdown_client(clp);
+ nfs_mod->shutdown_client(clp);
nfs_fscache_release_client_cookie(clp);
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index c3dfb7d..987656f 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -22,6 +22,7 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
void (*init_aclclient)(struct nfs_server *);
+ void (*shutdown_client)(struct nfs_client *);
int (*have_delegation)(struct inode *, fmode_t);
int (*have_delegated_attributes)(struct inode *);
int (*return_delegation)(struct inode *);
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 618ce83..7c29b04 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -19,6 +19,10 @@ static void nfs2_unreference(void)
module_put(THIS_MODULE);
}
+static void nfs2_shutdown_client(struct nfs_client *clp)
+{
+}
+
static int nfs2_no_delegation(struct inode *inode, fmode_t flags)
{
return 0;
@@ -37,6 +41,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
+ .shutdown_client = nfs2_shutdown_client,
.have_delegation = nfs2_no_delegation,
.have_delegated_attributes = nfs2_no_delegation2,
.return_delegation = nfs2_no_delegation2,
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index a999b2f..6293bf7 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -19,6 +19,10 @@ static void nfs3_unreference(void)
module_put(THIS_MODULE);
}
+static void nfs3_shutdown_client(struct nfs_client *clp)
+{
+}
+
static int nfs3_no_delegation(struct inode *inode, fmode_t flags)
{
return 0;
@@ -37,6 +41,7 @@ struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
+ .shutdown_client = nfs3_shutdown_client,
.have_delegation = nfs3_no_delegation,
.have_delegated_attributes = nfs3_no_delegation2,
.return_delegation = nfs3_no_delegation2,
diff --git a/fs/nfs/nfs4/client.c b/fs/nfs/nfs4/client.c
index bbc415d..9f53f3f 100644
--- a/fs/nfs/nfs4/client.c
+++ b/fs/nfs/nfs4/client.c
@@ -2,11 +2,50 @@
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*/
#include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_idmap.h>
#include <linux/nfs_mount.h>
+#include "nfs4_fs.h"
+#include "delegation.h"
+#include "callback.h"
+
void nfs4_init_aclclient(struct nfs_server *server)
{
server->flags &= ~NFS_MOUNT_NOACL;
server->flags &= ~NFS_CAP_ACLS;
}
+
+#ifdef CONFIG_NFS_V4_1
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+ if (nfs4_has_session(clp))
+ nfs4_destroy_session(clp->cl_session);
+}
+#else /* CONFIG_NFS_V4_1 */
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * Destroy the NFS4 callback service
+ */
+static void nfs4_destroy_callback(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ nfs_callback_down(clp->cl_mvops->minor_version);
+}
+
+void nfs4_shutdown_client(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ nfs4_kill_renewd(clp);
+ nfs4_shutdown_session(clp);
+ nfs4_destroy_callback(clp);
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
+
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 6d5cf57..97ff8d8 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -4,6 +4,7 @@
#include "../nfs.h"
void nfs4_init_aclclient(struct nfs_server *);
+void nfs4_shutdown_client(struct nfs_client *);
struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
struct vfsmount *nfs4_do_clone_mount(struct nfs_server *, const char *,
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
With this patch NFS v2 will no longer be automatically compiled in.
Instead, users will have to select NFS_V2 during Kconfig if they want to
use v2.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 9 +++++++++
fs/nfs/Makefile | 5 +++--
fs/nfs/client.c | 11 ++++++++++-
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index dbcd821..5419166 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -29,6 +29,15 @@ config NFS_FS
If unsure, say N.
+config NFS_V2
+ bool "NFS client support for NFS version 2"
+ depends on NFS_FS
+ help
+ This option enables support for version 2 of the NFS protocol
+ (RFC 1094) in the kernel's NFS client.
+
+ If unsure, say Y.
+
config NFS_V3
bool "NFS client support for NFS version 3"
depends on NFS_FS
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b58613d..7ddd45d 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -4,11 +4,12 @@
obj-$(CONFIG_NFS_FS) += nfs.o
-nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
- direct.o pagelist.o proc.o read.o symlink.o unlink.o \
+nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
+ direct.o pagelist.o read.o symlink.o unlink.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
+nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b8e9769..01cb068 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -90,7 +90,9 @@ static int nfs4_disable_idmapping = 0;
* RPC cruft for NFS
*/
static struct rpc_version *nfs_version[5] = {
+#ifdef CONFIG_NFS_V2
[2] = &nfs_version2,
+#endif
#ifdef CONFIG_NFS_V3
[3] = &nfs_version3,
#endif
@@ -829,7 +831,7 @@ static int nfs_init_server(struct nfs_server *server,
.hostname = data->nfs_server.hostname,
.addr = (const struct sockaddr *)&data->nfs_server.address,
.addrlen = data->nfs_server.addrlen,
- .rpc_ops = &nfs_v2_clientops,
+ .rpc_ops = NULL,
.proto = data->nfs_server.protocol,
};
struct rpc_timeout timeparms;
@@ -838,10 +840,17 @@ static int nfs_init_server(struct nfs_server *server,
dprintk("--> nfs_init_server()\n");
+
+#ifdef CONFIG_NFS_V2
+ if (data->version == 2)
+ cl_init.rpc_ops = &nfs_v2_clientops;
+#endif
#ifdef CONFIG_NFS_V3
if (data->version == 3)
cl_init.rpc_ops = &nfs_v3_clientops;
#endif
+ if (cl_init.rpc_ops == NULL)
+ return -EPROTONOSUPPORT;
nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans);
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This allows for a separate function in the v4 case, which can evenutally
be called from a pointer in the struct nfs_subversion.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/super.c | 46 ++++++++++++++++++++++++++--------------------
1 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 861d31e..b5ffc6a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1744,6 +1744,30 @@ out_path:
return -ENAMETOOLONG;
}
+int nfs_validate_text_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ struct nfs_fh *mntfh,
+ const char *dev_name)
+{
+ int status;
+ struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+
+ nfs_set_port(sap, &args->nfs_server.port, 0);
+ nfs_set_mount_transport_protocol(args);
+ status = nfs_parse_devname(dev_name,
+ &args->nfs_server.hostname,
+ PAGE_SIZE,
+ &args->nfs_server.export_path,
+ NFS_MAXPATHLEN);
+ if (!status)
+ status = nfs_try_mount(args, mntfh);
+
+ kfree(args->nfs_server.export_path);
+ args->nfs_server.export_path = NULL;
+
+ return status;
+}
+
/*
* Validate the NFS2/NFS3 mount data
* - fills in the mount root filehandle
@@ -1869,8 +1893,6 @@ static int nfs_validate_mount_data(void *options,
break;
default: {
- int status;
-
if (nfs_parse_mount_options((char *)options, args) == 0)
return -EINVAL;
@@ -1884,24 +1906,8 @@ static int nfs_validate_mount_data(void *options,
#else
goto out_v4_not_compiled;
#endif
-
- nfs_set_port(sap, &args->nfs_server.port, 0);
-
- nfs_set_mount_transport_protocol(args);
-
- status = nfs_parse_devname(dev_name,
- &args->nfs_server.hostname,
- PAGE_SIZE,
- &args->nfs_server.export_path,
- NFS_MAXPATHLEN);
- if (!status)
- status = nfs_try_mount(args, mntfh);
-
- kfree(args->nfs_server.export_path);
- args->nfs_server.export_path = NULL;
-
- if (status)
- return status;
+ else
+ return nfs_validate_text_mount_data(options, args, mntfh, dev_name);
break;
}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This gives v4 the opportunity to validate its own options while v2 and
v3 share the same validation function.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/nfs.h | 7 +++++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs4/nfs4.h | 2 ++
fs/nfs/super.c | 28 +++++++++++-----------------
6 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 60d0f57..998c3be 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -136,6 +136,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
+ .validate_mount_data = nfs4_validate_text_mount_data,
.init_aclclient = nfs4_init_aclclient,
.try_mount = nfs4_try_mount,
.shutdown_client = nfs4_shutdown_client,
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 847f593..3aa900d 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -22,6 +22,10 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
+ int (*validate_mount_data)(void *,
+ struct nfs_parsed_mount_data *,
+ struct nfs_fh *,
+ const char *);
void (*init_aclclient)(struct nfs_server *);
struct dentry *(*try_mount)(struct file_system_type *, int,
const char *, struct nfs_fh *,
@@ -96,4 +100,7 @@ struct vfsmount *nfs_do_clone_mount(struct nfs_server *, const char *,
struct dentry *generic_nfs_fs_mount(struct file_system_type *, int,
const char *, struct nfs_fh *,
struct nfs_parsed_mount_data *);
+int nfs_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
+ struct nfs_fh *, const char *);
+
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 9bc06ab..5efe3d8 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -40,6 +40,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
+ .validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs2_init_aclclient,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs2_shutdown_client,
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 3ca0066..f9c979f 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -40,6 +40,7 @@ struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
+ .validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs3_init_aclclient,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs3_shutdown_client,
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 2428896..6ff094f 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -12,5 +12,7 @@ struct vfsmount *nfs4_do_clone_mount(struct nfs_server *, const char *,
int nfs4_have_delegated_attributes(struct inode *);
struct dentry *nfs4_try_mount(struct file_system_type *, int, const char *,
struct nfs_fh *, struct nfs_parsed_mount_data *);
+int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
+ struct nfs_fh *, const char *);
#endif /* __LINUX_FS_NFS_NFS4_H */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b5ffc6a..e1ea351 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -309,8 +309,6 @@ static const struct super_operations nfs_sops = {
};
#ifdef CONFIG_NFS_V4
-static int nfs4_validate_text_mount_data(void *options,
- struct nfs_parsed_mount_data *args, const char *dev_name);
static struct dentry *nfs4_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
@@ -1767,6 +1765,7 @@ int nfs_validate_text_mount_data(void *options,
return status;
}
+EXPORT_SYMBOL_GPL(nfs_validate_text_mount_data);
/*
* Validate the NFS2/NFS3 mount data
@@ -1791,6 +1790,7 @@ static int nfs_validate_mount_data(void *options,
{
struct nfs_mount_data *data = (struct nfs_mount_data *)options;
struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+ struct nfs_subversion *nfs_mod;
if (data == NULL)
goto out_no_data;
@@ -1899,17 +1899,10 @@ static int nfs_validate_mount_data(void *options,
if (!nfs_verify_server_address(sap))
goto out_no_address;
- if (args->version == 4)
-#ifdef CONFIG_NFS_V4
- return nfs4_validate_text_mount_data(options,
- args, dev_name);
-#else
- goto out_v4_not_compiled;
-#endif
- else
- return nfs_validate_text_mount_data(options, args, mntfh, dev_name);
-
- break;
+ nfs_mod = get_nfs_version(args->version);
+ if (IS_ERR(nfs_mod))
+ return PTR_ERR(nfs_mod);
+ return nfs_mod->validate_mount_data(options, args, mntfh, dev_name);
}
}
@@ -2504,9 +2497,10 @@ static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
}
-static int nfs4_validate_text_mount_data(void *options,
- struct nfs_parsed_mount_data *args,
- const char *dev_name)
+int nfs4_validate_text_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ struct nfs_fh *mntfh,
+ const char *dev_name)
{
struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
@@ -2617,7 +2611,7 @@ static int nfs4_validate_mount_data(void *options,
if (!nfs_verify_server_address(sap))
return -EINVAL;
- return nfs4_validate_text_mount_data(options, args, dev_name);
+ return nfs4_validate_text_mount_data(options, args, NULL, dev_name);
}
return 0;
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This should be filled in by the v2, v3 and v4 nfs_subversion structures
for creating an aclclient. Right now, v2 and v4 clear the flags while
v3 does some extra setup.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 17 ++++++++++++-----
fs/nfs/nfs.h | 1 +
fs/nfs/nfs2/Makefile | 2 +-
fs/nfs/nfs2/client.c | 12 ++++++++++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs2/nfs2.h | 2 ++
6 files changed, 29 insertions(+), 6 deletions(-)
create mode 100644 fs/nfs/nfs2/client.c
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 20d1708..3f36e6e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -53,6 +53,8 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT
+static void nfs_init_server_aclclient(struct nfs_server *server);
+
static DEFINE_SPINLOCK(nfs_client_lock);
static DEFINE_SPINLOCK(nfs_version_lock);
static LIST_HEAD(nfs_versions);
@@ -132,8 +134,10 @@ static struct nfs_subversion nfs_v3_mod = {
.version = 3,
.rpc_vers = &nfs_version3,
.rpc_ops = &nfs_v3_clientops,
+
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
+ .init_aclclient = nfs_init_server_aclclient,
};
#endif /* CONFIG_NFS_V3 */
@@ -142,8 +146,10 @@ static struct nfs_subversion nfs_v4_mod = {
.version = 4,
.rpc_vers = &nfs_version4,
.rpc_ops = &nfs_v4_clientops,
+
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
+ .init_aclclient = nfs_init_server_aclclient,
};
#endif /* CONFIG_NFS_V4 */
@@ -830,8 +836,6 @@ static int nfs_start_lockd(struct nfs_server *server)
#ifdef CONFIG_NFS_V3_ACL
static void nfs_init_server_aclclient(struct nfs_server *server)
{
- if (server->nfs_client->rpc_ops->version != 3)
- goto out_noacl;
if (server->flags & NFS_MOUNT_NOACL)
goto out_noacl;
@@ -1001,7 +1005,7 @@ static int nfs_init_server(struct nfs_server *server,
server->namelen = data->namlen;
/* Create a client RPC handle for the NFSv3 ACL management interface */
- nfs_init_server_aclclient(server);
+ nfs_mod->init_aclclient(server);
dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
return 0;
@@ -1814,6 +1818,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
{
struct nfs_server *server;
struct nfs_fattr *fattr_fsinfo;
+ struct nfs_subversion *nfs_mod;
int error;
dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
@@ -1842,8 +1847,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
source->client->cl_auth->au_flavor);
if (error < 0)
goto out_free_server;
- if (!IS_ERR(source->client_acl))
- nfs_init_server_aclclient(server);
+ if (!IS_ERR(source->client_acl)) {
+ nfs_mod = get_nfs_server_version(server);
+ nfs_mod->init_aclclient(server);
+ }
/* probe the filesystem info for this server filesystem */
error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index b1fe653..6b746d7 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -19,6 +19,7 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
+ void (*init_aclclient)(struct nfs_server *);
};
void nfs_register_versions(void);
diff --git a/fs/nfs/nfs2/Makefile b/fs/nfs/nfs2/Makefile
index 0ca3b59..d5de35f 100644
--- a/fs/nfs/nfs2/Makefile
+++ b/fs/nfs/nfs2/Makefile
@@ -2,4 +2,4 @@
# Makefile for NFS v2
#
obj-$(CONFIG_NFS_V2) += nfs2.o
-nfs2-y := module.o dir.o file.o proc.o xdr.o
+nfs2-y := module.o client.o dir.o file.o proc.o xdr.o
diff --git a/fs/nfs/nfs2/client.c b/fs/nfs/nfs2/client.c
new file mode 100644
index 0000000..1150704
--- /dev/null
+++ b/fs/nfs/nfs2/client.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+
+void nfs2_init_aclclient(struct nfs_server *server)
+{
+ server->flags &= ~NFS_MOUNT_NOACL;
+ server->caps &= ~NFS_CAP_ACLS;
+}
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 04d415a..60302c7 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -26,6 +26,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
+ .init_aclclient = nfs2_init_aclclient,
};
static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs2/nfs2.h b/fs/nfs/nfs2/nfs2.h
index 6274821..76e62bf 100644
--- a/fs/nfs/nfs2/nfs2.h
+++ b/fs/nfs/nfs2/nfs2.h
@@ -7,6 +7,8 @@
extern struct rpc_version nfs_version2;
extern const struct nfs_rpc_ops nfs_v2_clientops;
+void nfs2_init_aclclient(struct nfs_server *);
+
extern const struct inode_operations nfs_file_inode_operations;
extern const struct file_operations nfs_file_operations;
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 3 +-
fs/nfs/dir.c | 331 +----------------------------------------------------
fs/nfs/nfs.h | 2 +
fs/nfs/nfs4/dir.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 335 insertions(+), 328 deletions(-)
create mode 100644 fs/nfs/nfs4/dir.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 041f947..6bb7470 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -14,7 +14,8 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
nfs4/client.o nfs4/module.o nfs4/sysctl.o \
- nfs4/getroot.o nfs4/inode.o nfs4/file.o
+ nfs4/getroot.o nfs4/inode.o nfs4/file.o \
+ nfs4/dir.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index b72aab3..210284f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -65,31 +65,6 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};
-#ifdef CONFIG_NFS_V4
-
-static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
-const struct inode_operations nfs4_dir_inode_operations = {
- .create = nfs_open_create,
- .lookup = nfs_atomic_lookup,
- .link = nfs_link,
- .unlink = nfs_unlink,
- .symlink = nfs_symlink,
- .mkdir = nfs_mkdir,
- .rmdir = nfs_rmdir,
- .mknod = nfs_mknod,
- .rename = nfs_rename,
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-};
-
-#endif /* CONFIG_NFS_V4 */
-
static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred)
{
struct nfs_open_dir_context *ctx;
@@ -971,11 +946,12 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
* component of the path and none of them is set before that last
* component.
*/
-static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
+inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
unsigned int mask)
{
return nd->flags & mask;
}
+EXPORT_SYMBOL_GPL(nfs_lookup_check_intent);
/*
* Use intent information to check whether or not we're going to do
@@ -1027,7 +1003,7 @@ out_force:
* If parent mtime has changed, we revalidate, else we wait for a
* period corresponding to the parent's attribute cache timeout value.
*/
-static inline
+inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
@@ -1038,6 +1014,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
return 1;
return !nfs_check_verifier(dir, dentry);
}
+EXPORT_SYMBOL_GPL(nfs_neg_need_reval);
/*
* This is called every time the dcache has a lookup hit,
@@ -1280,306 +1257,6 @@ out:
}
EXPORT_SYMBOL_GPL(nfs_lookup);
-#ifdef CONFIG_NFS_V4
-static int nfs_open_revalidate(struct dentry *, struct nameidata *);
-
-const struct dentry_operations nfs4_dentry_operations = {
- .d_revalidate = nfs_open_revalidate,
- .d_delete = nfs_dentry_delete,
- .d_iput = nfs_dentry_iput,
- .d_automount = nfs_d_automount,
- .d_release = nfs_d_release,
-};
-
-/*
- * Use intent information to determine whether we need to substitute
- * the NFSv4-style stateful OPEN for the LOOKUP call
- */
-static int is_atomic_open(struct nameidata *nd)
-{
- if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
- return 0;
- /* NFS does not (yet) have a stateful open for directories */
- if (nd->flags & LOOKUP_DIRECTORY)
- return 0;
- /* Are we trying to write to a read only partition? */
- if (__mnt_is_readonly(nd->path.mnt) &&
- (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
- return 0;
- return 1;
-}
-
-static fmode_t flags_to_mode(int flags)
-{
- fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
- if ((flags & O_ACCMODE) != O_WRONLY)
- res |= FMODE_READ;
- if ((flags & O_ACCMODE) != O_RDONLY)
- res |= FMODE_WRITE;
- return res;
-}
-
-static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags)
-{
- struct nfs_open_context *ctx;
- struct rpc_cred *cred;
- fmode_t fmode = flags_to_mode(open_flags);
-
- cred = rpc_lookup_cred();
- if (IS_ERR(cred))
- return ERR_CAST(cred);
- ctx = alloc_nfs_open_context(dentry, cred, fmode);
- put_rpccred(cred);
- if (ctx == NULL)
- return ERR_PTR(-ENOMEM);
- return ctx;
-}
-
-static int do_open(struct inode *inode, struct file *filp)
-{
- nfs_fscache_set_inode_cookie(inode, filp);
- return 0;
-}
-
-static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
-{
- struct file *filp;
- int ret = 0;
-
- /* If the open_intent is for execute, we have an extra check to make */
- if (ctx->mode & FMODE_EXEC) {
- ret = nfs_may_open(ctx->dentry->d_inode,
- ctx->cred,
- nd->intent.open.flags);
- if (ret < 0)
- goto out;
- }
- filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
- if (IS_ERR(filp))
- ret = PTR_ERR(filp);
- else
- nfs_file_set_open_context(filp, ctx);
-out:
- put_nfs_open_context(ctx);
- return ret;
-}
-
-static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct nfs_open_context *ctx;
- struct iattr attr;
- struct dentry *res = NULL;
- struct inode *inode;
- int open_flags;
- int err;
-
- dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
-
- /* Check that we are indeed trying to open this file */
- if (!is_atomic_open(nd))
- goto no_open;
-
- if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
- res = ERR_PTR(-ENAMETOOLONG);
- goto out;
- }
-
- /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
- * the dentry. */
- if (nd->flags & LOOKUP_EXCL) {
- d_instantiate(dentry, NULL);
- goto out;
- }
-
- open_flags = nd->intent.open.flags;
-
- ctx = create_nfs_open_context(dentry, open_flags);
- res = ERR_CAST(ctx);
- if (IS_ERR(ctx))
- goto out;
-
- if (nd->flags & LOOKUP_CREATE) {
- attr.ia_mode = nd->intent.open.create_mode;
- attr.ia_valid = ATTR_MODE;
- attr.ia_mode &= ~current_umask();
- } else {
- open_flags &= ~(O_EXCL | O_CREAT);
- attr.ia_valid = 0;
- }
-
- /* Open the file on the server */
- nfs_block_sillyrename(dentry->d_parent);
- inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
- if (IS_ERR(inode)) {
- nfs_unblock_sillyrename(dentry->d_parent);
- put_nfs_open_context(ctx);
- switch (PTR_ERR(inode)) {
- /* Make a negative dentry */
- case -ENOENT:
- d_add(dentry, NULL);
- res = NULL;
- goto out;
- /* This turned out not to be a regular file */
- case -EISDIR:
- case -ENOTDIR:
- goto no_open;
- case -ELOOP:
- if (!(nd->intent.open.flags & O_NOFOLLOW))
- goto no_open;
- /* case -EINVAL: */
- default:
- res = ERR_CAST(inode);
- goto out;
- }
- }
- res = d_add_unique(dentry, inode);
- nfs_unblock_sillyrename(dentry->d_parent);
- if (res != NULL) {
- dput(ctx->dentry);
- ctx->dentry = dget(res);
- dentry = res;
- }
- err = nfs_intent_set_file(nd, ctx);
- if (err < 0) {
- if (res != NULL)
- dput(res);
- return ERR_PTR(err);
- }
-out:
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- return res;
-no_open:
- return nfs_lookup(dir, dentry, nd);
-}
-
-static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
- struct dentry *parent = NULL;
- struct inode *inode;
- struct inode *dir;
- struct nfs_open_context *ctx;
- int openflags, ret = 0;
-
- if (nd->flags & LOOKUP_RCU)
- return -ECHILD;
-
- inode = dentry->d_inode;
- if (!is_atomic_open(nd) || d_mountpoint(dentry))
- goto no_open;
-
- parent = dget_parent(dentry);
- dir = parent->d_inode;
-
- /* We can't create new files in nfs_open_revalidate(), so we
- * optimize away revalidation of negative dentries.
- */
- if (inode == NULL) {
- if (!nfs_neg_need_reval(dir, dentry, nd))
- ret = 1;
- goto out;
- }
-
- /* NFS only supports OPEN on regular files */
- if (!S_ISREG(inode->i_mode))
- goto no_open_dput;
- openflags = nd->intent.open.flags;
- /* We cannot do exclusive creation on a positive dentry */
- if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
- goto no_open_dput;
- /* We can't create new files, or truncate existing ones here */
- openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
-
- ctx = create_nfs_open_context(dentry, openflags);
- ret = PTR_ERR(ctx);
- if (IS_ERR(ctx))
- goto out;
- /*
- * Note: we're not holding inode->i_mutex and so may be racing with
- * operations that change the directory. We therefore save the
- * change attribute *before* we do the RPC call.
- */
- inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
- if (IS_ERR(inode)) {
- ret = PTR_ERR(inode);
- switch (ret) {
- case -EPERM:
- case -EACCES:
- case -EDQUOT:
- case -ENOSPC:
- case -EROFS:
- goto out_put_ctx;
- default:
- goto out_drop;
- }
- }
- iput(inode);
- if (inode != dentry->d_inode)
- goto out_drop;
-
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- ret = nfs_intent_set_file(nd, ctx);
- if (ret >= 0)
- ret = 1;
-out:
- dput(parent);
- return ret;
-out_drop:
- d_drop(dentry);
- ret = 0;
-out_put_ctx:
- put_nfs_open_context(ctx);
- goto out;
-
-no_open_dput:
- dput(parent);
-no_open:
- return nfs_lookup_revalidate(dentry, nd);
-}
-
-static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
-{
- struct nfs_open_context *ctx = NULL;
- struct iattr attr;
- int error;
- int open_flags = O_CREAT|O_EXCL;
-
- dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
-
- attr.ia_mode = mode;
- attr.ia_valid = ATTR_MODE;
-
- if (nd)
- open_flags = nd->intent.open.flags;
-
- ctx = create_nfs_open_context(dentry, open_flags);
- error = PTR_ERR(ctx);
- if (IS_ERR(ctx))
- goto out_err_drop;
-
- error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
- if (error != 0)
- goto out_put_ctx;
- if (nd) {
- error = nfs_intent_set_file(nd, ctx);
- if (error < 0)
- goto out_err;
- } else {
- put_nfs_open_context(ctx);
- }
- return 0;
-out_put_ctx:
- put_nfs_open_context(ctx);
-out_err_drop:
- d_drop(dentry);
-out_err:
- return error;
-}
-
-#endif /* CONFIG_NFSV4 */
-
/*
* Code common to create, mkdir, and mknod.
*/
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index cff0f23..2cdcbcf 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -72,6 +72,8 @@ int nfs_symlink(struct inode *, struct dentry *, const char *);
int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
int nfs_permission(struct inode *, int);
+unsigned int nfs_lookup_check_intent(struct nameidata *, unsigned int);
+int nfs_neg_need_reval(struct inode *, struct dentry *, struct nameidata *);
/* Exported in file.c */
int nfs_check_flags(int);
diff --git a/fs/nfs/nfs4/dir.c b/fs/nfs/nfs4/dir.c
new file mode 100644
index 0000000..2d897f5
--- /dev/null
+++ b/fs/nfs/nfs4/dir.c
@@ -0,0 +1,327 @@
+
+#include <linux/nfs_fs.h>
+#include <linux/namei.h>
+
+#include "../internal.h"
+#include "../fscache.h"
+#include "delegation.h"
+#include "../nfs.h"
+#include "nfs4.h"
+
+static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int nfs_open_create(struct inode *, struct dentry *, int, struct nameidata *);
+static int nfs_open_revalidate(struct dentry *, struct nameidata *);
+
+const struct inode_operations nfs4_dir_inode_operations = {
+ .create = nfs_open_create,
+ .lookup = nfs_atomic_lookup,
+ .link = nfs_link,
+ .unlink = nfs_unlink,
+ .symlink = nfs_symlink,
+ .mkdir = nfs_mkdir,
+ .rmdir = nfs_rmdir,
+ .mknod = nfs_mknod,
+ .rename = nfs_rename,
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .getxattr = generic_getxattr,
+ .setxattr = generic_setxattr,
+ .listxattr = generic_listxattr,
+ .removexattr = generic_removexattr,
+};
+
+const struct dentry_operations nfs4_dentry_operations = {
+ .d_revalidate = nfs_open_revalidate,
+ .d_delete = nfs_dentry_delete,
+ .d_iput = nfs_dentry_iput,
+ .d_automount = nfs_d_automount,
+ .d_release = nfs_d_release,
+};
+
+/*
+ * Use intent information to determine whether we need to substitute
+ * the NFSv4-style stateful OPEN for the LOOKUP call
+ */
+static int is_atomic_open(struct nameidata *nd)
+{
+ if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
+ return 0;
+ /* NFS does not (yet) have a stateful open for directories */
+ if (nd->flags & LOOKUP_DIRECTORY)
+ return 0;
+ /* Are we trying to write to a read only partition? */
+ if (__mnt_is_readonly(nd->path.mnt) &&
+ (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
+ return 0;
+ return 1;
+}
+
+static fmode_t flags_to_mode(int flags)
+{
+ fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
+ if ((flags & O_ACCMODE) != O_WRONLY)
+ res |= FMODE_READ;
+ if ((flags & O_ACCMODE) != O_RDONLY)
+ res |= FMODE_WRITE;
+ return res;
+}
+
+static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags)
+{
+ struct nfs_open_context *ctx;
+ struct rpc_cred *cred;
+ fmode_t fmode = flags_to_mode(open_flags);
+
+ cred = rpc_lookup_cred();
+ if (IS_ERR(cred))
+ return ERR_CAST(cred);
+ ctx = alloc_nfs_open_context(dentry, cred, fmode);
+ put_rpccred(cred);
+ if (ctx == NULL)
+ return ERR_PTR(-ENOMEM);
+ return ctx;
+}
+
+static int do_open(struct inode *inode, struct file *filp)
+{
+ nfs_fscache_set_inode_cookie(inode, filp);
+ return 0;
+}
+
+static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+{
+ struct file *filp;
+ int ret = 0;
+
+ /* If the open_intent is for execute, we have an extra check to make */
+ if (ctx->mode & FMODE_EXEC) {
+ ret = nfs_may_open(ctx->dentry->d_inode,
+ ctx->cred,
+ nd->intent.open.flags);
+ if (ret < 0)
+ goto out;
+ }
+ filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
+ if (IS_ERR(filp))
+ ret = PTR_ERR(filp);
+ else
+ nfs_file_set_open_context(filp, ctx);
+out:
+ put_nfs_open_context(ctx);
+ return ret;
+}
+
+static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+ struct nfs_open_context *ctx;
+ struct iattr attr;
+ struct dentry *res = NULL;
+ struct inode *inode;
+ int open_flags;
+ int err;
+
+ dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+
+ /* Check that we are indeed trying to open this file */
+ if (!is_atomic_open(nd))
+ goto no_open;
+
+ if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
+ res = ERR_PTR(-ENAMETOOLONG);
+ goto out;
+ }
+
+ /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
+ * the dentry. */
+ if (nd->flags & LOOKUP_EXCL) {
+ d_instantiate(dentry, NULL);
+ goto out;
+ }
+
+ open_flags = nd->intent.open.flags;
+
+ ctx = create_nfs_open_context(dentry, open_flags);
+ res = ERR_CAST(ctx);
+ if (IS_ERR(ctx))
+ goto out;
+
+ if (nd->flags & LOOKUP_CREATE) {
+ attr.ia_mode = nd->intent.open.create_mode;
+ attr.ia_valid = ATTR_MODE;
+ attr.ia_mode &= ~current_umask();
+ } else {
+ open_flags &= ~(O_EXCL | O_CREAT);
+ attr.ia_valid = 0;
+ }
+
+ /* Open the file on the server */
+ nfs_block_sillyrename(dentry->d_parent);
+ inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+ if (IS_ERR(inode)) {
+ nfs_unblock_sillyrename(dentry->d_parent);
+ put_nfs_open_context(ctx);
+ switch (PTR_ERR(inode)) {
+ /* Make a negative dentry */
+ case -ENOENT:
+ d_add(dentry, NULL);
+ res = NULL;
+ goto out;
+ /* This turned out not to be a regular file */
+ case -EISDIR:
+ case -ENOTDIR:
+ goto no_open;
+ case -ELOOP:
+ if (!(nd->intent.open.flags & O_NOFOLLOW))
+ goto no_open;
+ /* case -EINVAL: */
+ default:
+ res = ERR_CAST(inode);
+ goto out;
+ }
+ }
+ res = d_add_unique(dentry, inode);
+ nfs_unblock_sillyrename(dentry->d_parent);
+ if (res != NULL) {
+ dput(ctx->dentry);
+ ctx->dentry = dget(res);
+ dentry = res;
+ }
+ err = nfs_intent_set_file(nd, ctx);
+ if (err < 0) {
+ if (res != NULL)
+ dput(res);
+ return ERR_PTR(err);
+ }
+out:
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ return res;
+no_open:
+ return nfs_lookup(dir, dentry, nd);
+}
+
+static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+ struct dentry *parent = NULL;
+ struct inode *inode;
+ struct inode *dir;
+ struct nfs_open_context *ctx;
+ int openflags, ret = 0;
+
+ if (nd->flags & LOOKUP_RCU)
+ return -ECHILD;
+
+ inode = dentry->d_inode;
+ if (!is_atomic_open(nd) || d_mountpoint(dentry))
+ goto no_open;
+
+ parent = dget_parent(dentry);
+ dir = parent->d_inode;
+
+ /* We can't create new files in nfs_open_revalidate(), so we
+ * optimize away revalidation of negative dentries.
+ */
+ if (inode == NULL) {
+ if (!nfs_neg_need_reval(dir, dentry, nd))
+ ret = 1;
+ goto out;
+ }
+
+ /* NFS only supports OPEN on regular files */
+ if (!S_ISREG(inode->i_mode))
+ goto no_open_dput;
+ openflags = nd->intent.open.flags;
+ /* We cannot do exclusive creation on a positive dentry */
+ if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+ goto no_open_dput;
+ /* We can't create new files, or truncate existing ones here */
+ openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
+
+ ctx = create_nfs_open_context(dentry, openflags);
+ ret = PTR_ERR(ctx);
+ if (IS_ERR(ctx))
+ goto out;
+ /*
+ * Note: we're not holding inode->i_mutex and so may be racing with
+ * operations that change the directory. We therefore save the
+ * change attribute *before* we do the RPC call.
+ */
+ inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
+ if (IS_ERR(inode)) {
+ ret = PTR_ERR(inode);
+ switch (ret) {
+ case -EPERM:
+ case -EACCES:
+ case -EDQUOT:
+ case -ENOSPC:
+ case -EROFS:
+ goto out_put_ctx;
+ default:
+ goto out_drop;
+ }
+ }
+ iput(inode);
+ if (inode != dentry->d_inode)
+ goto out_drop;
+
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ ret = nfs_intent_set_file(nd, ctx);
+ if (ret >= 0)
+ ret = 1;
+out:
+ dput(parent);
+ return ret;
+out_drop:
+ d_drop(dentry);
+ ret = 0;
+out_put_ctx:
+ put_nfs_open_context(ctx);
+ goto out;
+
+no_open_dput:
+ dput(parent);
+no_open:
+ return nfs_lookup_revalidate(dentry, nd);
+}
+
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
+{
+ struct nfs_open_context *ctx = NULL;
+ struct iattr attr;
+ int error;
+ int open_flags = O_CREAT|O_EXCL;
+
+ dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+
+ attr.ia_mode = mode;
+ attr.ia_valid = ATTR_MODE;
+
+ if (nd)
+ open_flags = nd->intent.open.flags;
+
+ ctx = create_nfs_open_context(dentry, open_flags);
+ error = PTR_ERR(ctx);
+ if (IS_ERR(ctx))
+ goto out_err_drop;
+
+ error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
+ if (error != 0)
+ goto out_put_ctx;
+ if (nd) {
+ error = nfs_intent_set_file(nd, ctx);
+ if (error < 0)
+ goto out_err;
+ } else {
+ put_nfs_open_context(ctx);
+ }
+ return 0;
+out_put_ctx:
+ put_nfs_open_context(ctx);
+out_err_drop:
+ d_drop(dentry);
+out_err:
+ return error;
+}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This gives v4 a chance to initialize the client idr structure.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 42 +++++++++++++++++++++++-------------------
fs/nfs/nfs.h | 10 ++++++++++
fs/nfs/nfs2/client.c | 6 ++++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs2/nfs2.h | 3 +++
fs/nfs/nfs3/client.c | 4 ++++
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs3/nfs3.h | 3 +++
fs/nfs/nfs4/nfs4.h | 1 +
9 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index dc10b2e..a4b7634 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -139,6 +139,7 @@ static struct nfs_subversion nfs_v4_mod = {
.unreference = nfs_module_null_function,
.validate_mount_data = nfs4_validate_text_mount_data,
.init_aclclient = nfs4_init_aclclient,
+ .alloc_client = nfs4_alloc_client,
.try_mount = nfs4_try_mount,
.shutdown_client = nfs4_shutdown_client,
.have_delegation = nfs4_have_delegation,
@@ -149,15 +150,6 @@ static struct nfs_subversion nfs_v4_mod = {
};
#endif /* CONFIG_NFS_V4 */
-struct nfs_client_initdata {
- const char *hostname;
- const struct sockaddr *addr;
- size_t addrlen;
- const struct nfs_rpc_ops *rpc_ops;
- int proto;
- u32 minorversion;
-};
-
struct nfs_subversion *get_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs;
@@ -224,6 +216,25 @@ void __init nfs_register_versions(void)
#endif
}
+#ifdef CONFIG_NFS_V4
+int nfs4_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
+{
+ int err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ if (err)
+ return err;
+
+ spin_lock_init(&clp->cl_lock);
+ INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+ clp->cl_boot_time = CURRENT_TIME;
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
+ clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+
+ return 0;
+}
+#endif
+
/*
* Allocate a shared client record
*
@@ -234,6 +245,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
{
struct nfs_client *clp;
struct rpc_cred *cred;
+ struct nfs_subversion *nfs_mod;
int err = -ENOMEM;
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
@@ -259,19 +271,11 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp->cl_proto = cl_init->proto;
-#ifdef CONFIG_NFS_V4
- err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ nfs_mod = get_nfs_client_version(clp);
+ err = nfs_mod->alloc_client(clp, cl_init);
if (err)
goto error_cleanup;
- spin_lock_init(&clp->cl_lock);
- INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
- clp->cl_boot_time = CURRENT_TIME;
- clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
- clp->cl_minorversion = cl_init->minorversion;
- clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
-#endif
cred = rpc_lookup_machine_cred("*");
if (!IS_ERR(cred))
clp->cl_machine_cred = cred;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 3aa900d..b2a930d 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -14,6 +14,15 @@
struct nfs_clone_mount;
struct nfs_parsed_mount_data;
+struct nfs_client_initdata {
+ const char *hostname;
+ const struct sockaddr *addr;
+ size_t addrlen;
+ const struct nfs_rpc_ops *rpc_ops;
+ int proto;
+ u32 minorversion;
+};
+
struct nfs_subversion {
unsigned int version; /* Protocol number */
struct rpc_version *rpc_vers; /* NFS version information */
@@ -27,6 +36,7 @@ struct nfs_subversion {
struct nfs_fh *,
const char *);
void (*init_aclclient)(struct nfs_server *);
+ int (*alloc_client)(struct nfs_client *, const struct nfs_client_initdata *);
struct dentry *(*try_mount)(struct file_system_type *, int,
const char *, struct nfs_fh *,
struct nfs_parsed_mount_data *);
diff --git a/fs/nfs/nfs2/client.c b/fs/nfs/nfs2/client.c
index 1150704..36d6499 100644
--- a/fs/nfs/nfs2/client.c
+++ b/fs/nfs/nfs2/client.c
@@ -4,9 +4,15 @@
#include <linux/sunrpc/sched.h>
#include <linux/nfs_fs_sb.h>
#include <linux/nfs_mount.h>
+#include "nfs2.h"
void nfs2_init_aclclient(struct nfs_server *server)
{
server->flags &= ~NFS_MOUNT_NOACL;
server->caps &= ~NFS_CAP_ACLS;
}
+
+int nfs2_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
+{
+ return 0;
+}
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 5efe3d8..e527001 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -42,6 +42,7 @@ struct nfs_subversion nfs_v2 = {
.unreference = nfs2_unreference,
.validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs2_init_aclclient,
+ .alloc_client = nfs2_alloc_client,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs2_shutdown_client,
.have_delegation = nfs2_no_delegation,
diff --git a/fs/nfs/nfs2/nfs2.h b/fs/nfs/nfs2/nfs2.h
index 76e62bf..2ce1245 100644
--- a/fs/nfs/nfs2/nfs2.h
+++ b/fs/nfs/nfs2/nfs2.h
@@ -4,10 +4,13 @@
#include <linux/fs.h>
#include <linux/sunrpc/clnt.h>
+#include "../nfs.h"
+
extern struct rpc_version nfs_version2;
extern const struct nfs_rpc_ops nfs_v2_clientops;
void nfs2_init_aclclient(struct nfs_server *);
+int nfs2_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
extern const struct inode_operations nfs_file_inode_operations;
extern const struct file_operations nfs_file_operations;
diff --git a/fs/nfs/nfs3/client.c b/fs/nfs/nfs3/client.c
index 9f7e997..4aa2024 100644
--- a/fs/nfs/nfs3/client.c
+++ b/fs/nfs/nfs3/client.c
@@ -56,3 +56,7 @@ void nfs3_init_aclclient(struct nfs_server *server)
}
#endif
+int nfs3_alloc_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init)
+{
+ return 0;
+}
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index f9c979f..a63dbe7 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -42,6 +42,7 @@ struct nfs_subversion nfs_v3 = {
.unreference = nfs3_unreference,
.validate_mount_data = nfs_validate_text_mount_data,
.init_aclclient = nfs3_init_aclclient,
+ .alloc_client = nfs3_alloc_client,
.try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs3_shutdown_client,
.have_delegation = nfs3_no_delegation,
diff --git a/fs/nfs/nfs3/nfs3.h b/fs/nfs/nfs3/nfs3.h
index 5ed7efa..d43df84 100644
--- a/fs/nfs/nfs3/nfs3.h
+++ b/fs/nfs/nfs3/nfs3.h
@@ -4,10 +4,13 @@
#include <linux/fs.h>
#include <linux/sunrpc/clnt.h>
+#include "../nfs.h"
+
extern struct rpc_version nfs_version3;
extern struct nfs_rpc_ops nfs_v3_clientops;
void nfs3_init_aclclient(struct nfs_server *);
+int nfs3_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
extern const struct inode_operations nfs3_file_inode_operations;
extern const struct file_operations nfs3_file_operations;
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 6ff094f..37f12d6 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -14,5 +14,6 @@ struct dentry *nfs4_try_mount(struct file_system_type *, int, const char *,
struct nfs_fh *, struct nfs_parsed_mount_data *);
int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *,
struct nfs_fh *, const char *);
+int nfs4_alloc_client(struct nfs_client *, const struct nfs_client_initdata *);
#endif /* __LINUX_FS_NFS_NFS4_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This list is used by nfs4_find_no_client_ident(), and needs to be locked
before traversing. Since this function is about to move to a different
file, I created functions to get a pointer to the list head and manage
the lock.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 26 ++++++++++++++++++++------
fs/nfs/nfs.h | 2 ++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 778ef62..56da3b6 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1177,17 +1177,18 @@ struct nfs_client *
nfs4_find_client_no_ident(const struct sockaddr *addr)
{
struct nfs_client *clp;
+ struct list_head *cl_list = nfs_client_list_start();
- spin_lock(&nfs_client_lock);
- list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+ list_for_each_entry(clp, cl_list, cl_share_link) {
if (nfs4_cb_match_client(addr, clp, 0) == false)
continue;
atomic_inc(&clp->cl_count);
- spin_unlock(&nfs_client_lock);
- return clp;
+ goto out;
}
- spin_unlock(&nfs_client_lock);
- return NULL;
+ clp = NULL;
+out:
+ nfs_client_list_end();
+ return clp;
}
/*
@@ -1850,6 +1851,19 @@ static void nfs_server_list_stop(struct seq_file *p, void *v)
spin_unlock(&nfs_client_lock);
}
+struct list_head *nfs_client_list_start(void)
+{
+ spin_lock(&nfs_client_lock);
+ return &nfs_client_list;
+}
+EXPORT_SYMBOL_GPL(nfs_client_list_start);
+
+void nfs_client_list_end(void)
+{
+ spin_unlock(&nfs_client_lock);
+}
+EXPORT_SYMBOL_GPL(nfs_client_list_end);
+
/*
* display a header line followed by a load of call lines
*/
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 13321fd..5f2d632 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -66,6 +66,8 @@ void unregister_nfs_version(struct nfs_subversion *);
struct nfs_server *nfs_alloc_server(void);
struct nfs_server *do_nfs_clone_server(struct nfs_server *, struct nfs_server *,
struct nfs_fh *, struct nfs_fattr *);
+struct list_head *nfs_client_list_start(void);
+void nfs_client_list_end(void);
/* Exported in dir.c */
int nfs_lookup_revalidate(struct dentry *, struct nameidata *);
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
You need to run `modprobe nfs2` before you can use it.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 15 +--------------
fs/nfs/file.c | 6 ------
fs/nfs/nfs2/Makefile | 5 +++++
fs/nfs/nfs2/dir.c | 30 ++++++++++++++++++++++++++++++
fs/nfs/nfs2/file.c | 32 ++++++++++++++++++++++++++++++++
fs/nfs/nfs2/module.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs2/nfs2.h | 17 +++++++++++++++++
fs/nfs/nfs2/proc.c | 1 +
include/linux/nfs_xdr.h | 3 +--
11 files changed, 134 insertions(+), 24 deletions(-)
create mode 100644 fs/nfs/nfs2/Makefile
create mode 100644 fs/nfs/nfs2/dir.c
create mode 100644 fs/nfs/nfs2/file.c
create mode 100644 fs/nfs/nfs2/module.c
create mode 100644 fs/nfs/nfs2/nfs2.h
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 5419166..b28e56f 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -30,7 +30,7 @@ config NFS_FS
If unsure, say N.
config NFS_V2
- bool "NFS client support for NFS version 2"
+ tristate "NFS client support for NFS version 2"
depends on NFS_FS
help
This option enables support for version 2 of the NFS protocol
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 44db87d..5733451 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,7 +9,6 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V2) += nfs2/proc.o nfs2/xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
@@ -23,5 +22,6 @@ nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
+obj-$(CONFIG_NFS_V2) += nfs2/
obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 168b469..20d1708 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -121,22 +121,12 @@ struct rpc_stat nfs_rpcstat = {
* Once everything has been converted this function will
* be removed.
*/
-#if defined(CONFIG_NFS_V2) || defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
static void nfs_module_null_function(void)
{
}
#endif
-#ifdef CONFIG_NFS_V2
-static struct nfs_subversion nfs_v2_mod = {
- .version = 2,
- .rpc_vers = &nfs_version2,
- .rpc_ops = &nfs_v2_clientops,
- .reference = nfs_module_null_function,
- .unreference = nfs_module_null_function,
-};
-#endif /* CONFIG_NFS_V2 */
-
#ifdef CONFIG_NFS_V3
static struct nfs_subversion nfs_v3_mod = {
.version = 3,
@@ -242,9 +232,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
*/
void __init nfs_register_versions(void)
{
-#ifdef CONFIG_NFS_V2
- register_nfs_version(&nfs_v2_mod);
-#endif
#ifdef CONFIG_NFS_V3
register_nfs_version(&nfs_v3_mod);
#endif
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 227694e..4ac4dae 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -44,12 +44,6 @@
static const struct vm_operations_struct nfs_file_vm_ops;
-const struct inode_operations nfs_file_inode_operations = {
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
-};
-
#ifdef CONFIG_NFS_V3
const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
diff --git a/fs/nfs/nfs2/Makefile b/fs/nfs/nfs2/Makefile
new file mode 100644
index 0000000..0ca3b59
--- /dev/null
+++ b/fs/nfs/nfs2/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for NFS v2
+#
+obj-$(CONFIG_NFS_V2) += nfs2.o
+nfs2-y := module.o dir.o file.o proc.o xdr.o
diff --git a/fs/nfs/nfs2/dir.c b/fs/nfs/nfs2/dir.c
new file mode 100644
index 0000000..64e2154
--- /dev/null
+++ b/fs/nfs/nfs2/dir.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include <linux/fs.h>
+
+#include "../nfs.h"
+#include "nfs2.h"
+
+const struct inode_operations nfs_dir_inode_operations = {
+ .create = nfs_create,
+ .lookup = nfs_lookup,
+ .link = nfs_link,
+ .unlink = nfs_unlink,
+ .symlink = nfs_symlink,
+ .mkdir = nfs_mkdir,
+ .rmdir = nfs_rmdir,
+ .mknod = nfs_mknod,
+ .rename = nfs_rename,
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+};
+
+const struct dentry_operations nfs_dentry_operations = {
+ .d_revalidate = nfs_lookup_revalidate,
+ .d_delete = nfs_dentry_delete,
+ .d_iput = nfs_dentry_iput,
+ .d_automount = nfs_d_automount,
+ .d_release = nfs_d_release,
+};
diff --git a/fs/nfs/nfs2/file.c b/fs/nfs/nfs2/file.c
new file mode 100644
index 0000000..bfe6412
--- /dev/null
+++ b/fs/nfs/nfs2/file.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include <linux/fs.h>
+
+#include "../nfs.h"
+#include "nfs2.h"
+
+const struct inode_operations nfs_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+};
+
+const struct file_operations nfs_file_operations = {
+ .llseek = nfs_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
+ .mmap = nfs_file_mmap,
+ .open = nfs_file_open,
+ .flush = nfs_file_flush,
+ .release = nfs_file_release,
+ .fsync = nfs_file_fsync,
+ .lock = nfs_lock,
+ .flock = nfs_flock,
+ .splice_read = nfs_file_splice_read,
+ .splice_write = nfs_file_splice_write,
+ .check_flags = nfs_check_flags,
+ .setlease = nfs_setlease,
+};
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
new file mode 100644
index 0000000..04d415a
--- /dev/null
+++ b/fs/nfs/nfs2/module.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Initialize the NFS v2 module
+ */
+
+#include <linux/module.h>
+#include "../nfs.h"
+
+#include "nfs2.h"
+
+static void nfs2_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs2_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+struct nfs_subversion nfs_v2 = {
+ .version = 2,
+ .rpc_vers = &nfs_version2,
+ .rpc_ops = &nfs_v2_clientops,
+
+ .reference = nfs2_reference,
+ .unreference = nfs2_unreference,
+};
+
+static int __init init_nfs_v2(void)
+{
+ register_nfs_version(&nfs_v2);
+ return 0;
+}
+
+static void __exit exit_nfs_v2(void)
+{
+ unregister_nfs_version(&nfs_v2);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v2);
+module_exit(exit_nfs_v2);
diff --git a/fs/nfs/nfs2/nfs2.h b/fs/nfs/nfs2/nfs2.h
new file mode 100644
index 0000000..6274821
--- /dev/null
+++ b/fs/nfs/nfs2/nfs2.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_FS_NFS_NFS2_H
+#define __LINUX_FS_NFS_NFS2_H
+
+#include <linux/fs.h>
+#include <linux/sunrpc/clnt.h>
+
+extern struct rpc_version nfs_version2;
+extern const struct nfs_rpc_ops nfs_v2_clientops;
+
+extern const struct inode_operations nfs_file_inode_operations;
+extern const struct file_operations nfs_file_operations;
+
+extern const struct inode_operations nfs_dir_inode_operations;
+extern const struct file_operations nfs_dir_operations;
+extern const struct dentry_operations nfs_dentry_operations;
+
+#endif /* __LINUX_FS_NFS_NFS2_H */
diff --git a/fs/nfs/nfs2/proc.c b/fs/nfs/nfs2/proc.c
index 65eafa3..6590fc7 100644
--- a/fs/nfs/nfs2/proc.c
+++ b/fs/nfs/nfs2/proc.c
@@ -42,6 +42,7 @@
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include "../internal.h"
+#include "nfs2.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a764cef..0ca9f10 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -3,6 +3,7 @@
#include <linux/nfsacl.h>
#include <linux/nfs3.h>
+#include <linux/nfs4.h>
#include <linux/sunrpc/gss_api.h>
/*
@@ -1272,10 +1273,8 @@ struct nfs_rpc_ops {
/*
* Function vectors etc. for the NFS client
*/
-extern const struct nfs_rpc_ops nfs_v2_clientops;
extern const struct nfs_rpc_ops nfs_v3_clientops;
extern const struct nfs_rpc_ops nfs_v4_clientops;
-extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This is called by the generic NFS client to return a v4 delegation. v2
and v3 don't have delegations, so they don't need to do anything.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/inode.c | 6 ++++++
fs/nfs/nfs.h | 2 ++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs4/delegation.c | 2 +-
fs/nfs/nfs4/delegation.h | 8 +-------
fs/nfs/nfs4/proc.c | 4 ++--
fs/nfs/unlink.c | 1 +
9 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 368aa7e..ca6ebe5 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -139,6 +139,7 @@ static struct nfs_subversion nfs_v4_mod = {
.init_aclclient = nfs4_init_aclclient,
.have_delegation = nfs4_have_delegation,
.have_delegated_attributes = nfs4_have_delegated_attributes,
+ .return_delegation = nfs4_inode_return_delegation,
.do_submount = nfs4_do_submount,
.do_clone_mount = nfs4_do_clone_mount,
};
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5328b68..1bea5b7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -136,6 +136,12 @@ int nfs_have_delegated_attributes(struct inode *inode)
return nfs_mod->have_delegated_attributes(inode);
}
+int nfs_inode_return_delegation(struct inode *inode)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ return nfs_mod->return_delegation(inode);
+}
+
/**
* nfs_sync_mapping - helper to flush all mmapped dirty data to disk
*/
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 08950a2..c3dfb7d 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -24,6 +24,7 @@ struct nfs_subversion {
void (*init_aclclient)(struct nfs_server *);
int (*have_delegation)(struct inode *, fmode_t);
int (*have_delegated_attributes)(struct inode *);
+ int (*return_delegation)(struct inode *);
struct vfsmount *(*do_submount)(struct dentry *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
struct vfsmount *(*do_clone_mount)(struct nfs_server *, const char *,
@@ -77,6 +78,7 @@ int nfs_setattr(struct dentry *, struct iattr *);
int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int nfs_have_delegation(struct inode *, fmode_t);
int nfs_have_delegated_attributes(struct inode *);
+int nfs_inode_return_delegation(struct inode *);
/* Exported in namespace.c */
struct vfsmount *nfs_d_automount(struct path *);
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index ef6dbb4..618ce83 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -39,6 +39,7 @@ struct nfs_subversion nfs_v2 = {
.init_aclclient = nfs2_init_aclclient,
.have_delegation = nfs2_no_delegation,
.have_delegated_attributes = nfs2_no_delegation2,
+ .return_delegation = nfs2_no_delegation2,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index bdd2e33..a999b2f 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -39,6 +39,7 @@ struct nfs_subversion nfs_v3 = {
.init_aclclient = nfs3_init_aclclient,
.have_delegation = nfs3_no_delegation,
.have_delegated_attributes = nfs3_no_delegation2,
+ .return_delegation = nfs3_no_delegation2,
.do_submount = nfs_do_submount,
.do_clone_mount = nfs_do_clone_mount,
};
diff --git a/fs/nfs/nfs4/delegation.c b/fs/nfs/nfs4/delegation.c
index 272e735..e8aa4b6 100644
--- a/fs/nfs/nfs4/delegation.c
+++ b/fs/nfs/nfs4/delegation.c
@@ -387,7 +387,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
*
* Returns zero on success, or a negative errno value.
*/
-int nfs_inode_return_delegation(struct inode *inode)
+int nfs4_inode_return_delegation(struct inode *inode)
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/nfs4/delegation.h b/fs/nfs/nfs4/delegation.h
index 2c45cb6..40bd6c2 100644
--- a/fs/nfs/nfs4/delegation.h
+++ b/fs/nfs/nfs4/delegation.h
@@ -33,7 +33,7 @@ enum {
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int nfs_inode_return_delegation(struct inode *inode);
+int nfs4_inode_return_delegation(struct inode *inode);
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
void nfs_inode_return_delegation_noreclaim(struct inode *inode);
@@ -58,11 +58,5 @@ int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
int nfs4_have_delegation(struct inode *inode, fmode_t flags);
-#else
-static inline int nfs_inode_return_delegation(struct inode *inode)
-{
- return 0;
-}
#endif
-
#endif
diff --git a/fs/nfs/nfs4/proc.c b/fs/nfs/nfs4/proc.c
index c86c351..1161e70 100644
--- a/fs/nfs/nfs4/proc.c
+++ b/fs/nfs/nfs4/proc.c
@@ -1017,7 +1017,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
return;
}
rcu_read_unlock();
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
}
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
@@ -3671,7 +3671,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
if (i < 0)
return i;
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
/*
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 1dbe14a..9f04700 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -19,6 +19,7 @@
#include "nfs4/nfs4_fs.h"
#include "iostat.h"
#include "nfs4/delegation.h"
+#include "nfs.h"
struct nfs_unlinkdata {
struct hlist_node list;
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
I move this function into the v4 subdirectory so it can exist in the
future v4 module, instead of the generic client.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 3 ++-
fs/nfs/client.c | 14 ++------------
fs/nfs/nfs4/client.c | 12 ++++++++++++
3 files changed, 16 insertions(+), 13 deletions(-)
create mode 100644 fs/nfs/nfs4/client.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index d782c47..16e3489 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -12,7 +12,8 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/delegation.o nfs4/idmap.o \
nfs4/callback.o nfs4/callback_xdr.o \
- nfs4/callback_proc.o nfs4/namespace.o
+ nfs4/callback_proc.o nfs4/namespace.o \
+ nfs4/client.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e24dd90..6c19290 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -42,6 +42,7 @@
#include <asm/system.h>
+#include "nfs4/nfs4.h"
#include "nfs4/nfs4_fs.h"
#include "nfs4/callback.h"
#include "nfs4/delegation.h"
@@ -53,8 +54,6 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT
-static void nfs_init_server_aclclient(struct nfs_server *server);
-
static DEFINE_SPINLOCK(nfs_client_lock);
static DEFINE_SPINLOCK(nfs_version_lock);
static LIST_HEAD(nfs_versions);
@@ -137,7 +136,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
- .init_aclclient = nfs_init_server_aclclient,
+ .init_aclclient = nfs4_init_aclclient,
};
#endif /* CONFIG_NFS_V4 */
@@ -801,15 +800,6 @@ static int nfs_start_lockd(struct nfs_server *server)
}
/*
- * Initialise an NFSv3 ACL client connection
- */
-static void nfs_init_server_aclclient(struct nfs_server *server)
-{
- server->flags &= ~NFS_MOUNT_NOACL;
- server->caps &= ~NFS_CAP_ACLS;
-}
-
-/*
* Create a general RPC client
*/
static int nfs_init_server_rpcclient(struct nfs_server *server,
diff --git a/fs/nfs/nfs4/client.c b/fs/nfs/nfs4/client.c
new file mode 100644
index 0000000..bbc415d
--- /dev/null
+++ b/fs/nfs/nfs4/client.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+
+void nfs4_init_aclclient(struct nfs_server *server)
+{
+ server->flags &= ~NFS_MOUNT_NOACL;
+ server->flags &= ~NFS_CAP_ACLS;
+}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This makes it easier for v2 and 3 to share the same code and for v4 to
do its own thing.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/nfs.h | 8 ++++++++
fs/nfs/nfs2/module.c | 1 +
fs/nfs/nfs3/module.c | 1 +
fs/nfs/nfs4/nfs4.h | 2 ++
fs/nfs/super.c | 19 +++++++------------
6 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index d7470fa..60d0f57 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -137,6 +137,7 @@ static struct nfs_subversion nfs_v4_mod = {
.reference = nfs_module_null_function,
.unreference = nfs_module_null_function,
.init_aclclient = nfs4_init_aclclient,
+ .try_mount = nfs4_try_mount,
.shutdown_client = nfs4_shutdown_client,
.have_delegation = nfs4_have_delegation,
.have_delegated_attributes = nfs4_have_delegated_attributes,
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 987656f..847f593 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -12,6 +12,7 @@
#include <linux/nfs_xdr.h>
struct nfs_clone_mount;
+struct nfs_parsed_mount_data;
struct nfs_subversion {
unsigned int version; /* Protocol number */
@@ -22,6 +23,9 @@ struct nfs_subversion {
void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
void (*init_aclclient)(struct nfs_server *);
+ struct dentry *(*try_mount)(struct file_system_type *, int,
+ const char *, struct nfs_fh *,
+ struct nfs_parsed_mount_data *);
void (*shutdown_client)(struct nfs_client *);
int (*have_delegation)(struct inode *, fmode_t);
int (*have_delegated_attributes)(struct inode *);
@@ -88,4 +92,8 @@ struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
struct vfsmount *nfs_do_clone_mount(struct nfs_server *, const char *,
struct nfs_clone_mount *);
+/* Exported in super.c */
+struct dentry *generic_nfs_fs_mount(struct file_system_type *, int,
+ const char *, struct nfs_fh *,
+ struct nfs_parsed_mount_data *);
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2/module.c b/fs/nfs/nfs2/module.c
index 7c29b04..9bc06ab 100644
--- a/fs/nfs/nfs2/module.c
+++ b/fs/nfs/nfs2/module.c
@@ -41,6 +41,7 @@ struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
.init_aclclient = nfs2_init_aclclient,
+ .try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs2_shutdown_client,
.have_delegation = nfs2_no_delegation,
.have_delegated_attributes = nfs2_no_delegation2,
diff --git a/fs/nfs/nfs3/module.c b/fs/nfs/nfs3/module.c
index 6293bf7..3ca0066 100644
--- a/fs/nfs/nfs3/module.c
+++ b/fs/nfs/nfs3/module.c
@@ -41,6 +41,7 @@ struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
.init_aclclient = nfs3_init_aclclient,
+ .try_mount = generic_nfs_fs_mount,
.shutdown_client = nfs3_shutdown_client,
.have_delegation = nfs3_no_delegation,
.have_delegated_attributes = nfs3_no_delegation2,
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 97ff8d8..2428896 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -10,5 +10,7 @@ struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *,
struct vfsmount *nfs4_do_clone_mount(struct nfs_server *, const char *,
struct nfs_clone_mount *);
int nfs4_have_delegated_attributes(struct inode *);
+struct dentry *nfs4_try_mount(struct file_system_type *, int, const char *,
+ struct nfs_fh *, struct nfs_parsed_mount_data *);
#endif /* __LINUX_FS_NFS_NFS4_H */
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 60d065f..861d31e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -57,6 +57,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+#include "nfs4/nfs4.h"
#include "nfs4/nfs4_fs.h"
#include "nfs4/callback.h"
#include "nfs4/delegation.h"
@@ -310,8 +311,6 @@ static const struct super_operations nfs_sops = {
#ifdef CONFIG_NFS_V4
static int nfs4_validate_text_mount_data(void *options,
struct nfs_parsed_mount_data *args, const char *dev_name);
-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_parsed_mount_data *data);
static struct dentry *nfs4_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
@@ -2298,6 +2297,7 @@ error_splat_bdi:
goto out;
}
+EXPORT_SYMBOL_GPL(generic_nfs_fs_mount);
static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
@@ -2326,13 +2326,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
goto out;
}
-#ifdef CONFIG_NFS_V4
- if (data->version == 4)
- mntroot = nfs4_try_mount(flags, dev_name, data);
- else
-#endif /* CONFIG_NFS_V4 */
- mntroot = generic_nfs_fs_mount(fs_type, flags, dev_name, mntfh, data);
-
+ mntroot = nfs_mod->try_mount(fs_type, flags, dev_name, mntfh, data);
if (!IS_ERR(mntroot))
nfs_mod->reference();
@@ -2829,8 +2823,9 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
return dentry;
}
-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_parsed_mount_data *data)
+struct dentry *nfs4_try_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
{
char *export_path;
struct vfsmount *root_mnt;
@@ -2875,7 +2870,7 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type,
goto out;
}
- res = nfs4_try_mount(flags, dev_name, data);
+ res = nfs4_try_mount(fs_type, flags, dev_name, NULL, data);
if (IS_ERR(res))
error = PTR_ERR(res);
--
1.7.8.3
On Fri, 13 Jan 2012 16:05:29 -0500 Bryan Schumaker <[email protected]>
wrote:
> >
> > It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
>
> Not that I know of. I found examples for compiling directories as
> modules, but not specific files or parts of files.
>
You can definitely compile specific files or small collections of files into
modules.
See for example drivers/md/
In Makefile
obj-$(CONFIG_FOO) += foo.o
will make a "foo.ko" if CONFIG_FOO == m
If you want two .c files to make a modules, then
foo-y :- foo-top.o foo-bot.o
obj-$(CONFIG_FOO) += foo.o
will do the trick.
Compiling parts of a file into one module and parts into another - while
possible - would certainly be frowned upon. Definitely split such files up.
NeilBrown
From: Bryan Schumaker <[email protected]>
I ended up with multiple files including this file, so to prevent
compiler errors later on I add ifndef guards now.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/internal.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 5ee9253..1dd22dc 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -2,6 +2,9 @@
* NFS internal definitions
*/
+#ifndef __LINUX_NFS_INTERNAL_H
+#define __LINUX_NFS_INTERNAL_H
+
#include "nfs4_fs.h"
#include <linux/mount.h>
#include <linux/security.h>
@@ -461,3 +464,4 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
PAGE_SIZE - 1) >> PAGE_SHIFT;
}
+#endif /* __LINUX_NFS_INTERNAL_H */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
These functions need to be available for v2 to work as a module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 2 +
fs/nfs/dir.c | 53 +++++++++++++++++++++++++++++----------------------
fs/nfs/file.c | 50 ++++++++++++++++++++++++++++++++----------------
fs/nfs/inode.c | 13 ++++++++++-
fs/nfs/namespace.c | 2 +
5 files changed, 78 insertions(+), 42 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ee63d6a..168b469 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -934,6 +934,7 @@ error:
dprintk("<-- nfs_init_client() = xerror %d\n", error);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_init_client);
/*
* Create a version 2 or 3 client
@@ -2196,6 +2197,7 @@ int nfs_stat_to_errno(enum nfs_stat status)
dprintk("NFS: Unrecognized nfs status value: %u\n", status);
return nfs_errtbl[i].errno;
}
+EXPORT_SYMBOL_GPL(nfs_stat_to_errno);
module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ac28990..6b2813b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -17,6 +17,7 @@
* 6 Jun 1999 Cache readdir lookups in the page cache. -DaveM
*/
+#include <linux/module.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/stat.h>
@@ -40,22 +41,13 @@
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
+#include "nfs.h"
/* #define NFS_DEBUG_VERBOSE 1 */
static int nfs_opendir(struct inode *, struct file *);
static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
-static int nfs_mkdir(struct inode *, struct dentry *, int);
-static int nfs_rmdir(struct inode *, struct dentry *);
-static int nfs_unlink(struct inode *, struct dentry *);
-static int nfs_symlink(struct inode *, struct dentry *, const char *);
-static int nfs_link(struct dentry *, struct inode *, struct dentry *);
-static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
-static int nfs_rename(struct inode *, struct dentry *,
- struct inode *, struct dentry *);
static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
static void nfs_readdir_clear_array(struct page*);
@@ -1094,7 +1086,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
* If the parent directory is seen to have changed, we throw out the
* cached dentry and do a new lookup.
*/
-static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct inode *dir;
struct inode *inode;
@@ -1192,11 +1184,12 @@ out_error:
dentry->d_name.name, error);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_lookup_revalidate);
/*
* This is called from dput() when d_count is going to 0.
*/
-static int nfs_dentry_delete(const struct dentry *dentry)
+int nfs_dentry_delete(const struct dentry *dentry)
{
dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -1218,6 +1211,7 @@ static int nfs_dentry_delete(const struct dentry *dentry)
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_dentry_delete);
static void nfs_drop_nlink(struct inode *inode)
{
@@ -1231,7 +1225,7 @@ static void nfs_drop_nlink(struct inode *inode)
* Called when the dentry loses inode.
* We use it to clean up silly-renamed files.
*/
-static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
+void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
{
if (S_ISDIR(inode->i_mode))
/* drop any readdir cache as it could easily be old */
@@ -1243,8 +1237,9 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
}
iput(inode);
}
+EXPORT_SYMBOL_GPL(nfs_dentry_iput);
-static void nfs_d_release(struct dentry *dentry)
+void nfs_d_release(struct dentry *dentry)
{
/* free cached devname value, if it survived that far */
if (unlikely(dentry->d_fsdata)) {
@@ -1254,6 +1249,7 @@ static void nfs_d_release(struct dentry *dentry)
kfree(dentry->d_fsdata);
}
}
+EXPORT_SYMBOL_GPL(nfs_d_release);
const struct dentry_operations nfs_dentry_operations = {
.d_revalidate = nfs_lookup_revalidate,
@@ -1263,7 +1259,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_release = nfs_d_release,
};
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *res;
struct dentry *parent;
@@ -1326,6 +1322,7 @@ out:
nfs_free_fhandle(fhandle);
return res;
}
+EXPORT_SYMBOL_GPL(nfs_lookup);
#ifdef CONFIG_NFS_V4
static int nfs_open_revalidate(struct dentry *, struct nameidata *);
@@ -1668,6 +1665,7 @@ out_error:
dput(parent);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_instantiate);
/*
* Following a failed create operation, we drop the dentry rather
@@ -1675,7 +1673,7 @@ out_error:
* that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed.
*/
-static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
+int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct iattr attr;
@@ -1699,11 +1697,12 @@ out_err:
d_drop(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_create);
/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int
+int
nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
{
struct iattr attr;
@@ -1726,11 +1725,12 @@ out_err:
d_drop(dentry);
return status;
}
+EXPORT_SYMBOL_GPL(nfs_mknod);
/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct iattr attr;
int error;
@@ -1749,6 +1749,7 @@ out_err:
d_drop(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_mkdir);
static void nfs_dentry_handle_enoent(struct dentry *dentry)
{
@@ -1756,7 +1757,7 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
d_delete(dentry);
}
-static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
+int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
@@ -1772,6 +1773,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
return error;
}
+EXPORT_SYMBOL_GPL(nfs_rmdir);
/*
* Remove a file after making sure there are no pending writes,
@@ -1815,7 +1817,7 @@ out:
*
* If sillyrename() returns 0, we do nothing, otherwise we unlink.
*/
-static int nfs_unlink(struct inode *dir, struct dentry *dentry)
+int nfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error;
int need_rehash = 0;
@@ -1843,6 +1845,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
d_rehash(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_unlink);
/*
* To create a symbolic link, most file systems instantiate a new inode,
@@ -1859,7 +1862,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
* now have a new file handle and can instantiate an in-core NFS inode
* and move the raw page into its mapping.
*/
-static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
struct pagevec lru_pvec;
struct page *page;
@@ -1913,8 +1916,9 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_symlink);
-static int
+int
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
@@ -1934,6 +1938,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
}
return error;
}
+EXPORT_SYMBOL_GPL(nfs_link);
/*
* RENAME
@@ -1959,7 +1964,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
* If these conditions are met, we can drop the dentries before doing
* the rename.
*/
-static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct inode *old_inode = old_dentry->d_inode;
@@ -2032,6 +2037,7 @@ out:
dput(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_rename);
static DEFINE_SPINLOCK(nfs_access_lru_lock);
static LIST_HEAD(nfs_access_lru_list);
@@ -2351,6 +2357,7 @@ out_notsup:
res = generic_permission(inode, mask);
goto out;
}
+EXPORT_SYMBOL_GPL(nfs_permission);
/*
* Local variables:
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c43a452..227694e 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -16,6 +16,7 @@
* nfs regular file handling functions
*/
+#include <linux/module.h>
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -37,6 +38,7 @@
#include "iostat.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_FILE
@@ -65,18 +67,19 @@ const struct inode_operations nfs3_file_inode_operations = {
# define IS_SWAPFILE(inode) (0)
#endif
-static int nfs_check_flags(int flags)
+int nfs_check_flags(int flags)
{
if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
return -EINVAL;
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_check_flags);
/*
* Open file
*/
-static int
+int
nfs_file_open(struct inode *inode, struct file *filp)
{
int res;
@@ -93,8 +96,9 @@ nfs_file_open(struct inode *inode, struct file *filp)
res = nfs_open(inode, filp);
return res;
}
+EXPORT_SYMBOL_GPL(nfs_file_open);
-static int
+int
nfs_file_release(struct inode *inode, struct file *filp)
{
dprintk("NFS: release(%s/%s)\n",
@@ -104,6 +108,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
return nfs_release(inode, filp);
}
+EXPORT_SYMBOL_GPL(nfs_file_release);
/**
* nfs_revalidate_size - Revalidate the file size
@@ -136,7 +141,7 @@ force_reval:
return __nfs_revalidate_inode(server, inode);
}
-static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
{
dprintk("NFS: llseek file(%s/%s, %lld, %d)\n",
filp->f_path.dentry->d_parent->d_name.name,
@@ -157,11 +162,12 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
return generic_file_llseek(filp, offset, origin);
}
+EXPORT_SYMBOL_GPL(nfs_file_llseek);
/*
* Flush all dirty pages, and check for write errors.
*/
-static int
+int
nfs_file_flush(struct file *file, fl_owner_t id)
{
struct dentry *dentry = file->f_path.dentry;
@@ -178,8 +184,9 @@ nfs_file_flush(struct file *file, fl_owner_t id)
/* Flush writes to the server and return any errors */
return vfs_fsync(file, 0);
}
+EXPORT_SYMBOL_GPL(nfs_file_flush);
-static ssize_t
+ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
@@ -202,8 +209,9 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
}
return result;
}
+EXPORT_SYMBOL_GPL(nfs_file_read);
-static ssize_t
+ssize_t
nfs_file_splice_read(struct file *filp, loff_t *ppos,
struct pipe_inode_info *pipe, size_t count,
unsigned int flags)
@@ -224,8 +232,9 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
}
return res;
}
+EXPORT_SYMBOL_GPL(nfs_file_splice_read);
-static int
+int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry *dentry = file->f_path.dentry;
@@ -245,6 +254,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
}
return status;
}
+EXPORT_SYMBOL_GPL(nfs_file_mmap);
/*
* Flush any dirty pages for this process, and check for write errors.
@@ -258,7 +268,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* nfs_file_write() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write.
*/
-static int
+int
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
@@ -290,6 +300,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
mutex_unlock(&inode->i_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_file_fsync);
/*
* Decide whether a read/modify/write cycle may be more efficient
@@ -563,8 +574,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
return 0;
}
-static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode;
@@ -614,10 +625,11 @@ out_swapfile:
printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
goto out;
}
+EXPORT_SYMBOL_GPL(nfs_file_write);
-static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
- struct file *filp, loff_t *ppos,
- size_t count, unsigned int flags)
+ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
+ struct file *filp, loff_t *ppos,
+ size_t count, unsigned int flags)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
@@ -645,6 +657,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_file_splice_write);
static int
do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
@@ -769,7 +782,7 @@ out:
/*
* Lock a (portion of) a file
*/
-static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int ret = -ENOLCK;
@@ -805,11 +818,12 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
out_err:
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_lock);
/*
* Lock a (portion of) a file
*/
-static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int is_local = 0;
@@ -834,18 +848,20 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
return do_unlk(filp, cmd, fl, is_local);
return do_setlk(filp, cmd, fl, is_local);
}
+EXPORT_SYMBOL_GPL(nfs_flock);
/*
* There is no protocol support for leases, so we have no way to implement
* them correctly in the face of opens by other clients.
*/
-static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
+int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
{
dprintk("NFS: setlease(%s/%s, arg=%ld)\n",
file->f_path.dentry->d_parent->d_name.name,
file->f_path.dentry->d_name.name, arg);
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(nfs_setlease);
const struct file_operations nfs_file_operations = {
.llseek = nfs_file_llseek,
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3c81a32..35db7b8 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -192,6 +192,7 @@ void nfs_invalidate_atime(struct inode *inode)
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
spin_unlock(&inode->i_lock);
}
+EXPORT_SYMBOL_GPL(nfs_invalidate_atime);
/*
* Invalidate, but do not unhash, the inode.
@@ -403,8 +404,7 @@ out_no_inode:
#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
-int
-nfs_setattr(struct dentry *dentry, struct iattr *attr)
+int nfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
struct nfs_fattr *fattr;
@@ -445,6 +445,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
out:
return error;
}
+EXPORT_SYMBOL_GPL(nfs_setattr);
/**
* nfs_vmtruncate - unmap mappings "freed" by truncate() syscall
@@ -503,6 +504,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
nfs_vmtruncate(inode, attr->ia_size);
}
}
+EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
@@ -541,6 +543,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
out:
return err;
}
+EXPORT_SYMBOL_GPL(nfs_getattr);
static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
{
@@ -629,6 +632,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
return;
nfs_revalidate_inode(server, inode);
}
+EXPORT_SYMBOL_GPL(nfs_close_context);
struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred, fmode_t f_mode)
{
@@ -1023,6 +1027,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
fattr->owner_name = NULL;
fattr->group_name = NULL;
}
+EXPORT_SYMBOL_GPL(nfs_fattr_init);
struct nfs_fattr *nfs_alloc_fattr(void)
{
@@ -1033,6 +1038,7 @@ struct nfs_fattr *nfs_alloc_fattr(void)
nfs_fattr_init(fattr);
return fattr;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_fattr);
struct nfs_fh *nfs_alloc_fhandle(void)
{
@@ -1043,6 +1049,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
fh->size = 0;
return fh;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_fhandle);
/**
* nfs_inode_attrs_need_update - check if the inode attributes need updating
@@ -1102,6 +1109,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
return status;
}
+EXPORT_SYMBOL_GPL(nfs_refresh_inode);
static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
{
@@ -1189,6 +1197,7 @@ out_noforce:
spin_unlock(&inode->i_lock);
return status;
}
+EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
/*
* Many nfs protocol calls return the new file attributes after
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 8102391..18c5e4f 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -7,6 +7,7 @@
* NFS namespace
*/
+#include <linux/module.h>
#include <linux/dcache.h>
#include <linux/gfp.h>
#include <linux/mount.h>
@@ -279,6 +280,7 @@ out_nofree:
dprintk("<-- nfs_follow_mountpoint() = %p\n", mnt);
return mnt;
}
+EXPORT_SYMBOL_GPL(nfs_d_automount);
const struct inode_operations nfs_mountpoint_inode_operations = {
.getattr = nfs_getattr,
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This keeps all the v4 code together and separate from the generic NFS
client.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 8 ++++----
fs/nfs/client.c | 6 +++---
fs/nfs/dir.c | 2 +-
fs/nfs/file.c | 2 +-
fs/nfs/getroot.c | 4 ++--
fs/nfs/inode.c | 6 +++---
fs/nfs/internal.h | 2 +-
fs/nfs/{ => nfs4}/callback.c | 2 +-
fs/nfs/{ => nfs4}/callback.h | 0
fs/nfs/{ => nfs4}/callback_proc.c | 4 ++--
fs/nfs/{ => nfs4}/callback_xdr.c | 2 +-
fs/nfs/{ => nfs4}/delegation.c | 2 +-
fs/nfs/{ => nfs4}/delegation.h | 0
fs/nfs/{ => nfs4}/idmap.c | 0
fs/nfs/{nfs4namespace.c => nfs4/namespace.c} | 4 ++--
fs/nfs/nfs4/nfs4.h | 6 ++++++
fs/nfs/{ => nfs4}/nfs4_fs.h | 0
fs/nfs/{nfs4proc.c => nfs4/proc.c} | 6 +++---
fs/nfs/{nfs4renewd.c => nfs4/renewd.c} | 0
fs/nfs/{nfs4state.c => nfs4/state.c} | 4 ++--
fs/nfs/{nfs4xdr.c => nfs4/xdr.c} | 4 ++--
fs/nfs/read.c | 2 +-
fs/nfs/super.c | 6 +++---
fs/nfs/sysctl.c | 2 +-
fs/nfs/unlink.c | 4 ++--
fs/nfs/write.c | 4 ++--
26 files changed, 44 insertions(+), 38 deletions(-)
rename fs/nfs/{ => nfs4}/callback.c (99%)
rename fs/nfs/{ => nfs4}/callback.h (100%)
rename fs/nfs/{ => nfs4}/callback_proc.c (99%)
rename fs/nfs/{ => nfs4}/callback_xdr.c (99%)
rename fs/nfs/{ => nfs4}/delegation.c (99%)
rename fs/nfs/{ => nfs4}/delegation.h (100%)
rename fs/nfs/{ => nfs4}/idmap.c (100%)
rename fs/nfs/{nfs4namespace.c => nfs4/namespace.c} (99%)
create mode 100644 fs/nfs/nfs4/nfs4.h
rename fs/nfs/{ => nfs4}/nfs4_fs.h (100%)
rename fs/nfs/{nfs4proc.c => nfs4/proc.c} (99%)
rename fs/nfs/{nfs4renewd.c => nfs4/renewd.c} (100%)
rename fs/nfs/{nfs4state.c => nfs4/state.c} (99%)
rename fs/nfs/{nfs4xdr.c => nfs4/xdr.c} (99%)
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index cfd238e..d782c47 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,10 +9,10 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
- delegation.o idmap.o \
- callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o
+nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
+ nfs4/delegation.o nfs4/idmap.o \
+ nfs4/callback.o nfs4/callback_xdr.o \
+ nfs4/callback_proc.o nfs4/namespace.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 1e1bbf8..e24dd90 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -42,9 +42,9 @@
#include <asm/system.h>
-#include "nfs4_fs.h"
-#include "callback.h"
-#include "delegation.h"
+#include "nfs4/nfs4_fs.h"
+#include "nfs4/callback.h"
+#include "nfs4/delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0348727..b72aab3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -37,7 +37,7 @@
#include <linux/kmemleak.h>
#include <linux/xattr.h>
-#include "delegation.h"
+#include "nfs4/delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d9f11c5..a691996 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -33,7 +33,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-#include "delegation.h"
+#include "nfs4/delegation.h"
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index dcb6154..64e086e 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -35,8 +35,8 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include "nfs4_fs.h"
-#include "delegation.h"
+#include "nfs4/nfs4_fs.h"
+#include "nfs4/delegation.h"
#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index cf2bab9..3588727 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -42,9 +42,9 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include "nfs4_fs.h"
-#include "callback.h"
-#include "delegation.h"
+#include "nfs4/nfs4_fs.h"
+#include "nfs4/callback.h"
+#include "nfs4/delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 1dd22dc..347f49f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -5,7 +5,7 @@
#ifndef __LINUX_NFS_INTERNAL_H
#define __LINUX_NFS_INTERNAL_H
-#include "nfs4_fs.h"
+#include "nfs4/nfs4_fs.h"
#include <linux/mount.h>
#include <linux/security.h>
diff --git a/fs/nfs/callback.c b/fs/nfs/nfs4/callback.c
similarity index 99%
rename from fs/nfs/callback.c
rename to fs/nfs/nfs4/callback.c
index 516f337..e428afc 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/nfs4/callback.c
@@ -22,7 +22,7 @@
#include "nfs4_fs.h"
#include "callback.h"
-#include "internal.h"
+#include "../internal.h"
#define NFSDBG_FACILITY NFSDBG_CALLBACK
diff --git a/fs/nfs/callback.h b/fs/nfs/nfs4/callback.h
similarity index 100%
rename from fs/nfs/callback.h
rename to fs/nfs/nfs4/callback.h
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/nfs4/callback_proc.c
similarity index 99%
rename from fs/nfs/callback_proc.c
rename to fs/nfs/nfs4/callback_proc.c
index 54cea8a..d11deba 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/nfs4/callback_proc.c
@@ -11,8 +11,8 @@
#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
-#include "internal.h"
-#include "pnfs.h"
+#include "../internal.h"
+#include "../pnfs.h"
#ifdef NFS_DEBUG
#define NFSDBG_FACILITY NFSDBG_CALLBACK
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/nfs4/callback_xdr.c
similarity index 99%
rename from fs/nfs/callback_xdr.c
rename to fs/nfs/nfs4/callback_xdr.c
index 726e59a..24a3114 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/nfs4/callback_xdr.c
@@ -13,7 +13,7 @@
#include <linux/sunrpc/bc_xprt.h>
#include "nfs4_fs.h"
#include "callback.h"
-#include "internal.h"
+#include "../internal.h"
#define CB_OP_TAGLEN_MAXSZ (512)
#define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ)
diff --git a/fs/nfs/delegation.c b/fs/nfs/nfs4/delegation.c
similarity index 99%
rename from fs/nfs/delegation.c
rename to fs/nfs/nfs4/delegation.c
index 7f26540..2f3dc3e 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/nfs4/delegation.c
@@ -19,7 +19,7 @@
#include "nfs4_fs.h"
#include "delegation.h"
-#include "internal.h"
+#include "../internal.h"
static void nfs_free_delegation(struct nfs_delegation *delegation)
{
diff --git a/fs/nfs/delegation.h b/fs/nfs/nfs4/delegation.h
similarity index 100%
rename from fs/nfs/delegation.h
rename to fs/nfs/nfs4/delegation.h
diff --git a/fs/nfs/idmap.c b/fs/nfs/nfs4/idmap.c
similarity index 100%
rename from fs/nfs/idmap.c
rename to fs/nfs/nfs4/idmap.c
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4/namespace.c
similarity index 99%
rename from fs/nfs/nfs4namespace.c
rename to fs/nfs/nfs4/namespace.c
index bb80c49..6a21d95 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4/namespace.c
@@ -16,9 +16,9 @@
#include <linux/sunrpc/clnt.h>
#include <linux/vfs.h>
#include <linux/inet.h>
-#include "internal.h"
+#include "../internal.h"
#include "nfs4_fs.h"
-#include "dns_resolve.h"
+#include "../dns_resolve.h"
#define NFSDBG_FACILITY NFSDBG_VFS
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
new file mode 100644
index 0000000..8ed9951
--- /dev/null
+++ b/fs/nfs/nfs4/nfs4.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_FS_NFS_NFS4_H
+#define __LINUX_FS_NFS_NFS4_H
+
+void nfs4_init_aclclient(struct nfs_server *);
+
+#endif /* __LINUX_FS_NFS_NFS4_H */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4/nfs4_fs.h
similarity index 100%
rename from fs/nfs/nfs4_fs.h
rename to fs/nfs/nfs4/nfs4_fs.h
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4/proc.c
similarity index 99%
rename from fs/nfs/nfs4proc.c
rename to fs/nfs/nfs4/proc.c
index df3d306..c86c351 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4/proc.c
@@ -59,10 +59,10 @@
#include "nfs4_fs.h"
#include "delegation.h"
-#include "internal.h"
-#include "iostat.h"
+#include "../internal.h"
+#include "../iostat.h"
#include "callback.h"
-#include "pnfs.h"
+#include "../pnfs.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4/renewd.c
similarity index 100%
rename from fs/nfs/nfs4renewd.c
rename to fs/nfs/nfs4/renewd.c
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4/state.c
similarity index 99%
rename from fs/nfs/nfs4state.c
rename to fs/nfs/nfs4/state.c
index a53f33b..e16e178 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4/state.c
@@ -54,8 +54,8 @@
#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
-#include "internal.h"
-#include "pnfs.h"
+#include "../internal.h"
+#include "../pnfs.h"
#define OPENOWNER_POOL_SIZE 8
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4/xdr.c
similarity index 99%
rename from fs/nfs/nfs4xdr.c
rename to fs/nfs/nfs4/xdr.c
index 95e92e4..97c36ca 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4/xdr.c
@@ -52,8 +52,8 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
#include "nfs4_fs.h"
-#include "internal.h"
-#include "pnfs.h"
+#include "../internal.h"
+#include "../pnfs.h"
#define NFSDBG_FACILITY NFSDBG_XDR
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index cfa175c..1f0cc70 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -23,7 +23,7 @@
#include <asm/system.h>
#include "pnfs.h"
-#include "nfs4_fs.h"
+#include "nfs4/nfs4_fs.h"
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2889a70..d7cdc50 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -57,9 +57,9 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include "nfs4_fs.h"
-#include "callback.h"
-#include "delegation.h"
+#include "nfs4/nfs4_fs.h"
+#include "nfs4/callback.h"
+#include "nfs4/delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index 978aaeb..d839b40d 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -13,7 +13,7 @@
#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>
-#include "callback.h"
+#include "nfs4/callback.h"
#ifdef CONFIG_NFS_V4
static const int nfs_set_port_min = 0;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 4f9319a..1dbe14a 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -16,9 +16,9 @@
#include <linux/namei.h>
#include "internal.h"
-#include "nfs4_fs.h"
+#include "nfs4/nfs4_fs.h"
#include "iostat.h"
-#include "delegation.h"
+#include "nfs4/delegation.h"
struct nfs_unlinkdata {
struct hlist_node list;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 1e92376..d5f61af 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -24,10 +24,10 @@
#include <asm/uaccess.h>
-#include "delegation.h"
+#include "nfs4/delegation.h"
#include "internal.h"
#include "iostat.h"
-#include "nfs4_fs.h"
+#include "nfs4/nfs4_fs.h"
#include "fscache.h"
#include "pnfs.h"
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
The v4 code uses these functions in the generic client, so they need to
be available to modules.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 2 ++
fs/nfs/dir.c | 2 ++
fs/nfs/dns_resolve.c | 4 ++++
fs/nfs/fscache.c | 4 ++++
fs/nfs/inode.c | 9 +++++++++
fs/nfs/namespace.c | 1 +
fs/nfs/super.c | 2 ++
fs/nfs/unlink.c | 3 +++
fs/nfs/write.c | 2 ++
9 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 2c3f50e..0e4ddbe 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
spin_unlock(&nfs_client_lock);
}
+EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
static void nfs_server_remove_lists(struct nfs_server *server)
{
@@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
nfs_release_automount_timer();
dprintk("<-- nfs_free_server()\n");
}
+EXPORT_SYMBOL_GPL(nfs_free_server);
/*
* Create a version 2 or 3 volume record
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 210284f..909f8de 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
{
NFS_I(dir)->cache_change_attribute++;
}
+EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
/*
* A check for whether or not the parent directory has changed.
@@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
{
return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
}
+EXPORT_SYMBOL_GPL(nfs_may_open);
int nfs_permission(struct inode *inode, int mask)
{
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index a6e711a..8b9aeba 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -6,6 +6,8 @@
* Resolves DNS hostnames into valid ip addresses
*/
+#include <linux/module.h>
+
#ifdef CONFIG_NFS_USE_KERNEL_DNS
#include <linux/sunrpc/clnt.h>
@@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
kfree(ip_addr);
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
#else
@@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
ret = -ESRCH;
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
int nfs_dns_resolver_init(void)
{
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 419119c..94e2d51 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -9,6 +9,7 @@
* 2 of the Licence, or (at your option) any later version.
*/
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -163,6 +164,7 @@ non_unique:
printk(KERN_WARNING "NFS:"
" Cache request denied due to non-unique superblock keys\n");
}
+EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
/*
* release a per-superblock cookie
@@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
nfss->fscache_key = NULL;
}
}
+EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
/*
* Initialise the per-inode cache cookie pointer for an NFS inode.
@@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
nfs_fscache_inode_unlock(inode);
}
}
+EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
/*
* Replace a per-inode cookie due to revalidation detecting a file having
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 57a68b8..d7afc2b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
schedule();
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
/**
* nfs_compat_user_ino64 - returns the user-visible inode number
@@ -421,6 +422,7 @@ out_no_inode:
dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
goto out;
}
+EXPORT_SYMBOL_GPL(nfs_fhget);
#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
@@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
}
return ctx;
}
+EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
{
@@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
atomic_inc(&ctx->lock_context.count);
return ctx;
}
+EXPORT_SYMBOL_GPL(get_nfs_open_context);
static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
{
@@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
{
__put_nfs_open_context(ctx, 0);
}
+EXPORT_SYMBOL_GPL(put_nfs_open_context);
/*
* Ensure that mmap has a recent RPC credential for use when writing out
@@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
list_add(&ctx->list, &nfsi->open_files);
spin_unlock(&inode->i_lock);
}
+EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
/*
* Given an inode, search for an open context with the desired characteristics
@@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
#endif /* CONFIG_NFS_V4 */
return &nfsi->vfs_inode;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_inode);
static void nfs_i_callback(struct rcu_head *head)
{
@@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, nfs_i_callback);
}
+EXPORT_SYMBOL_GPL(nfs_destroy_inode);
static inline void nfs4_init_once(struct nfs_inode *nfsi)
{
@@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
}
struct workqueue_struct *nfsiod_workqueue;
+EXPORT_SYMBOL_GPL(nfsiod_workqueue);
/*
* start up the nfsiod workqueue
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 203b4b3..d311128 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -114,6 +114,7 @@ Elong_unlock:
Elong:
return ERR_PTR(-ENAMETOOLONG);
}
+EXPORT_SYMBOL_GPL(nfs_path);
#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2c8ed6f..d2d1b6b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
if (atomic_inc_return(&server->active) == 1)
atomic_inc(&sb->s_active);
}
+EXPORT_SYMBOL_GPL(nfs_sb_active);
void nfs_sb_deactive(struct super_block *sb)
{
@@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
if (atomic_dec_and_test(&server->active))
deactivate_super(sb);
}
+EXPORT_SYMBOL_GPL(nfs_sb_deactive);
/*
* Deliver file system statistics to userspace
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 9f04700..32c1d70 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -5,6 +5,7 @@
*
*/
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/dcache.h>
@@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
}
+EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
void nfs_unblock_sillyrename(struct dentry *dentry)
{
@@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
}
spin_unlock(&dir->i_lock);
}
+EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
/**
* nfs_async_unlink - asynchronous unlinking of a file
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index f9ca30c..0750ebb 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
}
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_write_inode);
/*
* flush the inode to disk.
@@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
return sync_inode(inode, &wbc);
}
+EXPORT_SYMBOL_GPL(nfs_wb_all);
int nfs_wb_page_cancel(struct inode *inode, struct page *page)
{
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
The future module uses these functions, so I am moving them into the v4
directory rather than export v4-only functions to the v4 module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 3 +-
fs/nfs/getroot.c | 130 +---------------------------------------------
fs/nfs/nfs.h | 3 +
fs/nfs/nfs4/getroot.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 144 insertions(+), 129 deletions(-)
create mode 100644 fs/nfs/nfs4/getroot.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 87213a8..5335ce2 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,8 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/delegation.o nfs4/idmap.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
- nfs4/client.o nfs4/module.o nfs4/sysctl.o
+ nfs4/client.o nfs4/module.o nfs4/sysctl.o \
+ nfs4/getroot.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 64e086e..8847d5b 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -45,7 +45,7 @@
* Set the superblock root dentry.
* Note that this function frees the inode in case of error.
*/
-static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
+int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
{
/* The mntroot acts as the dummy root dentry for this superblock */
if (sb->s_root == NULL) {
@@ -71,6 +71,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
}
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_superblock_set_dummy_root);
/*
* get an NFS2/NFS3 root dentry from the root filehandle
@@ -138,130 +139,3 @@ out:
nfs_free_fattr(fsinfo.fattr);
return ret;
}
-
-#ifdef CONFIG_NFS_V4
-
-int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
-{
- struct nfs_fsinfo fsinfo;
- int ret = -ENOMEM;
-
- dprintk("--> nfs4_get_rootfh()\n");
-
- fsinfo.fattr = nfs_alloc_fattr();
- if (fsinfo.fattr == NULL)
- goto out;
-
- /* Start by getting the root filehandle from the server */
- ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
- if (ret < 0) {
- dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
- goto out;
- }
-
- if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
- || !S_ISDIR(fsinfo.fattr->mode)) {
- printk(KERN_ERR "nfs4_get_rootfh:"
- " getroot encountered non-directory\n");
- ret = -ENOTDIR;
- goto out;
- }
-
- if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
- printk(KERN_ERR "nfs4_get_rootfh:"
- " getroot obtained referral\n");
- ret = -EREMOTE;
- goto out;
- }
-
- memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
-out:
- nfs_free_fattr(fsinfo.fattr);
- dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
- return ret;
-}
-
-/*
- * get an NFS4 root dentry from the root filehandle
- */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
- const char *devname)
-{
- struct nfs_server *server = NFS_SB(sb);
- struct nfs_fattr *fattr = NULL;
- struct dentry *ret;
- struct inode *inode;
- void *name = kstrdup(devname, GFP_KERNEL);
- int error;
-
- dprintk("--> nfs4_get_root()\n");
-
- if (!name)
- return ERR_PTR(-ENOMEM);
-
- /* get the info about the server and filesystem */
- error = nfs4_server_capabilities(server, mntfh);
- if (error < 0) {
- dprintk("nfs_get_root: getcaps error = %d\n",
- -error);
- kfree(name);
- return ERR_PTR(error);
- }
-
- fattr = nfs_alloc_fattr();
- if (fattr == NULL) {
- kfree(name);
- return ERR_PTR(-ENOMEM);
- }
-
- /* get the actual root for this mount */
- error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
- if (error < 0) {
- dprintk("nfs_get_root: getattr error = %d\n", -error);
- ret = ERR_PTR(error);
- goto out;
- }
-
- if (fattr->valid & NFS_ATTR_FATTR_FSID &&
- !nfs_fsid_equal(&server->fsid, &fattr->fsid))
- memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
-
- inode = nfs_fhget(sb, mntfh, fattr);
- if (IS_ERR(inode)) {
- dprintk("nfs_get_root: get root inode failed\n");
- ret = ERR_CAST(inode);
- goto out;
- }
-
- error = nfs_superblock_set_dummy_root(sb, inode);
- if (error != 0) {
- ret = ERR_PTR(error);
- goto out;
- }
-
- /* root dentries normally start off anonymous and get spliced in later
- * if the dentry tree reaches them; however if the dentry already
- * exists, we'll pick it up at this point and use it as the root
- */
- ret = d_obtain_alias(inode);
- if (IS_ERR(ret)) {
- dprintk("nfs_get_root: get root dentry failed\n");
- goto out;
- }
-
- security_d_instantiate(ret, inode);
- spin_lock(&ret->d_lock);
- if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
- ret->d_fsdata = name;
- name = NULL;
- }
- spin_unlock(&ret->d_lock);
-out:
- if (name)
- kfree(name);
- nfs_free_fattr(fattr);
- dprintk("<-- nfs4_get_root()\n");
- return ret;
-}
-
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 7b40e24..5fee8ec 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -91,6 +91,9 @@ int nfs_lock(struct file *, int, struct file_lock *);
int nfs_flock(struct file *, int, struct file_lock *);
int nfs_setlease(struct file *, long, struct file_lock **);
+/* Exported in getroot.c */
+int nfs_superblock_set_dummy_root(struct super_block *, struct inode *);
+
/* Exported in inode.c */
int nfs_setattr(struct dentry *, struct iattr *);
int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
diff --git a/fs/nfs/nfs4/getroot.c b/fs/nfs/nfs4/getroot.c
new file mode 100644
index 0000000..9e7841c
--- /dev/null
+++ b/fs/nfs/nfs4/getroot.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ */
+
+#include <linux/dcache.h>
+#include <linux/nfs.h>
+#include <linux/nfs_fs.h>
+#include <linux/security.h>
+
+#include "nfs4_fs.h"
+#include "../nfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_CLIENT
+
+int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
+{
+ struct nfs_fsinfo fsinfo;
+ int ret = -ENOMEM;
+
+ dprintk("--> nfs4_get_rootfh()\n");
+
+ fsinfo.fattr = nfs_alloc_fattr();
+ if (fsinfo.fattr == NULL)
+ goto out;
+
+ /* Start by getting the root filehandle from the server */
+ ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+ if (ret < 0) {
+ dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
+ goto out;
+ }
+
+ if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
+ || !S_ISDIR(fsinfo.fattr->mode)) {
+ printk(KERN_ERR "nfs4_get_rootfh:"
+ " getroot encountered non-directory\n");
+ ret = -ENOTDIR;
+ goto out;
+ }
+
+ if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
+ printk(KERN_ERR "nfs4_get_rootfh:"
+ " getroot obtained referral\n");
+ ret = -EREMOTE;
+ goto out;
+ }
+
+ memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
+out:
+ nfs_free_fattr(fsinfo.fattr);
+ dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
+ return ret;
+}
+
+/*
+ * get an NFS4 root dentry from the root filehandle
+ */
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+ const char *devname)
+{
+ struct nfs_server *server = NFS_SB(sb);
+ struct nfs_fattr *fattr = NULL;
+ struct dentry *ret;
+ struct inode *inode;
+ void *name = kstrdup(devname, GFP_KERNEL);
+ int error;
+
+ dprintk("--> nfs4_get_root()\n");
+
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ /* get the info about the server and filesystem */
+ error = nfs4_server_capabilities(server, mntfh);
+ if (error < 0) {
+ dprintk("nfs_get_root: getcaps error = %d\n",
+ -error);
+ kfree(name);
+ return ERR_PTR(error);
+ }
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL) {
+ kfree(name);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* get the actual root for this mount */
+ error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
+ if (error < 0) {
+ dprintk("nfs_get_root: getattr error = %d\n", -error);
+ ret = ERR_PTR(error);
+ goto out;
+ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_FSID &&
+ !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+ memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
+
+ inode = nfs_fhget(sb, mntfh, fattr);
+ if (IS_ERR(inode)) {
+ dprintk("nfs_get_root: get root inode failed\n");
+ ret = ERR_CAST(inode);
+ goto out;
+ }
+
+ error = nfs_superblock_set_dummy_root(sb, inode);
+ if (error != 0) {
+ ret = ERR_PTR(error);
+ goto out;
+ }
+
+ /* root dentries normally start off anonymous and get spliced in later
+ * if the dentry tree reaches them; however if the dentry already
+ * exists, we'll pick it up at this point and use it as the root
+ */
+ ret = d_obtain_alias(inode);
+ if (IS_ERR(ret)) {
+ dprintk("nfs_get_root: get root dentry failed\n");
+ goto out;
+ }
+
+ security_d_instantiate(ret, inode);
+ spin_lock(&ret->d_lock);
+ if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+ ret->d_fsdata = name;
+ name = NULL;
+ }
+ spin_unlock(&ret->d_lock);
+out:
+ if (name)
+ kfree(name);
+ nfs_free_fattr(fattr);
+ dprintk("<-- nfs4_get_root()\n");
+ return ret;
+}
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
Just checking if CONFIG_NFS_V4 is defined will check if v4 is built in
to the kernel. Instead, we want to check if it is either built in OR a
module (CONFIG_NFS_V4_MODULE). This macro will do both.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/inode.c | 4 ++--
fs/nfs/internal.h | 14 +++++++-------
fs/nfs/namespace.c | 2 +-
fs/nfs/nfs4/Makefile | 7 +++++++
fs/nfs/nfs4/callback.h | 2 +-
fs/nfs/nfs4/delegation.h | 2 +-
fs/nfs/nfs4/nfs4_fs.h | 2 +-
fs/nfs/super.c | 16 ++++++++--------
include/linux/nfs_fs.h | 4 ++--
include/linux/nfs_fs_sb.h | 6 +++---
include/linux/nfs_xdr.h | 4 ++--
11 files changed, 35 insertions(+), 28 deletions(-)
create mode 100644 fs/nfs/nfs4/Makefile
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index a8d138b..57a68b8 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1468,7 +1468,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
nfsi->acl_access = ERR_PTR(-EAGAIN);
nfsi->acl_default = ERR_PTR(-EAGAIN);
#endif
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
nfsi->nfs4_acl = NULL;
#endif /* CONFIG_NFS_V4 */
return &nfsi->vfs_inode;
@@ -1488,7 +1488,7 @@ void nfs_destroy_inode(struct inode *inode)
static inline void nfs4_init_once(struct nfs_inode *nfsi)
{
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
INIT_LIST_HEAD(&nfsi->open_states);
nfsi->delegation = NULL;
nfsi->delegation_state = 0;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 347f49f..8428aab 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -185,7 +185,7 @@ static inline void nfs_fs_proc_exit(void)
#endif
/* nfs4namespace.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
#else
static inline
@@ -222,7 +222,7 @@ extern int nfs3_decode_dirent(struct xdr_stream *,
struct nfs_entry *, int);
/* nfs4xdr.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern int nfs4_decode_dirent(struct xdr_stream *,
struct nfs_entry *, int);
#endif
@@ -232,7 +232,7 @@ extern const u32 nfs41_maxwrite_overhead;
#endif
/* nfs4proc.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern struct rpc_procinfo nfs4_procedures[];
void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *);
#endif
@@ -256,7 +256,7 @@ extern struct inode *nfs_alloc_inode(struct super_block *sb);
extern void nfs_destroy_inode(struct inode *);
extern int nfs_write_inode(struct inode *, struct writeback_control *);
extern void nfs_evict_inode(struct inode *);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern void nfs4_evict_inode(struct inode *);
#endif
void nfs_zap_acl_cache(struct inode *inode);
@@ -264,7 +264,7 @@ extern int nfs_wait_bit_killable(void *word);
/* super.c */
extern struct file_system_type nfs_xdev_fs_type;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern struct file_system_type nfs4_xdev_fs_type;
extern struct file_system_type nfs4_referral_fs_type;
#endif
@@ -280,14 +280,14 @@ extern void nfs_sb_deactive(struct super_block *sb);
extern char *nfs_path(char **p, struct dentry *dentry,
char *buffer, ssize_t buflen);
extern struct vfsmount *nfs_d_automount(struct path *path);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
#endif
/* getroot.c */
extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
const char *);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
const char *);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 721d882..203b4b3 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -115,7 +115,7 @@ Elong:
return ERR_PTR(-ENAMETOOLONG);
}
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
{
struct gss_api_mech *mech;
diff --git a/fs/nfs/nfs4/Makefile b/fs/nfs/nfs4/Makefile
new file mode 100644
index 0000000..0355a3c
--- /dev/null
+++ b/fs/nfs/nfs4/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for NFS v4
+#
+obj-$(CONFIG_NFS_V4) += nfs4.o
+nfs4-y := proc.o xdr.o state.o renewd.o delegation.o idmap.o callback.o \
+ callback_xdr.o callback_proc.o namespace.o client.o module.o \
+ sysctl.o getroot.o inode.o file.o dir.o super.o
diff --git a/fs/nfs/nfs4/callback.h b/fs/nfs/nfs4/callback.h
index 07df5f1..ee18319 100644
--- a/fs/nfs/nfs4/callback.h
+++ b/fs/nfs/nfs4/callback.h
@@ -191,7 +191,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
struct cb_process_state *cps);
extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
struct cb_process_state *cps);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
extern void nfs_callback_down(int minorversion);
extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation,
diff --git a/fs/nfs/nfs4/delegation.h b/fs/nfs/nfs4/delegation.h
index 40bd6c2..ea58699 100644
--- a/fs/nfs/nfs4/delegation.h
+++ b/fs/nfs/nfs4/delegation.h
@@ -8,7 +8,7 @@
#ifndef FS_NFS_DELEGATION_H
#define FS_NFS_DELEGATION_H
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
/*
* NFSv4 delegation
*/
diff --git a/fs/nfs/nfs4/nfs4_fs.h b/fs/nfs/nfs4/nfs4_fs.h
index 4d7d0ae..01d7b63 100644
--- a/fs/nfs/nfs4/nfs4_fs.h
+++ b/fs/nfs/nfs4/nfs4_fs.h
@@ -9,7 +9,7 @@
#ifndef __LINUX_FS_NFS_NFS4_FS_H
#define __LINUX_FS_NFS_NFS4_FS_H
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
struct idmap;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 7bab19e..2c8ed6f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -318,7 +318,7 @@ int __init register_nfs_fs(void)
ret = nfs_register_sysctl();
if (ret < 0)
goto error_1;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
ret = init_nfs_v4();
if (ret < 0)
goto error_2;
@@ -326,7 +326,7 @@ int __init register_nfs_fs(void)
register_shrinker(&acl_shrinker);
return 0;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
error_2:
nfs_unregister_sysctl();
#endif
@@ -342,7 +342,7 @@ error_0:
void __exit unregister_nfs_fs(void)
{
unregister_shrinker(&acl_shrinker);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
exit_nfs_v4();
#endif
nfs_unregister_sysctl();
@@ -535,7 +535,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
nfs_show_mountd_netid(m, nfss, showdefaults);
}
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
int showdefaults)
{
@@ -656,7 +656,7 @@ int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
}
EXPORT_SYMBOL_GPL(nfs_show_options);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
#ifdef CONFIG_NFS_V4_1
static void show_sessions(struct seq_file *m, struct nfs_server *server)
{
@@ -668,7 +668,7 @@ static void show_sessions(struct seq_file *m, struct nfs_server *server) {}
#endif
#endif
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
#ifdef CONFIG_NFS_V4_1
static void show_pnfs(struct seq_file *m, struct nfs_server *server)
{
@@ -738,7 +738,7 @@ int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
seq_printf(m, ",bsize=%u", nfss->bsize);
seq_printf(m, ",namlen=%u", nfss->namelen);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
if (nfss->nfs_client->rpc_ops->version == 4) {
seq_printf(m, "\n\tnfsv4:\t");
seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
@@ -1866,7 +1866,7 @@ out_v3_not_compiled:
return -EPROTONOSUPPORT;
#endif /* !CONFIG_NFS_V3 */
-#ifndef CONFIG_NFS_V4
+#if !IS_ENABLED(CONFIG_NFS_V4)
out_v4_not_compiled:
dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n");
return -EPROTONOSUPPORT;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 4814fcc..8cd22a5 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -188,7 +188,7 @@ struct nfs_inode {
struct hlist_head silly_list;
wait_queue_head_t waitqueue;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
struct nfs4_cached_acl *nfs4_acl;
/* NFSv4 state */
struct list_head open_states;
@@ -405,7 +405,7 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
/*
* linux/fs/nfs/file.c
*/
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern const struct file_operations nfs4_file_operations;
#endif /* CONFIG_NFS_V4 */
extern const struct address_space_operations nfs_file_aops;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index ba4d765..ff49972 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -46,7 +46,7 @@ struct nfs_client {
u32 cl_minorversion;/* NFSv4 minorversion */
struct rpc_cred *cl_machine_cred;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
u64 cl_clientid; /* constant */
nfs4_verifier cl_confirm; /* Clientid verifier */
unsigned long cl_state;
@@ -132,7 +132,7 @@ struct nfs_server {
#endif
u32 pnfs_blksize; /* layout_blksize attr */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
u32 attr_bitmask[3];/* V4 bitmask representing the set
of attributes supported on this
filesystem */
@@ -190,7 +190,7 @@ struct nfs_server {
/* maximum number of slots to use */
#define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
/* Sessions */
#define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index afa36f8..164fbef 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -791,7 +791,7 @@ struct nfs3_getaclres {
struct posix_acl * acl_default;
};
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
typedef u64 clientid4;
@@ -1185,7 +1185,7 @@ struct nfs_write_data {
int ds_commit_index;
const struct rpc_call_ops *mds_ops;
int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
unsigned long timestamp; /* For lease renewal */
#endif
__u64 mds_offset; /* Filelayout dense stripe */
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
Just checking if CONFIG_NFS_V3 is defined will check if v3 is built in
to the kernel. Instead, we'll want to check if it is either built in OR
a module (CONFIG_NFS_V3_MODULE). This macro will do both.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 6 +++---
fs/nfs/dir.c | 2 +-
fs/nfs/direct.c | 2 +-
fs/nfs/file.c | 2 +-
fs/nfs/super.c | 6 +++---
fs/nfs/write.c | 8 ++++----
include/linux/nfs_fs.h | 6 +++---
7 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 3f36e6e..20cfc99 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -123,13 +123,13 @@ struct rpc_stat nfs_rpcstat = {
* Once everything has been converted this function will
* be removed.
*/
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
static void nfs_module_null_function(void)
{
}
#endif
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
static struct nfs_subversion nfs_v3_mod = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -238,7 +238,7 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
*/
void __init nfs_register_versions(void)
{
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
register_nfs_version(&nfs_v3_mod);
#endif
#ifdef CONFIG_NFS_V4
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a5e3a36..96bcfa3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -80,7 +80,7 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
const struct inode_operations nfs3_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 1940f1a..7aa353c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -460,7 +460,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
}
}
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{
struct inode *inode = dreq->inode;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 4ac4dae..d11bb90 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -44,7 +44,7 @@
static const struct vm_operations_struct nfs_file_vm_ops;
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index aee7b00..2889a70 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -68,7 +68,7 @@
#define NFSDBG_FACILITY NFSDBG_VFS
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
#define NFS_DEFAULT_VERSION 3
#else
#define NFS_DEFAULT_VERSION 2
@@ -1908,7 +1908,7 @@ static int nfs_validate_mount_data(void *options,
}
}
-#ifndef CONFIG_NFS_V3
+#if !IS_ENABLED(CONFIG_NFS_V3)
if (args->version == 3)
goto out_v3_not_compiled;
#endif /* !CONFIG_NFS_V3 */
@@ -1928,7 +1928,7 @@ out_no_sec:
dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
return -EINVAL;
-#ifndef CONFIG_NFS_V3
+#if !IS_ENABLED(CONFIG_NFS_V3)
out_v3_not_compiled:
dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
return -EPROTONOSUPPORT;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0c38852..1e92376 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -431,7 +431,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
__set_page_dirty_nobuffers(req->wb_page);
}
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
/*
* Add a request to the inode's commit list.
*/
@@ -516,7 +516,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req,
}
#endif
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
static int
nfs_need_commit(struct nfs_inode *nfsi)
{
@@ -1238,7 +1238,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
return;
nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
/* We tried a write call, but the server did not
* commit data to stable storage even though we
@@ -1297,7 +1297,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
}
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait)
{
int ret;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 92ecf55..666ebea 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -406,7 +406,7 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
* linux/fs/nfs/file.c
*/
extern const struct inode_operations nfs_file_inode_operations;
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
extern const struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_file_operations;
@@ -464,7 +464,7 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
* linux/fs/nfs/dir.c
*/
extern const struct inode_operations nfs_dir_inode_operations;
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
extern const struct inode_operations nfs3_dir_inode_operations;
#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_dir_operations;
@@ -524,7 +524,7 @@ extern void nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
extern int nfs_wb_all(struct inode *inode);
extern int nfs_wb_page(struct inode *inode, struct page* page);
extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, int);
extern struct nfs_write_data *nfs_commitdata_alloc(void);
extern void nfs_commit_free(struct nfs_write_data *wdata);
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
With this change, nfs v4 will completely configure itself through its
init() and exit() functions.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs4/module.c | 6 ++++++
fs/nfs/nfs4/nfs4.h | 2 ++
fs/nfs/super.c | 10 ++--------
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/nfs4/module.c b/fs/nfs/nfs4/module.c
index 9edd174..c57b642 100644
--- a/fs/nfs/nfs4/module.c
+++ b/fs/nfs/nfs4/module.c
@@ -48,9 +48,14 @@ int __init init_nfs_v4(void)
ret = nfs4_register_sysctl();
if (ret < 0)
goto error_0;
+ ret = register_filesystem(&nfs4_fs_type);
+ if (ret < 0)
+ goto error_1;
register_nfs_version(&nfs_v4);
return 0;
+error_1:
+ nfs4_unregister_sysctl();
error_0:
return ret;
}
@@ -58,5 +63,6 @@ error_0:
void exit_nfs_v4(void)
{
unregister_nfs_version(&nfs_v4);
+ unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl();
}
diff --git a/fs/nfs/nfs4/nfs4.h b/fs/nfs/nfs4/nfs4.h
index 5f69528..c24fb13 100644
--- a/fs/nfs/nfs4/nfs4.h
+++ b/fs/nfs/nfs4/nfs4.h
@@ -3,6 +3,8 @@
#include "../nfs.h"
+extern struct file_system_type nfs4_fs_type;
+
int init_nfs_v4(void);
void exit_nfs_v4(void);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 3306c43..f5c5cd9 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -321,7 +321,7 @@ static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_typ
int flags, const char *dev_name, void *raw_data);
static void nfs4_kill_super(struct super_block *sb);
-static struct file_system_type nfs4_fs_type = {
+struct file_system_type nfs4_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_mount,
@@ -400,18 +400,13 @@ int __init register_nfs_fs(void)
ret = init_nfs_v4();
if (ret < 0)
goto error_2;
- ret = register_filesystem(&nfs4_fs_type);
- if (ret < 0)
- goto error_3;
#endif
register_shrinker(&acl_shrinker);
return 0;
#ifdef CONFIG_NFS_V4
-error_3:
- nfs_unregister_sysctl();
error_2:
- exit_nfs_v4();
+ nfs_unregister_sysctl();
#endif
error_1:
unregister_filesystem(&nfs_fs_type);
@@ -426,7 +421,6 @@ void __exit unregister_nfs_fs(void)
{
unregister_shrinker(&acl_shrinker);
#ifdef CONFIG_NFS_V4
- unregister_filesystem(&nfs4_fs_type);
exit_nfs_v4();
#endif
nfs_unregister_sysctl();
--
1.7.8.3
From: Bryan Schumaker <[email protected]>
This was located in a file belonging to NFS v2, but it is also used by
v3. I moved it to a generic NFS client file to keep it from
disappearing once v2 becomes a module.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs2xdr.c | 64 ----------------------------------------------------
2 files changed, 66 insertions(+), 64 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 41bd67f..b8e9769 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -2014,6 +2014,72 @@ void nfs_fs_proc_exit(void)
#endif /* CONFIG_PROC_FS */
+/* Mapping from NFS error code to "errno" error code. */
+#define errno_NFSERR_IO EIO
+
+/*
+ * We need to translate between nfs status return values and
+ * the local errno values which may not be the same.
+ */
+static const struct {
+ int stat;
+ int errno;
+} nfs_errtbl[] = {
+ { NFS_OK, 0 },
+ { NFSERR_PERM, -EPERM },
+ { NFSERR_NOENT, -ENOENT },
+ { NFSERR_IO, -errno_NFSERR_IO},
+ { NFSERR_NXIO, -ENXIO },
+/* { NFSERR_EAGAIN, -EAGAIN }, */
+ { NFSERR_ACCES, -EACCES },
+ { NFSERR_EXIST, -EEXIST },
+ { NFSERR_XDEV, -EXDEV },
+ { NFSERR_NODEV, -ENODEV },
+ { NFSERR_NOTDIR, -ENOTDIR },
+ { NFSERR_ISDIR, -EISDIR },
+ { NFSERR_INVAL, -EINVAL },
+ { NFSERR_FBIG, -EFBIG },
+ { NFSERR_NOSPC, -ENOSPC },
+ { NFSERR_ROFS, -EROFS },
+ { NFSERR_MLINK, -EMLINK },
+ { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
+ { NFSERR_NOTEMPTY, -ENOTEMPTY },
+ { NFSERR_DQUOT, -EDQUOT },
+ { NFSERR_STALE, -ESTALE },
+ { NFSERR_REMOTE, -EREMOTE },
+#ifdef EWFLUSH
+ { NFSERR_WFLUSH, -EWFLUSH },
+#endif
+ { NFSERR_BADHANDLE, -EBADHANDLE },
+ { NFSERR_NOT_SYNC, -ENOTSYNC },
+ { NFSERR_BAD_COOKIE, -EBADCOOKIE },
+ { NFSERR_NOTSUPP, -ENOTSUPP },
+ { NFSERR_TOOSMALL, -ETOOSMALL },
+ { NFSERR_SERVERFAULT, -EREMOTEIO },
+ { NFSERR_BADTYPE, -EBADTYPE },
+ { NFSERR_JUKEBOX, -EJUKEBOX },
+ { -1, -EIO }
+};
+
+/**
+ * nfs_stat_to_errno - convert an NFS status code to a local errno
+ * @status: NFS status code to convert
+ *
+ * Returns a local errno value, or -EIO if the NFS status code is
+ * not recognized. This function is used jointly by NFSv2 and NFSv3.
+ */
+int nfs_stat_to_errno(enum nfs_stat status)
+{
+ int i;
+
+ for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+ if (nfs_errtbl[i].stat == (int)status)
+ return nfs_errtbl[i].errno;
+ }
+ dprintk("NFS: Unrecognized nfs status value: %u\n", status);
+ return nfs_errtbl[i].errno;
+}
+
module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
"Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 792cb13..61df96d 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -1057,70 +1057,6 @@ out_default:
return nfs_stat_to_errno(status);
}
-
-/*
- * We need to translate between nfs status return values and
- * the local errno values which may not be the same.
- */
-static const struct {
- int stat;
- int errno;
-} nfs_errtbl[] = {
- { NFS_OK, 0 },
- { NFSERR_PERM, -EPERM },
- { NFSERR_NOENT, -ENOENT },
- { NFSERR_IO, -errno_NFSERR_IO},
- { NFSERR_NXIO, -ENXIO },
-/* { NFSERR_EAGAIN, -EAGAIN }, */
- { NFSERR_ACCES, -EACCES },
- { NFSERR_EXIST, -EEXIST },
- { NFSERR_XDEV, -EXDEV },
- { NFSERR_NODEV, -ENODEV },
- { NFSERR_NOTDIR, -ENOTDIR },
- { NFSERR_ISDIR, -EISDIR },
- { NFSERR_INVAL, -EINVAL },
- { NFSERR_FBIG, -EFBIG },
- { NFSERR_NOSPC, -ENOSPC },
- { NFSERR_ROFS, -EROFS },
- { NFSERR_MLINK, -EMLINK },
- { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
- { NFSERR_NOTEMPTY, -ENOTEMPTY },
- { NFSERR_DQUOT, -EDQUOT },
- { NFSERR_STALE, -ESTALE },
- { NFSERR_REMOTE, -EREMOTE },
-#ifdef EWFLUSH
- { NFSERR_WFLUSH, -EWFLUSH },
-#endif
- { NFSERR_BADHANDLE, -EBADHANDLE },
- { NFSERR_NOT_SYNC, -ENOTSYNC },
- { NFSERR_BAD_COOKIE, -EBADCOOKIE },
- { NFSERR_NOTSUPP, -ENOTSUPP },
- { NFSERR_TOOSMALL, -ETOOSMALL },
- { NFSERR_SERVERFAULT, -EREMOTEIO },
- { NFSERR_BADTYPE, -EBADTYPE },
- { NFSERR_JUKEBOX, -EJUKEBOX },
- { -1, -EIO }
-};
-
-/**
- * nfs_stat_to_errno - convert an NFS status code to a local errno
- * @status: NFS status code to convert
- *
- * Returns a local errno value, or -EIO if the NFS status code is
- * not recognized. This function is used jointly by NFSv2 and NFSv3.
- */
-int nfs_stat_to_errno(enum nfs_stat status)
-{
- int i;
-
- for (i = 0; nfs_errtbl[i].stat != -1; i++) {
- if (nfs_errtbl[i].stat == (int)status)
- return nfs_errtbl[i].errno;
- }
- dprintk("NFS: Unrecognized nfs status value: %u\n", status);
- return nfs_errtbl[i].errno;
-}
-
#define PROC(proc, argtype, restype, timer) \
[NFSPROC_##proc] = { \
.p_proc = NFSPROC_##proc, \
--
1.7.8.3
On Fri Jan 13 16:05:29 2012, Bryan Schumaker wrote:
> On Fri Jan 13 15:48:38 2012, Chuck Lever wrote:
>>
>> On Jan 13, 2012, at 3:10 PM, [email protected] wrote:
>>
>>> From: Bryan Schumaker <[email protected]>
>>>
>>> The v4 code uses these functions in the generic client, so they need to
>>> be available to modules.
>>
>> If you add the EXPORT_SYMBOL() macros in separate patches, is that bisect-able? Seems like you should add the macros when you move functions.
>
> I thought it was since it would detect namespace collisions... I can
> fix it if I need to.
>
>>
>> It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
>
> Not that I know of. I found examples for compiling directories as
> modules, but not specific files or parts of files.
I should have looked at how obj-$(CONFIG_PNFS_FILE_LAYOUT) is done, so
it is possible. I would still need to split out a lot of the code into
nfs4 specific files to get the module to compile. This would create a
lot more files in fs/nfs/ directory, especially for NFS v4. I figured
subdirectories might be easier to work with, especially if we're going
to name everything with nfs3 or nfs4 as a prefix anyway.
- Bryan
>
>>
>>> Signed-off-by: Bryan Schumaker <[email protected]>
>>> ---
>>> fs/nfs/client.c | 2 ++
>>> fs/nfs/dir.c | 2 ++
>>> fs/nfs/dns_resolve.c | 4 ++++
>>> fs/nfs/fscache.c | 4 ++++
>>> fs/nfs/inode.c | 9 +++++++++
>>> fs/nfs/namespace.c | 1 +
>>> fs/nfs/super.c | 2 ++
>>> fs/nfs/unlink.c | 3 +++
>>> fs/nfs/write.c | 2 ++
>>> 9 files changed, 29 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>>> index 2c3f50e..0e4ddbe 100644
>>> --- a/fs/nfs/client.c
>>> +++ b/fs/nfs/client.c
>>> @@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
>>> spin_unlock(&nfs_client_lock);
>>>
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
>>>
>>> static void nfs_server_remove_lists(struct nfs_server *server)
>>> {
>>> @@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
>>> nfs_release_automount_timer();
>>> dprintk("<-- nfs_free_server()\n");
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_free_server);
>>>
>>> /*
>>> * Create a version 2 or 3 volume record
>>> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
>>> index 210284f..909f8de 100644
>>> --- a/fs/nfs/dir.c
>>> +++ b/fs/nfs/dir.c
>>> @@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
>>> {
>>> NFS_I(dir)->cache_change_attribute++;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
>>>
>>> /*
>>> * A check for whether or not the parent directory has changed.
>>> @@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
>>> {
>>> return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_may_open);
>>>
>>> int nfs_permission(struct inode *inode, int mask)
>>> {
>>> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
>>> index a6e711a..8b9aeba 100644
>>> --- a/fs/nfs/dns_resolve.c
>>> +++ b/fs/nfs/dns_resolve.c
>>> @@ -6,6 +6,8 @@
>>> * Resolves DNS hostnames into valid ip addresses
>>> */
>>>
>>> +#include <linux/module.h>
>>> +
>>> #ifdef CONFIG_NFS_USE_KERNEL_DNS
>>>
>>> #include <linux/sunrpc/clnt.h>
>>> @@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>> kfree(ip_addr);
>>> return ret;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>
>>> #else
>>>
>>> @@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>> ret = -ESRCH;
>>> return ret;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>
>>> int nfs_dns_resolver_init(void)
>>> {
>>> diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
>>> index 419119c..94e2d51 100644
>>> --- a/fs/nfs/fscache.c
>>> +++ b/fs/nfs/fscache.c
>>> @@ -9,6 +9,7 @@
>>> * 2 of the Licence, or (at your option) any later version.
>>> */
>>>
>>> +#include <linux/module.h>
>>> #include <linux/init.h>
>>> #include <linux/kernel.h>
>>> #include <linux/sched.h>
>>> @@ -163,6 +164,7 @@ non_unique:
>>> printk(KERN_WARNING "NFS:"
>>> " Cache request denied due to non-unique superblock keys\n");
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
>>>
>>> /*
>>> * release a per-superblock cookie
>>> @@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
>>> nfss->fscache_key = NULL;
>>> }
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
>>>
>>> /*
>>> * Initialise the per-inode cache cookie pointer for an NFS inode.
>>> @@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
>>> nfs_fscache_inode_unlock(inode);
>>> }
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
>>>
>>> /*
>>> * Replace a per-inode cookie due to revalidation detecting a file having
>>> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
>>> index 57a68b8..d7afc2b 100644
>>> --- a/fs/nfs/inode.c
>>> +++ b/fs/nfs/inode.c
>>> @@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
>>> schedule();
>>> return 0;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
>>>
>>> /**
>>> * nfs_compat_user_ino64 - returns the user-visible inode number
>>> @@ -421,6 +422,7 @@ out_no_inode:
>>> dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
>>> goto out;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_fhget);
>>>
>>> #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
>>>
>>> @@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
>>> }
>>> return ctx;
>>> }
>>> +EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
>>>
>>> struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>> {
>>> @@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>> atomic_inc(&ctx->lock_context.count);
>>> return ctx;
>>> }
>>> +EXPORT_SYMBOL_GPL(get_nfs_open_context);
>>>
>>> static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
>>> {
>>> @@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
>>> {
>>> __put_nfs_open_context(ctx, 0);
>>> }
>>> +EXPORT_SYMBOL_GPL(put_nfs_open_context);
>>>
>>> /*
>>> * Ensure that mmap has a recent RPC credential for use when writing out
>>> @@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
>>> list_add(&ctx->list, &nfsi->open_files);
>>> spin_unlock(&inode->i_lock);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
>>>
>>> /*
>>> * Given an inode, search for an open context with the desired characteristics
>>> @@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
>>> #endif /* CONFIG_NFS_V4 */
>>> return &nfsi->vfs_inode;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_alloc_inode);
>>>
>>> static void nfs_i_callback(struct rcu_head *head)
>>> {
>>> @@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
>>> {
>>> call_rcu(&inode->i_rcu, nfs_i_callback);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_destroy_inode);
>>>
>>> static inline void nfs4_init_once(struct nfs_inode *nfsi)
>>> {
>>> @@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
>>> }
>>>
>>> struct workqueue_struct *nfsiod_workqueue;
>>> +EXPORT_SYMBOL_GPL(nfsiod_workqueue);
>>>
>>> /*
>>> * start up the nfsiod workqueue
>>> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
>>> index 203b4b3..d311128 100644
>>> --- a/fs/nfs/namespace.c
>>> +++ b/fs/nfs/namespace.c
>>> @@ -114,6 +114,7 @@ Elong_unlock:
>>> Elong:
>>> return ERR_PTR(-ENAMETOOLONG);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_path);
>>>
>>> #if IS_ENABLED(CONFIG_NFS_V4)
>>> rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
>>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>>> index 2c8ed6f..d2d1b6b 100644
>>> --- a/fs/nfs/super.c
>>> +++ b/fs/nfs/super.c
>>> @@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
>>> if (atomic_inc_return(&server->active) == 1)
>>> atomic_inc(&sb->s_active);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_sb_active);
>>>
>>> void nfs_sb_deactive(struct super_block *sb)
>>> {
>>> @@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
>>> if (atomic_dec_and_test(&server->active))
>>> deactivate_super(sb);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_sb_deactive);
>>>
>>> /*
>>> * Deliver file system statistics to userspace
>>> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
>>> index 9f04700..32c1d70 100644
>>> --- a/fs/nfs/unlink.c
>>> +++ b/fs/nfs/unlink.c
>>> @@ -5,6 +5,7 @@
>>> *
>>> */
>>>
>>> +#include <linux/module.h>
>>> #include <linux/slab.h>
>>> #include <linux/string.h>
>>> #include <linux/dcache.h>
>>> @@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
>>>
>>> wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
>>>
>>> void nfs_unblock_sillyrename(struct dentry *dentry)
>>> {
>>> @@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
>>> }
>>> spin_unlock(&dir->i_lock);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
>>>
>>> /**
>>> * nfs_async_unlink - asynchronous unlinking of a file
>>> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
>>> index f9ca30c..0750ebb 100644
>>> --- a/fs/nfs/write.c
>>> +++ b/fs/nfs/write.c
>>> @@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
>>> }
>>> return ret;
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_write_inode);
>>>
>>> /*
>>> * flush the inode to disk.
>>> @@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
>>>
>>> return sync_inode(inode, &wbc);
>>> }
>>> +EXPORT_SYMBOL_GPL(nfs_wb_all);
>>>
>>> int nfs_wb_page_cancel(struct inode *inode, struct page *page)
>>> {
>>> --
>>> 1.7.8.3
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>>> the body of a message to [email protected]
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
>
On Fri Jan 13 16:25:14 2012, Chuck Lever wrote:
>
> On Jan 13, 2012, at 4:12 PM, Bryan Schumaker wrote:
>
>> On Fri Jan 13 16:05:29 2012, Bryan Schumaker wrote:
>>> On Fri Jan 13 15:48:38 2012, Chuck Lever wrote:
>>>>
>>>> On Jan 13, 2012, at 3:10 PM, [email protected] wrote:
>>>>
>>>>> From: Bryan Schumaker <[email protected]>
>>>>>
>>>>> The v4 code uses these functions in the generic client, so they need to
>>>>> be available to modules.
>>>>
>>>> If you add the EXPORT_SYMBOL() macros in separate patches, is that bisect-able? Seems like you should add the macros when you move functions.
>>>
>>> I thought it was since it would detect namespace collisions... I can
>>> fix it if I need to.
>>>
>>>>
>>>> It seems like an enormous amount of code movement. Isn't there a way to accomplish modularization without moving things into separate directories?
>>>
>>> Not that I know of. I found examples for compiling directories as
>>> modules, but not specific files or parts of files.
>>
>> I should have looked at how obj-$(CONFIG_PNFS_FILE_LAYOUT) is done, so
>> it is possible. I would still need to split out a lot of the code into
>> nfs4 specific files to get the module to compile.
>
> Do you have specific examples of what needs to be split?
One example would be the nfs4_fs_type in super.c, since it would need
to be registered by the v4 module. I ended up having to move over that
and a few other #ifdef CONFIG_NFS_V4 blocks from the file to get it to
compile.
>
>> This would create a
>> lot more files in fs/nfs/ directory, especially for NFS v4. I figured
>> subdirectories might be easier to work with, especially if we're going
>> to name everything with nfs3 or nfs4 as a prefix anyway.
>
> Moving existing code around like this makes it harder to forward and back-port patches, and it truncates the "git blame" history on all these files. Ideally we might want subdirectories, if we were starting from scratch, but that's not where we are today.
git blame -C gets it right... but you're right that without this option
it doesn't. The -C is slower, too, since it has to do the copy
detection stuff.
>
> I vote for starting with something simpler, for example modularizing just NFSv2 and NFSv3. We might want to split this work over more than one kernel release anyway, to avoid introducing a lot of churn and bugs all at once, and that's one way to divide the effort.
That makes sense. Work out the basic bugs first before v4 since v4 is
significantly more complicated.
>
>> - Bryan
>>
>>>
>>>>
>>>>> Signed-off-by: Bryan Schumaker <[email protected]>
>>>>> ---
>>>>> fs/nfs/client.c | 2 ++
>>>>> fs/nfs/dir.c | 2 ++
>>>>> fs/nfs/dns_resolve.c | 4 ++++
>>>>> fs/nfs/fscache.c | 4 ++++
>>>>> fs/nfs/inode.c | 9 +++++++++
>>>>> fs/nfs/namespace.c | 1 +
>>>>> fs/nfs/super.c | 2 ++
>>>>> fs/nfs/unlink.c | 3 +++
>>>>> fs/nfs/write.c | 2 ++
>>>>> 9 files changed, 29 insertions(+), 0 deletions(-)
>>>>>
>>>>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>>>>> index 2c3f50e..0e4ddbe 100644
>>>>> --- a/fs/nfs/client.c
>>>>> +++ b/fs/nfs/client.c
>>>>> @@ -913,6 +913,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
>>>>> spin_unlock(&nfs_client_lock);
>>>>>
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
>>>>>
>>>>> static void nfs_server_remove_lists(struct nfs_server *server)
>>>>> {
>>>>> @@ -992,6 +993,7 @@ void nfs_free_server(struct nfs_server *server)
>>>>> nfs_release_automount_timer();
>>>>> dprintk("<-- nfs_free_server()\n");
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_free_server);
>>>>>
>>>>> /*
>>>>> * Create a version 2 or 3 volume record
>>>>> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
>>>>> index 210284f..909f8de 100644
>>>>> --- a/fs/nfs/dir.c
>>>>> +++ b/fs/nfs/dir.c
>>>>> @@ -917,6 +917,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
>>>>> {
>>>>> NFS_I(dir)->cache_change_attribute++;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
>>>>>
>>>>> /*
>>>>> * A check for whether or not the parent directory has changed.
>>>>> @@ -1932,6 +1933,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
>>>>> {
>>>>> return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_may_open);
>>>>>
>>>>> int nfs_permission(struct inode *inode, int mask)
>>>>> {
>>>>> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
>>>>> index a6e711a..8b9aeba 100644
>>>>> --- a/fs/nfs/dns_resolve.c
>>>>> +++ b/fs/nfs/dns_resolve.c
>>>>> @@ -6,6 +6,8 @@
>>>>> * Resolves DNS hostnames into valid ip addresses
>>>>> */
>>>>>
>>>>> +#include <linux/module.h>
>>>>> +
>>>>> #ifdef CONFIG_NFS_USE_KERNEL_DNS
>>>>>
>>>>> #include <linux/sunrpc/clnt.h>
>>>>> @@ -26,6 +28,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>>>> kfree(ip_addr);
>>>>> return ret;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>>>
>>>>> #else
>>>>>
>>>>> @@ -358,6 +361,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
>>>>> ret = -ESRCH;
>>>>> return ret;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
>>>>>
>>>>> int nfs_dns_resolver_init(void)
>>>>> {
>>>>> diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
>>>>> index 419119c..94e2d51 100644
>>>>> --- a/fs/nfs/fscache.c
>>>>> +++ b/fs/nfs/fscache.c
>>>>> @@ -9,6 +9,7 @@
>>>>> * 2 of the Licence, or (at your option) any later version.
>>>>> */
>>>>>
>>>>> +#include <linux/module.h>
>>>>> #include <linux/init.h>
>>>>> #include <linux/kernel.h>
>>>>> #include <linux/sched.h>
>>>>> @@ -163,6 +164,7 @@ non_unique:
>>>>> printk(KERN_WARNING "NFS:"
>>>>> " Cache request denied due to non-unique superblock keys\n");
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);
>>>>>
>>>>> /*
>>>>> * release a per-superblock cookie
>>>>> @@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
>>>>> nfss->fscache_key = NULL;
>>>>> }
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);
>>>>>
>>>>> /*
>>>>> * Initialise the per-inode cache cookie pointer for an NFS inode.
>>>>> @@ -318,6 +321,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
>>>>> nfs_fscache_inode_unlock(inode);
>>>>> }
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
>>>>>
>>>>> /*
>>>>> * Replace a per-inode cookie due to revalidation detecting a file having
>>>>> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
>>>>> index 57a68b8..d7afc2b 100644
>>>>> --- a/fs/nfs/inode.c
>>>>> +++ b/fs/nfs/inode.c
>>>>> @@ -81,6 +81,7 @@ int nfs_wait_bit_killable(void *word)
>>>>> schedule();
>>>>> return 0;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
>>>>>
>>>>> /**
>>>>> * nfs_compat_user_ino64 - returns the user-visible inode number
>>>>> @@ -421,6 +422,7 @@ out_no_inode:
>>>>> dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
>>>>> goto out;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_fhget);
>>>>>
>>>>> #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
>>>>>
>>>>> @@ -673,6 +675,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
>>>>> }
>>>>> return ctx;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
>>>>>
>>>>> struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>>>> {
>>>>> @@ -680,6 +683,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
>>>>> atomic_inc(&ctx->lock_context.count);
>>>>> return ctx;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(get_nfs_open_context);
>>>>>
>>>>> static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
>>>>> {
>>>>> @@ -706,6 +710,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
>>>>> {
>>>>> __put_nfs_open_context(ctx, 0);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(put_nfs_open_context);
>>>>>
>>>>> /*
>>>>> * Ensure that mmap has a recent RPC credential for use when writing out
>>>>> @@ -721,6 +726,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
>>>>> list_add(&ctx->list, &nfsi->open_files);
>>>>> spin_unlock(&inode->i_lock);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
>>>>>
>>>>> /*
>>>>> * Given an inode, search for an open context with the desired characteristics
>>>>> @@ -1473,6 +1479,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
>>>>> #endif /* CONFIG_NFS_V4 */
>>>>> return &nfsi->vfs_inode;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_alloc_inode);
>>>>>
>>>>> static void nfs_i_callback(struct rcu_head *head)
>>>>> {
>>>>> @@ -1485,6 +1492,7 @@ void nfs_destroy_inode(struct inode *inode)
>>>>> {
>>>>> call_rcu(&inode->i_rcu, nfs_i_callback);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_destroy_inode);
>>>>>
>>>>> static inline void nfs4_init_once(struct nfs_inode *nfsi)
>>>>> {
>>>>> @@ -1534,6 +1542,7 @@ static void nfs_destroy_inodecache(void)
>>>>> }
>>>>>
>>>>> struct workqueue_struct *nfsiod_workqueue;
>>>>> +EXPORT_SYMBOL_GPL(nfsiod_workqueue);
>>>>>
>>>>> /*
>>>>> * start up the nfsiod workqueue
>>>>> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
>>>>> index 203b4b3..d311128 100644
>>>>> --- a/fs/nfs/namespace.c
>>>>> +++ b/fs/nfs/namespace.c
>>>>> @@ -114,6 +114,7 @@ Elong_unlock:
>>>>> Elong:
>>>>> return ERR_PTR(-ENAMETOOLONG);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_path);
>>>>>
>>>>> #if IS_ENABLED(CONFIG_NFS_V4)
>>>>> rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
>>>>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>>>>> index 2c8ed6f..d2d1b6b 100644
>>>>> --- a/fs/nfs/super.c
>>>>> +++ b/fs/nfs/super.c
>>>>> @@ -356,6 +356,7 @@ void nfs_sb_active(struct super_block *sb)
>>>>> if (atomic_inc_return(&server->active) == 1)
>>>>> atomic_inc(&sb->s_active);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_sb_active);
>>>>>
>>>>> void nfs_sb_deactive(struct super_block *sb)
>>>>> {
>>>>> @@ -364,6 +365,7 @@ void nfs_sb_deactive(struct super_block *sb)
>>>>> if (atomic_dec_and_test(&server->active))
>>>>> deactivate_super(sb);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_sb_deactive);
>>>>>
>>>>> /*
>>>>> * Deliver file system statistics to userspace
>>>>> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
>>>>> index 9f04700..32c1d70 100644
>>>>> --- a/fs/nfs/unlink.c
>>>>> +++ b/fs/nfs/unlink.c
>>>>> @@ -5,6 +5,7 @@
>>>>> *
>>>>> */
>>>>>
>>>>> +#include <linux/module.h>
>>>>> #include <linux/slab.h>
>>>>> #include <linux/string.h>
>>>>> #include <linux/dcache.h>
>>>>> @@ -229,6 +230,7 @@ void nfs_block_sillyrename(struct dentry *dentry)
>>>>>
>>>>> wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_block_sillyrename);
>>>>>
>>>>> void nfs_unblock_sillyrename(struct dentry *dentry)
>>>>> {
>>>>> @@ -250,6 +252,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
>>>>> }
>>>>> spin_unlock(&dir->i_lock);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_unblock_sillyrename);
>>>>>
>>>>> /**
>>>>> * nfs_async_unlink - asynchronous unlinking of a file
>>>>> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
>>>>> index f9ca30c..0750ebb 100644
>>>>> --- a/fs/nfs/write.c
>>>>> +++ b/fs/nfs/write.c
>>>>> @@ -1608,6 +1608,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
>>>>> }
>>>>> return ret;
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_write_inode);
>>>>>
>>>>> /*
>>>>> * flush the inode to disk.
>>>>> @@ -1623,6 +1624,7 @@ int nfs_wb_all(struct inode *inode)
>>>>>
>>>>> return sync_inode(inode, &wbc);
>>>>> }
>>>>> +EXPORT_SYMBOL_GPL(nfs_wb_all);
>>>>>
>>>>> int nfs_wb_page_cancel(struct inode *inode, struct page *page)
>>>>> {
>>>>> --
>>>>> 1.7.8.3
>>>>>
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>>>>> the body of a message to [email protected]
>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>
>>>
>>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
From: Bryan Schumaker <[email protected]>
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/inode.c | 24 ++----------------------
fs/nfs/nfs.h | 1 +
fs/nfs/nfs4/inode.c | 27 +++++++++++++++++++++++++++
4 files changed, 31 insertions(+), 23 deletions(-)
create mode 100644 fs/nfs/nfs4/inode.c
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 5335ce2..94d8631 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -14,7 +14,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4/proc.o nfs4/xdr.o nfs4/state.o nfs4/renewd.o \
nfs4/callback.o nfs4/callback_xdr.o \
nfs4/callback_proc.o nfs4/namespace.o \
nfs4/client.o nfs4/module.o nfs4/sysctl.o \
- nfs4/getroot.o
+ nfs4/getroot.o nfs4/inode.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 29673ac..a8d138b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -105,7 +105,7 @@ u64 nfs_compat_user_ino64(u64 fileid)
return ino;
}
-static void nfs_clear_inode(struct inode *inode)
+void nfs_clear_inode(struct inode *inode)
{
/*
* The following should never happen...
@@ -116,6 +116,7 @@ static void nfs_clear_inode(struct inode *inode)
nfs_access_zap_cache(inode);
nfs_fscache_release_inode_cookie(inode);
}
+EXPORT_SYMBOL_GPL(nfs_clear_inode);
void nfs_evict_inode(struct inode *inode)
{
@@ -1455,27 +1456,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
goto out_err;
}
-
-#ifdef CONFIG_NFS_V4
-
-/*
- * Clean out any remaining NFSv4 state that might be left over due
- * to open() calls that passed nfs_atomic_lookup, but failed to call
- * nfs_open().
- */
-void nfs4_evict_inode(struct inode *inode)
-{
- truncate_inode_pages(&inode->i_data, 0);
- end_writeback(inode);
- pnfs_return_layout(inode);
- pnfs_destroy_layout(NFS_I(inode));
- /* If we are holding a delegation, return it! */
- nfs_inode_return_delegation_noreclaim(inode);
- /* First call standard NFS clear_inode() code */
- nfs_clear_inode(inode);
-}
-#endif
-
struct inode *nfs_alloc_inode(struct super_block *sb)
{
struct nfs_inode *nfsi;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 5fee8ec..cff0f23 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -100,6 +100,7 @@ int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int nfs_have_delegation(struct inode *, fmode_t);
int nfs_have_delegated_attributes(struct inode *);
int nfs_inode_return_delegation(struct inode *);
+void nfs_clear_inode(struct inode *);
/* Exported in namespace.c */
struct vfsmount *nfs_d_automount(struct path *);
diff --git a/fs/nfs/nfs4/inode.c b/fs/nfs/nfs4/inode.c
new file mode 100644
index 0000000..65496c1
--- /dev/null
+++ b/fs/nfs/nfs4/inode.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include <linux/fs.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs.h>
+
+#include "delegation.h"
+#include "../nfs.h"
+#include "../pnfs.h"
+
+/*
+ * Clean out any remaining NFSv4 state that might be left over due
+ * to open() calls that passed nfs_atomic_lookup, but failed to call
+ * nfs_open().
+ */
+void nfs4_evict_inode(struct inode *inode)
+{
+ truncate_inode_pages(&inode->i_data, 0);
+ end_writeback(inode);
+ pnfs_return_layout(inode);
+ pnfs_destroy_layout(NFS_I(inode));
+ /* If we are holding a delegation, return it! */
+ nfs_inode_return_delegation_noreclaim(inode);
+ /* First call standard NFS clear_inode() code */
+ nfs_clear_inode(inode);
+}
--
1.7.8.3