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

[PATCH] (3/5) more BKL shifting

BKL shifted into ->link(), check for S_ISDIR moved into vfs_link().
parent 90ed880a
......@@ -55,7 +55,7 @@ locking rules:
BKL i_sem(inode)
lookup: no yes
create: no yes
link: yes yes
link: no yes
mknod: no yes
mkdir: no yes
unlink: no yes (both)
......
......@@ -80,9 +80,15 @@ can relax your locking.
---
[mandatory]
->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
->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.
---
[informational]
check for ->link() target not being a directory is done by callers. Feel
free to drop it...
......@@ -159,10 +159,9 @@ static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,
{
struct inode *inode = old_dentry->d_inode;
if(S_ISDIR(inode->i_mode))
return -EPERM;
lock_kernel();
inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count);
dget(dentry);
d_instantiate(dentry, inode);
......
......@@ -216,10 +216,9 @@ static int usbfs_link (struct dentry *old_dentry, struct inode *dir,
{
struct inode *inode = old_dentry->d_inode;
if(S_ISDIR(inode->i_mode))
return -EPERM;
lock_kernel();
inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count);
dget(dentry);
d_instantiate(dentry, inode);
......
......@@ -435,16 +435,17 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino,
(int)dentry->d_name.len,dentry->d_name.name);
if (S_ISDIR(inode->i_mode))
return -EPERM;
error = affs_add_entry(dir, inode, dentry, S_ISDIR(inode->i_mode) ? ST_LINKDIR : ST_LINKFILE);
lock_kernel();
error = affs_add_entry(dir, inode, dentry, ST_LINKFILE);
if (error) {
/* WTF??? */
inode->i_nlink = 0;
mark_inode_dirty(inode);
iput(inode);
unlock_kernel();
return error;
}
unlock_kernel();
return 0;
}
......
......@@ -151,17 +151,18 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
struct inode * inode = old->d_inode;
int err;
if (S_ISDIR(inode->i_mode))
return -EPERM;
lock_kernel();
err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
if (err)
if (err) {
unlock_kernel();
return err;
}
inode->i_nlink++;
inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
atomic_inc(&inode->i_count);
d_instantiate(new, inode);
unlock_kernel();
return 0;
}
......
......@@ -362,10 +362,13 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
int len = de->d_name.len;
int error;
lock_kernel();
coda_vfs_stat.link++;
if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
unlock_kernel();
return -EPERM;
}
CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));
......@@ -385,6 +388,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
out:
CDEBUG(D_INODE, "link result %d\n",error);
unlock_kernel();
return(error);
}
......
......@@ -168,14 +168,15 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= EXT2_LINK_MAX)
lock_kernel();
if (inode->i_nlink >= EXT2_LINK_MAX) {
unlock_kernel();
return -EMLINK;
}
inode->i_ctime = CURRENT_TIME;
ext2_inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count);
return ext2_add_nondir(dentry, inode);
......
......@@ -978,15 +978,17 @@ static int ext3_link (struct dentry * old_dentry,
struct inode *inode = old_dentry->d_inode;
int err;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= EXT3_LINK_MAX)
lock_kernel();
if (inode->i_nlink >= EXT3_LINK_MAX) {
unlock_kernel();
return -EMLINK;
}
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
if (IS_ERR(handle))
if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle);
}
if (IS_SYNC(dir))
handle->h_sync = 1;
......@@ -998,6 +1000,7 @@ static int ext3_link (struct dentry * old_dentry,
ext3_mark_inode_dirty(handle, inode);
err = ext3_add_nondir(handle, dentry, inode);
ext3_journal_stop(handle, dir);
unlock_kernel();
return err;
}
......
......@@ -501,11 +501,15 @@ static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct
static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
{
int ret = jffs2_do_link(old_dentry, dir_i, dentry, 0);
int ret;
lock_kernel();
ret = jffs2_do_link(old_dentry, dir_i, dentry, 0);
if (!ret) {
d_instantiate(dentry, old_dentry->d_inode);
atomic_inc(&old_dentry->d_inode->i_count);
}
unlock_kernel();
return ret;
}
......
......@@ -136,14 +136,15 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
lock_kernel();
if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max) {
unlock_kernel();
return -EMLINK;
}
inode->i_ctime = CURRENT_TIME;
inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count);
return add_nondir(dentry, inode);
}
......
......@@ -1613,11 +1613,11 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
return -EPERM;
if (!dir->i_op || !dir->i_op->link)
return -EPERM;
if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM;
DQUOT_INIT(dir);
lock_kernel();
error = dir->i_op->link(old_dentry, dir, new_dentry);
unlock_kernel();
if (!error)
inode_dir_notify(dir, DN_CREATE);
return error;
......
......@@ -951,10 +951,12 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
* Since nfs_proc_link doesn't return a file handle,
* we can't use the existing dentry.
*/
lock_kernel();
d_drop(dentry);
nfs_zap_caches(dir);
NFS_CACHEINV(inode);
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
unlock_kernel();
return error;
}
......
......@@ -166,10 +166,9 @@ static int ramfs_link(struct dentry *old_dentry, struct inode * dir, struct dent
{
struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode))
return -EPERM;
lock_kernel();
inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); /* New dentry reference */
dget(dentry); /* Extra pinning count for the created dentry */
d_instantiate(dentry, inode);
......
......@@ -978,12 +978,10 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
struct reiserfs_transaction_handle th ;
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3;
if (S_ISDIR(inode->i_mode))
return -EPERM;
lock_kernel();
if (inode->i_nlink >= REISERFS_LINK_MAX) {
//FIXME: sd_nlink is 32 bit for new files
unlock_kernel();
return -EMLINK;
}
......@@ -1000,6 +998,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
if (retval) {
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
unlock_kernel();
return retval;
}
......@@ -1011,6 +1010,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
d_instantiate(dentry, inode);
pop_journal_writer(windex) ;
journal_end(&th, dir->i_sb, jbegin_count) ;
unlock_kernel();
return 0;
}
......
......@@ -142,14 +142,15 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= inode->i_sb->sv_link_max)
lock_kernel();
if (inode->i_nlink >= inode->i_sb->sv_link_max) {
unlock_kernel();
return -EMLINK;
}
inode->i_ctime = CURRENT_TIME;
inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count);
return add_nondir(dentry, inode);
......
......@@ -1109,14 +1109,16 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
int err;
struct FileIdentDesc cfi, *fi;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
lock_kernel();
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
unlock_kernel();
return -EMLINK;
}
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
unlock_kernel();
return err;
}
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
if (UDF_SB_LVIDBH(inode->i_sb))
......@@ -1146,6 +1148,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
mark_inode_dirty(inode);
atomic_inc(&inode->i_count);
d_instantiate(dentry, inode);
unlock_kernel();
return 0;
}
......
......@@ -166,18 +166,21 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
int error;
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= UFS_LINK_MAX)
lock_kernel();
if (inode->i_nlink >= UFS_LINK_MAX) {
unlock_kernel();
return -EMLINK;
}
inode->i_ctime = CURRENT_TIME;
ufs_inc_count(inode);
atomic_inc(&inode->i_count);
return ufs_add_nondir(dentry, inode);
error = ufs_add_nondir(dentry, inode);
unlock_kernel();
return error;
}
static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
......
......@@ -1021,11 +1021,10 @@ static int shmem_link(struct dentry *old_dentry, struct inode * dir, struct dent
{
struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode))
return -EPERM;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
lock_kernel();
inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); /* New dentry reference */
dget(dentry); /* Extra pinning count for the created dentry */
d_instantiate(dentry, inode);
......
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