1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020, Oracle and/or its affiliates
*/
#ifndef SVC_RDMA_PCL_H
#define SVC_RDMA_PCL_H
#include <linux/list.h>
struct svc_rdma_segment {
u32 rs_handle;
u32 rs_length;
u64 rs_offset;
};
struct svc_rdma_chunk {
struct list_head ch_list;
u32 ch_position;
u32 ch_length;
u32 ch_payload_length;
u32 ch_segcount;
struct svc_rdma_segment ch_segments[];
};
struct svc_rdma_pcl {
unsigned int cl_count;
struct list_head cl_chunks;
};
/**
* pcl_init - Initialize a parsed chunk list
* @pcl: parsed chunk list to initialize
*
*/
static inline void pcl_init(struct svc_rdma_pcl *pcl)
{
INIT_LIST_HEAD(&pcl->cl_chunks);
}
/**
* pcl_is_empty - Return true if parsed chunk list is empty
* @pcl: parsed chunk list
*
*/
static inline bool pcl_is_empty(const struct svc_rdma_pcl *pcl)
{
return list_empty(&pcl->cl_chunks);
}
/**
* pcl_first_chunk - Return first chunk in a parsed chunk list
* @pcl: parsed chunk list
*
* Returns the first chunk in the list, or NULL if the list is empty.
*/
static inline struct svc_rdma_chunk *
pcl_first_chunk(const struct svc_rdma_pcl *pcl)
{
if (pcl_is_empty(pcl))
return NULL;
return list_first_entry(&pcl->cl_chunks, struct svc_rdma_chunk,
ch_list);
}
/**
* pcl_next_chunk - Return next chunk in a parsed chunk list
* @pcl: a parsed chunk list
* @chunk: chunk in @pcl
*
* Returns the next chunk in the list, or NULL if @chunk is already last.
*/
static inline struct svc_rdma_chunk *
pcl_next_chunk(const struct svc_rdma_pcl *pcl, struct svc_rdma_chunk *chunk)
{
if (list_is_last(&chunk->ch_list, &pcl->cl_chunks))
return NULL;
return list_next_entry(chunk, ch_list);
}
/**
* pcl_for_each_chunk - Iterate over chunks in a parsed chunk list
* @pos: the loop cursor
* @pcl: a parsed chunk list
*/
#define pcl_for_each_chunk(pos, pcl) \
for (pos = list_first_entry(&(pcl)->cl_chunks, struct svc_rdma_chunk, ch_list); \
&pos->ch_list != &(pcl)->cl_chunks; \
pos = list_next_entry(pos, ch_list))
/**
* pcl_for_each_segment - Iterate over segments in a parsed chunk
* @pos: the loop cursor
* @chunk: a parsed chunk
*/
#define pcl_for_each_segment(pos, chunk) \
for (pos = &(chunk)->ch_segments[0]; \
pos < &(chunk)->ch_segments[(chunk)->ch_segcount]; \
pos++)
/**
* pcl_chunk_end_offset - Return offset of byte range following @chunk
* @chunk: chunk in @pcl
*
* Returns starting offset of the region just after @chunk
*/
static inline unsigned int
pcl_chunk_end_offset(const struct svc_rdma_chunk *chunk)
{
return xdr_align_size(chunk->ch_position + chunk->ch_payload_length);
}
struct svc_rdma_recv_ctxt;
extern void pcl_free(struct svc_rdma_pcl *pcl);
extern bool pcl_alloc_call(struct svc_rdma_recv_ctxt *rctxt, __be32 *p);
extern bool pcl_alloc_read(struct svc_rdma_recv_ctxt *rctxt, __be32 *p);
extern bool pcl_alloc_write(struct svc_rdma_recv_ctxt *rctxt,
struct svc_rdma_pcl *pcl, __be32 *p);
extern bool pcl_check_read_chunk_positions(struct svc_rdma_recv_ctxt *rctxt,
unsigned int inline_len);
extern int pcl_process_nonpayloads(const struct svc_rdma_pcl *pcl,
const struct xdr_buf *xdr,
int (*actor)(const struct xdr_buf *,
void *),
void *data);
#endif /* SVC_RDMA_PCL_H */
|