dm crypt: avoid unnecessary wait when splitting bio
[safe/jmp/linux-2.6] / fs / msdos / namei.c
index 626a367..e844b98 100644 (file)
 #include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
 
-/* MS-DOS "device special files" */
-static const unsigned char *reserved_names[] = {
-       "CON     ", "PRN     ", "NUL     ", "AUX     ",
-       "LPT1    ", "LPT2    ", "LPT3    ", "LPT4    ",
-       "COM1    ", "COM2    ", "COM3    ", "COM4    ",
-       NULL
-};
-
 /* Characters that are undesirable in an MS-DOS file name */
 static unsigned char bad_chars[] = "*?<>|\"";
-static unsigned char bad_if_strict_pc[] = "+=,; ";
-/* GEMDOS is less restrictive */
-static unsigned char bad_if_strict_atari[] = " ";
-
-#define bad_if_strict(opts) \
-       ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc)
+static unsigned char bad_if_strict[] = "+=,; ";
 
 /***** Formats an MS-DOS file name. Rejects invalid names. */
 static int msdos_format_name(const unsigned char *name, int len,
@@ -40,7 +27,6 @@ static int msdos_format_name(const unsigned char *name, int len,
         */
 {
        unsigned char *walk;
-       const unsigned char **reserved;
        unsigned char c;
        int space;
 
@@ -49,21 +35,20 @@ static int msdos_format_name(const unsigned char *name, int len,
                        /* Get rid of dot - test for it elsewhere */
                        name++;
                        len--;
-               } else if (!opts->atari)
+               } else
                        return -EINVAL;
        }
        /*
-        * disallow names that _really_ start with a dot for MS-DOS,
-        * GEMDOS does not care
+        * disallow names that _really_ start with a dot
         */
-       space = !opts->atari;
+       space = 1;
        c = 0;
        for (walk = res; len && walk - res < 8; walk++) {
                c = *name++;
                len--;
                if (opts->name_check != 'r' && strchr(bad_chars, c))
                        return -EINVAL;
-               if (opts->name_check == 's' && strchr(bad_if_strict(opts), c))
+               if (opts->name_check == 's' && strchr(bad_if_strict, c))
                        return -EINVAL;
                if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
                        return -EINVAL;
@@ -103,7 +88,7 @@ static int msdos_format_name(const unsigned char *name, int len,
                        if (opts->name_check != 'r' && strchr(bad_chars, c))
                                return -EINVAL;
                        if (opts->name_check == 's' &&
-                           strchr(bad_if_strict(opts), c))
+                           strchr(bad_if_strict, c))
                                return -EINVAL;
                        if (c < ' ' || c == ':' || c == '\\')
                                return -EINVAL;
@@ -127,11 +112,7 @@ static int msdos_format_name(const unsigned char *name, int len,
        }
        while (walk - res < MSDOS_NAME)
                *walk++ = ' ';
-       if (!opts->atari)
-               /* GEMDOS is less stupid and has no reserved names */
-               for (reserved = reserved_names; *reserved; reserved++)
-                       if (!strncmp(res, *reserved, 8))
-                               return -EINVAL;
+
        return 0;
 }
 
@@ -227,7 +208,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
 
        dentry->d_op = &msdos_dentry_operations;
 
-       lock_kernel();
+       lock_super(sb);
        res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
        if (res == -ENOENT)
                goto add;
@@ -245,7 +226,7 @@ add:
        if (dentry)
                dentry->d_op = &msdos_dentry_operations;
 out:
-       unlock_kernel();
+       unlock_super(sb);
        if (!res)
                return dentry;
        return ERR_PTR(res);
@@ -256,6 +237,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
                           int is_dir, int is_hid, int cluster,
                           struct timespec *ts, struct fat_slot_info *sinfo)
 {
+       struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
        struct msdos_dir_entry de;
        __le16 time, date;
        int err;
@@ -265,7 +247,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
        if (is_hid)
                de.attr |= ATTR_HIDDEN;
        de.lcase = 0;
-       fat_date_unix2dos(ts->tv_sec, &time, &date);
+       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
        de.cdate = de.adate = 0;
        de.ctime = 0;
        de.ctime_cs = 0;
@@ -293,13 +275,13 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
                        struct nameidata *nd)
 {
        struct super_block *sb = dir->i_sb;
-       struct inode *inode;
+       struct inode *inode = NULL;
        struct fat_slot_info sinfo;
        struct timespec ts;
        unsigned char msdos_name[MSDOS_NAME];
        int err, is_hid;
 
-       lock_kernel();
+       lock_super(sb);
 
        err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
                                msdos_name, &MSDOS_SB(sb)->options);
@@ -328,18 +310,21 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
 
        d_instantiate(dentry, inode);
 out:
-       unlock_kernel();
+       unlock_super(sb);
+       if (!err)
+               err = fat_flush_inodes(sb, dir, inode);
        return err;
 }
 
 /***** Remove a directory */
 static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 {
+       struct super_block *sb = dir->i_sb;
        struct inode *inode = dentry->d_inode;
        struct fat_slot_info sinfo;
        int err;
 
-       lock_kernel();
+       lock_super(sb);
        /*
         * Check whether the directory is not in use, then check
         * whether it is empty.
@@ -354,13 +339,15 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       dir->i_nlink--;
+       drop_nlink(dir);
 
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_kernel();
+       unlock_super(sb);
+       if (!err)
+               err = fat_flush_inodes(sb, dir, inode);
 
        return err;
 }
@@ -375,7 +362,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        struct timespec ts;
        int err, is_hid, cluster;
 
-       lock_kernel();
+       lock_super(sb);
 
        err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
                                msdos_name, &MSDOS_SB(sb)->options);
@@ -398,7 +385,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
        if (err)
                goto out_free;
-       dir->i_nlink++;
+       inc_nlink(dir);
 
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
        brelse(sinfo.bh);
@@ -413,13 +400,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        d_instantiate(dentry, inode);
 
-       unlock_kernel();
+       unlock_super(sb);
+       fat_flush_inodes(sb, dir, inode);
        return 0;
 
 out_free:
        fat_free_clusters(dir, cluster);
 out:
-       unlock_kernel();
+       unlock_super(sb);
        return err;
 }
 
@@ -427,10 +415,11 @@ out:
 static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
+       struct super_block *sb= inode->i_sb;
        struct fat_slot_info sinfo;
        int err;
 
-       lock_kernel();
+       lock_super(sb);
        err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
        if (err)
                goto out;
@@ -438,11 +427,13 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_kernel();
+       unlock_super(sb);
+       if (!err)
+               err = fat_flush_inodes(sb, dir, inode);
 
        return err;
 }
@@ -555,9 +546,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
                        if (err)
                                goto error_dotdot;
                }
-               old_dir->i_nlink--;
+               drop_nlink(old_dir);
                if (!new_inode)
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
        }
 
        err = fat_remove_entries(old_dir, &old_sinfo);  /* and releases bh */
@@ -572,10 +563,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
                mark_inode_dirty(old_dir);
 
        if (new_inode) {
+               drop_nlink(new_inode);
                if (is_dir)
-                       new_inode->i_nlink -= 2;
-               else
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                new_inode->i_ctime = ts;
        }
 out:
@@ -616,7 +606,7 @@ error_inode:
        if (corrupt < 0) {
                fat_fs_panic(new_dir->i_sb,
                             "%s: Filesystem corrupted (i_pos %lld)",
-                            __FUNCTION__, sinfo.i_pos);
+                            __func__, sinfo.i_pos);
        }
        goto out;
 }
@@ -625,10 +615,11 @@ error_inode:
 static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry)
 {
+       struct super_block *sb = old_dir->i_sb;
        unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
        int err, is_hid;
 
-       lock_kernel();
+       lock_super(sb);
 
        err = msdos_format_name(old_dentry->d_name.name,
                                old_dentry->d_name.len, old_msdos_name,
@@ -647,18 +638,21 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
        err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
                              new_dir, new_msdos_name, new_dentry, is_hid);
 out:
-       unlock_kernel();
+       unlock_super(sb);
+       if (!err)
+               err = fat_flush_inodes(sb, old_dir, new_dir);
        return err;
 }
 
-static struct inode_operations msdos_dir_inode_operations = {
+static const struct inode_operations msdos_dir_inode_operations = {
        .create         = msdos_create,
        .lookup         = msdos_lookup,
        .unlink         = msdos_unlink,
        .mkdir          = msdos_mkdir,
        .rmdir          = msdos_rmdir,
        .rename         = msdos_rename,
-       .setattr        = fat_notify_change,
+       .setattr        = fat_setattr,
+       .getattr        = fat_getattr,
 };
 
 static int msdos_fill_super(struct super_block *sb, void *data, int silent)
@@ -674,11 +668,12 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 }
 
-static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
-                                       int flags, const char *dev_name,
-                                       void *data)
+static int msdos_get_sb(struct file_system_type *fs_type,
+                       int flags, const char *dev_name,
+                       void *data, struct vfsmount *mnt)
 {
-       return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
+       return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super,
+                          mnt);
 }
 
 static struct file_system_type msdos_fs_type = {