Commit 73769d9b authored by Paul Menage's avatar Paul Menage Committed by Linus Torvalds

[PATCH] Push BKL into ->permission() calls

This patch (against 2.5.22) removes the BKL from around the call
to i_op->permission() in fs/namei.c, and pushes the BKL into those
filesystems that have permission() methods that require it.
parent 67aa3988
...@@ -50,27 +50,27 @@ prototypes: ...@@ -50,27 +50,27 @@ prototypes:
int (*removexattr) (struct dentry *, const char *); int (*removexattr) (struct dentry *, const char *);
locking rules: locking rules:
all may block all may block, none have BKL
BKL i_sem(inode) i_sem(inode)
lookup: no yes lookup: yes
create: no yes create: yes
link: no yes (both) link: yes (both)
mknod: no yes mknod: yes
symlink: no yes symlink: yes
mkdir: no yes mkdir: yes
unlink: no yes (both) unlink: yes (both)
rmdir: no yes (both) (see below) rmdir: yes (both) (see below)
rename: no yes (all) (see below) rename: yes (all) (see below)
readlink: no no readlink: no
follow_link: no no follow_link: no
truncate: no yes (see below) truncate: yes (see below)
setattr: no yes setattr: yes
permission: yes no permission: no
getattr: no no getattr: no
setxattr: no yes setxattr: yes
getxattr: no yes getxattr: yes
listxattr: no yes listxattr: yes
removexattr: no yes removexattr: yes
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on
victim. victim.
cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
......
...@@ -81,9 +81,9 @@ can relax your locking. ...@@ -81,9 +81,9 @@ can relax your locking.
[mandatory] [mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(), ->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename() and ->readdir() ->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename(), ->permission()
are called without BKL now. Grab it on the entry, drop upon return - that and ->readdir() are called without BKL now. Grab it on entry, drop upon return
will guarantee the same locking you used to have. If your method or its - 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() and parts do not need BKL - better yet, now you can shift lock_kernel() and
unlock_kernel() so that they would protect exactly what needs to be unlock_kernel() so that they would protect exactly what needs to be
protected. protected.
......
...@@ -147,21 +147,26 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) ...@@ -147,21 +147,26 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry)
int coda_permission(struct inode *inode, int mask) int coda_permission(struct inode *inode, int mask)
{ {
int error; int error = 0;
if (!mask) if (!mask)
return 0; return 0;
lock_kernel();
coda_vfs_stat.permission++; coda_vfs_stat.permission++;
if (coda_cache_check(inode, mask)) if (coda_cache_check(inode, mask))
return 0; goto out;
error = venus_access(inode->i_sb, coda_i2f(inode), mask); error = venus_access(inode->i_sb, coda_i2f(inode), mask);
if (!error) if (!error)
coda_cache_enter(inode, mask); coda_cache_enter(inode, mask);
out:
unlock_kernel();
return error; return error;
} }
......
...@@ -785,13 +785,15 @@ int presto_permission(struct inode *inode, int mask) ...@@ -785,13 +785,15 @@ int presto_permission(struct inode *inode, int mask)
{ {
unsigned short mode = inode->i_mode; unsigned short mode = inode->i_mode;
struct presto_cache *cache; struct presto_cache *cache;
int rc; int rc = 0;
lock_kernel();
ENTRY; ENTRY;
if ( presto_can_ilookup() && !(mask & S_IWOTH)) { if ( presto_can_ilookup() && !(mask & S_IWOTH)) {
CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino); CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino);
EXIT; EXIT;
return 0; goto out;
} }
cache = presto_get_cache(inode); cache = presto_get_cache(inode);
...@@ -803,25 +805,22 @@ int presto_permission(struct inode *inode, int mask) ...@@ -803,25 +805,22 @@ int presto_permission(struct inode *inode, int mask)
if ( S_ISREG(mode) && fiops && fiops->permission ) { if ( S_ISREG(mode) && fiops && fiops->permission ) {
EXIT; EXIT;
return fiops->permission(inode, mask); rc = fiops->permission(inode, mask);
goto out;
} }
if ( S_ISDIR(mode) && diops && diops->permission ) { if ( S_ISDIR(mode) && diops && diops->permission ) {
EXIT; EXIT;
return diops->permission(inode, mask); rc = diops->permission(inode, mask);
goto out;
} }
} }
/* The cache filesystem doesn't have its own permission function, rc = vfs_permission(inode, mask);
* but we don't want to duplicate the VFS code here. In order
* to avoid looping from permission calling this function again,
* we temporarily override the permission operation while we call
* the VFS permission function.
*/
inode->i_op->permission = NULL;
rc = permission(inode, mask);
inode->i_op->permission = &presto_permission;
EXIT; EXIT;
out:
unlock_kernel();
return rc; return rc;
} }
......
...@@ -204,13 +204,8 @@ int vfs_permission(struct inode * inode, int mask) ...@@ -204,13 +204,8 @@ int vfs_permission(struct inode * inode, int mask)
int permission(struct inode * inode,int mask) int permission(struct inode * inode,int mask)
{ {
if (inode->i_op && inode->i_op->permission) { if (inode->i_op && inode->i_op->permission)
int retval; return inode->i_op->permission(inode, mask);
lock_kernel();
retval = inode->i_op->permission(inode, mask);
unlock_kernel();
return retval;
}
return vfs_permission(inode, mask); return vfs_permission(inode, mask);
} }
......
...@@ -1123,6 +1123,8 @@ nfs_permission(struct inode *inode, int mask) ...@@ -1123,6 +1123,8 @@ nfs_permission(struct inode *inode, int mask)
&& error != -EACCES) && error != -EACCES)
goto out; goto out;
lock_kernel();
error = NFS_PROTO(inode)->access(inode, mask, 0); error = NFS_PROTO(inode)->access(inode, mask, 0);
if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv && if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
...@@ -1130,6 +1132,8 @@ nfs_permission(struct inode *inode, int mask) ...@@ -1130,6 +1132,8 @@ nfs_permission(struct inode *inode, int mask)
(current->fsuid != current->uid || current->fsgid != current->gid)) (current->fsuid != current->uid || current->fsgid != current->gid))
error = NFS_PROTO(inode)->access(inode, mask, 1); error = NFS_PROTO(inode)->access(inode, mask, 1);
unlock_kernel();
out: out:
return error; return error;
} }
......
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