2121/* Call with exclusively locked inode->i_rwsem */
2222static void ceph_block_o_direct (struct ceph_inode_info * ci , struct inode * inode )
2323{
24+ bool is_odirect ;
25+
2426 lockdep_assert_held_write (& inode -> i_rwsem );
2527
26- if (READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ) {
27- spin_lock (& ci -> i_ceph_lock );
28- ci -> i_ceph_flags &= ~CEPH_I_ODIRECT ;
29- spin_unlock (& ci -> i_ceph_lock );
30- inode_dio_wait (inode );
28+ spin_lock (& ci -> i_ceph_lock );
29+ /* ensure that bit state is consistent */
30+ smp_mb__before_atomic ();
31+ is_odirect = READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ;
32+ if (is_odirect ) {
33+ clear_bit (CEPH_I_ODIRECT_BIT , & ci -> i_ceph_flags );
34+ /* ensure modified bit is visible */
35+ smp_mb__after_atomic ();
3136 }
37+ spin_unlock (& ci -> i_ceph_lock );
38+
39+ if (is_odirect )
40+ inode_dio_wait (inode );
3241}
3342
3443/**
@@ -50,14 +59,20 @@ static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode)
5059int ceph_start_io_read (struct inode * inode )
5160{
5261 struct ceph_inode_info * ci = ceph_inode (inode );
62+ bool is_odirect ;
5363 int err ;
5464
5565 /* Be an optimist! */
5666 err = down_read_killable (& inode -> i_rwsem );
5767 if (err )
5868 return err ;
5969
60- if (!(READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ))
70+ spin_lock (& ci -> i_ceph_lock );
71+ /* ensure that bit state is consistent */
72+ smp_mb__before_atomic ();
73+ is_odirect = READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ;
74+ spin_unlock (& ci -> i_ceph_lock );
75+ if (!is_odirect )
6176 return 0 ;
6277 up_read (& inode -> i_rwsem );
6378
@@ -116,12 +131,22 @@ ceph_end_io_write(struct inode *inode)
116131/* Call with exclusively locked inode->i_rwsem */
117132static void ceph_block_buffered (struct ceph_inode_info * ci , struct inode * inode )
118133{
134+ bool is_odirect ;
135+
119136 lockdep_assert_held_write (& inode -> i_rwsem );
120137
121- if (!(READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT )) {
122- spin_lock (& ci -> i_ceph_lock );
123- ci -> i_ceph_flags |= CEPH_I_ODIRECT ;
124- spin_unlock (& ci -> i_ceph_lock );
138+ spin_lock (& ci -> i_ceph_lock );
139+ /* ensure that bit state is consistent */
140+ smp_mb__before_atomic ();
141+ is_odirect = READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ;
142+ if (!is_odirect ) {
143+ set_bit (CEPH_I_ODIRECT_BIT , & ci -> i_ceph_flags );
144+ /* ensure modified bit is visible */
145+ smp_mb__after_atomic ();
146+ }
147+ spin_unlock (& ci -> i_ceph_lock );
148+
149+ if (!is_odirect ) {
125150 /* FIXME: unmap_mapping_range? */
126151 filemap_write_and_wait (inode -> i_mapping );
127152 }
@@ -146,14 +171,20 @@ static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode)
146171int ceph_start_io_direct (struct inode * inode )
147172{
148173 struct ceph_inode_info * ci = ceph_inode (inode );
174+ bool is_odirect ;
149175 int err ;
150176
151177 /* Be an optimist! */
152178 err = down_read_killable (& inode -> i_rwsem );
153179 if (err )
154180 return err ;
155181
156- if (READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT )
182+ spin_lock (& ci -> i_ceph_lock );
183+ /* ensure that bit state is consistent */
184+ smp_mb__before_atomic ();
185+ is_odirect = READ_ONCE (ci -> i_ceph_flags ) & CEPH_I_ODIRECT ;
186+ spin_unlock (& ci -> i_ceph_lock );
187+ if (is_odirect )
157188 return 0 ;
158189 up_read (& inode -> i_rwsem );
159190
0 commit comments