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

[PATCH] BKL shifting - ->rename()

parent a9b979a5
......@@ -61,7 +61,7 @@ symlink: no yes
mkdir: no yes
unlink: no yes (both)
rmdir: no yes (both) (see below)
rename: yes yes (all) (see below)
rename: no yes (all) (see below)
readlink: no no
follow_link: no no
truncate: no yes (see below)
......
......@@ -81,11 +81,11 @@ can relax your locking.
[mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
->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.
->rmdir(), ->link(), ->symlink() and ->rename() 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]
......
......@@ -462,6 +462,7 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct buffer_head *bh = NULL;
int retval;
lock_kernel();
pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
(u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
(u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
......@@ -472,9 +473,11 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* Unlink destination if it already exists */
if (new_dentry->d_inode) {
retval = affs_remove_header(new_dentry);
if (retval)
if (retval) {
unlock_kernel();
return retval;
}
}
retval = -EIO;
bh = affs_bread(sb, old_dentry->d_inode->i_ino);
......@@ -499,5 +502,6 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
done:
mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
affs_brelse(bh);
unlock_kernel();
return retval;
}
......@@ -213,6 +213,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
if (S_ISDIR(old_inode->i_mode))
return -EINVAL;
lock_kernel();
old_bh = bfs_find_entry(old_dir,
old_dentry->d_name.name,
old_dentry->d_name.len, &old_de);
......@@ -249,6 +250,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
error = 0;
end_rename:
unlock_kernel();
brelse(old_bh);
brelse(new_bh);
return error;
......
......@@ -501,6 +501,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
int link_adjust = 0;
int error;
lock_kernel();
coda_vfs_stat.rename++;
CDEBUG(D_INODE, "old: %s, (%d length), new: %s"
......@@ -527,6 +528,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
}
CDEBUG(D_INODE, "result %d\n", error);
unlock_kernel();
return error;
}
......
......@@ -31,7 +31,6 @@
#include "ext2.h"
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
/*
* Couple of helper functions - make the code slightly cleaner.
......
......@@ -1027,9 +1027,12 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
old_bh = new_bh = dir_bh = NULL;
lock_kernel();
handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
if (IS_ERR(handle))
if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle);
}
if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
handle->h_sync = 1;
......@@ -1138,6 +1141,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
brelse (old_bh);
brelse (new_bh);
ext3_journal_stop(handle, old_dir);
unlock_kernel();
return retval;
}
......@@ -1153,5 +1157,5 @@ struct inode_operations ext3_dir_inode_operations = {
mkdir: ext3_mkdir,
rmdir: ext3_rmdir,
mknod: ext3_mknod,
rename: ext3_rename, /* BKL held */
rename: ext3_rename,
};
......@@ -376,20 +376,27 @@ int hfs_rmdir(struct inode * parent, struct dentry *dentry)
int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct hfs_cat_entry *old_parent = HFS_I(old_dir)->entry;
struct hfs_cat_entry *new_parent = HFS_I(new_dir)->entry;
struct hfs_cat_entry *old_parent;
struct hfs_cat_entry *new_parent;
struct hfs_cat_entry *victim = NULL;
struct hfs_cat_entry *deleted;
struct hfs_cat_key key;
int error;
lock_kernel();
old_parent = HFS_I(old_dir)->entry;
new_parent = HFS_I(new_dir)->entry;
if (build_key(&key, old_dir, old_dentry->d_name.name,
old_dentry->d_name.len) ||
(HFS_ITYPE(old_dir->i_ino) != HFS_ITYPE(new_dir->i_ino)))
(HFS_ITYPE(old_dir->i_ino) != HFS_ITYPE(new_dir->i_ino))) {
unlock_kernel();
return -EPERM;
}
if (!(victim = hfs_cat_get(old_parent->mdb, &key)))
if (!(victim = hfs_cat_get(old_parent->mdb, &key))) {
unlock_kernel();
return -ENOENT;
}
error = -EPERM;
if (build_key(&key, new_dir, new_dentry->d_name.name,
......@@ -418,5 +425,6 @@ int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
hfs_rename_put:
hfs_cat_put(victim); /* Note that hfs_cat_put(NULL) is safe. */
unlock_kernel();
return error;
}
......@@ -366,6 +366,7 @@ static int dbl_rename(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
lock_kernel();
if (is_hdr(new_dir, new_dentry->d_name.name,
new_dentry->d_name.len)) {
error = -EPERM;
......@@ -378,6 +379,7 @@ static int dbl_rename(struct inode *old_dir, struct dentry *old_dentry,
error = -EPERM;
}
}
unlock_kernel();
return error;
}
......
......@@ -425,9 +425,11 @@ static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry)
static int nat_hdr_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct hfs_cat_entry *entry = HFS_I(old_dir)->entry;
struct hfs_cat_entry *entry;
int error = 0;
lock_kernel();
entry = HFS_I(old_dir)->entry;
if (!HFS_SB(old_dir->i_sb)->s_afpd) {
/* Not in AFPD compatibility mode */
error = -EPERM;
......@@ -456,5 +458,6 @@ static int nat_hdr_rename(struct inode *old_dir, struct dentry *old_dentry,
error = -EPERM;
}
}
unlock_kernel();
return error;
}
......@@ -482,6 +482,7 @@ int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
err = 0;
hpfs_adjust_length((char *)old_name, &old_len);
lock_kernel();
hpfs_lock_3inodes(old_dir, new_dir, i);
/* Erm? Moving over the empty non-busy directory is perfectly legal */
......@@ -562,5 +563,6 @@ int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
hpfs_decide_conv(i, (char *)new_name, new_len);
end1:
hpfs_unlock_3inodes(old_dir, new_dir, i);
unlock_kernel();
return err;
}
......@@ -422,10 +422,12 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
old_dir, old_dentry->d_name.name,
new_dir, new_dentry->d_name.name));
lock_kernel();
c = (struct jffs_control *)old_dir->i_sb->u.generic_sbp;
ASSERT(if (!c) {
printk(KERN_ERR "jffs_rename(): The old_dir inode "
"didn't have a reference to a jffs_file struct\n");
unlock_kernel();
return -EIO;
});
......@@ -544,6 +546,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
jffs_rename_end:
D3(printk (KERN_NOTICE "rename(): up biglock\n"));
up(&c->fmc->biglock);
unlock_kernel();
return result;
} /* jffs_rename() */
......
......@@ -978,9 +978,12 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
*/
/* Make a hard link */
lock_kernel();
ret = jffs2_do_link(old_dentry, new_dir_i, new_dentry, 1);
if (ret)
if (ret) {
unlock_kernel();
return ret;
}
/* Unlink the original */
ret = jffs2_do_unlink(old_dir_i, old_dentry, 1);
......@@ -1001,6 +1004,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
}
}
unlock_kernel();
return ret;
}
......@@ -6,7 +6,6 @@
#include <linux/fs.h>
#include <linux/minix_fs.h>
#include <linux/smp_lock.h>
#include <linux/pagemap.h>
static inline void inc_count(struct inode *inode)
......
......@@ -561,6 +561,7 @@ int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
int is_hid,old_hid; /* if new file and old file are hidden */
char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
lock_kernel();
error = msdos_format_name(old_dentry->d_name.name,
old_dentry->d_name.len,old_msdos_name,
&MSDOS_SB(old_dir->i_sb)->options);
......@@ -584,6 +585,7 @@ int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
fat_brelse(sb, old_bh);
rename_done:
unlock_kernel();
return error;
}
......
......@@ -1743,8 +1743,11 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
d_rehash(new_dentry);
dput(new_dentry);
}
if (!error)
if (!error) {
lock_kernel();
d_move(old_dentry,new_dentry);
unlock_kernel();
}
return error;
}
......@@ -1765,7 +1768,9 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
/* The following d_move() should become unconditional */
if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
lock_kernel();
d_move(old_dentry, new_dentry);
unlock_kernel();
}
}
if (target)
......@@ -1880,11 +1885,8 @@ static inline int do_rename(const char * oldname, const char * newname)
if (new_dentry == trap)
goto exit5;
lock_kernel();
error = vfs_rename(old_dir->d_inode, old_dentry,
new_dir->d_inode, new_dentry);
unlock_kernel();
exit5:
dput(new_dentry);
exit4:
......
......@@ -1035,6 +1035,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
error = -EIO;
lock_kernel();
if (!ncp_conn_valid(server))
goto out;
......@@ -1078,6 +1079,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
break;
}
out:
unlock_kernel();
return error;
}
......
......@@ -998,6 +998,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* To prevent any new references to the target during the rename,
* we unhash the dentry and free the inode in advance.
*/
lock_kernel();
if (!d_unhashed(new_dentry)) {
d_drop(new_dentry);
rehash = new_dentry;
......@@ -1074,6 +1075,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* new dentry created? */
if (dentry)
dput(dentry);
unlock_kernel();
return error;
}
......
......@@ -1101,13 +1101,17 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
// make sure, that oldname still exists and points to an object we
// are going to rename
old_de.de_gen_number_bit_string = 0;
lock_kernel();
retval = reiserfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len,
&old_entry_path, &old_de);
pathrelse (&old_entry_path);
if (retval == IO_ERROR)
if (retval == IO_ERROR) {
unlock_kernel();
return -EIO;
}
if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {
unlock_kernel();
return -ENOENT;
}
......@@ -1118,6 +1122,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
if (new_inode) {
if (!reiserfs_empty_dir(new_inode)) {
unlock_kernel();
return -ENOTEMPTY;
}
}
......@@ -1128,13 +1133,17 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
dot_dot_de.de_gen_number_bit_string = 0;
retval = reiserfs_find_entry (old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de);
pathrelse (&dot_dot_entry_path);
if (retval != NAME_FOUND)
if (retval != NAME_FOUND) {
unlock_kernel();
return -EIO;
}
/* inode number of .. must equal old_dir->i_ino */
if (dot_dot_de.de_objectid != old_dir->i_ino)
if (dot_dot_de.de_objectid != old_dir->i_ino) {
unlock_kernel();
return -EIO;
}
}
journal_begin(&th, old_dir->i_sb, jbegin_count) ;
windex = push_journal_writer("reiserfs_rename") ;
......@@ -1152,6 +1161,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
} else if (retval) {
pop_journal_writer(windex) ;
journal_end(&th, old_dir->i_sb, jbegin_count) ;
unlock_kernel();
return retval;
}
......@@ -1298,6 +1308,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
pop_journal_writer(windex) ;
journal_end(&th, old_dir->i_sb, jbegin_count) ;
unlock_kernel();
return 0;
}
......
......@@ -570,6 +570,7 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
* Close any open files, and check whether to delete the
* target before attempting the rename.
*/
lock_kernel();
if (old_dentry->d_inode)
smb_close(old_dentry->d_inode);
if (new_dentry->d_inode) {
......@@ -592,5 +593,6 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
smb_renew_times(new_dentry);
}
out:
unlock_kernel();
return error;
}
......@@ -1167,6 +1167,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
struct buffer_head *dir_bh = NULL;
int retval = -ENOENT;
lock_kernel();
if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))
{
if (ofibh.sbh != ofibh.ebh)
......@@ -1296,6 +1297,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
udf_release_data(nfibh.ebh);
udf_release_data(nfibh.sbh);
}
unlock_kernel();
return retval;
}
......
......@@ -282,6 +282,7 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
struct ufs_dir_entry *old_de;
int err = -ENOENT;
lock_kernel();
old_de = ufs_find_entry (old_dentry, &old_bh);
if (!old_de)
goto out;
......@@ -334,6 +335,7 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
ufs_set_link(old_inode, dir_de, dir_bh, new_dir);
ufs_dec_count(old_dir);
}
unlock_kernel();
return 0;
out_dir:
......@@ -342,6 +344,7 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
out_old:
brelse (old_bh);
out:
unlock_kernel();
return err;
}
......
......@@ -1199,6 +1199,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
old_bh = new_bh = dotdot_bh = NULL;
old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode;
lock_kernel();
res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
PRINTK3(("vfat_rename 2\n"));
if (res < 0) goto rename_done;
......@@ -1265,6 +1266,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
fat_brelse(sb, dotdot_bh);
fat_brelse(sb, old_bh);
fat_brelse(sb, new_bh);
unlock_kernel();
return res;
}
......
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