00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "fs.h"
00021 #include <fcntl.h>
00022 #include <minix/callnr.h>
00023 #include <minix/com.h>
00024 #include <minix/endpoint.h>
00025 #include "file.h"
00026 #include "fproc.h"
00027 #include "inode.h"
00028 #include "param.h"
00029 #include "super.h"
00030
00031 #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
00032
00033 extern int dmap_size;
00034 PRIVATE int dummyproc;
00035
00036
00037
00038
00039 PUBLIC int dev_open(dev, proc, flags)
00040 dev_t dev;
00041 int proc;
00042 int flags;
00043 {
00044 int major, r;
00045 struct dmap *dp;
00046
00047
00048
00049
00050
00051 major = (dev >> MAJOR) & BYTE;
00052 if (major >= NR_DEVICES) major = 0;
00053 dp = &dmap[major];
00054 if (dp->dmap_driver == NONE)
00055 return ENXIO;
00056 r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags);
00057 if (r == SUSPEND) panic(__FILE__,"suspend on open from", dp->dmap_driver);
00058 return(r);
00059 }
00060
00061
00062
00063
00064 PUBLIC void dev_close(dev)
00065 dev_t dev;
00066 {
00067
00068 if (dmap[(dev >> MAJOR)].dmap_driver == NONE) {
00069 return;
00070 }
00071 (void) (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, 0, 0);
00072 }
00073
00074
00075
00076
00077 PUBLIC void dev_status(message *m)
00078 {
00079 message st;
00080 int d, get_more = 1;
00081
00082 for(d = 0; d < NR_DEVICES; d++)
00083 if (dmap[d].dmap_driver != NONE &&
00084 dmap[d].dmap_driver == m->m_source)
00085 break;
00086
00087 if (d >= NR_DEVICES)
00088 return;
00089
00090 do {
00091 int r;
00092 st.m_type = DEV_STATUS;
00093 if ((r=sendrec(m->m_source, &st)) != OK) {
00094 printf("DEV_STATUS failed to %d: %d\n", m->m_source, r);
00095 if (r == EDEADSRCDST) return;
00096 if (r == EDSTDIED) return;
00097 if (r == ESRCDIED) return;
00098 panic(__FILE__,"couldn't sendrec for DEV_STATUS", r);
00099 }
00100
00101 switch(st.m_type) {
00102 case DEV_REVIVE:
00103 revive(st.REP_ENDPT, st.REP_STATUS);
00104 break;
00105 case DEV_IO_READY:
00106 select_notified(d, st.DEV_MINOR, st.DEV_SEL_OPS);
00107 break;
00108 default:
00109 printf("FS: unrecognized reply %d to DEV_STATUS\n", st.m_type);
00110
00111 case DEV_NO_STATUS:
00112 get_more = 0;
00113 break;
00114 }
00115 } while(get_more);
00116
00117 return;
00118 }
00119
00120
00121
00122
00123 PUBLIC int dev_io(op, dev, proc_e, buf, pos, bytes, flags)
00124 int op;
00125 dev_t dev;
00126 int proc_e;
00127 void *buf;
00128 off_t pos;
00129 int bytes;
00130 int flags;
00131 {
00132
00133 struct dmap *dp;
00134 message dev_mess;
00135
00136
00137 dp = &dmap[(dev >> MAJOR) & BYTE];
00138
00139
00140 if (dp->dmap_driver == NONE) {
00141 printf("FS: dev_io: no driver for dev %x\n", dev);
00142 return ENXIO;
00143 }
00144
00145 if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
00146 printf("FS: dev_io: old driver for dev %x (%d)\n",
00147 dev, dp->dmap_driver);
00148 return ENXIO;
00149 }
00150
00151
00152 dev_mess.m_type = op;
00153 dev_mess.DEVICE = (dev >> MINOR) & BYTE;
00154 dev_mess.POSITION = pos;
00155 dev_mess.IO_ENDPT = proc_e;
00156 dev_mess.ADDRESS = buf;
00157 dev_mess.COUNT = bytes;
00158 dev_mess.TTY_FLAGS = flags;
00159
00160
00161 (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
00162
00163 if(dp->dmap_driver == NONE) {
00164
00165 return EIO;
00166 }
00167
00168
00169 if (dev_mess.REP_STATUS == SUSPEND) {
00170 if (flags & O_NONBLOCK) {
00171
00172 dev_mess.m_type = CANCEL;
00173 dev_mess.IO_ENDPT = proc_e;
00174 dev_mess.DEVICE = (dev >> MINOR) & BYTE;
00175 (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
00176 if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
00177 } else {
00178
00179 suspend(dp->dmap_driver);
00180 return(SUSPEND);
00181 }
00182 }
00183 return(dev_mess.REP_STATUS);
00184 }
00185
00186
00187
00188
00189 PUBLIC int gen_opcl(op, dev, proc_e, flags)
00190 int op;
00191 dev_t dev;
00192 int proc_e;
00193 int flags;
00194 {
00195
00196 struct dmap *dp;
00197 message dev_mess;
00198
00199
00200 dp = &dmap[(dev >> MAJOR) & BYTE];
00201
00202 dev_mess.m_type = op;
00203 dev_mess.DEVICE = (dev >> MINOR) & BYTE;
00204 dev_mess.IO_ENDPT = proc_e;
00205 dev_mess.COUNT = flags;
00206
00207 if (dp->dmap_driver == NONE) {
00208 printf("FS: gen_opcl: no driver for dev %x\n", dev);
00209 return ENXIO;
00210 }
00211 if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
00212 printf("FS: gen_opcl: old driver for dev %x (%d)\n",
00213 dev, dp->dmap_driver);
00214 return ENXIO;
00215 }
00216
00217
00218 (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
00219
00220 return(dev_mess.REP_STATUS);
00221 }
00222
00223
00224
00225
00226 PUBLIC int tty_opcl(op, dev, proc_e, flags)
00227 int op;
00228 dev_t dev;
00229 int proc_e;
00230 int flags;
00231 {
00232
00233
00234 int r;
00235 register struct fproc *rfp;
00236
00237
00238
00239
00240
00241 if (!fp->fp_sesldr || fp->fp_tty != 0) {
00242 flags |= O_NOCTTY;
00243 } else {
00244 for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
00245 if(rfp->fp_pid == PID_FREE) continue;
00246 if (rfp->fp_tty == dev) flags |= O_NOCTTY;
00247 }
00248 }
00249
00250 r = gen_opcl(op, dev, proc_e, flags);
00251
00252
00253 if (r == 1) {
00254 fp->fp_tty = dev;
00255 r = OK;
00256 }
00257 return(r);
00258 }
00259
00260
00261
00262
00263 PUBLIC int ctty_opcl(op, dev, proc_e, flags)
00264 int op;
00265 dev_t dev;
00266 int proc_e;
00267 int flags;
00268 {
00269
00270
00271
00272
00273 return(fp->fp_tty == 0 ? ENXIO : OK);
00274 }
00275
00276
00277
00278
00279 PUBLIC int do_setsid()
00280 {
00281
00282
00283
00284 register struct fproc *rfp;
00285 int slot;
00286
00287
00288 if (who_e != PM_PROC_NR) return(ENOSYS);
00289
00290
00291 okendpt(m_in.endpt1, &slot);
00292 rfp = &fproc[slot];
00293 rfp->fp_sesldr = TRUE;
00294 rfp->fp_tty = 0;
00295 return(OK);
00296 }
00297
00298
00299
00300
00301 PUBLIC int do_ioctl()
00302 {
00303
00304
00305 struct filp *f;
00306 register struct inode *rip;
00307 dev_t dev;
00308
00309 if ( (f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
00310 rip = f->filp_ino;
00311 if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL
00312 && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
00313 dev = (dev_t) rip->i_zone[0];
00314
00315 #if ENABLE_BINCOMPAT
00316 if ((m_in.TTY_REQUEST >> 8) == 't') {
00317
00318 struct dmap *dp;
00319 message dev_mess;
00320
00321 dp = &dmap[(dev >> MAJOR) & BYTE];
00322
00323 dev_mess = m;
00324 dev_mess.m_type = DEV_IOCTL;
00325 dev_mess.PROC_NR = who_e;
00326 dev_mess.TTY_LINE = (dev >> MINOR) & BYTE;
00327
00328
00329
00330 if (dp->dmap_driver == NONE) {
00331 printf("FS: do_ioctl: no driver for dev %x\n", dev);
00332 return ENXIO;
00333 }
00334
00335 if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
00336 printf("FS: do_ioctl: old driver for dev %x (%d)\n",
00337 dev, dp->dmap_driver);
00338 return ENXIO;
00339 }
00340
00341 (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
00342
00343 m_out.TTY_SPEK = dev_mess.TTY_SPEK;
00344 m_out.TTY_FLAGS = dev_mess.TTY_FLAGS;
00345 return(dev_mess.REP_STATUS);
00346 }
00347 #endif
00348
00349 return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, 0L,
00350 m_in.REQUEST, f->filp_flags));
00351 }
00352
00353
00354
00355
00356 PUBLIC int gen_io(task_nr, mess_ptr)
00357 int task_nr;
00358 message *mess_ptr;
00359 {
00360
00361
00362
00363
00364 int r, proc_e;
00365
00366 proc_e = mess_ptr->IO_ENDPT;
00367
00368 #if DEAD_CODE
00369 while ((r = sendrec(task_nr, mess_ptr)) == ELOCKED) {
00370
00371
00372
00373
00374 if ((r = receive(task_nr, &local_m)) != OK) {
00375 break;
00376 }
00377
00378
00379
00380
00381
00382 if (mess_ptr->m_type == CANCEL && local_m.REP_ENDPT == proc_e) {
00383 return OK;
00384 }
00385
00386
00387 if (local_m.m_type != REVIVE) {
00388 printf(
00389 "fs: strange device reply from %d, type = %d, proc = %d (1)\n",
00390 local_m.m_source,
00391 local_m.m_type, local_m.REP_ENDPT);
00392 continue;
00393 }
00394
00395 revive(local_m.REP_ENDPT, local_m.REP_STATUS);
00396 }
00397 #endif
00398
00399
00400
00401
00402 r = sendrec(task_nr, mess_ptr);
00403 for(;;) {
00404 if (r != OK) {
00405 if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
00406 printf("fs: dead driver %d\n", task_nr);
00407 dmap_unmap_by_endpt(task_nr);
00408 return r;
00409 }
00410 if (r == ELOCKED) {
00411 printf("fs: ELOCKED talking to %d\n", task_nr);
00412 return r;
00413 }
00414 panic(__FILE__,"call_task: can't send/receive", r);
00415 }
00416
00417
00418 if (mess_ptr->REP_ENDPT == proc_e) {
00419 break;
00420 } else if (mess_ptr->m_type == REVIVE) {
00421
00422 revive(mess_ptr->REP_ENDPT, mess_ptr->REP_STATUS);
00423 } else {
00424 printf(
00425 "fs: strange device reply from %d, type = %d, proc = %d (2) ignored\n",
00426 mess_ptr->m_source,
00427 mess_ptr->m_type, mess_ptr->REP_ENDPT);
00428 }
00429 r = receive(task_nr, mess_ptr);
00430 }
00431
00432 return OK;
00433 }
00434
00435
00436
00437
00438 PUBLIC int ctty_io(task_nr, mess_ptr)
00439 int task_nr;
00440 message *mess_ptr;
00441 {
00442
00443
00444
00445
00446
00447 struct dmap *dp;
00448
00449 if (fp->fp_tty == 0) {
00450
00451 mess_ptr->REP_STATUS = EIO;
00452 } else {
00453
00454 dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE];
00455 mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
00456
00457 if (dp->dmap_driver == NONE) {
00458 printf("FS: ctty_io: no driver for dev\n");
00459 return EIO;
00460 }
00461
00462 if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
00463 printf("FS: ctty_io: old driver %d\n",
00464 dp->dmap_driver);
00465 return EIO;
00466 }
00467
00468 (*dp->dmap_io)(dp->dmap_driver, mess_ptr);
00469 }
00470 return OK;
00471 }
00472
00473
00474
00475
00476 PUBLIC int no_dev(op, dev, proc, flags)
00477 int op;
00478 dev_t dev;
00479 int proc;
00480 int flags;
00481 {
00482
00483 return(ENODEV);
00484 }
00485
00486
00487
00488
00489 PUBLIC int no_dev_io(int proc, message *m)
00490 {
00491
00492 printf("FS: I/O on unmapped device number\n");
00493 return EIO;
00494 }
00495
00496
00497
00498
00499 PUBLIC int clone_opcl(op, dev, proc_e, flags)
00500 int op;
00501 dev_t dev;
00502 int proc_e;
00503 int flags;
00504 {
00505
00506
00507
00508
00509
00510 struct dmap *dp;
00511 int r, minor;
00512 message dev_mess;
00513
00514
00515 dp = &dmap[(dev >> MAJOR) & BYTE];
00516 minor = (dev >> MINOR) & BYTE;
00517
00518 dev_mess.m_type = op;
00519 dev_mess.DEVICE = minor;
00520 dev_mess.IO_ENDPT = proc_e;
00521 dev_mess.COUNT = flags;
00522
00523
00524 if (dp->dmap_driver == NONE) {
00525 printf("FS: clone_opcl: no driver for dev %x\n", dev);
00526 return ENXIO;
00527 }
00528
00529 if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
00530 printf("FS: clone_opcl: old driver for dev %x (%d)\n",
00531 dev, dp->dmap_driver);
00532 return ENXIO;
00533 }
00534
00535
00536 r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
00537 if (r != OK)
00538 return r;
00539
00540 if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
00541 if (dev_mess.REP_STATUS != minor) {
00542
00543
00544
00545 struct inode *ip;
00546
00547
00548 dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
00549
00550 ip = alloc_inode(root_dev, ALL_MODES | I_CHAR_SPECIAL);
00551 if (ip == NIL_INODE) {
00552
00553 (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
00554 return(err_code);
00555 }
00556 ip->i_zone[0] = dev;
00557
00558 put_inode(fp->fp_filp[m_in.fd]->filp_ino);
00559 fp->fp_filp[m_in.fd]->filp_ino = ip;
00560 }
00561 dev_mess.REP_STATUS = OK;
00562 }
00563 return(dev_mess.REP_STATUS);
00564 }
00565
00566
00567
00568
00569 PUBLIC void dev_up(int maj)
00570 {
00571
00572
00573
00574
00575 struct super_block *sb;
00576 struct filp *fp;
00577 int r;
00578
00579
00580
00581
00582
00583 for(sb = super_block; sb < &super_block[NR_SUPERS]; sb++) {
00584 int minor;
00585 if(sb->s_dev == NO_DEV)
00586 continue;
00587 if(((sb->s_dev >> MAJOR) & BYTE) != maj)
00588 continue;
00589 minor = ((sb->s_dev >> MINOR) & BYTE);
00590 printf("FS: remounting dev %d/%d\n", maj, minor);
00591 if((r = dev_open(sb->s_dev, FS_PROC_NR,
00592 sb->s_rd_only ? R_BIT : (R_BIT|W_BIT))) != OK) {
00593 printf("FS: mounted dev %d/%d re-open failed: %d.\n",
00594 maj, minor, r);
00595 }
00596 }
00597
00598 for(fp = filp; fp < &filp[NR_FILPS]; fp++) {
00599 struct inode *in;
00600 int minor;
00601
00602 if(fp->filp_count < 1 || !(in=fp->filp_ino)) continue;
00603 if(((in->i_zone[0] >> MAJOR) & BYTE) != maj) continue;
00604 if(!(in->i_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue;
00605
00606 minor = ((in->i_zone[0] >> MINOR) & BYTE);
00607
00608 printf("FS: reopening special %d/%d..\n", maj, minor);
00609
00610 if((r = dev_open(in->i_zone[0], FS_PROC_NR,
00611 in->i_mode & (R_BIT|W_BIT))) != OK) {
00612 int n;
00613
00614
00615
00616
00617
00618 n = inval_filp(fp);
00619 if(n != fp->filp_count)
00620 printf("FS: warning: invalidate/count "
00621 "discrepancy (%d, %d)\n", n, fp->filp_count);
00622 fp->filp_count = 0;
00623 printf("FS: file on dev %d/%d re-open failed: %d; "
00624 "invalidated %d fd's.\n", maj, minor, r, n);
00625 }
00626 }
00627
00628 return;
00629 }
00630