Commit 754bc768 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] knfsd: nfsdv4 byte range locking - LOCKU

From: "William A.(Andy) Adamson" <andros@citi.umich.edu>

This implments the LOCKU operation.  These all pass the connectathon
lock test suite against the solaris nfsv4 client.
parent 50676cf4
......@@ -687,6 +687,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
case OP_LOCKT:
op->status = nfsd4_lockt(rqstp, &current_fh, &op->u.lockt);
break;
case OP_LOCKU:
op->status = nfsd4_locku(rqstp, &current_fh, &op->u.locku);
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, &current_fh, &op->u.lookup);
break;
......
......@@ -2033,6 +2033,65 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
return status;
}
int
nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
{
struct nfs4_stateid *stp;
struct file *filp = NULL;
struct file_lock file_lock;
int status;
dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
locku->lu_offset, locku->lu_length);
nfs4_lock_state();
if ((status = nfs4_preprocess_seqid_op(current_fh,
locku->lu_seqid,
&locku->lu_stateid,
CHECK_FH | LOCK_STATE,
&locku->lu_stateowner, &stp)))
goto out;
filp = &stp->st_vfs_file;
BUG_ON(!filp);
file_lock.fl_type = F_UNLCK;
file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
file_lock.fl_pid = lockownerid_hashval(locku->lu_stateowner->so_id);
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
file_lock.fl_notify = NULL;
file_lock.fl_insert = NULL;
file_lock.fl_remove = NULL;
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 = ~(u64)0;
else
file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
nfs4_transform_lock_offset(&file_lock);
/*
* Try to unlock the file in the VFS.
*/
status = posix_lock_file(filp, &file_lock);
if (status) {
printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
goto out_nfserr;
}
/*
* OK, unlock succeeded; the only thing left to do is update the stateid.
*/
update_stateid(&stp->st_stateid);
memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
out:
nfs4_unlock_state();
return status;
out_nfserr:
status = nfserrno(status);
goto out;
}
/*
* Start and stop routines
......
......@@ -624,6 +624,24 @@ nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
DECODE_TAIL;
}
static int
nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
{
DECODE_HEAD;
READ_BUF(24 + sizeof(stateid_t));
READ32(locku->lu_type);
if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
goto xdr_error;
READ32(locku->lu_seqid);
READ32(locku->lu_stateid.si_generation);
COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
READ64(locku->lu_offset);
READ64(locku->lu_length);
DECODE_TAIL;
}
static int
nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
{
......@@ -1052,6 +1070,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
case OP_LOCKT:
op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
break;
case OP_LOCKU:
op->status = nfsd4_decode_locku(argp, &op->u.locku);
break;
case OP_LOOKUP:
op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
break;
......@@ -1815,6 +1836,21 @@ nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
}
static void
nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
{
ENCODE_SEQID_OP_HEAD;
if (!nfserr) {
RESERVE_SPACE(sizeof(stateid_t));
WRITE32(locku->lu_stateid.si_generation);
WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
ADJUST_ARGS();
}
ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
}
static void
nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
......@@ -2232,6 +2268,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
case OP_LOCKT:
nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
break;
case OP_LOCKU:
nfsd4_encode_locku(resp, op->status, &op->u.locku);
break;
case OP_LOOKUP:
break;
case OP_LOOKUPP:
......
......@@ -173,6 +173,17 @@ struct nfsd4_lockt {
struct nfsd4_lock_denied lt_denied;
};
struct nfsd4_locku {
u32 lu_type;
u32 lu_seqid;
stateid_t lu_stateid;
u64 lu_offset;
u64 lu_length;
struct nfs4_stateowner *lu_stateowner;
};
struct nfsd4_lookup {
u32 lo_len; /* request */
char * lo_name; /* request */
......@@ -330,6 +341,7 @@ struct nfsd4_op {
struct nfsd4_link link;
struct nfsd4_lock lock;
struct nfsd4_lockt lockt;
struct nfsd4_locku locku;
struct nfsd4_lookup lookup;
struct nfsd4_verify nverify;
struct nfsd4_open open;
......@@ -425,6 +437,8 @@ extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_lock *lock);
extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_lockt *lockt);
extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_locku *locku);
#endif
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment