diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-31 11:44:06 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-31 13:50:42 -0500 |
commit | dc602dd706cb64036132a7903ead1c67d9a7bcb9 (patch) | |
tree | 88d632825b446b8445a0219c3ac24a00a1d2853b /fs/nfs/direct.c | |
parent | e07db907eb80525874b7707c62cc6f5e975ef130 (diff) |
NFS/pNFS: Fix up pNFS write reschedule layering violations and bugs
The flexfiles layout in particular, seems to want to poke around in the
O_DIRECT flags when retransmitting.
This patch sets up an interface to allow it to call back into O_DIRECT
to handle retransmission correctly. It also fixes a potential bug whereby
we could change the behaviour of O_DIRECT if an error is already pending.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 4b1d08f56aba..e73693f75dee 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -117,12 +117,6 @@ static inline int put_dreq(struct nfs_direct_req *dreq) | |||
117 | return atomic_dec_and_test(&dreq->io_count); | 117 | return atomic_dec_and_test(&dreq->io_count); |
118 | } | 118 | } |
119 | 119 | ||
120 | void nfs_direct_set_resched_writes(struct nfs_direct_req *dreq) | ||
121 | { | ||
122 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(nfs_direct_set_resched_writes); | ||
125 | |||
126 | static void | 120 | static void |
127 | nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr) | 121 | nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr) |
128 | { | 122 | { |
@@ -839,10 +833,25 @@ static void nfs_write_sync_pgio_error(struct list_head *head) | |||
839 | } | 833 | } |
840 | } | 834 | } |
841 | 835 | ||
836 | static void nfs_direct_write_reschedule_io(struct nfs_pgio_header *hdr) | ||
837 | { | ||
838 | struct nfs_direct_req *dreq = hdr->dreq; | ||
839 | |||
840 | spin_lock(&dreq->lock); | ||
841 | if (dreq->error == 0) { | ||
842 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | ||
843 | /* fake unstable write to let common nfs resend pages */ | ||
844 | hdr->verf.committed = NFS_UNSTABLE; | ||
845 | hdr->good_bytes = hdr->args.count; | ||
846 | } | ||
847 | spin_unlock(&dreq->lock); | ||
848 | } | ||
849 | |||
842 | static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = { | 850 | static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = { |
843 | .error_cleanup = nfs_write_sync_pgio_error, | 851 | .error_cleanup = nfs_write_sync_pgio_error, |
844 | .init_hdr = nfs_direct_pgio_init, | 852 | .init_hdr = nfs_direct_pgio_init, |
845 | .completion = nfs_direct_write_completion, | 853 | .completion = nfs_direct_write_completion, |
854 | .reschedule_io = nfs_direct_write_reschedule_io, | ||
846 | }; | 855 | }; |
847 | 856 | ||
848 | 857 | ||