]> err.no Git - linux-2.6/blobdiff - fs/ext2/inode.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6] / fs / ext2 / inode.c
index b890be02249637060adf34e0648e890f0b0a9c51..e7d3f0522d0165fc1f7d6ceb5aad03b607e168b2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mpage.h>
 #include "ext2.h"
 #include "acl.h"
+#include "xip.h"
 
 MODULE_AUTHOR("Remy Card and others");
 MODULE_DESCRIPTION("Second Extended Filesystem");
@@ -52,11 +53,26 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
                inode->i_blocks - ea_blocks == 0);
 }
 
+/*
+ * Called at each iput().
+ *
+ * The inode may be "bad" if ext2_read_inode() saw an error from
+ * ext2_get_inode(), so we need to check that to avoid freeing random disk
+ * blocks.
+ */
+void ext2_put_inode(struct inode *inode)
+{
+       if (!is_bad_inode(inode))
+               ext2_discard_prealloc(inode);
+}
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
 void ext2_delete_inode (struct inode * inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (is_bad_inode(inode))
                goto no_delete;
        EXT2_I(inode)->i_dtime  = get_seconds();
@@ -424,6 +440,10 @@ static int ext2_alloc_branch(struct inode *inode,
                 * the pointer to new one, then send parent to disk.
                 */
                bh = sb_getblk(inode->i_sb, parent);
+               if (!bh) {
+                       err = -EIO;
+                       break;
+               }
                lock_buffer(bh);
                memset(bh->b_data, 0, blocksize);
                branch[n].bh = bh;
@@ -581,6 +601,16 @@ out:
        if (err)
                goto cleanup;
 
+       if (ext2_use_xip(inode->i_sb)) {
+               /*
+                * we need to clear the block
+                */
+               err = ext2_clear_xip_target (inode,
+                       le32_to_cpu(chain[depth-1].key));
+               if (err)
+                       goto cleanup;
+       }
+
        if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
                goto changed;
 
@@ -678,6 +708,11 @@ struct address_space_operations ext2_aops = {
        .writepages             = ext2_writepages,
 };
 
+struct address_space_operations ext2_aops_xip = {
+       .bmap                   = ext2_bmap,
+       .get_xip_page           = ext2_get_xip_page,
+};
+
 struct address_space_operations ext2_nobh_aops = {
        .readpage               = ext2_readpage,
        .readpages              = ext2_readpages,
@@ -897,7 +932,9 @@ void ext2_truncate (struct inode * inode)
        iblock = (inode->i_size + blocksize-1)
                                        >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
 
-       if (test_opt(inode->i_sb, NOBH))
+       if (mapping_is_xip(inode->i_mapping))
+               xip_truncate_page(inode->i_mapping, inode->i_size);
+       else if (test_opt(inode->i_sb, NOBH))
                nobh_truncate_page(inode->i_mapping, inode->i_size);
        else
                block_truncate_page(inode->i_mapping,
@@ -1097,11 +1134,16 @@ void ext2_read_inode (struct inode * inode)
 
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &ext2_file_inode_operations;
-               inode->i_fop = &ext2_file_operations;
-               if (test_opt(inode->i_sb, NOBH))
+               if (ext2_use_xip(inode->i_sb)) {
+                       inode->i_mapping->a_ops = &ext2_aops_xip;
+                       inode->i_fop = &ext2_xip_file_operations;
+               } else if (test_opt(inode->i_sb, NOBH)) {
                        inode->i_mapping->a_ops = &ext2_nobh_aops;
-               else
+                       inode->i_fop = &ext2_file_operations;
+               } else {
                        inode->i_mapping->a_ops = &ext2_aops;
+                       inode->i_fop = &ext2_file_operations;
+               }
        } else if (S_ISDIR(inode->i_mode)) {
                inode->i_op = &ext2_dir_inode_operations;
                inode->i_fop = &ext2_dir_operations;