xfs: remove duplicated #include
[safe/jmp/linux-2.6] / fs / fat / inode.c
index 37a8af1..0ce143b 100644 (file)
@@ -76,7 +76,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
                return 0;
 
        if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
-               fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
+               fat_fs_error(sb, "corrupted file size (i_pos %lld, %lld)",
                        MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
                return -EIO;
        }
@@ -202,9 +202,9 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
        sector_t blocknr;
 
        /* fat_get_cluster() assumes the requested blocknr isn't truncated. */
-       mutex_lock(&mapping->host->i_mutex);
+       down_read(&mapping->host->i_alloc_sem);
        blocknr = generic_block_bmap(mapping, block, fat_get_block);
-       mutex_unlock(&mapping->host->i_mutex);
+       up_read(&mapping->host->i_alloc_sem);
 
        return blocknr;
 }
@@ -441,32 +441,49 @@ static void fat_clear_inode(struct inode *inode)
 
 static void fat_write_super(struct super_block *sb)
 {
+       lock_super(sb);
        sb->s_dirt = 0;
 
        if (!(sb->s_flags & MS_RDONLY))
                fat_clusters_flush(sb);
+       unlock_super(sb);
+}
+
+static int fat_sync_fs(struct super_block *sb, int wait)
+{
+       int err = 0;
+
+       if (sb->s_dirt) {
+               lock_super(sb);
+               sb->s_dirt = 0;
+               err = fat_clusters_flush(sb);
+               unlock_super(sb);
+       }
+
+       return err;
 }
 
 static void fat_put_super(struct super_block *sb)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-       if (sbi->nls_disk) {
-               unload_nls(sbi->nls_disk);
-               sbi->nls_disk = NULL;
-               sbi->options.codepage = fat_default_codepage;
-       }
-       if (sbi->nls_io) {
-               unload_nls(sbi->nls_io);
-               sbi->nls_io = NULL;
-       }
-       if (sbi->options.iocharset != fat_default_iocharset) {
+       lock_kernel();
+
+       if (sb->s_dirt)
+               fat_write_super(sb);
+
+       iput(sbi->fat_inode);
+
+       unload_nls(sbi->nls_disk);
+       unload_nls(sbi->nls_io);
+
+       if (sbi->options.iocharset != fat_default_iocharset)
                kfree(sbi->options.iocharset);
-               sbi->options.iocharset = fat_default_iocharset;
-       }
 
        sb->s_fs_info = NULL;
        kfree(sbi);
+
+       unlock_kernel();
 }
 
 static struct kmem_cache *fat_inode_cachep;
@@ -523,7 +540,9 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
 
 static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+       struct super_block *sb = dentry->d_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
        /* If the count of free cluster is still unknown, counts it here. */
        if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {
@@ -537,7 +556,9 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
        buf->f_bfree = sbi->free_clusters;
        buf->f_bavail = sbi->free_clusters;
-       buf->f_namelen = sbi->options.isvfat ? 260 : 12;
+       buf->f_fsid.val[0] = (u32)id;
+       buf->f_fsid.val[1] = (u32)(id >> 32);
+       buf->f_namelen = sbi->options.isvfat ? FAT_LFN_LEN : 12;
 
        return 0;
 }
@@ -556,7 +577,7 @@ static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,
        return i_pos;
 }
 
-static int fat_write_inode(struct inode *inode, int wait)
+static int __fat_write_inode(struct inode *inode, int wait)
 {
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -613,9 +634,14 @@ retry:
        return err;
 }
 
+static int fat_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+       return __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
 int fat_sync_inode(struct inode *inode)
 {
-       return fat_write_inode(inode, 1);
+       return __fat_write_inode(inode, 1);
 }
 
 EXPORT_SYMBOL_GPL(fat_sync_inode);
@@ -628,6 +654,7 @@ static const struct super_operations fat_sops = {
        .delete_inode   = fat_delete_inode,
        .put_super      = fat_put_super,
        .write_super    = fat_write_super,
+       .sync_fs        = fat_sync_fs,
        .statfs         = fat_statfs,
        .clear_inode    = fat_clear_inode,
        .remount_fs     = fat_remount,
@@ -794,7 +821,7 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                        seq_puts(m, ",shortname=mixed");
                        break;
                case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95:
-                       /* seq_puts(m, ",shortname=lower"); */
+                       seq_puts(m, ",shortname=lower");
                        break;
                default:
                        seq_puts(m, ",shortname=unknown");
@@ -830,6 +857,14 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                seq_puts(m, ",flush");
        if (opts->tz_utc)
                seq_puts(m, ",tz=UTC");
+       if (opts->errors == FAT_ERRORS_CONT)
+               seq_puts(m, ",errors=continue");
+       else if (opts->errors == FAT_ERRORS_PANIC)
+               seq_puts(m, ",errors=panic");
+       else
+               seq_puts(m, ",errors=remount-ro");
+       if (opts->discard)
+               seq_puts(m, ",discard");
 
        return 0;
 }
