Merge tag 'nfs-for-3.6-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull second wave of NFS client updates from Trond Myklebust:

 - Patches from Bryan to allow splitting of the NFSv2/v3/v4 code into
   separate modules.

 - Fix Oopses in the NFSv4 idmapper

 - Fix a deadlock whereby rpciod tries to allocate a new socket and ends
   up recursing into the NFS code due to memory reclaim.

 - Increase the number of permitted callback connections.

* tag 'nfs-for-3.6-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: explicitly reject LOCK_MAND flock() requests
  nfs: increase number of permitted callback connections.
  SUNRPC: return negative value in case rpcbind client creation error
  NFS: Convert v4 into a module
  NFS: Convert v3 into a module
  NFS: Convert v2 into a module
  NFS: Keep module parameters in the generic NFS client
  NFS: Split out remaining NFS v4 inode functions
  NFS: Pass super operations and xattr handlers in the nfs_subversion
  NFS: Only initialize the ACL client in the v3 case
  NFS: Create a try_mount rpc op
  NFS: Remove the NFS v4 xdev mount function
  NFS: Add version registering framework
  NFS: Fix a number of bugs in the idmapper
  nfs: skip commit in releasepage if we're freeing memory for fs-related reasons
  sunrpc: clarify comments on rpc_make_runnable
  pnfsblock: bail out partial page IO
This commit is contained in:
Linus Torvalds
2012-07-31 18:45:44 -07:00
40 changed files with 728 additions and 406 deletions
+3 -3
View File
@@ -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
default y
help
@@ -40,7 +40,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
default y
help
@@ -72,7 +72,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
select KEYS
+15 -14
View File
@@ -9,22 +9,23 @@ 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_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o nfs4file.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o nfs4getroot.o nfs4client.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
ifeq ($(CONFIG_SYSCTL), y)
nfs-y += sysctl.o
nfs-$(CONFIG_NFS_V4) += nfs4sysctl.o
endif
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
obj-$(CONFIG_NFS_V2) += nfs2.o
nfs2-y := nfs2super.o proc.o nfs2xdr.o
obj-$(CONFIG_NFS_V3) += nfs3.o
nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o
nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
obj-$(CONFIG_NFS_V4) += nfs4.o
nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \
delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o nfs4getroot.o nfs4client.o
nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o
nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
+36 -3
View File
@@ -228,6 +228,14 @@ bl_end_par_io_read(void *data, int unused)
schedule_work(&rdata->task.u.tk_work);
}
static bool
bl_check_alignment(u64 offset, u32 len, unsigned long blkmask)
{
if ((offset & blkmask) || (len & blkmask))
return false;
return true;
}
static enum pnfs_try_status
bl_read_pagelist(struct nfs_read_data *rdata)
{
@@ -244,6 +252,9 @@ bl_read_pagelist(struct nfs_read_data *rdata)
dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__,
rdata->pages.npages, f_offset, (unsigned int)rdata->args.count);
if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK))
goto use_mds;
par = alloc_parallel(rdata);
if (!par)
goto use_mds;
@@ -552,7 +563,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
struct bio *bio = NULL;
struct pnfs_block_extent *be = NULL, *cow_read = NULL;
sector_t isect, last_isect = 0, extent_length = 0;
struct parallel_io *par;
struct parallel_io *par = NULL;
loff_t offset = wdata->args.offset;
size_t count = wdata->args.count;
struct page **pages = wdata->args.pages;
@@ -563,6 +574,10 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
/* Check for alignment first */
if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK))
goto out_mds;
/* At this point, wdata->pages is a (sequential) list of nfs_pages.
* We want to write each, and if there is an error set pnfs_error
* to have it redone using nfs.
@@ -996,14 +1011,32 @@ bl_clear_layoutdriver(struct nfs_server *server)
return 0;
}
static void
bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{
if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
nfs_pageio_reset_read_mds(pgio);
else
pnfs_generic_pg_init_read(pgio, req);
}
static void
bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{
if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
nfs_pageio_reset_write_mds(pgio);
else
pnfs_generic_pg_init_write(pgio, req);
}
static const struct nfs_pageio_ops bl_pg_read_ops = {
.pg_init = pnfs_generic_pg_init_read,
.pg_init = bl_pg_init_read,
.pg_test = pnfs_generic_pg_test,
.pg_doio = pnfs_generic_pg_readpages,
};
static const struct nfs_pageio_ops bl_pg_write_ops = {
.pg_init = pnfs_generic_pg_init_write,
.pg_init = bl_pg_init_write,
.pg_test = pnfs_generic_pg_test,
.pg_doio = pnfs_generic_pg_writepages,
};
+4 -24
View File
@@ -37,31 +37,7 @@ static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
static DEFINE_MUTEX(nfs_callback_mutex);
static struct svc_program nfs4_callback_program;
unsigned int nfs_callback_set_tcpport;
unsigned short nfs_callback_tcpport;
unsigned short nfs_callback_tcpport6;
#define NFS_CALLBACK_MAXPORTNR (65535U)
static int param_set_portnr(const char *val, const struct kernel_param *kp)
{
unsigned long num;
int ret;
if (!val)
return -EINVAL;
ret = strict_strtoul(val, 0, &num);
if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
return -EINVAL;
*((unsigned int *)kp->arg) = num;
return 0;
}
static struct kernel_param_ops param_ops_portnr = {
.set = param_set_portnr,
.get = param_get_uint,
};
#define param_check_portnr(name, p) __param_check(name, p, unsigned int);
module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
/*
* This is the NFSv4 callback kernel thread.
@@ -265,6 +241,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
ret = -ENOMEM;
goto out_err;
}
/* As there is only one thread we need to over-ride the
* default maximum of 80 connections
*/
serv->sv_maxconn = 1024;
ret = svc_bind(serv, net);
if (ret < 0) {
+1 -1
View File
@@ -192,7 +192,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,
+103 -88
View File
@@ -51,25 +51,23 @@
#include "internal.h"
#include "fscache.h"
#include "pnfs.h"
#include "nfs.h"
#include "netns.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
static DEFINE_SPINLOCK(nfs_version_lock);
static DEFINE_MUTEX(nfs_version_mutex);
static LIST_HEAD(nfs_versions);
/*
* RPC cruft for NFS
*/
static const 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,
};
const struct rpc_program nfs_program = {
@@ -85,21 +83,64 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};
static struct nfs_subversion *find_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs;
spin_lock(&nfs_version_lock);
#ifdef CONFIG_NFS_V3_ACL
static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
static const struct rpc_version *nfsacl_version[] = {
[3] = &nfsacl_version3,
};
list_for_each_entry(nfs, &nfs_versions, list) {
if (nfs->rpc_ops->version == version) {
spin_unlock(&nfs_version_lock);
return nfs;
}
};
const 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 */
spin_unlock(&nfs_version_lock);
return ERR_PTR(-EPROTONOSUPPORT);;
}
struct nfs_subversion *get_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs = find_nfs_version(version);
if (IS_ERR(nfs)) {
mutex_lock(&nfs_version_mutex);
request_module("nfs%d", version);
nfs = find_nfs_version(version);
mutex_unlock(&nfs_version_mutex);
}
if (!IS_ERR(nfs))
try_module_get(nfs->owner);
return nfs;
}
void put_nfs_version(struct nfs_subversion *nfs)
{
module_put(nfs->owner);
}
void register_nfs_version(struct nfs_subversion *nfs)
{
spin_lock(&nfs_version_lock);
list_add(&nfs->list, &nfs_versions);
nfs_version[nfs->rpc_ops->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->rpc_ops->version] = NULL;
list_del(&nfs->list);
spin_unlock(&nfs_version_lock);
}
EXPORT_SYMBOL_GPL(unregister_nfs_version);
/*
* Allocate a shared client record
@@ -116,7 +157,10 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
goto error_0;
clp->rpc_ops = cl_init->rpc_ops;
clp->cl_nfs_mod = cl_init->nfs_mod;
try_module_get(clp->cl_nfs_mod->owner);
clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
@@ -145,12 +189,14 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
return clp;
error_cleanup:
put_nfs_version(clp->cl_nfs_mod);
kfree(clp);
error_0:
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(nfs_alloc_client);
#ifdef CONFIG_NFS_V4
#if IS_ENABLED(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(struct net *net)
{
@@ -205,11 +251,13 @@ void nfs_free_client(struct nfs_client *clp)
put_rpccred(clp->cl_machine_cred);
put_net(clp->cl_net);
put_nfs_version(clp->cl_nfs_mod);
kfree(clp->cl_hostname);
kfree(clp);
dprintk("<-- nfs_free_client()\n");
}
EXPORT_SYMBOL_GPL(nfs_free_client);
/*
* Release a reference to a shared client record
@@ -324,6 +372,7 @@ int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
}
return 0;
}
EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr);
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -362,7 +411,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
continue;
/* Different NFS versions cannot share the same nfs_client */
if (clp->rpc_ops != data->rpc_ops)
if (clp->rpc_ops != data->nfs_mod->rpc_ops)
continue;
if (clp->cl_proto != data->proto)
@@ -390,6 +439,7 @@ int nfs_wait_client_init_complete(const struct nfs_client *clp)
return wait_event_killable(nfs_client_active_wq,
nfs_client_init_is_complete(clp));
}
EXPORT_SYMBOL_GPL(nfs_wait_client_init_complete);
/*
* Found an existing client. Make sure it's ready before returning.
@@ -431,9 +481,10 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
{
struct nfs_client *clp, *new = NULL;
struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
dprintk("--> nfs_get_client(%s,v%u)\n",
cl_init->hostname ?: "", cl_init->rpc_ops->version);
cl_init->hostname ?: "", rpc_ops->version);
/* see if the client already exists */
do {
@@ -450,20 +501,20 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
list_add(&new->cl_share_link, &nn->nfs_client_list);
spin_unlock(&nn->nfs_client_lock);
new->cl_flags = cl_init->init_flags;
return cl_init->rpc_ops->init_client(new,
timeparms, ip_addr,
authflavour);
return rpc_ops->init_client(new, timeparms, ip_addr,
authflavour);
}
spin_unlock(&nn->nfs_client_lock);
new = cl_init->rpc_ops->alloc_client(cl_init);
new = rpc_ops->alloc_client(cl_init);
} while (!IS_ERR(new));
dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
cl_init->hostname ?: "", PTR_ERR(new));
return new;
}
EXPORT_SYMBOL_GPL(nfs_get_client);
/*
* Mark a server as ready or failed
@@ -474,6 +525,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);
/*
* Initialise the timeout values for a connection
@@ -515,6 +567,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
BUG();
}
}
EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
/*
* Create an RPC client handle
@@ -554,6 +607,7 @@ 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
@@ -605,36 +659,6 @@ static int nfs_start_lockd(struct nfs_server *server)
return 0;
}
/*
* Initialise an NFSv3 ACL client connection
*/
#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;
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
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
*/
@@ -670,6 +694,7 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
return 0;
}
EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
/**
* nfs_init_client - Initialise an NFS2 or NFS3 client
@@ -709,18 +734,20 @@ error:
dprintk("<-- nfs_init_client() = xerror %d\n", error);
return ERR_PTR(error);
}
EXPORT_SYMBOL_GPL(nfs_init_client);
/*
* Create a version 2 or 3 client
*/
static int nfs_init_server(struct nfs_server *server,
const struct nfs_parsed_mount_data *data)
const struct nfs_parsed_mount_data *data,
struct nfs_subversion *nfs_mod)
{
struct nfs_client_initdata cl_init = {
.hostname = data->nfs_server.hostname,
.addr = (const struct sockaddr *)&data->nfs_server.address,
.addrlen = data->nfs_server.addrlen,
.rpc_ops = NULL,
.nfs_mod = nfs_mod,
.proto = data->nfs_server.protocol,
.net = data->net,
};
@@ -730,21 +757,6 @@ static int nfs_init_server(struct nfs_server *server,
dprintk("--> nfs_init_server()\n");
switch (data->version) {
#ifdef CONFIG_NFS_V2
case 2:
cl_init.rpc_ops = &nfs_v2_clientops;
break;
#endif
#ifdef CONFIG_NFS_V3
case 3:
cl_init.rpc_ops = &nfs_v3_clientops;
break;
#endif
default:
return -EPROTONOSUPPORT;
}
nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans);
if (data->flags & NFS_MOUNT_NORESVPORT)
@@ -798,8 +810,6 @@ static int nfs_init_server(struct nfs_server *server,
server->mountd_protocol = data->mount_server.protocol;
server->namelen = data->namlen;
/* Create a client RPC handle for the NFSv3 ACL management interface */
nfs_init_server_aclclient(server);
dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
return 0;
@@ -911,6 +921,7 @@ 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
@@ -927,6 +938,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour
target->caps = source->caps;
target->options = source->options;
}
EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
void nfs_server_insert_lists(struct nfs_server *server)
{
@@ -940,6 +952,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
spin_unlock(&nn->nfs_client_lock);
}
EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
static void nfs_server_remove_lists(struct nfs_server *server)
{
@@ -999,6 +1012,7 @@ struct nfs_server *nfs_alloc_server(void)
return server;
}
EXPORT_SYMBOL_GPL(nfs_alloc_server);
/*
* Free up a server record
@@ -1027,13 +1041,14 @@ 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
* - keyed on server and FSID
*/
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)
struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{
struct nfs_server *server;
struct nfs_fattr *fattr;
@@ -1049,7 +1064,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
goto error;
/* Get a client representation */
error = nfs_init_server(server, data);
error = nfs_init_server(server, mount_info->parsed, nfs_mod);
if (error < 0)
goto error;
@@ -1058,13 +1073,13 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
/* Probe the root fh to retrieve its FSID */
error = nfs_probe_fsinfo(server, mntfh, fattr);
error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr);
if (error < 0)
goto error;
if (server->nfs_client->rpc_ops->version == 3) {
if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
server->namelen = NFS3_MAXNAMLEN;
if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
if (!(mount_info->parsed->flags & NFS_MOUNT_NORDIRPLUS))
server->caps |= NFS_CAP_READDIRPLUS;
} else {
if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
@@ -1072,7 +1087,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
}
if (!(fattr->valid & NFS_ATTR_FATTR)) {
error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr);
if (error < 0) {
dprintk("nfs_create_server: getattr error = %d\n", -error);
goto error;
@@ -1094,6 +1109,7 @@ error:
nfs_free_server(server);
return ERR_PTR(error);
}
EXPORT_SYMBOL_GPL(nfs_create_server);
/*
* Clone an NFS2, NFS3 or NFS4 server record
@@ -1133,8 +1149,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
flavor);
if (error < 0)
goto out_free_server;
if (!IS_ERR(source->client_acl))
nfs_init_server_aclclient(server);
/* probe the filesystem info for this server filesystem */
error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
@@ -1165,6 +1179,7 @@ out_free_server:
dprintk("<-- nfs_clone_server() = error %d\n", error);
return ERR_PTR(error);
}
EXPORT_SYMBOL_GPL(nfs_clone_server);
void nfs_clients_init(struct net *net)
{
@@ -1172,7 +1187,7 @@ void nfs_clients_init(struct net *net)
INIT_LIST_HEAD(&nn->nfs_client_list);
INIT_LIST_HEAD(&nn->nfs_volume_list);
#ifdef CONFIG_NFS_V4
#if IS_ENABLED(CONFIG_NFS_V4)
idr_init(&nn->cb_ident_idr);
#endif
spin_lock_init(&nn->nfs_client_lock);
+1 -1
View File
@@ -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
*/
+19 -1
View File
@@ -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>
@@ -935,6 +936,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.
@@ -1196,6 +1198,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_automount = nfs_d_automount,
.d_release = nfs_d_release,
};
EXPORT_SYMBOL_GPL(nfs_dentry_operations);
struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
{
@@ -1263,8 +1266,9 @@ out:
nfs_free_fhandle(fhandle);
return res;
}
EXPORT_SYMBOL_GPL(nfs_lookup);
#ifdef CONFIG_NFS_V4
#if IS_ENABLED(CONFIG_NFS_V4)
static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
const struct dentry_operations nfs4_dentry_operations = {
@@ -1274,6 +1278,7 @@ const struct dentry_operations nfs4_dentry_operations = {
.d_automount = nfs_d_automount,
.d_release = nfs_d_release,
};
EXPORT_SYMBOL_GPL(nfs4_dentry_operations);
static fmode_t flags_to_mode(int flags)
{
@@ -1416,6 +1421,7 @@ no_open:
return finish_no_open(file, res);
}
EXPORT_SYMBOL_GPL(nfs_atomic_open);
static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
{
@@ -1508,6 +1514,7 @@ out_error:
dput(parent);
return error;
}
EXPORT_SYMBOL_GPL(nfs_instantiate);
/*
* Following a failed create operation, we drop the dentry rather
@@ -1536,6 +1543,7 @@ out_err:
d_drop(dentry);
return error;
}
EXPORT_SYMBOL_GPL(nfs_create);
/*
* See comments for nfs_proc_create regarding failed operations.
@@ -1563,6 +1571,7 @@ out_err:
d_drop(dentry);
return status;
}
EXPORT_SYMBOL_GPL(nfs_mknod);
/*
* See comments for nfs_proc_create regarding failed operations.
@@ -1586,6 +1595,7 @@ out_err:
d_drop(dentry);
return error;
}
EXPORT_SYMBOL_GPL(nfs_mkdir);
static void nfs_dentry_handle_enoent(struct dentry *dentry)
{
@@ -1609,6 +1619,7 @@ 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,
@@ -1680,6 +1691,7 @@ 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,
@@ -1750,6 +1762,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
return 0;
}
EXPORT_SYMBOL_GPL(nfs_symlink);
int
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
@@ -1771,6 +1784,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
}
return error;
}
EXPORT_SYMBOL_GPL(nfs_link);
/*
* RENAME
@@ -1869,6 +1883,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);
@@ -1969,6 +1984,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)
{
@@ -2129,6 +2145,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)
{
@@ -2188,6 +2205,7 @@ out_notsup:
res = generic_permission(inode, mask);
goto out;
}
EXPORT_SYMBOL_GPL(nfs_permission);
/*
* Local variables:
+1 -1
View File
@@ -460,7 +460,7 @@ static void nfs_inode_dio_write_done(struct inode *inode)
inode_dio_done(inode);
}
#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 nfs_pageio_descriptor desc;
+4
View File
@@ -8,6 +8,7 @@
#ifdef CONFIG_NFS_USE_KERNEL_DNS
#include <linux/module.h>
#include <linux/sunrpc/clnt.h>
#include <linux/dns_resolver.h>
#include "dns_resolve.h"
@@ -27,9 +28,11 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
kfree(ip_addr);
return ret;
}
EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
#else
#include <linux/module.h>
#include <linux/hash.h>
#include <linux/string.h>
#include <linux/kmod.h>
@@ -345,6 +348,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name,
ret = -ESRCH;
return ret;
}
EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
int nfs_dns_resolver_cache_init(struct net *net)
{
+29 -2
View File
@@ -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>
@@ -52,6 +53,7 @@ int nfs_check_flags(int flags)
return 0;
}
EXPORT_SYMBOL_GPL(nfs_check_flags);
/*
* Open file
@@ -84,6 +86,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
@@ -137,6 +140,7 @@ 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.
@@ -165,6 +169,7 @@ 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);
ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
@@ -189,6 +194,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
}
return result;
}
EXPORT_SYMBOL_GPL(nfs_file_read);
ssize_t
nfs_file_splice_read(struct file *filp, loff_t *ppos,
@@ -211,6 +217,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
}
return res;
}
EXPORT_SYMBOL_GPL(nfs_file_splice_read);
int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
@@ -232,6 +239,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.
@@ -270,6 +278,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
ret = status;
return ret;
}
EXPORT_SYMBOL_GPL(nfs_file_fsync_commit);
static int
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
@@ -447,8 +456,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
/* Only do I/O if gfp is a superset of GFP_KERNEL */
if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
/* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not
* doing this memory reclaim for a fs-related allocation.
*/
if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL &&
!(current->flags & PF_FSTRANS)) {
int how = FLUSH_SYNC;
/* Don't let kswapd deadlock waiting for OOM RPC calls */
@@ -611,6 +623,7 @@ out_swapfile:
printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
goto out;
}
EXPORT_SYMBOL_GPL(nfs_file_write);
ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
struct file *filp, loff_t *ppos,
@@ -642,6 +655,7 @@ 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)
@@ -802,6 +816,7 @@ 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
@@ -819,6 +834,15 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
/*
* The NFSv4 protocol doesn't support LOCK_MAND, which is not part of
* any standard. In principle we might be able to support LOCK_MAND
* on NFSv2/3 since NLMv3/4 support DOS share modes, but for now the
* NFS code is not set up for it.
*/
if (fl->fl_type & LOCK_MAND)
return -EINVAL;
if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
is_local = 1;
@@ -831,6 +855,7 @@ 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
@@ -843,6 +868,7 @@ int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
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,
@@ -862,3 +888,4 @@ const struct file_operations nfs_file_operations = {
.check_flags = nfs_check_flags,
.setlease = nfs_setlease,
};
EXPORT_SYMBOL_GPL(nfs_file_operations);
+20 -9
View File
@@ -52,8 +52,6 @@
#define NFS_UINT_MAXLEN 11
/* Default cache timeout is 10 minutes */
unsigned int nfs_idmap_cache_timeout = 600;
static const struct cred *id_resolver_cache;
static struct key_type key_type_id_resolver_legacy;
@@ -205,12 +203,18 @@ static int nfs_idmap_init_keyring(void)
if (ret < 0)
goto failed_put_key;
ret = register_key_type(&key_type_id_resolver_legacy);
if (ret < 0)
goto failed_reg_legacy;
set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
cred->thread_keyring = keyring;
cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
id_resolver_cache = cred;
return 0;
failed_reg_legacy:
unregister_key_type(&key_type_id_resolver);
failed_put_key:
key_put(keyring);
failed_put_cred:
@@ -222,6 +226,7 @@ static void nfs_idmap_quit_keyring(void)
{
key_revoke(id_resolver_cache->thread_keyring);
unregister_key_type(&key_type_id_resolver);
unregister_key_type(&key_type_id_resolver_legacy);
put_cred(id_resolver_cache);
}
@@ -359,7 +364,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
}
/* idmap classic begins here */
module_param(nfs_idmap_cache_timeout, int, 0644);
enum {
Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
@@ -385,7 +389,7 @@ static const struct rpc_pipe_ops idmap_upcall_ops = {
};
static struct key_type key_type_id_resolver_legacy = {
.name = "id_resolver",
.name = "id_legacy",
.instantiate = user_instantiate,
.match = user_match,
.revoke = user_revoke,
@@ -674,6 +678,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
if (ret < 0)
goto out2;
BUG_ON(idmap->idmap_key_cons != NULL);
idmap->idmap_key_cons = cons;
ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
@@ -687,8 +692,7 @@ out2:
out1:
kfree(msg);
out0:
key_revoke(cons->key);
key_revoke(cons->authkey);
complete_request_key(cons, ret);
return ret;
}
@@ -722,11 +726,18 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
struct idmap *idmap = (struct idmap *)rpci->private;
struct key_construction *cons = idmap->idmap_key_cons;
struct key_construction *cons;
struct idmap_msg im;
size_t namelen_in;
int ret;
/* If instantiation is successful, anyone waiting for key construction
* will have been woken up and someone else may now have used
* idmap_key_cons - so after this point we may no longer touch it.
*/
cons = ACCESS_ONCE(idmap->idmap_key_cons);
idmap->idmap_key_cons = NULL;
if (mlen != sizeof(im)) {
ret = -ENOSPC;
goto out;
@@ -739,7 +750,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
ret = mlen;
complete_request_key(idmap->idmap_key_cons, -ENOKEY);
complete_request_key(cons, -ENOKEY);
goto out_incomplete;
}
@@ -756,7 +767,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
}
out:
complete_request_key(idmap->idmap_key_cons, ret);
complete_request_key(cons, ret);
out_incomplete:
return ret;
}
+47 -58
View File
@@ -50,6 +50,7 @@
#include "fscache.h"
#include "dns_resolve.h"
#include "pnfs.h"
#include "nfs.h"
#include "netns.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -81,6 +82,7 @@ int nfs_wait_bit_killable(void *word)
freezable_schedule();
return 0;
}
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
/**
* nfs_compat_user_ino64 - returns the user-visible inode number
@@ -105,7 +107,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 +118,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)
{
@@ -185,6 +188,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)
{
@@ -192,6 +196,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.
@@ -390,6 +395,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|ATTR_OPEN)
@@ -437,6 +443,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
@@ -495,6 +502,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)
{
@@ -534,6 +542,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)
{
@@ -622,6 +631,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, fmode_t f_mode)
{
@@ -648,6 +658,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f
ctx->mdsthreshold = NULL;
return ctx;
}
EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
{
@@ -655,6 +666,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)
{
@@ -682,6 +694,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
@@ -697,6 +710,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
@@ -841,6 +855,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)
{
@@ -1027,6 +1042,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)
{
@@ -1037,6 +1053,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)
{
@@ -1047,6 +1064,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
fh->size = 0;
return fh;
}
EXPORT_SYMBOL_GPL(nfs_alloc_fhandle);
#ifdef NFS_DEBUG
/*
@@ -1167,6 +1185,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)
{
@@ -1203,6 +1222,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
@@ -1254,6 +1274,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
@@ -1471,27 +1492,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
return -ESTALE;
}
#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);
clear_inode(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;
@@ -1504,11 +1504,12 @@ 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;
}
EXPORT_SYMBOL_GPL(nfs_alloc_inode);
static void nfs_i_callback(struct rcu_head *head)
{
@@ -1520,10 +1521,11 @@ 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)
{
#ifdef CONFIG_NFS_V4
#if IS_ENABLED(CONFIG_NFS_V4)
INIT_LIST_HEAD(&nfsi->open_states);
nfsi->delegation = NULL;
nfsi->delegation_state = 0;
@@ -1569,6 +1571,7 @@ static void nfs_destroy_inodecache(void)
}
struct workqueue_struct *nfsiod_workqueue;
EXPORT_SYMBOL_GPL(nfsiod_workqueue);
/*
* start up the nfsiod workqueue
@@ -1629,94 +1632,80 @@ static int __init init_nfs_fs(void)
err = nfs_dns_resolver_init();
if (err < 0)
goto out11;
goto out10;;
err = register_pernet_subsys(&nfs_net_ops);
if (err < 0)
goto out10;
goto out9;
err = nfs_fscache_register();
if (err < 0)
goto out9;
goto out8;
err = nfsiod_start();
if (err)
goto out8;
goto out7;
err = nfs_fs_proc_init();
if (err)
goto out7;
goto out6;
err = nfs_init_nfspagecache();
if (err)
goto out6;
goto out5;
err = nfs_init_inodecache();
if (err)
goto out5;
goto out4;
err = nfs_init_readpagecache();
if (err)
goto out4;
goto out3;
err = nfs_init_writepagecache();
if (err)
goto out3;
goto out2;
err = nfs_init_directcache();
if (err)
goto out2;
goto out1;
#ifdef CONFIG_PROC_FS
rpc_proc_register(&init_net, &nfs_rpcstat);
#endif
#ifdef CONFIG_NFS_V4
err = init_nfs_v4();
if (err)
goto out1;
#endif
if ((err = register_nfs_fs()) != 0)
goto out0;
return 0;
out0:
#ifdef CONFIG_NFS_V4
exit_nfs_v4();
out1:
#endif
#ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs");
#endif
nfs_destroy_directcache();
out2:
out1:
nfs_destroy_writepagecache();
out3:
out2:
nfs_destroy_readpagecache();
out4:
out3:
nfs_destroy_inodecache();
out5:
out4:
nfs_destroy_nfspagecache();
out6:
out5:
nfs_fs_proc_exit();
out7:
out6:
nfsiod_stop();
out8:
out7:
nfs_fscache_unregister();
out9:
out8:
unregister_pernet_subsys(&nfs_net_ops);
out10:
out9:
nfs_dns_resolver_destroy();
out11:
out10:
return err;
}
static void __exit exit_nfs_fs(void)
{
#ifdef CONFIG_NFS_V4
exit_nfs_v4();
#endif
nfs_destroy_directcache();
nfs_destroy_writepagecache();
nfs_destroy_readpagecache();
+23 -15
View File
@@ -90,7 +90,7 @@ struct nfs_client_initdata {
const char *hostname;
const struct sockaddr *addr;
size_t addrlen;
const struct nfs_rpc_ops *rpc_ops;
struct nfs_subversion *nfs_mod;
int proto;
u32 minorversion;
struct net *net;
@@ -187,12 +187,11 @@ extern struct nfs_client *nfs4_find_client_ident(struct net *, int);
extern struct nfs_client *
nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
struct nfs4_sessionid *);
extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *,
struct nfs_fh *);
extern struct nfs_server *nfs_create_server(struct nfs_mount_info *,
struct nfs_subversion *);
extern struct nfs_server *nfs4_create_server(
const struct nfs_parsed_mount_data *,
struct nfs_fh *);
struct nfs_mount_info *,
struct nfs_subversion *);
extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
struct nfs_fh *);
extern void nfs_free_server(struct nfs_server *server);
@@ -224,6 +223,13 @@ static inline void nfs_fs_proc_exit(void)
int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
#endif
/* nfs3client.c */
#if IS_ENABLED(CONFIG_NFS_V3)
struct nfs_server *nfs3_create_server(struct nfs_mount_info *, struct nfs_subversion *);
struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t);
#endif
/* callback_xdr.c */
extern struct svc_version nfs4_callback_version1;
extern struct svc_version nfs4_callback_version4;
@@ -256,7 +262,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
@@ -266,7 +272,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[];
#endif
@@ -313,24 +319,26 @@ extern struct workqueue_struct *nfsiod_workqueue;
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_clear_inode(struct inode *);
extern void nfs_evict_inode(struct inode *);
#ifdef CONFIG_NFS_V4
extern void nfs4_evict_inode(struct inode *);
#endif
void nfs_zap_acl_cache(struct inode *inode);
extern int nfs_wait_bit_killable(void *word);
/* super.c */
extern const struct super_operations nfs_sops;
extern struct file_system_type nfs_fs_type;
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
struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
struct nfs_subversion *);
void nfs_initialise_sb(struct super_block *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount_common(struct file_system_type *, struct nfs_server *,
int, const char *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
struct nfs_mount_info *, struct nfs_subversion *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
const char *, struct nfs_mount_info *);
@@ -356,7 +364,7 @@ struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
/* 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 *);
+4 -13
View File
@@ -7,6 +7,7 @@
* NFS namespace
*/
#include <linux/module.h>
#include <linux/dcache.h>
#include <linux/gfp.h>
#include <linux/mount.h>
@@ -112,6 +113,7 @@ Elong_unlock:
Elong:
return ERR_PTR(-ENAMETOOLONG);
}
EXPORT_SYMBOL_GPL(nfs_path);
/*
* nfs_d_automount - Handle crossing a mountpoint on the server
@@ -195,20 +197,7 @@ static struct vfsmount *nfs_do_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
}
/**
@@ -253,6 +242,7 @@ out:
dprintk("<-- nfs_do_submount() = %p\n", mnt);
return mnt;
}
EXPORT_SYMBOL_GPL(nfs_do_submount);
struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
struct nfs_fh *fh, struct nfs_fattr *fattr)
@@ -268,3 +258,4 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor);
}
EXPORT_SYMBOL_GPL(nfs_submount);
+1 -1
View File
@@ -20,7 +20,7 @@ struct nfs_net {
wait_queue_head_t bl_wq;
struct list_head nfs_client_list;
struct list_head nfs_volume_list;
#ifdef CONFIG_NFS_V4
#if IS_ENABLED(CONFIG_NFS_V4)
struct idr cb_ident_idr; /* Protected by nfs_client_lock */
#endif
spinlock_t nfs_client_lock;
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 {
struct module *owner; /* THIS_MODULE pointer */
struct file_system_type *nfs_fs; /* NFS filesystem type */
const struct rpc_version *rpc_vers; /* NFS version information */
const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
const struct super_operations *sops; /* NFS Super operations */
const struct xattr_handler **xattr; /* NFS xattr handlers */
struct list_head list; /* List of NFS versions */
};
struct nfs_subversion *get_nfs_version(unsigned int);
void put_nfs_version(struct nfs_subversion *);
void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);
#endif /* __LINUX_INTERNAL_NFS_H */
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include "internal.h"
#include "nfs.h"
static struct nfs_subversion nfs_v2 = {
.owner = THIS_MODULE,
.nfs_fs = &nfs_fs_type,
.rpc_vers = &nfs_version2,
.rpc_ops = &nfs_v2_clientops,
.sops = &nfs_sops,
};
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);
+65
View File
@@ -0,0 +1,65 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include "internal.h"
#ifdef CONFIG_NFS_V3_ACL
static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
static const struct rpc_version *nfsacl_version[] = {
[3] = &nfsacl_version3,
};
const struct rpc_program nfsacl_program = {
.name = "nfsacl",
.number = NFS_ACL_PROGRAM,
.nrvers = ARRAY_SIZE(nfsacl_version),
.version = nfsacl_version,
.stats = &nfsacl_rpcstat,
};
/*
* Initialise an NFSv3 ACL client connection
*/
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->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
struct nfs_server *nfs3_create_server(struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{
struct nfs_server *server = nfs_create_server(mount_info, nfs_mod);
/* Create a client RPC handle for the NFS v3 ACL management interface */
if (!IS_ERR(server))
nfs_init_server_aclclient(server);
return server;
}
struct nfs_server *nfs3_clone_server(struct nfs_server *source,
struct nfs_fh *fh,
struct nfs_fattr *fattr,
rpc_authflavor_t flavor)
{
struct nfs_server *server = nfs_clone_server(source, fh, fattr, flavor);
if (!IS_ERR(server) && !IS_ERR(source->client_acl))
nfs_init_server_aclclient(server);
return server;
}
+3
View File
@@ -925,6 +925,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.file_ops = &nfs_file_operations,
.getroot = nfs3_proc_get_root,
.submount = nfs_submount,
.try_mount = nfs_try_mount,
.getattr = nfs3_proc_getattr,
.setattr = nfs3_proc_setattr,
.lookup = nfs3_proc_lookup,
@@ -968,4 +969,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.alloc_client = nfs_alloc_client,
.init_client = nfs_init_client,
.free_client = nfs_free_client,
.create_server = nfs3_create_server,
.clone_server = nfs3_clone_server,
};

Some files were not shown because too many files have changed in this diff Show More