Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
38a125b31504 ("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>

authored by

Max Kellermann and committed by
Ilya Dryomov
fa073039 27c0a7b0

+49 -26
+11 -9
fs/ceph/file.c
··· 2121 2121 if (ceph_inode_is_shutdown(inode)) 2122 2122 return -ESTALE; 2123 2123 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; 2128 2128 2129 2129 if (!(fi->flags & CEPH_F_SYNC) && !direct_lock) 2130 2130 want |= CEPH_CAP_FILE_CACHE; ··· 2277 2277 (fi->flags & CEPH_F_SYNC)) 2278 2278 return copy_splice_read(in, ppos, pipe, len, flags); 2279 2279 2280 - ceph_start_io_read(inode); 2280 + ret = ceph_start_io_read(inode); 2281 + if (ret) 2282 + return ret; 2281 2283 2282 2284 want = CEPH_CAP_FILE_CACHE; 2283 2285 if (fi->fmode & CEPH_FILE_MODE_LAZY) ··· 2358 2356 direct_lock = true; 2359 2357 2360 2358 retry_snap: 2361 - if (direct_lock) 2362 - ceph_start_io_direct(inode); 2363 - else 2364 - ceph_start_io_write(inode); 2359 + err = direct_lock ? ceph_start_io_direct(inode) : 2360 + ceph_start_io_write(inode); 2361 + if (err) 2362 + goto out_unlocked; 2365 2363 2366 2364 if (iocb->ki_flags & IOCB_APPEND) { 2367 2365 err = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE, false);
+33 -14
fs/ceph/io.c
··· 47 47 * Note that buffered writes and truncates both take a write lock on 48 48 * inode->i_rwsem, meaning that those are serialised w.r.t. the reads. 49 49 */ 50 - void 51 - ceph_start_io_read(struct inode *inode) 50 + int ceph_start_io_read(struct inode *inode) 52 51 { 53 52 struct ceph_inode_info *ci = ceph_inode(inode); 53 + int err; 54 54 55 55 /* Be an optimist! */ 56 - down_read(&inode->i_rwsem); 56 + err = down_read_killable(&inode->i_rwsem); 57 + if (err) 58 + return err; 59 + 57 60 if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) 58 - return; 61 + return 0; 59 62 up_read(&inode->i_rwsem); 63 + 60 64 /* Slow path.... */ 61 - down_write(&inode->i_rwsem); 65 + err = down_write_killable(&inode->i_rwsem); 66 + if (err) 67 + return err; 68 + 62 69 ceph_block_o_direct(ci, inode); 63 70 downgrade_write(&inode->i_rwsem); 71 + 72 + return 0; 64 73 } 65 74 66 75 /** ··· 92 83 * Declare that a buffered write operation is about to start, and ensure 93 84 * that we block all direct I/O. 94 85 */ 95 - void 96 - ceph_start_io_write(struct inode *inode) 86 + int ceph_start_io_write(struct inode *inode) 97 87 { 98 - down_write(&inode->i_rwsem); 99 - ceph_block_o_direct(ceph_inode(inode), inode); 88 + int err = down_write_killable(&inode->i_rwsem); 89 + if (!err) 90 + ceph_block_o_direct(ceph_inode(inode), inode); 91 + return err; 100 92 } 101 93 102 94 /** ··· 143 133 * Note that buffered writes and truncates both take a write lock on 144 134 * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT. 145 135 */ 146 - void 147 - ceph_start_io_direct(struct inode *inode) 136 + int ceph_start_io_direct(struct inode *inode) 148 137 { 149 138 struct ceph_inode_info *ci = ceph_inode(inode); 139 + int err; 150 140 151 141 /* Be an optimist! */ 152 - down_read(&inode->i_rwsem); 142 + err = down_read_killable(&inode->i_rwsem); 143 + if (err) 144 + return err; 145 + 153 146 if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) 154 - return; 147 + return 0; 155 148 up_read(&inode->i_rwsem); 149 + 156 150 /* Slow path.... */ 157 - down_write(&inode->i_rwsem); 151 + err = down_write_killable(&inode->i_rwsem); 152 + if (err) 153 + return err; 154 + 158 155 ceph_block_buffered(ci, inode); 159 156 downgrade_write(&inode->i_rwsem); 157 + 158 + return 0; 160 159 } 161 160 162 161 /**
+5 -3
fs/ceph/io.h
··· 2 2 #ifndef _FS_CEPH_IO_H 3 3 #define _FS_CEPH_IO_H 4 4 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); 6 8 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); 8 10 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); 10 12 void ceph_end_io_direct(struct inode *inode); 11 13 12 14 #endif /* FS_CEPH_IO_H */