usb: otg: modify default to n for usb2.0
[firefly-linux-kernel-4.4.55.git] / fs / hpfs / super.c
index a0617e7069579c61baed047b3ba2992b294d6082..3713fd52b44bf393d0f293e3f4df49e03aca68e7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
@@ -52,32 +53,39 @@ static void unmark_dirty(struct super_block *s)
 }
 
 /* Filesystem error... */
-static char err_buf[1024];
-
 void hpfs_error(struct super_block *s, const char *fmt, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        va_start(args, fmt);
-       vsnprintf(err_buf, sizeof(err_buf), fmt, args);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       pr_err("filesystem error: %pV", &vaf);
+
        va_end(args);
 
-       printk("HPFS: filesystem error: %s", err_buf);
        if (!hpfs_sb(s)->sb_was_error) {
                if (hpfs_sb(s)->sb_err == 2) {
-                       printk("; crashing the system because you wanted it\n");
+                       pr_cont("; crashing the system because you wanted it\n");
                        mark_dirty(s, 0);
                        panic("HPFS panic");
                } else if (hpfs_sb(s)->sb_err == 1) {
-                       if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n");
+                       if (s->s_flags & MS_RDONLY)
+                               pr_cont("; already mounted read-only\n");
                        else {
-                               printk("; remounting read-only\n");
+                               pr_cont("; remounting read-only\n");
                                mark_dirty(s, 0);
                                s->s_flags |= MS_RDONLY;
                        }
-               } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
-               else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
-       } else printk("\n");
+               } else if (s->s_flags & MS_RDONLY)
+                               pr_cont("; going on - but anything won't be destroyed because it's read-only\n");
+               else
+                       pr_cont("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
+       } else
+               pr_cont("\n");
        hpfs_sb(s)->sb_was_error = 1;
 }
 
@@ -101,29 +109,35 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,
        return 0;
 }
 
-static void hpfs_put_super(struct super_block *s)
+static void free_sbi(struct hpfs_sb_info *sbi)
 {
-       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       kfree(sbi->sb_cp_table);
+       kfree(sbi->sb_bmp_dir);
+       kfree(sbi);
+}
+
+static void lazy_free_sbi(struct rcu_head *rcu)
+{
+       free_sbi(container_of(rcu, struct hpfs_sb_info, rcu));
+}
 
+static void hpfs_put_super(struct super_block *s)
+{
        hpfs_lock(s);
        unmark_dirty(s);
        hpfs_unlock(s);
-
-       kfree(sbi->sb_cp_table);
-       kfree(sbi->sb_bmp_dir);
-       s->s_fs_info = NULL;
-       kfree(sbi);
+       call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi);
 }
 
-unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
+static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
 {
        struct quad_buffer_head qbh;
        unsigned long *bits;
        unsigned count;
 
-       bits = hpfs_map_4sectors(s, secno, &qbh, 4);
+       bits = hpfs_map_4sectors(s, secno, &qbh, 0);
        if (!bits)
-               return 0;
+               return (unsigned)-1;
        count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
        hpfs_brelse4(&qbh);
        return count;
@@ -134,29 +148,49 @@ static unsigned count_bitmaps(struct super_block *s)
        unsigned n, count, n_bands;
        n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
        count = 0;
-       for (n = 0; n < n_bands; n++)
-               count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
+       for (n = 0; n < COUNT_RD_AHEAD; n++) {
+               hpfs_prefetch_bitmap(s, n);
+       }
+       for (n = 0; n < n_bands; n++) {
+               unsigned c;
+               hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
+               c = hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
+               if (c != (unsigned)-1)
+                       count += c;
+       }
        return count;
 }
 
+unsigned hpfs_get_free_dnodes(struct super_block *s)
+{
+       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       if (sbi->sb_n_free_dnodes == (unsigned)-1) {
+               unsigned c = hpfs_count_one_bitmap(s, sbi->sb_dmap);
+               if (c == (unsigned)-1)
+                       return 0;
+               sbi->sb_n_free_dnodes = c;
+       }
+       return sbi->sb_n_free_dnodes;
+}
+
 static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *s = dentry->d_sb;
        struct hpfs_sb_info *sbi = hpfs_sb(s);
        u64 id = huge_encode_dev(s->s_bdev->bd_dev);
+
        hpfs_lock(s);
 
-       /*if (sbi->sb_n_free == -1) {*/
+       if (sbi->sb_n_free == (unsigned)-1)
                sbi->sb_n_free = count_bitmaps(s);
-               sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap);
-       /*}*/
+
        buf->f_type = s->s_magic;
        buf->f_bsize = 512;
        buf->f_blocks = sbi->sb_fs_size;
        buf->f_bfree = sbi->sb_n_free;
        buf->f_bavail = sbi->sb_n_free;
        buf->f_files = sbi->sb_dirband_size / 4;
