X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Ffat%2Finode.c;h=1f92c966203757840498b336f401e587a51fda33;hb=refs%2Fheads%2Fvserver;hp=e7f4aa7fc6864be095def4db3ac8078f7f218052;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/fs/fat/inode.c b/fs/fat/inode.c index e7f4aa7fc..1f92c9662 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #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, - unsigned long max_blocks, - 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; + 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) @@ -196,7 +192,7 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping, block, fat_get_block); } -static struct address_space_operations fat_aops = { +static const struct address_space_operations fat_aops = { .readpage = fat_readpage, .readpages = fat_readpages, .writepage = fat_writepage, @@ -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 = @@ -390,7 +384,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) le16_to_cpu(de->cdate)) + secs; inode->i_ctime.tv_nsec = csecs * 10000000; inode->i_atime.tv_sec = - date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate)); + date_dos2unix(0, le16_to_cpu(de->adate)); inode->i_atime.tv_nsec = 0; } else inode->i_ctime = inode->i_atime = inode->i_mtime; @@ -483,12 +477,12 @@ static void fat_put_super(struct super_block *sb) kfree(sbi); } -static kmem_cache_t *fat_inode_cachep; +static struct kmem_cache *fat_inode_cachep; static struct inode *fat_alloc_inode(struct super_block *sb) { struct msdos_inode_info *ei; - ei = kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL); + ei = kmem_cache_alloc(fat_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode; @@ -499,7 +493,7 @@ static void fat_destroy_inode(struct inode *inode) kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; @@ -518,7 +512,8 @@ static int __init fat_init_inodecache(void) { fat_inode_cachep = kmem_cache_create("fat_inode_cache", sizeof(struct msdos_inode_info), - 0, SLAB_RECLAIM_ACCOUNT, + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), init_once, NULL); if (fat_inode_cachep == NULL) return -ENOMEM; @@ -527,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) @@ -538,18 +532,18 @@ static int fat_remount(struct super_block *sb, int *flags, char *data) return 0; } -static int fat_statfs(struct super_block *sb, struct kstatfs *buf) +static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); /* If the count of free cluster is still unknown, counts it here. */ if (sbi->free_clusters == -1) { - int err = fat_count_free_clusters(sb); + int err = fat_count_free_clusters(dentry->d_sb); if (err) return err; } - buf->f_type = sb->s_magic; + buf->f_type = dentry->d_sb->s_magic; buf->f_bsize = sbi->cluster_size; buf->f_blocks = sbi->max_cluster - FAT_START_ENT; buf->f_bfree = sbi->free_clusters; @@ -860,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 = { @@ -892,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"}, @@ -952,7 +947,8 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->shortname = 0; opts->name_check = 'n'; opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; - opts->utf8 = opts->unicode_xlate = 0; + opts->utf8 = 1; + opts->unicode_xlate = 0; opts->numtail = 1; opts->nocase = 0; *debug = 0; @@ -1033,6 +1029,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: @@ -1101,7 +1100,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, return -EINVAL; } } - /* UTF8 doesn't provide FAT semantics */ + /* UTF-8 doesn't provide FAT semantics */ if (!strcmp(opts->iocharset, "utf8")) { printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" " for FAT filesystems, filesystem will be case sensitive!\n"); @@ -1136,7 +1135,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; @@ -1167,11 +1165,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; @@ -1434,8 +1431,55 @@ out_fail: EXPORT_SYMBOL_GPL(fat_fill_super); -int __init fat_cache_init(void); -void fat_cache_destroy(void); +/* + * 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) { + 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) {