Merge branch 'timers/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / fs / fat / inode.c
index 53f3cf6..46a4508 100644 (file)
@@ -433,26 +433,20 @@ EXPORT_SYMBOL_GPL(fat_build_inode);
 static void fat_delete_inode(struct inode *inode)
 {
        truncate_inode_pages(&inode->i_data, 0);
-
-       if (!is_bad_inode(inode)) {
-               inode->i_size = 0;
-               fat_truncate(inode);
-       }
+       inode->i_size = 0;
+       fat_truncate(inode);
        clear_inode(inode);
 }
 
 static void fat_clear_inode(struct inode *inode)
 {
-       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+       struct super_block *sb = inode->i_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-       if (is_bad_inode(inode))
-               return;
-       lock_kernel();
        spin_lock(&sbi->inode_hash_lock);
        fat_cache_inval_inode(inode);
        hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
        spin_unlock(&sbi->inode_hash_lock);
-       unlock_kernel();
 }
 
 static void fat_write_super(struct super_block *sb)
@@ -490,7 +484,7 @@ 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, GFP_KERNEL);
+       ei = kmem_cache_alloc(fat_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -542,7 +536,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
        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) {
+       if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {
                int err = fat_count_free_clusters(dentry->d_sb);
                if (err)
                        return err;
@@ -572,7 +566,7 @@ retry:
        if (inode->i_ino == MSDOS_ROOT_INO || !i_pos)
                return 0;
 
-       lock_kernel();
+       lock_super(sb);
        bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
        if (!bh) {
                printk(KERN_ERR "FAT: unable to read inode block "
@@ -584,7 +578,7 @@ retry:
        if (i_pos != MSDOS_I(inode)->i_pos) {
                spin_unlock(&sbi->inode_hash_lock);
                brelse(bh);
-               unlock_kernel();
+               unlock_super(sb);
                goto retry;
        }
 
@@ -611,7 +605,7 @@ retry:
                err = sync_dirty_buffer(bh);
        brelse(bh);
 out:
-       unlock_kernel();
+       unlock_super(sb);
        return err;
 }
 
@@ -741,6 +735,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 
 static struct dentry *fat_get_parent(struct dentry *child)
 {
+       struct super_block *sb = child->d_sb;
        struct buffer_head *bh;
        struct msdos_dir_entry *de;
        loff_t i_pos;
@@ -748,14 +743,14 @@ static struct dentry *fat_get_parent(struct dentry *child)
        struct inode *inode;
        int err;
 
-       lock_kernel();
+       lock_super(sb);
 
        err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);
        if (err) {
                parent = ERR_PTR(err);
                goto out;
        }
-       inode = fat_build_inode(child->d_sb, de, i_pos);
+       inode = fat_build_inode(sb, de, i_pos);
        brelse(bh);
        if (IS_ERR(inode)) {
                parent = ERR_CAST(inode);
@@ -767,7 +762,7 @@ static struct dentry *fat_get_parent(struct dentry *child)
                parent = ERR_PTR(-ENOMEM);
        }
 out:
-       unlock_kernel();
+       unlock_super(sb);
 
        return parent;
 }
@@ -790,6 +785,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                seq_printf(m, ",gid=%u", opts->fs_gid);
        seq_printf(m, ",fmask=%04o", opts->fs_fmask);
        seq_printf(m, ",dmask=%04o", opts->fs_dmask);
+       if (opts->allow_utime)
+               seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
        if (sbi->nls_disk)
                seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
        if (isvfat) {
@@ -845,9 +842,9 @@ 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_usefree, Opt_nocase,
-       Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,
-       Opt_dots, Opt_nodots,
+       Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, 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,
        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,
@@ -866,6 +863,7 @@ static match_table_t fat_tokens = {
        {Opt_umask, "umask=%o"},
        {Opt_dmask, "dmask=%o"},
        {Opt_fmask, "fmask=%o"},
+       {Opt_allow_utime, "allow_utime=%o"},
        {Opt_codepage, "codepage=%u"},
        {Opt_usefree, "usefree"},
        {Opt_nocase, "nocase"},
@@ -937,6 +935,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
        opts->fs_uid = current->uid;
        opts->fs_gid = current->gid;
        opts->fs_fmask = opts->fs_dmask = current->fs->umask;
+       opts->allow_utime = -1;
        opts->codepage = fat_default_codepage;
        opts->iocharset = fat_default_iocharset;
        if (is_vfat)
@@ -1024,6 +1023,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                                return 0;
                        opts->fs_fmask = option;
                        break;
+               case Opt_allow_utime:
+                       if (match_octal(&args[0], &option))
+                               return 0;
+                       opts->allow_utime = option & (S_IWGRP | S_IWOTH);
+                       break;
                case Opt_codepage:
                        if (match_int(&args[0], &option))
                                return 0;
@@ -1106,6 +1110,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                       " for FAT filesystems, filesystem will be case sensitive!\n");
        }
 
+       /* If user doesn't specify allow_utime, it's initialized from dmask. */
+       if (opts->allow_utime == (unsigned short)-1)
+               opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
        if (opts->unicode_xlate)
                opts->utf8 = 0;
 
@@ -1165,6 +1172,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        long error;
        char buf[50];
 
+       /*
+        * GFP_KERNEL is ok here, because while we do hold the
+        * supeblock lock, memory pressure can't call back into
+        * the filesystem, since we're only just about to mount
+        * it and have no inodes etc active!
+        */
        sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
@@ -1208,18 +1221,17 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
         */
 
        media = b->media;
-       if (!FAT_VALID_MEDIA(media)) {
+       if (!fat_valid_media(media)) {
                if (!silent)
                        printk(KERN_ERR "FAT: invalid media value (0x%02x)\n",
                               media);
                brelse(bh);
                goto out_invalid;
        }
-       logical_sector_size =
-               le16_to_cpu(get_unaligned((__le16 *)&b->sector_size));
+       logical_sector_size = get_unaligned_le16(&b->sector_size);
        if (!is_power_of_2(logical_sector_size)
            || (logical_sector_size < 512)
-           || (PAGE_CACHE_SIZE < logical_sector_size)) {
+           || (logical_sector_size > 4096)) {
                if (!silent)
                        printk(KERN_ERR "FAT: bogus logical sector size %u\n",
                               logical_sector_size);
@@ -1267,6 +1279,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        sbi->fat_length = le16_to_cpu(b->fat_length);
        sbi->root_cluster = 0;
        sbi->free_clusters = -1;        /* Don't know yet */
+       sbi->free_clus_valid = 0;
        sbi->prev_free = FAT_START_ENT;
 
        if (!sbi->fat_length && b->fat32_length) {
@@ -1302,8 +1315,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                               sbi->fsinfo_sector);
                } else {
                        if (sbi->options.usefree)
-                               sbi->free_clusters =
-                                       le32_to_cpu(fsinfo->free_clusters);
+                               sbi->free_clus_valid = 1;
+                       sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters);
                        sbi->prev_free = le32_to_cpu(fsinfo->next_cluster);
                }
 
@@ -1314,8 +1327,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
        sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
-       sbi->dir_entries =
-               le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries));
+       sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
        if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
                if (!silent)
                        printk(KERN_ERR "FAT: bogus directroy-entries per block"
@@ -1327,7 +1339,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        rootdir_sectors = sbi->dir_entries
                * sizeof(struct msdos_dir_entry) / sb->s_blocksize;
        sbi->data_start = sbi->dir_start + rootdir_sectors;
-       total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors));
+       total_sectors = get_unaligned_le16(&b->sectors);
        if (total_sectors == 0)
                total_sectors = le32_to_cpu(b->total_sect);