Ocfs2: Teach 'coherency=full' O_DIRECT writes to correctly up_read i_alloc_sem.

Due to newly-introduced 'coherency=full' O_DIRECT writes also takes the EX
rw_lock like buffered writes did(rw_level == 1), it turns out messing the
usage of 'level' in ocfs2_dio_end_io() up, which caused i_alloc_sem being
failed to get up_read'd correctly.

This patch tries to teach ocfs2_dio_end_io to understand well on all locking
stuffs by explicitly introducing a new bit for i_alloc_sem in iocb's private
data, just like what we did for rw_lock.

Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>

authored by Tristan Ye and committed by Joel Becker 39c99f12 388c4bcb

+39 -6
+5 -2
fs/ocfs2/aops.c
··· 573 573 /* this io's submitter should not have unlocked this before we could */ 574 574 BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); 575 575 576 + if (ocfs2_iocb_is_sem_locked(iocb)) { 577 + up_read(&inode->i_alloc_sem); 578 + ocfs2_iocb_clear_sem_locked(iocb); 579 + } 580 + 576 581 ocfs2_iocb_clear_rw_locked(iocb); 577 582 578 583 level = ocfs2_iocb_rw_locked_level(iocb); 579 - if (!level) 580 - up_read(&inode->i_alloc_sem); 581 584 ocfs2_rw_unlock(inode, level); 582 585 583 586 if (is_async)
+21 -2
fs/ocfs2/aops.h
··· 68 68 else 69 69 clear_bit(1, (unsigned long *)&iocb->private); 70 70 } 71 + 72 + /* 73 + * Using a named enum representing lock types in terms of #N bit stored in 74 + * iocb->private, which is going to be used for communication bewteen 75 + * ocfs2_dio_end_io() and ocfs2_file_aio_write/read(). 76 + */ 77 + enum ocfs2_iocb_lock_bits { 78 + OCFS2_IOCB_RW_LOCK = 0, 79 + OCFS2_IOCB_RW_LOCK_LEVEL, 80 + OCFS2_IOCB_SEM, 81 + OCFS2_IOCB_NUM_LOCKS 82 + }; 83 + 71 84 #define ocfs2_iocb_clear_rw_locked(iocb) \ 72 - clear_bit(0, (unsigned long *)&iocb->private) 85 + clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private) 73 86 #define ocfs2_iocb_rw_locked_level(iocb) \ 74 - test_bit(1, (unsigned long *)&iocb->private) 87 + test_bit(OCFS2_IOCB_RW_LOCK_LEVEL, (unsigned long *)&iocb->private) 88 + #define ocfs2_iocb_set_sem_locked(iocb) \ 89 + set_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) 90 + #define ocfs2_iocb_clear_sem_locked(iocb) \ 91 + clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) 92 + #define ocfs2_iocb_is_sem_locked(iocb) \ 93 + test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) 75 94 #endif /* OCFS2_FILE_H */
+13 -2
fs/ocfs2/file.c
··· 2241 2241 2242 2242 mutex_lock(&inode->i_mutex); 2243 2243 2244 + ocfs2_iocb_clear_sem_locked(iocb); 2245 + 2244 2246 relock: 2245 2247 /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ 2246 2248 if (direct_io) { 2247 2249 down_read(&inode->i_alloc_sem); 2248 2250 have_alloc_sem = 1; 2251 + /* communicate with ocfs2_dio_end_io */ 2252 + ocfs2_iocb_set_sem_locked(iocb); 2249 2253 } 2250 2254 2251 2255 /* ··· 2386 2382 ocfs2_rw_unlock(inode, rw_level); 2387 2383 2388 2384 out_sems: 2389 - if (have_alloc_sem) 2385 + if (have_alloc_sem) { 2390 2386 up_read(&inode->i_alloc_sem); 2387 + ocfs2_iocb_clear_sem_locked(iocb); 2388 + } 2391 2389 2392 2390 mutex_unlock(&inode->i_mutex); 2393 2391 ··· 2533 2527 goto bail; 2534 2528 } 2535 2529 2530 + ocfs2_iocb_clear_sem_locked(iocb); 2531 + 2536 2532 /* 2537 2533 * buffered reads protect themselves in ->readpage(). O_DIRECT reads 2538 2534 * need locks to protect pending reads from racing with truncate. ··· 2542 2534 if (filp->f_flags & O_DIRECT) { 2543 2535 down_read(&inode->i_alloc_sem); 2544 2536 have_alloc_sem = 1; 2537 + ocfs2_iocb_set_sem_locked(iocb); 2545 2538 2546 2539 ret = ocfs2_rw_lock(inode, 0); 2547 2540 if (ret < 0) { ··· 2584 2575 } 2585 2576 2586 2577 bail: 2587 - if (have_alloc_sem) 2578 + if (have_alloc_sem) { 2588 2579 up_read(&inode->i_alloc_sem); 2580 + ocfs2_iocb_clear_sem_locked(iocb); 2581 + } 2589 2582 if (rw_level != -1) 2590 2583 ocfs2_rw_unlock(inode, rw_level); 2591 2584 mlog_exit(ret);