2 * Copyright (c) 1999 - 2002, 2004-2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "arla_local.h"
39 * Begining of breakout of nnpfs releated junk
42 static u_int
*seqnums
;
44 static List
*sleepers
;
46 /* number of times each type of message has been sent/recv */
51 } nnpfs_stats
[NNPFS_MSG_COUNT
];
53 static const char *rcvfuncs_name
[] =
89 * An interface for the userland to talk to the kernel and recv back
90 * an integer. For larger messages implement a similar function that
91 * uses the `wakeup' message with data.
95 nnpfs_message_rpc (int fd
, struct nnpfs_message_header
*h
, u_int size
)
99 ret
= nnpfs_message_send (fd
, h
, size
);
102 return nnpfs_message_sleep (h
->sequence_num
);
106 * Try to probe the version on `fd', returning the version.
110 nnpfs_send_message_version (int fd
)
112 struct nnpfs_message_version msg
;
115 msg
.header
.opcode
= NNPFS_MSG_VERSION
;
116 msg
.version
= NNPFS_VERSION
;
117 msg
.blocksize
= fcache_getblocksize();
118 msg
.appendquota
= fcache_set_appendquota();
119 arla_warnx (ADEBMSG
, "sending version");
120 ret
= nnpfs_message_rpc (fd
, (struct nnpfs_message_header
*)&msg
,
126 * Probe for version on `fd'. Fail if != version
130 nnpfs_probe_version (int fd
, int version
)
132 int ret
= nnpfs_send_message_version (fd
);
135 arla_errx (1, ADEBERROR
,
136 "Version mismatch. Nnpfs is version %d and arlad is version %d. Please {up,down}grade.",
141 * Send `num' `blocks' to nnpfs on `fd' as proposed gc-able blocks
142 * If `num' is 0 nnpfs should gc everything gc:able.
146 nnpfs_send_message_gc (int fd
, struct nnpfs_message_gc
*msg
, int num
)
149 "nnpfs_send_message_gc sending gc: num = %d", num
);
151 if (num
> NNPFS_GC_MAX_HANDLE
)
152 num
= NNPFS_GC_MAX_HANDLE
;
154 msg
->header
.opcode
= NNPFS_MSG_GC
;
157 nnpfs_message_send(fd
, (struct nnpfs_message_header
*)msg
,
162 * Init the nnpfs message passing things.
166 nnpfs_message_init (void)
170 seqnums
= (u_int
*)malloc (sizeof (*seqnums
) * getdtablesize ());
172 arla_err (1, ADEBERROR
, errno
, "nnpfs_message_init: malloc");
173 for (i
= 0; i
< getdtablesize (); ++i
)
175 sleepers
= listnew ();
176 if (sleepers
== NULL
)
177 arla_err (1, ADEBERROR
, errno
, "nnpfs_message_init: listnew");
179 assert (sizeof(rcvfuncs_name
) / sizeof(*rcvfuncs_name
) == NNPFS_MSG_COUNT
);
183 * Go to entry in jump-table depending on entry.
187 nnpfs_message_receive (int fd
, struct nnpfs_message_header
*h
, u_int size
)
189 unsigned opcode
= h
->opcode
;
191 if (opcode
>= NNPFS_MSG_COUNT
|| rcvfuncs
[opcode
] == NULL
) {
192 arla_warnx (ADEBMSG
, "Bad message opcode = %u", opcode
);
196 ++nnpfs_stats
[opcode
].recv
;
198 arla_warnx (ADEBMSG
, "Rec message: opcode = %u (%s), size = %u",
199 opcode
, rcvfuncs_name
[opcode
], h
->size
);
201 return (*rcvfuncs
[opcode
])(fd
, h
, size
);
205 * Send a message to the kernel module.
209 nnpfs_message_send (int fd
, struct nnpfs_message_header
*h
, u_int size
)
211 unsigned opcode
= h
->opcode
;
215 h
->sequence_num
= seqnums
[fd
]++;
217 if (opcode
>= NNPFS_MSG_COUNT
) {
218 arla_warnx (ADEBMSG
, "Bad message opcode = %u", opcode
);
222 ++nnpfs_stats
[opcode
].sent
;
224 arla_warnx (ADEBMSG
, "Send message: opcode = %u (%s), size = %u",
225 opcode
, rcvfuncs_name
[opcode
], h
->size
);
227 ret
= kern_write (fd
, h
, size
);
229 arla_warn (ADEBMSG
, errno
, "nnpfs_message_send: write");
236 * This code can only wake up message of type `nnpfs_message_wakeup'
241 nnpfs_message_wakeup (int fd
, struct nnpfs_message_wakeup
*h
, u_int size
)
244 struct nnpfs_message_wakeup
*w
;
246 assert (sizeof(*w
) >= size
);
248 for (i
= listhead (sleepers
); i
; i
= next
) {
249 next
= listnext (sleepers
, i
);
250 w
= (struct nnpfs_message_wakeup
*)listdata(i
);
251 if (w
->header
.sequence_num
== h
->sleepers_sequence_num
) {
252 listdel (sleepers
, i
);
254 LWP_SignalProcess ((char *)w
);
259 arla_warnx (ADEBWARN
, "nnpfs_message_wakeup: no message to wakeup!");
264 * The middle and last part of the nnpfs_message_rpc.
268 nnpfs_message_sleep (u_int seqnum
)
270 struct nnpfs_message_wakeup h
;
272 h
.header
.sequence_num
= seqnum
;
274 listaddtail (sleepers
, &h
);
275 LWP_WaitProcess ((char *)&h
);
280 * Wake up a sleeping kernel-thread that sleeps on `seqnum'
281 * and pass on `error' as an error to the thread.
285 nnpfs_send_message_wakeup (int fd
, u_int seqnum
, int error
)
287 struct nnpfs_message_wakeup msg
;
289 msg
.header
.opcode
= NNPFS_MSG_WAKEUP
;
290 msg
.sleepers_sequence_num
= seqnum
;
293 arla_warnx (ADEBMSG
, "sending wakeup: seq = %u, error = %d",
295 return nnpfs_message_send (fd
, (struct nnpfs_message_header
*)&msg
,
301 * Wake-up a kernel-thread with `seqnum', and pass on `error'
302 * and return value. Add also a data blob for generic use.
306 nnpfs_send_message_wakeup_data (int fd
, u_int seqnum
, int error
,
307 void *data
, int size
)
309 struct nnpfs_message_wakeup
*msg
;
313 "sending wakeup: seq = %u, error = %d", seqnum
, error
);
315 if (size
> NNPFS_MSG_MAX_DATASIZE
) {
316 arla_warnx(ADEBWARN
, "sending wakeup: seq = %u, bad size %d",
321 allocsize
= sizeof(*msg
) + size
;
322 msg
= malloc(allocsize
);
324 arla_warnx(ADEBERROR
, "sending wakeup: malloc failed");
328 msg
->header
.opcode
= NNPFS_MSG_WAKEUP
;
329 msg
->sleepers_sequence_num
= seqnum
;
334 memcpy(msg
->msg
, data
, size
);
336 return nnpfs_message_send (fd
, (struct nnpfs_message_header
*)msg
,
345 unsigned char buf
[NNPFS_MAX_MSG_SIZE
];
350 * Return 1 it buf is full, 0 if it's not.
355 struct nnpfs_message_header
*h
, size_t size
,
356 struct write_buf
*buf
)
358 /* align on 8 byte boundery */
360 if (size
> sizeof (buf
->buf
) - buf
->len
)
363 h
->sequence_num
= seqnums
[fd
]++;
364 h
->size
= (size
+ 8) & ~ 7;
366 assert (h
->opcode
>= 0 && h
->opcode
< NNPFS_MSG_COUNT
);
367 ++nnpfs_stats
[h
->opcode
].sent
;
369 arla_warnx (ADEBMSG
, "Multi-send: opcode = %u (%s), size = %u",
370 h
->opcode
, rcvfuncs_name
[h
->opcode
], h
->size
);
372 memcpy (buf
->buf
+ buf
->len
, h
, size
);
373 memset (buf
->buf
+ buf
->len
+ size
, 0, h
->size
- size
);
379 * Blast of a `buf' to `fd'.
383 send_msg (int fd
, struct write_buf
*buf
)
390 ret
= kern_write (fd
, buf
->buf
, buf
->len
);
391 if (ret
!= buf
->len
) {
392 arla_warn (ADEBMSG
, errno
,
406 nnpfs_send_message_vmultiple (int fd
,
409 struct nnpfs_message_header
*h
;
410 struct write_buf
*buf
;
414 buf
= malloc (sizeof (*buf
));
418 h
= va_arg (args
, struct nnpfs_message_header
*);
419 size
= va_arg (args
, size_t);
422 if (add_new_msg (fd
, h
, size
, buf
)) {
423 ret
= send_msg (fd
, buf
);
428 if (add_new_msg (fd
, h
, size
, buf
))
429 arla_warnx (ADEBERROR
,
430 "nnpfs_send_message_vmultiple: "
431 "add_new_msg failed");
434 h
= va_arg (args
, struct nnpfs_message_header
*);
435 size
= va_arg (args
, size_t);
437 ret
= send_msg (fd
, buf
);
443 * Same as above but different.
447 nnpfs_send_message_multiple (int fd
, ...)
453 ret
= nnpfs_send_message_vmultiple (fd
, args
);
459 * Almost same as above but different.
463 nnpfs_send_message_multiple_list (int fd
,
464 struct nnpfs_message_header
*h
,
468 struct write_buf
*buf
;
471 buf
= malloc (sizeof (*buf
));
475 while (num
&& ret
== 0) {
476 if (add_new_msg (fd
, h
, size
, buf
)) {
477 ret
= send_msg (fd
, buf
);
478 if (add_new_msg (fd
, h
, size
, buf
))
479 arla_warnx (ADEBERROR
,
480 "nnpfs_send_message_multiple_list: "
481 "add_new_msg failed");
483 h
= (struct nnpfs_message_header
*) (((unsigned char *)h
) + size
);
490 ret
= send_msg (fd
, buf
);
496 * Send multiple message to the kernel (for performace/simplicity resons)
500 nnpfs_send_message_wakeup_vmultiple (int fd
,
505 struct nnpfs_message_wakeup msg
;
508 ret
= nnpfs_send_message_vmultiple (fd
, args
);
510 arla_warnx (ADEBERROR
, "nnpfs_send_message_wakeup_vmultiple: "
511 "failed sending messages with error %d", ret
);
513 msg
.header
.opcode
= NNPFS_MSG_WAKEUP
;
514 msg
.header
.size
= sizeof(msg
);
515 msg
.header
.sequence_num
= seqnums
[fd
]++;
516 msg
.sleepers_sequence_num
= seqnum
;
520 ++nnpfs_stats
[NNPFS_MSG_WAKEUP
].sent
;
522 arla_warnx (ADEBMSG
, "multi-sending wakeup: seq = %u, error = %d",
525 ret
= kern_write (fd
, &msg
, sizeof(msg
));
526 if (ret
!= sizeof(msg
)) {
527 arla_warn (ADEBMSG
, errno
,
528 "nnpfs_send_message_wakeup_vmultiple: writev");
535 * Same as above but different.
539 nnpfs_send_message_wakeup_multiple (int fd
,
547 va_start (args
, error
);
548 ret
= nnpfs_send_message_wakeup_vmultiple (fd
, seqnum
, error
, args
);