diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 471a75f11ea..5b3207f557d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -104,6 +104,8 @@ static int nfs4_map_errors(int err) | |||
104 | return -EACCES; | 104 | return -EACCES; |
105 | case -NFS4ERR_MINOR_VERS_MISMATCH: | 105 | case -NFS4ERR_MINOR_VERS_MISMATCH: |
106 | return -EPROTONOSUPPORT; | 106 | return -EPROTONOSUPPORT; |
107 | case -NFS4ERR_ACCESS: | ||
108 | return -EACCES; | ||
107 | default: | 109 | default: |
108 | dprintk("%s could not handle NFSv4 error %d\n", | 110 | dprintk("%s could not handle NFSv4 error %d\n", |
109 | __func__, -err); | 111 | __func__, -err); |
@@ -860,6 +862,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
860 | p->o_arg.fh = NFS_FH(dir); | 862 | p->o_arg.fh = NFS_FH(dir); |
861 | p->o_arg.open_flags = flags; | 863 | p->o_arg.open_flags = flags; |
862 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); | 864 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); |
865 | /* ask server to check for all possible rights as results are cached */ | ||
866 | p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY | | ||
867 | NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE; | ||
863 | p->o_arg.clientid = server->nfs_client->cl_clientid; | 868 | p->o_arg.clientid = server->nfs_client->cl_clientid; |
864 | p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); | 869 | p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); |
865 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | 870 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; |
@@ -1643,6 +1648,39 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data) | |||
1643 | return status; | 1648 | return status; |
1644 | } | 1649 | } |
1645 | 1650 | ||
1651 | static int nfs4_opendata_access(struct rpc_cred *cred, | ||
1652 | struct nfs4_opendata *opendata, | ||
1653 | struct nfs4_state *state, fmode_t fmode) | ||
1654 | { | ||
1655 | struct nfs_access_entry cache; | ||
1656 | u32 mask; | ||
1657 | |||
1658 | /* access call failed or for some reason the server doesn't | ||
1659 | * support any access modes -- defer access call until later */ | ||
1660 | if (opendata->o_res.access_supported == 0) | ||
1661 | return 0; | ||
1662 | |||
1663 | mask = 0; | ||
1664 | if (fmode & FMODE_READ) | ||
1665 | mask |= MAY_READ; | ||
1666 | if (fmode & FMODE_WRITE) | ||
1667 | mask |= MAY_WRITE; | ||
1668 | if (fmode & FMODE_EXEC) | ||
1669 | mask |= MAY_EXEC; | ||
1670 | |||
1671 | cache.cred = cred; | ||
1672 | cache.jiffies = jiffies; | ||
1673 | nfs_access_set_mask(&cache, opendata->o_res.access_result); | ||
1674 | nfs_access_add_cache(state->inode, &cache); | ||
1675 | |||
1676 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | ||
1677 | return 0; | ||
1678 | |||
1679 | /* even though OPEN succeeded, access is denied. Close the file */ | ||
1680 | nfs4_close_state(state, fmode); | ||
1681 | return -NFS4ERR_ACCESS; | ||
1682 | } | ||
1683 | |||
1646 | /* | 1684 | /* |
1647 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata | 1685 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata |
1648 | */ | 1686 | */ |
@@ -1900,6 +1938,10 @@ static int _nfs4_do_open(struct inode *dir, | |||
1900 | if (server->caps & NFS_CAP_POSIX_LOCK) | 1938 | if (server->caps & NFS_CAP_POSIX_LOCK) |
1901 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 1939 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
1902 | 1940 | ||
1941 | status = nfs4_opendata_access(cred, opendata, state, fmode); | ||
1942 | if (status != 0) | ||
1943 | goto err_opendata_put; | ||
1944 | |||
1903 | if (opendata->o_arg.open_flags & O_EXCL) { | 1945 | if (opendata->o_arg.open_flags & O_EXCL) { |
1904 | nfs4_exclusive_attrset(opendata, sattr); | 1946 | nfs4_exclusive_attrset(opendata, sattr); |
1905 | 1947 | ||
@@ -1945,7 +1987,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
1945 | struct nfs4_state *res; | 1987 | struct nfs4_state *res; |
1946 | int status; | 1988 | int status; |
1947 | 1989 | ||
1948 | fmode &= FMODE_READ|FMODE_WRITE; | 1990 | fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC; |
1949 | do { | 1991 | do { |
1950 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, | 1992 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, |
1951 | &res, ctx_th); | 1993 | &res, ctx_th); |
@@ -2771,13 +2813,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2771 | 2813 | ||
2772 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2814 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2773 | if (!status) { | 2815 | if (!status) { |
2774 | entry->mask = 0; | 2816 | nfs_access_set_mask(entry, res.access); |
2775 | if (res.access & NFS4_ACCESS_READ) | ||
2776 | entry->mask |= MAY_READ; | ||
2777 | if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE)) | ||
2778 | entry->mask |= MAY_WRITE; | ||
2779 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) | ||
2780 | entry->mask |= MAY_EXEC; | ||
2781 | nfs_refresh_inode(inode, res.fattr); | 2817 | nfs_refresh_inode(inode, res.fattr); |
2782 | } | 2818 | } |
2783 | nfs_free_fattr(res.fattr); | 2819 | nfs_free_fattr(res.fattr); |