summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 b74971e19d5..56963e6c46c 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -522,12 +522,17 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
void *private)
{
struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
+ int level;
/* this io's submitter should not have unlocked this before we could */
BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
+
ocfs2_iocb_clear_rw_locked(iocb);
- up_read(&inode->i_alloc_sem);
- ocfs2_rw_unlock(inode, 0);
+
+ level = ocfs2_iocb_rw_locked_level(iocb);
+ if (!level)
+ up_read(&inode->i_alloc_sem);
+ ocfs2_rw_unlock(inode, level);
}
/*
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 1b4ba5356a4..45821d479b5 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,
/* all ocfs2_dio_end_io()'s fault */
#define ocfs2_iocb_is_rw_locked(iocb) \
test_bit(0, (unsigned long *)&iocb->private)
-#define ocfs2_iocb_set_rw_locked(iocb) \
- set_bit(0, (unsigned long *)&iocb->private)
+static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)
+{
+ set_bit(0, (unsigned long *)&iocb->private);
+ if (level)
+ set_bit(1, (unsigned long *)&iocb->private);
+ else
+ clear_bit(1, (unsigned long *)&iocb->private);
+}
#define ocfs2_iocb_clear_rw_locked(iocb) \
clear_bit(0, (unsigned long *)&iocb->private)
-
+#define ocfs2_iocb_rw_locked_level(iocb) \
+ test_bit(1, (unsigned long *)&iocb->private)
#endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index e34474c0467..520a2a6d767 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1542,7 +1542,7 @@ relock:
pos = *ppos;
/* communicate with ocfs2_dio_end_io */
- ocfs2_iocb_set_rw_locked(iocb);
+ ocfs2_iocb_set_rw_locked(iocb, rw_level);
if (direct_io) {
written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
@@ -1788,7 +1788,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
}
rw_level = 0;
/* communicate with ocfs2_dio_end_io */
- ocfs2_iocb_set_rw_locked(iocb);
+ ocfs2_iocb_set_rw_locked(iocb, rw_level);
}
/*