1 // SPDX-License-Identifier: GPL-2.0
3 * I/O and data path helper functionality.
5 * Borrowed from NFS Copyright (c) 2016 Trond Myklebust
8 #include <linux/kernel.h>
9 #include <linux/netfs.h>
13 * inode_dio_wait_interruptible - wait for outstanding DIO requests to finish
14 * @inode: inode to wait for
16 * Waits for all pending direct I/O requests to finish so that we can
17 * proceed with a truncate or equivalent operation.
19 * Must be called under a lock that serializes taking new references
20 * to i_dio_count, usually by inode->i_mutex.
22 static int inode_dio_wait_interruptible(struct inode *inode)
24 if (!atomic_read(&inode->i_dio_count))
27 wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP);
28 DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP);
31 prepare_to_wait(wq, &q.wq_entry, TASK_INTERRUPTIBLE);
32 if (!atomic_read(&inode->i_dio_count))
34 if (signal_pending(current))
38 finish_wait(wq, &q.wq_entry);
40 return atomic_read(&inode->i_dio_count) ? -ERESTARTSYS : 0;
43 /* Call with exclusively locked inode->i_rwsem */
44 static int netfs_block_o_direct(struct netfs_inode *ictx)
46 if (!test_bit(NETFS_ICTX_ODIRECT, &ictx->flags))
48 clear_bit(NETFS_ICTX_ODIRECT, &ictx->flags);
49 return inode_dio_wait_interruptible(&ictx->inode);
53 * netfs_start_io_read - declare the file is being used for buffered reads
56 * Declare that a buffered read operation is about to start, and ensure
57 * that we block all direct I/O.
58 * On exit, the function ensures that the NETFS_ICTX_ODIRECT flag is unset,
59 * and holds a shared lock on inode->i_rwsem to ensure that the flag
61 * In practice, this means that buffered read operations are allowed to
62 * execute in parallel, thanks to the shared lock, whereas direct I/O
63 * operations need to wait to grab an exclusive lock in order to set
65 * Note that buffered writes and truncates both take a write lock on
66 * inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
68 int netfs_start_io_read(struct inode *inode)
69 __acquires(inode->i_rwsem)
71 struct netfs_inode *ictx = netfs_inode(inode);
74 if (down_read_interruptible(&inode->i_rwsem) < 0)
76 if (test_bit(NETFS_ICTX_ODIRECT, &ictx->flags) == 0)
78 up_read(&inode->i_rwsem);
81 if (down_write_killable(&inode->i_rwsem) < 0)
83 if (netfs_block_o_direct(ictx) < 0) {
84 up_write(&inode->i_rwsem);
87 downgrade_write(&inode->i_rwsem);
90 EXPORT_SYMBOL(netfs_start_io_read);
93 * netfs_end_io_read - declare that the buffered read operation is done
96 * Declare that a buffered read operation is done, and release the shared
97 * lock on inode->i_rwsem.
99 void netfs_end_io_read(struct inode *inode)
100 __releases(inode->i_rwsem)
102 up_read(&inode->i_rwsem);
104 EXPORT_SYMBOL(netfs_end_io_read);
107 * netfs_start_io_write - declare the file is being used for buffered writes
110 * Declare that a buffered read operation is about to start, and ensure
111 * that we block all direct I/O.
113 int netfs_start_io_write(struct inode *inode)
114 __acquires(inode->i_rwsem)
116 struct netfs_inode *ictx = netfs_inode(inode);
118 if (down_write_killable(&inode->i_rwsem) < 0)
120 if (netfs_block_o_direct(ictx) < 0) {
121 up_write(&inode->i_rwsem);
126 EXPORT_SYMBOL(netfs_start_io_write);
129 * netfs_end_io_write - declare that the buffered write operation is done
132 * Declare that a buffered write operation is done, and release the
133 * lock on inode->i_rwsem.
135 void netfs_end_io_write(struct inode *inode)
136 __releases(inode->i_rwsem)
138 up_write(&inode->i_rwsem);
140 EXPORT_SYMBOL(netfs_end_io_write);
142 /* Call with exclusively locked inode->i_rwsem */
143 static int netfs_block_buffered(struct inode *inode)
145 struct netfs_inode *ictx = netfs_inode(inode);
148 if (!test_bit(NETFS_ICTX_ODIRECT, &ictx->flags)) {
149 set_bit(NETFS_ICTX_ODIRECT, &ictx->flags);
150 if (inode->i_mapping->nrpages != 0) {
151 unmap_mapping_range(inode->i_mapping, 0, 0, 0);
152 ret = filemap_fdatawait(inode->i_mapping);
154 clear_bit(NETFS_ICTX_ODIRECT, &ictx->flags);
163 * netfs_start_io_direct - declare the file is being used for direct i/o
166 * Declare that a direct I/O operation is about to start, and ensure
167 * that we block all buffered I/O.
168 * On exit, the function ensures that the NETFS_ICTX_ODIRECT flag is set,
169 * and holds a shared lock on inode->i_rwsem to ensure that the flag
171 * In practice, this means that direct I/O operations are allowed to
172 * execute in parallel, thanks to the shared lock, whereas buffered I/O
173 * operations need to wait to grab an exclusive lock in order to clear
174 * NETFS_ICTX_ODIRECT.
175 * Note that buffered writes and truncates both take a write lock on
176 * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
178 int netfs_start_io_direct(struct inode *inode)
179 __acquires(inode->i_rwsem)
181 struct netfs_inode *ictx = netfs_inode(inode);
184 /* Be an optimist! */
185 if (down_read_interruptible(&inode->i_rwsem) < 0)
187 if (test_bit(NETFS_ICTX_ODIRECT, &ictx->flags) != 0)
189 up_read(&inode->i_rwsem);
192 if (down_write_killable(&inode->i_rwsem) < 0)
194 ret = netfs_block_buffered(inode);
196 up_write(&inode->i_rwsem);
199 downgrade_write(&inode->i_rwsem);
202 EXPORT_SYMBOL(netfs_start_io_direct);
205 * netfs_end_io_direct - declare that the direct i/o operation is done
208 * Declare that a direct I/O operation is done, and release the shared
209 * lock on inode->i_rwsem.
211 void netfs_end_io_direct(struct inode *inode)
212 __releases(inode->i_rwsem)
214 up_read(&inode->i_rwsem);
216 EXPORT_SYMBOL(netfs_end_io_direct);