|
@@ -2781,6 +2781,25 @@ out:
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
|
|
|
+ * so we do a temporary open here just to get an open file to pass to
|
|
|
+ * vfs_test_lock. (Arguably perhaps test_lock should be done with an
|
|
|
+ * inode operation.)
|
|
|
+ */
|
|
|
+static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
|
|
|
+{
|
|
|
+ struct file *file;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ err = vfs_test_lock(file, lock);
|
|
|
+ nfsd_close(file);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* LOCKT operation
|
|
|
*/
|
|
@@ -2789,7 +2808,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
struct nfsd4_lockt *lockt)
|
|
|
{
|
|
|
struct inode *inode;
|
|
|
- struct file file;
|
|
|
struct file_lock file_lock;
|
|
|
int error;
|
|
|
__be32 status;
|
|
@@ -2847,16 +2865,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
|
|
|
nfs4_transform_lock_offset(&file_lock);
|
|
|
|
|
|
- /* vfs_test_lock uses the struct file _only_ to resolve the inode.
|
|
|
- * since LOCKT doesn't require an OPEN, and therefore a struct
|
|
|
- * file may not exist, pass vfs_test_lock a struct file with
|
|
|
- * only the dentry:inode set.
|
|
|
- */
|
|
|
- memset(&file, 0, sizeof (struct file));
|
|
|
- file.f_path.dentry = cstate->current_fh.fh_dentry;
|
|
|
-
|
|
|
status = nfs_ok;
|
|
|
- error = vfs_test_lock(&file, &file_lock);
|
|
|
+ error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
|
|
|
if (error) {
|
|
|
status = nfserrno(error);
|
|
|
goto out;
|