Whamcloud - gitweb
LU-17000 utils: handle_yaml_no_op() has wrong signature
[fs/lustre-release.git] / lnet / lnet / lib-md.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
4  * Use is subject to license terms.
5  *
6  * Copyright (c) 2012, 2017, Intel Corporation.
7  */
8
9 /* This file is part of Lustre, http://www.lustre.org/
10  *
11  * Memory Descriptor management routines
12  */
13
14 #define DEBUG_SUBSYSTEM S_LNET
15
16 #include <lnet/lib-lnet.h>
17
18 /* must be called with lnet_res_lock held */
19 void
20 lnet_md_unlink(struct lnet_libmd *md)
21 {
22         if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) == 0) {
23                 /* first unlink attempt... */
24                 struct lnet_me *me = md->md_me;
25
26                 md->md_flags |= LNET_MD_FLAG_ZOMBIE;
27
28                 /* Disassociate from ME (if any), and unlink it if it was created
29                  * with LNET_UNLINK */
30                 if (me != NULL) {
31                         /* detach MD from portal */
32                         lnet_ptl_detach_md(me, md);
33                         if (me->me_unlink == LNET_UNLINK)
34                                 lnet_me_unlink(me);
35                 }
36
37                 /* ensure all future handle lookups fail */
38                 lnet_res_lh_invalidate(&md->md_lh);
39         }
40
41         if (md->md_refcount != 0) {
42                 CDEBUG(D_NET, "Queueing unlink of md %p\n", md);
43                 return;
44         }
45
46         CDEBUG(D_NET, "Unlinking md %p\n", md);
47
48         LASSERT(!list_empty(&md->md_list));
49         list_del_init(&md->md_list);
50         LASSERT(!(md->md_flags & LNET_MD_FLAG_HANDLING));
51         lnet_md_free(md);
52 }
53
54 struct page *
55 lnet_get_first_page(struct lnet_libmd *md, unsigned int offset)
56 {
57         unsigned int niov;
58         struct bio_vec *kiov;
59
60         /*
61          * if the md_options has a bulk handle then we want to look at the
62          * bulk md because that's the data which we will be DMAing
63          */
64         if (md && (md->md_options & LNET_MD_BULK_HANDLE) != 0 &&
65             !LNetMDHandleIsInvalid(md->md_bulk_handle))
66                 md = lnet_handle2md(&md->md_bulk_handle);
67
68         if (!md || md->md_niov == 0)
69                 return NULL;
70
71         kiov = md->md_kiov;
72         niov = md->md_niov;
73
74         while (offset >= kiov->bv_len) {
75                 offset -= kiov->bv_len;
76                 niov--;
77                 kiov++;
78                 if (niov == 0) {
79                         CERROR("offset %d goes beyond kiov\n", offset);
80                         return NULL;
81                 }
82         }
83
84         return kiov->bv_page;
85 }
86
87 int
88 lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset)
89 {
90         struct page *page;
91         int cpt = CFS_CPT_ANY;
92
93         page = lnet_get_first_page(md, offset);
94         if (!page) {
95                 CDEBUG(D_NET, "Couldn't resolve first page of md %p with offset %u\n",
96                         md, offset);
97                 goto out;
98         }
99
100         cpt = cfs_cpt_of_node(lnet_cpt_table(), page_to_nid(page));
101
102 out:
103         return cpt;
104 }
105
106 static int lnet_md_validate(const struct lnet_md *umd);
107
108 static struct lnet_libmd *
109 lnet_md_build(const struct lnet_md *umd, int unlink)
110 {
111         int i;
112         unsigned int niov;
113         int total_length = 0;
114         struct lnet_libmd *lmd;
115         unsigned int size;
116
117         if (lnet_md_validate(umd) != 0)
118                 return ERR_PTR(-EINVAL);
119
120         if (umd->umd_options & LNET_MD_KIOV)
121                 niov = umd->umd_length;
122         else
123                 niov = DIV_ROUND_UP(
124                         offset_in_page(umd->umd_start) + umd->umd_length,
125                         PAGE_SIZE);
126         size = offsetof(struct lnet_libmd, md_kiov[niov]);
127
128         if (size <= LNET_SMALL_MD_SIZE) {
129                 lmd = kmem_cache_zalloc(lnet_small_mds_cachep, GFP_NOFS);
130                 if (lmd) {
131                         LIBCFS_MEM_MSG(lmd, size, "slab-alloced");
132                 } else {
133                         CDEBUG(D_MALLOC, "failed to allocate 'md' of size %u\n",
134                                size);
135                 }
136         } else {
137                 LIBCFS_ALLOC(lmd, size);
138         }
139
140         if (!lmd)
141                 return ERR_PTR(-ENOMEM);
142
143         lmd->md_niov = niov;
144         INIT_LIST_HEAD(&lmd->md_list);
145         lmd->md_me = NULL;
146         lmd->md_start = umd->umd_start;
147         lmd->md_offset = 0;
148         lmd->md_max_size = umd->umd_max_size;
149         lmd->md_options = umd->umd_options;
150         lmd->md_user_ptr = umd->umd_user_ptr;
151         lmd->md_handler = NULL;
152         lmd->md_threshold = umd->umd_threshold;
153         lmd->md_refcount = 0;
154         lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0;
155         lmd->md_bulk_handle = umd->umd_bulk_handle;
156
157         if (umd->umd_options & LNET_MD_GPU_ADDR)
158                 lmd->md_flags |= LNET_MD_FLAG_GPU;
159
160         if (umd->umd_options & LNET_MD_KIOV) {
161                 memcpy(lmd->md_kiov, umd->umd_start,
162                        niov * sizeof(lmd->md_kiov[0]));
163
164                 for (i = 0; i < (int)niov; i++) {
165                         /* We take the page pointer on trust */
166                         if (lmd->md_kiov[i].bv_offset +
167                             lmd->md_kiov[i].bv_len > PAGE_SIZE) {
168                                 lnet_md_free(lmd);
169                                 return ERR_PTR(-EINVAL); /* invalid length */
170                         }
171
172                         total_length += lmd->md_kiov[i].bv_len;
173                 }
174
175                 lmd->md_length = total_length;
176
177                 if ((umd->umd_options & LNET_MD_MAX_SIZE) && /* max size used */
178                     (umd->umd_max_size < 0 ||
179                      umd->umd_max_size > total_length)) { /* illegal max_size */
180                         lnet_md_free(lmd);
181                         return ERR_PTR(-EINVAL);
182                 }
183         } else {   /* contiguous - split into pages */
184                 void *pa = umd->umd_start;
185                 int len = umd->umd_length;
186
187                 lmd->md_length = len;
188                 i = 0;
189                 while (len) {
190                         struct page *p;
191                         int plen;
192
193                         if (is_vmalloc_addr(pa))
194                                 p = vmalloc_to_page(pa);
195                         else
196                                 p = virt_to_page(pa);
197                         plen = min_t(int, len, PAGE_SIZE - offset_in_page(pa));
198
199                         lmd->md_kiov[i].bv_page = p;
200                         lmd->md_kiov[i].bv_offset = offset_in_page(pa);
201                         lmd->md_kiov[i].bv_len = plen;
202
203                         len -= plen;
204                         pa += plen;
205                         i += 1;
206                 }
207
208                 WARN(!(lmd->md_options  & LNET_MD_GNILND) && i > LNET_MAX_IOV,
209                         "Max IOV exceeded: %d should be < %d\n",
210                         i, LNET_MAX_IOV);
211                 if ((umd->umd_options & LNET_MD_MAX_SIZE) && /* max size used */
212                     (umd->umd_max_size < 0 ||
213                      umd->umd_max_size > (int)umd->umd_length)) {
214                         lnet_md_free(lmd);
215                         return ERR_PTR(-EINVAL);
216                 }
217                 lmd->md_options |= LNET_MD_KIOV;
218         }
219
220         return lmd;
221 }
222
223 /* must be called with resource lock held */
224 static void
225 lnet_md_link(struct lnet_libmd *md, lnet_handler_t handler, int cpt)
226 {
227         struct lnet_res_container *container = the_lnet.ln_md_containers[cpt];
228
229         /* NB we are passed an allocated, but inactive md.
230          * Caller may lnet_md_unlink() it, or may lnet_md_free() it.
231          */
232         /* This implementation doesn't know how to create START events or
233          * disable END events.  Best to LASSERT our caller is compliant so
234          * we find out quickly...  */
235         /*  TODO - reevaluate what should be here in light of
236          * the removal of the start and end events
237          * maybe there we shouldn't even allow LNET_EQ_NONE!)
238          * LASSERT (handler != NULL);
239          */
240         md->md_handler = handler;
241
242         lnet_res_lh_initialize(container, &md->md_lh);
243
244         LASSERT(list_empty(&md->md_list));
245         list_add(&md->md_list, &container->rec_active);
246 }
247
248 void lnet_assert_handler_unused(lnet_handler_t handler)
249 {
250         struct lnet_res_container *container;
251         int cpt;
252
253         if (!handler)
254                 return;
255         cfs_percpt_for_each(container, cpt, the_lnet.ln_md_containers) {
256                 struct lnet_libmd *md;
257
258                 lnet_res_lock(cpt);
259                 list_for_each_entry(md, &container->rec_active, md_list) {
260                         LASSERT(md->md_handler != handler);
261                 }
262                 lnet_res_unlock(cpt);
263         }
264 }
265 EXPORT_SYMBOL(lnet_assert_handler_unused);
266
267 /* must be called with lnet_res_lock held */
268 void
269 lnet_md_deconstruct(struct lnet_libmd *lmd, struct lnet_event *ev)
270 {
271         ev->md_start = lmd->md_start;
272         ev->md_options = lmd->md_options;
273         ev->md_user_ptr = lmd->md_user_ptr;
274 }
275
276 static int
277 lnet_md_validate(const struct lnet_md *umd)
278 {
279         if (umd->umd_start == NULL && umd->umd_length != 0) {
280                 CERROR("MD start pointer can not be NULL with length %u\n",
281                        umd->umd_length);
282                 return -EINVAL;
283         }
284
285         if ((umd->umd_options & LNET_MD_KIOV) &&
286             umd->umd_length > LNET_MAX_IOV) {
287                 CERROR("Invalid option: too many fragments %u, %d max\n",
288                        umd->umd_length, LNET_MAX_IOV);
289                 return -EINVAL;
290         }
291
292         return 0;
293 }
294
295 /**
296  * Create a memory descriptor and attach it to a ME
297  *
298  * \param me An ME to associate the new MD with.
299  * \param umd Provides initial values for the user-visible parts of a MD.
300  * Other than its use for initialization, there is no linkage between this
301  * structure and the MD maintained by the LNet.
302  * \param unlink A flag to indicate whether the MD is automatically unlinked
303  * when it becomes inactive, either because the operation threshold drops to
304  * zero or because the available memory becomes less than \a umd.umd_max_size.
305  * (Note that the check for unlinking a MD only occurs after the completion
306  * of a successful operation on the MD.) The value LNET_UNLINK enables auto
307  * unlinking; the value LNET_RETAIN disables it.
308  * \param handle On successful returns, a handle to the newly created MD is
309  * saved here. This handle can be used later in LNetMDUnlink().
310  *
311  * The ME will either be linked to the new MD, or it will be freed.
312  *
313  * \retval 0       On success.
314  * \retval -EINVAL If \a umd is not valid.
315  * \retval -ENOMEM If new MD cannot be allocated.
316  */
317 int
318 LNetMDAttach(struct lnet_me *me, const struct lnet_md *umd,
319              enum lnet_unlink unlink, struct lnet_handle_md *handle)
320 {
321         LIST_HEAD(matches);
322         LIST_HEAD(drops);
323         struct lnet_libmd       *md;
324         int                     cpt;
325
326         LASSERT(the_lnet.ln_refcount > 0);
327         LASSERT(!me->me_md);
328
329         if ((umd->umd_options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) == 0) {
330                 CERROR("Invalid option: no MD_OP set\n");
331                 md = ERR_PTR(-EINVAL);
332         } else
333                 md = lnet_md_build(umd, unlink);
334
335         cpt = me->me_cpt;
336         lnet_res_lock(cpt);
337
338         if (IS_ERR(md)) {
339                 lnet_me_unlink(me);
340                 lnet_res_unlock(cpt);
341                 return PTR_ERR(md);
342         }
343
344         lnet_md_link(md, umd->umd_handler, cpt);
345
346         /* attach this MD to portal of ME and check if it matches any
347          * blocked msgs on this portal */
348         lnet_ptl_attach_md(me, md, &matches, &drops);
349
350         lnet_md2handle(handle, md);
351
352         lnet_res_unlock(cpt);
353
354         lnet_drop_delayed_msg_list(&drops, "Bad match");
355         lnet_recv_delayed_msg_list(&matches);
356
357         return 0;
358 }
359 EXPORT_SYMBOL(LNetMDAttach);
360
361 /**
362  * Create a "free floating" memory descriptor - a MD that is not associated
363  * with a ME. Such MDs are usually used in LNetPut() and LNetGet() operations.
364  *
365  * \param umd,umd_unlink See the discussion for LNetMDAttach().
366  * \param handle On successful returns, a handle to the newly created MD is
367  * saved here. This handle can be used later in LNetMDUnlink(), LNetPut(),
368  * and LNetGet() operations.
369  *
370  * \retval 0       On success.
371  * \retval -EINVAL If \a umd is not valid.
372  * \retval -ENOMEM If new MD cannot be allocated.
373  */
374 int
375 LNetMDBind(const struct lnet_md *umd, enum lnet_unlink unlink,
376            struct lnet_handle_md *handle)
377 {
378         struct lnet_libmd       *md;
379         int             cpt;
380         int             rc;
381
382         LASSERT(the_lnet.ln_refcount > 0);
383
384         if ((umd->umd_options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) != 0) {
385                 CERROR("Invalid option: GET|PUT illegal on active MDs\n");
386                 return -EINVAL;
387         }
388
389         md = lnet_md_build(umd, unlink);
390         if (IS_ERR(md))
391                 return PTR_ERR(md);
392
393         if (md->md_length > LNET_MTU) {
394                 CERROR("Invalid length: too big transfer size %u, %d max\n",
395                        md->md_length, LNET_MTU);
396                 rc = -EINVAL;
397                 goto out_free;
398         }
399
400         cpt = lnet_res_lock_current();
401
402         lnet_md_link(md, umd->umd_handler, cpt);
403
404         lnet_md2handle(handle, md);
405
406         lnet_res_unlock(cpt);
407         return 0;
408
409  out_free:
410         lnet_md_free(md);
411         return rc;
412 }
413 EXPORT_SYMBOL(LNetMDBind);
414
415 /**
416  * Unlink the memory descriptor from any ME it may be linked to and release
417  * the internal resources associated with it. As a result, active messages
418  * associated with the MD may get aborted.
419  *
420  * This function does not free the memory region associated with the MD;
421  * i.e., the memory the user allocated for this MD. If the ME associated with
422  * this MD is not NULL and was created with auto unlink enabled, the ME is
423  * unlinked as well (see LNetMEAttach()).
424  *
425  * Explicitly unlinking a MD via this function call has the same behavior as
426  * a MD that has been automatically unlinked, except that no LNET_EVENT_UNLINK
427  * is generated in the latter case.
428  *
429  * An unlinked event can be reported in two ways:
430  * - If there's no pending operations on the MD, it's unlinked immediately
431  *   and an LNET_EVENT_UNLINK event is logged before this function returns.
432  * - Otherwise, the MD is only marked for deletion when this function
433  *   returns, and the unlinked event will be piggybacked on the event of
434  *   the completion of the last operation by setting the unlinked field of
435  *   the event. No dedicated LNET_EVENT_UNLINK event is generated.
436  *
437  * Note that in both cases the unlinked field of the event is always set; no
438  * more event will happen on the MD after such an event is logged.
439  *
440  * \param mdh A handle for the MD to be unlinked.
441  *
442  * \retval 0       On success.
443  * \retval -ENOENT If \a mdh does not point to a valid MD object.
444  */
445 int
446 LNetMDUnlink(struct lnet_handle_md mdh)
447 {
448         struct lnet_event ev;
449         struct lnet_libmd *md = NULL;
450         lnet_handler_t handler = NULL;
451         int cpt;
452
453         LASSERT(the_lnet.ln_refcount > 0);
454
455         cpt = lnet_cpt_of_cookie(mdh.cookie);
456         lnet_res_lock(cpt);
457         while (!md) {
458                 md = lnet_handle2md(&mdh);
459                 if (!md) {
460                         lnet_res_unlock(cpt);
461                         return -ENOENT;
462                 }
463                 if (md->md_refcount == 0 &&
464                     md->md_flags & LNET_MD_FLAG_HANDLING) {
465                         /* Race with unlocked call to ->md_handler. */
466                         lnet_md_wait_handling(md, cpt);
467                         md = NULL;
468                 }
469         }
470
471         md->md_flags |= LNET_MD_FLAG_ABORTED;
472         /* If the MD is busy, lnet_md_unlink just marks it for deletion, and
473          * when the LND is done, the completion event flags that the MD was
474          * unlinked. Otherwise, we enqueue an event now... */
475         if (md->md_handler && md->md_refcount == 0) {
476                 lnet_build_unlink_event(md, &ev);
477                 handler = md->md_handler;
478         }
479
480         if (md->md_rspt_ptr != NULL)
481                 lnet_detach_rsp_tracker(md, cpt);
482
483         lnet_md_unlink(md);
484
485         lnet_res_unlock(cpt);
486
487         if (handler)
488                 handler(&ev);
489
490         return 0;
491 }
492 EXPORT_SYMBOL(LNetMDUnlink);