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