1 /* When a needed block is not in the cache, it must be fetched from the disk.
2 * Special character files also require I/O. The routines for these are here.
4 * The entry points in this file are:
5 * dev_open: FS opens a device
6 * dev_close: FS closes a device
7 * dev_io: FS does a read or write on a device
8 * dev_status: FS processes callback request alert
9 * gen_opcl: generic call to a task to perform an open/close
10 * gen_io: generic call to a task to perform an I/O operation
11 * no_dev: open/close processing for devices that don't exist
12 * no_dev_io: i/o processing for devices that don't exist
13 * tty_opcl: perform tty-specific processing for open/close
14 * ctty_opcl: perform controlling-tty-specific processing for open/close
15 * ctty_io: perform controlling-tty-specific processing for I/O
16 * do_ioctl: perform the IOCTL system call
17 * do_setsid: perform the SETSID system call (FS side)
23 #include <minix/callnr.h>
24 #include <minix/com.h>
25 #include <minix/endpoint.h>
26 #include <minix/ioctl.h>
27 #include <minix/u64.h>
31 #include <minix/vfsif.h>
36 #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
38 FORWARD
_PROTOTYPE( int safe_io_conversion
, (endpoint_t
,
39 cp_grant_id_t
*, int *, cp_grant_id_t
*, int, endpoint_t
*,
40 void **, int *, vir_bytes
, off_t
*));
41 FORWARD
_PROTOTYPE( void safe_io_cleanup
, (cp_grant_id_t
, cp_grant_id_t
*,
45 PRIVATE
int dummyproc
;
48 /*===========================================================================*
50 *===========================================================================*/
51 PUBLIC
int dev_open(dev
, proc
, flags
)
52 dev_t dev
; /* device to open */
53 int proc
; /* process to open for */
54 int flags
; /* mode bits and flags */
59 /* Determine the major device number call the device class specific
60 * open/close routine. (This is the only routine that must check the
61 * device number for being in range. All others can trust this check.)
63 major
= (dev
>> MAJOR
) & BYTE
;
64 if (major
>= NR_DEVICES
) major
= 0;
66 if (dp
->dmap_driver
== NONE
)
68 r
= (*dp
->dmap_opcl
)(DEV_OPEN
, dev
, proc
, flags
);
69 if (r
== SUSPEND
) panic(__FILE__
,"suspend on open from", dp
->dmap_driver
);
74 /*===========================================================================*
76 *===========================================================================*/
77 PUBLIC
void dev_close(dev
)
78 dev_t dev
; /* device to close */
80 /* See if driver is roughly valid. */
81 if (dmap
[(dev
>> MAJOR
)].dmap_driver
== NONE
) {
84 (void) (*dmap
[(dev
>> MAJOR
) & BYTE
].dmap_opcl
)(DEV_CLOSE
, dev
, 0, 0);
87 /*===========================================================================*
89 *===========================================================================*/
90 endpoint_t
suspended_ep(endpoint_t driver
, cp_grant_id_t g
)
92 /* A process is suspended on a driver for which FS issued
93 * a grant. Find out which process it was.
96 for (rfp
= &fproc
[0]; rfp
< &fproc
[NR_PROCS
]; rfp
++) {
97 if(rfp
->fp_pid
== PID_FREE
)
99 if(rfp
->fp_suspended
== SUSPENDED
&&
100 rfp
->fp_task
== -driver
&& rfp
->fp_grant
== g
) {
101 return rfp
->fp_endpoint
;
108 /*===========================================================================*
110 *===========================================================================*/
111 PUBLIC
void dev_status(message
*m
)
117 for(d
= 0; d
< NR_DEVICES
; d
++)
118 if (dmap
[d
].dmap_driver
!= NONE
&&
119 dmap
[d
].dmap_driver
== m
->m_source
)
127 st
.m_type
= DEV_STATUS
;
128 if ((r
=sendrec(m
->m_source
, &st
)) != OK
) {
129 printf("DEV_STATUS failed to %d: %d\n", m
->m_source
, r
);
130 if (r
== EDEADSRCDST
) return;
131 if (r
== EDSTDIED
) return;
132 if (r
== ESRCDIED
) return;
133 panic(__FILE__
,"couldn't sendrec for DEV_STATUS", r
);
138 endpt
= st
.REP_ENDPT
;
139 if(endpt
== FS_PROC_NR
) {
140 endpt
= suspended_ep(m
->m_source
,
143 printf("FS: proc with "
144 "grant %d from %d not found (revive)\n",
150 revive(endpt
, st
.REP_STATUS
);
153 select_notified(d
, st
.DEV_MINOR
,
157 printf("FS: unrecognized reply %d to "
158 "DEV_STATUS\n", st
.m_type
);
169 /*===========================================================================*
170 * safe_io_conversion *
171 *===========================================================================*/
172 PRIVATE
int safe_io_conversion(driver
, gid
, op
, gids
, gids_size
,
173 io_ept
, buf
, vec_grants
, bytes
, pos
)
185 int access
= 0, size
;
188 static iovec_t new_iovec
[NR_IOREQS
];
190 /* Number of grants allocated in vector I/O. */
193 /* Driver can handle it - change request to a safe one. */
195 *gid
= GRANT_INVALID
;
200 /* Change to safe op. */
201 *op
= *op
== VFS_DEV_READ
? DEV_READ_S
: DEV_WRITE_S
;
203 if((*gid
=cpf_grant_magic(driver
, *io_ept
,
204 (vir_bytes
) *buf
, bytes
,
205 *op
== DEV_READ_S
? CPF_WRITE
: CPF_READ
)) < 0) {
207 "cpf_grant_magic of buffer failed\n", NO_NUM
);
212 case VFS_DEV_SCATTER
:
213 /* Change to safe op. */
214 *op
= *op
== VFS_DEV_GATHER
?
215 DEV_GATHER_S
: DEV_SCATTER_S
;
217 /* Grant access to my new i/o vector. */
218 if((*gid
= cpf_grant_direct(driver
,
219 (vir_bytes
) new_iovec
, bytes
* sizeof(iovec_t
),
220 CPF_READ
| CPF_WRITE
)) < 0) {
222 "cpf_grant_direct of vector failed", NO_NUM
);
224 v
= (iovec_t
*) *buf
;
225 /* Grant access to i/o buffers. */
226 for(j
= 0; j
< bytes
; j
++) {
228 panic(__FILE__
, "vec too big", bytes
);
229 new_iovec
[j
].iov_addr
= gids
[j
] =
230 cpf_grant_direct(driver
, (vir_bytes
)
231 v
[j
].iov_addr
, v
[j
].iov_size
,
232 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
233 if(!GRANT_VALID(gids
[j
])) {
234 panic(__FILE__
, "grant to iovec buf failed",
237 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
241 /* Set user's vector to the new one. */
245 *pos
= *io_ept
; /* Old endpoint in POSITION field. */
247 if(_MINIX_IOCTL_IOR(m_in
.REQUEST
)) access
|= CPF_WRITE
;
248 if(_MINIX_IOCTL_IOW(m_in
.REQUEST
)) access
|= CPF_READ
;
249 if(_MINIX_IOCTL_BIG(m_in
.REQUEST
))
250 size
= _MINIX_IOCTL_SIZE_BIG(m_in
.REQUEST
);
252 size
= _MINIX_IOCTL_SIZE(m_in
.REQUEST
);
255 /* Do this even if no I/O happens with the ioctl, in
256 * order to disambiguate requests with DEV_IOCTL_S.
258 if((*gid
=cpf_grant_magic(driver
, *io_ept
,
259 (vir_bytes
) *buf
, size
, access
)) < 0) {
261 "cpf_grant_magic failed (ioctl)\n",
269 panic(__FILE__
,"safe_io_conversion: unknown operation",
273 /* If we have converted to a safe operation, I/O
274 * endpoint becomes FS if it wasn't already.
276 if(GRANT_VALID(*gid
)) {
277 *io_ept
= FS_PROC_NR
;
281 /* Not converted to a safe operation (because there is no
282 * copying involved in this operation).
287 /*===========================================================================*
289 *===========================================================================*/
290 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
295 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
300 for(j
= 0; j
< gids_size
; j
++)
306 /*===========================================================================*
308 *===========================================================================*/
309 PUBLIC
int dev_bio(op
, dev
, proc_e
, buf
, pos
, bytes
)
310 int op
; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
311 dev_t dev
; /* major-minor device number */
312 int proc_e
; /* in whose address space is buf? */
313 void *buf
; /* virtual address of the buffer */
314 off_t pos
; /* byte position */
315 int bytes
; /* how many bytes to transfer */
317 /* Read or write from a device. The parameter 'dev' tells which one. */
322 cp_grant_id_t gid
= GRANT_INVALID
;
325 /* Determine task dmap. */
326 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
328 /* The io vector copying relies on this I/O being for FS itself. */
329 if(proc_e
!= FS_PROC_NR
)
330 panic(__FILE__
, "doing dev_bio for non-self", proc_e
);
336 static cp_grant_id_t gids
[NR_IOREQS
];
337 cp_grant_id_t gid
= GRANT_INVALID
;
340 /* See if driver is roughly valid. */
341 if (dp
->dmap_driver
== NONE
) {
342 printf("FS: dev_io: no driver for dev %x\n", dev
);
346 /* By default, these are right. */
351 /* Convert parameters to 'safe mode'. */
353 safe
= safe_io_conversion(dp
->dmap_driver
, &gid
,
354 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
355 &vec_grants
, bytes
, &pos
);
357 /* Set up rest of the message. */
358 if(safe
) m
.IO_GRANT
= (char *) gid
;
361 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
367 (*dp
->dmap_io
)(dp
->dmap_driver
, &m
);
369 /* As block I/O never SUSPENDs, safe cleanup must be done whether
370 * the I/O succeeded or not.
372 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
374 if(dp
->dmap_driver
== NONE
) {
375 /* Driver has vanished. Wait for a new one. */
378 r
= receive(RS_PROC_NR
, &m
);
382 "dev_bio: unable to receive from RS",
385 if (m
.m_type
== DEVCTL
)
387 r
= fs_devctl(m
.ctl_req
, m
.dev_nr
, m
.driver_nr
,
388 m
.dev_style
, m
.m_force
);
393 "dev_bio: got message from RS, type",
397 r
= send(RS_PROC_NR
, &m
);
401 "dev_bio: unable to send to RS",
404 if (dp
->dmap_driver
!= NONE
)
407 printf("dev_bio: trying new driver\n");
411 /* Task has completed. See if call completed. */
412 if (m
.REP_STATUS
== SUSPEND
) {
413 panic(__FILE__
, "dev_bio: driver returned SUSPEND", NO_NUM
);
416 if(buf
!= buf_used
) {
417 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
420 return(m
.REP_STATUS
);
424 /*===========================================================================*
426 *===========================================================================*/
427 PUBLIC
int dev_io(op
, dev
, proc_e
, buf
, posX
, bytes
, flags
)
428 int op
; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
429 dev_t dev
; /* major-minor device number */
430 int proc_e
; /* in whose address space is buf? */
431 void *buf
; /* virtual address of the buffer */
432 u64_t posX
; /* byte position */
433 int bytes
; /* how many bytes to transfer */
434 int flags
; /* special flags, like O_NONBLOCK */
436 /* Read or write from a device. The parameter 'dev' tells which one. */
440 cp_grant_id_t gid
= GRANT_INVALID
;
441 static cp_grant_id_t gids
[NR_IOREQS
];
442 int vec_grants
= 0, orig_op
, safe
;
446 if (ex64hi(posX
) != 0)
447 panic(__FILE__
, "dev_io: postition too high", NO_NUM
);
450 /* Determine task dmap. */
451 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
454 /* See if driver is roughly valid. */
455 if (dp
->dmap_driver
== NONE
) {
456 printf("FS: dev_io: no driver for dev %x\n", dev
);
460 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
461 printf("FS: dev_io: old driver for dev %x (%d)\n",
462 dev
, dp
->dmap_driver
);
466 /* By default, these are right. */
467 dev_mess
.IO_ENDPT
= proc_e
;
468 dev_mess
.ADDRESS
= buf
;
470 /* Convert DEV_* to DEV_*_S variants. */
472 safe
= safe_io_conversion(dp
->dmap_driver
, &gid
,
473 &op
, gids
, NR_IOREQS
, &dev_mess
.IO_ENDPT
, &buf_used
,
474 &vec_grants
, bytes
, &pos
);
477 panic(__FILE__
,"dev_io: safe_io_conversion changed buffer", NO_NUM
);
479 /* If the safe conversion was done, set the ADDRESS to
482 if(safe
) dev_mess
.IO_GRANT
= (char *) gid
;
484 /* Set up the rest of the message passed to task. */
485 dev_mess
.m_type
= op
;
486 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
487 dev_mess
.POSITION
= pos
;
488 dev_mess
.COUNT
= bytes
;
489 dev_mess
.HIGHPOS
= 0;
491 /* This will be used if the i/o is suspended. */
492 ioproc
= dev_mess
.IO_ENDPT
;
495 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
497 if(dp
->dmap_driver
== NONE
) {
498 /* Driver has vanished. */
499 printf("Driver gone?\n");
500 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
504 /* Task has completed. See if call completed. */
505 if (dev_mess
.REP_STATUS
== SUSPEND
) {
507 panic(__FILE__
,"SUSPEND on vectored i/o", NO_NUM
);
509 /* fp is uninitialized at init time. */
511 panic(__FILE__
,"SUSPEND on NULL fp", NO_NUM
);
513 if (flags
& O_NONBLOCK
) {
514 /* Not supposed to block. */
515 dev_mess
.m_type
= CANCEL
;
516 dev_mess
.IO_ENDPT
= ioproc
;
517 dev_mess
.IO_GRANT
= (char *) gid
;
519 /* This R_BIT/W_BIT check taken from suspend()/unpause()
520 * logic. Mode is expected in the COUNT field.
523 if(call_nr
== READ
) dev_mess
.COUNT
= R_BIT
;
524 else if(call_nr
== WRITE
) dev_mess
.COUNT
= W_BIT
;
525 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
526 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
527 if (dev_mess
.REP_STATUS
== EINTR
) dev_mess
.REP_STATUS
= EAGAIN
;
530 suspend(dp
->dmap_driver
);
531 assert(!GRANT_VALID(fp
->fp_grant
));
532 fp
->fp_grant
= gid
; /* revoke this when unsuspended. */
533 fp
->fp_ioproc
= ioproc
;
538 /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
539 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
541 return(dev_mess
.REP_STATUS
);
544 /*===========================================================================*
546 *===========================================================================*/
547 PUBLIC
int gen_opcl(op
, dev
, proc_e
, flags
)
548 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
549 dev_t dev
; /* device to open or close */
550 int proc_e
; /* process to open/close for */
551 int flags
; /* mode bits and flags */
553 /* Called from the dmap struct in table.c on opens & closes of special files.*/
557 /* Determine task dmap. */
558 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
560 dev_mess
.m_type
= op
;
561 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
562 dev_mess
.IO_ENDPT
= proc_e
;
563 dev_mess
.COUNT
= flags
;
565 if (dp
->dmap_driver
== NONE
) {
566 printf("FS: gen_opcl: no driver for dev %x\n", dev
);
571 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
573 return(dev_mess
.REP_STATUS
);
576 /*===========================================================================*
578 *===========================================================================*/
579 PUBLIC
int tty_opcl(op
, dev
, proc_e
, flags
)
580 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
581 dev_t dev
; /* device to open or close */
582 int proc_e
; /* process to open/close for */
583 int flags
; /* mode bits and flags */
585 /* This procedure is called from the dmap struct on tty open/close. */
588 register struct fproc
*rfp
;
590 /* Add O_NOCTTY to the flags if this process is not a session leader, or
591 * if it already has a controlling tty, or if it is someone elses
594 if (!fp
->fp_sesldr
|| fp
->fp_tty
!= 0) {
597 for (rfp
= &fproc
[0]; rfp
< &fproc
[NR_PROCS
]; rfp
++) {
598 if(rfp
->fp_pid
== PID_FREE
) continue;
599 if (rfp
->fp_tty
== dev
) flags
|= O_NOCTTY
;
603 r
= gen_opcl(op
, dev
, proc_e
, flags
);
605 /* Did this call make the tty the controlling tty? */
613 /*===========================================================================*
615 *===========================================================================*/
616 PUBLIC
int ctty_opcl(op
, dev
, proc_e
, flags
)
617 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
618 dev_t dev
; /* device to open or close */
619 int proc_e
; /* process to open/close for */
620 int flags
; /* mode bits and flags */
622 /* This procedure is called from the dmap struct in table.c on opening/closing
623 * /dev/tty, the magic device that translates to the controlling tty.
626 return(fp
->fp_tty
== 0 ? ENXIO
: OK
);
629 /*===========================================================================*
631 *===========================================================================*/
632 PUBLIC
void pm_setsid(proc_e
)
635 /* Perform the FS side of the SETSID call, i.e. get rid of the controlling
636 * terminal of a process, and make the process a session leader.
638 register struct fproc
*rfp
;
641 /* Make the process a session leader with no controlling tty. */
642 okendpt(proc_e
, &slot
);
644 rfp
->fp_sesldr
= TRUE
;
648 /*===========================================================================*
650 *===========================================================================*/
651 PUBLIC
int do_ioctl()
653 /* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
656 register struct vnode
*vp
;
659 if ( (f
= get_filp(m_in
.ls_fd
)) == NIL_FILP
) return(err_code
);
660 vp
= f
->filp_vno
; /* get vnode pointer */
661 if ( (vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
662 && (vp
->v_mode
& I_TYPE
) != I_BLOCK_SPECIAL
) return(ENOTTY
);
663 dev
= (dev_t
) vp
->v_sdev
;
665 return (dev_io(VFS_DEV_IOCTL
, dev
, who_e
, m_in
.ADDRESS
, cvu64(0),
666 m_in
.REQUEST
, f
->filp_flags
));
669 /*===========================================================================*
671 *===========================================================================*/
672 PUBLIC
int gen_io(task_nr
, mess_ptr
)
673 int task_nr
; /* which task to call */
674 message
*mess_ptr
; /* pointer to message for task */
676 /* All file system I/O ultimately comes down to I/O on major/minor device
677 * pairs. These lead to calls on the following routines via the dmap table.
682 proc_e
= mess_ptr
->IO_ENDPT
;
684 r
= sendrec(task_nr
, mess_ptr
);
686 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
687 printf("fs: dead driver %d\n", task_nr
);
688 dmap_unmap_by_endpt(task_nr
);
692 printf("fs: ELOCKED talking to %d\n", task_nr
);
695 panic(__FILE__
,"call_task: can't send/receive", r
);
698 /* Did the process we did the sendrec() for get a result? */
699 if (mess_ptr
->REP_ENDPT
!= proc_e
) {
701 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
705 mess_ptr
->REP_ENDPT
);
712 /*===========================================================================*
714 *===========================================================================*/
715 PUBLIC
int ctty_io(task_nr
, mess_ptr
)
716 int task_nr
; /* not used - for compatibility with dmap_t */
717 message
*mess_ptr
; /* pointer to message for task */
719 /* This routine is only called for one device, namely /dev/tty. Its job
720 * is to change the message to use the controlling terminal, instead of the
721 * major/minor pair for /dev/tty itself.
726 if (fp
->fp_tty
== 0) {
727 /* No controlling tty present anymore, return an I/O error. */
728 mess_ptr
->REP_STATUS
= EIO
;
730 /* Substitute the controlling terminal device. */
731 dp
= &dmap
[(fp
->fp_tty
>> MAJOR
) & BYTE
];
732 mess_ptr
->DEVICE
= (fp
->fp_tty
>> MINOR
) & BYTE
;
734 if (dp
->dmap_driver
== NONE
) {
735 printf("FS: ctty_io: no driver for dev\n");
739 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
740 printf("FS: ctty_io: old driver %d\n",
745 (*dp
->dmap_io
)(dp
->dmap_driver
, mess_ptr
);
751 /*===========================================================================*
753 *===========================================================================*/
754 PUBLIC
int no_dev(op
, dev
, proc
, flags
)
755 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
756 dev_t dev
; /* device to open or close */
757 int proc
; /* process to open/close for */
758 int flags
; /* mode bits and flags */
760 /* Called when opening a nonexistent device. */
764 /*===========================================================================*
766 *===========================================================================*/
767 PUBLIC
int no_dev_io(int proc
, message
*m
)
769 /* Called when doing i/o on a nonexistent device. */
770 printf("VFS: I/O on unmapped device number\n");
776 /*===========================================================================*
778 *===========================================================================*/
779 PUBLIC
int clone_opcl(op
, dev
, proc_e
, flags
)
780 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
781 dev_t dev
; /* device to open or close */
782 int proc_e
; /* process to open/close for */
783 int flags
; /* mode bits and flags */
785 /* Some devices need special processing upon open. Such a device is "cloned",
786 * i.e. on a succesful open it is replaced by a new device with a new unique
787 * minor device number. This new device number identifies a new object (such
788 * as a new network connection) that has been allocated within a task.
794 /* Determine task dmap. */
795 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
796 minor
= (dev
>> MINOR
) & BYTE
;
798 dev_mess
.m_type
= op
;
799 dev_mess
.DEVICE
= minor
;
800 dev_mess
.IO_ENDPT
= proc_e
;
801 dev_mess
.COUNT
= flags
;
804 if (dp
->dmap_driver
== NONE
) {
805 printf("FS: clone_opcl: no driver for dev %x\n", dev
);
809 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
810 printf("FS: clone_opcl: old driver for dev %x (%d)\n",
811 dev
, dp
->dmap_driver
);
816 r
= (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
820 if (op
== DEV_OPEN
&& dev_mess
.REP_STATUS
>= 0) {
821 if (dev_mess
.REP_STATUS
!= minor
) {
825 struct clone_opcl_req req
;
826 struct node_details res
;
827 /* A new minor device number has been returned.
828 * Request root FS to create a temporary device file to hold it.
831 /* Device number of the new device. */
832 dev
= (dev
& ~(BYTE
<< MINOR
)) | (dev_mess
.REP_STATUS
<< MINOR
);
834 /* Fill in request */
835 req
.fs_e
= ROOT_FS_E
;
839 if ((r
= req_clone_opcl(&req
, &res
)) != OK
) {
840 (void) clone_opcl(DEV_CLOSE
, dev
, proc_e
, 0);
844 /* Drop old node and use the new values */
845 vp
= fp
->fp_filp
[m_in
.fd
]->filp_vno
;
848 if ((vp
= get_free_vnode(__FILE__
, __LINE__
)) == NIL_VNODE
) {
849 printf("VFSclone_opcl: failed to get a free vnode..\n");
850 vp
= fp
->fp_filp
[m_in
.fd
]->filp_vno
;
853 vp
->v_fs_e
= res
.fs_e
;
854 if ((vmp
= find_vmnt(vp
->v_fs_e
)) == NIL_VMNT
)
855 printf("VFSclone_opcl: no vmnt found\n");
858 vp
->v_dev
= vmp
->m_dev
;
860 vp
->v_inode_nr
= res
.inode_nr
;
861 vp
->v_mode
= res
.fmode
;
865 fp
->fp_filp
[m_in
.fd
]->filp_vno
= vp
;
867 dev_mess
.REP_STATUS
= OK
;
869 return(dev_mess
.REP_STATUS
);
872 /*===========================================================================*
874 *===========================================================================*/
875 PUBLIC
void dev_up(int maj
)
877 /* A new device driver has been mapped in. This function
878 * checks if any filesystems are mounted on it, and if so,
879 * dev_open()s them so the filesystem can be reused.
886 /* Open a device once for every filp that's opened on it,
887 * and once for every filesystem mounted from it.
889 new_driver_e
= dmap
[maj
].dmap_driver
;
891 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
) {
893 if (vmp
->m_dev
== NO_DEV
) continue;
894 if ( ((vmp
->m_dev
>> MAJOR
) & BYTE
) != maj
) continue;
895 minor
= ((vmp
->m_dev
>> MINOR
) & BYTE
);
897 printf("VFS: re-opening dev: %d/%d\n", maj
, minor
);
899 if ((r
= dev_open(vmp
->m_dev
, FS_PROC_NR
,
900 vmp
->m_flags
? R_BIT
: (R_BIT
|W_BIT
))) != OK
) {
901 printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
905 /* Send new driver endpoint */
906 printf("VFS: sending new driver for dev: %d, endpoint: %d, FS_e: %d\n",
907 vmp
->m_dev
, new_driver_e
, vmp
->m_fs_e
);
909 if (OK
!= req_newdriver(vmp
->m_fs_e
, vmp
->m_dev
, new_driver_e
))
910 printf("VFSdev_up: error sending new driver endpoint. FS_e: %d req_nr: %d\n",
911 vmp
->m_fs_e
, REQ_NEW_DRIVER
);
913 vmp
->m_driver_e
= new_driver_e
;
916 for (fp
= filp
; fp
< &filp
[NR_FILPS
]; fp
++) {
920 if(fp
->filp_count
< 1 || !(vp
= fp
->filp_vno
)) continue;
921 if(((vp
->v_sdev
>> MAJOR
) & BYTE
) != maj
) continue;
922 if(!(vp
->v_mode
& (I_BLOCK_SPECIAL
|I_CHAR_SPECIAL
))) continue;
924 minor
= ((vp
->v_sdev
>> MINOR
) & BYTE
);
926 printf("VFS: reopening special %d/%d..\n", maj
, minor
);
928 if((r
= dev_open(vp
->v_sdev
, FS_PROC_NR
,
929 vp
->v_mode
& (R_BIT
|W_BIT
))) != OK
) {
931 /* This function will set the fp_filp[]s of processes
932 * holding that fp to NULL, but _not_ clear
933 * fp_filp_inuse, so that fd can't be recycled until
937 if(n
!= fp
->filp_count
)
938 printf("VFS: warning: invalidate/count "
939 "discrepancy (%d, %d)\n", n
, fp
->filp_count
);
941 printf("VFS: file on dev %d/%d re-open failed: %d; "
942 "invalidated %d fd's.\n", maj
, minor
, r
, n
);