aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8a0530921685..c82a21228a34 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2431,6 +2431,20 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
2431} 2431}
2432EXPORT_SYMBOL_GPL(nfs_may_open); 2432EXPORT_SYMBOL_GPL(nfs_may_open);
2433 2433
2434static int nfs_execute_ok(struct inode *inode, int mask)
2435{
2436 struct nfs_server *server = NFS_SERVER(inode);
2437 int ret;
2438
2439 if (mask & MAY_NOT_BLOCK)
2440 ret = nfs_revalidate_inode_rcu(server, inode);
2441 else
2442 ret = nfs_revalidate_inode(server, inode);
2443 if (ret == 0 && !execute_ok(inode))
2444 ret = -EACCES;
2445 return ret;
2446}
2447
2434int nfs_permission(struct inode *inode, int mask) 2448int nfs_permission(struct inode *inode, int mask)
2435{ 2449{
2436 struct rpc_cred *cred; 2450 struct rpc_cred *cred;
@@ -2448,6 +2462,9 @@ int nfs_permission(struct inode *inode, int mask)
2448 case S_IFLNK: 2462 case S_IFLNK:
2449 goto out; 2463 goto out;
2450 case S_IFREG: 2464 case S_IFREG:
2465 if ((mask & MAY_OPEN) &&
2466 nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN))
2467 return 0;
2451 break; 2468 break;
2452 case S_IFDIR: 2469 case S_IFDIR:
2453 /* 2470 /*
@@ -2480,8 +2497,8 @@ force_lookup:
2480 res = PTR_ERR(cred); 2497 res = PTR_ERR(cred);
2481 } 2498 }
2482out: 2499out:
2483 if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) 2500 if (!res && (mask & MAY_EXEC))
2484 res = -EACCES; 2501 res = nfs_execute_ok(inode, mask);
2485 2502
2486 dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n", 2503 dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n",
2487 inode->i_sb->s_id, inode->i_ino, mask, res); 2504 inode->i_sb->s_id, inode->i_ino, mask, res);