nfsd: last_byte_offset

refactor the nfs4 server lock code to use last_byte_offset
to compute the last byte covered by the lock.  Check for overflow
so that the last byte is set to NFS4_MAX_UINT64 if offset + len
wraps around.

Also, use NFS4_MAX_UINT64 for ~(u64)0 where appropriate.

Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
Benny Halevy 2008-12-15 19:42:03 +02:00 committed by J. Bruce Fields
parent 4e65ebf089
commit 87df4de807
2 changed files with 28 additions and 16 deletions

View File

@ -2416,6 +2416,26 @@ out:
#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS) #define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS)
#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1) #define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1)
static inline u64
end_offset(u64 start, u64 len)
{
u64 end;
end = start + len;
return end >= start ? end: NFS4_MAX_UINT64;
}
/* last octet in a range */
static inline u64
last_byte_offset(u64 start, u64 len)
{
u64 end;
BUG_ON(!len);
end = start + len;
return end > start ? end - 1: NFS4_MAX_UINT64;
}
#define lockownerid_hashval(id) \ #define lockownerid_hashval(id) \
((id) & LOCK_HASH_MASK) ((id) & LOCK_HASH_MASK)
@ -2519,8 +2539,8 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
deny->ld_clientid.cl_id = 0; deny->ld_clientid.cl_id = 0;
} }
deny->ld_start = fl->fl_start; deny->ld_start = fl->fl_start;
deny->ld_length = ~(u64)0; deny->ld_length = NFS4_MAX_UINT64;
if (fl->fl_end != ~(u64)0) if (fl->fl_end != NFS4_MAX_UINT64)
deny->ld_length = fl->fl_end - fl->fl_start + 1; deny->ld_length = fl->fl_end - fl->fl_start + 1;
deny->ld_type = NFS4_READ_LT; deny->ld_type = NFS4_READ_LT;
if (fl->fl_type != F_RDLCK) if (fl->fl_type != F_RDLCK)
@ -2617,7 +2637,7 @@ out:
static int static int
check_lock_length(u64 offset, u64 length) check_lock_length(u64 offset, u64 length)
{ {
return ((length == 0) || ((length != ~(u64)0) && return ((length == 0) || ((length != NFS4_MAX_UINT64) &&
LOFF_OVERFLOW(offset, length))); LOFF_OVERFLOW(offset, length)));
} }
@ -2737,11 +2757,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
file_lock.fl_lmops = &nfsd_posix_mng_ops; file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lock->lk_offset; file_lock.fl_start = lock->lk_offset;
if ((lock->lk_length == ~(u64)0) || file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
LOFF_OVERFLOW(lock->lk_offset, lock->lk_length))
file_lock.fl_end = ~(u64)0;
else
file_lock.fl_end = lock->lk_offset + lock->lk_length - 1;
nfs4_transform_lock_offset(&file_lock); nfs4_transform_lock_offset(&file_lock);
/* /*
@ -2858,10 +2874,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
file_lock.fl_lmops = &nfsd_posix_mng_ops; file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lockt->lt_offset; file_lock.fl_start = lockt->lt_offset;
if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length)) file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
file_lock.fl_end = ~(u64)0;
else
file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1;
nfs4_transform_lock_offset(&file_lock); nfs4_transform_lock_offset(&file_lock);
@ -2917,10 +2930,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
file_lock.fl_lmops = &nfsd_posix_mng_ops; file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = locku->lu_offset; file_lock.fl_start = locku->lu_offset;
if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length);
file_lock.fl_end = ~(u64)0;
else
file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
nfs4_transform_lock_offset(&file_lock); nfs4_transform_lock_offset(&file_lock);
/* /*

View File

@ -88,6 +88,8 @@
#define NFS4_ACE_GENERIC_EXECUTE 0x001200A0 #define NFS4_ACE_GENERIC_EXECUTE 0x001200A0
#define NFS4_ACE_MASK_ALL 0x001F01FF #define NFS4_ACE_MASK_ALL 0x001F01FF
#define NFS4_MAX_UINT64 (~(u64)0)
enum nfs4_acl_whotype { enum nfs4_acl_whotype {
NFS4_ACL_WHO_NAMED = 0, NFS4_ACL_WHO_NAMED = 0,
NFS4_ACL_WHO_OWNER, NFS4_ACL_WHO_OWNER,