aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2010-07-27 11:56:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2010-07-27 11:56:05 -0400
commit47def82672b3ba4e7c5e9a4fe48a556f8684d0d6 (patch)
treea0cfdaca8be99980c09d2b38ff676834c85ab2c4
parent40389687382bf0ae71458e7c0f828137a438a956 (diff)
jbd2: Remove __GFP_NOFAIL from jbd2 layer
__GFP_NOFAIL is going away, so add our own retry loop. Also add jbd2__journal_start() and jbd2__journal_restart() which take a gfp mask, so that file systems can optionally (re)start transaction handles using GFP_KERNEL. If they do this, then they need to be prepared to handle receiving an PTR_ERR(-ENOMEM) error, and be ready to reflect that error up to userspace. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/jbd2/journal.c15
-rw-r--r--fs/jbd2/transaction.c61
-rw-r--r--include/linux/jbd2.h4
3 files changed, 57 insertions, 23 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index f7bf15787d68..a79d3345b55a 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -41,6 +41,7 @@
41#include <linux/hash.h> 41#include <linux/hash.h>
42#include <linux/log2.h> 42#include <linux/log2.h>
43#include <linux/vmalloc.h> 43#include <linux/vmalloc.h>
44#include <linux/backing-dev.h>
44 45
45#define CREATE_TRACE_POINTS 46#define CREATE_TRACE_POINTS
46#include <trace/events/jbd2.h> 47#include <trace/events/jbd2.h>
@@ -48,8 +49,6 @@
48#include <asm/uaccess.h> 49#include <asm/uaccess.h>
49#include <asm/page.h> 50#include <asm/page.h>
50 51
51EXPORT_SYMBOL(jbd2_journal_start);
52EXPORT_SYMBOL(jbd2_journal_restart);
53EXPORT_SYMBOL(jbd2_journal_extend); 52EXPORT_SYMBOL(jbd2_journal_extend);
54EXPORT_SYMBOL(jbd2_journal_stop); 53EXPORT_SYMBOL(jbd2_journal_stop);
55EXPORT_SYMBOL(jbd2_journal_lock_updates); 54EXPORT_SYMBOL(jbd2_journal_lock_updates);
@@ -311,7 +310,17 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
311 */ 310 */
312 J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); 311 J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
313 312
314 new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); 313retry_alloc:
314 new_bh = alloc_buffer_head(GFP_NOFS);
315 if (!new_bh) {
316 /*
317 * Failure is not an option, but __GFP_NOFAIL is going
318 * away; so we retry ourselves here.
319 */
320 congestion_wait(BLK_RW_ASYNC, HZ/50);
321 goto retry_alloc;
322 }
323
315 /* keep subsequent assertions sane */ 324 /* keep subsequent assertions sane */
316 new_bh->b_state = 0; 325 new_bh->b_state = 0;
317 init_buffer(new_bh, NULL, NULL); 326 init_buffer(new_bh, NULL, NULL);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index e214d68620ac..001e95fb0fe1 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -26,6 +26,8 @@
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/highmem.h> 27#include <linux/highmem.h>
28#include <linux/hrtimer.h> 28#include <linux/hrtimer.h>
29#include <linux/backing-dev.h>
30#include <linux/module.h>
29 31
30static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); 32static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
31 33
@@ -83,30 +85,38 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
83 * transaction's buffer credits. 85 * transaction's buffer credits.
84 */ 86 */
85 87
86static int start_this_handle(journal_t *journal, handle_t *handle) 88static int start_this_handle(journal_t *journal, handle_t *handle,
89 int gfp_mask)
87{ 90{
88 transaction_t *transaction; 91 transaction_t *transaction;
89 int needed; 92 int needed;
90 int nblocks = handle->h_buffer_credits; 93 int nblocks = handle->h_buffer_credits;
91 transaction_t *new_transaction = NULL; 94 transaction_t *new_transaction = NULL;
92 int ret = 0;
93 unsigned long ts = jiffies; 95 unsigned long ts = jiffies;
94 96
95 if (nblocks > journal->j_max_transaction_buffers) { 97 if (nblocks > journal->j_max_transaction_buffers) {
96 printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", 98 printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
97 current->comm, nblocks, 99 current->comm, nblocks,
98 journal->j_max_transaction_buffers); 100 journal->j_max_transaction_buffers);
99 ret = -ENOSPC; 101 return -ENOSPC;
100 goto out;
101 } 102 }
102 103
103alloc_transaction: 104alloc_transaction:
104 if (!journal->j_running_transaction) { 105 if (!journal->j_running_transaction) {
105 new_transaction = kzalloc(sizeof(*new_transaction), 106 new_transaction = kzalloc(sizeof(*new_transaction), gfp_mask);
106 GFP_NOFS|__GFP_NOFAIL);
107 if (!new_transaction) { 107 if (!new_transaction) {
108 ret = -ENOMEM; 108 /*
109 goto out; 109 * If __GFP_FS is not present, then we may be
110 * being called from inside the fs writeback
111 * layer, so we MUST NOT fail. Since
112 * __GFP_NOFAIL is going away, we will arrange
113 * to retry the allocation ourselves.
114 */
115 if ((gfp_mask & __GFP_FS) == 0) {
116 congestion_wait(BLK_RW_ASYNC, HZ/50);
117 goto alloc_transaction;
118 }
119 return -ENOMEM;
110 } 120 }
111 } 121 }
112 122
@@ -123,8 +133,8 @@ repeat_locked:
123 if (is_journal_aborted(journal) || 133 if (is_journal_aborted(journal) ||
124 (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { 134 (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) {
125 spin_unlock(&journal->j_state_lock); 135 spin_unlock(&journal->j_state_lock);
126 ret = -EROFS; 136 kfree(new_transaction);
127 goto out; 137 return -EROFS;
128 } 138 }
129 139
130 /* Wait on the journal's transaction barrier if necessary */ 140 /* Wait on the journal's transaction barrier if necessary */
@@ -240,10 +250,8 @@ repeat_locked:
240 spin_unlock(&journal->j_state_lock); 250 spin_unlock(&journal->j_state_lock);
241 251
242 lock_map_acquire(&handle->h_lockdep_map); 252 lock_map_acquire(&handle->h_lockdep_map);
243out: 253 kfree(new_transaction);
244 if (unlikely(new_transaction)) /* It's usually NULL */ 254 return 0;
245 kfree(new_transaction);
246 return ret;
247} 255}
248 256
249static struct lock_class_key jbd2_handle_key; 257static struct lock_class_key jbd2_handle_key;
@@ -278,7 +286,7 @@ static handle_t *new_handle(int nblocks)
278 * 286 *
279 * Return a pointer to a newly allocated handle, or NULL on failure 287 * Return a pointer to a newly allocated handle, or NULL on failure
280 */ 288 */
281handle_t *jbd2_journal_start(journal_t *journal, int nblocks) 289handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask)
282{ 290{
283 handle_t *handle = journal_current_handle(); 291 handle_t *handle = journal_current_handle();
284 int err; 292 int err;
@@ -298,7 +306,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
298 306
299 current->journal_info = handle; 307 current->journal_info = handle;
300 308
301 err = start_this_handle(journal, handle); 309 err = start_this_handle(journal, handle, gfp_mask);
302 if (err < 0) { 310 if (err < 0) {
303 jbd2_free_handle(handle); 311 jbd2_free_handle(handle);
304 current->journal_info = NULL; 312 current->journal_info = NULL;
@@ -308,6 +316,15 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
308out: 316out:
309 return handle; 317 return handle;
310} 318}
319EXPORT_SYMBOL(jbd2__journal_start);
320
321
322handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
323{
324 return jbd2__journal_start(journal, nblocks, GFP_NOFS);
325}
326EXPORT_SYMBOL(jbd2_journal_start);
327
311 328
312/** 329/**
313 * int jbd2_journal_extend() - extend buffer credits. 330 * int jbd2_journal_extend() - extend buffer credits.
@@ -394,8 +411,7 @@ out:
394 * transaction capabable of guaranteeing the requested number of 411 * transaction capabable of guaranteeing the requested number of
395 * credits. 412 * credits.
396 */ 413 */
397 414int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
398int jbd2_journal_restart(handle_t *handle, int nblocks)
399{ 415{
400 transaction_t *transaction = handle->h_transaction; 416 transaction_t *transaction = handle->h_transaction;
401 journal_t *journal = transaction->t_journal; 417 journal_t *journal = transaction->t_journal;
@@ -428,10 +444,17 @@ int jbd2_journal_restart(handle_t *handle, int nblocks)
428 444
429 lock_map_release(&handle->h_lockdep_map); 445 lock_map_release(&handle->h_lockdep_map);
430 handle->h_buffer_credits = nblocks; 446 handle->h_buffer_credits = nblocks;
431 ret = start_this_handle(journal, handle); 447 ret = start_this_handle(journal, handle, gfp_mask);
432 return ret; 448 return ret;
433} 449}
450EXPORT_SYMBOL(jbd2__journal_restart);
451
434 452
453int jbd2_journal_restart(handle_t *handle, int nblocks)
454{
455 return jbd2__journal_restart(handle, nblocks, GFP_NOFS);
456}
457EXPORT_SYMBOL(jbd2_journal_restart);
435 458
436/** 459/**
437 * void jbd2_journal_lock_updates () - establish a transaction barrier. 460 * void jbd2_journal_lock_updates () - establish a transaction barrier.
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index a4d2e9f7088a..5a72bc75b273 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1081,7 +1081,9 @@ static inline handle_t *journal_current_handle(void)
1081 */ 1081 */
1082 1082
1083extern handle_t *jbd2_journal_start(journal_t *, int nblocks); 1083extern handle_t *jbd2_journal_start(journal_t *, int nblocks);
1084extern int jbd2_journal_restart (handle_t *, int nblocks); 1084extern handle_t *jbd2__journal_start(journal_t *, int nblocks, int gfp_mask);
1085extern int jbd2_journal_restart(handle_t *, int nblocks);
1086extern int jbd2__journal_restart(handle_t *, int nblocks, int gfp_mask);
1085extern int jbd2_journal_extend (handle_t *, int nblocks); 1087extern int jbd2_journal_extend (handle_t *, int nblocks);
1086extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *); 1088extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
1087extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *); 1089extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *);