![]() |
|
|||
0001 // SPDX-License-Identifier: GPL-2.0 0002 /* 0003 * Copyright (c) 2016 Trond Myklebust 0004 * Copyright (c) 2019 Jeff Layton 0005 * 0006 * I/O and data path helper functionality. 0007 * 0008 * Heavily borrowed from equivalent code in fs/nfs/io.c 0009 */ 0010 0011 #include <linux/ceph/ceph_debug.h> 0012 0013 #include <linux/types.h> 0014 #include <linux/kernel.h> 0015 #include <linux/rwsem.h> 0016 #include <linux/fs.h> 0017 0018 #include "super.h" 0019 #include "io.h" 0020 0021 /* Call with exclusively locked inode->i_rwsem */ 0022 static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode) 0023 { 0024 lockdep_assert_held_write(&inode->i_rwsem); 0025 0026 if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) { 0027 spin_lock(&ci->i_ceph_lock); 0028 ci->i_ceph_flags &= ~CEPH_I_ODIRECT; 0029 spin_unlock(&ci->i_ceph_lock); 0030 inode_dio_wait(inode); 0031 } 0032 } 0033 0034 /** 0035 * ceph_start_io_read - declare the file is being used for buffered reads 0036 * @inode: file inode 0037 * 0038 * Declare that a buffered read operation is about to start, and ensure 0039 * that we block all direct I/O. 0040 * On exit, the function ensures that the CEPH_I_ODIRECT flag is unset, 0041 * and holds a shared lock on inode->i_rwsem to ensure that the flag 0042 * cannot be changed. 0043 * In practice, this means that buffered read operations are allowed to 0044 * execute in parallel, thanks to the shared lock, whereas direct I/O 0045 * operations need to wait to grab an exclusive lock in order to set 0046 * CEPH_I_ODIRECT. 0047 * Note that buffered writes and truncates both take a write lock on 0048 * inode->i_rwsem, meaning that those are serialised w.r.t. the reads. 0049 */ 0050 void 0051 ceph_start_io_read(struct inode *inode) 0052 { 0053 struct ceph_inode_info *ci = ceph_inode(inode); 0054 0055 /* Be an optimist! */ 0056 down_read(&inode->i_rwsem); 0057 if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) 0058 return; 0059 up_read(&inode->i_rwsem); 0060 /* Slow path.... */ 0061 down_write(&inode->i_rwsem); 0062 ceph_block_o_direct(ci, inode); 0063 downgrade_write(&inode->i_rwsem); 0064 } 0065 0066 /** 0067 * ceph_end_io_read - declare that the buffered read operation is done 0068 * @inode: file inode 0069 * 0070 * Declare that a buffered read operation is done, and release the shared 0071 * lock on inode->i_rwsem. 0072 */ 0073 void 0074 ceph_end_io_read(struct inode *inode) 0075 { 0076 up_read(&inode->i_rwsem); 0077 } 0078 0079 /** 0080 * ceph_start_io_write - declare the file is being used for buffered writes 0081 * @inode: file inode 0082 * 0083 * Declare that a buffered write operation is about to start, and ensure 0084 * that we block all direct I/O. 0085 */ 0086 void 0087 ceph_start_io_write(struct inode *inode) 0088 { 0089 down_write(&inode->i_rwsem); 0090 ceph_block_o_direct(ceph_inode(inode), inode); 0091 } 0092 0093 /** 0094 * ceph_end_io_write - declare that the buffered write operation is done 0095 * @inode: file inode 0096 * 0097 * Declare that a buffered write operation is done, and release the 0098 * lock on inode->i_rwsem. 0099 */ 0100 void 0101 ceph_end_io_write(struct inode *inode) 0102 { 0103 up_write(&inode->i_rwsem); 0104 } 0105 0106 /* Call with exclusively locked inode->i_rwsem */ 0107 static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode) 0108 { 0109 lockdep_assert_held_write(&inode->i_rwsem); 0110 0111 if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) { 0112 spin_lock(&ci->i_ceph_lock); 0113 ci->i_ceph_flags |= CEPH_I_ODIRECT; 0114 spin_unlock(&ci->i_ceph_lock); 0115 /* FIXME: unmap_mapping_range? */ 0116 filemap_write_and_wait(inode->i_mapping); 0117 } 0118 } 0119 0120 /** 0121 * ceph_start_io_direct - declare the file is being used for direct i/o 0122 * @inode: file inode 0123 * 0124 * Declare that a direct I/O operation is about to start, and ensure 0125 * that we block all buffered I/O. 0126 * On exit, the function ensures that the CEPH_I_ODIRECT flag is set, 0127 * and holds a shared lock on inode->i_rwsem to ensure that the flag 0128 * cannot be changed. 0129 * In practice, this means that direct I/O operations are allowed to 0130 * execute in parallel, thanks to the shared lock, whereas buffered I/O 0131 * operations need to wait to grab an exclusive lock in order to clear 0132 * CEPH_I_ODIRECT. 0133 * Note that buffered writes and truncates both take a write lock on 0134 * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT. 0135 */ 0136 void 0137 ceph_start_io_direct(struct inode *inode) 0138 { 0139 struct ceph_inode_info *ci = ceph_inode(inode); 0140 0141 /* Be an optimist! */ 0142 down_read(&inode->i_rwsem); 0143 if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) 0144 return; 0145 up_read(&inode->i_rwsem); 0146 /* Slow path.... */ 0147 down_write(&inode->i_rwsem); 0148 ceph_block_buffered(ci, inode); 0149 downgrade_write(&inode->i_rwsem); 0150 } 0151 0152 /** 0153 * ceph_end_io_direct - declare that the direct i/o operation is done 0154 * @inode: file inode 0155 * 0156 * Declare that a direct I/O operation is done, and release the shared 0157 * lock on inode->i_rwsem. 0158 */ 0159 void 0160 ceph_end_io_direct(struct inode *inode) 0161 { 0162 up_read(&inode->i_rwsem); 0163 }
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |