Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 333157
b: refs/heads/master
c: 6168f62
h: refs/heads/master
i:
  333155: 7c72c73
v: v3
  • Loading branch information
Weston Andros Adamson authored and Trond Myklebust committed Oct 1, 2012
1 parent b608413 commit 53aa10c
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57a51048da742c764b6ce5d028c7f334ae04d363
refs/heads/master: 6168f62cbde8dcf4f58255794efbcdb8df603959
16 changes: 15 additions & 1 deletion trunk/fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2072,7 +2072,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
nfs_access_free_entry(entry);
}

static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
{
struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
if (cache == NULL)
Expand All @@ -2098,6 +2098,20 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s
spin_unlock(&nfs_access_lru_lock);
}
}
EXPORT_SYMBOL_GPL(nfs_access_add_cache);

void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result)
{
entry->mask = 0;
if (access_result & NFS4_ACCESS_READ)
entry->mask |= MAY_READ;
if (access_result &
(NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
entry->mask |= MAY_WRITE;
if (access_result & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
entry->mask |= MAY_EXEC;
}
EXPORT_SYMBOL_GPL(nfs_access_set_mask);

static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
{
Expand Down
52 changes: 44 additions & 8 deletions trunk/fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ static int nfs4_map_errors(int err)
return -EACCES;
case -NFS4ERR_MINOR_VERS_MISMATCH:
return -EPROTONOSUPPORT;
case -NFS4ERR_ACCESS:
return -EACCES;
default:
dprintk("%s could not handle NFSv4 error %d\n",
__func__, -err);
Expand Down Expand Up @@ -860,6 +862,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p->o_arg.fh = NFS_FH(dir);
p->o_arg.open_flags = flags;
p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
/* ask server to check for all possible rights as results are cached */
p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY |
NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE;
p->o_arg.clientid = server->nfs_client->cl_clientid;
p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
Expand Down Expand Up @@ -1643,6 +1648,39 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
return status;
}

static int nfs4_opendata_access(struct rpc_cred *cred,
struct nfs4_opendata *opendata,
struct nfs4_state *state, fmode_t fmode)
{
struct nfs_access_entry cache;
u32 mask;

/* access call failed or for some reason the server doesn't
* support any access modes -- defer access call until later */
if (opendata->o_res.access_supported == 0)
return 0;

mask = 0;
if (fmode & FMODE_READ)
mask |= MAY_READ;
if (fmode & FMODE_WRITE)
mask |= MAY_WRITE;
if (fmode & FMODE_EXEC)
mask |= MAY_EXEC;

cache.cred = cred;
cache.jiffies = jiffies;
nfs_access_set_mask(&cache, opendata->o_res.access_result);
nfs_access_add_cache(state->inode, &cache);

if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
return 0;

/* even though OPEN succeeded, access is denied. Close the file */
nfs4_close_state(state, fmode);
return -NFS4ERR_ACCESS;
}

/*
* Note: On error, nfs4_proc_open will free the struct nfs4_opendata
*/
Expand Down Expand Up @@ -1900,6 +1938,10 @@ static int _nfs4_do_open(struct inode *dir,
if (server->caps & NFS_CAP_POSIX_LOCK)
set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);

status = nfs4_opendata_access(cred, opendata, state, fmode);
if (status != 0)
goto err_opendata_put;

if (opendata->o_arg.open_flags & O_EXCL) {
nfs4_exclusive_attrset(opendata, sattr);

Expand Down Expand Up @@ -1945,7 +1987,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
struct nfs4_state *res;
int status;

fmode &= FMODE_READ|FMODE_WRITE;
fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC;
do {
status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
&res, ctx_th);
Expand Down Expand Up @@ -2771,13 +2813,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry

status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
if (!status) {
entry->mask = 0;
if (res.access & NFS4_ACCESS_READ)
entry->mask |= MAY_READ;
if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
entry->mask |= MAY_WRITE;
if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
entry->mask |= MAY_EXEC;
nfs_access_set_mask(entry, res.access);
nfs_refresh_inode(inode, res.fattr);
}
nfs_free_fattr(res.fattr);
Expand Down
16 changes: 12 additions & 4 deletions trunk/fs/nfs/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,14 @@ static int nfs4_stat_to_errno(int);
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_access_maxsz + \
encode_getfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
decode_getfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_open_confirm_sz \
Expand All @@ -467,11 +469,13 @@ static int nfs4_stat_to_errno(int);
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_access_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
Expand Down Expand Up @@ -2220,6 +2224,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
encode_putfh(xdr, args->fh, &hdr);
encode_open(xdr, args, &hdr);
encode_getfh(xdr, &hdr);
encode_access(xdr, args->access, &hdr);
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
encode_nops(&hdr);
}
Expand Down Expand Up @@ -2256,6 +2261,7 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fh, &hdr);
encode_open(xdr, args, &hdr);
encode_access(xdr, args->access, &hdr);
encode_getfattr(xdr, args->bitmask, &hdr);
encode_nops(&hdr);
}
Expand Down Expand Up @@ -4099,7 +4105,7 @@ static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *c
return -EIO;
}

static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
{
__be32 *p;
uint32_t supp, acc;
Expand All @@ -4113,8 +4119,8 @@ static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
goto out_overflow;
supp = be32_to_cpup(p++);
acc = be32_to_cpup(p);
access->supported = supp;
access->access = acc;
*supported = supp;
*access = acc;
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
Expand Down Expand Up @@ -5892,7 +5898,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
status = decode_putfh(xdr);
if (status != 0)
goto out;
status = decode_access(xdr, res);
status = decode_access(xdr, &res->supported, &res->access);
if (status != 0)
goto out;
decode_getfattr(xdr, res->fattr, res->server);
Expand Down Expand Up @@ -6233,6 +6239,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
status = decode_getfh(xdr, &res->fh);
if (status)
goto out;
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr(xdr, res->f_attr, res->server);
out:
return status;
Expand Down Expand Up @@ -6281,6 +6288,7 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
status = decode_open(xdr, res);
if (status)
goto out;
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr(xdr, res->f_attr, res->server);
out:
return status;
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
extern int nfs_permission(struct inode *, int);
extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/nfs_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ struct nfs_openargs {
struct nfs_seqid * seqid;
int open_flags;
fmode_t fmode;
u32 access;
__u64 clientid;
struct stateowner_id id;
union {
Expand Down Expand Up @@ -368,6 +369,8 @@ struct nfs_openres {
struct nfs4_string *owner;
struct nfs4_string *group_owner;
struct nfs4_sequence_res seq_res;
__u32 access_supported;
__u32 access_result;
};

/*
Expand Down

0 comments on commit 53aa10c

Please sign in to comment.