1 #include <minix/drivers.h>
2 #include <minix/ioctl.h>
3 #include <sys/ioc_fbd.h>
8 static struct fbd_rule rules
[MAX_RULES
];
9 static struct fbd_rule
*matches
[MAX_RULES
];
10 static int nr_matches
;
12 /*===========================================================================*
14 *===========================================================================*/
15 int rule_ctl(int request
, endpoint_t endpt
, cp_grant_id_t grant
)
17 /* Handle an I/O control request regarding rules. */
21 /* Note that any of the safecopy calls may fail if the ioctl is
22 * improperly defined in userland; never panic if they fail!
26 /* Find a free rule slot. */
27 for (i
= 1; i
<= MAX_RULES
; i
++)
28 if (rules
[i
-1].num
== 0)
34 /* Copy in the rule. */
35 if ((r
= sys_safecopyfrom(endpt
, grant
, 0,
36 (vir_bytes
) &rules
[i
-1], sizeof(rules
[0]))) != OK
)
39 /* Mark the rule as active, and return its number. */
45 /* Copy in the given rule number. */
46 if ((r
= sys_safecopyfrom(endpt
, grant
, 0, (vir_bytes
) &i
,
50 /* Fail if the given rule number is not valid or in use.
51 * Allow the caller to determine the maximum rule number.
53 if (i
<= 0 || i
> MAX_RULES
) return EINVAL
;
55 if (rules
[i
-1].num
!= i
) return ENOENT
;
57 /* Mark the rule as not active. */
63 /* Copy in just the rule number from the given structure. */
64 if ((r
= sys_safecopyfrom(endpt
, grant
,
65 offsetof(struct fbd_rule
, num
), (vir_bytes
) &i
,
69 /* Fail if the given rule number is not valid or in use.
70 * Allow the caller to determine the maximum rule number.
72 if (i
<= 0 || i
> MAX_RULES
) return EINVAL
;
74 if (rules
[i
-1].num
!= i
) return ENOENT
;
76 /* Copy out the entire rule as is. */
77 return sys_safecopyto(endpt
, grant
, 0, (vir_bytes
) &rules
[i
-1],
85 /*===========================================================================*
87 *===========================================================================*/
88 static int rule_match(struct fbd_rule
*rule
, u64_t pos
, size_t size
, int flag
)
90 /* Check whether the given rule matches the given parameters. As side
91 * effect, update counters in the rule as appropriate.
94 /* Ranges must overlap (start < pos+size && end > pos). */
95 if (cmp64(rule
->start
, add64u(pos
, size
)) >= 0 ||
96 (cmp64u(rule
->end
, 0) && cmp64(rule
->end
, pos
) <= 0))
99 /* Flags must match. */
100 if (!(rule
->flags
& flag
)) return FALSE
;
102 /* This is a match, but is it supposed to trigger yet? */
103 if (rule
->skip
> 0) {
112 /*===========================================================================*
114 *===========================================================================*/
115 int rule_find(u64_t pos
, size_t size
, int flag
)
117 /* Find all matching rules, and return a hook mask. */
118 struct fbd_rule
*rule
;
124 for (i
= 0; i
< MAX_RULES
; i
++) {
127 if (rule
->num
== 0) continue;
129 if (!rule_match(rule
, pos
, size
, flag
))
132 matches
[nr_matches
++] = rule
;
134 /* If the rule has a limited lifetime, update it now. */
135 if (rule
->count
> 0) {
138 /* Disable the rule from future matching. */
139 if (rule
->count
== 0)
143 hooks
|= action_mask(rule
);
149 /*===========================================================================*
151 *===========================================================================*/
152 void rule_pre_hook(iovec_t
*iov
, unsigned *count
, size_t *size
,
157 for (i
= 0; i
< nr_matches
; i
++)
158 if (action_mask(matches
[i
]) & PRE_HOOK
)
159 action_pre_hook(matches
[i
], iov
, count
, size
, pos
);
162 /*===========================================================================*
164 *===========================================================================*/
165 void rule_io_hook(char *buf
, size_t size
, u64_t pos
, int flag
)
169 for (i
= 0; i
< nr_matches
; i
++)
170 if (action_mask(matches
[i
]) & IO_HOOK
)
171 action_io_hook(matches
[i
], buf
, size
, pos
, flag
);
174 /*===========================================================================*
176 *===========================================================================*/
177 void rule_post_hook(size_t osize
, int *result
)
181 for (i
= 0; i
< nr_matches
; i
++)
182 if (action_mask(matches
[i
]) & POST_HOOK
)
183 action_post_hook(matches
[i
], osize
, result
);