aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-06-04 12:37:50 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-06-04 12:37:50 -0400
commit5fe2fe895a9a6b857e2f3a7fc5b8f080b03fd55f (patch)
tree4413bc3674762e6f8accef300c5ea07f76911336 /fs/ext4
parent8f7d89f36829b9061a14f9040cda1372f264c4fe (diff)
ext4: provide wrappers for transaction reservation calls
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4_jbd2.c58
-rw-r--r--fs/ext4/ext4_jbd2.h26
-rw-r--r--fs/ext4/ialloc.c3
3 files changed, 70 insertions, 17 deletions
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index bd25e782ec6b..72a3600aedbd 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -38,31 +38,43 @@ static void ext4_put_nojournal(handle_t *handle)
38/* 38/*
39 * Wrappers for jbd2_journal_start/end. 39 * Wrappers for jbd2_journal_start/end.
40 */ 40 */
41handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, 41static int ext4_journal_check_start(struct super_block *sb)
42 int type, int nblocks)
43{ 42{
44 journal_t *journal; 43 journal_t *journal;
45 44
46 might_sleep(); 45 might_sleep();
47
48 trace_ext4_journal_start(sb, nblocks, _RET_IP_);
49 if (sb->s_flags & MS_RDONLY) 46 if (sb->s_flags & MS_RDONLY)
50 return ERR_PTR(-EROFS); 47 return -EROFS;
51
52 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); 48 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
53 journal = EXT4_SB(sb)->s_journal; 49 journal = EXT4_SB(sb)->s_journal;
54 if (!journal)
55 return ext4_get_nojournal();
56 /* 50 /*
57 * Special case here: if the journal has aborted behind our 51 * Special case here: if the journal has aborted behind our
58 * backs (eg. EIO in the commit thread), then we still need to 52 * backs (eg. EIO in the commit thread), then we still need to
59 * take the FS itself readonly cleanly. 53 * take the FS itself readonly cleanly.
60 */ 54 */
61 if (is_journal_aborted(journal)) { 55 if (journal && is_journal_aborted(journal)) {
62 ext4_abort(sb, "Detected aborted journal"); 56 ext4_abort(sb, "Detected aborted journal");
63 return ERR_PTR(-EROFS); 57 return -EROFS;
64 } 58 }
65 return jbd2__journal_start(journal, nblocks, 0, GFP_NOFS, type, line); 59 return 0;
60}
61
62handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
63 int type, int blocks, int rsv_blocks)
64{
65 journal_t *journal;
66 int err;
67
68 trace_ext4_journal_start(sb, blocks, rsv_blocks, _RET_IP_);
69 err = ext4_journal_check_start(sb);
70 if (err < 0)
71 return ERR_PTR(err);
72
73 journal = EXT4_SB(sb)->s_journal;
74 if (!journal)
75 return ext4_get_nojournal();
76 return jbd2__journal_start(journal, blocks, rsv_blocks, GFP_NOFS,
77 type, line);
66} 78}
67 79
68int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) 80int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
@@ -86,6 +98,30 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
86 return err; 98 return err;
87} 99}
88 100
101handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
102 int type)
103{
104 struct super_block *sb;
105 int err;
106
107 if (!ext4_handle_valid(handle))
108 return ext4_get_nojournal();
109
110 sb = handle->h_journal->j_private;
111 trace_ext4_journal_start_reserved(sb, handle->h_buffer_credits,
112 _RET_IP_);
113 err = ext4_journal_check_start(sb);
114 if (err < 0) {
115 jbd2_journal_free_reserved(handle);
116 return ERR_PTR(err);
117 }
118
119 err = jbd2_journal_start_reserved(handle, type, line);
120 if (err < 0)
121 return ERR_PTR(err);
122 return handle;
123}
124
89void ext4_journal_abort_handle(const char *caller, unsigned int line, 125void ext4_journal_abort_handle(const char *caller, unsigned int line,
90 const char *err_fn, struct buffer_head *bh, 126 const char *err_fn, struct buffer_head *bh,
91 handle_t *handle, int err) 127 handle_t *handle, int err)
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index c8c6885406db..fdd865eb1879 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -265,7 +265,7 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
265 __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb)) 265 __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
266 266
267handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, 267handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
268 int type, int nblocks); 268 int type, int blocks, int rsv_blocks);
269int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle); 269int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
270 270
271#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096) 271#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)
@@ -300,21 +300,37 @@ static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed)
300} 300}
301 301
302#define ext4_journal_start_sb(sb, type, nblocks) \ 302#define ext4_journal_start_sb(sb, type, nblocks) \
303 __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks)) 303 __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks), 0)
304 304
305#define ext4_journal_start(inode, type, nblocks) \ 305#define ext4_journal_start(inode, type, nblocks) \
306 __ext4_journal_start((inode), __LINE__, (type), (nblocks)) 306 __ext4_journal_start((inode), __LINE__, (type), (nblocks), 0)
307
308#define ext4_journal_start_with_reserve(inode, type, blocks, rsv_blocks) \
309 __ext4_journal_start((inode), __LINE__, (type), (blocks), (rsv_blocks))
307 310
308static inline handle_t *__ext4_journal_start(struct inode *inode, 311static inline handle_t *__ext4_journal_start(struct inode *inode,
309 unsigned int line, int type, 312 unsigned int line, int type,
310 int nblocks) 313 int blocks, int rsv_blocks)
311{ 314{
312 return __ext4_journal_start_sb(inode->i_sb, line, type, nblocks); 315 return __ext4_journal_start_sb(inode->i_sb, line, type, blocks,
316 rsv_blocks);
313} 317}
314 318
315#define ext4_journal_stop(handle) \ 319#define ext4_journal_stop(handle) \
316 __ext4_journal_stop(__func__, __LINE__, (handle)) 320 __ext4_journal_stop(__func__, __LINE__, (handle))
317 321
322#define ext4_journal_start_reserve(handle, type) \
323 __ext4_journal_start_reserved((handle), __LINE__, (type))
324
325handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
326 int type);
327
328static inline void ext4_journal_free_reserved(handle_t *handle)
329{
330 if (ext4_handle_valid(handle))
331 jbd2_journal_free_reserved(handle);
332}
333
318static inline handle_t *ext4_journal_current_handle(void) 334static inline handle_t *ext4_journal_current_handle(void)
319{ 335{
320 return journal_current_handle(); 336 return journal_current_handle();
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 00a818d67b54..f03598c6ffd3 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -747,7 +747,8 @@ repeat_in_this_group:
747 if (!handle) { 747 if (!handle) {
748 BUG_ON(nblocks <= 0); 748 BUG_ON(nblocks <= 0);
749 handle = __ext4_journal_start_sb(dir->i_sb, line_no, 749 handle = __ext4_journal_start_sb(dir->i_sb, line_no,
750 handle_type, nblocks); 750 handle_type, nblocks,
751 0);
751 if (IS_ERR(handle)) { 752 if (IS_ERR(handle)) {
752 err = PTR_ERR(handle); 753 err = PTR_ERR(handle);
753 ext4_std_error(sb, err); 754 ext4_std_error(sb, err);