aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/aops.c9
-rw-r--r--fs/ocfs2/aops.h13
-rw-r--r--fs/ocfs2/file.c4
3 files changed, 19 insertions, 7 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index b74971e19d54..56963e6c46c0 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -522,12 +522,17 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
522 void *private) 522 void *private)
523{ 523{
524 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; 524 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
525 int level;
525 526
526 /* this io's submitter should not have unlocked this before we could */ 527 /* this io's submitter should not have unlocked this before we could */
527 BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); 528 BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
529
528 ocfs2_iocb_clear_rw_locked(iocb); 530 ocfs2_iocb_clear_rw_locked(iocb);
529 up_read(&inode->i_alloc_sem); 531
530 ocfs2_rw_unlock(inode, 0); 532 level = ocfs2_iocb_rw_locked_level(iocb);
533 if (!level)
534 up_read(&inode->i_alloc_sem);
535 ocfs2_rw_unlock(inode, level);
531} 536}
532 537
533/* 538/*
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 1b4ba5356a42..45821d479b5a 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -97,9 +97,16 @@ int ocfs2_map_and_write_splice_data(struct inode *inode,
97/* all ocfs2_dio_end_io()'s fault */ 97/* all ocfs2_dio_end_io()'s fault */
98#define ocfs2_iocb_is_rw_locked(iocb) \ 98#define ocfs2_iocb_is_rw_locked(iocb) \
99 test_bit(0, (unsigned long *)&iocb->private) 99 test_bit(0, (unsigned long *)&iocb->private)
100#define ocfs2_iocb_set_rw_locked(iocb) \ 100static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)
101 set_bit(0, (unsigned long *)&iocb->private) 101{
102 set_bit(0, (unsigned long *)&iocb->private);
103 if (level)
104 set_bit(1, (unsigned long *)&iocb->private);
105 else
106 clear_bit(1, (unsigned long *)&iocb->private);
107}
102#define ocfs2_iocb_clear_rw_locked(iocb) \ 108#define ocfs2_iocb_clear_rw_locked(iocb) \
103 clear_bit(0, (unsigned long *)&iocb->private) 109 clear_bit(0, (unsigned long *)&iocb->private)
104 110#define ocfs2_iocb_rw_locked_level(iocb) \
111 test_bit(1, (unsigned long *)&iocb->private)
105#endif /* OCFS2_FILE_H */ 112#endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index e34474c04678..520a2a6d7670 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1542,7 +1542,7 @@ relock:
1542 pos = *ppos; 1542 pos = *ppos;
1543 1543
1544 /* communicate with ocfs2_dio_end_io */ 1544 /* communicate with ocfs2_dio_end_io */
1545 ocfs2_iocb_set_rw_locked(iocb); 1545 ocfs2_iocb_set_rw_locked(iocb, rw_level);
1546 1546
1547 if (direct_io) { 1547 if (direct_io) {
1548 written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, 1548 written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
@@ -1788,7 +1788,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
1788 } 1788 }
1789 rw_level = 0; 1789 rw_level = 0;
1790 /* communicate with ocfs2_dio_end_io */ 1790 /* communicate with ocfs2_dio_end_io */
1791 ocfs2_iocb_set_rw_locked(iocb); 1791 ocfs2_iocb_set_rw_locked(iocb, rw_level);
1792 } 1792 }
1793 1793
1794 /* 1794 /*