aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/namespace.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-09 09:34:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-09 09:34:33 -0400
commitf7b422b17ee5ee4920e8ae24a6ad04bf3481ce72 (patch)
tree4ae8372762efc092ceb4f884b57cad1efe6594de /fs/nfs/namespace.c
parent4e5ccf60c5aa79d325c123f47d288a068166f389 (diff)
NFS: Split fs/nfs/inode.c
As fs/nfs/inode.c is rather large, heterogenous and unwieldy, the attached patch splits it up into a number of files: (*) fs/nfs/inode.c Strictly inode specific functions. (*) fs/nfs/super.c Superblock management functions for NFS and NFS4, normal access, clones and referrals. The NFS4 superblock functions _could_ move out into a separate conditionally compiled file, but it's probably not worth it as there're so many common bits. (*) fs/nfs/namespace.c Some namespace-specific functions have been moved here. (*) fs/nfs/nfs4namespace.c NFS4-specific namespace functions (this could be merged into the previous file). This file is conditionally compiled. (*) fs/nfs/internal.h Inter-file declarations, plus a few simple utility functions moved from fs/nfs/inode.c. Additionally, all the in-.c-file externs have been moved here, and those files they were moved from now includes this file. For the most part, the functions have not been changed, only some multiplexor functions have changed significantly. I've also: (*) Added some extra banner comments above some functions. (*) Rearranged the function order within the files to be more logical and better grouped (IMO), though someone may prefer a different order. (*) Reduced the number of #ifdefs in .c files. (*) Added missing __init and __exit directives. Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/nfs/namespace.c')
-rw-r--r--fs/nfs/namespace.c112
1 files changed, 111 insertions, 1 deletions
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 8ca44b7b25c3..19b98ca468eb 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -15,15 +15,64 @@
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/sunrpc/clnt.h> 16#include <linux/sunrpc/clnt.h>
17#include <linux/vfs.h> 17#include <linux/vfs.h>
18#include "internal.h"
18 19
19#define NFSDBG_FACILITY NFSDBG_VFS 20#define NFSDBG_FACILITY NFSDBG_VFS
20 21
21LIST_HEAD(nfs_automount_list);
22static void nfs_expire_automounts(void *list); 22static void nfs_expire_automounts(void *list);
23
24LIST_HEAD(nfs_automount_list);
23static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list); 25static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
24int nfs_mountpoint_expiry_timeout = 500 * HZ; 26int nfs_mountpoint_expiry_timeout = 500 * HZ;
25 27
26/* 28/*
29 * nfs_path - reconstruct the path given an arbitrary dentry
30 * @base - arbitrary string to prepend to the path
31 * @dentry - pointer to dentry
32 * @buffer - result buffer
33 * @buflen - length of buffer
34 *
35 * Helper function for constructing the path from the
36 * root dentry to an arbitrary hashed dentry.
37 *
38 * This is mainly for use in figuring out the path on the
39 * server side when automounting on top of an existing partition.
40 */
41char *nfs_path(const char *base, const struct dentry *dentry,
42 char *buffer, ssize_t buflen)
43{
44 char *end = buffer+buflen;
45 int namelen;
46
47 *--end = '\0';
48 buflen--;
49 spin_lock(&dcache_lock);
50 while (!IS_ROOT(dentry)) {
51 namelen = dentry->d_name.len;
52 buflen -= namelen + 1;
53 if (buflen < 0)
54 goto Elong;
55 end -= namelen;
56 memcpy(end, dentry->d_name.name, namelen);
57 *--end = '/';
58 dentry = dentry->d_parent;
59 }
60 spin_unlock(&dcache_lock);
61 namelen = strlen(base);
62 /* Strip off excess slashes in base string */
63 while (namelen > 0 && base[namelen - 1] == '/')
64 namelen--;
65 buflen -= namelen;
66 if (buflen < 0)
67 goto Elong;
68 end -= namelen;
69 memcpy(end, base, namelen);
70 return end;
71Elong:
72 return ERR_PTR(-ENAMETOOLONG);
73}
74
75/*
27 * nfs_follow_mountpoint - handle crossing a mountpoint on the server 76 * nfs_follow_mountpoint - handle crossing a mountpoint on the server
28 * @dentry - dentry of mountpoint 77 * @dentry - dentry of mountpoint
29 * @nd - nameidata info 78 * @nd - nameidata info
@@ -117,3 +166,64 @@ void nfs_release_automount_timer(void)
117 flush_scheduled_work(); 166 flush_scheduled_work();
118 } 167 }
119} 168}
169
170/*
171 * Clone a mountpoint of the appropriate type
172 */
173static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname,
174 struct nfs_clone_mount *mountdata)
175{
176#ifdef CONFIG_NFS_V4
177 struct vfsmount *mnt = NULL;
178 switch (server->rpc_ops->version) {
179 case 2:
180 case 3:
181 mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
182 break;
183 case 4:
184 mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata);
185 }
186 return mnt;
187#else
188 return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
189#endif
190}
191
192/**
193 * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
194 * @mnt_parent - mountpoint of parent directory
195 * @dentry - parent directory
196 * @fh - filehandle for new root dentry
197 * @fattr - attributes for new root inode
198 *
199 */
200struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
201 const struct dentry *dentry, struct nfs_fh *fh,
202 struct nfs_fattr *fattr)
203{
204 struct nfs_clone_mount mountdata = {
205 .sb = mnt_parent->mnt_sb,
206 .dentry = dentry,
207 .fh = fh,
208 .fattr = fattr,
209 };
210 struct vfsmount *mnt = ERR_PTR(-ENOMEM);
211 char *page = (char *) __get_free_page(GFP_USER);
212 char *devname;
213
214 dprintk("%s: submounting on %s/%s\n", __FUNCTION__,
215 dentry->d_parent->d_name.name,
216 dentry->d_name.name);
217 if (page == NULL)
218 goto out;
219 devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
220 mnt = (struct vfsmount *)devname;
221 if (IS_ERR(devname))
222 goto free_page;
223 mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
224free_page:
225 free_page((unsigned long)page);
226out:
227 dprintk("%s: done\n", __FUNCTION__);
228 return mnt;
229}