X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Ffat%2Finode.c;h=cfaf5877d98bf2da19fa54f1f487a1288ce18c61;hb=9aacd599342fdfc1fb9422f37e900609b7a46249;hp=a9e4688582a2599a7c1df7f3579aa15fe4632a87;hpb=b361735043e3001eadb1d40916fd1a4fca1a9363;p=linux-2.6 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a9e4688582..cfaf5877d9 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifndef CONFIG_FAT_DEFAULT_IOCHARSET @@ -173,10 +174,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, * * But we must fill the remaining area or hole by nul for * updating ->mmu_private. + * + * Return 0, and fallback to normal buffered write. */ loff_t size = offset + iov_length(iov, nr_segs); if (MSDOS_I(inode)->mmu_private < size) - return -EINVAL; + return 0; } /* @@ -351,8 +354,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) } else { /* not a directory */ inode->i_generation |= 1; inode->i_mode = MSDOS_MKMODE(de->attr, - ((sbi->options.showexec && - !is_exec(de->ext)) + ((sbi->options.showexec && !is_exec(de->name + 8)) ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~sbi->options.fs_fmask) | S_IFREG; MSDOS_I(inode)->i_start = le16_to_cpu(de->start); @@ -497,15 +499,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) { - spin_lock_init(&ei->cache_lru_lock); - ei->nr_caches = 0; - ei->cache_valid_id = FAT_CACHE_VALID + 1; - INIT_LIST_HEAD(&ei->cache_lru); - INIT_HLIST_NODE(&ei->i_fat_hash); - inode_init_once(&ei->vfs_inode); - } + spin_lock_init(&ei->cache_lru_lock); + ei->nr_caches = 0; + ei->cache_valid_id = FAT_CACHE_VALID + 1; + INIT_LIST_HEAD(&ei->cache_lru); + INIT_HLIST_NODE(&ei->i_fat_hash); + inode_init_once(&ei->vfs_inode); } static int __init fat_init_inodecache(void) @@ -618,7 +617,7 @@ int fat_sync_inode(struct inode *inode) EXPORT_SYMBOL_GPL(fat_sync_inode); static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); -static struct super_operations fat_sops = { +static const struct super_operations fat_sops = { .alloc_inode = fat_alloc_inode, .destroy_inode = fat_destroy_inode, .write_inode = fat_write_inode, @@ -823,6 +822,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) } if (opts->name_check != 'n') seq_printf(m, ",check=%c", opts->name_check); + if (opts->usefree) + seq_puts(m, ",usefree"); if (opts->quiet) seq_puts(m, ",quiet"); if (opts->showexec) @@ -848,7 +849,7 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) enum { Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, - Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase, + Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, Opt_dots, Opt_nodots, Opt_charset, Opt_shortname_lower, Opt_shortname_win95, @@ -870,6 +871,7 @@ static match_table_t fat_tokens = { {Opt_dmask, "dmask=%o"}, {Opt_fmask, "fmask=%o"}, {Opt_codepage, "codepage=%u"}, + {Opt_usefree, "usefree"}, {Opt_nocase, "nocase"}, {Opt_quiet, "quiet"}, {Opt_showexec, "showexec"}, @@ -949,7 +951,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; opts->utf8 = opts->unicode_xlate = 0; opts->numtail = 1; - opts->nocase = 0; + opts->usefree = opts->nocase = 0; *debug = 0; if (!options) @@ -977,6 +979,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, case Opt_check_n: opts->name_check = 'n'; break; + case Opt_usefree: + opts->usefree = 1; + break; case Opt_nocase: if (!is_vfat) opts->nocase = 1; @@ -1151,7 +1156,7 @@ static int fat_read_root(struct inode *inode) * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, - struct inode_operations *fs_dir_inode_ops, int isvfat) + const struct inode_operations *fs_dir_inode_ops, int isvfat) { struct inode *root_inode = NULL; struct buffer_head *bh; @@ -1216,8 +1221,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, } logical_sector_size = le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); - if (!logical_sector_size - || (logical_sector_size & (logical_sector_size - 1)) + if (!is_power_of_2(logical_sector_size) || (logical_sector_size < 512) || (PAGE_CACHE_SIZE < logical_sector_size)) { if (!silent) @@ -1227,8 +1231,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, goto out_invalid; } sbi->sec_per_clus = b->sec_per_clus; - if (!sbi->sec_per_clus - || (sbi->sec_per_clus & (sbi->sec_per_clus - 1))) { + if (!is_power_of_2(sbi->sec_per_clus)) { if (!silent) printk(KERN_ERR "FAT: bogus sectors per cluster %u\n", sbi->sec_per_clus); @@ -1304,7 +1307,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, le32_to_cpu(fsinfo->signature2), sbi->fsinfo_sector); } else { - sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters); + if (sbi->options.usefree) + sbi->free_clusters = + le32_to_cpu(fsinfo->free_clusters); sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); }