Commit 7994321a authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] BKL shifted inside ->unlink()

	Next one in the series - this time it's ->unlink()...
parent 24b10ca2
...@@ -54,7 +54,7 @@ create: no yes ...@@ -54,7 +54,7 @@ create: no yes
link: yes yes link: yes yes
mknod: no yes mknod: no yes
mkdir: yes yes mkdir: yes yes
unlink: yes yes (both) unlink: no yes (both)
rmdir: yes yes (both) (see below) rmdir: yes yes (both) (see below)
rename: yes yes (all) (see below) rename: yes yes (all) (see below)
readlink: no no readlink: no no
......
...@@ -80,8 +80,8 @@ can relax your locking. ...@@ -80,8 +80,8 @@ can relax your locking.
--- ---
[mandatory] [mandatory]
->lookup(), ->truncate(), ->create() and ->mknod() are called without BKL now. ->lookup(), ->truncate(), ->create(), ->unlink() and ->mknod() are called
Grab it on the entry, drop upon return - that will guarantee the same without BKL now. Grab it on the entry, drop upon return - that will
locking you used to have. If your ->method or its parts do not need guarantee the same locking you used to have. If your ->method or its
BKL - better yet, now you can shift lock_kernel()/ unlock_kernel() parts do not need BKL - better yet, now you can shift lock_kernel() /
so that they would protect exactly what needs to be protected. unlock_kernel() so that they would protect exactly what needs to be protected.
...@@ -199,7 +199,9 @@ static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -199,7 +199,9 @@ static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry)
if (pcihpfs_empty(dentry)) { if (pcihpfs_empty(dentry)) {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
dput(dentry); dput(dentry);
error = 0; error = 0;
} }
......
...@@ -256,7 +256,9 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -256,7 +256,9 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
if (usbfs_empty(dentry)) { if (usbfs_empty(dentry)) {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
dput(dentry); dput(dentry);
error = 0; error = 0;
} }
......
...@@ -253,13 +253,17 @@ affs_lookup(struct inode *dir, struct dentry *dentry) ...@@ -253,13 +253,17 @@ affs_lookup(struct inode *dir, struct dentry *dentry)
int int
affs_unlink(struct inode *dir, struct dentry *dentry) affs_unlink(struct inode *dir, struct dentry *dentry)
{ {
int res;
pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino, pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino,
(int)dentry->d_name.len, dentry->d_name.name); (int)dentry->d_name.len, dentry->d_name.name);
if (!dentry->d_inode) if (!dentry->d_inode)
return -ENOENT; return -ENOENT;
return affs_remove_header(dentry); lock_kernel();
res = affs_remove_header(dentry);
unlock_kernel();
return res;
} }
int int
......
...@@ -332,18 +332,27 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) ...@@ -332,18 +332,27 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
unsigned int n; unsigned int n;
/* This allows root to remove symlinks */ /* This allows root to remove symlinks */
if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) lock_kernel();
if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) {
unlock_kernel();
return -EACCES; return -EACCES;
}
ent = autofs_hash_lookup(dh, &dentry->d_name); ent = autofs_hash_lookup(dh, &dentry->d_name);
if ( !ent ) if ( !ent ) {
unlock_kernel();
return -ENOENT; return -ENOENT;
}
n = ent->ino - AUTOFS_FIRST_SYMLINK; n = ent->ino - AUTOFS_FIRST_SYMLINK;
if ( n >= AUTOFS_MAX_SYMLINKS ) if ( n >= AUTOFS_MAX_SYMLINKS ) {
unlock_kernel();
return -EISDIR; /* It's a directory, dummy */ return -EISDIR; /* It's a directory, dummy */
if ( !test_bit(n,sbi->symlink_bitmap) ) }
if ( !test_bit(n,sbi->symlink_bitmap) ) {
unlock_kernel();
return -EINVAL; /* Nonexistent symlink? Shouldn't happen */ return -EINVAL; /* Nonexistent symlink? Shouldn't happen */
}
dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL; dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL;
autofs_hash_delete(ent); autofs_hash_delete(ent);
...@@ -351,6 +360,7 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) ...@@ -351,6 +360,7 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
kfree(sbi->symlink[n].data); kfree(sbi->symlink[n].data);
d_drop(dentry); d_drop(dentry);
unlock_kernel();
return 0; return 0;
} }
......
...@@ -376,8 +376,11 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) ...@@ -376,8 +376,11 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
struct autofs_info *ino = autofs4_dentry_ino(dentry); struct autofs_info *ino = autofs4_dentry_ino(dentry);
/* This allows root to remove symlinks */ /* This allows root to remove symlinks */
if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) lock_kernel();
if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) {
unlock_kernel();
return -EACCES; return -EACCES;
}
dput(ino->dentry); dput(ino->dentry);
...@@ -387,6 +390,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) ...@@ -387,6 +390,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
dir->i_mtime = CURRENT_TIME; dir->i_mtime = CURRENT_TIME;
d_drop(dentry); d_drop(dentry);
unlock_kernel();
return 0; return 0;
} }
......
...@@ -174,6 +174,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry) ...@@ -174,6 +174,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
struct bfs_dirent * de; struct bfs_dirent * de;
inode = dentry->d_inode; inode = dentry->d_inode;
lock_kernel();
bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
if (!bh || de->ino != inode->i_ino) if (!bh || de->ino != inode->i_ino)
goto out_brelse; goto out_brelse;
...@@ -194,6 +195,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry) ...@@ -194,6 +195,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
out_brelse: out_brelse:
brelse(bh); brelse(bh);
unlock_kernel();
return error; return error;
} }
......
...@@ -425,6 +425,7 @@ int coda_unlink(struct inode *dir, struct dentry *de) ...@@ -425,6 +425,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
const char *name = de->d_name.name; const char *name = de->d_name.name;
int len = de->d_name.len; int len = de->d_name.len;
lock_kernel();
coda_vfs_stat.unlink++; coda_vfs_stat.unlink++;
CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name ,
...@@ -433,11 +434,13 @@ int coda_unlink(struct inode *dir, struct dentry *de) ...@@ -433,11 +434,13 @@ int coda_unlink(struct inode *dir, struct dentry *de)
error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
if ( error ) { if ( error ) {
CDEBUG(D_INODE, "upc returned error %d\n", error); CDEBUG(D_INODE, "upc returned error %d\n", error);
unlock_kernel();
return error; return error;
} }
coda_dir_changed(dir, 0); coda_dir_changed(dir, 0);
de->d_inode->i_nlink--; de->d_inode->i_nlink--;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -3030,19 +3030,30 @@ static int devfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -3030,19 +3030,30 @@ static int devfs_unlink (struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct fs_info *fs_info = dir->i_sb->u.generic_sbp; struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode); de = get_devfs_entry_from_vfs_inode (inode);
DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de); DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
if (de == NULL) return -ENOENT; if (de == NULL) {
if (!de->vfs_deletable) return -EPERM; unlock_kernel();
return -ENOENT;
}
if (!de->vfs_deletable) {
unlock_kernel();
return -EPERM;
}
write_lock (&de->parent->u.dir.lock); write_lock (&de->parent->u.dir.lock);
unhooked = _devfs_unhook (de); unhooked = _devfs_unhook (de);
write_unlock (&de->parent->u.dir.lock); write_unlock (&de->parent->u.dir.lock);
if (!unhooked) return -ENOENT; if (!unhooked) {
unlock_kernel();
return -ENOENT;
}
if ( !is_devfsd_or_child (fs_info) ) if ( !is_devfsd_or_child (fs_info) )
devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode, devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
inode->i_uid, inode->i_gid, fs_info, 0); inode->i_uid, inode->i_gid, fs_info, 0);
free_dentry (de); free_dentry (de);
devfs_put (de); devfs_put (de);
unlock_kernel();
return 0; return 0;
} /* End Function devfs_unlink */ } /* End Function devfs_unlink */
......
...@@ -180,7 +180,9 @@ static int driverfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -180,7 +180,9 @@ static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
if (driverfs_empty(dentry)) { if (driverfs_empty(dentry)) {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
dput(dentry); dput(dentry);
error = 0; error = 0;
} }
......
...@@ -862,9 +862,12 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) ...@@ -862,9 +862,12 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
struct ext3_dir_entry_2 * de; struct ext3_dir_entry_2 * de;
handle_t *handle; handle_t *handle;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
if (IS_ERR(handle)) if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle); return PTR_ERR(handle);
}
if (IS_SYNC(dir)) if (IS_SYNC(dir))
handle->h_sync = 1; handle->h_sync = 1;
...@@ -902,6 +905,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) ...@@ -902,6 +905,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
end_unlink: end_unlink:
ext3_journal_stop(handle, dir); ext3_journal_stop(handle, dir);
unlock_kernel();
brelse (bh); brelse (bh);
return retval; return retval;
} }
...@@ -1129,7 +1133,7 @@ struct inode_operations ext3_dir_inode_operations = { ...@@ -1129,7 +1133,7 @@ struct inode_operations ext3_dir_inode_operations = {
create: ext3_create, create: ext3_create,
lookup: ext3_lookup, lookup: ext3_lookup,
link: ext3_link, /* BKL held */ link: ext3_link, /* BKL held */
unlink: ext3_unlink, /* BKL held */ unlink: ext3_unlink,
symlink: ext3_symlink, /* BKL held */ symlink: ext3_symlink, /* BKL held */
mkdir: ext3_mkdir, /* BKL held */ mkdir: ext3_mkdir, /* BKL held */
rmdir: ext3_rmdir, /* BKL held */ rmdir: ext3_rmdir, /* BKL held */
......
...@@ -262,12 +262,18 @@ int hfs_unlink(struct inode * dir, struct dentry *dentry) ...@@ -262,12 +262,18 @@ int hfs_unlink(struct inode * dir, struct dentry *dentry)
struct hfs_cat_key key; struct hfs_cat_key key;
int error; int error;
lock_kernel();
entry = HFS_I(dir)->entry;
if (build_key(&key, dir, dentry->d_name.name, if (build_key(&key, dir, dentry->d_name.name,
dentry->d_name.len)) dentry->d_name.len)) {
unlock_kernel();
return -EPERM; return -EPERM;
}
if (!(victim = hfs_cat_get(entry->mdb, &key))) if (!(victim = hfs_cat_get(entry->mdb, &key))) {
unlock_kernel();
return -ENOENT; return -ENOENT;
}
error = -EPERM; error = -EPERM;
if (victim->type != HFS_CDR_FIL) if (victim->type != HFS_CDR_FIL)
...@@ -285,6 +291,7 @@ int hfs_unlink(struct inode * dir, struct dentry *dentry) ...@@ -285,6 +291,7 @@ int hfs_unlink(struct inode * dir, struct dentry *dentry)
hfs_unlink_put: hfs_unlink_put:
hfs_cat_put(victim); /* Note that hfs_cat_put(NULL) is safe. */ hfs_cat_put(victim); /* Note that hfs_cat_put(NULL) is safe. */
unlock_kernel();
return error; return error;
} }
......
...@@ -315,11 +315,13 @@ static int dbl_unlink(struct inode * dir, struct dentry *dentry) ...@@ -315,11 +315,13 @@ static int dbl_unlink(struct inode * dir, struct dentry *dentry)
{ {
int error; int error;
lock_kernel();
error = hfs_unlink(dir, dentry); error = hfs_unlink(dir, dentry);
if ((error == -ENOENT) && is_hdr(dir, dentry->d_name.name, if ((error == -ENOENT) && is_hdr(dir, dentry->d_name.name,
dentry->d_name.len)) { dentry->d_name.len)) {
error = -EPERM; error = -EPERM;
} }
unlock_kernel();
return error; return error;
} }
......
...@@ -369,9 +369,11 @@ static int nat_rmdir(struct inode *parent, struct dentry *dentry) ...@@ -369,9 +369,11 @@ static int nat_rmdir(struct inode *parent, struct dentry *dentry)
*/ */
static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry) static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct hfs_cat_entry *entry = HFS_I(dir)->entry; struct hfs_cat_entry *entry;
int error = 0; int error = 0;
lock_kernel();
entry = HFS_I(dir)->entry;
if (!HFS_SB(dir->i_sb)->s_afpd) { if (!HFS_SB(dir->i_sb)->s_afpd) {
/* Not in AFPD compatibility mode */ /* Not in AFPD compatibility mode */
error = -EPERM; error = -EPERM;
...@@ -396,6 +398,7 @@ static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry) ...@@ -396,6 +398,7 @@ static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry)
} }
} }
} }
unlock_kernel();
return error; return error;
} }
......
...@@ -313,21 +313,26 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -313,21 +313,26 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry)
fnode_secno fno; fnode_secno fno;
int r; int r;
int rep = 0; int rep = 0;
lock_kernel();
hpfs_adjust_length((char *)name, &len); hpfs_adjust_length((char *)name, &len);
again: again:
hpfs_lock_2inodes(dir, inode); hpfs_lock_2inodes(dir, inode);
if (!(de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh))) { if (!(de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh))) {
hpfs_unlock_2inodes(dir, inode); hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -ENOENT; return -ENOENT;
} }
if (de->first) { if (de->first) {
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode); hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -EPERM; return -EPERM;
} }
if (de->directory) { if (de->directory) {
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode); hpfs_unlock_2inodes(dir, inode);
unlock_kernel();
return -EISDIR; return -EISDIR;
} }
fno = de->fnode; fno = de->fnode;
...@@ -360,7 +365,8 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -360,7 +365,8 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry)
rep = 1; rep = 1;
goto again; goto again;
} }
ret: ret:
unlock_kernel();
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0; return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
} }
......
...@@ -912,12 +912,14 @@ jffs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -912,12 +912,14 @@ jffs_unlink(struct inode *dir, struct dentry *dentry)
struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp; struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp;
int ret; int ret;
lock_kernel();
D3(printk("***jffs_unlink()\n")); D3(printk("***jffs_unlink()\n"));
D3(printk (KERN_NOTICE "unlink(): down biglock\n")); D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
down(&c->fmc->biglock); down(&c->fmc->biglock);
ret = jffs_remove(dir, dentry, 0); ret = jffs_remove(dir, dentry, 0);
D3(printk (KERN_NOTICE "unlink(): up biglock\n")); D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
up(&c->fmc->biglock); up(&c->fmc->biglock);
unlock_kernel();
return ret; return ret;
} }
......
...@@ -425,7 +425,11 @@ static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int renam ...@@ -425,7 +425,11 @@ static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int renam
static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
{ {
return jffs2_do_unlink(dir_i, dentry, 0); int res;
lock_kernel();
res = jffs2_do_unlink(dir_i, dentry, 0);
unlock_kernel();
return res;
} }
/***********************************************************************/ /***********************************************************************/
......
...@@ -11,13 +11,17 @@ ...@@ -11,13 +11,17 @@
static inline void inc_count(struct inode *inode) static inline void inc_count(struct inode *inode)
{ {
lock_kernel();
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
static inline void dec_count(struct inode *inode) static inline void dec_count(struct inode *inode)
{ {
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
...@@ -67,17 +71,13 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry) ...@@ -67,17 +71,13 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
if (dentry->d_name.len > dir->i_sb->u.minix_sb.s_namelen) if (dentry->d_name.len > dir->i_sb->u.minix_sb.s_namelen)
return ERR_PTR(-ENAMETOOLONG); return ERR_PTR(-ENAMETOOLONG);
lock_kernel();
ino = minix_inode_by_name(dentry); ino = minix_inode_by_name(dentry);
if (ino) { if (ino) {
inode = iget(dir->i_sb, ino); inode = iget(dir->i_sb, ino);
if (!inode) { if (!inode)
unlock_kernel();
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
}
} }
unlock_kernel();
d_add(dentry, inode); d_add(dentry, inode);
return NULL; return NULL;
} }
...@@ -91,9 +91,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int ...@@ -91,9 +91,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int
inode->i_mode = mode; inode->i_mode = mode;
minix_set_inode(inode, rdev); minix_set_inode(inode, rdev);
mark_inode_dirty(inode); mark_inode_dirty(inode);
lock_kernel();
error = add_nondir(dentry, inode); error = add_nondir(dentry, inode);
unlock_kernel();
} }
return error; return error;
} }
...@@ -266,8 +264,11 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -266,8 +264,11 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
inc_count(old_inode); inc_count(old_inode);
minix_set_link(new_de, new_page, old_inode); minix_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME; new_inode->i_ctime = CURRENT_TIME;
if (dir_de) if (dir_de) {
lock_kernel();
new_inode->i_nlink--; new_inode->i_nlink--;
unlock_kernel();
}
dec_count(new_inode); dec_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -424,6 +424,7 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry) ...@@ -424,6 +424,7 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry)
struct msdos_dir_entry *de; struct msdos_dir_entry *de;
bh = NULL; bh = NULL;
lock_kernel();
res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
&bh, &de, &ino); &bh, &de, &ino);
if (res < 0) if (res < 0)
...@@ -439,6 +440,7 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry) ...@@ -439,6 +440,7 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry)
mark_inode_dirty(dir); mark_inode_dirty(dir);
res = 0; res = 0;
unlink_done: unlink_done:
unlock_kernel();
return res; return res;
} }
......
...@@ -1486,9 +1486,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1486,9 +1486,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
if (d_mountpoint(dentry)) if (d_mountpoint(dentry))
error = -EBUSY; error = -EBUSY;
else { else {
lock_kernel();
error = dir->i_op->unlink(dir, dentry); error = dir->i_op->unlink(dir, dentry);
unlock_kernel();
if (!error) if (!error)
d_delete(dentry); d_delete(dentry);
} }
......
...@@ -958,9 +958,11 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -958,9 +958,11 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
static int ncp_unlink(struct inode *dir, struct dentry *dentry) static int ncp_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct ncp_server *server = NCP_SERVER(dir); struct ncp_server *server;
int error; int error;
lock_kernel();
server = NCP_SERVER(dir);
DPRINTK("ncp_unlink: unlinking %s/%s\n", DPRINTK("ncp_unlink: unlinking %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name);
...@@ -1011,6 +1013,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1011,6 +1013,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
} }
out: out:
unlock_kernel();
return error; return error;
} }
......
...@@ -871,6 +871,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -871,6 +871,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name); dir->i_ino, dentry->d_name.name);
lock_kernel();
error = nfs_sillyrename(dir, dentry); error = nfs_sillyrename(dir, dentry);
if (error && error != -EBUSY) { if (error && error != -EBUSY) {
error = nfs_safe_remove(dentry); error = nfs_safe_remove(dentry);
...@@ -878,6 +879,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -878,6 +879,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
nfs_renew_times(dentry); nfs_renew_times(dentry);
} }
} }
unlock_kernel();
return error; return error;
} }
......
...@@ -871,6 +871,7 @@ static int openpromfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -871,6 +871,7 @@ static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
name = dentry->d_name.name; name = dentry->d_name.name;
len = dentry->d_name.len; len = dentry->d_name.len;
lock_kernel();
for (i = 0; i < aliases_nodes; i++) for (i = 0; i < aliases_nodes; i++)
if ((strlen (alias_names [i]) == len) if ((strlen (alias_names [i]) == len)
&& !strncmp (name, alias_names[i], len)) { && !strncmp (name, alias_names[i], len)) {
...@@ -884,6 +885,7 @@ static int openpromfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -884,6 +885,7 @@ static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
buffer [10 + len] = 0; buffer [10 + len] = 0;
prom_feval (buffer); prom_feval (buffer);
} }
unlock_kernel();
return 0; return 0;
} }
......
...@@ -205,9 +205,11 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry) ...@@ -205,9 +205,11 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
int ino; int ino;
QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name)); QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name));
lock_kernel();
bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name, bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
&de, &ino); &de, &ino);
if (bh == NULL) { if (bh == NULL) {
unlock_kernel();
return -ENOENT; return -ENOENT;
} }
inode = dentry->d_inode; inode = dentry->d_inode;
...@@ -233,7 +235,8 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry) ...@@ -233,7 +235,8 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
mark_inode_dirty(inode); mark_inode_dirty(inode);
retval = 0; retval = 0;
end_unlink: end_unlink:
unlock_kernel();
brelse(bh); brelse(bh);
return retval; return retval;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -219,7 +220,9 @@ static int ramfs_unlink(struct inode * dir, struct dentry *dentry) ...@@ -219,7 +220,9 @@ static int ramfs_unlink(struct inode * dir, struct dentry *dentry)
if (ramfs_empty(dentry)) { if (ramfs_empty(dentry)) {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
dput(dentry); /* Undo the count from "create" - this does all the work */ dput(dentry); /* Undo the count from "create" - this does all the work */
retval = 0; retval = 0;
} }
......
...@@ -817,6 +817,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry) ...@@ -817,6 +817,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
two stat datas */ two stat datas */
jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2; jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2;
lock_kernel();
journal_begin(&th, dir->i_sb, jbegin_count) ; journal_begin(&th, dir->i_sb, jbegin_count) ;
windex = push_journal_writer("reiserfs_unlink") ; windex = push_journal_writer("reiserfs_unlink") ;
...@@ -865,6 +866,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry) ...@@ -865,6 +866,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
pop_journal_writer(windex) ; pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ; journal_end(&th, dir->i_sb, jbegin_count) ;
reiserfs_check_path(&path) ; reiserfs_check_path(&path) ;
unlock_kernel();
return 0; return 0;
end_unlink: end_unlink:
...@@ -872,6 +874,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry) ...@@ -872,6 +874,7 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
pop_journal_writer(windex) ; pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ; journal_end(&th, dir->i_sb, jbegin_count) ;
reiserfs_check_path(&path) ; reiserfs_check_path(&path) ;
unlock_kernel();
return retval; return retval;
} }
......
...@@ -545,12 +545,14 @@ smb_unlink(struct inode *dir, struct dentry *dentry) ...@@ -545,12 +545,14 @@ smb_unlink(struct inode *dir, struct dentry *dentry)
/* /*
* Close the file if it's open. * Close the file if it's open.
*/ */
lock_kernel();
smb_close(dentry->d_inode); smb_close(dentry->d_inode);
smb_invalid_dir_cache(dir); smb_invalid_dir_cache(dir);
error = smb_proc_unlink(dentry); error = smb_proc_unlink(dentry);
if (!error) if (!error)
smb_renew_times(dentry); smb_renew_times(dentry);
unlock_kernel();
return error; return error;
} }
......
...@@ -19,13 +19,17 @@ ...@@ -19,13 +19,17 @@
static inline void inc_count(struct inode *inode) static inline void inc_count(struct inode *inode)
{ {
lock_kernel();
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
static inline void dec_count(struct inode *inode) static inline void dec_count(struct inode *inode)
{ {
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
...@@ -73,17 +77,13 @@ static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry) ...@@ -73,17 +77,13 @@ static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry)
dentry->d_op = dir->i_sb->s_root->d_op; dentry->d_op = dir->i_sb->s_root->d_op;
if (dentry->d_name.len > SYSV_NAMELEN) if (dentry->d_name.len > SYSV_NAMELEN)
return ERR_PTR(-ENAMETOOLONG); return ERR_PTR(-ENAMETOOLONG);
lock_kernel();
ino = sysv_inode_by_name(dentry); ino = sysv_inode_by_name(dentry);
if (ino) { if (ino) {
inode = iget(dir->i_sb, ino); inode = iget(dir->i_sb, ino);
if (!inode) { if (!inode)
unlock_kernel();
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
}
} }
unlock_kernel();
d_add(dentry, inode); d_add(dentry, inode);
return NULL; return NULL;
} }
...@@ -96,9 +96,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int ...@@ -96,9 +96,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int
if (!IS_ERR(inode)) { if (!IS_ERR(inode)) {
sysv_set_inode(inode, rdev); sysv_set_inode(inode, rdev);
mark_inode_dirty(inode); mark_inode_dirty(inode);
lock_kernel();
err = add_nondir(dentry, inode); err = add_nondir(dentry, inode);
unlock_kernel();
} }
return err; return err;
} }
...@@ -274,8 +272,11 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -274,8 +272,11 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
inc_count(old_inode); inc_count(old_inode);
sysv_set_link(new_de, new_page, old_inode); sysv_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME; new_inode->i_ctime = CURRENT_TIME;
if (dir_de) if (dir_de) {
lock_kernel();
new_inode->i_nlink--; new_inode->i_nlink--;
unlock_kernel();
}
dec_count(new_inode); dec_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -892,6 +892,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry) ...@@ -892,6 +892,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
struct FileIdentDesc cfi; struct FileIdentDesc cfi;
retval = -ENOENT; retval = -ENOENT;
lock_kernel();
fi = udf_find_entry(dir, dentry, &fibh, &cfi); fi = udf_find_entry(dir, dentry, &fibh, &cfi);
if (!fi) if (!fi)
goto out; goto out;
...@@ -926,6 +927,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry) ...@@ -926,6 +927,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
udf_release_data(fibh.ebh); udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh); udf_release_data(fibh.sbh);
out: out:
unlock_kernel();
return retval; return retval;
} }
......
...@@ -228,6 +228,7 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry) ...@@ -228,6 +228,7 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry)
struct ufs_dir_entry * de; struct ufs_dir_entry * de;
int err = -ENOENT; int err = -ENOENT;
lock_kernel();
de = ufs_find_entry (dentry, &bh); de = ufs_find_entry (dentry, &bh);
if (!de) if (!de)
goto out; goto out;
...@@ -240,6 +241,7 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry) ...@@ -240,6 +241,7 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry)
ufs_dec_count(inode); ufs_dec_count(inode);
err = 0; err = 0;
out: out:
unlock_kernel();
return err; return err;
} }
......
...@@ -1112,9 +1112,12 @@ int vfat_unlink(struct inode *dir, struct dentry* dentry) ...@@ -1112,9 +1112,12 @@ int vfat_unlink(struct inode *dir, struct dentry* dentry)
struct msdos_dir_entry *de; struct msdos_dir_entry *de;
PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name)); PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
lock_kernel();
res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de); res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
if (res < 0) if (res < 0) {
unlock_kernel();
return res; return res;
}
dentry->d_inode->i_nlink = 0; dentry->d_inode->i_nlink = 0;
dentry->d_inode->i_mtime = CURRENT_TIME; dentry->d_inode->i_mtime = CURRENT_TIME;
dentry->d_inode->i_atime = CURRENT_TIME; dentry->d_inode->i_atime = CURRENT_TIME;
...@@ -1122,6 +1125,7 @@ int vfat_unlink(struct inode *dir, struct dentry* dentry) ...@@ -1122,6 +1125,7 @@ int vfat_unlink(struct inode *dir, struct dentry* dentry)
mark_inode_dirty(dentry->d_inode); mark_inode_dirty(dentry->d_inode);
/* releases bh */ /* releases bh */
vfat_remove_entry(dir,&sinfo,bh,de); vfat_remove_entry(dir,&sinfo,bh,de);
unlock_kernel();
return res; return res;
} }
......
...@@ -1069,7 +1069,9 @@ static int shmem_unlink(struct inode * dir, struct dentry *dentry) ...@@ -1069,7 +1069,9 @@ static int shmem_unlink(struct inode * dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel();
dput(dentry); /* Undo the count from "create" - this does all the work */ dput(dentry); /* Undo the count from "create" - this does all the work */
return 0; 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