Commit 1fad1e9a authored by Linus Torvalds's avatar Linus Torvalds

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

Pull NFS client updates from Trond Myklebust:
 "Features include:
   - More preparatory patches for modularising NFSv2/v3/v4.  Split out
     the various NFSv2/v3/v4-specific code into separate files
   - More preparation for the NFSv4 migration code
   - Ensure that OPEN(O_CREATE) observes the pNFS mds threshold
     parameters
   - pNFS fast failover when the data servers are down
   - Various cleanups and debugging patches"

* tag 'nfs-for-3.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits)
  nfs: fix fl_type tests in NFSv4 code
  NFS: fix pnfs regression with directio writes
  NFS: fix pnfs regression with directio reads
  sunrpc: clnt: Add missing braces
  nfs: fix stub return type warnings
  NFS: exit_nfs_v4() shouldn't be an __exit function
  SUNRPC: Add a missing spin_unlock to gss_mech_list_pseudoflavors
  NFS: Split out NFS v4 client functions
  NFS: Split out the NFS v4 filesystem types
  NFS: Create a single nfs_clone_super() function
  NFS: Split out NFS v4 server creating code
  NFS: Initialize the NFS v4 client from init_nfs_v4()
  NFS: Move the v4 getroot code to nfs4getroot.c
  NFS: Split out NFS v4 file operations
  NFS: Initialize v4 sysctls from nfs_init_v4()
  NFS: Create an init_nfs_v4() function
  NFS: Split out NFS v4 inode operations
  NFS: Split out NFS v3 inode operations
  NFS: Split out NFS v2 inode operations
  NFS: Clean up nfs4_proc_setclientid() and friends
  ...
