Merge branch 'omap-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / fs / ubifs / journal.c
index 914f1bd..aed25e8 100644 (file)
@@ -690,7 +690,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 {
        struct ubifs_data_node *data;
        int err, lnum, offs, compr_type, out_len;
-       int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
+       int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
        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,
                DBGKEY(key));
        ubifs_assert(len <= UBIFS_BLOCK_SIZE);
 
-       data = kmalloc(dlen, GFP_NOFS);
-       if (!data)
-               return -ENOMEM;
+       data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
+       if (!data) {
+               /*
+                * Fall-back to the write reserve buffer. Note, we might be
+                * currently on the memory reclaim path, when the kernel is
+                * trying to free some memory by writing out dirty pages. The
+                * write reserve buffer helps us to guarantee that we are
+                * always able to write the data.
+                */
+               allocated = 0;
+               mutex_lock(&c->write_reserve_mutex);
+               data = c->write_reserve_buf;
+       }
 
        data->ch.node_type = UBIFS_DATA_NODE;
        key_write(c, key, &data->key);
@@ -736,7 +746,10 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
                goto out_ro;
 
        finish_reservation(c);
-       kfree(data);
+       if (!allocated)
+               mutex_unlock(&c->write_reserve_mutex);
+       else
+               kfree(data);
        return 0;
 
 out_release:
@@ -745,7 +758,10 @@ out_ro:
        ubifs_ro_mode(c, err);
        finish_reservation(c);
 out_free:
-       kfree(data);
+       if (!allocated)
+               mutex_unlock(&c->write_reserve_mutex);
+       else
+               kfree(data);
        return err;
 }