-       buf->f_ffree = sbi->sb_n_free_dnodes;
+       buf->f_ffree = hpfs_get_free_dnodes(s);
        buf->f_fsid.val[0] = (u32)id;
        buf->f_fsid.val[1] = (u32)(id >> 32);
        buf->f_namelen = 254;
@@ -166,12 +200,39 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
+
+long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+       switch (cmd) {
+               case FITRIM: {
+                       struct fstrim_range range;
+                       secno n_trimmed;
+                       int r;
+                       if (!capable(CAP_SYS_ADMIN))
+                               return -EPERM;
+                       if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
+                               return -EFAULT;
+                       r = hpfs_trim_fs(file_inode(file)->i_sb, range.start >> 9, (range.start + range.len) >> 9, (range.minlen + 511) >> 9, &n_trimmed);
+                       if (r)
+                               return r;
+                       range.len = (u64)n_trimmed << 9;
+                       if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range)))
+                               return -EFAULT;
+                       return 0;
+               }
+               default: {
+                       return -ENOIOCTLCMD;
+               }
+       }
+}
+
+
 static struct kmem_cache * hpfs_inode_cachep;
 
 static struct inode *hpfs_alloc_inode(struct super_block *sb)
 {
        struct hpfs_inode_info *ei;
-       ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
+       ei = kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
        ei->vfs_inode.i_version = 1;
@@ -266,7 +327,7 @@ static int parse_opts(char *opts, kuid_t *uid, kgid_t *gid, umode_t *umask,
        if (!opts)
                return 1;
 
-       /*printk("Parsing opts: '%s'\n",opts);*/
+       /*pr_info("Parsing opts: '%s'\n",opts);*/
 
        while ((p = strsep(&opts, ",")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
@@ -361,7 +422,7 @@ static int parse_opts(char *opts, kuid_t *uid, kgid_t *gid, umode_t *umask,
 
 static inline void hpfs_help(void)
 {
-       printk("\n\
+       pr_info("\n\
 HPFS filesystem options:\n\
       help              do not mount and display this text\n\
       uid=xxx           set uid of files that don't have uid specified in eas\n\
@@ -393,10 +454,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
        int lowercase, eas, chk, errs, chkdsk, timeshift;
        int o;
        struct hpfs_sb_info *sbi = hpfs_sb(s);
-       char *new_opts = kstrdup(data, GFP_KERNEL);
-       
+
+       sync_filesystem(s);
+
        *flags |= MS_NOATIME;
-       
+
        hpfs_lock(s);
        uid = sbi->sb_uid; gid = sbi->sb_gid;
        umask = 0777 & ~sbi->sb_mode;
@@ -406,7 +468,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 
        if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase,
            &eas, &chk, &errs, &chkdsk, &timeshift))) {
-               printk("HPFS: bad mount options.\n");
+               pr_err("bad mount options.\n");
                goto out_err;
        }
        if (o == 2) {
@@ -414,7 +476,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
                goto out_err;
        }
        if (timeshift != sbi->sb_timeshift) {
-               printk("HPFS: timeshift can't be changed using remount.\n");
+               pr_err("timeshift can't be changed using remount.\n");
                goto out_err;
        }
 
@@ -428,17 +490,44 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 
        if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
 
-       replace_mount_options(s, new_opts);
-
        hpfs_unlock(s);
        return 0;
 
 out_err:
        hpfs_unlock(s);
-       kfree(new_opts);
        return -EINVAL;
 }
 
+static int hpfs_show_options(struct seq_file *seq, struct dentry *root)
+{
+       struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb);
+
+       seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid));
+       seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid));
+       seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777));
+       if (sbi->sb_lowercase)
+               seq_printf(seq, ",case=lower");
+       if (!sbi->sb_chk)
+               seq_printf(seq, ",check=none");
+       if (sbi->sb_chk == 2)
+               seq_printf(seq, ",check=strict");
+       if (!sbi->sb_err)
+               seq_printf(seq, ",errors=continue");
+       if (sbi->sb_err == 2)
+               seq_printf(seq, ",errors=panic");
+       if (!sbi->sb_chkdsk)
+               seq_printf(seq, ",chkdsk=no");
+       if (sbi->sb_chkdsk == 2)
+               seq_printf(seq, ",chkdsk=always");
+       if (!sbi->sb_eas)
+               seq_printf(seq, ",eas=no");
+       if (sbi->sb_eas == 1)
+               seq_printf(seq, ",eas=ro");
+       if (sbi->sb_timeshift)
+               seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift);
+       return 0;
+}
+
 /* Super operations */
 
 static const struct super_operations hpfs_sops =
