root/fs/dlm/midcomms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. copy_from_cb
  2. dlm_process_incoming_buffer

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /******************************************************************************
   3 *******************************************************************************
   4 **
   5 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
   6 **  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
   7 **
   8 **
   9 *******************************************************************************
  10 ******************************************************************************/
  11 
  12 /*
  13  * midcomms.c
  14  *
  15  * This is the appallingly named "mid-level" comms layer.
  16  *
  17  * Its purpose is to take packets from the "real" comms layer,
  18  * split them up into packets and pass them to the interested
  19  * part of the locking mechanism.
  20  *
  21  * It also takes messages from the locking layer, formats them
  22  * into packets and sends them to the comms layer.
  23  */
  24 
  25 #include "dlm_internal.h"
  26 #include "lowcomms.h"
  27 #include "config.h"
  28 #include "lock.h"
  29 #include "midcomms.h"
  30 
  31 
  32 static void copy_from_cb(void *dst, const void *base, unsigned offset,
  33                          unsigned len, unsigned limit)
  34 {
  35         unsigned copy = len;
  36 
  37         if ((copy + offset) > limit)
  38                 copy = limit - offset;
  39         memcpy(dst, base + offset, copy);
  40         len -= copy;
  41         if (len)
  42                 memcpy(dst + copy, base, len);
  43 }
  44 
  45 /*
  46  * Called from the low-level comms layer to process a buffer of
  47  * commands.
  48  *
  49  * Only complete messages are processed here, any "spare" bytes from
  50  * the end of a buffer are saved and tacked onto the front of the next
  51  * message that comes in. I doubt this will happen very often but we
  52  * need to be able to cope with it and I don't want the task to be waiting
  53  * for packets to come in when there is useful work to be done.
  54  */
  55 
  56 int dlm_process_incoming_buffer(int nodeid, const void *base,
  57                                 unsigned offset, unsigned len, unsigned limit)
  58 {
  59         union {
  60                 unsigned char __buf[DLM_INBUF_LEN];
  61                 /* this is to force proper alignment on some arches */
  62                 union dlm_packet p;
  63         } __tmp;
  64         union dlm_packet *p = &__tmp.p;
  65         int ret = 0;
  66         int err = 0;
  67         uint16_t msglen;
  68         uint32_t lockspace;
  69 
  70         while (len > sizeof(struct dlm_header)) {
  71 
  72                 /* Copy just the header to check the total length.  The
  73                    message may wrap around the end of the buffer back to the
  74                    start, so we need to use a temp buffer and copy_from_cb. */
  75 
  76                 copy_from_cb(p, base, offset, sizeof(struct dlm_header),
  77                              limit);
  78 
  79                 msglen = le16_to_cpu(p->header.h_length);
  80                 lockspace = p->header.h_lockspace;
  81 
  82                 err = -EINVAL;
  83                 if (msglen < sizeof(struct dlm_header))
  84                         break;
  85                 if (p->header.h_cmd == DLM_MSG) {
  86                         if (msglen < sizeof(struct dlm_message))
  87                                 break;
  88                 } else {
  89                         if (msglen < sizeof(struct dlm_rcom))
  90                                 break;
  91                 }
  92                 err = -E2BIG;
  93                 if (msglen > dlm_config.ci_buffer_size) {
  94                         log_print("message size %d from %d too big, buf len %d",
  95                                   msglen, nodeid, len);
  96                         break;
  97                 }
  98                 err = 0;
  99 
 100                 /* If only part of the full message is contained in this
 101                    buffer, then do nothing and wait for lowcomms to call
 102                    us again later with more data.  We return 0 meaning
 103                    we've consumed none of the input buffer. */
 104 
 105                 if (msglen > len)
 106                         break;
 107 
 108                 /* Allocate a larger temp buffer if the full message won't fit
 109                    in the buffer on the stack (which should work for most
 110                    ordinary messages). */
 111 
 112                 if (msglen > sizeof(__tmp) && p == &__tmp.p) {
 113                         p = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
 114                         if (p == NULL)
 115                                 return ret;
 116                 }
 117 
 118                 copy_from_cb(p, base, offset, msglen, limit);
 119 
 120                 BUG_ON(lockspace != p->header.h_lockspace);
 121 
 122                 ret += msglen;
 123                 offset += msglen;
 124                 offset &= (limit - 1);
 125                 len -= msglen;
 126 
 127                 dlm_receive_buffer(p, nodeid);
 128         }
 129 
 130         if (p != &__tmp.p)
 131                 kfree(p);
 132 
 133         return err ? err : ret;
 134 }
 135 

/* [<][>][^][v][top][bottom][index][help] */