5 #include <minix/callnr.h>
7 #include <minix/endpoint.h>
8 #include <minix/ioctl.h>
9 #include <minix/safecopies.h>
10 #include <minix/u64.h>
17 #include <minix/vfsif.h>
19 PRIVATE
int dummyproc
;
21 FORWARD
_PROTOTYPE( int safe_io_conversion
, (endpoint_t
,
22 cp_grant_id_t
*, int *, cp_grant_id_t
*, int, endpoint_t
*,
23 void **, int *, vir_bytes
));
24 FORWARD
_PROTOTYPE( void safe_io_cleanup
, (cp_grant_id_t
, cp_grant_id_t
*,
27 /*===========================================================================*
29 *===========================================================================*/
30 PUBLIC
int fs_clone_opcl(void)
32 /* A new minor device number has been returned.
33 * Create a temporary device file to hold it.
38 dev
= fs_m_in
.REQ_DEV
; /* Device number */
40 ip
= alloc_inode(fs_dev
, ALL_MODES
| I_CHAR_SPECIAL
);
42 if (ip
== NIL_INODE
) return err_code
;
46 fs_m_out
.m_source
= ip
->i_dev
;
47 fs_m_out
.RES_INODE_NR
= ip
->i_num
;
48 fs_m_out
.RES_MODE
= ip
->i_mode
;
53 /*===========================================================================*
55 *===========================================================================*/
56 PUBLIC
int fs_new_driver(void)
58 /* New driver endpoint for this device */
59 driver_endpoints
[(fs_m_in
.REQ_DEV
>> MAJOR
) & BYTE
].driver_e
=
65 /*===========================================================================*
66 * safe_io_conversion *
67 *===========================================================================*/
68 PRIVATE
int safe_io_conversion(driver
, gid
, op
, gids
, gids_size
,
69 io_ept
, buf
, vec_grants
, bytes
)
83 static iovec_t new_iovec
[NR_IOREQS
];
85 /* Number of grants allocated in vector I/O. */
88 /* Driver can handle it - change request to a safe one. */
95 /* Change to safe op. */
96 *op
= *op
== MFS_DEV_READ
? DEV_READ_S
: DEV_WRITE_S
;
98 if((*gid
=cpf_grant_direct(driver
, (vir_bytes
) *buf
,
99 bytes
, *op
== DEV_READ_S
? CPF_WRITE
:
102 "cpf_grant_magic of buffer failed\n", NO_NUM
);
107 case MFS_DEV_SCATTER
:
108 /* Change to safe op. */
109 *op
= *op
== MFS_DEV_GATHER
?
110 DEV_GATHER_S
: DEV_SCATTER_S
;
112 /* Grant access to my new i/o vector. */
113 if((*gid
= cpf_grant_direct(driver
,
114 (vir_bytes
) new_iovec
, bytes
* sizeof(iovec_t
),
115 CPF_READ
| CPF_WRITE
)) < 0) {
117 "cpf_grant_direct of vector failed", NO_NUM
);
119 v
= (iovec_t
*) *buf
;
120 /* Grant access to i/o buffers. */
121 for(j
= 0; j
< bytes
; j
++) {
123 panic(__FILE__
, "vec too big", bytes
);
124 new_iovec
[j
].iov_addr
= gids
[j
] =
125 cpf_grant_direct(driver
, (vir_bytes
)
126 v
[j
].iov_addr
, v
[j
].iov_size
,
127 *op
== DEV_GATHER_S
? CPF_WRITE
: CPF_READ
);
128 if(!GRANT_VALID(gids
[j
])) {
129 panic(__FILE__
, "mfs: grant to iovec buf failed",
132 new_iovec
[j
].iov_size
= v
[j
].iov_size
;
136 /* Set user's vector to the new one. */
141 /* If we have converted to a safe operation, I/O
142 * endpoint becomes FS if it wasn't already.
144 if(GRANT_VALID(*gid
)) {
149 /* Not converted to a safe operation (because there is no
150 * copying involved in this operation).
155 /*===========================================================================*
157 *===========================================================================*/
158 PRIVATE
void safe_io_cleanup(gid
, gids
, gids_size
)
163 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
168 for(j
= 0; j
< gids_size
; j
++)
174 /*===========================================================================*
176 *===========================================================================*/
177 PUBLIC
int block_dev_io(op
, dev
, proc_e
, buf
, pos
, bytes
, flags
)
178 int op
; /* MFS_DEV_READ, MFS_DEV_WRITE, etc. */
179 dev_t dev
; /* major-minor device number */
180 int proc_e
; /* in whose address space is buf? */
181 void *buf
; /* virtual address of the buffer */
182 u64_t pos
; /* byte position */
183 int bytes
; /* how many bytes to transfer */
184 int flags
; /* special flags, like O_NONBLOCK */
186 /* Read or write from a device. The parameter 'dev' tells which one. */
191 cp_grant_id_t gid
= GRANT_INVALID
;
195 static cp_grant_id_t gids
[NR_IOREQS
];
198 /* Determine driver endpoint for this device */
199 driver_e
= driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
;
201 /* See if driver is roughly valid. */
202 if (driver_e
== NONE
) {
203 printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E
, dev
);
207 /* The io vector copying relies on this I/O being for FS itself. */
208 if(proc_e
!= SELF_E
) {
209 printf("MFS(%d) doing block_dev_io for non-self %d\n", SELF_E
, proc_e
);
210 panic(__FILE__
, "doing block_dev_io for non-self", proc_e
);
213 /* By default, these are right. */
218 /* Convert parameters to 'safe mode'. */
220 safe
= safe_io_conversion(driver_e
, &gid
,
221 &op_used
, gids
, NR_IOREQS
, &m
.IO_ENDPT
, &buf_used
,
224 /* Set up rest of the message. */
225 if (safe
) m
.IO_GRANT
= (char *) gid
;
228 m
.DEVICE
= (dev
>> MINOR
) & BYTE
;
229 m
.POSITION
= ex64lo(pos
);
231 m
.HIGHPOS
= ex64hi(pos
);
234 r
= sendrec(driver_e
, &m
);
236 /* As block I/O never SUSPENDs, safe cleanup must be done whether
237 * the I/O succeeded or not. */
238 if (safe
) safe_io_cleanup(gid
, gids
, vec_grants
);
241 * - send back dead driver number
242 * - VFS unmaps it, waits for new driver
243 * - VFS sends the new driver endp for the FS proc and the request again
246 if (r
== EDEADSRCDST
|| r
== EDSTDIED
|| r
== ESRCDIED
) {
247 printf("MFS(%d) dead driver %d\n", SELF_E
, driver_e
);
248 driver_endpoints
[(dev
>> MAJOR
) & BYTE
].driver_e
= NONE
;
250 /*dmap_unmap_by_endpt(task_nr); <- in the VFS proc... */
252 else if (r
== ELOCKED
) {
253 printf("MFS(%d) ELOCKED talking to %d\n", SELF_E
, driver_e
);
257 panic(__FILE__
,"call_task: can't send/receive", r
);
260 /* Did the process we did the sendrec() for get a result? */
261 if (m
.REP_ENDPT
!= proc_e
) {
262 printf("MFS(%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E
, m
.m_source
, m
.m_type
, proc_e
, m
.REP_ENDPT
);
267 /* Task has completed. See if call completed. */
268 if (m
.REP_STATUS
== SUSPEND
) {
269 panic(__FILE__
, "MFS block_dev_io: driver returned SUSPEND", NO_NUM
);
272 if(buf
!= buf_used
&& r
== OK
) {
273 memcpy(buf
, buf_used
, bytes
* sizeof(iovec_t
));
276 return(m
.REP_STATUS
);