From: Bryan Schumaker <[email protected]>
These patches begin splitting out various NFS features from the generic
client. Most of the time I create a new {rpc, file, super} operation
pointing to an NFS version specific implementation, such as NFS v4
delegation functions which don't need to do as much in the v2 or v3 case.
These patches are a prerequisite for my modularization patches. The idea
is that each NFS module can have its own self-contained implementation for
each feature.
Questions and comments are appreciated!
- Bryan
Bryan Schumaker (10):
NFS: set_pnfs_layoutdriver() from nfs4_proc_fsinfo()
NFS: Use nfs4_destroy_server() to clean up NFS v4
NFS: Create a v4-specific fsync function
NFS: Create a have_delegation rpc_op
NFS: Create a return_delegation rpc op
NFS: Create a free_client rpc_op
NFS: Create an alloc_client rpc_op
NFS: Create an read_pageio_init() function
NFS: Create an write_pageio_init() function
NFS: Create custom NFS v4 write_inode() function
fs/nfs/client.c | 62 +++++++++++++++++++++++++++++--------------------
fs/nfs/delegation.c | 7 +++---
fs/nfs/delegation.h | 19 ++++-----------
fs/nfs/dir.c | 10 ++++----
fs/nfs/file.c | 46 +++++++++++++++++++++++++++---------
fs/nfs/inode.c | 4 ++--
fs/nfs/internal.h | 6 +++--
fs/nfs/nfs3proc.c | 17 ++++++++++++++
fs/nfs/nfs4_fs.h | 7 ++++++
fs/nfs/nfs4proc.c | 24 ++++++++++++++-----
fs/nfs/pnfs.c | 22 ++++++++----------
fs/nfs/pnfs.h | 12 +++++-----
fs/nfs/proc.c | 17 ++++++++++++++
fs/nfs/read.c | 16 +++----------
fs/nfs/super.c | 25 +++++---------------
fs/nfs/unlink.c | 2 +-
fs/nfs/write.c | 31 +++++++++++++------------
include/linux/nfs_xdr.h | 10 ++++++++
18 files changed, 201 insertions(+), 136 deletions(-)
--
1.7.11
From: Bryan Schumaker <[email protected]>
v2 and v3 don't need to worry about doing a pnfs layoutcommit.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/file.c | 40 ++++++++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index a6708e6b..8941ac4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -265,7 +265,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* fall back to doing a synchronous write.
*/
static 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 nfs_open_context *ctx = nfs_file_open_context(file);
@@ -277,9 +277,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,
datasync);
- ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
- mutex_lock(&inode->i_mutex);
-
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC);
@@ -290,10 +287,20 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
ret = xchg(&ctx->error, 0);
if (!ret && status < 0)
ret = status;
- if (!ret && !datasync)
- /* application has asked for meta-data sync */
- ret = pnfs_layoutcommit_inode(inode, true);
+ return ret;
+}
+
+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);
+
return ret;
}
@@ -956,6 +963,23 @@ out_drop:
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,
@@ -966,7 +990,7 @@ const struct file_operations nfs4_file_operations = {
.open = nfs4_file_open,
.flush = nfs_file_flush,
.release = nfs_file_release,
- .fsync = nfs_file_fsync,
+ .fsync = nfs4_file_fsync,
.lock = nfs_lock,
.flock = nfs_flock,
.splice_read = nfs_file_splice_read,
--
1.7.11
From: Bryan Schumaker <[email protected]>
Delegations are a v4 feature, so push return_delegation out of the
generic client by creating a new rpc_op and renaming the old function to
be in the nfs v4 "namespace"
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/delegation.c | 2 +-
fs/nfs/delegation.h | 8 +-------
fs/nfs/dir.c | 8 ++++----
fs/nfs/inode.c | 2 +-
fs/nfs/nfs3proc.c | 7 +++++++
fs/nfs/nfs4proc.c | 7 ++++---
fs/nfs/proc.c | 7 +++++++
fs/nfs/unlink.c | 2 +-
include/linux/nfs_xdr.h | 1 +
9 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 36c7c64..81c5eec 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -388,7 +388,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
*
* Returns zero on success, or a negative errno value.
*/
-int nfs_inode_return_delegation(struct inode *inode)
+int nfs4_inode_return_delegation(struct inode *inode)
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index d134fc5..1f3ccd9 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -33,7 +33,7 @@ enum {
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int nfs_inode_return_delegation(struct inode *inode);
+int nfs4_inode_return_delegation(struct inode *inode);
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
void nfs_inode_return_delegation_noreclaim(struct inode *inode);
@@ -58,12 +58,6 @@ bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
int nfs4_have_delegation(struct inode *inode, fmode_t flags);
-#else
-static inline int nfs_inode_return_delegation(struct inode *inode)
-{
- nfs_wb_all(inode);
- return 0;
-}
#endif
static inline int nfs_have_delegated_attributes(struct inode *inode)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 4a3e23a..68e451f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1778,7 +1778,7 @@ static int nfs_safe_remove(struct dentry *dentry)
}
if (inode != NULL) {
- nfs_inode_return_delegation(inode);
+ NFS_PROTO(inode)->return_delegation(inode);
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
/* The VFS may want to delete this inode */
if (error == 0)
@@ -1906,7 +1906,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,
dentry->d_parent->d_name.name, dentry->d_name.name);
- nfs_inode_return_delegation(inode);
+ NFS_PROTO(inode)->return_delegation(inode);
d_drop(dentry);
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
@@ -1990,9 +1990,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)
- 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,
new_dir, &new_dentry->d_name);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0f0b928..28c9ebb 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -430,7 +430,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
* Return any delegations if we're going to change ACLs
*/
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);
if (error == 0)
nfs_refresh_inode(inode, fattr);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 08f8326..4749a32 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -882,6 +882,12 @@ 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;
+}
+
const struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
@@ -927,5 +933,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.clear_acl_cache = nfs3_forget_cached_acls,
.close_context = nfs_close_context,
.have_delegation = nfs3_have_delegation,
+ .return_delegation = nfs3_return_delegation,
.init_client = nfs_init_client,
};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 993d6ec..b2cd0f1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -295,7 +295,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
return 0;
case -NFS4ERR_OPENMODE:
if (inode && nfs4_have_delegation(inode, FMODE_READ)) {
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
exception->retry = 1;
return 0;
}
@@ -1065,7 +1065,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
return;
}
rcu_read_unlock();
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
}
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
@@ -3868,7 +3868,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
if (i < 0)
return i;
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
/*
@@ -6803,6 +6803,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.close_context = nfs4_close_context,
.open_context = nfs4_atomic_open,
.have_delegation = nfs4_have_delegation,
+ .return_delegation = nfs4_inode_return_delegation,
.init_client = nfs4_init_client,
};
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 4aed3dd..1663293 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -739,6 +739,12 @@ 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;
+}
+
const struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
@@ -783,5 +789,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.lock_check_bounds = nfs_lock_check_bounds,
.close_context = nfs_close_context,
.have_delegation = nfs_have_delegation,
+ .return_delegation = nfs_return_delegation,
.init_client = nfs_init_client,
};
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 3210a03..13cea63 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -501,7 +501,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
(unsigned long long)NFS_FILEID(dentry->d_inode));
/* 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;
do {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 8787f77..62235be 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1423,6 +1423,7 @@ struct nfs_rpc_ops {
int open_flags,
struct iattr *iattr);
int (*have_delegation)(struct inode *, fmode_t);
+ int (*return_delegation)(struct inode *);
struct nfs_client *
(*init_client) (struct nfs_client *, const struct rpc_timeout *,
const char *, rpc_authflavor_t);
--
1.7.11
From: Bryan Schumaker <[email protected]>
Delegations are a v4 feature, so push them out of the generic code.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/delegation.c | 2 +-
fs/nfs/delegation.h | 9 ++-------
fs/nfs/dir.c | 2 +-
fs/nfs/file.c | 6 +++---
fs/nfs/inode.c | 2 +-
fs/nfs/nfs3proc.c | 6 ++++++
fs/nfs/nfs4proc.c | 5 +++--
fs/nfs/proc.c | 6 ++++++
fs/nfs/write.c | 2 +-
include/linux/nfs_xdr.h | 1 +
10 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 9a7a1b4..36c7c64 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -47,7 +47,7 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
*
* Returns one if inode has the indicated delegation, otherwise zero.
*/
-int nfs_have_delegation(struct inode *inode, fmode_t flags)
+int nfs4_have_delegation(struct inode *inode, fmode_t flags)
{
struct nfs_delegation *delegation;
int ret = 0;
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 206db56..d134fc5 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -56,14 +56,9 @@ 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);
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);
@@ -73,7 +68,7 @@ static inline int nfs_inode_return_delegation(struct inode *inode)
static inline int nfs_have_delegated_attributes(struct inode *inode)
{
- return nfs_have_delegation(inode, FMODE_READ) &&
+ return NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) &&
!(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index f430057..4a3e23a 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1144,7 +1144,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
goto out_bad;
}
- if (nfs_have_delegation(inode, FMODE_READ))
+ if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
goto out_set_verifier;
/* Force a full look up iff the parent directory has changed */
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 8941ac4..57a22a1 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -178,7 +178,7 @@ nfs_file_flush(struct file *file, fl_owner_t id)
* If we're holding a write delegation, then just start the i/o
* 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);
/* Flush writes to the server and return any errors */
@@ -677,7 +677,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
}
fl->fl_type = saved_type;
- if (nfs_have_delegation(inode, FMODE_READ))
+ if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
goto out_noconflict;
if (is_local)
@@ -772,7 +772,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
* This makes locking act as a cache coherency point.
*/
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))
__nfs_revalidate_inode(NFS_SERVER(inode), inode);
else
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f729698..0f0b928 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1457,7 +1457,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|| S_ISLNK(inode->i_mode)))
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))
nfsi->cache_validity |= invalid;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 2292a0f..08f8326 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -877,6 +877,11 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
}
+static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
+{
+ return 0;
+}
+
const struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
@@ -921,5 +926,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.lock = nfs3_proc_lock,
.clear_acl_cache = nfs3_forget_cached_acls,
.close_context = nfs_close_context,
+ .have_delegation = nfs3_have_delegation,
.init_client = nfs_init_client,
};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a533e63..993d6ec 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -294,7 +294,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
case 0:
return 0;
case -NFS4ERR_OPENMODE:
- if (inode && nfs_have_delegation(inode, FMODE_READ)) {
+ if (inode && nfs4_have_delegation(inode, FMODE_READ)) {
nfs_inode_return_delegation(inode);
exception->retry = 1;
return 0;
@@ -3464,7 +3464,7 @@ bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data)
/* Otherwise, request attributes if and only if we don't hold
* a delegation
*/
- return nfs_have_delegation(hdr->inode, FMODE_READ) == 0;
+ return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
}
static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
@@ -6802,6 +6802,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.clear_acl_cache = nfs4_zap_acl_attr,
.close_context = nfs4_close_context,
.open_context = nfs4_atomic_open,
+ .have_delegation = nfs4_have_delegation,
.init_client = nfs4_init_client,
};
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 617c741..4aed3dd 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -734,6 +734,11 @@ out_einval:
return -EINVAL;
}
+static int nfs_have_delegation(struct inode *inode, fmode_t flags)
+{
+ return 0;
+}
+
const struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
@@ -777,5 +782,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.lock = nfs_proc_lock,
.lock_check_bounds = nfs_lock_check_bounds,
.close_context = nfs_close_context,
+ .have_delegation = nfs_have_delegation,
.init_client = nfs_init_client,
};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ee929e5..f163355 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -410,7 +410,7 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
nfs_lock_request(req);
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++;
set_bit(PG_MAPPED, &req->wb_flags);
SetPagePrivate(req->wb_page);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 5c0014d..8787f77 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1422,6 +1422,7 @@ struct nfs_rpc_ops {
struct nfs_open_context *ctx,
int open_flags,
struct iattr *iattr);
+ int (*have_delegation)(struct inode *, fmode_t);
struct nfs_client *
(*init_client) (struct nfs_client *, const struct rpc_timeout *,
const char *, rpc_authflavor_t);
--
1.7.11
From: Bryan Schumaker <[email protected]>
pNFS needs to select a read function based on the layout driver
currently in use, so I let each NFS version decide how to best handle
initializing reads.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/internal.h | 2 +-
fs/nfs/nfs3proc.c | 1 +
fs/nfs/nfs4proc.c | 1 +
fs/nfs/pnfs.c | 11 +++++------
fs/nfs/pnfs.h | 6 +++---
fs/nfs/proc.c | 1 +
fs/nfs/read.c | 16 +++-------------
include/linux/nfs_xdr.h | 3 +++
8 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 633af81..b312112 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -306,7 +306,7 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt,
extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
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,
const struct nfs_pgio_completion_ops *compl_ops);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 77c7aac..9864d05 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -921,6 +921,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.pathconf = nfs3_proc_pathconf,
.decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup,
+ .read_pageio_init = nfs_pageio_init_read,
.read_rpc_prepare = nfs3_proc_read_rpc_prepare,
.read_done = nfs3_read_done,
.write_setup = nfs3_proc_write_setup,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9ed2cc3..31d9c80 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6790,6 +6790,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.set_capabilities = nfs4_server_capabilities,
.decode_dirent = nfs4_decode_dirent,
.read_setup = nfs4_proc_read_setup,
+ .read_pageio_init = pnfs_pageio_init_read,
.read_rpc_prepare = nfs4_proc_read_rpc_prepare,
.read_done = nfs4_read_done,
.write_setup = nfs4_proc_write_setup,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index bbc49ca..9c83060 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1209,7 +1209,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
-bool
+void
pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
const struct nfs_pgio_completion_ops *compl_ops)
{
@@ -1217,10 +1217,9 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
if (ld == NULL)
- return false;
- nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops,
- server->rsize, 0);
- return true;
+ nfs_pageio_init_read(pgio, inode, compl_ops);
+ else
+ nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0);
}
bool
@@ -1427,7 +1426,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode,
LIST_HEAD(failed);
/* 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)) {
struct nfs_page *req = nfs_list_entry(head->next);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 64f90d8..80ee891 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -178,7 +178,7 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
void get_layout_hdr(struct pnfs_layout_hdr *lo);
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 *);
bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *,
int, const struct nfs_pgio_completion_ops *);
@@ -438,10 +438,10 @@ 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)
{
- 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,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 99a0025..6fea6e1 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -778,6 +778,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.pathconf = nfs_proc_pathconf,
.decode_dirent = nfs2_decode_dirent,
.read_setup = nfs_proc_read_setup,
+ .read_pageio_init = nfs_pageio_init_read,
.read_rpc_prepare = nfs_proc_read_rpc_prepare,
.read_done = nfs_read_done,
.write_setup = nfs_proc_write_setup,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 86ced78..6267b87 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -20,8 +20,6 @@
#include <linux/nfs_page.h>
#include <linux/module.h>
-#include "pnfs.h"
-
#include "nfs4_fs.h"
#include "internal.h"
#include "iostat.h"
@@ -108,7 +106,7 @@ int nfs_return_empty_page(struct page *page)
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,
const struct nfs_pgio_completion_ops *compl_ops)
{
@@ -123,14 +121,6 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
}
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,
struct page *page)
{
@@ -149,7 +139,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
if (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_complete(&pgio);
NFS_I(inode)->read_io += pgio.pg_bytes_written;
@@ -652,7 +642,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
if (ret == 0)
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);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4d62b77..e00b8b3 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1354,6 +1354,7 @@ struct nfs_access_entry;
struct nfs_client;
struct rpc_timeout;
struct nfs_client_initdata;
+struct nfs_pageio_descriptor;
/*
* RPC procedure vector for NFSv2/NFSv3 demuxing
@@ -1407,6 +1408,8 @@ struct nfs_rpc_ops {
int (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int);
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 *);
int (*read_done) (struct rpc_task *, struct nfs_read_data *);
void (*write_setup) (struct nfs_write_data *, struct rpc_message *);
--
1.7.11
From: Bryan Schumaker <[email protected]>
I can use this function to return delegations and unset the pnfs layout
driver rather than continuing to do these things in the generic client.
With this change, we no longer need an nfs4_kill_super().
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 3 ++-
fs/nfs/delegation.c | 3 +--
fs/nfs/delegation.h | 2 +-
fs/nfs/super.c | 23 +++++------------------
4 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e646b14..bf0f896 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -266,6 +266,8 @@ static void pnfs_init_server(struct nfs_server *server)
static void nfs4_destroy_server(struct nfs_server *server)
{
+ nfs_server_return_all_delegations(server);
+ unset_pnfs_layoutdriver(server);
nfs4_purge_state_owners(server);
}
@@ -1137,7 +1139,6 @@ void nfs_free_server(struct nfs_server *server)
dprintk("--> nfs_free_server()\n");
nfs_server_remove_lists(server);
- unset_pnfs_layoutdriver(server);
if (server->destroy != NULL)
server->destroy(server);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index bd3a960..9a7a1b4 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -417,9 +417,8 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
* @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_delegation *delegation;
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 72709c4..206db56 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -38,7 +38,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
void nfs_inode_return_delegation_noreclaim(struct inode *inode);
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_delegation_types(struct nfs_client *clp, fmode_t flags);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 906f09c..5a1c860 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -347,13 +347,12 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
-static void nfs4_kill_super(struct super_block *sb);
static struct file_system_type nfs4_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs_fs_mount,
- .kill_sb = nfs4_kill_super,
+ .kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -361,7 +360,7 @@ static struct file_system_type nfs4_remote_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_remote_mount,
- .kill_sb = nfs4_kill_super,
+ .kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -369,7 +368,7 @@ struct file_system_type nfs4_xdev_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_xdev_mount,
- .kill_sb = nfs4_kill_super,
+ .kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -377,7 +376,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_remote_referral_mount,
- .kill_sb = nfs4_kill_super,
+ .kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -385,7 +384,7 @@ struct file_system_type nfs4_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_referral_mount,
- .kill_sb = nfs4_kill_super,
+ .kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -2874,18 +2873,6 @@ static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
return res;
}
-static void nfs4_kill_super(struct super_block *sb)
-{
- struct nfs_server *server = NFS_SB(sb);
-
- dprintk("--> %s\n", __func__);
- nfs_super_return_all_delegations(sb);
- kill_anon_super(sb);
- nfs_fscache_release_super_cookie(sb);
- nfs_free_server(server);
- dprintk("<-- %s\n", __func__);
-}
-
/*
* Clone an NFS4 server record on xdev traversal (FSID-change)
*/
--
1.7.11
From: Bryan Schumaker <[email protected]>
The generic client doesn't need to know about pnfs layout drivers, so
this should be done in the v4 code.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 -
fs/nfs/nfs4proc.c | 8 +++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index f005b5b..e646b14 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -975,7 +975,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
server->wsize = NFS_MAX_FILE_IO_SIZE;
server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
server->pnfs_blksize = fsinfo->blksize;
- set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype);
server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5a7b372..a533e63 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3330,8 +3330,14 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str
static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
+ int error;
+
nfs_fattr_init(fsinfo->fattr);
- return nfs4_do_fsinfo(server, fhandle, fsinfo);
+ error = nfs4_do_fsinfo(server, fhandle, fsinfo);
+ if (error == 0)
+ set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
+
+ return error;
}
static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
--
1.7.11
From: Bryan Schumaker <[email protected]>
pNFS needs to select a write function based on the layout driver
currently in use, so I let each NFS version decide how to best handle
initializing writes.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/internal.h | 2 +-
fs/nfs/nfs3proc.c | 1 +
fs/nfs/nfs4proc.c | 1 +
fs/nfs/pnfs.c | 11 +++++------
fs/nfs/pnfs.h | 6 +++---
fs/nfs/proc.c | 1 +
fs/nfs/write.c | 18 ++++++------------
include/linux/nfs_xdr.h | 2 ++
8 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b312112..7edc172 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -320,7 +320,7 @@ extern struct nfs_write_header *nfs_writehdr_alloc(void);
extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
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,
const struct nfs_pgio_completion_ops *compl_ops);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 9864d05..f3344f7 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -925,6 +925,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.read_rpc_prepare = nfs3_proc_read_rpc_prepare,
.read_done = nfs3_read_done,
.write_setup = nfs3_proc_write_setup,
+ .write_pageio_init = nfs_pageio_init_write,
.write_rpc_prepare = nfs3_proc_write_rpc_prepare,
.write_done = nfs3_write_done,
.commit_setup = nfs3_proc_commit_setup,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 31d9c80..9ac9c40 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6794,6 +6794,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.read_rpc_prepare = nfs4_proc_read_rpc_prepare,
.read_done = nfs4_read_done,
.write_setup = nfs4_proc_write_setup,
+ .write_pageio_init = pnfs_pageio_init_write,
.write_rpc_prepare = nfs4_proc_write_rpc_prepare,
.write_done = nfs4_write_done,
.commit_setup = nfs4_proc_commit_setup,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 9c83060..2617831 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1222,7 +1222,7 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0);
}
-bool
+void
pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
int ioflags,
const struct nfs_pgio_completion_ops *compl_ops)
@@ -1231,10 +1231,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
if (ld == NULL)
- return false;
- nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops,
- server->wsize, ioflags);
- return true;
+ nfs_pageio_init_write(pgio, inode, ioflags, compl_ops);
+ else
+ nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, server->wsize, ioflags);
}
bool
@@ -1271,7 +1270,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode,
LIST_HEAD(failed);
/* 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)) {
struct nfs_page *req = nfs_list_entry(head->next);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 80ee891..592beb0 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -180,7 +180,7 @@ void put_lseg(struct pnfs_layout_segment *lseg);
void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *,
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 *);
void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
@@ -444,10 +444,10 @@ static inline void pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, str
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)
{
- return false;
+ nfs_pageio_init_write(pgio, inode, ioflags, compl_ops);
}
static inline int
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 6fea6e1..cf64997 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -782,6 +782,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.read_rpc_prepare = nfs_proc_read_rpc_prepare,
.read_done = nfs_read_done,
.write_setup = nfs_proc_write_setup,
+ .write_pageio_init = nfs_pageio_init_write,
.write_rpc_prepare = nfs_proc_write_rpc_prepare,
.write_done = nfs_write_done,
.commit_setup = nfs_proc_commit_setup,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index f163355..c11fb00 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -336,8 +336,10 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
struct nfs_pageio_descriptor pgio;
int err;
- nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc),
- &nfs_async_write_completion_ops);
+ NFS_PROTO(page->mapping->host)->write_pageio_init(&pgio,
+ page->mapping->host,
+ wb_priority(wbc),
+ &nfs_async_write_completion_ops);
err = nfs_do_writepage(page, wbc, &pgio);
nfs_pageio_complete(&pgio);
if (err < 0)
@@ -380,8 +382,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
- nfs_pageio_init_write(&pgio, inode, wb_priority(wbc),
- &nfs_async_write_completion_ops);
+ NFS_PROTO(inode)->write_pageio_init(&pgio, inode, wb_priority(wbc), &nfs_async_write_completion_ops);
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
nfs_pageio_complete(&pgio);
@@ -1202,7 +1203,7 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = {
.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,
const struct nfs_pgio_completion_ops *compl_ops)
{
@@ -1217,13 +1218,6 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
}
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)
{
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e00b8b3..8ed8ec6 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1413,6 +1413,8 @@ struct nfs_rpc_ops {
void (*read_rpc_prepare)(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_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 *);
int (*write_done) (struct rpc_task *, struct nfs_write_data *);
void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
--
1.7.11
From: Bryan Schumaker <[email protected]>
NFS v4 needs a way to shut down callbacks and sessions, but v2 and v3
don't.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 18 +++++++++---------
fs/nfs/internal.h | 1 +
fs/nfs/nfs3proc.c | 1 +
fs/nfs/nfs4_fs.h | 2 ++
fs/nfs/nfs4proc.c | 1 +
fs/nfs/proc.c | 1 +
include/linux/nfs_xdr.h | 1 +
7 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bf0f896..82cb8a3 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -242,6 +242,12 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
kfree(clp->cl_implid);
}
+void nfs4_free_client(struct nfs_client *clp)
+{
+ nfs4_shutdown_client(clp);
+ nfs_free_client(clp);
+}
+
/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
void nfs_cleanup_cb_ident_idr(struct net *net)
{
@@ -272,10 +278,6 @@ static void nfs4_destroy_server(struct nfs_server *server)
}
#else
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-}
-
void nfs_cleanup_cb_ident_idr(struct net *net)
{
}
@@ -293,12 +295,10 @@ static void pnfs_init_server(struct nfs_server *server)
/*
* Destroy a shared client record
*/
-static void nfs_free_client(struct nfs_client *clp)
+void nfs_free_client(struct nfs_client *clp)
{
dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
- nfs4_shutdown_client(clp);
-
nfs_fscache_release_client_cookie(clp);
/* -EIO all pending I/O */
@@ -335,7 +335,7 @@ void nfs_put_client(struct nfs_client *clp)
BUG_ON(!list_empty(&clp->cl_superblocks));
- nfs_free_client(clp);
+ clp->rpc_ops->free_client(clp);
}
}
EXPORT_SYMBOL_GPL(nfs_put_client);
@@ -574,7 +574,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
if (clp) {
spin_unlock(&nn->nfs_client_lock);
if (new)
- nfs_free_client(new);
+ new->rpc_ops->free_client(new);
return nfs_found_client(cl_init, clp);
}
if (new) {
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 18f99ef..93b7325 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -151,6 +151,7 @@ extern void nfs_clients_init(struct net *net);
extern void nfs_cleanup_cb_ident_idr(struct net *);
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_sessionid(struct net *, const struct sockaddr *,
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 4749a32..4ccb34b 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -935,4 +935,5 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.have_delegation = nfs3_have_delegation,
.return_delegation = nfs3_return_delegation,
.init_client = nfs_init_client,
+ .free_client = nfs_free_client,
};
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cc5900a..9889ee4 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -301,6 +301,8 @@ extern const u32 nfs4_pathconf_bitmap[2];
extern const u32 nfs4_fsinfo_bitmap[3];
extern const u32 nfs4_fs_locations_bitmap[2];
+void nfs4_free_client(struct nfs_client *);
+
/* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs_client *);
extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b2cd0f1..9ba482e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6805,6 +6805,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.have_delegation = nfs4_have_delegation,
.return_delegation = nfs4_inode_return_delegation,
.init_client = nfs4_init_client,
+ .free_client = nfs4_free_client,
};
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 1663293..53620bf 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -791,4 +791,5 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.have_delegation = nfs_have_delegation,
.return_delegation = nfs_return_delegation,
.init_client = nfs_init_client,
+ .free_client = nfs_free_client,
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 62235be..e61dc72 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1427,6 +1427,7 @@ struct nfs_rpc_ops {
struct nfs_client *
(*init_client) (struct nfs_client *, const struct rpc_timeout *,
const char *, rpc_authflavor_t);
+ void (*free_client) (struct nfs_client *);
};
/*
--
1.7.11
From: Bryan Schumaker <[email protected]>
This gives pnfs a chance to do a layout commit inside the v4 code.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs4_fs.h | 3 +++
fs/nfs/super.c | 2 +-
fs/nfs/write.c | 10 ++++++++--
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a0be2d1a..3696ca7 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -202,6 +202,9 @@ struct nfs4_state_maintenance_ops {
extern const struct dentry_operations nfs4_dentry_operations;
extern const struct inode_operations nfs4_dir_inode_operations;
+/* write.c */
+int nfs4_write_inode(struct inode *, struct writeback_control *);
+
/* nfs4namespace.c */
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5a1c860..9d33fb2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -391,7 +391,7 @@ struct file_system_type nfs4_referral_fs_type = {
static const struct super_operations nfs4_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
- .write_inode = nfs_write_inode,
+ .write_inode = nfs4_write_inode,
.put_super = nfs_put_super,
.statfs = nfs_statfs,
.evict_inode = nfs4_evict_inode,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c11fb00..f312860 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1671,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 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)) {
int status;
bool sync = true;
@@ -1687,6 +1692,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
}
return ret;
}
+#endif
/*
* flush the inode to disk.
--
1.7.11
From: Bryan Schumaker <[email protected]>
This gives NFS v4 a way to set up callbacks and sessions without v2 or
v3 having to do them as well.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 40 ++++++++++++++++++++++++++--------------
fs/nfs/internal.h | 1 +
fs/nfs/nfs3proc.c | 1 +
fs/nfs/nfs4_fs.h | 2 ++
fs/nfs/nfs4proc.c | 1 +
fs/nfs/proc.c | 1 +
include/linux/nfs_xdr.h | 2 ++
7 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 82cb8a3..254719c 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -147,7 +147,7 @@ struct nfs_client_initdata {
* Since these are allocated/deallocated very rarely, we don't
* bother putting them in a slab cache...
*/
-static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
+struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
{
struct nfs_client *clp;
struct rpc_cred *cred;
@@ -177,18 +177,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp->cl_proto = cl_init->proto;
clp->cl_net = get_net(cl_init->net);
-#ifdef CONFIG_NFS_V4
- err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
- if (err)
- goto error_cleanup;
-
- spin_lock_init(&clp->cl_lock);
- INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
- clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
- clp->cl_minorversion = cl_init->minorversion;
- clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
-#endif
cred = rpc_lookup_machine_cred("*");
if (!IS_ERR(cred))
clp->cl_machine_cred = cred;
@@ -218,6 +206,30 @@ static void nfs4_shutdown_session(struct nfs_client *clp)
}
#endif /* CONFIG_NFS_V4_1 */
+struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
+{
+ int err;
+ struct nfs_client *clp = nfs_alloc_client(cl_init);
+ if (IS_ERR(clp))
+ return clp;
+
+ err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ if (err)
+ goto error;
+
+ spin_lock_init(&clp->cl_lock);
+ INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
+ clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+ return clp;
+
+error:
+ kfree(clp);
+ return ERR_PTR(err);
+}
+
/*
* Destroy the NFS4 callback service
*/
@@ -588,7 +600,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
spin_unlock(&nn->nfs_client_lock);
- new = nfs_alloc_client(cl_init);
+ new = cl_init->rpc_ops->alloc_client(cl_init);
} while (!IS_ERR(new));
dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 93b7325..633af81 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -148,6 +148,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
/* client.c */
extern const struct rpc_program nfs_program;
extern void nfs_clients_init(struct net *net);
+extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
extern void nfs_cleanup_cb_ident_idr(struct net *);
extern void nfs_put_client(struct nfs_client *);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 4ccb34b..77c7aac 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -934,6 +934,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.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,
.free_client = nfs_free_client,
};
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 9889ee4..a0be2d1a 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -303,6 +303,8 @@ 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 */
extern void nfs4_schedule_state_renewal(struct nfs_client *);
extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9ba482e..9ed2cc3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6804,6 +6804,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.open_context = nfs4_atomic_open,
.have_delegation = nfs4_have_delegation,
.return_delegation = nfs4_inode_return_delegation,
+ .alloc_client = nfs4_alloc_client,
.init_client = nfs4_init_client,
.free_client = nfs4_free_client,
};
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 53620bf..99a0025 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -790,6 +790,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.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,
.free_client = nfs_free_client,
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e61dc72..4d62b77 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1353,6 +1353,7 @@ struct nfs_renamedata {
struct nfs_access_entry;
struct nfs_client;
struct rpc_timeout;
+struct nfs_client_initdata;
/*
* RPC procedure vector for NFSv2/NFSv3 demuxing
@@ -1424,6 +1425,7 @@ struct nfs_rpc_ops {
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 *
(*init_client) (struct nfs_client *, const struct rpc_timeout *,
const char *, rpc_authflavor_t);
--
1.7.11