Merge branch 'master' into upstream
[sfrench/cifs-2.6.git] / fs / fat / inode.c
index 31b7174176ba76798284286e8f6767419cef7e12..045738032a83d5f4579208881d17088a65326e5a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
+#include <linux/writeback.h>
 #include <asm/unaligned.h>
 
 #ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -50,14 +51,14 @@ static int fat_add_cluster(struct inode *inode)
        return err;
 }
 
-static int __fat_get_blocks(struct inode *inode, sector_t iblock,
-                           unsigned long *max_blocks,
-                           struct buffer_head *bh_result, int create)
+static inline int __fat_get_block(struct inode *inode, sector_t iblock,
+                                 unsigned long *max_blocks,
+                                 struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       sector_t phys;
        unsigned long mapped_blocks;
+       sector_t phys;
        int err, offset;
 
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
@@ -73,7 +74,7 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
 
        if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
                fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
-                            MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
+                       MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
                return -EIO;
        }
 
@@ -93,34 +94,29 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
        if (err)
                return err;
+
        BUG_ON(!phys);
        BUG_ON(*max_blocks != mapped_blocks);
        set_buffer_new(bh_result);
        map_bh(bh_result, sb, phys);
+
        return 0;
 }
 
-static int fat_get_blocks(struct inode *inode, sector_t iblock,
-                         struct buffer_head *bh_result, int create)
+static int fat_get_block(struct inode *inode, sector_t iblock,
+                        struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
-       int err;
        unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
+       int err;
 
-       err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
+       err = __fat_get_block(inode, iblock, &max_blocks, bh_result, create);
        if (err)
                return err;
        bh_result->b_size = max_blocks << sb->s_blocksize_bits;
        return 0;
 }
 
-static int fat_get_block(struct inode *inode, sector_t iblock,
-                        struct buffer_head *bh_result, int create)
-{
-       unsigned long max_blocks = 1;
-       return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
-}
-
 static int fat_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page, fat_get_block, wbc);
@@ -188,7 +184,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
         * condition of fat_get_block() and ->truncate().
         */
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                                 offset, nr_segs, fat_get_blocks, NULL);
+                                 offset, nr_segs, fat_get_block, NULL);
 }
 
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
@@ -375,8 +371,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                        inode->i_flags |= S_IMMUTABLE;
        }
        MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
-       /* this is as close to the truth as we can get ... */
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        inode->i_mtime.tv_sec =
@@ -528,8 +522,7 @@ static int __init fat_init_inodecache(void)
 
 static void __exit fat_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(fat_inode_cachep))
-               printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(fat_inode_cachep);
 }
 
 static int fat_remount(struct super_block *sb, int *flags, char *data)
@@ -861,7 +854,7 @@ enum {
        Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
        Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
        Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
-       Opt_obsolate, Opt_err,
+       Opt_obsolate, Opt_flush, Opt_err,
 };
 
 static match_table_t fat_tokens = {
@@ -893,7 +886,8 @@ static match_table_t fat_tokens = {
        {Opt_obsolate, "cvf_format=%20s"},
        {Opt_obsolate, "cvf_options=%100s"},
        {Opt_obsolate, "posix"},
-       {Opt_err, NULL}
+       {Opt_flush, "flush"},
+       {Opt_err, NULL},
 };
 static match_table_t msdos_tokens = {
        {Opt_nodots, "nodots"},
@@ -1034,6 +1028,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                                return 0;
                        opts->codepage = option;
                        break;
+               case Opt_flush:
+                       opts->flush = 1;
+                       break;
 
                /* msdos specific */
                case Opt_dots:
@@ -1137,7 +1134,6 @@ static int fat_read_root(struct inode *inode)
                MSDOS_I(inode)->i_start = 0;
                inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
        }
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        MSDOS_I(inode)->i_logstart = 0;
@@ -1168,11 +1164,10 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        long error;
        char buf[50];
 
-       sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct msdos_sb_info));
 
        sb->s_flags |= MS_NODIRATIME;
        sb->s_magic = MSDOS_SUPER_MAGIC;
@@ -1435,6 +1430,56 @@ out_fail:
 
 EXPORT_SYMBOL_GPL(fat_fill_super);
 
+/*
+ * helper function for fat_flush_inodes.  This writes both the inode
+ * and the file data blocks, waiting for in flight data blocks before
+ * the start of the call.  It does not wait for any io started
+ * during the call
+ */
+static int writeback_inode(struct inode *inode)
+{
+
+       int ret;
+       struct address_space *mapping = inode->i_mapping;
+       struct writeback_control wbc = {
+              .sync_mode = WB_SYNC_NONE,
+             .nr_to_write = 0,
+       };
+       /* if we used WB_SYNC_ALL, sync_inode waits for the io for the
+       * inode to finish.  So WB_SYNC_NONE is sent down to sync_inode
+       * and filemap_fdatawrite is used for the data blocks
+       */
+       ret = sync_inode(inode, &wbc);
+       if (!ret)
+              ret = filemap_fdatawrite(mapping);
+       return ret;
+}
+
+/*
+ * write data and metadata corresponding to i1 and i2.  The io is
+ * started but we do not wait for any of it to finish.
+ *
+ * filemap_flush is used for the block device, so if there is a dirty
+ * page for a block already in flight, we will not wait and start the
+ * io over again
+ */
+int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
+{
+       int ret = 0;
+       if (!MSDOS_SB(sb)->options.flush)
+               return 0;
+       if (i1)
+               ret = writeback_inode(i1);
+       if (!ret && i2)
+               ret = writeback_inode(i2);
+       if (!ret && sb) {
+               struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+               ret = filemap_flush(mapping);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(fat_flush_inodes);
+
 static int __init init_fat_fs(void)
 {
        int err;