diff options
Diffstat (limited to 'fs/ubifs/journal.c')
-rw-r--r-- | fs/ubifs/journal.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 914f1bd89e57..aed25e864227 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
@@ -690,7 +690,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
690 | { | 690 | { |
691 | struct ubifs_data_node *data; | 691 | struct ubifs_data_node *data; |
692 | int err, lnum, offs, compr_type, out_len; | 692 | int err, lnum, offs, compr_type, out_len; |
693 | int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR; | 693 | int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1; |
694 | struct ubifs_inode *ui = ubifs_inode(inode); | 694 | struct ubifs_inode *ui = ubifs_inode(inode); |
695 | 695 | ||
696 | dbg_jnl("ino %lu, blk %u, len %d, key %s", | 696 | dbg_jnl("ino %lu, blk %u, len %d, key %s", |
@@ -698,9 +698,19 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
698 | DBGKEY(key)); | 698 | DBGKEY(key)); |
699 | ubifs_assert(len <= UBIFS_BLOCK_SIZE); | 699 | ubifs_assert(len <= UBIFS_BLOCK_SIZE); |
700 | 700 | ||
701 | data = kmalloc(dlen, GFP_NOFS); | 701 | data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN); |
702 | if (!data) | 702 | if (!data) { |
703 | return -ENOMEM; | 703 | /* |
704 | * Fall-back to the write reserve buffer. Note, we might be | ||
705 | * currently on the memory reclaim path, when the kernel is | ||
706 | * trying to free some memory by writing out dirty pages. The | ||
707 | * write reserve buffer helps us to guarantee that we are | ||
708 | * always able to write the data. | ||
709 | */ | ||
710 | allocated = 0; | ||
711 | mutex_lock(&c->write_reserve_mutex); | ||
712 | data = c->write_reserve_buf; | ||
713 | } | ||
704 | 714 | ||
705 | data->ch.node_type = UBIFS_DATA_NODE; | 715 | data->ch.node_type = UBIFS_DATA_NODE; |
706 | key_write(c, key, &data->key); | 716 | key_write(c, key, &data->key); |
@@ -736,7 +746,10 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
736 | goto out_ro; | 746 | goto out_ro; |
737 | 747 | ||
738 | finish_reservation(c); | 748 | finish_reservation(c); |
739 | kfree(data); | 749 | if (!allocated) |
750 | mutex_unlock(&c->write_reserve_mutex); | ||
751 | else | ||
752 | kfree(data); | ||
740 | return 0; | 753 | return 0; |
741 | 754 | ||
742 | out_release: | 755 | out_release: |
@@ -745,7 +758,10 @@ out_ro: | |||
745 | ubifs_ro_mode(c, err); | 758 | ubifs_ro_mode(c, err); |
746 | finish_reservation(c); | 759 | finish_reservation(c); |
747 | out_free: | 760 | out_free: |
748 | kfree(data); | 761 | if (!allocated) |
762 | mutex_unlock(&c->write_reserve_mutex); | ||
763 | else | ||
764 | kfree(data); | ||
749 | return err; | 765 | return err; |
750 | } | 766 | } |
751 | 767 | ||