Commit 90ed880a authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] (2/5) more BKL shifting

BKL shifted into ->rmdir()
parent b2461ad6
......@@ -59,7 +59,7 @@ link: yes yes
mknod: no yes
mkdir: no yes
unlink: no yes (both)
rmdir: yes yes (both) (see below)
rmdir: no yes (both) (see below)
rename: yes yes (all) (see below)
readlink: no no
follow_link: no no
......
......@@ -80,8 +80,9 @@ can relax your locking.
---
[mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod() and ->mkdir()
are called without BKL now. Grab it on the entry, drop upon return - that
will guarantee the same locking you used to have. If your ->method or its
parts do not need BKL - better yet, now you can shift lock_kernel() /
unlock_kernel() so that they would protect exactly what needs to be protected.
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir() and
->rmdir() are called without BKL now. Grab it on the entry, drop upon
return - that will guarantee the same locking you used to have. If your
method or its parts do not need BKL - better yet, now you can shift
lock_kernel() / unlock_kernel() so that they would protect exactly what
needs to be protected.
......@@ -881,17 +881,22 @@ static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode)
static int comx_rmdir(struct inode *dir, struct dentry *dentry)
{
struct proc_dir_entry *entry = PDE(dentry->d_inode);
struct net_device *dev = entry->data;
struct comx_channel *ch = dev->priv;
struct net_device *dev;
struct comx_channel *ch;
int ret;
lock_kernel();
dev = entry->data;
ch = dev->priv;
if (dev->flags & IFF_UP) {
printk(KERN_ERR "%s: down interface before removing it\n", dev->name);
unlock_kernel();
return -EBUSY;
}
if (ch->protocol && ch->protocol->line_exit &&
(ret=ch->protocol->line_exit(dev))) {
unlock_kernel();
return ret;
}
if (ch->hardware && ch->hardware->hw_exit &&
......@@ -899,6 +904,7 @@ static int comx_rmdir(struct inode *dir, struct dentry *dentry)
if(ch->protocol && ch->protocol->line_init) {
ch->protocol->line_init(dev);
}
unlock_kernel();
return ret;
}
ch->protocol = NULL;
......@@ -924,6 +930,7 @@ static int comx_rmdir(struct inode *dir, struct dentry *dentry)
remove_proc_entry(dentry->d_name.name, comx_root_dir);
MOD_DEC_USE_COUNT;
unlock_kernel();
return 0;
}
......
......@@ -338,13 +338,19 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
int
affs_rmdir(struct inode *dir, struct dentry *dentry)
{
int res;
pr_debug("AFFS: rmdir(dir=%u, \"%.*s\")\n", (u32)dir->i_ino,
(int)dentry->d_name.len, dentry->d_name.name);
lock_kernel();
/* WTF??? */
if (!dentry->d_inode)
return -ENOENT;
return affs_remove_header(dentry);
res = affs_remove_header(dentry);
unlock_kernel();
return res;
}
int
......
......@@ -370,15 +370,22 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
struct autofs_dirhash *dh = &sbi->dirhash;
struct autofs_dir_ent *ent;
if ( !autofs_oz_mode(sbi) )
lock_kernel();
if ( !autofs_oz_mode(sbi) ) {
unlock_kernel();
return -EACCES;
}
ent = autofs_hash_lookup(dh, &dentry->d_name);
if ( !ent )
if ( !ent ) {
unlock_kernel();
return -ENOENT;
}
if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO )
if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) {
unlock_kernel();
return -ENOTDIR; /* Not a directory */
}
if ( ent->dentry != dentry ) {
printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name);
......@@ -388,6 +395,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
autofs_hash_delete(ent);
dir->i_nlink--;
d_drop(dentry);
unlock_kernel();
return 0;
}
......
......@@ -401,12 +401,16 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (!autofs4_oz_mode(sbi))
lock_kernel();
if (!autofs4_oz_mode(sbi)) {
unlock_kernel();
return -EACCES;
}
spin_lock(&dcache_lock);
if (!list_empty(&dentry->d_subdirs)) {
spin_unlock(&dcache_lock);
unlock_kernel();
return -ENOTEMPTY;
}
list_del_init(&dentry->d_hash);
......@@ -420,6 +424,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
if (dir->i_nlink)
dir->i_nlink--;
unlock_kernel();
return 0;
}
......
......@@ -457,20 +457,25 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
int len = de->d_name.len;
int error;
lock_kernel();
coda_vfs_stat.rmdir++;
if (!d_unhashed(de))
if (!d_unhashed(de)) {
unlock_kernel();
return -EBUSY;
}
error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
if ( error ) {
CDEBUG(D_INODE, "upc returned error %d\n", error);
unlock_kernel();
return error;
}
coda_dir_changed(dir, -1);
de->d_inode->i_nlink--;
d_delete(de);
unlock_kernel();
return 0;
}
......
......@@ -3140,27 +3140,45 @@ static int devfs_rmdir (struct inode *dir, struct dentry *dentry)
struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct inode *inode = dentry->d_inode;
/* WTF??? */
if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL;
lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode);
if (de == NULL) return -ENOENT;
if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
if (!de->vfs_deletable) return -EPERM;
if (de == NULL) {
unlock_kernel();
return -ENOENT;
}
if ( !S_ISDIR (de->mode) ) {
unlock_kernel();
return -ENOTDIR;
}
if (!de->vfs_deletable) {
unlock_kernel();
return -EPERM;
}
/* First ensure the directory is empty and will stay thay way */
write_lock (&de->u.dir.lock);
de->u.dir.no_more_additions = TRUE;
if (de->u.dir.first) err = -ENOTEMPTY;
write_unlock (&de->u.dir.lock);
if (err) return err;
if (err) {
unlock_kernel();
return err;
}
/* Now unhook the directory from it's parent */
write_lock (&de->parent->u.dir.lock);
if ( !_devfs_unhook (de) ) err = -ENOENT;
write_unlock (&de->parent->u.dir.lock);
if (err) return err;
if (err) {
unlock_kernel();
return err;
}
if ( !is_devfsd_or_child (fs_info) )
devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
inode->i_uid, inode->i_gid, fs_info, 0);
free_dentry (de);
devfs_put (de);
unlock_kernel();
return 0;
} /* End Function devfs_rmdir */
......
......@@ -809,9 +809,12 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
struct ext3_dir_entry_2 * de;
handle_t *handle;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
if (IS_ERR(handle))
if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle);
}
retval = -ENOENT;
bh = ext3_find_entry (dentry, &de);
......@@ -855,6 +858,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
end_rmdir:
ext3_journal_stop(handle, dir);
brelse (bh);
unlock_kernel();
return retval;
}
......
......@@ -313,18 +313,24 @@ int hfs_unlink(struct inode * dir, struct dentry *dentry)
*/
int hfs_rmdir(struct inode * parent, struct dentry *dentry)
{
struct hfs_cat_entry *entry = HFS_I(parent)->entry;
struct hfs_cat_entry *entry;
struct hfs_cat_entry *victim = NULL;
struct inode *inode = dentry->d_inode;
struct hfs_cat_key key;
int error;
lock_kernel();
entry = HFS_I(parent)->entry;
if (build_key(&key, parent, dentry->d_name.name,
dentry->d_name.len))
dentry->d_name.len)) {
unlock_kernel();
return -EPERM;
}
if (!(victim = hfs_cat_get(entry->mdb, &key)))
if (!(victim = hfs_cat_get(entry->mdb, &key))) {
unlock_kernel();
return -ENOENT;
}
error = -ENOTDIR;
if (victim->type != HFS_CDR_DIR)
......@@ -352,6 +358,7 @@ int hfs_rmdir(struct inode * parent, struct dentry *dentry)
hfs_rmdir_put:
hfs_cat_put(victim); /* Note that hfs_cat_put(NULL) is safe. */
unlock_kernel();
return error;
}
......
......@@ -339,11 +339,13 @@ static int dbl_rmdir(struct inode * parent, struct dentry *dentry)
{
int error;
lock_kernel();
error = hfs_rmdir(parent, dentry);
if ((error == -ENOENT) && is_hdr(parent, dentry->d_name.name,
dentry->d_name.len)) {
error = -ENOTDIR;
}
unlock_kernel();
return error;
}
......
......@@ -333,6 +333,7 @@ static int nat_rmdir(struct inode *parent, struct dentry *dentry)
struct hfs_name cname;
int error;
lock_kernel();
hfs_nameout(parent, &cname, dentry->d_name.name, dentry->d_name.len);
if (hfs_streq(cname.Name, cname.Len,
DOT_APPLEDOUBLE->Name, DOT_APPLEDOUBLE_LEN)) {
......@@ -349,6 +350,7 @@ static int nat_rmdir(struct inode *parent, struct dentry *dentry)
} else {
error = hfs_rmdir(parent, dentry);
}
unlock_kernel();
return error;
}
......
......@@ -386,25 +386,30 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
int n_items = 0;
int r;
hpfs_adjust_length((char *)name, &len);
lock_kernel();
hpfs_lock_2inodes(dir, inode);
if (!(de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh))) {
hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -ENOENT;
}
if (de->first) {
hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -EPERM;
}
if (!de->directory) {
hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -ENOTDIR;
}
hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items);
if (n_items) {
hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -ENOTEMPTY;
}
fno = de->fnode;
......@@ -415,6 +420,7 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_nlink = 0;
hpfs_unlock_2inodes(dir, inode);
} else hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
}
......
......@@ -900,10 +900,12 @@ jffs_rmdir(struct inode *dir, struct dentry *dentry)
int ret;
D3(printk("***jffs_rmdir()\n"));
D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
lock_kernel();
down(&c->fmc->biglock);
ret = jffs_remove(dir, dentry, S_IFDIR);
D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
up(&c->fmc->biglock);
unlock_kernel();
return ret;
}
......
......@@ -793,10 +793,14 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
struct jffs2_full_dirent *fd;
lock_kernel();
for (fd = f->dents ; fd; fd = fd->next) {
if (fd->ino)
if (fd->ino) {
unlock_kernel();
return -ENOTEMPTY;
}
}
unlock_kernel();
return jffs2_unlink(dir_i, dentry);
}
......
......@@ -323,6 +323,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
struct msdos_dir_entry *de;
bh = NULL;
lock_kernel();
res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
&bh, &de, &ino);
if (res < 0)
......@@ -347,6 +348,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
rmdir_done:
fat_brelse(sb, bh);
unlock_kernel();
return res;
}
......
......@@ -1409,9 +1409,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
else if (d_mountpoint(dentry))
error = -EBUSY;
else {
lock_kernel();
error = dir->i_op->rmdir(dir, dentry);
unlock_kernel();
if (!error)
dentry->d_inode->i_flags |= S_DEAD;
}
......
......@@ -915,6 +915,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_parent->d_name.name, dentry->d_name.name);
error = -EIO;
lock_kernel();
if (!ncp_conn_valid(server))
goto out;
......@@ -954,6 +955,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
break;
}
out:
unlock_kernel();
return error;
}
......
......@@ -726,10 +726,12 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
dfprintk(VFS, "NFS: rmdir(%s/%ld, %s\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name);
lock_kernel();
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
if (!error)
dentry->d_inode->i_nlink = 0;
unlock_kernel();
return error;
}
......
......@@ -159,9 +159,11 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
int ino;
QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
lock_kernel();
bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
&de, &ino);
if (bh == NULL) {
unlock_kernel();
return -ENOENT;
}
inode = dentry->d_inode;
......@@ -193,6 +195,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
end_rmdir:
brelse(bh);
unlock_kernel();
return retval;
}
......
......@@ -732,6 +732,7 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
/* we will be doing 2 balancings and update 2 stat data */
jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2;
lock_kernel();
journal_begin(&th, dir->i_sb, jbegin_count) ;
windex = push_journal_writer("reiserfs_rmdir") ;
......@@ -785,6 +786,7 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
reiserfs_check_path(&path) ;
unlock_kernel();
return 0;
end_rmdir:
......@@ -794,6 +796,7 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
pathrelse (&path);
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
unlock_kernel();
return retval;
}
......
......@@ -523,6 +523,7 @@ smb_rmdir(struct inode *dir, struct dentry *dentry)
/*
* Close the directory if it's open.
*/
lock_kernel();
smb_close(inode);
/*
......@@ -536,6 +537,7 @@ smb_rmdir(struct inode *dir, struct dentry *dentry)
error = smb_proc_rmdir(dentry);
out:
unlock_kernel();
return error;
}
......
......@@ -852,6 +852,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
struct FileIdentDesc *fi, cfi;
retval = -ENOENT;
lock_kernel();
fi = udf_find_entry(dir, dentry, &fibh, &cfi);
if (!fi)
goto out;
......@@ -882,6 +883,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
out:
unlock_kernel();
return retval;
}
......
......@@ -253,6 +253,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
struct inode * inode = dentry->d_inode;
int err= -ENOTEMPTY;
lock_kernel();
if (ufs_empty_dir (inode)) {
err = ufs_unlink(dir, dentry);
if (!err) {
......@@ -261,6 +262,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
ufs_dec_count(dir);
}
}
unlock_kernel();
return err;
}
......
......@@ -1086,13 +1086,18 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
lock_kernel();
res = fat_dir_empty(dentry->d_inode);
if (res)
if (res) {
unlock_kernel();
return res;
}
res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
if (res<0)
if (res<0) {
unlock_kernel();
return res;
}
dentry->d_inode->i_nlink = 0;
dentry->d_inode->i_mtime = CURRENT_TIME;
dentry->d_inode->i_atime = CURRENT_TIME;
......@@ -1101,6 +1106,7 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
/* releases bh */
vfat_remove_entry(dir,&sinfo,bh,de);
dir->i_nlink--;
unlock_kernel();
return 0;
}
......
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