summaryrefslogtreecommitdiff
path: root/minix/lib/libbdev/call.c
blob: 2a33791faf8f9cb1c48b5558a28fe24e0fd1a2dd (plain)
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
/* libbdev - asynchronous call structure management */

#include <minix/drivers.h>
#include <minix/bdev.h>
#include <assert.h>

#include "const.h"
#include "type.h"
#include "proto.h"

static bdev_call_t *calls[NR_CALLS];

bdev_call_t *bdev_call_alloc(int count)
{
/* Allocate a call structure.
 */
  bdev_call_t *call;
  bdev_id_t id;

  for (id = 0; id < NR_CALLS; id++)
	if (calls[id] == NULL)
		break;

  if (id == NR_CALLS)
	return NULL;

  call = malloc(sizeof(bdev_call_t) +
	sizeof(call->gvec[0]) * (count - 1) +
	sizeof(call->vec[0]) * count);

  if (call == NULL)
	return NULL;

  call->id = id;
  call->vec = (iovec_t *) &call->gvec[count];

  calls[id] = call;

  return call;
}

void bdev_call_free(bdev_call_t *call)
{
/* Free a call structure.
 */

  assert(calls[call->id] == call);

  calls[call->id] = NULL;

  free(call);
}

bdev_call_t *bdev_call_get(bdev_id_t id)
{
/* Retrieve a call structure by request number.
 */

  if (id < 0 || id >= NR_CALLS)
	return NULL;

  return calls[id];
}

bdev_call_t *bdev_call_find(dev_t dev)
{
/* Find the first asynchronous request for the given device, if any.
 */
  bdev_id_t id;

  for (id = 0; id < NR_CALLS; id++)
	if (calls[id] != NULL && calls[id]->dev == dev)
		return calls[id];

  return NULL;
}

bdev_call_t *bdev_call_iter_maj(dev_t dev, bdev_call_t *call,
	bdev_call_t **next)
{
/* Iterate over all asynchronous requests for a major device. This function
 * must be safe even if the returned call structure is freed.
 */
  bdev_id_t id;
  int major;

  major = major(dev);

  /* If this is the first invocation, find the first match. Otherwise, take the
   * call we found to be next in the last invocation, which may be NULL.
   */
  if (call == NULL) {
	for (id = 0; id < NR_CALLS; id++)
		if (calls[id] != NULL && major(calls[id]->dev) == major)
			break;

	if (id == NR_CALLS)
		return NULL;

	call = calls[id];
  } else {
	if ((call = *next) == NULL)
		return NULL;
  }

  /* Look for the next match, if any. */
  *next = NULL;

  for (id = call->id + 1; id < NR_CALLS; id++) {
	if (calls[id] != NULL && major(calls[id]->dev) == major) {
		*next = calls[id];

		break;
	}
  }

  return call;
}