Commit 8f593427 authored by Linus Torvalds's avatar Linus Torvalds Committed by Jonathan Corbet

Replace BKL with superblock lock in fat/msdos/vfat

This replaces the use of the BKL in the FAT family of filesystems with the
existing superblock lock instead.

The code already appears to do mostly proper locking with its own private
spinlocks (and mutexes), but while the BKL could possibly have been
dropped entirely, converting it to use the superblock lock (which is just
a regular mutex) is the conservative thing to do.

As a per-filesystem mutex, it not only won't have any of the possible
latency issues related to the BKL, but the lock is obviously private to
the particular filesystem instance and will thus not cause problems for
entirely unrelated users like the BKL can.
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent 5ca6a93d
...@@ -61,7 +61,7 @@ void fat_cache_destroy(void) ...@@ -61,7 +61,7 @@ void fat_cache_destroy(void)
static inline struct fat_cache *fat_cache_alloc(struct inode *inode) static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
{ {
return kmem_cache_alloc(fat_cache_cachep, GFP_KERNEL); return kmem_cache_alloc(fat_cache_cachep, GFP_NOFS);
} }
static inline void fat_cache_free(struct fat_cache *cache) static inline void fat_cache_free(struct fat_cache *cache)
......
...@@ -472,7 +472,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, ...@@ -472,7 +472,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
loff_t cpos; loff_t cpos;
int ret = 0; int ret = 0;
lock_kernel(); lock_super(sb);
cpos = filp->f_pos; cpos = filp->f_pos;
/* Fake . and .. for the root directory. */ /* Fake . and .. for the root directory. */
...@@ -654,7 +654,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, ...@@ -654,7 +654,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
if (unicode) if (unicode)
__putname(unicode); __putname(unicode);
out: out:
unlock_kernel(); unlock_super(sb);
return ret; return ret;
} }
......
...@@ -229,7 +229,8 @@ static int fat_free(struct inode *inode, int skip) ...@@ -229,7 +229,8 @@ static int fat_free(struct inode *inode, int skip)
void fat_truncate(struct inode *inode) void fat_truncate(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);
const unsigned int cluster_size = sbi->cluster_size; const unsigned int cluster_size = sbi->cluster_size;
int nr_clusters; int nr_clusters;
...@@ -242,9 +243,9 @@ void fat_truncate(struct inode *inode) ...@@ -242,9 +243,9 @@ void fat_truncate(struct inode *inode)
nr_clusters = (inode->i_size + (cluster_size - 1)) >> sbi->cluster_bits; nr_clusters = (inode->i_size + (cluster_size - 1)) >> sbi->cluster_bits;
lock_kernel(); lock_super(sb);
fat_free(inode, nr_clusters); fat_free(inode, nr_clusters);
unlock_kernel(); unlock_super(sb);
fat_flush_inodes(inode->i_sb, inode, NULL); fat_flush_inodes(inode->i_sb, inode, NULL);
} }
...@@ -297,12 +298,13 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode) ...@@ -297,12 +298,13 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
int fat_setattr(struct dentry *dentry, struct iattr *attr) int fat_setattr(struct dentry *dentry, struct iattr *attr)
{ {
struct super_block *sb = dentry->d_sb;
struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int mask, error = 0; int mask, error = 0;
unsigned int ia_valid; unsigned int ia_valid;
lock_kernel(); lock_super(sb);
/* /*
* Expand the file. Since inode_setattr() updates ->i_size * Expand the file. Since inode_setattr() updates ->i_size
...@@ -356,7 +358,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -356,7 +358,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
mask = sbi->options.fs_fmask; mask = sbi->options.fs_fmask;
inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
out: out:
unlock_kernel(); unlock_super(sb);
return error; return error;
} }
EXPORT_SYMBOL_GPL(fat_setattr); EXPORT_SYMBOL_GPL(fat_setattr);
......
...@@ -440,14 +440,13 @@ static void fat_delete_inode(struct inode *inode) ...@@ -440,14 +440,13 @@ static void fat_delete_inode(struct inode *inode)
static void fat_clear_inode(struct 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);
lock_kernel();
spin_lock(&sbi->inode_hash_lock); spin_lock(&sbi->inode_hash_lock);
fat_cache_inval_inode(inode); fat_cache_inval_inode(inode);
hlist_del_init(&MSDOS_I(inode)->i_fat_hash); hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
spin_unlock(&sbi->inode_hash_lock); spin_unlock(&sbi->inode_hash_lock);
unlock_kernel();
} }
static void fat_write_super(struct super_block *sb) static void fat_write_super(struct super_block *sb)
...@@ -485,7 +484,7 @@ static struct kmem_cache *fat_inode_cachep; ...@@ -485,7 +484,7 @@ static struct kmem_cache *fat_inode_cachep;
static struct inode *fat_alloc_inode(struct super_block *sb) static struct inode *fat_alloc_inode(struct super_block *sb)
{ {
struct msdos_inode_info *ei; 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) if (!ei)
return NULL; return NULL;
return &ei->vfs_inode; return &ei->vfs_inode;
...@@ -567,7 +566,7 @@ static int fat_write_inode(struct inode *inode, int wait) ...@@ -567,7 +566,7 @@ static int fat_write_inode(struct inode *inode, int wait)
if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) if (inode->i_ino == MSDOS_ROOT_INO || !i_pos)
return 0; return 0;
lock_kernel(); lock_super(sb);
bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
if (!bh) { if (!bh) {
printk(KERN_ERR "FAT: unable to read inode block " printk(KERN_ERR "FAT: unable to read inode block "
...@@ -579,7 +578,7 @@ static int fat_write_inode(struct inode *inode, int wait) ...@@ -579,7 +578,7 @@ static int fat_write_inode(struct inode *inode, int wait)
if (i_pos != MSDOS_I(inode)->i_pos) { if (i_pos != MSDOS_I(inode)->i_pos) {
spin_unlock(&sbi->inode_hash_lock); spin_unlock(&sbi->inode_hash_lock);
brelse(bh); brelse(bh);
unlock_kernel(); unlock_super(sb);
goto retry; goto retry;
} }
...@@ -606,7 +605,7 @@ static int fat_write_inode(struct inode *inode, int wait) ...@@ -606,7 +605,7 @@ static int fat_write_inode(struct inode *inode, int wait)
err = sync_dirty_buffer(bh); err = sync_dirty_buffer(bh);
brelse(bh); brelse(bh);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
...@@ -736,6 +735,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) ...@@ -736,6 +735,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
static struct dentry *fat_get_parent(struct dentry *child) static struct dentry *fat_get_parent(struct dentry *child)
{ {
struct super_block *sb = child->d_sb;
struct buffer_head *bh; struct buffer_head *bh;
struct msdos_dir_entry *de; struct msdos_dir_entry *de;
loff_t i_pos; loff_t i_pos;
...@@ -743,14 +743,14 @@ static struct dentry *fat_get_parent(struct dentry *child) ...@@ -743,14 +743,14 @@ static struct dentry *fat_get_parent(struct dentry *child)
struct inode *inode; struct inode *inode;
int err; int err;
lock_kernel(); lock_super(sb);
err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos); err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);
if (err) { if (err) {
parent = ERR_PTR(err); parent = ERR_PTR(err);
goto out; goto out;
} }
inode = fat_build_inode(child->d_sb, de, i_pos); inode = fat_build_inode(sb, de, i_pos);
brelse(bh); brelse(bh);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
parent = ERR_CAST(inode); parent = ERR_CAST(inode);
...@@ -762,7 +762,7 @@ static struct dentry *fat_get_parent(struct dentry *child) ...@@ -762,7 +762,7 @@ static struct dentry *fat_get_parent(struct dentry *child)
parent = ERR_PTR(-ENOMEM); parent = ERR_PTR(-ENOMEM);
} }
out: out:
unlock_kernel(); unlock_super(sb);
return parent; return parent;
} }
...@@ -1172,6 +1172,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -1172,6 +1172,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
long error; long error;
char buf[50]; 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); sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
if (!sbi) if (!sbi)
return -ENOMEM; return -ENOMEM;
......
...@@ -214,7 +214,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, ...@@ -214,7 +214,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
dentry->d_op = &msdos_dentry_operations; dentry->d_op = &msdos_dentry_operations;
lock_kernel(); lock_super(sb);
res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
if (res == -ENOENT) if (res == -ENOENT)
goto add; goto add;
...@@ -232,7 +232,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, ...@@ -232,7 +232,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
if (dentry) if (dentry)
dentry->d_op = &msdos_dentry_operations; dentry->d_op = &msdos_dentry_operations;
out: out:
unlock_kernel(); unlock_super(sb);
if (!res) if (!res)
return dentry; return dentry;
return ERR_PTR(res); return ERR_PTR(res);
...@@ -286,7 +286,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -286,7 +286,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
unsigned char msdos_name[MSDOS_NAME]; unsigned char msdos_name[MSDOS_NAME];
int err, is_hid; int err, is_hid;
lock_kernel(); lock_super(sb);
err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options); msdos_name, &MSDOS_SB(sb)->options);
...@@ -315,7 +315,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -315,7 +315,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
out: out:
unlock_kernel(); unlock_super(sb);
if (!err) if (!err)
err = fat_flush_inodes(sb, dir, inode); err = fat_flush_inodes(sb, dir, inode);
return err; return err;
...@@ -324,11 +324,12 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -324,11 +324,12 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
/***** Remove a directory */ /***** Remove a directory */
static int msdos_rmdir(struct inode *dir, struct dentry *dentry) static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
{ {
struct super_block *sb = dir->i_sb;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
lock_kernel(); lock_super(sb);
/* /*
* Check whether the directory is not in use, then check * Check whether the directory is not in use, then check
* whether it is empty. * whether it is empty.
...@@ -349,9 +350,9 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -349,9 +350,9 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
unlock_kernel(); unlock_super(sb);
if (!err) if (!err)
err = fat_flush_inodes(inode->i_sb, dir, inode); err = fat_flush_inodes(sb, dir, inode);
return err; return err;
} }
...@@ -366,7 +367,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -366,7 +367,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
struct timespec ts; struct timespec ts;
int err, is_hid, cluster; int err, is_hid, cluster;
lock_kernel(); lock_super(sb);
err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options); msdos_name, &MSDOS_SB(sb)->options);
...@@ -404,14 +405,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -404,14 +405,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
unlock_kernel(); unlock_super(sb);
fat_flush_inodes(sb, dir, inode); fat_flush_inodes(sb, dir, inode);
return 0; return 0;
out_free: out_free:
fat_free_clusters(dir, cluster); fat_free_clusters(dir, cluster);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
...@@ -419,10 +420,11 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -419,10 +420,11 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
static int msdos_unlink(struct inode *dir, struct dentry *dentry) static int msdos_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct super_block *sb= inode->i_sb;
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
lock_kernel(); lock_super(sb);
err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
if (err) if (err)
goto out; goto out;
...@@ -434,9 +436,9 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) ...@@ -434,9 +436,9 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
unlock_kernel(); unlock_super(sb);
if (!err) if (!err)
err = fat_flush_inodes(inode->i_sb, dir, inode); err = fat_flush_inodes(sb, dir, inode);
return err; return err;
} }
...@@ -618,10 +620,11 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -618,10 +620,11 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_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]; unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
int err, is_hid; int err, is_hid;
lock_kernel(); lock_super(sb);
err = msdos_format_name(old_dentry->d_name.name, err = msdos_format_name(old_dentry->d_name.name,
old_dentry->d_name.len, old_msdos_name, old_dentry->d_name.len, old_msdos_name,
...@@ -640,9 +643,9 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -640,9 +643,9 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
err = do_msdos_rename(old_dir, old_msdos_name, old_dentry, err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
new_dir, new_msdos_name, new_dentry, is_hid); new_dir, new_msdos_name, new_dentry, is_hid);
out: out:
unlock_kernel(); unlock_super(sb);
if (!err) if (!err)
err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir); err = fat_flush_inodes(sb, old_dir, new_dir);
return err; return err;
} }
......
...@@ -645,7 +645,7 @@ static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir, ...@@ -645,7 +645,7 @@ static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
if (len == 0) if (len == 0)
return -ENOENT; return -ENOENT;
slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_KERNEL); slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS);
if (slots == NULL) if (slots == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -687,7 +687,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, ...@@ -687,7 +687,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
struct dentry *alias; struct dentry *alias;
int err, table; int err, table;
lock_kernel(); lock_super(sb);
table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0; table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0;
dentry->d_op = &vfat_dentry_ops[table]; dentry->d_op = &vfat_dentry_ops[table];
...@@ -699,7 +699,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, ...@@ -699,7 +699,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
brelse(sinfo.bh); brelse(sinfo.bh);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
unlock_kernel(); unlock_super(sb);
return ERR_CAST(inode); return ERR_CAST(inode);
} }
alias = d_find_alias(inode); alias = d_find_alias(inode);
...@@ -708,13 +708,13 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, ...@@ -708,13 +708,13 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
dput(alias); dput(alias);
else { else {
iput(inode); iput(inode);
unlock_kernel(); unlock_super(sb);
return alias; return alias;
} }
} }
error: error:
unlock_kernel(); unlock_super(sb);
dentry->d_op = &vfat_dentry_ops[table]; dentry->d_op = &vfat_dentry_ops[table];
dentry->d_time = dentry->d_parent->d_inode->i_version; dentry->d_time = dentry->d_parent->d_inode->i_version;
dentry = d_splice_alias(inode, dentry); dentry = d_splice_alias(inode, dentry);
...@@ -734,7 +734,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -734,7 +734,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, int mode,
struct timespec ts; struct timespec ts;
int err; int err;
lock_kernel(); lock_super(sb);
ts = CURRENT_TIME_SEC; ts = CURRENT_TIME_SEC;
err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
...@@ -755,17 +755,18 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -755,17 +755,18 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, int mode,
dentry->d_time = dentry->d_parent->d_inode->i_version; dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
static int vfat_rmdir(struct inode *dir, struct dentry *dentry) static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
lock_kernel(); lock_super(sb);
err = fat_dir_empty(inode); err = fat_dir_empty(inode);
if (err) if (err)
...@@ -783,7 +784,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -783,7 +784,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
...@@ -791,10 +792,11 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -791,10 +792,11 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
static int vfat_unlink(struct inode *dir, struct dentry *dentry) static int vfat_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
int err; int err;
lock_kernel(); lock_super(sb);
err = vfat_find(dir, &dentry->d_name, &sinfo); err = vfat_find(dir, &dentry->d_name, &sinfo);
if (err) if (err)
...@@ -807,7 +809,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry) ...@@ -807,7 +809,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
...@@ -820,7 +822,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -820,7 +822,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
struct timespec ts; struct timespec ts;
int err, cluster; int err, cluster;
lock_kernel(); lock_super(sb);
ts = CURRENT_TIME_SEC; ts = CURRENT_TIME_SEC;
cluster = fat_alloc_new_dir(dir, &ts); cluster = fat_alloc_new_dir(dir, &ts);
...@@ -849,13 +851,13 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -849,13 +851,13 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dentry->d_time = dentry->d_parent->d_inode->i_version; dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
unlock_kernel(); unlock_super(sb);
return 0; return 0;
out_free: out_free:
fat_free_clusters(dir, cluster); fat_free_clusters(dir, cluster);
out: out:
unlock_kernel(); unlock_super(sb);
return err; return err;
} }
...@@ -869,11 +871,12 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -869,11 +871,12 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct timespec ts; struct timespec ts;
loff_t dotdot_i_pos, new_i_pos; loff_t dotdot_i_pos, new_i_pos;
int err, is_dir, update_dotdot, corrupt = 0; int err, is_dir, update_dotdot, corrupt = 0;
struct super_block *sb = old_dir->i_sb;
old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
old_inode = old_dentry->d_inode; old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode; new_inode = new_dentry->d_inode;
lock_kernel(); lock_super(sb);
err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
if (err) if (err)
goto out; goto out;
...@@ -951,7 +954,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -951,7 +954,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
brelse(sinfo.bh); brelse(sinfo.bh);
brelse(dotdot_bh); brelse(dotdot_bh);
brelse(old_sinfo.bh); brelse(old_sinfo.bh);
unlock_kernel(); unlock_super(sb);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment