This source file includes following definitions.
- xfs_initq
- xfs_emptyq
- xfs_onq
- xfs_appendq
- xfs_outq
- xfs_devopen_common
- xfs_devclose_common
- xfs_cursig
- xfs_devread
- xfs_devwrite
- xfs_message_send
- xfs_block_sigset
- xfs_message_rpc
- xfs_message_receive
- xfs_message_wakeup
- xfs_message_wakeup_data
- xfs_uprintf_device
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 #include <xfs/xfs_locl.h>
36 #include <xfs/xfs_message.h>
37 #include <xfs/xfs_msg_locl.h>
38 #include <xfs/xfs_fs.h>
39 #include <xfs/xfs_dev.h>
40 #include <xfs/xfs_deb.h>
41
42 RCSID("$arla: xfs_dev-common.c,v 1.61 2003/07/15 16:25:42 lha Exp $");
43
44 struct xfs_channel xfs_channel[NNNPFS];
45
46 void
47 xfs_initq(struct xfs_link *q)
48 {
49 q->next = q;
50 q->prev = q;
51 }
52
53
54 int
55 xfs_emptyq(const struct xfs_link *q)
56 {
57 return q->next == q;
58 }
59
60
61 int
62 xfs_onq(const struct xfs_link *link)
63 {
64 return link->next != NULL || link->prev != NULL;
65 }
66
67
68 void
69 xfs_appendq(struct xfs_link *q, struct xfs_link *p)
70 {
71 p->next = q;
72 p->prev = q->prev;
73 p->prev->next = p;
74 q->prev = p;
75 }
76
77
78 void
79 xfs_outq(struct xfs_link *p)
80 {
81 p->next->prev = p->prev;
82 p->prev->next = p->next;
83 p->next = p->prev = NULL;
84 }
85
86
87
88
89 int
90 xfs_devopen_common(dev_t dev)
91 {
92 struct xfs_channel *chan;
93
94 if (minor(dev) < 0 || minor(dev) >= NNNPFS)
95 return ENXIO;
96
97 chan = &xfs_channel[minor(dev)];
98
99
100 if (chan->status & CHANNEL_OPENED) {
101 NNPFSDEB(XDEBDEV, ("xfs_devopen: already open\n"));
102 return EBUSY;
103 } else {
104 chan->status |= CHANNEL_OPENED;
105 }
106
107 chan->message_buffer = xfs_alloc(MAX_XMSG_SIZE, M_NNPFS_MSG);
108
109
110 xfs_initq(&chan->sleepq);
111 xfs_initq(&chan->messageq);
112
113 return 0;
114 }
115
116 #if defined(HAVE_TWO_ARGUMENT_VFS_BUSY)
117 #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags))
118 #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
119 #elif defined(HAVE_THREE_ARGUMENT_VFS_BUSY)
120 #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock))
121 #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
122 #elif defined(HAVE_FOUR_ARGUMENT_VFS_BUSY)
123 #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock), (proc))
124 #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp), (proc))
125 #elif defined(__osf__)
126 #define xfs_vfs_busy(mp, flags, lock, proc) (0)
127 #define xfs_vfs_unbusy(mp, proc) (0)
128 #else
129 #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp))
130 #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
131 #endif
132
133
134
135
136 int
137 xfs_devclose_common(dev_t dev, d_thread_t *proc)
138 {
139 struct xfs_channel *chan = &xfs_channel[minor(dev)];
140 struct xfs_link *first;
141
142
143 if (!(chan->status & CHANNEL_OPENED))
144 panic("xfs_devclose never opened?");
145
146 chan->status &= ~CHANNEL_OPENED;
147
148
149 while (!xfs_emptyq(&chan->messageq)) {
150 NNPFSDEB(XDEBDEV, ("before outq(messageq)\n"));
151
152 first = chan->messageq.next;
153 xfs_outq(first);
154 if (first->error_or_size != 0)
155 xfs_free(first, first->error_or_size, M_NNPFS_LINK);
156
157 NNPFSDEB(XDEBDEV, ("after outq(messageq)\n"));
158 }
159
160
161 while (!xfs_emptyq(&chan->sleepq)) {
162 NNPFSDEB(XDEBDEV, ("before outq(sleepq)\n"));
163 first = chan->sleepq.next;
164 xfs_outq(first);
165 first->error_or_size = ENODEV;
166 wakeup((caddr_t) first);
167 NNPFSDEB(XDEBDEV, ("after outq(sleepq)\n"));
168 }
169
170 if (chan->status & CHANNEL_WAITING)
171 wakeup((caddr_t) chan);
172
173 if (chan->message_buffer) {
174 xfs_free(chan->message_buffer, MAX_XMSG_SIZE, M_NNPFS_MSG);
175 chan->message_buffer = NULL;
176 }
177
178
179
180
181
182 if (xfs[minor(dev)].mp != NULL) {
183 if (xfs_vfs_busy(xfs[minor(dev)].mp, VB_READ|VB_WAIT, NULL, proc)) {
184 NNPFSDEB(XDEBNODE, ("xfs_dev_close: vfs_busy() --> BUSY\n"));
185 return EBUSY;
186 }
187 free_all_xfs_nodes(&xfs[minor(dev)], FORCECLOSE, 0);
188
189 xfs_vfs_unbusy(xfs[minor(dev)].mp, proc);
190 }
191
192 return 0;
193 }
194
195 #ifdef NNPFS_DEBUG
196
197
198
199
200 static long
201 xfs_cursig (d_thread_t *p)
202 {
203 #if defined(__osf__)
204 thread_t th = current_thread();
205 struct np_uthread *npu = thread_to_np_uthread(th);
206 return CURSIG(p,npu);
207 #elif defined(HAVE_FREEBSD_THREAD)
208 #ifndef CURSIG
209 return 0;
210
211 #else
212 return CURSIG(p->td_proc);
213 #endif
214 #else
215 #if defined(__NetBSD__) && __NetBSD_Version__ >= 106130000
216 return 0;
217 #else
218 return CURSIG(p);
219 #endif
220 #endif
221 }
222 #endif
223
224
225
226
227
228 int
229 xfs_devread(dev_t dev, struct uio * uiop, int ioflag)
230 {
231 struct xfs_channel *chan = &xfs_channel[minor(dev)];
232 struct xfs_link *first;
233 int error = 0;
234 #ifdef NNPFS_DEBUG
235 char devname[64];
236 #endif
237
238 NNPFSDEB(XDEBDEV, ("xfs_devread dev = %s\n",
239 xfs_devtoname_r(dev, devname, sizeof(devname))));
240
241 NNPFSDEB(XDEBDEV, ("xfs_devread: m = %lx, m->prev = %lx, m->next = %lx\n",
242 (unsigned long)&chan->messageq,
243 (unsigned long)chan->messageq.prev,
244 (unsigned long)chan->messageq.next));
245
246 #ifdef HAVE_FREEBSD_THREAD
247 chan->proc = xfs_uio_to_thread(uiop);
248 #else
249 chan->proc = xfs_uio_to_proc(uiop);
250 #endif
251
252 again:
253
254 if (!xfs_emptyq (&chan->messageq)) {
255 while (!xfs_emptyq (&chan->messageq)) {
256
257 first = chan->messageq.next;
258 NNPFSDEB(XDEBDEV, ("xfs_devread: first = %lx, "
259 "first->prev = %lx, first->next = %lx\n",
260 (unsigned long)first,
261 (unsigned long)first->prev,
262 (unsigned long)first->next));
263
264 NNPFSDEB(XDEBDEV, ("xfs_devread: message->size = %u\n",
265 first->message->size));
266
267 if (first->message->size > uiop->uio_resid)
268 break;
269
270 error = uiomove((caddr_t) first->message, first->message->size,
271 uiop);
272 if (error)
273 break;
274
275 xfs_outq(first);
276
277 if (first->error_or_size != 0)
278 xfs_free(first, first->error_or_size, M_NNPFS_LINK);
279 }
280 } else {
281 chan->status |= CHANNEL_WAITING;
282 if (tsleep((caddr_t) chan, (PZERO + 1) | PCATCH, "xfsread", 0)) {
283 #ifdef HAVE_FREEBSD_THREAD
284 NNPFSDEB(XDEBMSG,
285 ("caught signal xfs_devread: %ld\n",
286 xfs_cursig(xfs_uio_to_thread(uiop))));
287 #else
288 NNPFSDEB(XDEBMSG,
289 ("caught signal xfs_devread: %ld\n",
290 xfs_cursig(xfs_uio_to_proc(uiop))));
291 #endif
292 error = EINTR;
293 } else if ((chan->status & CHANNEL_WAITING) == 0) {
294 goto again;
295 } else
296 error = EIO;
297 }
298
299 NNPFSDEB(XDEBDEV, ("xfs_devread done error = %d\n", error));
300
301 return error;
302 }
303
304
305
306
307
308 int
309 xfs_devwrite(dev_t dev, struct uio *uiop, int ioflag)
310 {
311 struct xfs_channel *chan = &xfs_channel[minor(dev)];
312 char *p;
313 int error;
314 u_int cnt;
315 struct xfs_message_header *msg_buf;
316 #ifdef NNPFS_DEBUG
317 char devname[64];
318 #endif
319
320 NNPFSDEB(XDEBDEV, ("xfs_devwrite dev = %s\n",
321 xfs_devtoname_r (dev, devname, sizeof(devname))));
322
323 #ifdef HAVE_FREEBSD_THREAD
324 chan->proc = xfs_uio_to_thread(uiop);
325 #else
326 chan->proc = xfs_uio_to_proc(uiop);
327 #endif
328 cnt = uiop->uio_resid;
329 error = uiomove((caddr_t) chan->message_buffer, MAX_XMSG_SIZE, uiop);
330 if (error != 0)
331 return error;
332
333 cnt -= uiop->uio_resid;
334
335
336
337
338 for (p = (char *)chan->message_buffer;
339 cnt > 0;
340 p += msg_buf->size, cnt -= msg_buf->size) {
341 #ifdef HAVE_FREEBSD_THREAD
342 d_thread_t *pp = xfs_uio_to_thread(uiop);
343 #else
344 d_thread_t *pp = xfs_uio_to_proc(uiop);
345 #endif
346
347 msg_buf = (struct xfs_message_header *)p;
348 error = xfs_message_receive (minor(dev),
349 msg_buf,
350 msg_buf->size,
351 pp);
352 }
353 NNPFSDEB(XDEBDEV, ("xfs_devwrite error = %d\n", error));
354 return error;
355 }
356
357
358
359
360 int
361 xfs_message_send(int fd, struct xfs_message_header * message, u_int size)
362 {
363 struct xfs_channel *chan = &xfs_channel[fd];
364 struct {
365 struct xfs_link this_message;
366 struct xfs_message_header msg;
367 } *t;
368
369 NNPFSDEB(XDEBMSG, ("xfs_message_send opcode = %d\n", message->opcode));
370
371 if (!(chan->status & CHANNEL_OPENED))
372 return ENODEV;
373
374
375 message->size = size;
376 message->sequence_num = chan->nsequence++;
377
378 t = xfs_alloc(sizeof(t->this_message) + size, M_NNPFS);
379 t->this_message.error_or_size = sizeof(t->this_message) + size;
380 bcopy(message, &t->msg, size);
381
382 t->this_message.message = &t->msg;
383 xfs_appendq(&chan->messageq, &t->this_message);
384 if (chan->status & CHANNEL_WAITING) {
385 chan->status &= ~CHANNEL_WAITING;
386 wakeup((caddr_t) chan);
387 }
388 xfs_select_wakeup(chan);
389
390 return 0;
391 }
392
393 #if defined(SWEXIT)
394 #define NNPFS_P_EXIT SWEXIT
395 #elif defined(P_WEXIT)
396 #define NNPFS_P_EXIT P_WEXIT
397 #else
398 #error what is your exit named ?
399 #endif
400
401 #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
402 static void
403 xfs_block_sigset (sigset_t *sigset)
404 {
405
406 #if defined(__sigaddset)
407 #define xfs_sig_block(ss,signo) __sigaddset((ss), (signo))
408 #elif defined(SIGADDSET)
409 #define xfs_sig_block(ss,signo) SIGADDSET(*(ss), (signo))
410 #else
411 #define xfs_sig_block(ss,signo) *(ss) |= sigmask(signo)
412 #endif
413
414 xfs_sig_block(sigset, SIGIO);
415 xfs_sig_block(sigset, SIGALRM);
416 xfs_sig_block(sigset, SIGVTALRM);
417 xfs_sig_block(sigset, SIGCHLD);
418 #ifdef SIGINFO
419 xfs_sig_block(sigset, SIGINFO);
420 #endif
421 #undef xfs_sig_block
422 }
423 #endif
424
425
426
427
428
429 int
430 xfs_message_rpc(int fd, struct xfs_message_header * message, u_int size,
431 d_thread_t *proc)
432 {
433 int ret;
434 struct xfs_channel *chan = &xfs_channel[fd];
435 struct xfs_link *this_message;
436 struct xfs_link *this_process;
437 struct xfs_message_header *msg;
438 #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
439 sigset_t oldsigmask;
440 #endif
441 int catch;
442
443 NNPFSDEB(XDEBMSG, ("xfs_message_rpc opcode = %d\n", message->opcode));
444
445 if (proc == NULL) {
446 #ifdef HAVE_FREEBSD_THREAD
447 proc = xfs_curthread();
448 #else
449 proc = xfs_curproc();
450 #endif
451 }
452 if (!(chan->status & CHANNEL_OPENED))
453 return ENODEV;
454
455 #ifdef HAVE_FREEBSD_THREAD
456 if (chan->proc != NULL && chan->proc->td_proc != NULL &&
457 proc->td_proc->p_pid == chan->proc->td_proc->p_pid) {
458 printf("xfs_message_rpc: deadlock avoided "
459 "pid = %u == %u\n", proc->td_proc->p_pid, chan->proc->td_proc->p_pid);
460 #else
461 if (chan->proc != NULL && proc->p_pid == chan->proc->p_pid) {
462 printf("xfs_message_rpc: deadlock avoided "
463 "pid = %u == %u\n", proc->p_pid, chan->proc->p_pid);
464 #endif
465 #if 0
466 psignal (proc, SIGABRT);
467 #endif
468 return EDEADLK;
469 }
470
471 if (size < sizeof(struct xfs_message_wakeup)) {
472 printf("NNPFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message->opcode);
473 return ENOMEM;
474 }
475 this_message = xfs_alloc(sizeof(struct xfs_link), M_NNPFS_LINK);
476 this_process = xfs_alloc(sizeof(struct xfs_link), M_NNPFS_LINK);
477 msg = xfs_alloc(size, M_NNPFS_MSG);
478 bcopy(message, msg, size);
479
480 msg->size = size;
481 msg->sequence_num = chan->nsequence++;
482 this_message->error_or_size = 0;
483 this_message->message = msg;
484 this_process->message = msg;
485 xfs_appendq(&chan->messageq, this_message);
486 xfs_appendq(&chan->sleepq, this_process);
487 xfs_select_wakeup(chan);
488 this_process->error_or_size = 0;
489
490 if (chan->status & CHANNEL_WAITING) {
491 chan->status &= ~CHANNEL_WAITING;
492 wakeup((caddr_t) chan);
493 }
494
495
496
497
498
499
500
501 #ifdef HAVE_FREEBSD_THREAD
502
503 oldsigmask = proc->td_sigmask;
504 xfs_block_sigset (&proc->td_sigmask);
505 #elif HAVE_STRUCT_PROC_P_SIGMASK
506
507 oldsigmask = proc->p_sigmask;
508 xfs_block_sigset (&proc->p_sigmask);
509 #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
510
511 oldsigmask = proc->p_sigctx.ps_sigmask;
512 xfs_block_sigset (&proc->p_sigctx.ps_sigmask);
513 #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
514
515 oldsigmask = proc->p_sigwaitmask;
516 xfs_block_sigset (&proc->p_sigwaitmask);
517 #elif defined(__osf__)
518
519 oldsigmask = u.u_sigmask;
520 xfs_block_sigset (&u.u_sigmask);
521 #endif
522
523
524
525
526
527
528
529
530 catch = 0;
531 #ifdef HAVE_FREEBSD_THREAD
532 if (!(proc->td_proc->p_flag & NNPFS_P_EXIT))
533 #else
534 if (!(proc->p_flag & NNPFS_P_EXIT))
535 #endif
536 catch |= PCATCH;
537
538
539
540
541
542
543 if (!(chan->status & CHANNEL_OPENED)) {
544 NNPFSDEB(XDEBMSG, ("xfs_message_rpc: channel went away\n"));
545 this_process->error_or_size = EINTR;
546 } else if ((ret = tsleep((caddr_t) this_process,
547 (PZERO + 1) | catch, "xfs", 0)) != 0) {
548 NNPFSDEB(XDEBMSG, ("caught signal (%d): %ld\n",
549 ret, xfs_cursig(proc)));
550 this_process->error_or_size = EINTR;
551 }
552
553 #ifdef HAVE_FREEBSD_THREAD
554 proc->td_sigmask = oldsigmask;
555 #elif HAVE_STRUCT_PROC_P_SIGMASK
556 proc->p_sigmask = oldsigmask;
557 #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
558 proc->p_sigctx.ps_sigmask = oldsigmask;
559 #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
560 proc->p_sigwaitmask = oldsigmask;
561 #elif defined(__osf__)
562 u.u_sigmask = oldsigmask;
563 #endif
564
565
566
567
568
569 if (xfs_onq(this_message)) {
570 xfs_outq(this_message);
571 }
572 if (xfs_onq(this_process)) {
573 xfs_outq(this_process);
574 }
575 ret = this_process->error_or_size;
576
577 NNPFSDEB(XDEBMSG, ("xfs_message_rpc this_process->error_or_size = %d\n",
578 this_process->error_or_size));
579 NNPFSDEB(XDEBMSG, ("xfs_message_rpc opcode ((xfs_message_wakeup*)(this_process->message))->error = %d\n", ((struct xfs_message_wakeup *) (this_process->message))->error));
580
581 bcopy(msg, message, size);
582
583 xfs_free(this_message, sizeof(*this_message), M_NNPFS_LINK);
584 xfs_free(this_process, sizeof(*this_process), M_NNPFS_LINK);
585 xfs_free(msg, size, M_NNPFS_MSG);
586
587 return ret;
588 }
589
590
591
592
593
594
595 int
596 xfs_message_receive(int fd,
597 struct xfs_message_header *message,
598 u_int size,
599 d_thread_t *p)
600 {
601 NNPFSDEB(XDEBMSG, ("xfs_message_receive opcode = %d\n", message->opcode));
602
603
604 switch (message->opcode) {
605 case NNPFS_MSG_WAKEUP:
606 return xfs_message_wakeup(fd,
607 (struct xfs_message_wakeup *) message,
608 message->size,
609 p);
610 case NNPFS_MSG_WAKEUP_DATA:
611 return xfs_message_wakeup_data(fd,
612 (struct xfs_message_wakeup_data *) message,
613 message->size,
614 p);
615 case NNPFS_MSG_INSTALLROOT:
616 return xfs_message_installroot(fd,
617 (struct xfs_message_installroot *) message,
618 message->size,
619 p);
620 case NNPFS_MSG_INSTALLNODE:
621 return xfs_message_installnode(fd,
622 (struct xfs_message_installnode *) message,
623 message->size,
624 p);
625 case NNPFS_MSG_INSTALLATTR:
626 return xfs_message_installattr(fd,
627 (struct xfs_message_installattr *) message,
628 message->size,
629 p);
630 case NNPFS_MSG_INSTALLDATA:
631 return xfs_message_installdata(fd,
632 (struct xfs_message_installdata *) message,
633 message->size,
634 p);
635 case NNPFS_MSG_INVALIDNODE:
636 return xfs_message_invalidnode(fd,
637 (struct xfs_message_invalidnode *) message,
638 message->size,
639 p);
640 case NNPFS_MSG_UPDATEFID:
641 return xfs_message_updatefid(fd,
642 (struct xfs_message_updatefid *)message,
643 message->size,
644 p);
645 case NNPFS_MSG_GC_NODES:
646 return xfs_message_gc_nodes(fd,
647 (struct xfs_message_gc_nodes *)message,
648 message->size,
649 p);
650 case NNPFS_MSG_VERSION:
651 return xfs_message_version(fd,
652 (struct xfs_message_version *)message,
653 message->size,
654 p);
655 default:
656 printf("NNPFS PANIC Warning xfs_dev: Unknown message opcode == %d\n",
657 message->opcode);
658 return EINVAL;
659 }
660 }
661
662 int
663 xfs_message_wakeup(int fd,
664 struct xfs_message_wakeup *message,
665 u_int size,
666 d_thread_t *p)
667 {
668 struct xfs_channel *chan = &xfs_channel[fd];
669 struct xfs_link *sleepq = &chan->sleepq;
670 struct xfs_link *t = chan->sleepq.next;
671
672 NNPFSDEB(XDEBMSG, ("xfs_message_wakeup error: %d\n", message->error));
673
674 for (; t != sleepq; t = t->next)
675 if (t->message->sequence_num == message->sleepers_sequence_num) {
676 if (t->message->size < size) {
677 printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
678 t->error_or_size = ENOMEM;
679 } else
680 bcopy(message, t->message, size);
681
682 wakeup((caddr_t) t);
683 break;
684 }
685
686 return 0;
687 }
688
689 int
690 xfs_message_wakeup_data(int fd,
691 struct xfs_message_wakeup_data * message,
692 u_int size,
693 d_thread_t *p)
694 {
695 struct xfs_channel *chan = &xfs_channel[fd];
696 struct xfs_link *sleepq = &chan->sleepq;
697 struct xfs_link *t = chan->sleepq.next;
698
699 NNPFSDEB(XDEBMSG, ("xfs_message_wakeup_data error: %d\n", message->error));
700
701 for (; t != sleepq; t = t->next)
702 if (t->message->sequence_num == message->sleepers_sequence_num) {
703 if (t->message->size < size) {
704 printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
705 t->error_or_size = ENOMEM;
706 } else
707 bcopy(message, t->message, size);
708 wakeup((caddr_t) t);
709 break;
710 }
711 return 0;
712 }
713
714
715
716
717 int
718 xfs_uprintf_device(void)
719 {
720 #if 0
721 int i;
722
723 for (i = 0; i < NNNPFS; i++) {
724 uprintf("xfs_channel[%d] = {\n", i);
725 uprintf("messageq.next = %lx ", xfs_channel[i].messageq.next);
726 uprintf("messageq.prev = %lx ", xfs_channel[i].messageq.prev);
727 uprintf("sleepq.next = %lx ", xfs_channel[i].sleepq.next);
728 uprintf("sleepq.prev = %lx ", xfs_channel[i].sleepq.prev);
729 uprintf("nsequence = %d status = %d\n",
730 xfs_channel[i].nsequence,
731 xfs_channel[i].status);
732 uprintf("}\n");
733 }
734 #endif
735 return 0;
736 }