aboutsummaryrefslogtreecommitdiff
path: root/fs/fat/namei_msdos.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fat/namei_msdos.c')
-rw-r--r--fs/fat/namei_msdos.c138
1 files changed, 59 insertions, 79 deletions
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index da3f361a37d..a783b0e1272 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/time.h>
#include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
#include "fat.h"
/* Characters that are undesirable in an MS-DOS file name */
@@ -149,7 +148,7 @@ static int msdos_find(struct inode *dir, const unsigned char *name, int len,
* that the existing dentry can be used. The msdos fs routines will
* return ENOENT or EINVAL as appropriate.
*/
-static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
+static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
{
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
unsigned char msdos_name[MSDOS_NAME];
@@ -165,16 +164,17 @@ static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
* Compare two msdos names. If either of the names are invalid,
* we fall back to doing the standard name comparison.
*/
-static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
{
- struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
+ struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
int error;
- error = msdos_format_name(a->name, a->len, a_msdos_name, options);
+ error = msdos_format_name(name->name, name->len, a_msdos_name, options);
if (error)
goto old_compare;
- error = msdos_format_name(b->name, b->len, b_msdos_name, options);
+ error = msdos_format_name(str, len, b_msdos_name, options);
if (error)
goto old_compare;
error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
@@ -183,8 +183,8 @@ out:
old_compare:
error = 1;
- if (a->len == b->len)
- error = memcmp(a->name, b->name, a->len);
+ if (name->len == len)
+ error = memcmp(name->name, str, len);
goto out;
}
@@ -199,41 +199,28 @@ static const struct dentry_operations msdos_dentry_operations = {
/***** Get inode using directory and name */
static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
- struct nameidata *nd)
+ unsigned int flags)
{
struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo;
struct inode *inode;
int err;
- lock_super(sb);
-
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
- if (err) {
- if (err == -ENOENT) {
- inode = NULL;
- goto out;
- }
- goto error;
- }
-
- inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
- brelse(sinfo.bh);
- if (IS_ERR(inode)) {
- err = PTR_ERR(inode);
- goto error;
+ switch (err) {
+ case -ENOENT:
+ inode = NULL;
+ break;
+ case 0:
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ break;
+ default:
+ inode = ERR_PTR(err);
}
-out:
- unlock_super(sb);
- dentry->d_op = &msdos_dentry_operations;
- dentry = d_splice_alias(inode, dentry);
- if (dentry)
- dentry->d_op = &msdos_dentry_operations;
- return dentry;
-
-error:
- unlock_super(sb);
- return ERR_PTR(err);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
+ return d_splice_alias(inode, dentry);
}
/***** Creates a directory entry (name is already formatted). */
@@ -257,8 +244,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
de.ctime_cs = 0;
de.time = time;
de.date = date;
- de.start = cpu_to_le16(cluster);
- de.starthi = cpu_to_le16(cluster >> 16);
+ fat_set_start(&de, cluster);
de.size = 0;
err = fat_add_entries(dir, &de, 1, sinfo);
@@ -275,8 +261,8 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
}
/***** Create a file */
-static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ bool excl)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
@@ -285,7 +271,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
unsigned char msdos_name[MSDOS_NAME];
int err, is_hid;
- lock_super(sb);
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options);
@@ -314,7 +300,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
d_instantiate(dentry, inode);
out:
- unlock_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!err)
err = fat_flush_inodes(sb, dir, inode);
return err;
@@ -328,7 +314,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
struct fat_slot_info sinfo;
int err;
- lock_super(sb);
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
/*
* Check whether the directory is not in use, then check
* whether it is empty.
@@ -349,7 +335,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
- unlock_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!err)
err = fat_flush_inodes(sb, dir, inode);
@@ -357,7 +343,7 @@ out:
}
/***** Make a directory */
-static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo;
@@ -366,7 +352,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
struct timespec ts;
int err, is_hid, cluster;
- lock_super(sb);
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options);
@@ -398,20 +384,20 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
/* the directory was completed, just return a error */
goto out;
}
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode);
- unlock_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
fat_flush_inodes(sb, dir, inode);
return 0;
out_free:
fat_free_clusters(dir, cluster);
out:
- unlock_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
return err;
}
@@ -419,11 +405,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 super_block *sb = inode->i_sb;
struct fat_slot_info sinfo;
int err;
- lock_super(sb);
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
if (err)
goto out;
@@ -435,7 +421,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
- unlock_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!err)
err = fat_flush_inodes(sb, dir, inode);
@@ -452,7 +438,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo;
struct timespec ts;
- loff_t dotdot_i_pos, new_i_pos;
+ loff_t new_i_pos;
int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
@@ -468,8 +454,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
is_dir = S_ISDIR(old_inode->i_mode);
update_dotdot = (is_dir && old_dir != new_dir);
if (update_dotdot) {
- if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
- &dotdot_i_pos) < 0) {
+ if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) {
err = -EIO;
goto out;
}
@@ -541,10 +526,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
mark_inode_dirty(old_inode);
if (update_dotdot) {
- int start = MSDOS_I(new_dir)->i_logstart;
- dotdot_de->start = cpu_to_le16(start);
- dotdot_de->starthi = cpu_to_le16(start >> 16);
- mark_buffer_dirty(dotdot_bh);
+ fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart);
+ mark_buffer_dirty_inode(dotdot_bh, old_inode);
if (IS_DIRSYNC(new_dir)) {
err = sync_dirty_buffer(dotdot_bh);
if (err)
@@ -583,10 +566,8 @@ error_dotdot:
corrupt = 1;
if (update_dotdot) {
- int start = MSDOS_I(old_dir)->i_logstart;
- dotdot_de->start = cpu_to_le16(start);
- dotdot_de->starthi = cpu_to_le16(start >> 16);
- mark_buffer_dirty(dotdot_bh);
+ fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart);
+ mark_buffer_dirty_inode(dotdot_bh, old_inode);
corrupt |= sync_dirty_buffer(dotdot_bh);
}
error_inode:
@@ -608,7 +589,7 @@ error_inode:
sinfo.bh = NULL;
}
if (corrupt < 0) {
- fat_fs_panic(new_dir->i_sb,
+ fat_fs_error(new_dir->i_sb,
"%s: Filesystem corrupted (i_pos %lld)",
__func__, sinfo.i_pos);
}
@@ -623,7 +604,7 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
int err, is_hid;
- lock_super(sb);
+ mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_format_name(old_dentry->d_name.name,
old_dentry->d_name.len, old_msdos_name,
@@ -642,7 +623,7 @@ 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_super(sb);
+ mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!err)
err = fat_flush_inodes(sb, old_dir, new_dir);
return err;
@@ -659,34 +640,33 @@ static const struct inode_operations msdos_dir_inode_operations = {
.getattr = fat_getattr,
};
-static int msdos_fill_super(struct super_block *sb, void *data, int silent)
+static void setup(struct super_block *sb)
{
- int res;
-
- res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
- if (res)
- return res;
-
+ MSDOS_SB(sb)->dir_ops = &msdos_dir_inode_operations;
+ sb->s_d_op = &msdos_dentry_operations;
sb->s_flags |= MS_NOATIME;
- sb->s_root->d_op = &msdos_dentry_operations;
- return 0;
}
-static int msdos_get_sb(struct file_system_type *fs_type,
+static int msdos_fill_super(struct super_block *sb, void *data, int silent)
+{
+ return fat_fill_super(sb, data, silent, 0, setup);
+}
+
+static struct dentry *msdos_mount(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data, struct vfsmount *mnt)
+ void *data)
{
- return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super,
- mnt);
+ return mount_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
}
static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE,
.name = "msdos",
- .get_sb = msdos_get_sb,
+ .mount = msdos_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
+MODULE_ALIAS_FS("msdos");
static int __init init_msdos_fs(void)
{