summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/clnt4xdr.c2
-rw-r--r--fs/lockd/lockd.h25
-rw-r--r--fs/lockd/xdr4.c13
-rw-r--r--fs/lockd/xdr4.h1
4 files changed, 27 insertions, 14 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 61ee5fa6dfa4..c09e67765cac 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -287,7 +287,7 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
fl->c.flc_type = exclusive != 0 ? F_WRLCK : F_RDLCK;
p = xdr_decode_hyper(p, &l_offset);
xdr_decode_hyper(p, &l_len);
- nlm4svc_set_file_lock_range(fl, l_offset, l_len);
+ lockd_set_file_lock_range4(fl, l_offset, l_len);
error = 0;
out:
return error;
diff --git a/fs/lockd/lockd.h b/fs/lockd/lockd.h
index e73c6b348154..ef6431b4cac0 100644
--- a/fs/lockd/lockd.h
+++ b/fs/lockd/lockd.h
@@ -413,6 +413,31 @@ static inline int nlm_compare_locks(const struct file_lock *fl1,
&&(fl1->c.flc_type == fl2->c.flc_type || fl2->c.flc_type == F_UNLCK);
}
+/**
+ * lockd_set_file_lock_range4 - set the byte range of a file_lock
+ * @fl: file_lock whose length fields are to be initialized
+ * @off: starting offset of the lock, in bytes
+ * @len: length of the byte range, in bytes, or zero
+ *
+ * The NLMv4 protocol represents lock byte ranges as (start, length),
+ * where length zero means "lock to end of file." The kernel's file_lock
+ * structure uses (start, end) representation. Convert from NLMv4 format
+ * to file_lock format, clamping the starting offset and treating
+ * arithmetic overflow as "lock to EOF."
+ */
+static inline void
+lockd_set_file_lock_range4(struct file_lock *fl, u64 off, u64 len)
+{
+ u64 clamped_off = (off > OFFSET_MAX) ? OFFSET_MAX : off;
+ s64 end = clamped_off + len - 1;
+
+ fl->fl_start = clamped_off;
+ if (len == 0 || end < 0)
+ fl->fl_end = OFFSET_MAX;
+ else
+ fl->fl_end = end;
+}
+
extern const struct lock_manager_operations nlmsvc_lock_operations;
#endif /* _LOCKD_LOCKD_H */
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index f57d4881d5f1..dbbb2dfcb81b 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -34,17 +34,6 @@ loff_t_to_s64(loff_t offset)
return res;
}
-void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len)
-{
- s64 end = off + len - 1;
-
- fl->fl_start = off;
- if (len == 0 || end < 0)
- fl->fl_end = OFFSET_MAX;
- else
- fl->fl_end = end;
-}
-
/*
* NLM file handles are defined by specification to be a variable-length
* XDR opaque no longer than 1024 bytes. However, this implementation
@@ -91,7 +80,7 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
locks_init_lock(fl);
fl->c.flc_type = F_RDLCK;
- nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
+ lockd_set_file_lock_range4(fl, lock->lock_start, lock->lock_len);
return true;
}
diff --git a/fs/lockd/xdr4.h b/fs/lockd/xdr4.h
index 7be318c0512b..4ddf51a2e0ea 100644
--- a/fs/lockd/xdr4.h
+++ b/fs/lockd/xdr4.h
@@ -15,7 +15,6 @@
#define nlm4_fbig cpu_to_be32(NLM_FBIG)
#define nlm4_failed cpu_to_be32(NLM_FAILED)
-void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len);
bool nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);