@@ -842,7 +877,8 @@ 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_flush, Opt_tz_utc, Opt_rodir, Opt_err,
+       Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
+       Opt_err_panic, Opt_err_ro, Opt_discard, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -865,6 +901,12 @@ static const match_table_t fat_tokens = {
        {Opt_showexec, "showexec"},
        {Opt_debug, "debug"},
        {Opt_immutable, "sys_immutable"},
+       {Opt_flush, "flush"},
+       {Opt_tz_utc, "tz=UTC"},
+       {Opt_err_cont, "errors=continue"},
+       {Opt_err_panic, "errors=panic"},
+       {Opt_err_ro, "errors=remount-ro"},
+       {Opt_discard, "discard"},
        {Opt_obsolate, "conv=binary"},
        {Opt_obsolate, "conv=text"},
        {Opt_obsolate, "conv=auto"},
@@ -876,8 +918,6 @@ static const match_table_t fat_tokens = {
        {Opt_obsolate, "cvf_format=%20s"},
        {Opt_obsolate, "cvf_options=%100s"},
        {Opt_obsolate, "posix"},
-       {Opt_flush, "flush"},
-       {Opt_tz_utc, "tz=UTC"},
        {Opt_err, NULL},
 };
 static const match_table_t msdos_tokens = {
@@ -928,14 +968,14 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
 
        opts->isvfat = is_vfat;
 
-       opts->fs_uid = current->uid;
-       opts->fs_gid = current->gid;
-       opts->fs_fmask = opts->fs_dmask = current->fs->umask;
+       opts->fs_uid = current_uid();
+       opts->fs_gid = current_gid();
+       opts->fs_fmask = opts->fs_dmask = current_umask();
        opts->allow_utime = -1;
        opts->codepage = fat_default_codepage;
        opts->iocharset = fat_default_iocharset;
        if (is_vfat) {
-               opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
+               opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95;
                opts->rodir = 0;
        } else {
                opts->shortname = 0;
@@ -947,6 +987,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
        opts->numtail = 1;
        opts->usefree = opts->nocase = 0;
        opts->tz_utc = 0;
+       opts->errors = FAT_ERRORS_RO;
        *debug = 0;
 
        if (!options)
@@ -1039,6 +1080,15 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_tz_utc:
                        opts->tz_utc = 1;
                        break;
+               case Opt_err_cont:
+                       opts->errors = FAT_ERRORS_CONT;
+                       break;
+               case Opt_err_panic:
+                       opts->errors = FAT_ERRORS_PANIC;
+                       break;
+               case Opt_err_ro:
+                       opts->errors = FAT_ERRORS_RO;
+                       break;
 
                /* msdos specific */
                case Opt_dots:
@@ -1094,6 +1144,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_rodir:
                        opts->rodir = 1;
                        break;
+               case Opt_discard:
+                       opts->discard = 1;
+                       break;
 
                /* obsolete mount options */
                case Opt_obsolate:
@@ -1170,7 +1223,7 @@ static int fat_read_root(struct inode *inode)
 int fat_fill_super(struct super_block *sb, void *data, int silent,
                   const struct inode_operations *fs_dir_inode_ops, int isvfat)
 {
-       struct inode *root_inode = NULL;
+       struct inode *root_inode = NULL, *fat_inode = NULL;
        struct buffer_head *bh;
        struct fat_boot_sector *b;
        struct msdos_sb_info *sbi;
@@ -1410,6 +1463,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        }
 
        error = -ENOMEM;
+       fat_inode = new_inode(sb);
+       if (!fat_inode)
+               goto out_fail;
+       MSDOS_I(fat_inode)->i_pos = 0;
+       sbi->fat_inode = fat_inode;
        root_inode = new_inode(sb);
        if (!root_inode)
                goto out_fail;
@@ -1435,6 +1493,8 @@ out_invalid:
                       " on dev %s.\n", sb->s_id);
 
 out_fail:
+       if (fat_inode)
+               iput(fat_inode);
        if (root_inode)
                iput(root_inode);
        if (sbi->nls_io)