nfsd: wrap accesses to st_access_bmap

Currently, we do this for the most part with "bare" bitops, but
eventually we'll need to expand the share mode code to handle access
and deny modes on other nodes.

In order to facilitate that code in the future, move to some generic
accessor functions. For now, these are mostly static inlines, but
eventually we'll want to move these to "real" functions that are
able to handle multi-node configurations or have a way to "swap in"
new operations to be done in lieu of or in conjunction with these
atomic bitops.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Jeff Layton 2012-05-11 09:45:13 -04:00 committed by J. Bruce Fields
parent 3a3286147f
commit 82c5ff1b14
1 changed files with 54 additions and 28 deletions

View File

@ -471,6 +471,27 @@ test_share(struct nfs4_ol_stateid *stp, struct nfsd4_open *open) {
return true;
}
/* set share access for a given stateid */
static inline void
set_access(u32 access, struct nfs4_ol_stateid *stp)
{
__set_bit(access, &stp->st_access_bmap);
}
/* clear share access for a given stateid */
static inline void
clear_access(u32 access, struct nfs4_ol_stateid *stp)
{
__clear_bit(access, &stp->st_access_bmap);
}
/* test whether a given stateid has access */
static inline bool
test_access(u32 access, struct nfs4_ol_stateid *stp)
{
return test_bit(access, &stp->st_access_bmap);
}
static int nfs4_access_to_omode(u32 access)
{
switch (access & NFS4_SHARE_ACCESS_BOTH) {
@ -484,6 +505,20 @@ static int nfs4_access_to_omode(u32 access)
BUG();
}
/* release all access and file references for a given stateid */
static void
release_all_access(struct nfs4_ol_stateid *stp)
{
int i;
for (i = 1; i < 4; i++) {
if (test_access(i, stp))
nfs4_file_put_access(stp->st_file,
nfs4_access_to_omode(i));
clear_access(i, stp);
}
}
static void unhash_generic_stateid(struct nfs4_ol_stateid *stp)
{
list_del(&stp->st_perfile);
@ -492,16 +527,7 @@ static void unhash_generic_stateid(struct nfs4_ol_stateid *stp)
static void close_generic_stateid(struct nfs4_ol_stateid *stp)
{
int i;
if (stp->st_access_bmap) {
for (i = 1; i < 4; i++) {
if (test_bit(i, &stp->st_access_bmap))
nfs4_file_put_access(stp->st_file,
nfs4_access_to_omode(i));
__clear_bit(i, &stp->st_access_bmap);
}
}
release_all_access(stp);
put_nfs4_file(stp->st_file);
stp->st_file = NULL;
}
@ -2435,7 +2461,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
stp->st_file = fp;
stp->st_access_bmap = 0;
stp->st_deny_bmap = 0;
__set_bit(open->op_share_access, &stp->st_access_bmap);
set_access(open->op_share_access, stp);
__set_bit(open->op_share_deny, &stp->st_deny_bmap);
stp->st_openstp = NULL;
}
@ -2772,7 +2798,7 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
bool new_access;
__be32 status;
new_access = !test_bit(op_share_access, &stp->st_access_bmap);
new_access = !test_access(op_share_access, stp);
if (new_access) {
status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
if (status)
@ -2787,7 +2813,7 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
return status;
}
/* remember the open */
__set_bit(op_share_access, &stp->st_access_bmap);
set_access(op_share_access, stp);
__set_bit(open->op_share_deny, &stp->st_deny_bmap);
return nfs_ok;
@ -3263,18 +3289,18 @@ STALE_STATEID(stateid_t *stateid)
}
static inline int
access_permit_read(unsigned long access_bmap)
access_permit_read(struct nfs4_ol_stateid *stp)
{
return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||
test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);
return test_access(NFS4_SHARE_ACCESS_READ, stp) ||
test_access(NFS4_SHARE_ACCESS_BOTH, stp) ||
test_access(NFS4_SHARE_ACCESS_WRITE, stp);
}
static inline int
access_permit_write(unsigned long access_bmap)
access_permit_write(struct nfs4_ol_stateid *stp)
{
return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
return test_access(NFS4_SHARE_ACCESS_WRITE, stp) ||
test_access(NFS4_SHARE_ACCESS_BOTH, stp);
}
static
@ -3285,9 +3311,9 @@ __be32 nfs4_check_openmode(struct nfs4_ol_stateid *stp, int flags)
/* For lock stateid's, we test the parent open, not the lock: */
if (stp->st_openstp)
stp = stp->st_openstp;
if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))
if ((flags & WR_STATE) && !access_permit_write(stp))
goto out;
if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap)))
if ((flags & RD_STATE) && !access_permit_read(stp))
goto out;
status = nfs_ok;
out:
@ -3636,10 +3662,10 @@ out:
static inline void nfs4_stateid_downgrade_bit(struct nfs4_ol_stateid *stp, u32 access)
{
if (!test_bit(access, &stp->st_access_bmap))
if (!test_access(access, stp))
return;
nfs4_file_put_access(stp->st_file, nfs4_access_to_omode(access));
__clear_bit(access, &stp->st_access_bmap);
clear_access(access, stp);
}
static inline void nfs4_stateid_downgrade(struct nfs4_ol_stateid *stp, u32 to_access)
@ -3693,8 +3719,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
if (status)
goto out;
status = nfserr_inval;
if (!test_bit(od->od_share_access, &stp->st_access_bmap)) {
dprintk("NFSD:access not a subset current bitmap: 0x%lx, input access=%08x\n",
if (!test_access(od->od_share_access, stp)) {
dprintk("NFSD: access not a subset current bitmap: 0x%lx, input access=%08x\n",
stp->st_access_bmap, od->od_share_access);
goto out;
}
@ -3995,10 +4021,10 @@ static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access)
struct nfs4_file *fp = lock_stp->st_file;
int oflag = nfs4_access_to_omode(access);
if (test_bit(access, &lock_stp->st_access_bmap))
if (test_access(access, lock_stp))
return;
nfs4_file_get_access(fp, oflag);
__set_bit(access, &lock_stp->st_access_bmap);
set_access(access, lock_stp);
}
static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_ol_stateid *ost, struct nfsd4_lock *lock, struct nfs4_ol_stateid **lst, bool *new)