Skip to content

Commit fa07303

Browse files
MaxKellermannidryomov
authored andcommitted
ceph: make ceph_start_io_*() killable
This allows killing processes that wait for a lock when one process is stuck waiting for the Ceph server. This is similar to the NFS commit 38a125b ("fs/nfs/io: make nfs_start_io_*() killable"). [ idryomov: drop comment on include, formatting ] Signed-off-by: Max Kellermann <max.kellermann@ionos.com> Reviewed-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent 27c0a7b commit fa07303

3 files changed

Lines changed: 49 additions & 26 deletions

File tree

fs/ceph/file.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,10 +2121,10 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
21212121
if (ceph_inode_is_shutdown(inode))
21222122
return -ESTALE;
21232123

2124-
if (direct_lock)
2125-
ceph_start_io_direct(inode);
2126-
else
2127-
ceph_start_io_read(inode);
2124+
ret = direct_lock ? ceph_start_io_direct(inode) :
2125+
ceph_start_io_read(inode);
2126+
if (ret)
2127+
return ret;
21282128

21292129
if (!(fi->flags & CEPH_F_SYNC) && !direct_lock)
21302130
want |= CEPH_CAP_FILE_CACHE;
@@ -2277,7 +2277,9 @@ static ssize_t ceph_splice_read(struct file *in, loff_t *ppos,
22772277
(fi->flags & CEPH_F_SYNC))
22782278
return copy_splice_read(in, ppos, pipe, len, flags);
22792279

2280-
ceph_start_io_read(inode);
2280+
ret = ceph_start_io_read(inode);
2281+
if (ret)
2282+
return ret;
22812283

22822284
want = CEPH_CAP_FILE_CACHE;
22832285
if (fi->fmode & CEPH_FILE_MODE_LAZY)
@@ -2356,10 +2358,10 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
23562358
direct_lock = true;
23572359

23582360
retry_snap:
2359-
if (direct_lock)
2360-
ceph_start_io_direct(inode);
2361-
else
2362-
ceph_start_io_write(inode);
2361+
err = direct_lock ? ceph_start_io_direct(inode) :
2362+
ceph_start_io_write(inode);
2363+
if (err)
2364+
goto out_unlocked;
23632365

23642366
if (iocb->ki_flags & IOCB_APPEND) {
23652367
err = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE, false);

fs/ceph/io.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,29 @@ static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode)
4747
* Note that buffered writes and truncates both take a write lock on
4848
* inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
4949
*/
50-
void
51-
ceph_start_io_read(struct inode *inode)
50+
int ceph_start_io_read(struct inode *inode)
5251
{
5352
struct ceph_inode_info *ci = ceph_inode(inode);
53+
int err;
5454

5555
/* Be an optimist! */
56-
down_read(&inode->i_rwsem);
56+
err = down_read_killable(&inode->i_rwsem);
57+
if (err)
58+
return err;
59+
5760
if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT))
58-
return;
61+
return 0;
5962
up_read(&inode->i_rwsem);
63+
6064
/* Slow path.... */
61-
down_write(&inode->i_rwsem);
65+
err = down_write_killable(&inode->i_rwsem);
66+
if (err)
67+
return err;
68+
6269
ceph_block_o_direct(ci, inode);
6370
downgrade_write(&inode->i_rwsem);
71+
72+
return 0;
6473
}
6574

6675
/**
@@ -83,11 +92,12 @@ ceph_end_io_read(struct inode *inode)
8392
* Declare that a buffered write operation is about to start, and ensure
8493
* that we block all direct I/O.
8594
*/
86-
void
87-
ceph_start_io_write(struct inode *inode)
95+
int ceph_start_io_write(struct inode *inode)
8896
{
89-
down_write(&inode->i_rwsem);
90-
ceph_block_o_direct(ceph_inode(inode), inode);
97+
int err = down_write_killable(&inode->i_rwsem);
98+
if (!err)
99+
ceph_block_o_direct(ceph_inode(inode), inode);
100+
return err;
91101
}
92102

93103
/**
@@ -133,20 +143,29 @@ static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode)
133143
* Note that buffered writes and truncates both take a write lock on
134144
* inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
135145
*/
136-
void
137-
ceph_start_io_direct(struct inode *inode)
146+
int ceph_start_io_direct(struct inode *inode)
138147
{
139148
struct ceph_inode_info *ci = ceph_inode(inode);
149+
int err;
140150

141151
/* Be an optimist! */
142-
down_read(&inode->i_rwsem);
152+
err = down_read_killable(&inode->i_rwsem);
153+
if (err)
154+
return err;
155+
143156
if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)
144-
return;
157+
return 0;
145158
up_read(&inode->i_rwsem);
159+
146160
/* Slow path.... */
147-
down_write(&inode->i_rwsem);
161+
err = down_write_killable(&inode->i_rwsem);
162+
if (err)
163+
return err;
164+
148165
ceph_block_buffered(ci, inode);
149166
downgrade_write(&inode->i_rwsem);
167+
168+
return 0;
150169
}
151170

152171
/**

fs/ceph/io.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
#ifndef _FS_CEPH_IO_H
33
#define _FS_CEPH_IO_H
44

5-
void ceph_start_io_read(struct inode *inode);
5+
#include <linux/compiler_attributes.h>
6+
7+
int __must_check ceph_start_io_read(struct inode *inode);
68
void ceph_end_io_read(struct inode *inode);
7-
void ceph_start_io_write(struct inode *inode);
9+
int __must_check ceph_start_io_write(struct inode *inode);
810
void ceph_end_io_write(struct inode *inode);
9-
void ceph_start_io_direct(struct inode *inode);
11+
int __must_check ceph_start_io_direct(struct inode *inode);
1012
void ceph_end_io_direct(struct inode *inode);
1113

1214
#endif /* FS_CEPH_IO_H */

0 commit comments

Comments
 (0)