@@ -449,7 +538,7 @@ static const struct super_operations hpfs_sops =
        .put_super      = hpfs_put_super,
        .statfs         = hpfs_statfs,
        .remount_fs     = hpfs_remount_fs,
-       .show_options   = generic_show_options,
+       .show_options   = hpfs_show_options,
 };
 
 static int hpfs_fill_super(struct super_block *s, void *options, int silent)
@@ -472,17 +561,12 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        int o;
 
-       save_mount_options(s, options);
-
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi) {
                return -ENOMEM;
        }
        s->s_fs_info = sbi;
 
-       sbi->sb_bmp_dir = NULL;
-       sbi->sb_cp_table = NULL;
-
        mutex_init(&sbi->hpfs_mutex);
        hpfs_lock(s);
 
@@ -498,7 +582,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,
            &eas, &chk, &errs, &chkdsk, &timeshift))) {
-               printk("HPFS: bad mount options.\n");
+               pr_err("bad mount options.\n");
                goto bail0;
        }
        if (o==2) {
@@ -517,16 +601,17 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC
            ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC
            || le32_to_cpu(spareblock->magic) != SP_MAGIC) {
-               if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n");
+               if (!silent)
+                       pr_err("Bad magic ... probably not HPFS\n");
                goto bail4;
        }
 
        /* Check version */
        if (!(s->s_flags & MS_RDONLY) &&
              superblock->funcversion != 2 && superblock->funcversion != 3) {
-               printk("HPFS: Bad version %d,%d. Mount readonly to go around\n",
+               pr_err("Bad version %d,%d. Mount readonly to go around\n",
                        (int)superblock->version, (int)superblock->funcversion);
-               printk("HPFS: please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n");
+               pr_err("please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n");
                goto bail4;
        }
 
@@ -558,7 +643,16 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        sbi->sb_cp_table = NULL;
        sbi->sb_c_bitmap = -1;
        sbi->sb_max_fwd_alloc = 0xffffff;
-       
+
+       if (sbi->sb_fs_size >= 0x80000000) {
+               hpfs_error(s, "invalid size in superblock: %08x",
+                       (unsigned)sbi->sb_fs_size);
+               goto bail4;
+       }
+
+       if (spareblock->n_spares_used)
+               hpfs_load_hotfix_map(s, spareblock);
+
        /* Load bitmap directory */
        if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
                goto bail4;
@@ -566,7 +660,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        /* Check for general fs errors*/
        if (spareblock->dirty && !spareblock->old_wrote) {
                if (errs == 2) {
-                       printk("HPFS: Improperly stopped, not mounted\n");
+                       pr_err("Improperly stopped, not mounted\n");
                        goto bail4;
                }
                hpfs_error(s, "improperly stopped");
@@ -578,24 +672,15 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
                mark_buffer_dirty(bh2);
        }
 
-       if (spareblock->hotfixes_used || spareblock->n_spares_used) {
-               if (errs >= 2) {
-                       printk("HPFS: Hotfixes not supported here, try chkdsk\n");
-                       mark_dirty(s, 0);
-                       goto bail4;
-               }
-               hpfs_error(s, "hotfixes not supported here, try chkdsk");
-               if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
-               else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
-       }
        if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
                if (errs >= 2) {
-                       printk("HPFS: Spare dnodes used, try chkdsk\n");
+                       pr_err("Spare dnodes used, try chkdsk\n");
                        mark_dirty(s, 0);
                        goto bail4;
                }
                hpfs_error(s, "warning: spare dnodes used, try chkdsk");
-               if (errs == 0) printk("HPFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n");
+               if (errs == 0)
+                       pr_err("Proceeding, but your filesystem could be corrupted if you delete files or directories\n");
        }
        if (chk) {
                unsigned a;
@@ -614,12 +699,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
                        goto bail4;
                }
                sbi->sb_dirband_size = a;
-       } else printk("HPFS: You really don't want any checks? You are crazy...\n");
+       } else
+               pr_err("You really don't want any checks? You are crazy...\n");
 
        /* Load code page table */
        if (le32_to_cpu(spareblock->n_code_pages))
                if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir))))
-                       printk("HPFS: Warning: code page support is disabled\n");
+                       pr_err("code page support is disabled\n");
 
        brelse(bh2);
        brelse(bh1);
@@ -668,10 +754,7 @@ bail2:     brelse(bh0);
 bail1:
 bail0:
        hpfs_unlock(s);
-       kfree(sbi->sb_bmp_dir);
-       kfree(sbi->sb_cp_table);
-       s->s_fs_info = NULL;
-       kfree(sbi);
+       free_sbi(sbi);
        return -EINVAL;
 }