Commit c89d22eb authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] (4/5) more BKL shifting

BKL shifted into ->symlink() (+ fixes for {ramfs,shmem}_symlink())
parent a48489f8
......@@ -57,6 +57,7 @@ lookup: no yes
create: no yes
link: no yes
mknod: no yes
symlink: no yes
mkdir: no yes
unlink: no yes (both)
rmdir: no yes (both) (see below)
......
......@@ -81,11 +81,11 @@ can relax your locking.
[mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
->rmdir() and ->link() 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.
->rmdir(), ->link() and ->symlink() 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.
---
[informational]
......
......@@ -366,11 +366,14 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino,
(int)dentry->d_name.len,dentry->d_name.name,symname);
lock_kernel();
maxlen = AFFS_SB->s_hashsize * sizeof(u32) - 1;
error = -ENOSPC;
inode = affs_new_inode(dir);
if (!inode)
if (!inode) {
unlock_kernel();
return -ENOSPC;
}
inode->i_op = &affs_symlink_inode_operations;
inode->i_data.a_ops = &affs_symlink_aops;
......@@ -416,6 +419,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK);
if (error)
goto err;
unlock_kernel();
return 0;
......@@ -423,6 +427,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
inode->i_nlink = 0;
mark_inode_dirty(inode);
iput(inode);
unlock_kernel();
return error;
}
......
......@@ -265,15 +265,22 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
DPRINTK(("autofs_root_symlink: %s <- ", symname));
autofs_say(dentry->d_name.name,dentry->d_name.len);
if ( !autofs_oz_mode(sbi) )
lock_kernel();
if ( !autofs_oz_mode(sbi) ) {
unlock_kernel();
return -EACCES;
}
if ( autofs_hash_lookup(dh, &dentry->d_name) )
if ( autofs_hash_lookup(dh, &dentry->d_name) ) {
unlock_kernel();
return -EEXIST;
}
n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
if ( n >= AUTOFS_MAX_SYMLINKS )
if ( n >= AUTOFS_MAX_SYMLINKS ) {
unlock_kernel();
return -ENOSPC;
}
set_bit(n,sbi->symlink_bitmap);
sl = &sbi->symlink[n];
......@@ -281,6 +288,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
if ( !sl->data ) {
clear_bit(n,sbi->symlink_bitmap);
unlock_kernel();
return -ENOSPC;
}
......@@ -288,6 +296,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
if ( !ent ) {
kfree(sl->data);
clear_bit(n,sbi->symlink_bitmap);
unlock_kernel();
return -ENOSPC;
}
......@@ -296,6 +305,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
kfree(sl->data);
kfree(ent);
clear_bit(n,sbi->symlink_bitmap);
unlock_kernel();
return -ENOSPC;
}
......@@ -309,7 +319,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
autofs_hash_insert(dh,ent);
d_instantiate(dentry, iget(dir->i_sb,ent->ino));
unlock_kernel();
return 0;
}
......
......@@ -321,18 +321,24 @@ static int autofs4_dir_symlink(struct inode *dir,
DPRINTK(("autofs_dir_symlink: %s <- %.*s\n", symname,
dentry->d_name.len, dentry->d_name.name));
if (!autofs4_oz_mode(sbi))
lock_kernel();
if (!autofs4_oz_mode(sbi)) {
unlock_kernel();
return -EACCES;
}
ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
if (ino == NULL)
if (ino == NULL) {
unlock_kernel();
return -ENOSPC;
}
ino->size = strlen(symname);
ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);
if (cp == NULL) {
kfree(ino);
unlock_kernel();
return -ENOSPC;
}
......@@ -352,6 +358,7 @@ static int autofs4_dir_symlink(struct inode *dir,
dir->i_mtime = CURRENT_TIME;
unlock_kernel();
return 0;
}
......
......@@ -401,14 +401,19 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
int symlen;
int error=0;
lock_kernel();
coda_vfs_stat.symlink++;
if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
unlock_kernel();
return -EPERM;
}
symlen = strlen(symname);
if ( symlen > CODA_MAXPATHLEN )
return -ENAMETOOLONG;
if ( symlen > CODA_MAXPATHLEN ) {
unlock_kernel();
return -ENAMETOOLONG;
}
CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
......@@ -425,6 +430,7 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
coda_dir_changed(dir_inode, 0);
CDEBUG(D_INODE, "in symlink result %d\n",error);
unlock_kernel();
return error;
}
......
......@@ -3066,27 +3066,37 @@ static int devfs_symlink (struct inode *dir, struct dentry *dentry,
struct inode *inode;
/* First try to get the devfs entry for this directory */
lock_kernel();
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) return -ENOENT;
if (parent == NULL) {
unlock_kernel();
return -ENOENT;
}
err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
symname, &de, NULL);
DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
dentry->d_name.name, err);
if (err < 0) return err;
if (err < 0) {
unlock_kernel();
return err;
}
de->vfs_deletable = TRUE;
de->inode.uid = current->euid;
de->inode.gid = current->egid;
de->inode.atime = CURRENT_TIME;
de->inode.mtime = CURRENT_TIME;
de->inode.ctime = CURRENT_TIME;
if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) {
unlock_kernel();
return -ENOMEM;
}
DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n",
dentry->d_name.name, de->inode.ino, inode, dentry);
d_instantiate (dentry, inode);
if ( !is_devfsd_or_child (fs_info) )
devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
inode->i_uid, inode->i_gid, fs_info, 0);
unlock_kernel();
return 0;
} /* End Function devfs_symlink */
......
......@@ -929,9 +929,12 @@ static int ext3_symlink (struct inode * dir,
if (l > dir->i_sb->s_blocksize)
return -ENAMETOOLONG;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
if (IS_ERR(handle))
if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle);
}
if (IS_SYNC(dir))
handle->h_sync = 1;
......@@ -962,6 +965,7 @@ static int ext3_symlink (struct inode * dir,
err = ext3_add_nondir(handle, dentry, inode);
out_stop:
ext3_journal_stop(handle, dir);
unlock_kernel();
return err;
out_no_entry:
......@@ -1143,11 +1147,11 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
struct inode_operations ext3_dir_inode_operations = {
create: ext3_create,
lookup: ext3_lookup,
link: ext3_link, /* BKL held */
link: ext3_link,
unlink: ext3_unlink,
symlink: ext3_symlink, /* BKL held */
mkdir: ext3_mkdir, /* BKL held */
rmdir: ext3_rmdir, /* BKL held */
symlink: ext3_symlink,
mkdir: ext3_mkdir,
rmdir: ext3_rmdir,
mknod: ext3_mknod,
rename: ext3_rename, /* BKL held */
};
......@@ -252,7 +252,11 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
struct inode *result;
int err;
if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
if (dir->i_sb->s_hpfs_eas < 2) return -EPERM;
lock_kernel();
if (dir->i_sb->s_hpfs_eas < 2) {
unlock_kernel();
return -EPERM;
}
if (!(fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh))) goto bail;
memset(&dee, 0, sizeof dee);
dee.archive = 1;
......@@ -266,6 +270,7 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
brelse(bh);
hpfs_free_sectors(dir->i_sb, fno, 1);
hpfs_unlock_inode(dir);
unlock_kernel();
return -EEXIST;
}
fnode->len = len;
......@@ -297,12 +302,14 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
}
hpfs_unlock_iget(dir->i_sb);
hpfs_unlock_inode(dir);
unlock_kernel();
return 0;
bail1:
bail1:
brelse(bh);
hpfs_free_sectors(dir->i_sb, fno, 1);
hpfs_unlock_inode(dir);
bail:
bail:
unlock_kernel();
return -ENOSPC;
}
......
......@@ -1148,6 +1148,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
int symname_len = strlen(symname);
int err;
lock_kernel();
D1({
int len = dentry->d_name.len;
char *_name = (char *)kmalloc(len + 1, GFP_KERNEL);
......@@ -1167,6 +1168,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
ASSERT(if (!dir_f) {
printk(KERN_ERR "jffs_symlink(): No reference to a "
"jffs_file struct in inode.\n");
unlock_kernel();
return -EIO;
});
......@@ -1175,6 +1177,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
/* Create a node and initialize it as much as needed. */
if (!(node = jffs_alloc_node())) {
D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
unlock_kernel();
return -ENOMEM;
}
D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
......@@ -1229,6 +1232,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
jffs_symlink_end:
D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
up(&c->fmc->biglock);
unlock_kernel();
return err;
} /* jffs_symlink() */
......
......@@ -534,6 +534,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
if (strlen(target) > 254)
return -EINVAL;
lock_kernel();
ri = jffs2_alloc_raw_inode();
if (!ri)
......@@ -549,6 +550,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
if (ret) {
jffs2_free_raw_inode(ri);
unlock_kernel();
return ret;
}
......@@ -557,6 +559,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
if (IS_ERR(inode)) {
jffs2_free_raw_inode(ri);
jffs2_complete_reservation(c);
unlock_kernel();
return PTR_ERR(inode);
}
......@@ -581,6 +584,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
up(&f->sem);
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
unlock_kernel();
return PTR_ERR(fn);
}
/* No data here. Only a metadata node, which will be
......@@ -601,6 +605,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
if (ret) {
/* Eep. */
jffs2_clear_inode(inode);
unlock_kernel();
return ret;
}
}
......@@ -610,6 +615,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
unlock_kernel();
return -ENOMEM;
}
......@@ -640,6 +646,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
as if it were the final unlink() */
up(&dir_f->sem);
jffs2_clear_inode(inode);
unlock_kernel();
return PTR_ERR(fd);
}
......@@ -649,6 +656,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
up(&dir_f->sem);
d_instantiate(dentry, inode);
unlock_kernel();
return 0;
}
......
......@@ -1549,9 +1549,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
return -EPERM;
DQUOT_INIT(dir);
lock_kernel();
error = dir->i_op->symlink(dir, dentry, oldname);
unlock_kernel();
if (!error)
inode_dir_notify(dir, DN_CREATE);
return error;
......
......@@ -28,6 +28,7 @@
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/smp_lock.h>
#include "ncplib_kernel.h"
......@@ -121,6 +122,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
return -ENOMEM;
err = -EIO;
lock_kernel();
if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN))
goto failfree;
......@@ -147,6 +149,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
ncp_inode_close(inode);
ncp_make_closed(inode);
unlock_kernel();
kfree(link);
return 0;
......@@ -154,6 +157,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
ncp_inode_close(inode);
ncp_make_closed(inode);
failfree:
unlock_kernel();
kfree(link);
return err;
}
......
......@@ -920,6 +920,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
qsymname.name = symname;
qsymname.len = strlen(symname);
lock_kernel();
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
&attr, &sym_fh, &sym_attr);
......@@ -931,6 +932,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
dentry->d_parent->d_name.name, dentry->d_name.name);
d_drop(dentry);
}
unlock_kernel();
out:
return error;
......
......@@ -253,13 +253,18 @@ static int ramfs_rename(struct inode * old_dir, struct dentry *old_dentry, struc
static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
int error;
struct inode *inode;
int error = -ENOSPC;
error = ramfs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
if (!error) {
inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
struct inode *inode = dentry->d_inode;
error = block_symlink(inode, symname, l);
if (!error) {
d_instantiate(dentry, inode);
dget(dentry);
} else
iput(inode);
}
return error;
}
......
......@@ -915,9 +915,11 @@ static int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const c
return -ENAMETOOLONG;
}
lock_kernel();
name = reiserfs_kmalloc (item_len, GFP_NOFS, dir->i_sb);
if (!name) {
iput(inode) ;
unlock_kernel();
return -ENOMEM;
}
memcpy (name, symname, strlen (symname));
......@@ -932,6 +934,7 @@ static int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const c
if (inode == 0) { /* reiserfs_new_inode iputs for us */
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
unlock_kernel();
return retval;
}
......@@ -953,12 +956,14 @@ static int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const c
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
iput (inode);
unlock_kernel();
return retval;
}
d_instantiate(dentry, inode);
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
unlock_kernel();
return 0;
}
......
......@@ -949,6 +949,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
int err;
int block;
lock_kernel();
if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
goto out;
......@@ -1092,6 +1093,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
err = 0;
out:
unlock_kernel();
return err;
out_no_entry:
......
......@@ -132,6 +132,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
if (l > sb->s_blocksize)
goto out;
lock_kernel();
inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
err = PTR_ERR(inode);
if (IS_ERR(inode))
......@@ -154,6 +155,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
err = ufs_add_nondir(dentry, inode);
out:
unlock_kernel();
return err;
out_fail:
......
......@@ -1109,22 +1109,22 @@ static int shmem_rename(struct inode * old_dir, struct dentry *old_dentry, struc
static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
int error;
int len;
struct inode *inode;
struct page *page;
char *kaddr;
struct shmem_inode_info * info;
error = shmem_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
if (error)
return error;
inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
if (!inode)
return -ENOSPC;
len = strlen(symname) + 1;
if (len > PAGE_CACHE_SIZE)
if (len > PAGE_CACHE_SIZE) {
iput(inode);
return -ENAMETOOLONG;
}
inode = dentry->d_inode;
info = SHMEM_I(inode);
inode->i_size = len-1;
if (len <= sizeof(struct shmem_inode_info)) {
......@@ -1139,6 +1139,7 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
page = shmem_getpage_locked(info, inode, 0);
if (IS_ERR(page)) {
up(&info->sem);
iput(inode);
return PTR_ERR(page);
}
kaddr = kmap(page);
......@@ -1151,6 +1152,8 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
inode->i_op = &shmem_symlink_inode_operations;
}
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
d_instantiate(dentry, inode);
dget(dentry);
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