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>
30 #include <minix/vfsif.h>
35 #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
37 FORWARD
_PROTOTYPE( int safe_io_conversion
, (endpoint_t
,
38 cp_grant_id_t
*, int *, cp_grant_id_t
*, int, endpoint_t
*,
39 void **, int *, vir_bytes
, off_t
*));
40 FORWARD
_PROTOTYPE( void safe_io_cleanup
, (cp_grant_id_t
, cp_grant_id_t
*,
44 PRIVATE
int dummyproc
;
47 /*===========================================================================*
49 *===========================================================================*/
50 PUBLIC
int dev_open(dev
, proc
, flags
)
51 dev_t dev
; /* device to open */
52 int proc
; /* process to open for */
53 int flags
; /* mode bits and flags */
58 /* Determine the major device number call the device class specific
59 * open/close routine. (This is the only routine that must check the
60 * device number for being in range. All others can trust this check.)
62 major
= (dev
>> MAJOR
) & BYTE
;
63 if (major
>= NR_DEVICES
) major
= 0;
65 if (dp
->dmap_driver
== NONE
)
67 r
= (*dp
->dmap_opcl
)(DEV_OPEN
, dev
, proc
, flags
);
68 if (r
== SUSPEND
) panic(__FILE__
,"suspend on open from", dp
->dmap_driver
);
73 /*===========================================================================*
75 *===========================================================================*/
76 PUBLIC
void dev_close(dev
)
77 dev_t dev
; /* device to close */
79 /* See if driver is roughly valid. */
80 if (dmap
[(dev
>> MAJOR
)].dmap_driver
== NONE
) {
83 (void) (*dmap
[(dev
>> MAJOR
) & BYTE
].dmap_opcl
)(DEV_CLOSE
, dev
, 0, 0);
86 /*===========================================================================*
88 *===========================================================================*/
89 endpoint_t
suspended_ep(endpoint_t driver
, cp_grant_id_t g
)
91 /* A process is suspended on a driver for which FS issued
92 * a grant. Find out which process it was.
95 for (rfp
= &fproc
[0]; rfp
< &fproc
[NR_PROCS
]; rfp
++) {
96 if(rfp
->fp_pid
== PID_FREE
)
98 if(rfp
->fp_suspended
== SUSPENDED
&&
99 rfp
->fp_task
== -driver
&& rfp
->fp_grant
== g
) {
100 return rfp
->fp_endpoint
;
107 /*===========================================================================*
109 *===========================================================================*/
110 PUBLIC
void dev_status(message
*m
)
116 for(d
= 0; d
< NR_DEVICES
; d
++)
117 if (dmap
[d
].dmap_driver
!= NONE
&&
118 dmap
[d
].dmap_driver
== m
->m_source
)
126 st
.m_type
= DEV_STATUS
;
127 if ((r
=sendrec(m
->m_source
, &st
)) != OK
) {
128 printf("DEV_STATUS failed to %d: %d\n", m
->m_source
, r
);
129 if (r
== EDEADSRCDST
) return;
130 if (r
== EDSTDIED
) return;
131 if (r
== ESRCDIED
) return;
132 panic(__FILE__
,"couldn't sendrec for DEV_STATUS", r
);
137 endpt
= st
.REP_ENDPT
;
138 if(endpt
== FS_PROC_NR
) {
139 endpt
= suspended_ep(m
->m_source
,
142 printf("FS: proc with "
143 "grant %d from %d not found (revive)\n",
149 revive(endpt
, st
.REP_STATUS
);
152 select_notified(d
, st
.DEV_MINOR
,
156 printf("FS: unrecognized reply %d to "
157 "DEV_STATUS\n", st
.m_type
);
168 /*===========================================================================*
169 * safe_io_conversion *
170 *===========================================================================*/
171 PRIVATE
int safe_io_conversion(driver
, gid
, op
, gids
, gids_size
,
172 io_ept
, buf
, vec_grants
, bytes
, pos
)
184 int access
= 0, size
;
187 static iovec_t new_iovec
[NR_IOREQS
];
189 /* Number of grants allocated in vector I/O. */
192 /* Driver can handle it - change request to a safe one. */
194 *gid
= GRANT_INVALID
;
199 /* Change to safe op. */
200 *op
= *op
== DEV_READ
? DEV_READ_S
: DEV_WRITE_S
;
202 if((*gid
=cpf_grant_magic(driver
, *io_ept
,
203 (vir_bytes
) *buf
, bytes
,
204 *op
== DEV_READ_S
? CPF_WRITE
: CPF_READ
)) < 0) {
206 "cpf_grant_magic of buffer failed\n", NO_NUM
);
212 /* Change to safe op. */
213 *op
= *op
== DEV_GATHER
? DEV_GATHER_S
: DEV_SCATTER_S
;
215 /* Grant access to my new i/o vector. */
216 if((*gid
= cpf_grant_direct(driver
,
217 (vir_bytes
) new_iovec
, bytes
* sizeof(iovec_t
),
218 CPF_READ
| CPF_WRITE
)) < 0) {
220 "cpf_grant_direct of vector failed", NO_NUM
);
222 v
= (iovec_t
*) *buf
;
223 /* Grant access to i/o buffers. */
224 for(j
= 0; j
< bytes
; j
++) {
226 panic(__FILE__
, "vec too big", bytes
);
227 new_iovec
[j
].iov_addr
= gids
[j
] =
228 cpf_grant_direct(driver
, (vir_bytes
)
229 v
[j
].iov_addr
, v
[j
].iov_size
,
230 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
231 if(!GRANT_VALID(gids
[j
])) {
232 panic(__FILE__
, "grant to iovec buf failed",
235 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
239 /* Set user's vector to the new one. */
243 *pos
= *io_ept
; /* Old endpoint in POSITION field. */
245 if(_MINIX_IOCTL_IOR(m_in
.REQUEST
)) access
|= CPF_WRITE
;
246 if(_MINIX_IOCTL_IOW(m_in
.REQUEST
)) access
|= CPF_READ
;
247 if(_MINIX_IOCTL_BIG(m_in
.REQUEST
))
248 size
= _MINIX_IOCTL_SIZE_BIG(m_in
.REQUEST
);
250 size
= _MINIX_IOCTL_SIZE(m_in
.REQUEST
);
253 /* Do this even if no I/O happens with the ioctl, in
254 * order to disambiguate requests with DEV_IOCTL_S.
256 if((*gid
=cpf_grant_magic(driver
, *io_ept
,
257 (vir_bytes
) *buf
, size
, access
)) < 0) {
259 "cpf_grant_magic failed (ioctl)\n",
264 /* If we have converted to a safe operation, I/O
265 * endpoint becomes FS if it wasn't already.
267 if(GRANT_VALID(*gid
)) {
268 *io_ept
= FS_PROC_NR
;
272 /* Not converted to a safe operation (because there is no
273 * copying involved in this operation).
278 /*===========================================================================*
280 *===========================================================================*/
281 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
286 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
291 for(j
= 0; j
< gids_size
; j
++)
297 /*===========================================================================*
299 *===========================================================================*/
300 PUBLIC
int dev_bio(op
, dev
, proc_e
, buf
, pos
, bytes
)
301 int op
; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
302 dev_t dev
; /* major-minor device number */
303 int proc_e
; /* in whose address space is buf? */
304 void *buf
; /* virtual address of the buffer */
305 off_t pos
; /* byte position */
306 int bytes
; /* how many bytes to transfer */
308 /* Read or write from a device. The parameter 'dev' tells which one. */
313 cp_grant_id_t gid
= GRANT_INVALID
;
316 /* Determine task dmap. */
317 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
319 /* The io vector copying relies on this I/O being for FS itself. */
320 if(proc_e
!= FS_PROC_NR
)
321 panic(__FILE__
, "doing dev_bio for non-self", proc_e
);
327 static cp_grant_id_t gids
[NR_IOREQS
];
328 cp_grant_id_t gid
= GRANT_INVALID
;
331 /* See if driver is roughly valid. */
332 if (dp
->dmap_driver
== NONE
) {
333 printf("FS: dev_io: no driver for dev %x\n", dev
);
337 /* By default, these are right. */
342 /* Convert parameters to 'safe mode'. */
344 safe
= safe_io_conversion(dp
->dmap_driver
, &gid
,
345 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
346 &vec_grants
, bytes
, &pos
);
348 /* Set up rest of the message. */
349 if(safe
) m
.IO_GRANT
= (char *) gid
;
352 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
358 (*dp
->dmap_io
)(dp
->dmap_driver
, &m
);
360 /* As block I/O never SUSPENDs, safe cleanup must be done whether
361 * the I/O succeeded or not.
363 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
365 if(dp
->dmap_driver
== NONE
) {
366 /* Driver has vanished. Wait for a new one. */
369 r
= receive(RS_PROC_NR
, &m
);
373 "dev_bio: unable to receive from RS",
376 if (m
.m_type
== DEVCTL
)
378 r
= fs_devctl(m
.ctl_req
, m
.dev_nr
, m
.driver_nr
,
379 m
.dev_style
, m
.m_force
);
384 "dev_bio: got message from RS, type",
388 r
= send(RS_PROC_NR
, &m
);
392 "dev_bio: unable to send to RS",
395 if (dp
->dmap_driver
!= NONE
)
398 printf("dev_bio: trying new driver\n");
402 /* Task has completed. See if call completed. */
403 if (m
.REP_STATUS
== SUSPEND
) {
404 panic(__FILE__
, "dev_bio: driver returned SUSPEND", NO_NUM
);
407 if(buf
!= buf_used
) {
408 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
411 return(m
.REP_STATUS
);
415 /*===========================================================================*
417 *===========================================================================*/
418 PUBLIC
int dev_io(op
, dev
, proc_e
, buf
, pos
, bytes
, flags
)
419 int op
; /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
420 dev_t dev
; /* major-minor device number */
421 int proc_e
; /* in whose address space is buf? */
422 void *buf
; /* virtual address of the buffer */
423 off_t pos
; /* byte position */
424 int bytes
; /* how many bytes to transfer */
425 int flags
; /* special flags, like O_NONBLOCK */
427 /* Read or write from a device. The parameter 'dev' tells which one. */
430 cp_grant_id_t gid
= GRANT_INVALID
;
431 static cp_grant_id_t gids
[NR_IOREQS
];
432 int vec_grants
= 0, orig_op
, safe
;
436 /* Determine task dmap. */
437 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
440 /* See if driver is roughly valid. */
441 if (dp
->dmap_driver
== NONE
) {
442 printf("FS: dev_io: no driver for dev %x\n", dev
);
446 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
447 printf("FS: dev_io: old driver for dev %x (%d)\n",
448 dev
, dp
->dmap_driver
);
452 /* By default, these are right. */
453 dev_mess
.IO_ENDPT
= proc_e
;
454 dev_mess
.ADDRESS
= buf
;
456 /* Convert DEV_* to DEV_*_S variants. */
458 safe
= safe_io_conversion(dp
->dmap_driver
, &gid
,
459 &op
, gids
, NR_IOREQS
, &dev_mess
.IO_ENDPT
, &buf_used
,
460 &vec_grants
, bytes
, &pos
);
463 panic(__FILE__
,"dev_io: safe_io_conversion changed buffer", NO_NUM
);
465 /* If the safe conversion was done, set the ADDRESS to
468 if(safe
) dev_mess
.IO_GRANT
= (char *) gid
;
470 /* Set up the rest of the message passed to task. */
471 dev_mess
.m_type
= op
;
472 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
473 dev_mess
.POSITION
= pos
;
474 dev_mess
.COUNT
= bytes
;
475 dev_mess
.HIGHPOS
= 0;
477 /* This will be used if the i/o is suspended. */
478 ioproc
= dev_mess
.IO_ENDPT
;
481 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
483 if(dp
->dmap_driver
== NONE
) {
484 /* Driver has vanished. */
485 printf("Driver gone?\n");
486 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
490 /* Task has completed. See if call completed. */
491 if (dev_mess
.REP_STATUS
== SUSPEND
) {
493 panic(__FILE__
,"SUSPEND on vectored i/o", NO_NUM
);
495 /* fp is uninitialized at init time. */
497 panic(__FILE__
,"SUSPEND on NULL fp", NO_NUM
);
499 if (flags
& O_NONBLOCK
) {
500 /* Not supposed to block. */
501 dev_mess
.m_type
= CANCEL
;
502 dev_mess
.IO_ENDPT
= ioproc
;
503 dev_mess
.IO_GRANT
= (char *) gid
;
505 /* This R_BIT/W_BIT check taken from suspend()/unpause()
506 * logic. Mode is expected in the COUNT field.
509 if(call_nr
== READ
) dev_mess
.COUNT
= R_BIT
;
510 else if(call_nr
== WRITE
) dev_mess
.COUNT
= W_BIT
;
511 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
512 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
513 if (dev_mess
.REP_STATUS
== EINTR
) dev_mess
.REP_STATUS
= EAGAIN
;
516 suspend(dp
->dmap_driver
);
517 assert(!GRANT_VALID(fp
->fp_grant
));
518 fp
->fp_grant
= gid
; /* revoke this when unsuspended. */
519 fp
->fp_ioproc
= ioproc
;
524 /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
525 if(safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
527 return(dev_mess
.REP_STATUS
);
530 /*===========================================================================*
532 *===========================================================================*/
533 PUBLIC
int gen_opcl(op
, dev
, proc_e
, flags
)
534 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
535 dev_t dev
; /* device to open or close */
536 int proc_e
; /* process to open/close for */
537 int flags
; /* mode bits and flags */
539 /* Called from the dmap struct in table.c on opens & closes of special files.*/
543 /* Determine task dmap. */
544 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
546 dev_mess
.m_type
= op
;
547 dev_mess
.DEVICE
= (dev
>> MINOR
) & BYTE
;
548 dev_mess
.IO_ENDPT
= proc_e
;
549 dev_mess
.COUNT
= flags
;
551 if (dp
->dmap_driver
== NONE
) {
552 printf("FS: gen_opcl: no driver for dev %x\n", dev
);
557 (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
559 return(dev_mess
.REP_STATUS
);
562 /*===========================================================================*
564 *===========================================================================*/
565 PUBLIC
int tty_opcl(op
, dev
, proc_e
, flags
)
566 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
567 dev_t dev
; /* device to open or close */
568 int proc_e
; /* process to open/close for */
569 int flags
; /* mode bits and flags */
571 /* This procedure is called from the dmap struct on tty open/close. */
574 register struct fproc
*rfp
;
576 /* Add O_NOCTTY to the flags if this process is not a session leader, or
577 * if it already has a controlling tty, or if it is someone elses
580 if (!fp
->fp_sesldr
|| fp
->fp_tty
!= 0) {
583 for (rfp
= &fproc
[0]; rfp
< &fproc
[NR_PROCS
]; rfp
++) {
584 if(rfp
->fp_pid
== PID_FREE
) continue;
585 if (rfp
->fp_tty
== dev
) flags
|= O_NOCTTY
;
589 r
= gen_opcl(op
, dev
, proc_e
, flags
);
591 /* Did this call make the tty the controlling tty? */
599 /*===========================================================================*
601 *===========================================================================*/
602 PUBLIC
int ctty_opcl(op
, dev
, proc_e
, flags
)
603 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
604 dev_t dev
; /* device to open or close */
605 int proc_e
; /* process to open/close for */
606 int flags
; /* mode bits and flags */
608 /* This procedure is called from the dmap struct in table.c on opening/closing
609 * /dev/tty, the magic device that translates to the controlling tty.
612 return(fp
->fp_tty
== 0 ? ENXIO
: OK
);
615 /*===========================================================================*
617 *===========================================================================*/
618 PUBLIC
void pm_setsid(proc_e
)
621 /* Perform the FS side of the SETSID call, i.e. get rid of the controlling
622 * terminal of a process, and make the process a session leader.
624 register struct fproc
*rfp
;
627 /* Make the process a session leader with no controlling tty. */
628 okendpt(proc_e
, &slot
);
630 rfp
->fp_sesldr
= TRUE
;
634 /*===========================================================================*
636 *===========================================================================*/
637 PUBLIC
int do_ioctl()
639 /* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
642 register struct vnode
*vp
;
645 if ( (f
= get_filp(m_in
.ls_fd
)) == NIL_FILP
) return(err_code
);
646 vp
= f
->filp_vno
; /* get vnode pointer */
647 if ( (vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
648 && (vp
->v_mode
& I_TYPE
) != I_BLOCK_SPECIAL
) return(ENOTTY
);
649 dev
= (dev_t
) vp
->v_sdev
;
651 return(dev_io(DEV_IOCTL
, dev
, who_e
, m_in
.ADDRESS
, 0L,
652 m_in
.REQUEST
, f
->filp_flags
));
655 /*===========================================================================*
657 *===========================================================================*/
658 PUBLIC
int gen_io(task_nr
, mess_ptr
)
659 int task_nr
; /* which task to call */
660 message
*mess_ptr
; /* pointer to message for task */
662 /* All file system I/O ultimately comes down to I/O on major/minor device
663 * pairs. These lead to calls on the following routines via the dmap table.
668 proc_e
= mess_ptr
->IO_ENDPT
;
670 r
= sendrec(task_nr
, mess_ptr
);
672 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
673 printf("fs: dead driver %d\n", task_nr
);
674 dmap_unmap_by_endpt(task_nr
);
678 printf("fs: ELOCKED talking to %d\n", task_nr
);
681 panic(__FILE__
,"call_task: can't send/receive", r
);
684 /* Did the process we did the sendrec() for get a result? */
685 if (mess_ptr
->REP_ENDPT
!= proc_e
) {
687 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
691 mess_ptr
->REP_ENDPT
);
698 /*===========================================================================*
700 *===========================================================================*/
701 PUBLIC
int ctty_io(task_nr
, mess_ptr
)
702 int task_nr
; /* not used - for compatibility with dmap_t */
703 message
*mess_ptr
; /* pointer to message for task */
705 /* This routine is only called for one device, namely /dev/tty. Its job
706 * is to change the message to use the controlling terminal, instead of the
707 * major/minor pair for /dev/tty itself.
712 if (fp
->fp_tty
== 0) {
713 /* No controlling tty present anymore, return an I/O error. */
714 mess_ptr
->REP_STATUS
= EIO
;
716 /* Substitute the controlling terminal device. */
717 dp
= &dmap
[(fp
->fp_tty
>> MAJOR
) & BYTE
];
718 mess_ptr
->DEVICE
= (fp
->fp_tty
>> MINOR
) & BYTE
;
720 if (dp
->dmap_driver
== NONE
) {
721 printf("FS: ctty_io: no driver for dev\n");
725 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
726 printf("FS: ctty_io: old driver %d\n",
731 (*dp
->dmap_io
)(dp
->dmap_driver
, mess_ptr
);
737 /*===========================================================================*
739 *===========================================================================*/
740 PUBLIC
int no_dev(op
, dev
, proc
, flags
)
741 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
742 dev_t dev
; /* device to open or close */
743 int proc
; /* process to open/close for */
744 int flags
; /* mode bits and flags */
746 /* Called when opening a nonexistent device. */
750 /*===========================================================================*
752 *===========================================================================*/
753 PUBLIC
int no_dev_io(int proc
, message
*m
)
755 /* Called when doing i/o on a nonexistent device. */
756 printf("VFS: I/O on unmapped device number\n");
762 /*===========================================================================*
764 *===========================================================================*/
765 PUBLIC
int clone_opcl(op
, dev
, proc_e
, flags
)
766 int op
; /* operation, DEV_OPEN or DEV_CLOSE */
767 dev_t dev
; /* device to open or close */
768 int proc_e
; /* process to open/close for */
769 int flags
; /* mode bits and flags */
771 /* Some devices need special processing upon open. Such a device is "cloned",
772 * i.e. on a succesful open it is replaced by a new device with a new unique
773 * minor device number. This new device number identifies a new object (such
774 * as a new network connection) that has been allocated within a task.
780 /* Determine task dmap. */
781 dp
= &dmap
[(dev
>> MAJOR
) & BYTE
];
782 minor
= (dev
>> MINOR
) & BYTE
;
784 dev_mess
.m_type
= op
;
785 dev_mess
.DEVICE
= minor
;
786 dev_mess
.IO_ENDPT
= proc_e
;
787 dev_mess
.COUNT
= flags
;
790 if (dp
->dmap_driver
== NONE
) {
791 printf("FS: clone_opcl: no driver for dev %x\n", dev
);
795 if(isokendpt(dp
->dmap_driver
, &dummyproc
) != OK
) {
796 printf("FS: clone_opcl: old driver for dev %x (%d)\n",
797 dev
, dp
->dmap_driver
);
802 r
= (*dp
->dmap_io
)(dp
->dmap_driver
, &dev_mess
);
806 if (op
== DEV_OPEN
&& dev_mess
.REP_STATUS
>= 0) {
807 if (dev_mess
.REP_STATUS
!= minor
) {
811 struct clone_opcl_req req
;
812 struct node_details res
;
813 /* A new minor device number has been returned.
814 * Request root FS to create a temporary device file to hold it.
817 /* Device number of the new device. */
818 dev
= (dev
& ~(BYTE
<< MINOR
)) | (dev_mess
.REP_STATUS
<< MINOR
);
820 /* Fill in request */
821 req
.fs_e
= ROOT_FS_E
;
825 if ((r
= req_clone_opcl(&req
, &res
)) != OK
) {
826 (void) clone_opcl(DEV_CLOSE
, dev
, proc_e
, 0);
830 /* Drop old node and use the new values */
831 vp
= fp
->fp_filp
[m_in
.fd
]->filp_vno
;
834 if ((vp
= get_free_vnode()) == NIL_VNODE
) {
835 printf("VFSclone_opcl: failed to get a free vnode..\n");
836 vp
= fp
->fp_filp
[m_in
.fd
]->filp_vno
;
839 vp
->v_fs_e
= res
.fs_e
;
840 if ((vmp
= find_vmnt(vp
->v_fs_e
)) == NIL_VMNT
)
841 printf("VFSclone_opcl: no vmnt found\n");
844 vp
->v_dev
= vmp
->m_dev
;
846 vp
->v_inode_nr
= res
.inode_nr
;
847 vp
->v_mode
= res
.fmode
;
850 fp
->fp_filp
[m_in
.fd
]->filp_vno
= vp
;
852 dev_mess
.REP_STATUS
= OK
;
854 return(dev_mess
.REP_STATUS
);
857 /*===========================================================================*
859 *===========================================================================*/
860 PUBLIC
void dev_up(int maj
)
862 /* A new device driver has been mapped in. This function
863 * checks if any filesystems are mounted on it, and if so,
864 * dev_open()s them so the filesystem can be reused.
871 /* Open a device once for every filp that's opened on it,
872 * and once for every filesystem mounted from it.
874 new_driver_e
= dmap
[maj
].dmap_driver
;
876 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
) {
878 if (vmp
->m_dev
== NO_DEV
) continue;
879 if ( ((vmp
->m_dev
>> MAJOR
) & BYTE
) != maj
) continue;
880 minor
= ((vmp
->m_dev
>> MINOR
) & BYTE
);
882 printf("VFS: re-opening dev: %d/%d\n", maj
, minor
);
884 if ((r
= dev_open(vmp
->m_dev
, FS_PROC_NR
,
885 vmp
->m_flags
? R_BIT
: (R_BIT
|W_BIT
))) != OK
) {
886 printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
890 /* Send new driver endpoint */
891 printf("VFS: sending new dirver for dev: %d, endpoint: %d, FS_e: %d\n",
892 vmp
->m_dev
, new_driver_e
, vmp
->m_fs_e
);
894 if (OK
!= req_newdriver(vmp
->m_fs_e
, vmp
->m_dev
, new_driver_e
))
895 printf("VFSdev_up: error sending new driver endpoint. FS_e: %d req_nr: %d\n",
896 vmp
->m_fs_e
, REQ_NEW_DRIVER
);
898 vmp
->m_driver_e
= new_driver_e
;
901 for (fp
= filp
; fp
< &filp
[NR_FILPS
]; fp
++) {
905 if(fp
->filp_count
< 1 || !(vp
= fp
->filp_vno
)) continue;
906 if(((vp
->v_sdev
>> MAJOR
) & BYTE
) != maj
) continue;
907 if(!(vp
->v_mode
& (I_BLOCK_SPECIAL
|I_CHAR_SPECIAL
))) continue;
909 minor
= ((vp
->v_sdev
>> MINOR
) & BYTE
);
911 printf("VFS: reopening special %d/%d..\n", maj
, minor
);
913 if((r
= dev_open(vp
->v_sdev
, FS_PROC_NR
,
914 vp
->v_mode
& (R_BIT
|W_BIT
))) != OK
) {
916 /* This function will set the fp_filp[]s of processes
917 * holding that fp to NULL, but _not_ clear
918 * fp_filp_inuse, so that fd can't be recycled until
922 if(n
!= fp
->filp_count
)
923 printf("VFS: warning: invalidate/count "
924 "discrepancy (%d, %d)\n", n
, fp
->filp_count
);
926 printf("VFS: file on dev %d/%d re-open failed: %d; "
927 "invalidated %d fd's.\n", maj
, minor
, r
, n
);