Skip to content

Commit 275d9fd

Browse files
MaxKellermanngregkh
authored andcommitted
fs/nfs/io: make nfs_start_io_*() killable
[ Upstream commit 38a125b ] This allows killing processes that wait for a lock when one process is stuck waiting for the NFS server. This aims to complete the coverage of NFS operations being killable, like nfs_direct_wait() does, for example. Signed-off-by: Max Kellermann <max.kellermann@ionos.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Stable-dep-of: 9eb90f4 ("NFS: Serialise O_DIRECT i/o and truncate()") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 06c26a6 commit 275d9fd

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

fs/nfs/direct.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
469469
if (user_backed_iter(iter))
470470
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
471471

472-
if (!swap)
473-
nfs_start_io_direct(inode);
472+
if (!swap) {
473+
result = nfs_start_io_direct(inode);
474+
if (result) {
475+
/* release the reference that would usually be
476+
* consumed by nfs_direct_read_schedule_iovec()
477+
*/
478+
nfs_direct_req_release(dreq);
479+
goto out_release;
480+
}
481+
}
474482

475483
NFS_I(inode)->read_io += count;
476484
requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos);
@@ -1023,7 +1031,14 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
10231031
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
10241032
FLUSH_STABLE);
10251033
} else {
1026-
nfs_start_io_direct(inode);
1034+
result = nfs_start_io_direct(inode);
1035+
if (result) {
1036+
/* release the reference that would usually be
1037+
* consumed by nfs_direct_write_schedule_iovec()
1038+
*/
1039+
nfs_direct_req_release(dreq);
1040+
goto out_release;
1041+
}
10271042

10281043
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
10291044
FLUSH_COND_STABLE);

fs/nfs/file.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
167167
iocb->ki_filp,
168168
iov_iter_count(to), (unsigned long) iocb->ki_pos);
169169

170-
nfs_start_io_read(inode);
170+
result = nfs_start_io_read(inode);
171+
if (result)
172+
return result;
173+
171174
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
172175
if (!result) {
173176
result = generic_file_read_iter(iocb, to);
@@ -188,7 +191,10 @@ nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe
188191

189192
dprintk("NFS: splice_read(%pD2, %zu@%llu)\n", in, len, *ppos);
190193

191-
nfs_start_io_read(inode);
194+
result = nfs_start_io_read(inode);
195+
if (result)
196+
return result;
197+
192198
result = nfs_revalidate_mapping(inode, in->f_mapping);
193199
if (!result) {
194200
result = filemap_splice_read(in, ppos, pipe, len, flags);
@@ -668,7 +674,9 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
668674
nfs_clear_invalid_mapping(file->f_mapping);
669675

670676
since = filemap_sample_wb_err(file->f_mapping);
671-
nfs_start_io_write(inode);
677+
error = nfs_start_io_write(inode);
678+
if (error)
679+
return error;
672680
result = generic_write_checks(iocb, from);
673681
if (result > 0)
674682
result = generic_perform_write(iocb, from);

fs/nfs/internal.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "nfs4_fs.h"
77
#include <linux/fs_context.h>
88
#include <linux/security.h>
9+
#include <linux/compiler_attributes.h>
910
#include <linux/crc32.h>
1011
#include <linux/sunrpc/addr.h>
1112
#include <linux/nfs_page.h>
@@ -461,11 +462,11 @@ extern const struct netfs_request_ops nfs_netfs_ops;
461462
#endif
462463

463464
/* io.c */
464-
extern void nfs_start_io_read(struct inode *inode);
465+
extern __must_check int nfs_start_io_read(struct inode *inode);
465466
extern void nfs_end_io_read(struct inode *inode);
466-
extern void nfs_start_io_write(struct inode *inode);
467+
extern __must_check int nfs_start_io_write(struct inode *inode);
467468
extern void nfs_end_io_write(struct inode *inode);
468-
extern void nfs_start_io_direct(struct inode *inode);
469+
extern __must_check int nfs_start_io_direct(struct inode *inode);
469470
extern void nfs_end_io_direct(struct inode *inode);
470471

471472
static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)

fs/nfs/io.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,28 @@ static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
3939
* Note that buffered writes and truncates both take a write lock on
4040
* inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
4141
*/
42-
void
42+
int
4343
nfs_start_io_read(struct inode *inode)
4444
{
4545
struct nfs_inode *nfsi = NFS_I(inode);
46+
int err;
47+
4648
/* Be an optimist! */
47-
down_read(&inode->i_rwsem);
49+
err = down_read_killable(&inode->i_rwsem);
50+
if (err)
51+
return err;
4852
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0)
49-
return;
53+
return 0;
5054
up_read(&inode->i_rwsem);
55+
5156
/* Slow path.... */
52-
down_write(&inode->i_rwsem);
57+
err = down_write_killable(&inode->i_rwsem);
58+
if (err)
59+
return err;
5360
nfs_block_o_direct(nfsi, inode);
5461
downgrade_write(&inode->i_rwsem);
62+
63+
return 0;
5564
}
5665

5766
/**
@@ -74,11 +83,15 @@ nfs_end_io_read(struct inode *inode)
7483
* Declare that a buffered read operation is about to start, and ensure
7584
* that we block all direct I/O.
7685
*/
77-
void
86+
int
7887
nfs_start_io_write(struct inode *inode)
7988
{
80-
down_write(&inode->i_rwsem);
81-
nfs_block_o_direct(NFS_I(inode), inode);
89+
int err;
90+
91+
err = down_write_killable(&inode->i_rwsem);
92+
if (!err)
93+
nfs_block_o_direct(NFS_I(inode), inode);
94+
return err;
8295
}
8396

8497
/**
@@ -119,19 +132,28 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode)
119132
* Note that buffered writes and truncates both take a write lock on
120133
* inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
121134
*/
122-
void
135+
int
123136
nfs_start_io_direct(struct inode *inode)
124137
{
125138
struct nfs_inode *nfsi = NFS_I(inode);
139+
int err;
140+
126141
/* Be an optimist! */
127-
down_read(&inode->i_rwsem);
142+
err = down_read_killable(&inode->i_rwsem);
143+
if (err)
144+
return err;
128145
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags) != 0)
129-
return;
146+
return 0;
130147
up_read(&inode->i_rwsem);
148+
131149
/* Slow path.... */
132-
down_write(&inode->i_rwsem);
150+
err = down_write_killable(&inode->i_rwsem);
151+
if (err)
152+
return err;
133153
nfs_block_buffered(nfsi, inode);
134154
downgrade_write(&inode->i_rwsem);
155+
156+
return 0;
135157
}
136158

137159
/**

0 commit comments

Comments
 (0)