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>
This commit is contained in:
parent
4e5ccf60c5
commit
f7b422b17e
16 changed files with 1993 additions and 1802 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_NFS_FS) += nfs.o
|
||||
|
||||
nfs-y := dir.o file.o inode.o nfs2xdr.o pagelist.o \
|
||||
nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \
|
||||
proc.o read.o symlink.o unlink.o write.o \
|
||||
namespace.o
|
||||
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
|
||||
|
@ -12,7 +12,8 @@ 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 \
|
||||
delegation.o idmap.o \
|
||||
callback.o callback_xdr.o callback_proc.o
|
||||
callback.o callback_xdr.o callback_proc.o \
|
||||
nfs4namespace.o
|
||||
nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
|
||||
nfs-$(CONFIG_SYSCTL) += sysctl.o
|
||||
nfs-objs := $(nfs-y)
|
||||
|
|
|
@ -182,8 +182,6 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
|
|||
/*
|
||||
* Define NFS4 callback program
|
||||
*/
|
||||
extern struct svc_version nfs4_callback_version1;
|
||||
|
||||
static struct svc_version *nfs4_callback_version[] = {
|
||||
[1] = &nfs4_callback_version1,
|
||||
};
|
||||
|
|
|
@ -892,7 +892,7 @@ out:
|
|||
* nfs_init_directcache - create a slab cache for nfs_direct_req structures
|
||||
*
|
||||
*/
|
||||
int nfs_init_directcache(void)
|
||||
int __init nfs_init_directcache(void)
|
||||
{
|
||||
nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
|
||||
sizeof(struct nfs_direct_req),
|
||||
|
@ -906,10 +906,10 @@ int nfs_init_directcache(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* nfs_init_directcache - destroy the slab cache for nfs_direct_req structures
|
||||
* nfs_destroy_directcache - destroy the slab cache for nfs_direct_req structures
|
||||
*
|
||||
*/
|
||||
void nfs_destroy_directcache(void)
|
||||
void __exit nfs_destroy_directcache(void)
|
||||
{
|
||||
if (kmem_cache_destroy(nfs_direct_cachep))
|
||||
printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n");
|
||||
|
|
1793
fs/nfs/inode.c
1793
fs/nfs/inode.c
File diff suppressed because it is too large
Load diff
179
fs/nfs/internal.h
Normal file
179
fs/nfs/internal.h
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* NFS internal definitions
|
||||
*/
|
||||
|
||||
#include <linux/mount.h>
|
||||
|
||||
struct nfs_clone_mount {
|
||||
const struct super_block *sb;
|
||||
const struct dentry *dentry;
|
||||
struct nfs_fh *fh;
|
||||
struct nfs_fattr *fattr;
|
||||
char *hostname;
|
||||
char *mnt_path;
|
||||
struct sockaddr_in *addr;
|
||||
rpc_authflavor_t authflavor;
|
||||
};
|
||||
|
||||
/* namespace-nfs4.c */
|
||||
#ifdef CONFIG_NFS_V4
|
||||
extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
|
||||
#else
|
||||
static inline
|
||||
struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
|
||||
{
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* callback_xdr.c */
|
||||
extern struct svc_version nfs4_callback_version1;
|
||||
|
||||
/* pagelist.c */
|
||||
extern int __init nfs_init_nfspagecache(void);
|
||||
extern void __exit nfs_destroy_nfspagecache(void);
|
||||
extern int __init nfs_init_readpagecache(void);
|
||||
extern void __exit nfs_destroy_readpagecache(void);
|
||||
extern int __init nfs_init_writepagecache(void);
|
||||
extern void __exit nfs_destroy_writepagecache(void);
|
||||
|
||||
#ifdef CONFIG_NFS_DIRECTIO
|
||||
extern int __init nfs_init_directcache(void);
|
||||
extern void __exit nfs_destroy_directcache(void);
|
||||
#else
|
||||
#define nfs_init_directcache() (0)
|
||||
#define nfs_destroy_directcache() do {} while(0)
|
||||
#endif
|
||||
|
||||
/* nfs2xdr.c */
|
||||
extern struct rpc_procinfo nfs_procedures[];
|
||||
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
|
||||
|
||||
/* nfs3xdr.c */
|
||||
extern struct rpc_procinfo nfs3_procedures[];
|
||||
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
|
||||
|
||||
/* nfs4xdr.c */
|
||||
extern int nfs_stat_to_errno(int);
|
||||
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
|
||||
|
||||
/* nfs4proc.c */
|
||||
extern struct rpc_procinfo nfs4_procedures[];
|
||||
|
||||
extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
|
||||
struct nfs4_fs_locations *fs_locations,
|
||||
struct page *page);
|
||||
|
||||
/* inode.c */
|
||||
extern struct inode *nfs_alloc_inode(struct super_block *sb);
|
||||
extern void nfs_destroy_inode(struct inode *);
|
||||
extern int nfs_write_inode(struct inode *,int);
|
||||
extern void nfs_clear_inode(struct inode *);
|
||||
#ifdef CONFIG_NFS_V4
|
||||
extern void nfs4_clear_inode(struct inode *);
|
||||
#endif
|
||||
|
||||
/* super.c */
|
||||
extern struct file_system_type nfs_referral_nfs4_fs_type;
|
||||
extern struct file_system_type clone_nfs_fs_type;
|
||||
#ifdef CONFIG_NFS_V4
|
||||
extern struct file_system_type clone_nfs4_fs_type;
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
extern struct rpc_stat nfs_rpcstat;
|
||||
#endif
|
||||
extern int __init register_nfs_fs(void);
|
||||
extern void __exit unregister_nfs_fs(void);
|
||||
|
||||
/* namespace.c */
|
||||
extern char *nfs_path(const char *base, const struct dentry *dentry,
|
||||
char *buffer, ssize_t buflen);
|
||||
|
||||
/*
|
||||
* Determine the mount path as a string
|
||||
*/
|
||||
static inline char *nfs4_path(const struct dentry *dentry, char *buffer, ssize_t buflen)
|
||||
{
|
||||
return nfs_path(NFS_SB(dentry->d_sb)->mnt_path, dentry, buffer, buflen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the device name as a string
|
||||
*/
|
||||
static inline char *nfs_devname(const struct vfsmount *mnt_parent,
|
||||
const struct dentry *dentry,
|
||||
char *buffer, ssize_t buflen)
|
||||
{
|
||||
return nfs_path(mnt_parent->mnt_devname, dentry, buffer, buflen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the actual block size (and log2 thereof)
|
||||
*/
|
||||
static inline
|
||||
unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
|
||||
{
|
||||
/* make sure blocksize is a power of two */
|
||||
if ((bsize & (bsize - 1)) || nrbitsp) {
|
||||
unsigned char nrbits;
|
||||
|
||||
for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
|
||||
;
|
||||
bsize = 1 << nrbits;
|
||||
if (nrbitsp)
|
||||
*nrbitsp = nrbits;
|
||||
}
|
||||
|
||||
return bsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of 512byte blocks used.
|
||||
*/
|
||||
static inline unsigned long nfs_calc_block_size(u64 tsize)
|
||||
{
|
||||
loff_t used = (tsize + 511) >> 9;
|
||||
return (used > ULONG_MAX) ? ULONG_MAX : used;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute and set NFS server blocksize
|
||||
*/
|
||||
static inline
|
||||
unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
|
||||
{
|
||||
if (bsize < NFS_MIN_FILE_IO_SIZE)
|
||||
bsize = NFS_DEF_FILE_IO_SIZE;
|
||||
else if (bsize >= NFS_MAX_FILE_IO_SIZE)
|
||||
bsize = NFS_MAX_FILE_IO_SIZE;
|
||||
|
||||
return nfs_block_bits(bsize, nrbitsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the maximum file size for a superblock
|
||||
*/
|
||||
static inline
|
||||
void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
|
||||
{
|
||||
sb->s_maxbytes = (loff_t)maxfilesize;
|
||||
if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
|
||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the string represents a "valid" IPv4 address
|
||||
*/
|
||||
static inline int valid_ipaddr4(const char *buf)
|
||||
{
|
||||
int rc, count, in[4];
|
||||
|
||||
rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
|
||||
if (rc != 4)
|
||||
return -EINVAL;
|
||||
for (count = 0; count < 4; count++) {
|
||||
if (in[count] > 255)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -15,14 +15,63 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include <linux/vfs.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||
|
||||
LIST_HEAD(nfs_automount_list);
|
||||
static void nfs_expire_automounts(void *list);
|
||||
|
||||
LIST_HEAD(nfs_automount_list);
|
||||
static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
|
||||
int nfs_mountpoint_expiry_timeout = 500 * HZ;
|
||||
|
||||
/*
|
||||
* nfs_path - reconstruct the path given an arbitrary dentry
|
||||
* @base - arbitrary string to prepend to the path
|
||||
* @dentry - pointer to dentry
|
||||
* @buffer - result buffer
|
||||
* @buflen - length of buffer
|
||||
*
|
||||
* Helper function for constructing the path from the
|
||||
* root dentry to an arbitrary hashed dentry.
|
||||
*
|
||||
* This is mainly for use in figuring out the path on the
|
||||
* server side when automounting on top of an existing partition.
|
||||
*/
|
||||
char *nfs_path(const char *base, const struct dentry *dentry,
|
||||
char *buffer, ssize_t buflen)
|
||||
{
|
||||
char *end = buffer+buflen;
|
||||
int namelen;
|
||||
|
||||
*--end = '\0';
|
||||
buflen--;
|
||||
spin_lock(&dcache_lock);
|
||||
while (!IS_ROOT(dentry)) {
|
||||
namelen = dentry->d_name.len;
|
||||
buflen -= namelen + 1;
|
||||
if (buflen < 0)
|
||||
goto Elong;
|
||||
end -= namelen;
|
||||
memcpy(end, dentry->d_name.name, namelen);
|
||||
*--end = '/';
|
||||
dentry = dentry->d_parent;
|
||||
}
|
||||
spin_unlock(&dcache_lock);
|
||||
namelen = strlen(base);
|
||||
/* Strip off excess slashes in base string */
|
||||
while (namelen > 0 && base[namelen - 1] == '/')
|
||||
namelen--;
|
||||
buflen -= namelen;
|
||||
if (buflen < 0)
|
||||
goto Elong;
|
||||
end -= namelen;
|
||||
memcpy(end, base, namelen);
|
||||
return end;
|
||||
Elong:
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs_follow_mountpoint - handle crossing a mountpoint on the server
|
||||
* @dentry - dentry of mountpoint
|
||||
|
@ -117,3 +166,64 @@ void nfs_release_automount_timer(void)
|
|||
flush_scheduled_work();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clone a mountpoint of the appropriate type
|
||||
*/
|
||||
static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname,
|
||||
struct nfs_clone_mount *mountdata)
|
||||
{
|
||||
#ifdef CONFIG_NFS_V4
|
||||
struct vfsmount *mnt = NULL;
|
||||
switch (server->rpc_ops->version) {
|
||||
case 2:
|
||||
case 3:
|
||||
mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
|
||||
break;
|
||||
case 4:
|
||||
mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata);
|
||||
}
|
||||
return mnt;
|
||||
#else
|
||||
return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_do_submount - set up mountpoint when crossing a filesystem boundary
|
||||
* @mnt_parent - mountpoint of parent directory
|
||||
* @dentry - parent directory
|
||||
* @fh - filehandle for new root dentry
|
||||
* @fattr - attributes for new root inode
|
||||
*
|
||||
*/
|
||||
struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
|
||||
const struct dentry *dentry, struct nfs_fh *fh,
|
||||
struct nfs_fattr *fattr)
|
||||
{
|
||||
struct nfs_clone_mount mountdata = {
|
||||
.sb = mnt_parent->mnt_sb,
|
||||
.dentry = dentry,
|
||||
.fh = fh,
|
||||
.fattr = fattr,
|
||||
};
|
||||
struct vfsmount *mnt = ERR_PTR(-ENOMEM);
|
||||
char *page = (char *) __get_free_page(GFP_USER);
|
||||
char *devname;
|
||||
|
||||
dprintk("%s: submounting on %s/%s\n", __FUNCTION__,
|
||||
dentry->d_parent->d_name.name,
|
||||
dentry->d_name.name);
|
||||
if (page == NULL)
|
||||
goto out;
|
||||
devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
|
||||
mnt = (struct vfsmount *)devname;
|
||||
if (IS_ERR(devname))
|
||||
goto free_page;
|
||||
mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
|
||||
free_page:
|
||||
free_page((unsigned long)page);
|
||||
out:
|
||||
dprintk("%s: done\n", __FUNCTION__);
|
||||
return mnt;
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#define NFSDBG_FACILITY NFSDBG_XDR
|
||||
/* #define NFS_PARANOIA 1 */
|
||||
|
||||
extern int nfs_stat_to_errno(int stat);
|
||||
|
||||
/* Mapping from NFS error code to "errno" error code. */
|
||||
#define errno_NFSERR_IO EIO
|
||||
|
||||
|
|
|
@ -20,11 +20,10 @@
|
|||
#include <linux/nfs_mount.h>
|
||||
|
||||
#include "iostat.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PROC
|
||||
|
||||
extern struct rpc_procinfo nfs3_procedures[];
|
||||
|
||||
/* A wrapper to handle the EJUKEBOX error message */
|
||||
static int
|
||||
nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
|
||||
|
@ -809,8 +808,6 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
|
|||
return status;
|
||||
}
|
||||
|
||||
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
|
||||
|
||||
static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
|
||||
{
|
||||
if (nfs3_async_handle_jukebox(task, data->inode))
|
||||
|
|
|
@ -22,14 +22,13 @@
|
|||
#include <linux/nfs3.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/nfsacl.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_XDR
|
||||
|
||||
/* Mapping from NFS error code to "errno" error code. */
|
||||
#define errno_NFSERR_IO EIO
|
||||
|
||||
extern int nfs_stat_to_errno(int);
|
||||
|
||||
/*
|
||||
* Declare the space requirements for NFS arguments and replies as
|
||||
* number of 32bit-words
|
||||
|
|
201
fs/nfs/nfs4namespace.c
Normal file
201
fs/nfs/nfs4namespace.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* linux/fs/nfs/nfs4namespace.c
|
||||
*
|
||||
* Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
|
||||
*
|
||||
* NFSv4 namespace
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/inet.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||
|
||||
/*
|
||||
* Check if fs_root is valid
|
||||
*/
|
||||
static inline char *nfs4_pathname_string(struct nfs4_pathname *pathname,
|
||||
char *buffer, ssize_t buflen)
|
||||
{
|
||||
char *end = buffer + buflen;
|
||||
int n;
|
||||
|
||||
*--end = '\0';
|
||||
buflen--;
|
||||
|
||||
n = pathname->ncomponents;
|
||||
while (--n >= 0) {
|
||||
struct nfs4_string *component = &pathname->components[n];
|
||||
buflen -= component->len + 1;
|
||||
if (buflen < 0)
|
||||
goto Elong;
|
||||
end -= component->len;
|
||||
memcpy(end, component->data, component->len);
|
||||
*--end = '/';
|
||||
}
|
||||
return end;
|
||||
Elong:
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nfs_follow_referral - set up mountpoint when hitting a referral on moved error
|
||||
* @mnt_parent - mountpoint of parent directory
|
||||
* @dentry - parent directory
|
||||
* @fspath - fs path returned in fs_locations
|
||||
* @mntpath - mount path to new server
|
||||
* @hostname - hostname of new server
|
||||
* @addr - host addr of new server
|
||||
*
|
||||
*/
|
||||
static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
|
||||
const struct dentry *dentry,
|
||||
struct nfs4_fs_locations *locations)
|
||||
{
|
||||
struct vfsmount *mnt = ERR_PTR(-ENOENT);
|
||||
struct nfs_clone_mount mountdata = {
|
||||
.sb = mnt_parent->mnt_sb,
|
||||
.dentry = dentry,
|
||||
.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
|
||||
};
|
||||
char *page, *page2;
|
||||
char *path, *fs_path;
|
||||
char *devname;
|
||||
int loc, s;
|
||||
|
||||
if (locations == NULL || locations->nlocations <= 0)
|
||||
goto out;
|
||||
|
||||
dprintk("%s: referral at %s/%s\n", __FUNCTION__,
|
||||
dentry->d_parent->d_name.name, dentry->d_name.name);
|
||||
|
||||
/* Ensure fs path is a prefix of current dentry path */
|
||||
page = (char *) __get_free_page(GFP_USER);
|
||||
if (page == NULL)
|
||||
goto out;
|
||||
page2 = (char *) __get_free_page(GFP_USER);
|
||||
if (page2 == NULL)
|
||||
goto out;
|
||||
|
||||
path = nfs4_path(dentry, page, PAGE_SIZE);
|
||||
if (IS_ERR(path))
|
||||
goto out_free;
|
||||
|
||||
fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE);
|
||||
if (IS_ERR(fs_path))
|
||||
goto out_free;
|
||||
|
||||
if (strncmp(path, fs_path, strlen(fs_path)) != 0) {
|
||||
dprintk("%s: path %s does not begin with fsroot %s\n", __FUNCTION__, path, fs_path);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
|
||||
if (IS_ERR(devname)) {
|
||||
mnt = (struct vfsmount *)devname;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
loc = 0;
|
||||
while (loc < locations->nlocations && IS_ERR(mnt)) {
|
||||
struct nfs4_fs_location *location = &locations->locations[loc];
|
||||
char *mnt_path;
|
||||
|
||||
if (location == NULL || location->nservers <= 0 ||
|
||||
location->rootpath.ncomponents == 0) {
|
||||
loc++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
|
||||
if (IS_ERR(mnt_path)) {
|
||||
loc++;
|
||||
continue;
|
||||
}
|
||||
mountdata.mnt_path = mnt_path;
|
||||
|
||||
s = 0;
|
||||
while (s < location->nservers) {
|
||||
struct sockaddr_in addr = {};
|
||||
|
||||
if (location->servers[s].len <= 0 ||
|
||||
valid_ipaddr4(location->servers[s].data) < 0) {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mountdata.hostname = location->servers[s].data;
|
||||
addr.sin_addr.s_addr = in_aton(mountdata.hostname);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(NFS_PORT);
|
||||
mountdata.addr = &addr;
|
||||
|
||||
mnt = vfs_kern_mount(&nfs_referral_nfs4_fs_type, 0, devname, &mountdata);
|
||||
if (!IS_ERR(mnt)) {
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
loc++;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free_page((unsigned long)page);
|
||||
free_page((unsigned long)page2);
|
||||
out:
|
||||
dprintk("%s: done\n", __FUNCTION__);
|
||||
return mnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs_do_refmount - handle crossing a referral on server
|
||||
* @dentry - dentry of referral
|
||||
* @nd - nameidata info
|
||||
*
|
||||
*/
|
||||
struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
|
||||
{
|
||||
struct vfsmount *mnt = ERR_PTR(-ENOENT);
|
||||
struct dentry *parent;
|
||||
struct nfs4_fs_locations *fs_locations = NULL;
|
||||
struct page *page;
|
||||
int err;
|
||||
|
||||
/* BUG_ON(IS_ROOT(dentry)); */
|
||||
dprintk("%s: enter\n", __FUNCTION__);
|
||||
|
||||
page = alloc_page(GFP_KERNEL);
|
||||
if (page == NULL)
|
||||
goto out;
|
||||
|
||||
fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
|
||||
if (fs_locations == NULL)
|
||||
goto out_free;
|
||||
|
||||
/* Get locations */
|
||||
parent = dget_parent(dentry);
|
||||
dprintk("%s: getting locations for %s/%s\n", __FUNCTION__, parent->d_name.name, dentry->d_name.name);
|
||||
err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page);
|
||||
dput(parent);
|
||||
if (err != 0 || fs_locations->nlocations <= 0 ||
|
||||
fs_locations->fs_path.ncomponents <= 0)
|
||||
goto out_free;
|
||||
|
||||
mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations);
|
||||
out_free:
|
||||
__free_page(page);
|
||||
kfree(fs_locations);
|
||||
out:
|
||||
dprintk("%s: done\n", __FUNCTION__);
|
||||
return mnt;
|
||||
}
|
|
@ -65,8 +65,6 @@ static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *)
|
|||
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
|
||||
static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
|
||||
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp);
|
||||
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
|
||||
extern struct rpc_procinfo nfs4_procedures[];
|
||||
|
||||
/* Prevent leaks of NFSv4 errors into userland */
|
||||
int nfs4_map_errors(int err)
|
||||
|
|
|
@ -378,7 +378,7 @@ out:
|
|||
return res;
|
||||
}
|
||||
|
||||
int nfs_init_nfspagecache(void)
|
||||
int __init nfs_init_nfspagecache(void)
|
||||
{
|
||||
nfs_page_cachep = kmem_cache_create("nfs_page",
|
||||
sizeof(struct nfs_page),
|
||||
|
@ -390,7 +390,7 @@ int nfs_init_nfspagecache(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nfs_destroy_nfspagecache(void)
|
||||
void __exit nfs_destroy_nfspagecache(void)
|
||||
{
|
||||
if (kmem_cache_destroy(nfs_page_cachep))
|
||||
printk(KERN_INFO "nfs_page: not all structures were freed\n");
|
||||
|
|
|
@ -44,11 +44,10 @@
|
|||
#include <linux/nfs_page.h>
|
||||
#include <linux/lockd/bind.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PROC
|
||||
|
||||
extern struct rpc_procinfo nfs_procedures[];
|
||||
|
||||
/*
|
||||
* Bare-bones access to getattr: this is for nfs_read_super.
|
||||
*/
|
||||
|
@ -611,8 +610,6 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
|
||||
|
||||
static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
|
||||
{
|
||||
if (task->tk_status >= 0) {
|
||||
|
|
|
@ -694,7 +694,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int nfs_init_readpagecache(void)
|
||||
int __init nfs_init_readpagecache(void)
|
||||
{
|
||||
nfs_rdata_cachep = kmem_cache_create("nfs_read_data",
|
||||
sizeof(struct nfs_read_data),
|
||||
|
@ -711,7 +711,7 @@ int nfs_init_readpagecache(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nfs_destroy_readpagecache(void)
|
||||
void __exit nfs_destroy_readpagecache(void)
|
||||
{
|
||||
mempool_destroy(nfs_rdata_mempool);
|
||||
if (kmem_cache_destroy(nfs_rdata_cachep))
|
||||
|
|
1468
fs/nfs/super.c
Normal file
1468
fs/nfs/super.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1529,7 +1529,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int nfs_init_writepagecache(void)
|
||||
int __init nfs_init_writepagecache(void)
|
||||
{
|
||||
nfs_wdata_cachep = kmem_cache_create("nfs_write_data",
|
||||
sizeof(struct nfs_write_data),
|
||||
|
@ -1551,7 +1551,7 @@ int nfs_init_writepagecache(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nfs_destroy_writepagecache(void)
|
||||
void __exit nfs_destroy_writepagecache(void)
|
||||
{
|
||||
mempool_destroy(nfs_commit_mempool);
|
||||
mempool_destroy(nfs_wdata_mempool);
|
||||
|
|
Loading…
Reference in a new issue