parents bbeb0af2 f44106e2
...@@ -88,9 +88,8 @@ config NFS_V4 ...@@ -88,9 +88,8 @@ config NFS_V4
config NFS_V4_1 config NFS_V4_1
bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
depends on NFS_FS && NFS_V4 && EXPERIMENTAL depends on NFS_V4 && EXPERIMENTAL
select SUNRPC_BACKCHANNEL select SUNRPC_BACKCHANNEL
select PNFS_FILE_LAYOUT
help help
This option enables support for minor version 1 of the NFSv4 protocol This option enables support for minor version 1 of the NFSv4 protocol
(RFC 5661) in the kernel's NFS client. (RFC 5661) in the kernel's NFS client.
...@@ -99,15 +98,17 @@ config NFS_V4_1 ...@@ -99,15 +98,17 @@ config NFS_V4_1
config PNFS_FILE_LAYOUT config PNFS_FILE_LAYOUT
tristate tristate
depends on NFS_V4_1
default m
config PNFS_BLOCK config PNFS_BLOCK
tristate tristate
depends on NFS_FS && NFS_V4_1 && BLK_DEV_DM depends on NFS_V4_1 && BLK_DEV_DM
default m default m
config PNFS_OBJLAYOUT config PNFS_OBJLAYOUT
tristate tristate
depends on NFS_FS && NFS_V4_1 && SCSI_OSD_ULD depends on NFS_V4_1 && SCSI_OSD_ULD
default m default m
config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN
......
...@@ -13,11 +13,16 @@ nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o ...@@ -13,11 +13,16 @@ nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \ nfs4super.o nfs4file.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \ callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o nfs4namespace.o nfs4getroot.o nfs4client.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
ifeq ($(CONFIG_SYSCTL), y)
nfs-y += sysctl.o
nfs-$(CONFIG_NFS_V4) += nfs4sysctl.o
endif
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
......
This diff is collapsed.
...@@ -47,7 +47,7 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) ...@@ -47,7 +47,7 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
* *
* Returns one if inode has the indicated delegation, otherwise zero. * 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; struct nfs_delegation *delegation;
int ret = 0; int ret = 0;
...@@ -388,7 +388,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode) ...@@ -388,7 +388,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
* *
* Returns zero on success, or a negative errno value. * 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_server *server = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
...@@ -417,9 +417,8 @@ static void nfs_mark_return_delegation(struct nfs_server *server, ...@@ -417,9 +417,8 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
* @sb: sb to process * @sb: sb to process
* *
*/ */
void nfs_super_return_all_delegations(struct super_block *sb) void nfs_server_return_all_delegations(struct nfs_server *server)
{ {
struct nfs_server *server = NFS_SB(sb);
struct nfs_client *clp = server->nfs_client; struct nfs_client *clp = server->nfs_client;
struct nfs_delegation *delegation; struct nfs_delegation *delegation;
......
...@@ -33,12 +33,12 @@ enum { ...@@ -33,12 +33,12 @@ enum {
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); 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); 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); int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
void nfs_inode_return_delegation_noreclaim(struct inode *inode); void nfs_inode_return_delegation_noreclaim(struct inode *inode);
struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
void nfs_super_return_all_delegations(struct super_block *sb); void nfs_server_return_all_delegations(struct nfs_server *);
void nfs_expire_all_delegations(struct nfs_client *clp); void nfs_expire_all_delegations(struct nfs_client *clp);
void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags); void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
...@@ -56,24 +56,13 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl); ...@@ -56,24 +56,13 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags); bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags);
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation); 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)
{
nfs_wb_all(inode);
return 0;
}
#endif #endif
static inline int nfs_have_delegated_attributes(struct inode *inode) static inline int nfs_have_delegated_attributes(struct inode *inode)
{ {
return nfs_have_delegation(inode, FMODE_READ) && return NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) &&
!(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED); !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
} }
......
...@@ -46,16 +46,6 @@ ...@@ -46,16 +46,6 @@
static int nfs_opendir(struct inode *, struct file *); static int nfs_opendir(struct inode *, struct file *);
static int nfs_closedir(struct inode *, struct file *); static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t); static int nfs_readdir(struct file *, void *, filldir_t);
static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
static int nfs_create(struct inode *, struct dentry *, umode_t, bool);
static int nfs_mkdir(struct inode *, struct dentry *, umode_t);
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 *, umode_t, 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 int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int); static loff_t nfs_llseek_dir(struct file *, loff_t, int);
static void nfs_readdir_clear_array(struct page*); static void nfs_readdir_clear_array(struct page*);
...@@ -69,73 +59,10 @@ const struct file_operations nfs_dir_operations = { ...@@ -69,73 +59,10 @@ const struct file_operations nfs_dir_operations = {
.fsync = nfs_fsync_dir, .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 = { const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array, .freepage = nfs_readdir_clear_array,
}; };
#ifdef 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 int nfs_atomic_open(struct inode *, struct dentry *,
struct file *, unsigned, umode_t,
int *);
const struct inode_operations nfs4_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
.atomic_open = nfs_atomic_open,
.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) static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred)
{ {
struct nfs_open_dir_context *ctx; struct nfs_open_dir_context *ctx;
...@@ -1128,7 +1055,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -1128,7 +1055,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
goto out_bad; goto out_bad;
} }
if (nfs_have_delegation(inode, FMODE_READ)) if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
goto out_set_verifier; goto out_set_verifier;
/* Force a full look up iff the parent directory has changed */ /* Force a full look up iff the parent directory has changed */
...@@ -1270,7 +1197,7 @@ const struct dentry_operations nfs_dentry_operations = { ...@@ -1270,7 +1197,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_release = nfs_d_release, .d_release = nfs_d_release,
}; };
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
{ {
struct dentry *res; struct dentry *res;
struct dentry *parent; struct dentry *parent;
...@@ -1398,9 +1325,9 @@ static int nfs_finish_open(struct nfs_open_context *ctx, ...@@ -1398,9 +1325,9 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
return err; return err;
} }
static int nfs_atomic_open(struct inode *dir, struct dentry *dentry, int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned open_flags, struct file *file, unsigned open_flags,
umode_t mode, int *opened) umode_t mode, int *opened)
{ {
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct dentry *res; struct dentry *res;
...@@ -1588,7 +1515,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, ...@@ -1588,7 +1515,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
* that the operation succeeded on the server, but an error in the * that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed. * reply path made it appear to have failed.
*/ */
static int nfs_create(struct inode *dir, struct dentry *dentry, int nfs_create(struct inode *dir, struct dentry *dentry,
umode_t mode, bool excl) umode_t mode, bool excl)
{ {
struct iattr attr; struct iattr attr;
...@@ -1613,7 +1540,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, ...@@ -1613,7 +1540,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
/* /*
* See comments for nfs_proc_create regarding failed operations. * See comments for nfs_proc_create regarding failed operations.
*/ */
static int int
nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
{ {
struct iattr attr; struct iattr attr;
...@@ -1640,7 +1567,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) ...@@ -1640,7 +1567,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
/* /*
* See comments for nfs_proc_create regarding failed operations. * See comments for nfs_proc_create regarding failed operations.
*/ */
static int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{ {
struct iattr attr; struct iattr attr;
int error; int error;
...@@ -1666,7 +1593,7 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry) ...@@ -1666,7 +1593,7 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
d_delete(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; int error;
...@@ -1706,7 +1633,7 @@ static int nfs_safe_remove(struct dentry *dentry) ...@@ -1706,7 +1633,7 @@ static int nfs_safe_remove(struct dentry *dentry)
} }
if (inode != NULL) { if (inode != NULL) {
nfs_inode_return_delegation(inode); NFS_PROTO(inode)->return_delegation(inode);
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
/* The VFS may want to delete this inode */ /* The VFS may want to delete this inode */
if (error == 0) if (error == 0)
...@@ -1725,7 +1652,7 @@ static int nfs_safe_remove(struct dentry *dentry) ...@@ -1725,7 +1652,7 @@ static int nfs_safe_remove(struct dentry *dentry)
* *
* If sillyrename() returns 0, we do nothing, otherwise we unlink. * 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 error;
int need_rehash = 0; int need_rehash = 0;
...@@ -1769,7 +1696,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1769,7 +1696,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 * now have a new file handle and can instantiate an in-core NFS inode
* and move the raw page into its mapping. * 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 pagevec lru_pvec;
struct page *page; struct page *page;
...@@ -1824,7 +1751,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym ...@@ -1824,7 +1751,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
return 0; return 0;
} }
static int int
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
...@@ -1834,7 +1761,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) ...@@ -1834,7 +1761,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
old_dentry->d_parent->d_name.name, old_dentry->d_name.name, old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
nfs_inode_return_delegation(inode); NFS_PROTO(inode)->return_delegation(inode);
d_drop(dentry); d_drop(dentry);
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
...@@ -1869,7 +1796,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) ...@@ -1869,7 +1796,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 * If these conditions are met, we can drop the dentries before doing
* the rename. * 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 *new_dir, struct dentry *new_dentry)
{ {
struct inode *old_inode = old_dentry->d_inode; struct inode *old_inode = old_dentry->d_inode;
...@@ -1918,9 +1845,9 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1918,9 +1845,9 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
} }
nfs_inode_return_delegation(old_inode); NFS_PROTO(old_inode)->return_delegation(old_inode);
if (new_inode != NULL) if (new_inode != NULL)
nfs_inode_return_delegation(new_inode); NFS_PROTO(new_inode)->return_delegation(new_inode);
error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
new_dir, &new_dentry->d_name); new_dir, &new_dentry->d_name);
......
...@@ -393,7 +393,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, ...@@ -393,7 +393,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
size_t requested_bytes = 0; size_t requested_bytes = 0;
unsigned long seg; unsigned long seg;
nfs_pageio_init_read(&desc, dreq->inode, NFS_PROTO(dreq->inode)->read_pageio_init(&desc, dreq->inode,
&nfs_direct_read_completion_ops); &nfs_direct_read_completion_ops);
get_dreq(dreq); get_dreq(dreq);
desc.pg_dreq = dreq; desc.pg_dreq = dreq;
...@@ -478,7 +478,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) ...@@ -478,7 +478,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
dreq->count = 0; dreq->count = 0;
get_dreq(dreq); get_dreq(dreq);
nfs_pageio_init_write(&desc, dreq->inode, FLUSH_STABLE, NFS_PROTO(dreq->inode)->write_pageio_init(&desc, dreq->inode, FLUSH_STABLE,
&nfs_direct_write_completion_ops); &nfs_direct_write_completion_ops);
desc.pg_dreq = dreq; desc.pg_dreq = dreq;
...@@ -782,7 +782,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, ...@@ -782,7 +782,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
size_t requested_bytes = 0; size_t requested_bytes = 0;
unsigned long seg; unsigned long seg;
nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, NFS_PROTO(inode)->write_pageio_init(&desc, inode, FLUSH_COND_STABLE,
&nfs_direct_write_completion_ops); &nfs_direct_write_completion_ops);
desc.pg_dreq = dreq; desc.pg_dreq = dreq;
get_dreq(dreq); get_dreq(dreq);
......
...@@ -35,36 +35,17 @@ ...@@ -35,36 +35,17 @@
#include "internal.h" #include "internal.h"
#include "iostat.h" #include "iostat.h"
#include "fscache.h" #include "fscache.h"
#include "pnfs.h"
#define NFSDBG_FACILITY NFSDBG_FILE #define NFSDBG_FACILITY NFSDBG_FILE
static const struct vm_operations_struct nfs_file_vm_ops; 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,
.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 */ /* Hack for future NFS swap support */
#ifndef IS_SWAPFILE #ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0) # define IS_SWAPFILE(inode) (0)
#endif #endif
static int nfs_check_flags(int flags) int nfs_check_flags(int flags)
{ {
if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT)) if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
return -EINVAL; return -EINVAL;
...@@ -93,7 +74,7 @@ nfs_file_open(struct inode *inode, struct file *filp) ...@@ -93,7 +74,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
return res; return res;
} }
static int int
nfs_file_release(struct inode *inode, struct file *filp) nfs_file_release(struct inode *inode, struct file *filp)
{ {
dprintk("NFS: release(%s/%s)\n", dprintk("NFS: release(%s/%s)\n",
...@@ -135,7 +116,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) ...@@ -135,7 +116,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
return __nfs_revalidate_inode(server, inode); 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", dprintk("NFS: llseek file(%s/%s, %lld, %d)\n",
filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_parent->d_name.name,
...@@ -160,7 +141,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) ...@@ -160,7 +141,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
/* /*
* Flush all dirty pages, and check for write errors. * Flush all dirty pages, and check for write errors.
*/ */
static int int
nfs_file_flush(struct file *file, fl_owner_t id) nfs_file_flush(struct file *file, fl_owner_t id)
{ {
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
...@@ -178,14 +159,14 @@ nfs_file_flush(struct file *file, fl_owner_t id) ...@@ -178,14 +159,14 @@ nfs_file_flush(struct file *file, fl_owner_t id)
* If we're holding a write delegation, then just start the i/o * If we're holding a write delegation, then just start the i/o
* but don't wait for completion (or send a commit). * but don't wait for completion (or send a commit).
*/ */
if (nfs_have_delegation(inode, FMODE_WRITE)) if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
return filemap_fdatawrite(file->f_mapping); return filemap_fdatawrite(file->f_mapping);
/* Flush writes to the server and return any errors */ /* Flush writes to the server and return any errors */
return vfs_fsync(file, 0); return vfs_fsync(file, 0);
} }
static ssize_t ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov, nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
...@@ -209,7 +190,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, ...@@ -209,7 +190,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
return result; return result;
} }
static ssize_t ssize_t
nfs_file_splice_read(struct file *filp, loff_t *ppos, nfs_file_splice_read(struct file *filp, loff_t *ppos,
struct pipe_inode_info *pipe, size_t count, struct pipe_inode_info *pipe, size_t count,
unsigned int flags) unsigned int flags)
...@@ -231,7 +212,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, ...@@ -231,7 +212,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
return res; return res;
} }
static int int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma) nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{ {
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
...@@ -264,8 +245,8 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) ...@@ -264,8 +245,8 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* nfs_file_write() that a write error occurred, and hence cause it to * nfs_file_write() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write. * fall back to doing a synchronous write.
*/ */
static int int
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
{ {
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
struct nfs_open_context *ctx = nfs_file_open_context(file); struct nfs_open_context *ctx = nfs_file_open_context(file);
...@@ -277,9 +258,6 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -277,9 +258,6 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
datasync); datasync);
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
mutex_lock(&inode->i_mutex);
nfs_inc_stats(inode, NFSIOS_VFSFSYNC); nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC); status = nfs_commit_inode(inode, FLUSH_SYNC);
...@@ -290,10 +268,20 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -290,10 +268,20 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
ret = xchg(&ctx->error, 0); ret = xchg(&ctx->error, 0);
if (!ret && status < 0) if (!ret && status < 0)
ret = status; ret = status;
if (!ret && !datasync) return ret;
/* application has asked for meta-data sync */ }
ret = pnfs_layoutcommit_inode(inode, true);
static int
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
int ret;
struct inode *inode = file->f_path.dentry->d_inode;
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
mutex_lock(&inode->i_mutex);
ret = nfs_file_fsync_commit(file, start, end, datasync);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
return ret; return ret;
} }
...@@ -572,8 +560,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) ...@@ -572,8 +560,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
return 0; return 0;
} }
static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
struct dentry * dentry = iocb->ki_filp->f_path.dentry; struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
...@@ -624,9 +612,9 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -624,9 +612,9 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
goto out; goto out;
} }
static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
struct file *filp, loff_t *ppos, struct file *filp, loff_t *ppos,
size_t count, unsigned int flags) size_t count, unsigned int flags)
{ {
struct dentry *dentry = filp->f_path.dentry; struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
...@@ -670,7 +658,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) ...@@ -670,7 +658,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
} }
fl->fl_type = saved_type; fl->fl_type = saved_type;
if (nfs_have_delegation(inode, FMODE_READ)) if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
goto out_noconflict; goto out_noconflict;
if (is_local) if (is_local)
...@@ -765,7 +753,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) ...@@ -765,7 +753,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
* This makes locking act as a cache coherency point. * This makes locking act as a cache coherency point.
*/ */
nfs_sync_mapping(filp->f_mapping); nfs_sync_mapping(filp->f_mapping);
if (!nfs_have_delegation(inode, FMODE_READ)) { if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) {
if (is_time_granular(&NFS_SERVER(inode)->time_delta)) if (is_time_granular(&NFS_SERVER(inode)->time_delta))
__nfs_revalidate_inode(NFS_SERVER(inode), inode); __nfs_revalidate_inode(NFS_SERVER(inode), inode);
else else
...@@ -778,7 +766,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) ...@@ -778,7 +766,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
/* /*
* Lock a (portion of) a file * 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; struct inode *inode = filp->f_mapping->host;
int ret = -ENOLCK; int ret = -ENOLCK;
...@@ -818,7 +806,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -818,7 +806,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
/* /*
* Lock a (portion of) a file * 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; struct inode *inode = filp->f_mapping->host;
int is_local = 0; int is_local = 0;
...@@ -848,7 +836,7 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -848,7 +836,7 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
* There is no protocol support for leases, so we have no way to implement * There is no protocol support for leases, so we have no way to implement
* them correctly in the face of opens by other clients. * 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", dprintk("NFS: setlease(%s/%s, arg=%ld)\n",
file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_parent->d_name.name,
...@@ -874,104 +862,3 @@ const struct file_operations nfs_file_operations = { ...@@ -874,104 +862,3 @@ const struct file_operations nfs_file_operations = {
.check_flags = nfs_check_flags, .check_flags = nfs_check_flags,
.setlease = nfs_setlease, .setlease = nfs_setlease,
}; };
#ifdef CONFIG_NFS_V4
static int
nfs4_file_open(struct inode *inode, struct file *filp)
{
struct nfs_open_context *ctx;
struct dentry *dentry = filp->f_path.dentry;
struct dentry *parent = NULL;
struct inode *dir;
unsigned openflags = filp->f_flags;
struct iattr attr;
int err;
BUG_ON(inode != dentry->d_inode);
/*
* If no cached dentry exists or if it's negative, NFSv4 handled the
* opens in ->lookup() or ->create().
*
* We only get this far for a cached positive dentry. We skipped
* revalidation, so handle it here by dropping the dentry and returning
* -EOPENSTALE. The VFS will retry the lookup/create/open.
*/
dprintk("NFS: open file(%s/%s)\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
if ((openflags & O_ACCMODE) == 3)
openflags--;
/* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL);
parent = dget_parent(dentry);
dir = parent->d_inode;
ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
err = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out;
attr.ia_valid = ATTR_OPEN;
if (openflags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
nfs_wb_all(inode);
}
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
switch (err) {
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));
nfs_file_set_open_context(filp, ctx);
err = 0;
out_put_ctx:
put_nfs_open_context(ctx);
out:
dput(parent);
return err;
out_drop:
d_drop(dentry);
err = -EOPENSTALE;
goto out_put_ctx;
}
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 */
...@@ -23,21 +23,15 @@ ...@@ -23,21 +23,15 @@
#include <linux/sunrpc/stats.h> #include <linux/sunrpc/stats.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/nfs_mount.h> #include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h> #include <linux/lockd/bind.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/nfs_idmap.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/security.h> #include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "nfs4_fs.h"
#include "delegation.h"
#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT #define NFSDBG_FACILITY NFSDBG_CLIENT
/* /*
...@@ -135,47 +129,3 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, ...@@ -135,47 +129,3 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
nfs_free_fattr(fsinfo.fattr); nfs_free_fattr(fsinfo.fattr);
return ret; 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 = nfs4_proc_get_rootfh(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;
}
#endif /* CONFIG_NFS_V4 */
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <linux/lockd/bind.h> #include <linux/lockd/bind.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/nfs_idmap.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/nfs_xdr.h> #include <linux/nfs_xdr.h>
...@@ -430,7 +429,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -430,7 +429,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
* Return any delegations if we're going to change ACLs * Return any delegations if we're going to change ACLs
*/ */
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
nfs_inode_return_delegation(inode); NFS_PROTO(inode)->return_delegation(inode);
error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
if (error == 0) if (error == 0)
nfs_refresh_inode(inode, fattr); nfs_refresh_inode(inode, fattr);
...@@ -1457,7 +1456,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1457,7 +1456,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|| S_ISLNK(inode->i_mode))) || S_ISLNK(inode->i_mode)))
invalid &= ~NFS_INO_INVALID_DATA; invalid &= ~NFS_INO_INVALID_DATA;
if (!nfs_have_delegation(inode, FMODE_READ) || if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) ||
(save_cache_validity & NFS_INO_REVAL_FORCED)) (save_cache_validity & NFS_INO_REVAL_FORCED))
nfsi->cache_validity |= invalid; nfsi->cache_validity |= invalid;
...@@ -1628,87 +1627,96 @@ static int __init init_nfs_fs(void) ...@@ -1628,87 +1627,96 @@ static int __init init_nfs_fs(void)
{ {
int err; int err;
err = nfs_idmap_init();
if (err < 0)
goto out10;
err = nfs_dns_resolver_init(); err = nfs_dns_resolver_init();
if (err < 0) if (err < 0)
goto out9; goto out11;
err = register_pernet_subsys(&nfs_net_ops); err = register_pernet_subsys(&nfs_net_ops);
if (err < 0) if (err < 0)
goto out8; goto out10;
err = nfs_fscache_register(); err = nfs_fscache_register();
if (err < 0) if (err < 0)
goto out7; goto out9;
err = nfsiod_start(); err = nfsiod_start();
if (err) if (err)
goto out6; goto out8;
err = nfs_fs_proc_init(); err = nfs_fs_proc_init();
if (err) if (err)
goto out5; goto out7;
err = nfs_init_nfspagecache(); err = nfs_init_nfspagecache();
if (err) if (err)
goto out4; goto out6;
err = nfs_init_inodecache(); err = nfs_init_inodecache();
if (err) if (err)
goto out3; goto out5;
err = nfs_init_readpagecache(); err = nfs_init_readpagecache();
if (err) if (err)
goto out2; goto out4;
err = nfs_init_writepagecache(); err = nfs_init_writepagecache();
if (err) if (err)
goto out1; goto out3;
err = nfs_init_directcache(); err = nfs_init_directcache();
if (err) if (err)
goto out0; goto out2;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
rpc_proc_register(&init_net, &nfs_rpcstat); rpc_proc_register(&init_net, &nfs_rpcstat);
#endif #endif
#ifdef CONFIG_NFS_V4
err = init_nfs_v4();
if (err)
goto out1;
#endif
if ((err = register_nfs_fs()) != 0) if ((err = register_nfs_fs()) != 0)
goto out; goto out0;
return 0; return 0;
out: out0:
#ifdef CONFIG_NFS_V4
exit_nfs_v4();
out1:
#endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs"); rpc_proc_unregister(&init_net, "nfs");
#endif #endif
nfs_destroy_directcache(); nfs_destroy_directcache();
out0:
nfs_destroy_writepagecache();
out1:
nfs_destroy_readpagecache();
out2: out2:
nfs_destroy_inodecache(); nfs_destroy_writepagecache();
out3: out3:
nfs_destroy_nfspagecache(); nfs_destroy_readpagecache();
out4: out4:
nfs_fs_proc_exit(); nfs_destroy_inodecache();
out5: out5:
nfsiod_stop(); nfs_destroy_nfspagecache();
out6: out6:
nfs_fscache_unregister(); nfs_fs_proc_exit();
out7: out7:
unregister_pernet_subsys(&nfs_net_ops); nfsiod_stop();
out8: out8:
nfs_dns_resolver_destroy(); nfs_fscache_unregister();
out9: out9:
nfs_idmap_quit(); unregister_pernet_subsys(&nfs_net_ops);
out10: out10:
nfs_dns_resolver_destroy();
out11:
return err; return err;
} }
static void __exit exit_nfs_fs(void) static void __exit exit_nfs_fs(void)
{ {
#ifdef CONFIG_NFS_V4
exit_nfs_v4();
#endif
nfs_destroy_directcache(); nfs_destroy_directcache();
nfs_destroy_writepagecache(); nfs_destroy_writepagecache();
nfs_destroy_readpagecache(); nfs_destroy_readpagecache();
...@@ -1717,7 +1725,6 @@ static void __exit exit_nfs_fs(void) ...@@ -1717,7 +1725,6 @@ static void __exit exit_nfs_fs(void)
nfs_fscache_unregister(); nfs_fscache_unregister();
unregister_pernet_subsys(&nfs_net_ops); unregister_pernet_subsys(&nfs_net_ops);
nfs_dns_resolver_destroy(); nfs_dns_resolver_destroy();
nfs_idmap_quit();
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs"); rpc_proc_unregister(&init_net, "nfs");
#endif #endif
......
...@@ -85,6 +85,17 @@ struct nfs_clone_mount { ...@@ -85,6 +85,17 @@ struct nfs_clone_mount {
*/ */
#define NFS_MAX_READDIR_PAGES 8 #define NFS_MAX_READDIR_PAGES 8
struct nfs_client_initdata {
unsigned long init_flags;
const char *hostname;
const struct sockaddr *addr;
size_t addrlen;
const struct nfs_rpc_ops *rpc_ops;
int proto;
u32 minorversion;
struct net *net;
};
/* /*
* In-kernel mount arguments * In-kernel mount arguments
*/ */
...@@ -142,15 +153,36 @@ struct nfs_mount_request { ...@@ -142,15 +153,36 @@ struct nfs_mount_request {
struct net *net; struct net *net;
}; };
struct nfs_mount_info {
void (*fill_super)(struct super_block *, struct nfs_mount_info *);
int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct nfs_parsed_mount_data *parsed;
struct nfs_clone_mount *cloned;
struct nfs_fh *mntfh;
};
extern int nfs_mount(struct nfs_mount_request *info); extern int nfs_mount(struct nfs_mount_request *info);
extern void nfs_umount(const struct nfs_mount_request *info); extern void nfs_umount(const struct nfs_mount_request *info);
/* client.c */ /* client.c */
extern const struct rpc_program nfs_program; extern const struct rpc_program nfs_program;
extern void nfs_clients_init(struct net *net); extern void nfs_clients_init(struct net *net);
extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *, rpc_authflavor_t);
struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
const struct rpc_timeout *, const char *,
rpc_authflavor_t);
int nfs_probe_fsinfo(struct nfs_server *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 *t,
rpc_authflavor_t);
struct nfs_server *nfs_alloc_server(void);
void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *);
extern void nfs_cleanup_cb_ident_idr(struct net *); extern void nfs_cleanup_cb_ident_idr(struct net *);
extern void nfs_put_client(struct nfs_client *); extern void nfs_put_client(struct nfs_client *);
extern void nfs_free_client(struct nfs_client *);
extern struct nfs_client *nfs4_find_client_ident(struct net *, int); extern struct nfs_client *nfs4_find_client_ident(struct net *, int);
extern struct nfs_client * extern struct nfs_client *
nfs4_find_client_sessionid(struct net *, const struct sockaddr *, nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
...@@ -188,6 +220,10 @@ static inline void nfs_fs_proc_exit(void) ...@@ -188,6 +220,10 @@ static inline void nfs_fs_proc_exit(void)
} }
#endif #endif
#ifdef CONFIG_NFS_V4_1
int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
#endif
/* callback_xdr.c */ /* callback_xdr.c */
extern struct svc_version nfs4_callback_version1; extern struct svc_version nfs4_callback_version1;
extern struct svc_version nfs4_callback_version4; extern struct svc_version nfs4_callback_version4;
...@@ -245,6 +281,32 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp, ...@@ -245,6 +281,32 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
/* dir.c */ /* dir.c */
extern int nfs_access_cache_shrinker(struct shrinker *shrink, extern int nfs_access_cache_shrinker(struct shrinker *shrink,
struct shrink_control *sc); struct shrink_control *sc);
struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
int nfs_create(struct inode *, struct dentry *, umode_t, bool);
int nfs_mkdir(struct inode *, struct dentry *, umode_t);
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_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/* file.c */
int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int);
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 *);
ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
int nfs_file_release(struct inode *, struct file *);
int nfs_lock(struct file *, int, struct file_lock *);
int nfs_flock(struct file *, int, struct file_lock *);
ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *,
size_t, unsigned int);
int nfs_check_flags(int);
int nfs_setlease(struct file *, long, struct file_lock **);
/* inode.c */ /* inode.c */
extern struct workqueue_struct *nfsiod_workqueue; extern struct workqueue_struct *nfsiod_workqueue;
...@@ -264,6 +326,16 @@ extern struct file_system_type nfs_xdev_fs_type; ...@@ -264,6 +326,16 @@ extern struct file_system_type nfs_xdev_fs_type;
extern struct file_system_type nfs4_xdev_fs_type; extern struct file_system_type nfs4_xdev_fs_type;
extern struct file_system_type nfs4_referral_fs_type; extern struct file_system_type nfs4_referral_fs_type;
#endif #endif
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(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 *);
void nfs_kill_super(struct super_block *);
void nfs_fill_super(struct super_block *, struct nfs_mount_info *);
extern struct rpc_stat nfs_rpcstat; extern struct rpc_stat nfs_rpcstat;
...@@ -304,12 +376,23 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt, ...@@ -304,12 +376,23 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt,
extern void nfs_read_prepare(struct rpc_task *task, void *calldata); extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr); struct nfs_pgio_header *hdr);
extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops); const struct nfs_pgio_completion_ops *compl_ops);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
extern void nfs_readdata_release(struct nfs_read_data *rdata); extern void nfs_readdata_release(struct nfs_read_data *rdata);
/* super.c */
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
void nfs_umount_begin(struct super_block *);
int nfs_statfs(struct dentry *, struct kstatfs *);
int nfs_show_options(struct seq_file *, struct dentry *);
int nfs_show_devname(struct seq_file *, struct dentry *);
int nfs_show_path(struct seq_file *, struct dentry *);
int nfs_show_stats(struct seq_file *, struct dentry *);
void nfs_put_super(struct super_block *);
int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
/* write.c */ /* write.c */
extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, struct inode *inode, int ioflags,
...@@ -318,7 +401,7 @@ extern struct nfs_write_header *nfs_writehdr_alloc(void); ...@@ -318,7 +401,7 @@ extern struct nfs_write_header *nfs_writehdr_alloc(void);
extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr); struct nfs_pgio_header *hdr);
extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, struct inode *inode, int ioflags,
const struct nfs_pgio_completion_ops *compl_ops); const struct nfs_pgio_completion_ops *compl_ops);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
......
...@@ -106,19 +106,16 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) ...@@ -106,19 +106,16 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
{ {
u32 recvd, count; u32 recvd, count;
size_t hdrlen;
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
goto out_overflow; goto out_overflow;
count = be32_to_cpup(p); count = be32_to_cpup(p);
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; recvd = xdr_read_pages(xdr, count);
recvd = xdr->buf->len - hdrlen;
if (unlikely(count > recvd)) if (unlikely(count > recvd))
goto out_cheating; goto out_cheating;
out: out:
xdr_read_pages(xdr, count);
result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */
result->count = count; result->count = count;
return count; return count;
...@@ -440,7 +437,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) ...@@ -440,7 +437,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
static int decode_path(struct xdr_stream *xdr) static int decode_path(struct xdr_stream *xdr)
{ {
u32 length, recvd; u32 length, recvd;
size_t hdrlen;
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
...@@ -449,12 +445,9 @@ static int decode_path(struct xdr_stream *xdr) ...@@ -449,12 +445,9 @@ static int decode_path(struct xdr_stream *xdr)
length = be32_to_cpup(p); length = be32_to_cpup(p);
if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
goto out_size; goto out_size;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; recvd = xdr_read_pages(xdr, length);
recvd = xdr->buf->len - hdrlen;
if (unlikely(length > recvd)) if (unlikely(length > recvd))
goto out_cheating; goto out_cheating;
xdr_read_pages(xdr, length);
xdr_terminate_string(xdr->buf, length); xdr_terminate_string(xdr->buf, length);
return 0; return 0;
out_size: out_size:
...@@ -972,22 +965,7 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, ...@@ -972,22 +965,7 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
*/ */
static int decode_readdirok(struct xdr_stream *xdr) static int decode_readdirok(struct xdr_stream *xdr)
{ {
u32 recvd, pglen; return xdr_read_pages(xdr, xdr->buf->page_len);
size_t hdrlen;
pglen = xdr->buf->page_len;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
recvd = xdr->buf->len - hdrlen;
if (unlikely(pglen > recvd))
goto out_cheating;
out:
xdr_read_pages(xdr, pglen);
return pglen;
out_cheating:
dprintk("NFS: server cheating in readdir result: "
"pglen %u > recvd %u\n", pglen, recvd);
pglen = recvd;
goto out;
} }
static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
......
...@@ -877,6 +877,46 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) ...@@ -877,6 +877,46 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
} }
static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
{
return 0;
}
static int nfs3_return_delegation(struct inode *inode)
{
nfs_wb_all(inode);
return 0;
}
static 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,
};
static 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 nfs_rpc_ops nfs_v3_clientops = { const struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */ .version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations, .dentry_ops = &nfs_dentry_operations,
...@@ -910,9 +950,11 @@ const struct nfs_rpc_ops nfs_v3_clientops = { ...@@ -910,9 +950,11 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.pathconf = nfs3_proc_pathconf, .pathconf = nfs3_proc_pathconf,
.decode_dirent = nfs3_decode_dirent, .decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup, .read_setup = nfs3_proc_read_setup,
.read_pageio_init = nfs_pageio_init_read,
.read_rpc_prepare = nfs3_proc_read_rpc_prepare, .read_rpc_prepare = nfs3_proc_read_rpc_prepare,
.read_done = nfs3_read_done, .read_done = nfs3_read_done,
.write_setup = nfs3_proc_write_setup, .write_setup = nfs3_proc_write_setup,
.write_pageio_init = nfs_pageio_init_write,
.write_rpc_prepare = nfs3_proc_write_rpc_prepare, .write_rpc_prepare = nfs3_proc_write_rpc_prepare,
.write_done = nfs3_write_done, .write_done = nfs3_write_done,
.commit_setup = nfs3_proc_commit_setup, .commit_setup = nfs3_proc_commit_setup,
...@@ -921,5 +963,9 @@ const struct nfs_rpc_ops nfs_v3_clientops = { ...@@ -921,5 +963,9 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.lock = nfs3_proc_lock, .lock = nfs3_proc_lock,
.clear_acl_cache = nfs3_forget_cached_acls, .clear_acl_cache = nfs3_forget_cached_acls,
.close_context = nfs_close_context, .close_context = nfs_close_context,
.have_delegation = nfs3_have_delegation,
.return_delegation = nfs3_return_delegation,
.alloc_client = nfs_alloc_client,
.init_client = nfs_init_client, .init_client = nfs_init_client,
.free_client = nfs_free_client,
}; };
...@@ -246,7 +246,6 @@ static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, ...@@ -246,7 +246,6 @@ static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
static int decode_nfspath3(struct xdr_stream *xdr) static int decode_nfspath3(struct xdr_stream *xdr)
{ {
u32 recvd, count; u32 recvd, count;
size_t hdrlen;
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
...@@ -255,12 +254,9 @@ static int decode_nfspath3(struct xdr_stream *xdr) ...@@ -255,12 +254,9 @@ static int decode_nfspath3(struct xdr_stream *xdr)
count = be32_to_cpup(p); count = be32_to_cpup(p);
if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
goto out_nametoolong; goto out_nametoolong;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; recvd = xdr_read_pages(xdr, count);
recvd = xdr->buf->len - hdrlen;
if (unlikely(count > recvd)) if (unlikely(count > recvd))
goto out_cheating; goto out_cheating;
xdr_read_pages(xdr, count);
xdr_terminate_string(xdr->buf, count); xdr_terminate_string(xdr->buf, count);
return 0; return 0;
...@@ -329,14 +325,14 @@ static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier) ...@@ -329,14 +325,14 @@ static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
memcpy(p, verifier, NFS3_CREATEVERFSIZE); memcpy(p, verifier, NFS3_CREATEVERFSIZE);
} }
static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier) static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
{ {
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
goto out_overflow; goto out_overflow;
memcpy(verifier, p, NFS3_WRITEVERFSIZE); memcpy(verifier->data, p, NFS3_WRITEVERFSIZE);
return 0; return 0;
out_overflow: out_overflow:
print_overflow_msg(__func__, xdr); print_overflow_msg(__func__, xdr);
...@@ -1587,7 +1583,6 @@ static int decode_read3resok(struct xdr_stream *xdr, ...@@ -1587,7 +1583,6 @@ static int decode_read3resok(struct xdr_stream *xdr,
struct nfs_readres *result) struct nfs_readres *result)
{ {
u32 eof, count, ocount, recvd; u32 eof, count, ocount, recvd;
size_t hdrlen;
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, 4 + 4 + 4); p = xdr_inline_decode(xdr, 4 + 4 + 4);
...@@ -1598,13 +1593,10 @@ static int decode_read3resok(struct xdr_stream *xdr, ...@@ -1598,13 +1593,10 @@ static int decode_read3resok(struct xdr_stream *xdr,
ocount = be32_to_cpup(p++); ocount = be32_to_cpup(p++);
if (unlikely(ocount != count)) if (unlikely(ocount != count))
goto out_mismatch; goto out_mismatch;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; recvd = xdr_read_pages(xdr, count);
recvd = xdr->buf->len - hdrlen;
if (unlikely(count > recvd)) if (unlikely(count > recvd))
goto out_cheating; goto out_cheating;
out: out:
xdr_read_pages(xdr, count);
result->eof = eof; result->eof = eof;
result->count = count; result->count = count;
return count; return count;
...@@ -1676,20 +1668,22 @@ static int decode_write3resok(struct xdr_stream *xdr, ...@@ -1676,20 +1668,22 @@ static int decode_write3resok(struct xdr_stream *xdr,
{ {
__be32 *p; __be32 *p;
p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE); p = xdr_inline_decode(xdr, 4 + 4);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
goto out_overflow; goto out_overflow;
result->count = be32_to_cpup(p++); result->count = be32_to_cpup(p++);
result->verf->committed = be32_to_cpup(p++); result->verf->committed = be32_to_cpup(p++);
if (unlikely(result->verf->committed > NFS_FILE_SYNC)) if (unlikely(result->verf->committed > NFS_FILE_SYNC))
goto out_badvalue; goto out_badvalue;
memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE); if (decode_writeverf3(xdr, &result->verf->verifier))
goto out_eio;
return result->count; return result->count;
out_badvalue: out_badvalue:
dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
return -EIO; return -EIO;
out_overflow: out_overflow:
print_overflow_msg(__func__, xdr); print_overflow_msg(__func__, xdr);
out_eio:
return -EIO; return -EIO;
} }
...@@ -2039,22 +2033,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, ...@@ -2039,22 +2033,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
*/ */
static int decode_dirlist3(struct xdr_stream *xdr) static int decode_dirlist3(struct xdr_stream *xdr)
{ {
u32 recvd, pglen; return xdr_read_pages(xdr, xdr->buf->page_len);
size_t hdrlen;
pglen = xdr->buf->page_len;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
recvd = xdr->buf->len - hdrlen;
if (unlikely(pglen > recvd))
goto out_cheating;
out:
xdr_read_pages(xdr, pglen);
return pglen;
out_cheating:
dprintk("NFS: server cheating in readdir result: "
"pglen %u > recvd %u\n", pglen, recvd);
pglen = recvd;
goto out;
} }
static int decode_readdir3resok(struct xdr_stream *xdr, static int decode_readdir3resok(struct xdr_stream *xdr,
...@@ -2337,7 +2316,7 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, ...@@ -2337,7 +2316,7 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
goto out; goto out;
if (status != NFS3_OK) if (status != NFS3_OK)
goto out_status; goto out_status;
error = decode_writeverf3(xdr, result->verf->verifier); error = decode_writeverf3(xdr, &result->verf->verifier);
out: out:
return error; return error;
out_status: out_status:
...@@ -2364,7 +2343,7 @@ static inline int decode_getacl3resok(struct xdr_stream *xdr, ...@@ -2364,7 +2343,7 @@ static inline int decode_getacl3resok(struct xdr_stream *xdr,
if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
goto out; goto out;
hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; hdrlen = xdr_stream_pos(xdr);
acl = NULL; acl = NULL;
if (result->mask & NFS_ACL) if (result->mask & NFS_ACL)
......
...@@ -200,7 +200,13 @@ struct nfs4_state_maintenance_ops { ...@@ -200,7 +200,13 @@ struct nfs4_state_maintenance_ops {
}; };
extern const struct dentry_operations nfs4_dentry_operations; extern const struct dentry_operations nfs4_dentry_operations;
extern const struct inode_operations nfs4_dir_inode_operations;
/* dir.c */
int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
unsigned, umode_t, int *);
/* write.c */
int nfs4_write_inode(struct inode *, struct writeback_control *);
/* nfs4namespace.c */ /* nfs4namespace.c */
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
...@@ -301,6 +307,10 @@ extern const u32 nfs4_pathconf_bitmap[2]; ...@@ -301,6 +307,10 @@ extern const u32 nfs4_pathconf_bitmap[2];
extern const u32 nfs4_fsinfo_bitmap[3]; extern const u32 nfs4_fsinfo_bitmap[3];
extern const u32 nfs4_fs_locations_bitmap[2]; extern const u32 nfs4_fs_locations_bitmap[2];
void nfs4_free_client(struct nfs_client *);
struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *);
/* nfs4renewd.c */ /* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs_client *); extern void nfs4_schedule_state_renewal(struct nfs_client *);
extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
...@@ -354,6 +364,27 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta ...@@ -354,6 +364,27 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta
extern const nfs4_stateid zero_stateid; extern const nfs4_stateid zero_stateid;
/* nfs4super.c */
struct nfs_mount_info;
struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
int init_nfs_v4(void);
void exit_nfs_v4(void);
/* nfs4sysctl.c */
#ifdef CONFIG_SYSCTL
int nfs4_register_sysctl(void);
void nfs4_unregister_sysctl(void);
#else
static inline int nfs4_register_sysctl(void)
{
return 0;
}
static inline void nfs4_unregister_sysctl(void)
{
}
#endif
/* nfs4xdr.c */ /* nfs4xdr.c */
extern struct rpc_procinfo nfs4_procedures[]; extern struct rpc_procinfo nfs4_procedures[];
......
This diff is collapsed.
/*
* linux/fs/nfs/file.c
*
* Copyright (C) 1992 Rick Sladkey
*/
#include <linux/nfs_fs.h>
#include "internal.h"
#include "pnfs.h"
#define NFSDBG_FACILITY NFSDBG_FILE
static int
nfs4_file_open(struct inode *inode, struct file *filp)
{
struct nfs_open_context *ctx;
struct dentry *dentry = filp->f_path.dentry;
struct dentry *parent = NULL;
struct inode *dir;
unsigned openflags = filp->f_flags;
struct iattr attr;
int err;
BUG_ON(inode != dentry->d_inode);
/*
* If no cached dentry exists or if it's negative, NFSv4 handled the
* opens in ->lookup() or ->create().
*
* We only get this far for a cached positive dentry. We skipped
* revalidation, so handle it here by dropping the dentry and returning
* -EOPENSTALE. The VFS will retry the lookup/create/open.
*/
dprintk("NFS: open file(%s/%s)\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
if ((openflags & O_ACCMODE) == 3)
openflags--;
/* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL);
parent = dget_parent(dentry);
dir = parent->d_inode;
ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
err = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out;
attr.ia_valid = ATTR_OPEN;
if (openflags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
nfs_wb_all(inode);
}
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
switch (err) {
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));
nfs_file_set_open_context(filp, ctx);
err = 0;
out_put_ctx:
put_nfs_open_context(ctx);
out:
dput(parent);
return err;
out_drop:
d_drop(dentry);
err = -EOPENSTALE;
goto out_put_ctx;
}
static int
nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
int ret;
struct inode *inode = file->f_path.dentry->d_inode;
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
mutex_lock(&inode->i_mutex);
ret = nfs_file_fsync_commit(file, start, end, datasync);
if (!ret && !datasync)
/* application has asked for meta-data sync */
ret = pnfs_layoutcommit_inode(inode, true);
mutex_unlock(&inode->i_mutex);
return ret;
}
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 = nfs4_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,
};
...@@ -205,9 +205,9 @@ static int filelayout_async_handle_error(struct rpc_task *task, ...@@ -205,9 +205,9 @@ static int filelayout_async_handle_error(struct rpc_task *task,
case -EPIPE: case -EPIPE:
dprintk("%s DS connection error %d\n", __func__, dprintk("%s DS connection error %d\n", __func__,
task->tk_status); task->tk_status);
if (!filelayout_test_devid_invalid(devid))
_pnfs_return_layout(inode);
filelayout_mark_devid_invalid(devid); filelayout_mark_devid_invalid(devid);
clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
_pnfs_return_layout(inode);
rpc_wake_up(&tbl->slot_tbl_waitq); rpc_wake_up(&tbl->slot_tbl_waitq);
nfs4_ds_disconnect(clp); nfs4_ds_disconnect(clp);
/* fall through */ /* fall through */
...@@ -351,9 +351,9 @@ static void prepare_to_resend_writes(struct nfs_commit_data *data) ...@@ -351,9 +351,9 @@ static void prepare_to_resend_writes(struct nfs_commit_data *data)
struct nfs_page *first = nfs_list_entry(data->pages.next); struct nfs_page *first = nfs_list_entry(data->pages.next);
data->task.tk_status = 0; data->task.tk_status = 0;
memcpy(data->verf.verifier, first->wb_verf.verifier, memcpy(&data->verf.verifier, &first->wb_verf,
sizeof(first->wb_verf.verifier)); sizeof(data->verf.verifier));
data->verf.verifier[0]++; /* ensure verifier mismatch */ data->verf.verifier.data[0]++; /* ensure verifier mismatch */
} }
static int filelayout_commit_done_cb(struct rpc_task *task, static int filelayout_commit_done_cb(struct rpc_task *task,
......
...@@ -728,7 +728,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_fla ...@@ -728,7 +728,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_fla
pdev->layout_type = LAYOUT_NFSV4_1_FILES; pdev->layout_type = LAYOUT_NFSV4_1_FILES;
pdev->pages = pages; pdev->pages = pages;
pdev->pgbase = 0; pdev->pgbase = 0;
pdev->pglen = PAGE_SIZE * max_pages; pdev->pglen = max_resp_sz;
pdev->mincount = 0; pdev->mincount = 0;
rc = nfs4_proc_getdeviceinfo(server, pdev); rc = nfs4_proc_getdeviceinfo(server, pdev);
......
/*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#include <linux/nfs_fs.h>
#include "nfs4_fs.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 = nfs4_proc_get_rootfh(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;
}
This diff is collapsed.
...@@ -1606,10 +1606,15 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) ...@@ -1606,10 +1606,15 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
return -ESERVERFAULT; return -ESERVERFAULT;
/* Lease confirmation error: retry after purging the lease */ /* Lease confirmation error: retry after purging the lease */
ssleep(1); ssleep(1);
case -NFS4ERR_CLID_INUSE:
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_CLIENTID:
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
break; break;
case -NFS4ERR_CLID_INUSE:
pr_err("NFS: Server %s reports our clientid is in use\n",
clp->cl_hostname);
nfs_mark_client_ready(clp, -EPERM);
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
return -EPERM;
case -EACCES: case -EACCES:
if (clp->cl_machine_cred == NULL) if (clp->cl_machine_cred == NULL)
return -EACCES; return -EACCES;
...@@ -1642,7 +1647,7 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) ...@@ -1642,7 +1647,7 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
return 0; return 0;
} }
static int nfs4_reclaim_lease(struct nfs_client *clp) static int nfs4_establish_lease(struct nfs_client *clp)
{ {
struct rpc_cred *cred; struct rpc_cred *cred;
const struct nfs4_state_recovery_ops *ops = const struct nfs4_state_recovery_ops *ops =
...@@ -1655,7 +1660,41 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) ...@@ -1655,7 +1660,41 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
status = ops->establish_clid(clp, cred); status = ops->establish_clid(clp, cred);
put_rpccred(cred); put_rpccred(cred);
if (status != 0) if (status != 0)
return status;
pnfs_destroy_all_layouts(clp);
return 0;
}
/*
* Returns zero or a negative errno. NFS4ERR values are converted
* to local errno values.
*/
static int nfs4_reclaim_lease(struct nfs_client *clp)
{
int status;
status = nfs4_establish_lease(clp);
if (status < 0)
return nfs4_handle_reclaim_lease_error(clp, status);
if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state))
nfs4_state_start_reclaim_nograce(clp);
if (!test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
return 0;
}
static int nfs4_purge_lease(struct nfs_client *clp)
{
int status;
status = nfs4_establish_lease(clp);
if (status < 0)
return nfs4_handle_reclaim_lease_error(clp, status); return nfs4_handle_reclaim_lease_error(clp, status);
clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
nfs4_state_start_reclaim_nograce(clp);
return 0; return 0;
} }
...@@ -1764,6 +1803,8 @@ static int nfs4_reset_session(struct nfs_client *clp) ...@@ -1764,6 +1803,8 @@ static int nfs4_reset_session(struct nfs_client *clp)
struct rpc_cred *cred; struct rpc_cred *cred;
int status; int status;
if (!nfs4_has_session(clp))
return 0;
nfs4_begin_drain_session(clp); nfs4_begin_drain_session(clp);
cred = nfs4_get_exchange_id_cred(clp); cred = nfs4_get_exchange_id_cred(clp);
status = nfs4_proc_destroy_session(clp->cl_session, cred); status = nfs4_proc_destroy_session(clp->cl_session, cred);
...@@ -1792,12 +1833,14 @@ static int nfs4_reset_session(struct nfs_client *clp) ...@@ -1792,12 +1833,14 @@ static int nfs4_reset_session(struct nfs_client *clp)
static int nfs4_recall_slot(struct nfs_client *clp) static int nfs4_recall_slot(struct nfs_client *clp)
{ {
struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table; struct nfs4_slot_table *fc_tbl;
struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs;
struct nfs4_slot *new, *old; struct nfs4_slot *new, *old;
int i; int i;
if (!nfs4_has_session(clp))
return 0;
nfs4_begin_drain_session(clp); nfs4_begin_drain_session(clp);
fc_tbl = &clp->cl_session->fc_slot_table;
new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
GFP_NOFS); GFP_NOFS);
if (!new) if (!new)
...@@ -1810,11 +1853,10 @@ static int nfs4_recall_slot(struct nfs_client *clp) ...@@ -1810,11 +1853,10 @@ static int nfs4_recall_slot(struct nfs_client *clp)
fc_tbl->slots = new; fc_tbl->slots = new;
fc_tbl->max_slots = fc_tbl->target_max_slots; fc_tbl->max_slots = fc_tbl->target_max_slots;
fc_tbl->target_max_slots = 0; fc_tbl->target_max_slots = 0;
fc_attrs->max_reqs = fc_tbl->max_slots; clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
spin_unlock(&fc_tbl->slot_tbl_lock); spin_unlock(&fc_tbl->slot_tbl_lock);
kfree(old); kfree(old);
nfs4_end_drain_session(clp);
return 0; return 0;
} }
...@@ -1823,6 +1865,8 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) ...@@ -1823,6 +1865,8 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
struct rpc_cred *cred; struct rpc_cred *cred;
int ret; int ret;
if (!nfs4_has_session(clp))
return 0;
nfs4_begin_drain_session(clp); nfs4_begin_drain_session(clp);
cred = nfs4_get_exchange_id_cred(clp); cred = nfs4_get_exchange_id_cred(clp);
ret = nfs4_proc_bind_conn_to_session(clp, cred); ret = nfs4_proc_bind_conn_to_session(clp, cred);
...@@ -1857,37 +1901,29 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) ...@@ -1857,37 +1901,29 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
static void nfs4_state_manager(struct nfs_client *clp) static void nfs4_state_manager(struct nfs_client *clp)
{ {
int status = 0; int status = 0;
const char *section = "", *section_sep = "";
/* Ensure exclusive access to NFSv4 state */ /* Ensure exclusive access to NFSv4 state */
do { do {
if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
status = nfs4_reclaim_lease(clp); section = "purge state";
status = nfs4_purge_lease(clp);
if (status < 0) if (status < 0)
goto out_error; goto out_error;
clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); continue;
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
} }
if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
section = "lease expired";
/* We're going to have to re-establish a clientid */ /* We're going to have to re-establish a clientid */
status = nfs4_reclaim_lease(clp); status = nfs4_reclaim_lease(clp);
if (status < 0) if (status < 0)
goto out_error; goto out_error;
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue;
continue;
clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH,
&clp->cl_state))
nfs4_state_start_reclaim_nograce(clp);
else
set_bit(NFS4CLNT_RECLAIM_REBOOT,
&clp->cl_state);
pnfs_destroy_all_layouts(clp);
} }
if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
section = "check lease";
status = nfs4_check_lease(clp); status = nfs4_check_lease(clp);
if (status < 0) if (status < 0)
goto out_error; goto out_error;
...@@ -1896,8 +1932,8 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1896,8 +1932,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
} }
/* Initialize or reset the session */ /* Initialize or reset the session */
if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) {
&& nfs4_has_session(clp)) { section = "reset session";
status = nfs4_reset_session(clp); status = nfs4_reset_session(clp);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
continue; continue;
...@@ -1907,15 +1943,26 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1907,15 +1943,26 @@ static void nfs4_state_manager(struct nfs_client *clp)
/* Send BIND_CONN_TO_SESSION */ /* Send BIND_CONN_TO_SESSION */
if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION,
&clp->cl_state) && nfs4_has_session(clp)) { &clp->cl_state)) {
section = "bind conn to session";
status = nfs4_bind_conn_to_session(clp); status = nfs4_bind_conn_to_session(clp);
if (status < 0) if (status < 0)
goto out_error; goto out_error;
continue; continue;
} }
/* Recall session slots */
if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) {
section = "recall slot";
status = nfs4_recall_slot(clp);
if (status < 0)
goto out_error;
continue;
}
/* First recover reboot state... */ /* First recover reboot state... */
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
section = "reclaim reboot";
status = nfs4_do_reclaim(clp, status = nfs4_do_reclaim(clp,
clp->cl_mvops->reboot_recovery_ops); clp->cl_mvops->reboot_recovery_ops);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
...@@ -1930,6 +1977,7 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1930,6 +1977,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
/* Now recover expired state... */ /* Now recover expired state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
section = "reclaim nograce";
status = nfs4_do_reclaim(clp, status = nfs4_do_reclaim(clp,
clp->cl_mvops->nograce_recovery_ops); clp->cl_mvops->nograce_recovery_ops);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
...@@ -1945,15 +1993,6 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1945,15 +1993,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
nfs_client_return_marked_delegations(clp); nfs_client_return_marked_delegations(clp);
continue; continue;
} }
/* Recall session slots */
if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)
&& nfs4_has_session(clp)) {
status = nfs4_recall_slot(clp);
if (status < 0)
goto out_error;
continue;
}
nfs4_clear_state_manager_bit(clp); nfs4_clear_state_manager_bit(clp);
/* Did we race with an attempt to give us more work? */ /* Did we race with an attempt to give us more work? */
...@@ -1964,8 +2003,11 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1964,8 +2003,11 @@ static void nfs4_state_manager(struct nfs_client *clp)
} while (atomic_read(&clp->cl_count) > 1); } while (atomic_read(&clp->cl_count) > 1);
return; return;
out_error: out_error:
pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s" if (strlen(section))
" with error %d\n", clp->cl_hostname, -status); section_sep = ": ";
pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s"
" with error %d\n", section_sep, section,
clp->cl_hostname, -status);
nfs4_end_drain_session(clp); nfs4_end_drain_session(clp);
nfs4_clear_state_manager_bit(clp); nfs4_clear_state_manager_bit(clp);
} }
......
/*
* Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com>
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/nfs_idmap.h>
#include <linux/nfs4_mount.h>
#include <linux/nfs_fs.h>
#include "internal.h"
#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_VFS
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 struct file_system_type nfs4_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs_fs_mount,
.kill_sb = nfs_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 = nfs_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 = nfs_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 = nfs_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 = nfs_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 = nfs4_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,
};
/*
* Set up an NFS4 superblock
*/
static void nfs4_fill_super(struct super_block *sb,
struct nfs_mount_info *mount_info)
{
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);
}
/*
* 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 *info)
{
struct nfs_mount_info *mount_info = info;
struct nfs_server *server;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
mount_info->fill_super = nfs4_fill_super;
mount_info->set_security = nfs_set_sb_security;
/* Get a volume representation */
server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
if (IS_ERR(server)) {
mntroot = ERR_CAST(server);
goto out;
}
mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
out:
return mntroot;
}
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) + 5;
root_devname = kmalloc(len, GFP_KERNEL);
if (root_devname == NULL)
return ERR_PTR(-ENOMEM);
/* Does hostname needs to be enclosed in brackets? */
if (strchr(hostname, ':'))
snprintf(root_devname, len, "[%s]:/", hostname);
else
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 err;
if (IS_ERR(root_mnt))
return ERR_CAST(root_mnt);
err = nfs_referral_loop_protect();
if (err) {
mntput(root_mnt);
return ERR_PTR(err);
}
dentry = mount_subtree(root_mnt, export_path);
nfs_referral_loop_unprotect();
return dentry;
}
struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct nfs_mount_info *mount_info)
{
char *export_path;
struct vfsmount *root_mnt;
struct dentry *res;
struct nfs_parsed_mount_data *data = mount_info->parsed;
dfprintk(MOUNT, "--> nfs4_try_mount()\n");
mount_info->fill_super = nfs4_fill_super;
export_path = data->nfs_server.export_path;
data->nfs_server.export_path = "/";
root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
data->nfs_server.hostname);
data->nfs_server.export_path = export_path;
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;
}
/*
* 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_mount_info mount_info = {
.fill_super = nfs_clone_super,
.set_security = nfs_clone_sb_security,
.cloned = raw_data,
};
return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
}
static struct dentry *
nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
struct nfs_mount_info mount_info = {
.fill_super = nfs4_fill_super,
.set_security = nfs_clone_sb_security,
.cloned = raw_data,
};
struct nfs_server *server;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
dprintk("--> nfs4_referral_get_sb()\n");
mount_info.mntfh = nfs_alloc_fhandle();
if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
goto out;
/* create a new volume representation */
server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
if (IS_ERR(server)) {
mntroot = ERR_CAST(server);
goto out;
}
mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
out:
nfs_free_fhandle(mount_info.mntfh);
return mntroot;
}
/*
* 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 = 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;
}
int __init init_nfs_v4(void)
{
int err;
err = nfs_idmap_init();
if (err)
goto out;
err = nfs4_register_sysctl();
if (err)
goto out1;
err = register_filesystem(&nfs4_fs_type);
if (err < 0)
goto out2;
return 0;
out2:
nfs4_unregister_sysctl();
out1:
nfs_idmap_quit();
out:
return err;
}
void exit_nfs_v4(void)
{
unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl();
nfs_idmap_quit();
}
/*
* linux/fs/nfs/nfs4sysctl.c
*
* Sysctl interface to NFS v4 parameters
*
* Copyright (c) 2006 Trond Myklebust <Trond.Myklebust@netapp.com>
*/
#include <linux/sysctl.h>
#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>
#include "callback.h"
static const int nfs_set_port_min = 0;
static const int nfs_set_port_max = 65535;
static struct ctl_table_header *nfs4_callback_sysctl_table;
static ctl_table nfs4_cb_sysctls[] = {
{
.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,
},
{
.procname = "idmap_cache_timeout",
.data = &nfs_idmap_cache_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
static ctl_table nfs4_cb_sysctl_dir[] = {
{
.procname = "nfs",
.mode = 0555,
.child = nfs4_cb_sysctls,
},
{ }
};
static ctl_table nfs4_cb_sysctl_root[] = {
{
.procname = "fs",
.mode = 0555,
.child = nfs4_cb_sysctl_dir,
},
{ }
};
int nfs4_register_sysctl(void)
{
nfs4_callback_sysctl_table = register_sysctl_table(nfs4_cb_sysctl_root);
if (nfs4_callback_sysctl_table == NULL)
return -ENOMEM;
return 0;
}
void nfs4_unregister_sysctl(void)
{
unregister_sysctl_table(nfs4_callback_sysctl_table);
nfs4_callback_sysctl_table = NULL;
}
...@@ -1236,7 +1236,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct ...@@ -1236,7 +1236,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct
static inline int nfs4_lock_type(struct file_lock *fl, int block) static inline int nfs4_lock_type(struct file_lock *fl, int block)
{ {
if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) if (fl->fl_type == F_RDLCK)
return block ? NFS4_READW_LT : NFS4_READ_LT; return block ? NFS4_READW_LT : NFS4_READ_LT;
return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
} }
...@@ -3078,7 +3078,7 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) ...@@ -3078,7 +3078,7 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
return -EIO; return -EIO;
} }
static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep)
{ {
__be32 *p; __be32 *p;
...@@ -3086,7 +3086,7 @@ static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, ...@@ -3086,7 +3086,7 @@ static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen,
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
*attrlen = be32_to_cpup(p); *attrlen = be32_to_cpup(p);
*savep = xdr->p; *savep = xdr_stream_pos(xdr);
return 0; return 0;
out_overflow: out_overflow:
print_overflow_msg(__func__, xdr); print_overflow_msg(__func__, xdr);
...@@ -4068,10 +4068,10 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str ...@@ -4068,10 +4068,10 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str
return status; return status;
} }
static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen)
{ {
unsigned int attrwords = XDR_QUADLEN(attrlen); unsigned int attrwords = XDR_QUADLEN(attrlen);
unsigned int nwords = xdr->p - savep; unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2;
if (unlikely(attrwords != nwords)) { if (unlikely(attrwords != nwords)) {
dprintk("%s: server returned incorrect attribute length: " dprintk("%s: server returned incorrect attribute length: "
...@@ -4158,13 +4158,18 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier) ...@@ -4158,13 +4158,18 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier)
return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
} }
static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
{
return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE);
}
static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
{ {
int status; int status;
status = decode_op_hdr(xdr, OP_COMMIT); status = decode_op_hdr(xdr, OP_COMMIT);
if (!status) if (!status)
status = decode_verifier(xdr, res->verf->verifier); status = decode_write_verifier(xdr, &res->verf->verifier);
return status; return status;
} }
...@@ -4193,7 +4198,7 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) ...@@ -4193,7 +4198,7 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
{ {
__be32 *savep; unsigned int savep;
uint32_t attrlen, bitmap[3] = {0}; uint32_t attrlen, bitmap[3] = {0};
int status; int status;
...@@ -4222,7 +4227,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re ...@@ -4222,7 +4227,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re
static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
{ {
__be32 *savep; unsigned int savep;
uint32_t attrlen, bitmap[3] = {0}; uint32_t attrlen, bitmap[3] = {0};
int status; int status;
...@@ -4254,7 +4259,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) ...@@ -4254,7 +4259,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
{ {
__be32 *savep; unsigned int savep;
uint32_t attrlen, bitmap[3] = {0}; uint32_t attrlen, bitmap[3] = {0};
int status; int status;
...@@ -4299,7 +4304,8 @@ static int decode_threshold_hint(struct xdr_stream *xdr, ...@@ -4299,7 +4304,8 @@ static int decode_threshold_hint(struct xdr_stream *xdr,
static int decode_first_threshold_item4(struct xdr_stream *xdr, static int decode_first_threshold_item4(struct xdr_stream *xdr,
struct nfs4_threshold *res) struct nfs4_threshold *res)
{ {
__be32 *p, *savep; __be32 *p;
unsigned int savep;
uint32_t bitmap[3] = {0,}, attrlen; uint32_t bitmap[3] = {0,}, attrlen;
int status; int status;
...@@ -4503,7 +4509,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat ...@@ -4503,7 +4509,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
const struct nfs_server *server) const struct nfs_server *server)
{ {
__be32 *savep; unsigned int savep;
uint32_t attrlen, uint32_t attrlen,
bitmap[3] = {0}; bitmap[3] = {0};
int status; int status;
...@@ -4615,7 +4621,7 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, ...@@ -4615,7 +4621,7 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
{ {
__be32 *savep; unsigned int savep;
uint32_t attrlen, bitmap[3]; uint32_t attrlen, bitmap[3];
int status; int status;
...@@ -4920,9 +4926,8 @@ static int decode_putrootfh(struct xdr_stream *xdr) ...@@ -4920,9 +4926,8 @@ static int decode_putrootfh(struct xdr_stream *xdr)
static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
{ {
struct kvec *iov = req->rq_rcv_buf.head;
__be32 *p; __be32 *p;
uint32_t count, eof, recvd, hdrlen; uint32_t count, eof, recvd;
int status; int status;
status = decode_op_hdr(xdr, OP_READ); status = decode_op_hdr(xdr, OP_READ);
...@@ -4933,15 +4938,13 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_ ...@@ -4933,15 +4938,13 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_
goto out_overflow; goto out_overflow;
eof = be32_to_cpup(p++); eof = be32_to_cpup(p++);
count = be32_to_cpup(p); count = be32_to_cpup(p);
hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; recvd = xdr_read_pages(xdr, count);
recvd = req->rq_rcv_buf.len - hdrlen;
if (count > recvd) { if (count > recvd) {
dprintk("NFS: server cheating in read reply: " dprintk("NFS: server cheating in read reply: "
"count %u > recvd %u\n", count, recvd); "count %u > recvd %u\n", count, recvd);
count = recvd; count = recvd;
eof = 0; eof = 0;
} }
xdr_read_pages(xdr, count);
res->eof = eof; res->eof = eof;
res->count = count; res->count = count;
return 0; return 0;
...@@ -4952,10 +4955,6 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_ ...@@ -4952,10 +4955,6 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_
static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
{ {
struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
struct kvec *iov = rcvbuf->head;
size_t hdrlen;
u32 recvd, pglen = rcvbuf->page_len;
int status; int status;
__be32 verf[2]; __be32 verf[2];
...@@ -4967,22 +4966,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n ...@@ -4967,22 +4966,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
memcpy(verf, readdir->verifier.data, sizeof(verf)); memcpy(verf, readdir->verifier.data, sizeof(verf));
dprintk("%s: verifier = %08x:%08x\n", dprintk("%s: verifier = %08x:%08x\n",
__func__, verf[0], verf[1]); __func__, verf[0], verf[1]);
return xdr_read_pages(xdr, xdr->buf->page_len);
hdrlen = (char *) xdr->p - (char *) iov->iov_base;
recvd = rcvbuf->len - hdrlen;
if (pglen > recvd)
pglen = recvd;
xdr_read_pages(xdr, pglen);
return pglen;
} }
static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
{ {
struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
struct kvec *iov = rcvbuf->head;
size_t hdrlen;
u32 len, recvd; u32 len, recvd;
__be32 *p; __be32 *p;
int status; int status;
...@@ -5000,14 +4989,12 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) ...@@ -5000,14 +4989,12 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
dprintk("nfs: server returned giant symlink!\n"); dprintk("nfs: server returned giant symlink!\n");
return -ENAMETOOLONG; return -ENAMETOOLONG;
} }
hdrlen = (char *) xdr->p - (char *) iov->iov_base; recvd = xdr_read_pages(xdr, len);
recvd = req->rq_rcv_buf.len - hdrlen;
if (recvd < len) { if (recvd < len) {
dprintk("NFS: server cheating in readlink reply: " dprintk("NFS: server cheating in readlink reply: "
"count %u > recvd %u\n", len, recvd); "count %u > recvd %u\n", len, recvd);
return -EIO; return -EIO;
} }
xdr_read_pages(xdr, len);
/* /*
* The XDR encode routine has set things up so that * The XDR encode routine has set things up so that
* the link text will be copied directly into the * the link text will be copied directly into the
...@@ -5063,10 +5050,10 @@ decode_restorefh(struct xdr_stream *xdr) ...@@ -5063,10 +5050,10 @@ decode_restorefh(struct xdr_stream *xdr)
static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
struct nfs_getaclres *res) struct nfs_getaclres *res)
{ {
__be32 *savep, *bm_p; unsigned int savep;
__be32 *bm_p;
uint32_t attrlen, uint32_t attrlen,
bitmap[3] = {0}; bitmap[3] = {0};
struct kvec *iov = req->rq_rcv_buf.head;
int status; int status;
size_t page_len = xdr->buf->page_len; size_t page_len = xdr->buf->page_len;
...@@ -5089,7 +5076,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, ...@@ -5089,7 +5076,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
return -EIO; return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
size_t hdrlen;
/* The bitmap (xdr len + bitmaps) and the attr xdr len words /* The bitmap (xdr len + bitmaps) and the attr xdr len words
* are stored with the acl data to handle the problem of * are stored with the acl data to handle the problem of
...@@ -5098,7 +5084,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, ...@@ -5098,7 +5084,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
/* We ignore &savep and don't do consistency checks on /* We ignore &savep and don't do consistency checks on
* the attr length. Let userspace figure it out.... */ * the attr length. Let userspace figure it out.... */
hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
attrlen += res->acl_data_offset; attrlen += res->acl_data_offset;
if (attrlen > page_len) { if (attrlen > page_len) {
if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
...@@ -5212,13 +5197,12 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) ...@@ -5212,13 +5197,12 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
if (status) if (status)
return status; return status;
p = xdr_inline_decode(xdr, 16); p = xdr_inline_decode(xdr, 8);
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
res->count = be32_to_cpup(p++); res->count = be32_to_cpup(p++);
res->verf->committed = be32_to_cpup(p++); res->verf->committed = be32_to_cpup(p++);
memcpy(res->verf->verifier, p, NFS4_VERIFIER_SIZE); return decode_write_verifier(xdr, &res->verf->verifier);
return 0;
out_overflow: out_overflow:
print_overflow_msg(__func__, xdr); print_overflow_msg(__func__, xdr);
return -EIO; return -EIO;
...@@ -5599,7 +5583,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr, ...@@ -5599,7 +5583,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr,
{ {
__be32 *p; __be32 *p;
int status, i; int status, i;
struct nfs_writeverf verftemp; nfs4_verifier verftemp;
status = decode_op_hdr(xdr, OP_GETDEVICELIST); status = decode_op_hdr(xdr, OP_GETDEVICELIST);
if (status) if (status)
...@@ -5613,7 +5597,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr, ...@@ -5613,7 +5597,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr,
p += 2; p += 2;
/* Read verifier */ /* Read verifier */
p = xdr_decode_opaque_fixed(p, verftemp.verifier, NFS4_VERIFIER_SIZE); p = xdr_decode_opaque_fixed(p, verftemp.data, NFS4_VERIFIER_SIZE);
res->num_devs = be32_to_cpup(p); res->num_devs = be32_to_cpup(p);
...@@ -5707,9 +5691,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, ...@@ -5707,9 +5691,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
__be32 *p; __be32 *p;
int status; int status;
u32 layout_count; u32 layout_count;
struct xdr_buf *rcvbuf = &req->rq_rcv_buf; u32 recvd;
struct kvec *iov = rcvbuf->head;
u32 hdrlen, recvd;
status = decode_op_hdr(xdr, OP_LAYOUTGET); status = decode_op_hdr(xdr, OP_LAYOUTGET);
if (status) if (status)
...@@ -5746,8 +5728,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, ...@@ -5746,8 +5728,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
res->type, res->type,
res->layoutp->len); res->layoutp->len);
hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; recvd = xdr_read_pages(xdr, res->layoutp->len);
recvd = req->rq_rcv_buf.len - hdrlen;
if (res->layoutp->len > recvd) { if (res->layoutp->len > recvd) {
dprintk("NFS: server cheating in layoutget reply: " dprintk("NFS: server cheating in layoutget reply: "
"layout len %u > recvd %u\n", "layout len %u > recvd %u\n",
...@@ -5755,8 +5736,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, ...@@ -5755,8 +5736,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
return -EINVAL; return -EINVAL;
} }
xdr_read_pages(xdr, res->layoutp->len);
if (layout_count > 1) { if (layout_count > 1) {
/* We only handle a length one array at the moment. Any /* We only handle a length one array at the moment. Any
* further entries are just ignored. Note that this means * further entries are just ignored. Note that this means
...@@ -7103,6 +7082,7 @@ static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, ...@@ -7103,6 +7082,7 @@ static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
int plus) int plus)
{ {
unsigned int savep;
uint32_t bitmap[3] = {0}; uint32_t bitmap[3] = {0};
uint32_t len; uint32_t len;
__be32 *p = xdr_inline_decode(xdr, 4); __be32 *p = xdr_inline_decode(xdr, 4);
...@@ -7141,7 +7121,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, ...@@ -7141,7 +7121,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
if (decode_attr_bitmap(xdr, bitmap) < 0) if (decode_attr_bitmap(xdr, bitmap) < 0)
goto out_overflow; goto out_overflow;
if (decode_attr_length(xdr, &len, &p) < 0) if (decode_attr_length(xdr, &len, &savep) < 0)
goto out_overflow; goto out_overflow;
if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
......
...@@ -651,7 +651,14 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -651,7 +651,14 @@ send_layoutget(struct pnfs_layout_hdr *lo,
return NULL; return NULL;
} }
/* Initiates a LAYOUTRETURN(FILE) */ /*
* Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
* when the layout segment list is empty.
*
* Note that a pnfs_layout_hdr can exist with an empty layout segment
* list when LAYOUTGET has failed, or when LAYOUTGET succeeded, but the
* deviceid is marked invalid.
*/
int int
_pnfs_return_layout(struct inode *ino) _pnfs_return_layout(struct inode *ino)
{ {
...@@ -660,22 +667,31 @@ _pnfs_return_layout(struct inode *ino) ...@@ -660,22 +667,31 @@ _pnfs_return_layout(struct inode *ino)
LIST_HEAD(tmp_list); LIST_HEAD(tmp_list);
struct nfs4_layoutreturn *lrp; struct nfs4_layoutreturn *lrp;
nfs4_stateid stateid; nfs4_stateid stateid;
int status = 0; int status = 0, empty;
dprintk("--> %s\n", __func__); dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
spin_lock(&ino->i_lock); spin_lock(&ino->i_lock);
lo = nfsi->layout; lo = nfsi->layout;
if (!lo) { if (!lo || pnfs_test_layout_returned(lo)) {
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
dprintk("%s: no layout to return\n", __func__); dprintk("NFS: %s no layout to return\n", __func__);
return status; goto out;
} }
stateid = nfsi->layout->plh_stateid; stateid = nfsi->layout->plh_stateid;
/* Reference matched in nfs4_layoutreturn_release */ /* Reference matched in nfs4_layoutreturn_release */
get_layout_hdr(lo); get_layout_hdr(lo);
empty = list_empty(&lo->plh_segs);
mark_matching_lsegs_invalid(lo, &tmp_list, NULL); mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
/* Don't send a LAYOUTRETURN if list was initially empty */
if (empty) {
spin_unlock(&ino->i_lock);
put_layout_hdr(lo);
dprintk("NFS: %s no layout segments to return\n", __func__);
goto out;
}
lo->plh_block_lgets++; lo->plh_block_lgets++;
pnfs_mark_layout_returned(lo);
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
pnfs_free_lseg_list(&tmp_list); pnfs_free_lseg_list(&tmp_list);
...@@ -686,6 +702,7 @@ _pnfs_return_layout(struct inode *ino) ...@@ -686,6 +702,7 @@ _pnfs_return_layout(struct inode *ino)
status = -ENOMEM; status = -ENOMEM;
set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags); set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);
set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags);
pnfs_clear_layout_returned(lo);
put_layout_hdr(lo); put_layout_hdr(lo);
goto out; goto out;
} }
...@@ -1075,6 +1092,10 @@ pnfs_update_layout(struct inode *ino, ...@@ -1075,6 +1092,10 @@ pnfs_update_layout(struct inode *ino,
get_layout_hdr(lo); get_layout_hdr(lo);
if (list_empty(&lo->plh_segs)) if (list_empty(&lo->plh_segs))
first = true; first = true;
/* Enable LAYOUTRETURNs */
pnfs_clear_layout_returned(lo);
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
if (first) { if (first) {
/* The lo must be on the clp list if there is any /* The lo must be on the clp list if there is any
...@@ -1209,7 +1230,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page * ...@@ -1209,7 +1230,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
} }
EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
bool void
pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
{ {
...@@ -1217,13 +1238,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, ...@@ -1217,13 +1238,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
if (ld == NULL) if (ld == NULL)
return false; nfs_pageio_init_read(pgio, inode, compl_ops);
nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, else
server->rsize, 0); nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0);
return true;
} }
bool void
pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
int ioflags, int ioflags,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
...@@ -1232,10 +1252,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, ...@@ -1232,10 +1252,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
if (ld == NULL) if (ld == NULL)
return false; nfs_pageio_init_write(pgio, inode, ioflags, compl_ops);
nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, else
server->wsize, ioflags); nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, server->wsize, ioflags);
return true;
} }
bool bool
...@@ -1272,7 +1291,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode, ...@@ -1272,7 +1291,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode,
LIST_HEAD(failed); LIST_HEAD(failed);
/* Resend all requests through the MDS */ /* Resend all requests through the MDS */
nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE, compl_ops); nfs_pageio_init_write(&pgio, inode, FLUSH_STABLE, compl_ops);
while (!list_empty(head)) { while (!list_empty(head)) {
struct nfs_page *req = nfs_list_entry(head->next); struct nfs_page *req = nfs_list_entry(head->next);
...@@ -1427,7 +1446,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode, ...@@ -1427,7 +1446,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode,
LIST_HEAD(failed); LIST_HEAD(failed);
/* Resend all requests through the MDS */ /* Resend all requests through the MDS */
nfs_pageio_init_read_mds(&pgio, inode, compl_ops); nfs_pageio_init_read(&pgio, inode, compl_ops);
while (!list_empty(head)) { while (!list_empty(head)) {
struct nfs_page *req = nfs_list_entry(head->next); struct nfs_page *req = nfs_list_entry(head->next);
......
...@@ -64,6 +64,7 @@ enum { ...@@ -64,6 +64,7 @@ enum {
NFS_LAYOUT_ROC, /* some lseg had roc bit set */ NFS_LAYOUT_ROC, /* some lseg had roc bit set */
NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */
NFS_LAYOUT_INVALID, /* layout is being destroyed */ NFS_LAYOUT_INVALID, /* layout is being destroyed */
NFS_LAYOUT_RETURNED, /* layout has already been returned */
}; };
enum layoutdriver_policy_flags { enum layoutdriver_policy_flags {
...@@ -178,9 +179,9 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); ...@@ -178,9 +179,9 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
void get_layout_hdr(struct pnfs_layout_hdr *lo); void get_layout_hdr(struct pnfs_layout_hdr *lo);
void put_lseg(struct pnfs_layout_segment *lseg); void put_lseg(struct pnfs_layout_segment *lseg);
bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *,
const struct nfs_pgio_completion_ops *); const struct nfs_pgio_completion_ops *);
bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *,
int, const struct nfs_pgio_completion_ops *); int, const struct nfs_pgio_completion_ops *);
void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
...@@ -255,6 +256,24 @@ struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node * ...@@ -255,6 +256,24 @@ struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *
bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
void nfs4_deviceid_purge_client(const struct nfs_client *); void nfs4_deviceid_purge_client(const struct nfs_client *);
static inline void
pnfs_mark_layout_returned(struct pnfs_layout_hdr *lo)
{
set_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}
static inline void
pnfs_clear_layout_returned(struct pnfs_layout_hdr *lo)
{
clear_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}
static inline bool
pnfs_test_layout_returned(struct pnfs_layout_hdr *lo)
{
return test_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}
static inline int lo_fail_bit(u32 iomode) static inline int lo_fail_bit(u32 iomode)
{ {
return iomode == IOMODE_RW ? return iomode == IOMODE_RW ?
...@@ -438,16 +457,16 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s) ...@@ -438,16 +457,16 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
{ {
} }
static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, static inline void pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
{ {
return false; nfs_pageio_init_read(pgio, inode, compl_ops);
} }
static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags, static inline void pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
{ {
return false; nfs_pageio_init_write(pgio, inode, ioflags, compl_ops);
} }
static inline int static inline int
......
...@@ -734,6 +734,38 @@ static int nfs_lock_check_bounds(const struct file_lock *fl) ...@@ -734,6 +734,38 @@ static int nfs_lock_check_bounds(const struct file_lock *fl)
return -EINVAL; return -EINVAL;
} }
static int nfs_have_delegation(struct inode *inode, fmode_t flags)
{
return 0;
}
static int nfs_return_delegation(struct inode *inode)
{
nfs_wb_all(inode);
return 0;
}
static 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,
};
static const struct inode_operations nfs_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
};
const struct nfs_rpc_ops nfs_v2_clientops = { const struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */ .version = 2, /* protocol version */
.dentry_ops = &nfs_dentry_operations, .dentry_ops = &nfs_dentry_operations,
...@@ -767,9 +799,11 @@ const struct nfs_rpc_ops nfs_v2_clientops = { ...@@ -767,9 +799,11 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.pathconf = nfs_proc_pathconf, .pathconf = nfs_proc_pathconf,
.decode_dirent = nfs2_decode_dirent, .decode_dirent = nfs2_decode_dirent,
.read_setup = nfs_proc_read_setup, .read_setup = nfs_proc_read_setup,
.read_pageio_init = nfs_pageio_init_read,
.read_rpc_prepare = nfs_proc_read_rpc_prepare, .read_rpc_prepare = nfs_proc_read_rpc_prepare,
.read_done = nfs_read_done, .read_done = nfs_read_done,
.write_setup = nfs_proc_write_setup, .write_setup = nfs_proc_write_setup,
.write_pageio_init = nfs_pageio_init_write,
.write_rpc_prepare = nfs_proc_write_rpc_prepare, .write_rpc_prepare = nfs_proc_write_rpc_prepare,
.write_done = nfs_write_done, .write_done = nfs_write_done,
.commit_setup = nfs_proc_commit_setup, .commit_setup = nfs_proc_commit_setup,
...@@ -777,5 +811,9 @@ const struct nfs_rpc_ops nfs_v2_clientops = { ...@@ -777,5 +811,9 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.lock = nfs_proc_lock, .lock = nfs_proc_lock,
.lock_check_bounds = nfs_lock_check_bounds, .lock_check_bounds = nfs_lock_check_bounds,
.close_context = nfs_close_context, .close_context = nfs_close_context,
.have_delegation = nfs_have_delegation,
.return_delegation = nfs_return_delegation,
.alloc_client = nfs_alloc_client,
.init_client = nfs_init_client, .init_client = nfs_init_client,
.free_client = nfs_free_client,
}; };
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <linux/nfs_page.h> #include <linux/nfs_page.h>
#include <linux/module.h> #include <linux/module.h>
#include "pnfs.h"
#include "nfs4_fs.h" #include "nfs4_fs.h"
#include "internal.h" #include "internal.h"
#include "iostat.h" #include "iostat.h"
...@@ -108,7 +106,7 @@ int nfs_return_empty_page(struct page *page) ...@@ -108,7 +106,7 @@ int nfs_return_empty_page(struct page *page)
return 0; return 0;
} }
void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
{ {
...@@ -123,14 +121,6 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) ...@@ -123,14 +121,6 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
} }
EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops)
{
if (!pnfs_pageio_init_read(pgio, inode, compl_ops))
nfs_pageio_init_read_mds(pgio, inode, compl_ops);
}
int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
struct page *page) struct page *page)
{ {
...@@ -149,7 +139,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, ...@@ -149,7 +139,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
if (len < PAGE_CACHE_SIZE) if (len < PAGE_CACHE_SIZE)
zero_user_segment(page, len, PAGE_CACHE_SIZE); zero_user_segment(page, len, PAGE_CACHE_SIZE);
nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); NFS_PROTO(inode)->read_pageio_init(&pgio, inode, &nfs_async_read_completion_ops);
nfs_pageio_add_request(&pgio, new); nfs_pageio_add_request(&pgio, new);
nfs_pageio_complete(&pgio); nfs_pageio_complete(&pgio);
NFS_I(inode)->read_io += pgio.pg_bytes_written; NFS_I(inode)->read_io += pgio.pg_bytes_written;
...@@ -652,7 +642,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, ...@@ -652,7 +642,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
if (ret == 0) if (ret == 0)
goto read_complete; /* all pages were read */ goto read_complete; /* all pages were read */
nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); NFS_PROTO(inode)->read_pageio_init(&pgio, inode, &nfs_async_read_completion_ops);
ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
......
This diff is collapsed.
...@@ -9,37 +9,11 @@ ...@@ -9,37 +9,11 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nfs4.h>
#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.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 struct ctl_table_header *nfs_callback_sysctl_table;
static ctl_table nfs_cb_sysctls[] = { 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,
},
{
.procname = "idmap_cache_timeout",
.data = &nfs_idmap_cache_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
#endif
{ {
.procname = "nfs_mountpoint_timeout", .procname = "nfs_mountpoint_timeout",
.data = &nfs_mountpoint_expiry_timeout, .data = &nfs_mountpoint_expiry_timeout,
......
...@@ -501,7 +501,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) ...@@ -501,7 +501,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
(unsigned long long)NFS_FILEID(dentry->d_inode)); (unsigned long long)NFS_FILEID(dentry->d_inode));
/* Return delegation in anticipation of the rename */ /* Return delegation in anticipation of the rename */
nfs_inode_return_delegation(dentry->d_inode); NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode);
sdentry = NULL; sdentry = NULL;
do { do {
......
...@@ -336,8 +336,10 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc ...@@ -336,8 +336,10 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
struct nfs_pageio_descriptor pgio; struct nfs_pageio_descriptor pgio;
int err; int err;
nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc), NFS_PROTO(page->mapping->host)->write_pageio_init(&pgio,
&nfs_async_write_completion_ops); page->mapping->host,
wb_priority(wbc),
&nfs_async_write_completion_ops);
err = nfs_do_writepage(page, wbc, &pgio); err = nfs_do_writepage(page, wbc, &pgio);
nfs_pageio_complete(&pgio); nfs_pageio_complete(&pgio);
if (err < 0) if (err < 0)
...@@ -380,8 +382,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) ...@@ -380,8 +382,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), NFS_PROTO(inode)->write_pageio_init(&pgio, inode, wb_priority(wbc), &nfs_async_write_completion_ops);
&nfs_async_write_completion_ops);
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
nfs_pageio_complete(&pgio); nfs_pageio_complete(&pgio);
...@@ -410,7 +411,7 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) ...@@ -410,7 +411,7 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
nfs_lock_request(req); nfs_lock_request(req);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
inode->i_version++; inode->i_version++;
set_bit(PG_MAPPED, &req->wb_flags); set_bit(PG_MAPPED, &req->wb_flags);
SetPagePrivate(req->wb_page); SetPagePrivate(req->wb_page);
...@@ -620,7 +621,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) ...@@ -620,7 +621,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
goto next; goto next;
} }
if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) {
memcpy(&req->wb_verf, hdr->verf, sizeof(req->wb_verf)); memcpy(&req->wb_verf, &hdr->verf->verifier, sizeof(req->wb_verf));
nfs_mark_request_commit(req, hdr->lseg, &cinfo); nfs_mark_request_commit(req, hdr->lseg, &cinfo);
goto next; goto next;
} }
...@@ -1202,7 +1203,7 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = { ...@@ -1202,7 +1203,7 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = {
.pg_doio = nfs_generic_pg_writepages, .pg_doio = nfs_generic_pg_writepages,
}; };
void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, struct inode *inode, int ioflags,
const struct nfs_pgio_completion_ops *compl_ops) const struct nfs_pgio_completion_ops *compl_ops)
{ {
...@@ -1217,13 +1218,6 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) ...@@ -1217,13 +1218,6 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
} }
EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags,
const struct nfs_pgio_completion_ops *compl_ops)
{
if (!pnfs_pageio_init_write(pgio, inode, ioflags, compl_ops))
nfs_pageio_init_write_mds(pgio, inode, ioflags, compl_ops);
}
void nfs_write_prepare(struct rpc_task *task, void *calldata) void nfs_write_prepare(struct rpc_task *task, void *calldata)
{ {
...@@ -1547,7 +1541,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) ...@@ -1547,7 +1541,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
/* Okay, COMMIT succeeded, apparently. Check the verifier /* Okay, COMMIT succeeded, apparently. Check the verifier
* returned by the server against all stored verfs. */ * returned by the server against all stored verfs. */
if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { if (!memcmp(&req->wb_verf, &data->verf.verifier, sizeof(req->wb_verf))) {
/* We have a match */ /* We have a match */
nfs_inode_remove_request(req); nfs_inode_remove_request(req);
dprintk(" OK\n"); dprintk(" OK\n");
...@@ -1677,9 +1671,14 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr ...@@ -1677,9 +1671,14 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{ {
int ret; return nfs_commit_unstable_pages(inode, wbc);
}
#ifdef CONFIG_NFS_V4
int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
{
int ret = nfs_write_inode(inode, wbc);
ret = nfs_commit_unstable_pages(inode, wbc);
if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) {
int status; int status;
bool sync = true; bool sync = true;
...@@ -1693,6 +1692,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) ...@@ -1693,6 +1692,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
} }
return ret; return ret;
} }
#endif
/* /*
* flush the inode to disk. * flush the inode to disk.
......
...@@ -427,10 +427,6 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/ ...@@ -427,10 +427,6 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
/* /*
* linux/fs/nfs/file.c * linux/fs/nfs/file.c
*/ */
extern const struct inode_operations nfs_file_inode_operations;
#ifdef CONFIG_NFS_V3
extern const struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_file_operations; extern const struct file_operations nfs_file_operations;
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
extern const struct file_operations nfs4_file_operations; extern const struct file_operations nfs4_file_operations;
...@@ -485,10 +481,6 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb, ...@@ -485,10 +481,6 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
/* /*
* linux/fs/nfs/dir.c * linux/fs/nfs/dir.c
*/ */
extern const struct inode_operations nfs_dir_inode_operations;
#ifdef 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 file_operations nfs_dir_operations;
extern const struct dentry_operations nfs_dentry_operations; extern const struct dentry_operations nfs_dentry_operations;
......
...@@ -69,10 +69,9 @@ struct nfs_client { ...@@ -69,10 +69,9 @@ struct nfs_client {
struct idmap * cl_idmap; struct idmap * cl_idmap;
/* Our own IP address, as a null-terminated string. /* Our own IP address, as a null-terminated string.
* This is used to generate the clientid, and the callback address. * This is used to generate the mv0 callback address.
*/ */
char cl_ipaddr[48]; char cl_ipaddr[48];
unsigned char cl_id_uniquifier;
u32 cl_cb_ident; /* v4.0 callback identifier */ u32 cl_cb_ident; /* v4.0 callback identifier */
const struct nfs4_minor_version_ops *cl_mvops; const struct nfs4_minor_version_ops *cl_mvops;
......
...@@ -42,7 +42,7 @@ struct nfs_page { ...@@ -42,7 +42,7 @@ struct nfs_page {
wb_bytes; /* Length of request */ wb_bytes; /* Length of request */
struct kref wb_kref; /* reference count */ struct kref wb_kref; /* reference count */
unsigned long wb_flags; unsigned long wb_flags;
struct nfs_writeverf wb_verf; /* Commit cookie */ struct nfs_write_verifier wb_verf; /* Commit cookie */
}; };
struct nfs_pageio_descriptor; struct nfs_pageio_descriptor;
......
...@@ -514,9 +514,13 @@ struct nfs_writeargs { ...@@ -514,9 +514,13 @@ struct nfs_writeargs {
struct nfs4_sequence_args seq_args; struct nfs4_sequence_args seq_args;
}; };
struct nfs_write_verifier {
char data[8];
};
struct nfs_writeverf { struct nfs_writeverf {
struct nfs_write_verifier verifier;
enum nfs3_stable_how committed; enum nfs3_stable_how committed;
__be32 verifier[2];
}; };
struct nfs_writeres { struct nfs_writeres {
...@@ -1349,6 +1353,8 @@ struct nfs_renamedata { ...@@ -1349,6 +1353,8 @@ struct nfs_renamedata {
struct nfs_access_entry; struct nfs_access_entry;
struct nfs_client; struct nfs_client;
struct rpc_timeout; struct rpc_timeout;
struct nfs_client_initdata;
struct nfs_pageio_descriptor;
/* /*
* RPC procedure vector for NFSv2/NFSv3 demuxing * RPC procedure vector for NFSv2/NFSv3 demuxing
...@@ -1402,9 +1408,13 @@ struct nfs_rpc_ops { ...@@ -1402,9 +1408,13 @@ struct nfs_rpc_ops {
int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); int (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int); int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int);
void (*read_setup) (struct nfs_read_data *, struct rpc_message *); void (*read_setup) (struct nfs_read_data *, struct rpc_message *);
void (*read_pageio_init)(struct nfs_pageio_descriptor *, struct inode *,
const struct nfs_pgio_completion_ops *);
void (*read_rpc_prepare)(struct rpc_task *, struct nfs_read_data *); void (*read_rpc_prepare)(struct rpc_task *, struct nfs_read_data *);
int (*read_done) (struct rpc_task *, struct nfs_read_data *); int (*read_done) (struct rpc_task *, struct nfs_read_data *);
void (*write_setup) (struct nfs_write_data *, struct rpc_message *); void (*write_setup) (struct nfs_write_data *, struct rpc_message *);
void (*write_pageio_init)(struct nfs_pageio_descriptor *, struct inode *, int,
const struct nfs_pgio_completion_ops *);
void (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *); void (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *);
int (*write_done) (struct rpc_task *, struct nfs_write_data *); int (*write_done) (struct rpc_task *, struct nfs_write_data *);
void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *); void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
...@@ -1418,9 +1428,13 @@ struct nfs_rpc_ops { ...@@ -1418,9 +1428,13 @@ struct nfs_rpc_ops {
struct nfs_open_context *ctx, struct nfs_open_context *ctx,
int open_flags, int open_flags,
struct iattr *iattr); struct iattr *iattr);
int (*have_delegation)(struct inode *, fmode_t);
int (*return_delegation)(struct inode *);
struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);
struct nfs_client * struct nfs_client *
(*init_client) (struct nfs_client *, const struct rpc_timeout *, (*init_client) (struct nfs_client *, const struct rpc_timeout *,
const char *, rpc_authflavor_t); const char *, rpc_authflavor_t);
void (*free_client) (struct nfs_client *);
}; };
/* /*
......
...@@ -101,6 +101,7 @@ struct rpc_authops { ...@@ -101,6 +101,7 @@ struct rpc_authops {
struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
int (*pipes_create)(struct rpc_auth *); int (*pipes_create)(struct rpc_auth *);
void (*pipes_destroy)(struct rpc_auth *); void (*pipes_destroy)(struct rpc_auth *);
int (*list_pseudoflavors)(rpc_authflavor_t *, int);
}; };
struct rpc_credops { struct rpc_credops {
...@@ -135,6 +136,7 @@ int rpcauth_register(const struct rpc_authops *); ...@@ -135,6 +136,7 @@ int rpcauth_register(const struct rpc_authops *);
int rpcauth_unregister(const struct rpc_authops *); int rpcauth_unregister(const struct rpc_authops *);
struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
void rpcauth_release(struct rpc_auth *); void rpcauth_release(struct rpc_auth *);
int rpcauth_list_flavors(rpc_authflavor_t *, int);
struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int); struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1619,6 +1619,7 @@ static const struct rpc_authops authgss_ops = { ...@@ -1619,6 +1619,7 @@ static const struct rpc_authops authgss_ops = {
.crcreate = gss_create_cred, .crcreate = gss_create_cred,
.pipes_create = gss_pipes_dentries_create, .pipes_create = gss_pipes_dentries_create,
.pipes_destroy = gss_pipes_dentries_destroy, .pipes_destroy = gss_pipes_dentries_destroy,
.list_pseudoflavors = gss_mech_list_pseudoflavors,
}; };
static const struct rpc_credops gss_credops = { static const struct rpc_credops gss_credops = {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment