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: ...@@ -55,7 +55,7 @@ locking rules:
BKL i_sem(inode) BKL i_sem(inode)
lookup: no yes lookup: no yes
create: no yes create: no yes
link: yes yes link: no yes
mknod: no yes mknod: no yes
mkdir: no yes mkdir: no yes
unlink: no yes (both) unlink: no yes (both)
......
...@@ -80,9 +80,15 @@ can relax your locking. ...@@ -80,9 +80,15 @@ can relax your locking.
--- ---
[mandatory] [mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir() and ->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
->rmdir() are called without BKL now. Grab it on the entry, drop upon ->rmdir() and ->link() are called without BKL now. Grab it on the entry,
return - that will guarantee the same locking you used to have. If your drop upon return - that will guarantee the same locking you used to have.
method or its parts do not need BKL - better yet, now you can shift 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 lock_kernel() / unlock_kernel() so that they would protect exactly what
needs to be protected. 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, ...@@ -159,10 +159,9 @@ static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if(S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM;
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
dget(dentry); dget(dentry);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
...@@ -216,10 +216,9 @@ static int usbfs_link (struct dentry *old_dentry, struct inode *dir, ...@@ -216,10 +216,9 @@ static int usbfs_link (struct dentry *old_dentry, struct inode *dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if(S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM;
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
dget(dentry); dget(dentry);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
...@@ -435,16 +435,17 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) ...@@ -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, 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); (int)dentry->d_name.len,dentry->d_name.name);
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; error = affs_add_entry(dir, inode, dentry, ST_LINKFILE);
error = affs_add_entry(dir, inode, dentry, S_ISDIR(inode->i_mode) ? ST_LINKDIR : ST_LINKFILE);
if (error) { if (error) {
/* WTF??? */
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;
} }
unlock_kernel();
return 0; return 0;
} }
......
...@@ -151,17 +151,18 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new ...@@ -151,17 +151,18 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
struct inode * inode = old->d_inode; struct inode * inode = old->d_inode;
int err; int err;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM;
err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino); err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
if (err) if (err) {
unlock_kernel();
return err; return err;
}
inode->i_nlink++; inode->i_nlink++;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode); mark_inode_dirty(inode);
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
d_instantiate(new, inode); d_instantiate(new, inode);
unlock_kernel();
return 0; return 0;
} }
......
...@@ -362,10 +362,13 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, ...@@ -362,10 +362,13 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
int len = de->d_name.len; int len = de->d_name.len;
int error; int error;
lock_kernel();
coda_vfs_stat.link++; 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; return -EPERM;
}
CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode)); CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_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, ...@@ -385,6 +388,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
out: out:
CDEBUG(D_INODE, "link result %d\n",error); CDEBUG(D_INODE, "link result %d\n",error);
unlock_kernel();
return(error); return(error);
} }
......
...@@ -168,14 +168,15 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, ...@@ -168,14 +168,15 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= EXT2_LINK_MAX) {
unlock_kernel();
if (inode->i_nlink >= EXT2_LINK_MAX)
return -EMLINK; return -EMLINK;
}
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
ext2_inc_count(inode); ext2_inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
return ext2_add_nondir(dentry, inode); return ext2_add_nondir(dentry, inode);
......
...@@ -978,15 +978,17 @@ static int ext3_link (struct dentry * old_dentry, ...@@ -978,15 +978,17 @@ static int ext3_link (struct dentry * old_dentry,
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
int err; int err;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= EXT3_LINK_MAX) {
unlock_kernel();
if (inode->i_nlink >= EXT3_LINK_MAX)
return -EMLINK; return -EMLINK;
}
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); handle = ext3_journal_start(dir, EXT3_DATA_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;
...@@ -998,6 +1000,7 @@ static int ext3_link (struct dentry * old_dentry, ...@@ -998,6 +1000,7 @@ static int ext3_link (struct dentry * old_dentry,
ext3_mark_inode_dirty(handle, inode); ext3_mark_inode_dirty(handle, inode);
err = ext3_add_nondir(handle, dentry, inode); err = ext3_add_nondir(handle, dentry, inode);
ext3_journal_stop(handle, dir); ext3_journal_stop(handle, dir);
unlock_kernel();
return err; return err;
} }
......
...@@ -501,11 +501,15 @@ static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct ...@@ -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) 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) { if (!ret) {
d_instantiate(dentry, old_dentry->d_inode); d_instantiate(dentry, old_dentry->d_inode);
atomic_inc(&old_dentry->d_inode->i_count); atomic_inc(&old_dentry->d_inode->i_count);
} }
unlock_kernel();
return ret; return ret;
} }
......
...@@ -136,14 +136,15 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, ...@@ -136,14 +136,15 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max) {
unlock_kernel();
if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
return -EMLINK; return -EMLINK;
}
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inc_count(inode); inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
return add_nondir(dentry, inode); return add_nondir(dentry, inode);
} }
......
...@@ -1613,11 +1613,11 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de ...@@ -1613,11 +1613,11 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
return -EPERM; return -EPERM;
if (!dir->i_op || !dir->i_op->link) if (!dir->i_op || !dir->i_op->link)
return -EPERM; return -EPERM;
if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM;
DQUOT_INIT(dir); DQUOT_INIT(dir);
lock_kernel();
error = dir->i_op->link(old_dentry, dir, new_dentry); error = dir->i_op->link(old_dentry, dir, new_dentry);
unlock_kernel();
if (!error) if (!error)
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
return error; return error;
......
...@@ -951,10 +951,12 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) ...@@ -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, * Since nfs_proc_link doesn't return a file handle,
* we can't use the existing dentry. * we can't use the existing dentry.
*/ */
lock_kernel();
d_drop(dentry); d_drop(dentry);
nfs_zap_caches(dir); nfs_zap_caches(dir);
NFS_CACHEINV(inode); NFS_CACHEINV(inode);
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
unlock_kernel();
return error; return error;
} }
......
...@@ -166,10 +166,9 @@ static int ramfs_link(struct dentry *old_dentry, struct inode * dir, struct dent ...@@ -166,10 +166,9 @@ static int ramfs_link(struct dentry *old_dentry, struct inode * dir, struct dent
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM;
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); /* New dentry reference */ atomic_inc(&inode->i_count); /* New dentry reference */
dget(dentry); /* Extra pinning count for the created dentry */ dget(dentry); /* Extra pinning count for the created dentry */
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
...@@ -978,12 +978,10 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct ...@@ -978,12 +978,10 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3;
lock_kernel();
if (S_ISDIR(inode->i_mode))
return -EPERM;
if (inode->i_nlink >= REISERFS_LINK_MAX) { if (inode->i_nlink >= REISERFS_LINK_MAX) {
//FIXME: sd_nlink is 32 bit for new files //FIXME: sd_nlink is 32 bit for new files
unlock_kernel();
return -EMLINK; return -EMLINK;
} }
...@@ -1000,6 +998,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct ...@@ -1000,6 +998,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
if (retval) { if (retval) {
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;
} }
...@@ -1011,6 +1010,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct ...@@ -1011,6 +1010,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
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;
} }
......
...@@ -142,14 +142,15 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, ...@@ -142,14 +142,15 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= inode->i_sb->sv_link_max) {
unlock_kernel();
if (inode->i_nlink >= inode->i_sb->sv_link_max)
return -EMLINK; return -EMLINK;
}
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inc_count(inode); inc_count(inode);
unlock_kernel();
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
return add_nondir(dentry, inode); return add_nondir(dentry, inode);
......
...@@ -1109,14 +1109,16 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, ...@@ -1109,14 +1109,16 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
int err; int err;
struct FileIdentDesc cfi, *fi; struct FileIdentDesc cfi, *fi;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
unlock_kernel();
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
return -EMLINK; 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; return err;
}
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
if (UDF_SB_LVIDBH(inode->i_sb)) if (UDF_SB_LVIDBH(inode->i_sb))
...@@ -1146,6 +1148,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, ...@@ -1146,6 +1148,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
mark_inode_dirty(inode); mark_inode_dirty(inode);
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
unlock_kernel();
return 0; return 0;
} }
......
...@@ -166,18 +166,21 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir, ...@@ -166,18 +166,21 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
struct dentry *dentry) struct dentry *dentry)
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
int error;
if (S_ISDIR(inode->i_mode)) lock_kernel();
return -EPERM; if (inode->i_nlink >= UFS_LINK_MAX) {
unlock_kernel();
if (inode->i_nlink >= UFS_LINK_MAX)
return -EMLINK; return -EMLINK;
}
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
ufs_inc_count(inode); ufs_inc_count(inode);
atomic_inc(&inode->i_count); 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) 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 ...@@ -1021,11 +1021,10 @@ static int shmem_link(struct dentry *old_dentry, struct inode * dir, struct dent
{ {
struct inode *inode = old_dentry->d_inode; 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; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
lock_kernel();
inode->i_nlink++; inode->i_nlink++;
unlock_kernel();
atomic_inc(&inode->i_count); /* New dentry reference */ atomic_inc(&inode->i_count); /* New dentry reference */
dget(dentry); /* Extra pinning count for the created dentry */ dget(dentry); /* Extra pinning count for the created dentry */
d_instantiate(dentry, inode); 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