BOOK.TXT
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:999k
源码类别:

操作系统开发

开发平台:

C/C++

  1. 17264   sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
  2. 17265   return(OK);
  3. 17266 }
  4. 17269 /*===========================================================================*
  5. 17270  *                              read_header                                  *
  6. 17271  *===========================================================================*/
  7. 17272 PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, 
  8. 17273                                                 tot_bytes, sym_bytes, sc, pc)
  9. 17274 int fd;                         /* file descriptor for reading exec file */
  10. 17275 int *ft;                        /* place to return ft number */
  11. 17276 vir_bytes *text_bytes;          /* place to return text size */
  12. 17277 vir_bytes *data_bytes;          /* place to return initialized data size */
  13. 17278 vir_bytes *bss_bytes;           /* place to return bss size */
  14. 17279 phys_bytes *tot_bytes;          /* place to return total size */
  15. 17280 long *sym_bytes;                /* place to return symbol table size */
  16. 17281 vir_clicks sc;                  /* stack size in clicks */
  17. 17282 vir_bytes *pc;                  /* program entry point (initial PC) */
  18. 17283 {
  19. 17284 /* Read the header and extract the text, data, bss and total sizes from it. */
  20. 17285
  21. 17286   int m, ct;
  22. 17287   vir_clicks tc, dc, s_vir, dvir;
  23. 17288   phys_clicks totc;
  24. 17289   struct exec hdr;              /* a.out header is read in here */
  25. 17290
  26. 17291   /* Read the header and check the magic number.  The standard MINIX header 
  27. 17292    * is defined in <a.out.h>.  It consists of 8 chars followed by 6 longs.
  28. 17293    * Then come 4 more longs that are not used here.
  29. 17294    *    Byte 0: magic number 0x01
  30. 17295    *    Byte 1: magic number 0x03
  31. 17296    *    Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
  32. 17297    *    Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, 
  33. 17298    *            Motorola = 0x0B, Sun SPARC = 0x17
  34. 17299    *    Byte 4: Header length = 0x20
  35. 17300    *    Bytes 5-7 are not used.
  36. 17301    *
  37. 17302    *    Now come the 6 longs
  38. 17303    *    Bytes  8-11: size of text segments in bytes
  39. 17304    *    Bytes 12-15: size of initialized data segment in bytes
  40. 17305    *    Bytes 16-19: size of bss in bytes
  41. 17306    *    Bytes 20-23: program entry point
  42. 17307    *    Bytes 24-27: total memory allocated to program (text, data + stack)
  43. 17308    *    Bytes 28-31: size of symbol table in bytes
  44. 17309    * The longs are represented in a machine dependent order,
  45. 17310    * little-endian on the 8088, big-endian on the 68000.
  46. 17311    * The header is followed directly by the text and data segments, and the 
  47. 17312    * symbol table (if any). The sizes are given in the header. Only the 
  48. 17313    * text and data segments are copied into memory by exec. The header is 
  49. 17314    * used here only. The symbol table is for the benefit of a debugger and 
  50. 17315    * is ignored here.
  51. 17316    */
  52. 17317
  53. 17318   if (read(fd, (char *) &hdr, A_MINHDR) != A_MINHDR) return(ENOEXEC);
  54. 17319
  55. 17320   /* Check magic number, cpu type, and flags. */
  56. 17321   if (BADMAG(hdr)) return(ENOEXEC);
  57. 17322 #if (CHIP == INTEL && _WORD_SIZE == 2)
  58. 17323   if (hdr.a_cpu != A_I8086) return(ENOEXEC);
  59. 17324 #endif
  60. 17325 #if (CHIP == INTEL && _WORD_SIZE == 4)
  61. 17326   if (hdr.a_cpu != A_I80386) return(ENOEXEC);
  62. 17327 #endif
  63. 17328   if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
  64. 17329
  65. 17330   *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0);    /* separate I & D or not */
  66. 17331
  67. 17332   /* Get text and data sizes. */
  68. 17333   *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */
  69. 17334   *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */
  70. 17335   *bss_bytes  = (vir_bytes) hdr.a_bss;  /* bss size in bytes */
  71. 17336   *tot_bytes  = hdr.a_total;            /* total bytes to allocate for prog */
  72. 17337   *sym_bytes  = hdr.a_syms;             /* symbol table size in bytes */
  73. 17338   if (*tot_bytes == 0) return(ENOEXEC);
  74. 17339
  75. 17340   if (*ft != SEPARATE) {
  76. 17341
  77. 17342         /* If I & D space is not separated, it is all considered data. Text=0*/
  78. 17343         *data_bytes += *text_bytes;
  79. 17344         *text_bytes = 0;
  80. 17345
  81. 17346   }
  82. 17347   *pc = hdr.a_entry;    /* initial address to start execution */
  83. 17348
  84. 17349   /* Check to see if segment sizes are feasible. */
  85. 17350   tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  86. 17351   dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  87. 17352   totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  88. 17353   if (dc >= totc) return(ENOEXEC);      /* stack must be at least 1 click */
  89. 17354   dvir = (*ft == SEPARATE ? 0 : tc);
  90. 17355   s_vir = dvir + (totc - sc);
  91. 17356   m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
  92. 17357   ct = hdr.a_hdrlen & BYTE;             /* header length */
  93. 17358   if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */
  94. 17359   return(m);
  95. 17360 }
  96. 17363 /*===========================================================================*
  97. 17364  *                              new_mem                                      *
  98. 17365  *===========================================================================*/
  99. 17366 PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes)
  100. 17367 struct mproc *sh_mp;            /* text can be shared with this process */
  101. 17368 vir_bytes text_bytes;           /* text segment size in bytes */
  102. 17369 vir_bytes data_bytes;           /* size of initialized data in bytes */
  103. 17370 vir_bytes bss_bytes;            /* size of bss in bytes */
  104. 17371 vir_bytes stk_bytes;            /* size of initial stack segment in bytes */
  105. 17372 phys_bytes tot_bytes;           /* total memory to allocate, including gap */
  106. 17373 {
  107. 17374 /* Allocate new memory and release the old memory.  Change the map and report
  108. 17375  * the new map to the kernel.  Zero the new core image's bss, gap and stack.
  109. 17376  */
  110. 17377
  111. 17378   register struct mproc *rmp;
  112. 17379   vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
  113. 17380   phys_clicks new_base;
  114. 17381
  115. 17382   static char zero[1024];               /* used to zero bss */
  116. 17383   phys_bytes bytes, base, count, bss_offset;
  117. 17384
  118. 17385   /* No need to allocate text if it can be shared. */
  119. 17386   if (sh_mp != NULL) text_bytes = 0;
  120. 17387
  121. 17388   /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
  122. 17389    * and stack occupies an integral number of clicks, starting at click
  123. 17390    * boundary.  The data and bss parts are run together with no space.
  124. 17391    */
  125. 17392
  126. 17393   text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  127. 17394   data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  128. 17395   stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  129. 17396   tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  130. 17397   gap_clicks = tot_clicks - data_clicks - stack_clicks;
  131. 17398   if ( (int) gap_clicks < 0) return(ENOMEM);
  132. 17399
  133. 17400   /* Check to see if there is a hole big enough.  If so, we can risk first
  134. 17401    * releasing the old core image before allocating the new one, since we
  135. 17402    * know it will succeed.  If there is not enough, return failure.
  136. 17403    */
  137. 17404   if (text_clicks + tot_clicks > max_hole()) return(EAGAIN);
  138. 17405
  139. 17406   /* There is enough memory for the new core image.  Release the old one. */
  140. 17407   rmp = mp;
  141. 17408
  142. 17409   if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
  143. 17410         /* No other process shares the text segment, so free it. */
  144. 17411         free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
  145. 17412   }
  146. 17413   /* Free the data and stack segments. */
  147. 17414   free_mem(rmp->mp_seg[D].mem_phys,
  148. 17415       rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
  149. 17416
  150. 17417   /* We have now passed the point of no return.  The old core image has been
  151. 17418    * forever lost.  The call must go through now.  Set up and report new map.
  152. 17419    */
  153. 17420   new_base = alloc_mem(text_clicks + tot_clicks);       /* new core image */
  154. 17421   if (new_base == NO_MEM) panic("MM hole list is inconsistent", NO_NUM);
  155. 17422
  156. 17423   if (sh_mp != NULL) {
  157. 17424         /* Share the text segment. */
  158. 17425         rmp->mp_seg[T] = sh_mp->mp_seg[T];
  159. 17426   } else {
  160. 17427         rmp->mp_seg[T].mem_phys = new_base;
  161. 17428         rmp->mp_seg[T].mem_vir = 0;
  162. 17429         rmp->mp_seg[T].mem_len = text_clicks;
  163. 17430   }
  164. 17431   rmp->mp_seg[D].mem_phys = new_base + text_clicks;
  165. 17432   rmp->mp_seg[D].mem_vir = 0;
  166. 17433   rmp->mp_seg[D].mem_len = data_clicks;
  167. 17434   rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
  168. 17435   rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
  169. 17436   rmp->mp_seg[S].mem_len = stack_clicks;
  170. 17437
  171. 17438
  172. 17439   sys_newmap(who, rmp->mp_seg);   /* report new map to the kernel */
  173. 17440
  174. 17441   /* Zero the bss, gap, and stack segment. */
  175. 17442   bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
  176. 17443   base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
  177. 17444   bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
  178. 17445   base += bss_offset;
  179. 17446   bytes -= bss_offset;
  180. 17447
  181. 17448   while (bytes > 0) {
  182. 17449         count = MIN(bytes, (phys_bytes) sizeof(zero));
  183. 17450         if (sys_copy(MM_PROC_NR, D, (phys_bytes) zero,
  184. 17451                                                 ABS, 0, base, count) != OK) {
  185. 17452                 panic("new_mem can't zero", NO_NUM);
  186. 17453         }
  187. 17454         base += count;
  188. 17455         bytes -= count;
  189. 17456   }
  190. 17457
  191. 17458   return(OK);
  192. 17459 }
  193. 17462 /*===========================================================================*
  194. 17463  *                              patch_ptr                                    *
  195. 17464  *===========================================================================*/
  196. 17465 PRIVATE void patch_ptr(stack, base)
  197. 17466 char stack[ARG_MAX];    /* pointer to stack image within MM */
  198. 17467 vir_bytes base;                 /* virtual address of stack base inside user */
  199. 17468 {
  200. 17469 /* When doing an exec(name, argv, envp) call, the user builds up a stack
  201. 17470  * image with arg and env pointers relative to the start of the stack.  Now
  202. 17471  * these pointers must be relocated, since the stack is not positioned at
  203. 17472  * address 0 in the user's address space.
  204. 17473  */
  205. 17474
  206. 17475   char **ap, flag;
  207. 17476   vir_bytes v;
  208. 17477
  209. 17478   flag = 0;                     /* counts number of 0-pointers seen */
  210. 17479   ap = (char **) stack;         /* points initially to 'nargs' */
  211. 17480   ap++;                         /* now points to argv[0] */
  212. 17481   while (flag < 2) {
  213. 17482         if (ap >= (char **) &stack[ARG_MAX]) return;    /* too bad */
  214. 17483         if (*ap != NIL_PTR) {
  215. 17484                 v = (vir_bytes) *ap;    /* v is relative pointer */
  216. 17485                 v += base;              /* relocate it */
  217. 17486                 *ap = (char *) v;       /* put it back */
  218. 17487         } else {
  219. 17488                 flag++;
  220. 17489         }
  221. 17490         ap++;
  222. 17491   }
  223. 17492 }
  224. 17495 /*===========================================================================*
  225. 17496  *                              load_seg                                     *
  226. 17497  *===========================================================================*/
  227. 17498 PRIVATE void load_seg(fd, seg, seg_bytes)
  228. 17499 int fd;                         /* file descriptor to read from */
  229. 17500 int seg;                        /* T or D */
  230. 17501 vir_bytes seg_bytes;            /* how big is the segment */
  231. 17502 {
  232. 17503 /* Read in text or data from the exec file and copy to the new core image.
  233. 17504  * This procedure is a little bit tricky.  The logical way to load a segment
  234. 17505  * would be to read it block by block and copy each block to the user space
  235. 17506  * one at a time.  This is too slow, so we do something dirty here, namely
  236. 17507  * send the user space and virtual address to the file system in the upper
  237. 17508  * 10 bits of the file descriptor, and pass it the user virtual address
  238. 17509  * instead of a MM address.  The file system extracts these parameters when 
  239. 17510  * gets a read call from the memory manager, which is the only process that
  240. 17511  * is permitted to use this trick.  The file system then copies the whole 
  241. 17512  * segment directly to user space, bypassing MM completely.
  242. 17513  */
  243. 17514
  244. 17515   int new_fd, bytes;
  245. 17516   char *ubuf_ptr;
  246. 17517
  247. 17518   new_fd = (who << 8) | (seg << 6) | fd;
  248. 17519   ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
  249. 17520   while (seg_bytes != 0) {
  250. 17521         bytes = (INT_MAX / BLOCK_SIZE) * BLOCK_SIZE;
  251. 17522         if (seg_bytes < bytes)
  252. 17523                 bytes = (int)seg_bytes;
  253. 17524         if (read(new_fd, ubuf_ptr, bytes) != bytes)
  254. 17525                 break;          /* error */
  255. 17526         ubuf_ptr += bytes;
  256. 17527         seg_bytes -= bytes;
  257. 17528   }
  258. 17529 }
  259. 17532 /*===========================================================================*
  260. 17533  *                              find_share                                   *
  261. 17534  *===========================================================================*/
  262. 17535 PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
  263. 17536 struct mproc *mp_ign;           /* process that should not be looked at */
  264. 17537 ino_t ino;                      /* parameters that uniquely identify a file */
  265. 17538 dev_t dev;
  266. 17539 time_t ctime;
  267. 17540 {
  268. 17541 /* Look for a process that is the file <ino, dev, ctime> in execution.  Don't
  269. 17542  * accidentally "find" mp_ign, because it is the process on whose behalf this
  270. 17543  * call is made.
  271. 17544  */
  272. 17545   struct mproc *sh_mp;
  273. 17546
  274. 17547   for (sh_mp = &mproc[INIT_PROC_NR]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
  275. 17548         if ((sh_mp->mp_flags & (IN_USE | HANGING | SEPARATE))
  276. 17549                                         != (IN_USE | SEPARATE)) continue;
  277. 17550         if (sh_mp == mp_ign) continue;
  278. 17551         if (sh_mp->mp_ino != ino) continue;
  279. 17552         if (sh_mp->mp_dev != dev) continue;
  280. 17553         if (sh_mp->mp_ctime != ctime) continue;
  281. 17554         return sh_mp;
  282. 17555   }
  283. 17556   return(NULL);
  284. 17557 }
  285. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  286. src/mm/break.c    
  287. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  288. 17600 /* The MINIX model of memory allocation reserves a fixed amount of memory for
  289. 17601  * the combined text, data, and stack segments.  The amount used for a child
  290. 17602  * process created by FORK is the same as the parent had.  If the child does
  291. 17603  * an EXEC later, the new size is taken from the header of the file EXEC'ed.
  292. 17604  *
  293. 17605  * The layout in memory consists of the text segment, followed by the data
  294. 17606  * segment, followed by a gap (unused memory), followed by the stack segment.
  295. 17607  * The data segment grows upward and the stack grows downward, so each can
  296. 17608  * take memory from the gap.  If they meet, the process must be killed.  The
  297. 17609  * procedures in this file deal with the growth of the data and stack segments.
  298. 17610  *
  299. 17611  * The entry points into this file are:
  300. 17612  *   do_brk:      BRK/SBRK system calls to grow or shrink the data segment
  301. 17613  *   adjust:      see if a proposed segment adjustment is allowed
  302. 17614  *   size_ok:     see if the segment sizes are feasible
  303. 17615  */
  304. 17616
  305. 17617 #include "mm.h"
  306. 17618 #include <signal.h>
  307. 17619 #include "mproc.h"
  308. 17620 #include "param.h"
  309. 17621
  310. 17622 #define DATA_CHANGED       1    /* flag value when data segment size changed */
  311. 17623 #define STACK_CHANGED      2    /* flag value when stack size changed */
  312. 17624
  313. 17625 /*===========================================================================*
  314. 17626  *                              do_brk                                       *
  315. 17627  *===========================================================================*/
  316. 17628 PUBLIC int do_brk()
  317. 17629 {
  318. 17630 /* Perform the brk(addr) system call.
  319. 17631  *
  320. 17632  * The call is complicated by the fact that on some machines (e.g., 8088),
  321. 17633  * the stack pointer can grow beyond the base of the stack segment without
  322. 17634  * anybody noticing it.
  323. 17635  * The parameter, 'addr' is the new virtual address in D space.
  324. 17636  */
  325. 17637
  326. 17638   register struct mproc *rmp;
  327. 17639   int r;
  328. 17640   vir_bytes v, new_sp;
  329. 17641   vir_clicks new_clicks;
  330. 17642
  331. 17643   rmp = mp;
  332. 17644   v = (vir_bytes) addr;
  333. 17645   new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
  334. 17646   if (new_clicks < rmp->mp_seg[D].mem_vir) {
  335. 17647         res_ptr = (char *) -1;
  336. 17648         return(ENOMEM);
  337. 17649   }
  338. 17650   new_clicks -= rmp->mp_seg[D].mem_vir;
  339. 17651   sys_getsp(who, &new_sp);      /* ask kernel for current sp value */
  340. 17652   r = adjust(rmp, new_clicks, new_sp);
  341. 17653   res_ptr = (r == OK ? addr : (char *) -1);
  342. 17654   return(r);                    /* return new address or -1 */
  343. 17655 }
  344. 17658 /*===========================================================================*
  345. 17659  *                              adjust                                       *
  346. 17660  *===========================================================================*/
  347. 17661 PUBLIC int adjust(rmp, data_clicks, sp)
  348. 17662 register struct mproc *rmp;     /* whose memory is being adjusted? */
  349. 17663 vir_clicks data_clicks;         /* how big is data segment to become? */
  350. 17664 vir_bytes sp;                   /* new value of sp */
  351. 17665 {
  352. 17666 /* See if data and stack segments can coexist, adjusting them if need be.
  353. 17667  * Memory is never allocated or freed.  Instead it is added or removed from the
  354. 17668  * gap between data segment and stack segment.  If the gap size becomes
  355. 17669  * negative, the adjustment of data or stack fails and ENOMEM is returned.
  356. 17670  */
  357. 17671
  358. 17672   register struct mem_map *mem_sp, *mem_dp;
  359. 17673   vir_clicks sp_click, gap_base, lower, old_clicks;
  360. 17674   int changed, r, ft;
  361. 17675   long base_of_stack, delta;    /* longs avoid certain problems */
  362. 17676
  363. 17677   mem_dp = &rmp->mp_seg[D];     /* pointer to data segment map */
  364. 17678   mem_sp = &rmp->mp_seg[S];     /* pointer to stack segment map */
  365. 17679   changed = 0;                  /* set when either segment changed */
  366. 17680
  367. 17681   if (mem_sp->mem_len == 0) return(OK); /* don't bother init */
  368. 17682
  369. 17683   /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
  370. 17684   base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
  371. 17685   sp_click = sp >> CLICK_SHIFT; /* click containing sp */
  372. 17686   if (sp_click >= base_of_stack) return(ENOMEM);        /* sp too high */
  373. 17687
  374. 17688   /* Compute size of gap between stack and data segments. */
  375. 17689   delta = (long) mem_sp->mem_vir - (long) sp_click;
  376. 17690   lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
  377. 17691
  378. 17692   /* Add a safety margin for future stack growth. Impossible to do right. */
  379. 17693 #define SAFETY_BYTES  (384 * sizeof(char *))
  380. 17694 #define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
  381. 17695   gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
  382. 17696   if (lower < gap_base) return(ENOMEM); /* data and stack collided */
  383. 17697
  384. 17698   /* Update data length (but not data orgin) on behalf of brk() system call. */
  385. 17699   old_clicks = mem_dp->mem_len;
  386. 17700   if (data_clicks != mem_dp->mem_len) {
  387. 17701         mem_dp->mem_len = data_clicks;
  388. 17702         changed |= DATA_CHANGED;
  389. 17703   }
  390. 17704
  391. 17705   /* Update stack length and origin due to change in stack pointer. */
  392. 17706   if (delta > 0) {
  393. 17707         mem_sp->mem_vir -= delta;
  394. 17708         mem_sp->mem_phys -= delta;
  395. 17709         mem_sp->mem_len += delta;
  396. 17710         changed |= STACK_CHANGED;
  397. 17711   }
  398. 17712
  399. 17713   /* Do the new data and stack segment sizes fit in the address space? */
  400. 17714   ft = (rmp->mp_flags & SEPARATE);
  401. 17715   r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, 
  402. 17716        rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
  403. 17717   if (r == OK) {
  404. 17718         if (changed) sys_newmap((int)(rmp - mproc), rmp->mp_seg);
  405. 17719         return(OK);
  406. 17720   }
  407. 17721
  408. 17722   /* New sizes don't fit or require too many page/segment registers. Restore.*/
  409. 17723   if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
  410. 17724   if (changed & STACK_CHANGED) {
  411. 17725         mem_sp->mem_vir += delta;
  412. 17726         mem_sp->mem_phys += delta;
  413. 17727         mem_sp->mem_len -= delta;
  414. 17728   }
  415. 17729   return(ENOMEM);
  416. 17730 }
  417. 17733 /*===========================================================================*
  418. 17734  *                              size_ok                                      *
  419. 17735  *===========================================================================*/
  420. 17736 PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
  421. 17737 int file_type;                  /* SEPARATE or 0 */
  422. 17738 vir_clicks tc;                  /* text size in clicks */
  423. 17739 vir_clicks dc;                  /* data size in clicks */
  424. 17740 vir_clicks sc;                  /* stack size in clicks */
  425. 17741 vir_clicks dvir;                /* virtual address for start of data seg */
  426. 17742 vir_clicks s_vir;               /* virtual address for start of stack seg */
  427. 17743 {
  428. 17744 /* Check to see if the sizes are feasible and enough segmentation registers
  429. 17745  * exist.  On a machine with eight 8K pages, text, data, stack sizes of
  430. 17746  * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
  431. 17747  * former is bigger (64K) than the latter (63K).  Even on the 8088 this test
  432. 17748  * is needed, since the data and stack may not exceed 4096 clicks.
  433. 17749  */
  434. 17750
  435. 17751 #if (CHIP == INTEL && _WORD_SIZE == 2)
  436. 17752   int pt, pd, ps;               /* segment sizes in pages */
  437. 17753
  438. 17754   pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  439. 17755   pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  440. 17756   ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  441. 17757
  442. 17758   if (file_type == SEPARATE) {
  443. 17759         if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
  444. 17760   } else {
  445. 17761         if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
  446. 17762   }
  447. 17763 #endif
  448. 17764
  449. 17765   if (dvir + dc > s_vir) return(ENOMEM);
  450. 17766
  451. 17767   return(OK);
  452. 17768 }
  453. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  454. src/mm/signal.c    
  455. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  456. 17800 /* This file handles signals, which are asynchronous events and are generally
  457. 17801  * a messy and unpleasant business.  Signals can be generated by the KILL
  458. 17802  * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
  459. 17803  * In all cases control eventually passes to check_sig() to see which processes
  460. 17804  * can be signaled.  The actual signaling is done by sig_proc().
  461. 17805  *
  462. 17806  * The entry points into this file are:
  463. 17807  *   do_sigaction:   perform the SIGACTION system call
  464. 17808  *   do_sigpending:  perform the SIGPENDING system call
  465. 17809  *   do_sigprocmask: perform the SIGPROCMASK system call
  466. 17810  *   do_sigreturn:   perform the SIGRETURN system call
  467. 17811  *   do_sigsuspend:  perform the SIGSUSPEND system call
  468. 17812  *   do_kill:   perform the KILL system call
  469. 17813  *   do_ksig:   accept a signal originating in the kernel (e.g., SIGINT)
  470. 17814  *   do_alarm:  perform the ALARM system call by calling set_alarm()
  471. 17815  *   set_alarm: tell the clock task to start or stop a timer
  472. 17816  *   do_pause:  perform the PAUSE system call
  473. 17817  *   do_reboot: kill all processes, then reboot system
  474. 17818  *   sig_proc:  interrupt or terminate a signaled process
  475. 17819  *   check_sig: check which processes to signal with sig_proc()
  476. 17820  */
  477. 17821
  478. 17822 #include "mm.h"
  479. 17823 #include <sys/stat.h>
  480. 17824 #include <minix/callnr.h>
  481. 17825 #include <minix/com.h>
  482. 17826 #include <signal.h>
  483. 17827 #include <sys/sigcontext.h>
  484. 17828 #include <string.h>
  485. 17829 #include "mproc.h"
  486. 17830 #include "param.h"
  487. 17831
  488. 17832 #define CORE_MODE       0777    /* mode to use on core image files */
  489. 17833 #define DUMPED          0200    /* bit set in status when core dumped */
  490. 17834 #define DUMP_SIZE       ((INT_MAX / BLOCK_SIZE) * BLOCK_SIZE)
  491. 17835                                 /* buffer size for core dumps */
  492. 17836
  493. 17837 FORWARD _PROTOTYPE( void check_pending, (void)                          );
  494. 17838 FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp)                 );
  495. 17839 FORWARD _PROTOTYPE( void unpause, (int pro)                             );
  496. 17840
  497. 17841
  498. 17842 /*===========================================================================*
  499. 17843  *                             do_sigaction                                  *
  500. 17844  *===========================================================================*/
  501. 17845 PUBLIC int do_sigaction()
  502. 17846 {
  503. 17847   int r;
  504. 17848   struct sigaction svec;
  505. 17849   struct sigaction *svp;
  506. 17850
  507. 17851   if (sig_nr == SIGKILL) return(OK);
  508. 17852   if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL);
  509. 17853   svp = &mp->mp_sigact[sig_nr];
  510. 17854   if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) {
  511. 17855         r = sys_copy(MM_PROC_NR,D, (phys_bytes) svp,
  512. 17856                 who, D, (phys_bytes) sig_osa, (phys_bytes) sizeof(svec));
  513. 17857         if (r != OK) return(r);
  514. 17858   }
  515. 17859
  516. 17860   if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK);
  517. 17861
  518. 17862   /* Read in the sigaction structure. */
  519. 17863   r = sys_copy(who, D, (phys_bytes) sig_nsa,
  520. 17864                 MM_PROC_NR, D, (phys_bytes) &svec, (phys_bytes) sizeof(svec));
  521. 17865   if (r != OK) return(r);
  522. 17866
  523. 17867   if (svec.sa_handler == SIG_IGN) {
  524. 17868         sigaddset(&mp->mp_ignore, sig_nr);
  525. 17869         sigdelset(&mp->mp_sigpending, sig_nr);
  526. 17870         sigdelset(&mp->mp_catch, sig_nr);
  527. 17871   } else {
  528. 17872         sigdelset(&mp->mp_ignore, sig_nr);
  529. 17873         if (svec.sa_handler == SIG_DFL)
  530. 17874                 sigdelset(&mp->mp_catch, sig_nr);
  531. 17875         else
  532. 17876                 sigaddset(&mp->mp_catch, sig_nr);
  533. 17877   }
  534. 17878   mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler;
  535. 17879   sigdelset(&svec.sa_mask, SIGKILL);
  536. 17880   mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask;
  537. 17881   mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags;
  538. 17882   mp->mp_sigreturn = (vir_bytes) sig_ret;
  539. 17883   return(OK);
  540. 17884 }
  541. 17886 /*===========================================================================*
  542. 17887  *                            do_sigpending                                  *
  543. 17888  *===========================================================================*/
  544. 17889 PUBLIC int do_sigpending()
  545. 17890 {
  546. 17891   ret_mask = (long) mp->mp_sigpending;
  547. 17892   return OK;
  548. 17893 }
  549. 17895 /*===========================================================================*
  550. 17896  *                            do_sigprocmask                                 *
  551. 17897  *===========================================================================*/
  552. 17898 PUBLIC int do_sigprocmask()
  553. 17899 {
  554. 17900 /* Note that the library interface passes the actual mask in sigmask_set,
  555. 17901  * not a pointer to the mask, in order to save a sys_copy.  Similarly,
  556. 17902  * the old mask is placed in the return message which the library
  557. 17903  * interface copies (if requested) to the user specified address.
  558. 17904  *
  559. 17905  * The library interface must set SIG_INQUIRE if the 'act' argument
  560. 17906  * is NULL.
  561. 17907  */
  562. 17908
  563. 17909   int i;
  564. 17910
  565. 17911   ret_mask = (long) mp->mp_sigmask;
  566. 17912
  567. 17913   switch (sig_how) {
  568. 17914       case SIG_BLOCK:
  569. 17915         sigdelset((sigset_t *)&sig_set, SIGKILL);
  570. 17916         for (i = 1; i < _NSIG; i++) {
  571. 17917                 if (sigismember((sigset_t *)&sig_set, i))
  572. 17918                         sigaddset(&mp->mp_sigmask, i);
  573. 17919         }
  574. 17920         break;
  575. 17921
  576. 17922       case SIG_UNBLOCK:
  577. 17923         for (i = 1; i < _NSIG; i++) {
  578. 17924                 if (sigismember((sigset_t *)&sig_set, i))
  579. 17925                         sigdelset(&mp->mp_sigmask, i);
  580. 17926         }
  581. 17927         check_pending();
  582. 17928         break;
  583. 17929
  584. 17930       case SIG_SETMASK:
  585. 17931         sigdelset((sigset_t *)&sig_set, SIGKILL);
  586. 17932         mp->mp_sigmask = (sigset_t)sig_set;
  587. 17933         check_pending();
  588. 17934         break;
  589. 17935
  590. 17936       case SIG_INQUIRE:
  591. 17937         break;
  592. 17938
  593. 17939       default:
  594. 17940         return(EINVAL);
  595. 17941         break;
  596. 17942   }
  597. 17943   return OK;
  598. 17944 }
  599. 17946 /*===========================================================================*
  600. 17947  *                            do_sigsuspend                                  *
  601. 17948  *===========================================================================*/
  602. 17949 PUBLIC int do_sigsuspend()
  603. 17950 {
  604. 17951   mp->mp_sigmask2 = mp->mp_sigmask;     /* save the old mask */
  605. 17952   mp->mp_sigmask = (sigset_t) sig_set;
  606. 17953   sigdelset(&mp->mp_sigmask, SIGKILL);
  607. 17954   mp->mp_flags |= SIGSUSPENDED;
  608. 17955   dont_reply = TRUE;
  609. 17956   check_pending();
  610. 17957   return OK;
  611. 17958 }
  612. 17961 /*===========================================================================*
  613. 17962  *                               do_sigreturn                                *
  614. 17963  *===========================================================================*/
  615. 17964 PUBLIC int do_sigreturn()
  616. 17965 {
  617. 17966 /* A user signal handler is done.  Restore context and check for
  618. 17967  * pending unblocked signals.
  619. 17968  */
  620. 17969
  621. 17970   int r;
  622. 17971
  623. 17972   mp->mp_sigmask = (sigset_t) sig_set;
  624. 17973   sigdelset(&mp->mp_sigmask, SIGKILL);
  625. 17974
  626. 17975   r = sys_sigreturn(who, (vir_bytes)sig_context, sig_flags);
  627. 17976   check_pending();
  628. 17977   return(r);
  629. 17978 }
  630. 17980 /*===========================================================================*
  631. 17981  *                              do_kill                                      *
  632. 17982  *===========================================================================*/
  633. 17983 PUBLIC int do_kill()
  634. 17984 {
  635. 17985 /* Perform the kill(pid, signo) system call. */
  636. 17986
  637. 17987   return check_sig(pid, sig_nr);
  638. 17988 }
  639. 17991 /*===========================================================================*
  640. 17992  *                              do_ksig                                      *
  641. 17993  *===========================================================================*/
  642. 17994 PUBLIC int do_ksig()
  643. 17995 {
  644. 17996 /* Certain signals, such as segmentation violations and DEL, originate in the
  645. 17997  * kernel.  When the kernel detects such signals, it sets bits in a bit map.
  646. 17998  * As soon as MM is awaiting new work, the kernel sends MM a message containing
  647. 17999  * the process slot and bit map.  That message comes here.  The File System
  648. 18000  * also uses this mechanism to signal writing on broken pipes (SIGPIPE).
  649. 18001  */
  650. 18002
  651. 18003   register struct mproc *rmp;
  652. 18004   int i, proc_nr;
  653. 18005   pid_t proc_id, id;
  654. 18006   sigset_t sig_map;
  655. 18007
  656. 18008   /* Only kernel may make this call. */
  657. 18009   if (who != HARDWARE) return(EPERM);
  658. 18010   dont_reply = TRUE;            /* don't reply to the kernel */
  659. 18011   proc_nr = mm_in.SIG_PROC;
  660. 18012   rmp = &mproc[proc_nr];
  661. 18013   if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
  662. 18014   proc_id = rmp->mp_pid;
  663. 18015   sig_map = (sigset_t) mm_in.SIG_MAP;
  664. 18016   mp = &mproc[0];               /* pretend kernel signals are from MM */
  665. 18017   mp->mp_procgrp = rmp->mp_procgrp;     /* get process group right */
  666. 18018
  667. 18019   /* Check each bit in turn to see if a signal is to be sent.  Unlike
  668. 18020    * kill(), the kernel may collect several unrelated signals for a
  669. 18021    * process and pass them to MM in one blow.  Thus loop on the bit
  670. 18022    * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
  671. 18023    * to the recipient's process group.  For SIGKILL, use proc_id -1 to
  672. 18024    * indicate a systemwide broadcast.
  673. 18025    */
  674. 18026   for (i = 1; i <= _NSIG; i++) {
  675. 18027         if (!sigismember(&sig_map, i)) continue;
  676. 18028         switch (i) {
  677. 18029             case SIGINT:
  678. 18030             case SIGQUIT:
  679. 18031                 id = 0; break;  /* broadcast to process group */
  680. 18032             case SIGKILL:
  681. 18033                 id = -1; break; /* broadcast to all except INIT */
  682. 18034             case SIGALRM:
  683. 18035                 /* Disregard SIGALRM when the target process has not
  684. 18036                  * requested an alarm.  This only applies for a KERNEL
  685. 18037                  * generated signal.
  686. 18038                  */
  687. 18039                 if ((rmp->mp_flags & ALARM_ON) == 0) continue;
  688. 18040                 rmp->mp_flags &= ~ALARM_ON;
  689. 18041                 /* fall through */
  690. 18042             default:
  691. 18043                 id = proc_id;
  692. 18044                 break;
  693. 18045         }
  694. 18046         check_sig(id, i);
  695. 18047         sys_endsig(proc_nr);    /* tell kernel it's done */
  696. 18048   }
  697. 18049   return(OK);
  698. 18050 }
  699. 18053 /*===========================================================================*
  700. 18054  *                              do_alarm                                     *
  701. 18055  *===========================================================================*/
  702. 18056 PUBLIC int do_alarm()
  703. 18057 {
  704. 18058 /* Perform the alarm(seconds) system call. */
  705. 18059
  706. 18060   return(set_alarm(who, seconds));
  707. 18061 }
  708. 18064 /*===========================================================================*
  709. 18065  *                              set_alarm                                    *
  710. 18066  *===========================================================================*/
  711. 18067 PUBLIC int set_alarm(proc_nr, sec)
  712. 18068 int proc_nr;                    /* process that wants the alarm */
  713. 18069 int sec;                        /* how many seconds delay before the signal */
  714. 18070 {
  715. 18071 /* This routine is used by do_alarm() to set the alarm timer.  It is also used
  716. 18072  * to turn the timer off when a process exits with the timer still on.
  717. 18073  */
  718. 18074
  719. 18075   message m_sig;
  720. 18076   int remaining;
  721. 18077
  722. 18078   if (sec != 0)
  723. 18079         mproc[proc_nr].mp_flags |= ALARM_ON;
  724. 18080   else
  725. 18081         mproc[proc_nr].mp_flags &= ~ALARM_ON;
  726. 18082
  727. 18083   /* Tell the clock task to provide a signal message when the time comes.
  728. 18084    *
  729. 18085    * Large delays cause a lot of problems.  First, the alarm system call
  730. 18086    * takes an unsigned seconds count and the library has cast it to an int.
  731. 18087    * That probably works, but on return the library will convert "negative"
  732. 18088    * unsigneds to errors.  Presumably no one checks for these errors, so
  733. 18089    * force this call through.  Second, If unsigned and long have the same
  734. 18090    * size, converting from seconds to ticks can easily overflow.  Finally,
  735. 18091    * the kernel has similar overflow bugs adding ticks.
  736. 18092    *
  737. 18093    * Fixing this requires a lot of ugly casts to fit the wrong interface
  738. 18094    * types and to avoid overflow traps.  DELTA_TICKS has the right type
  739. 18095    * (clock_t) although it is declared as long.  How can variables like
  740. 18096    * this be declared properly without combinatorial explosion of message
  741. 18097    * types?
  742. 18098    */
  743. 18099   m_sig.m_type = SET_ALARM;
  744. 18100   m_sig.CLOCK_PROC_NR = proc_nr;
  745. 18101   m_sig.DELTA_TICKS = (clock_t) (HZ * (unsigned long) (unsigned) sec);
  746. 18102   if ( (unsigned long) m_sig.DELTA_TICKS / HZ != (unsigned) sec)
  747. 18103         m_sig.DELTA_TICKS = LONG_MAX;   /* eternity (really CLOCK_T_MAX) */
  748. 18104   if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
  749. 18105   remaining = (int) m_sig.SECONDS_LEFT;
  750. 18106   if (remaining != m_sig.SECONDS_LEFT || remaining < 0)
  751. 18107         remaining = INT_MAX;    /* true value is not representable */
  752. 18108   return(remaining);
  753. 18109 }
  754. 18112 /*===========================================================================*
  755. 18113  *                              do_pause                                     *
  756. 18114  *===========================================================================*/
  757. 18115 PUBLIC int do_pause()
  758. 18116 {
  759. 18117 /* Perform the pause() system call. */
  760. 18118
  761. 18119   mp->mp_flags |= PAUSED;
  762. 18120   dont_reply = TRUE;
  763. 18121   return(OK);
  764. 18122 }
  765. 18125 /*=====================================================================*
  766. 18126  *                          do_reboot                                  *
  767. 18127  *=====================================================================*/
  768. 18128 PUBLIC int do_reboot()
  769. 18129 {
  770. 18130   register struct mproc *rmp = mp;
  771. 18131   char monitor_code[64];
  772. 18132
  773. 18133   if (rmp->mp_effuid != SUPER_USER)   return EPERM;
  774. 18134
  775. 18135   switch (reboot_flag) {
  776. 18136   case RBT_HALT:
  777. 18137   case RBT_REBOOT:
  778. 18138   case RBT_PANIC:
  779. 18139   case RBT_RESET:
  780. 18140         break;
  781. 18141   case RBT_MONITOR:
  782. 18142         if (reboot_size > sizeof(monitor_code)) return EINVAL;
  783. 18143         memset(monitor_code, 0, sizeof(monitor_code));
  784. 18144         if (sys_copy(who, D, (phys_bytes) reboot_code,
  785. 18145                 MM_PROC_NR, D, (phys_bytes) monitor_code,
  786. 18146                 (phys_bytes) reboot_size) != OK) return EFAULT;
  787. 18147         if (monitor_code[sizeof(monitor_code)-1] != 0) return EINVAL;
  788. 18148         break;
  789. 18149   default:
  790. 18150         return EINVAL;
  791. 18151   }
  792. 18152
  793. 18153   /* Kill all processes except init. */
  794. 18154   check_sig(-1, SIGKILL);
  795. 18155
  796. 18156   tell_fs(EXIT, INIT_PROC_NR, 0, 0);    /* cleanup init */
  797. 18157
  798. 18158   tell_fs(SYNC,0,0,0);
  799. 18159
  800. 18160   sys_abort(reboot_flag, monitor_code);
  801. 18161   /* NOTREACHED */
  802. 18162 }
  803. 18165 /*===========================================================================*
  804. 18166  *                              sig_proc                                     *
  805. 18167  *===========================================================================*/
  806. 18168 PUBLIC void sig_proc(rmp, signo)
  807. 18169 register struct mproc *rmp;     /* pointer to the process to be signaled */
  808. 18170 int signo;                      /* signal to send to process (1 to _NSIG) */
  809. 18171 {
  810. 18172 /* Send a signal to a process.  Check to see if the signal is to be caught,
  811. 18173  * ignored, or blocked.  If the signal is to be caught, coordinate with
  812. 18174  * KERNEL to push a sigcontext structure and a sigframe structure onto
  813. 18175  * the catcher's stack.  Also, KERNEL will reset the program counter and
  814. 18176  * stack pointer, so that when the process next runs, it will be executing
  815. 18177  * the signal handler.  When the signal handler returns,  sigreturn(2)
  816. 18178  * will be called.  Then KERNEL will restore the signal context from the
  817. 18179  * sigcontext structure.
  818. 18180  *
  819. 18181  * If there is insufficient stack space, kill the process.
  820. 18182  */
  821. 18183
  822. 18184   vir_bytes new_sp;
  823. 18185   int slot;
  824. 18186   int sigflags;
  825. 18187   struct sigmsg sm;
  826. 18188
  827. 18189   slot = (int) (rmp - mproc);
  828. 18190   if (!(rmp->mp_flags & IN_USE)) {
  829. 18191         printf("MM: signal %d sent to dead process %dn", signo, slot);
  830. 18192         panic("", NO_NUM);
  831. 18193   }
  832. 18194   if (rmp->mp_flags & HANGING) {
  833. 18195         printf("MM: signal %d sent to HANGING process %dn", signo, slot);
  834. 18196         panic("", NO_NUM);
  835. 18197   }
  836. 18198   if (rmp->mp_flags & TRACED && signo != SIGKILL) {
  837. 18199         /* A traced process has special handling. */
  838. 18200         unpause(slot);
  839. 18201         stop_proc(rmp, signo);  /* a signal causes it to stop */
  840. 18202         return;
  841. 18203   }
  842. 18204   /* Some signals are ignored by default. */
  843. 18205   if (sigismember(&rmp->mp_ignore, signo)) return; 
  844. 18206
  845. 18207   if (sigismember(&rmp->mp_sigmask, signo)) {
  846. 18208         /* Signal should be blocked. */
  847. 18209         sigaddset(&rmp->mp_sigpending, signo);
  848. 18210         return;
  849. 18211   }
  850. 18212   sigflags = rmp->mp_sigact[signo].sa_flags;
  851. 18213   if (sigismember(&rmp->mp_catch, signo)) {
  852. 18214         if (rmp->mp_flags & SIGSUSPENDED)
  853. 18215                 sm.sm_mask = rmp->mp_sigmask2;
  854. 18216         else
  855. 18217                 sm.sm_mask = rmp->mp_sigmask;
  856. 18218         sm.sm_signo = signo;
  857. 18219         sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
  858. 18220         sm.sm_sigreturn = rmp->mp_sigreturn;
  859. 18221         sys_getsp(slot, &new_sp);
  860. 18222         sm.sm_stkptr = new_sp;
  861. 18223
  862. 18224         /* Make room for the sigcontext and sigframe struct. */
  863. 18225         new_sp -= sizeof(struct sigcontext)
  864. 18226                                  + 3 * sizeof(char *) + 2 * sizeof(int);
  865. 18227
  866. 18228         if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
  867. 18229                 goto doterminate;
  868. 18230
  869. 18231         rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
  870. 18232         if (sigflags & SA_NODEFER)
  871. 18233                 sigdelset(&rmp->mp_sigmask, signo);
  872. 18234         else
  873. 18235                 sigaddset(&rmp->mp_sigmask, signo);
  874. 18236
  875. 18237         if (sigflags & SA_RESETHAND) {
  876. 18238                 sigdelset(&rmp->mp_catch, signo);
  877. 18239                 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
  878. 18240         }
  879. 18241
  880. 18242         sys_sendsig(slot, &sm);
  881. 18243         sigdelset(&rmp->mp_sigpending, signo);
  882. 18244         /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
  883. 18245          * release it.
  884. 18246          */
  885. 18247         unpause(slot);
  886. 18248         return;
  887. 18249   }
  888. 18250 doterminate:
  889. 18251   /* Signal should not or cannot be caught.  Terminate the process. */
  890. 18252   rmp->mp_sigstatus = (char) signo;
  891. 18253   if (sigismember(&core_sset, signo)) {
  892. 18254         /* Switch to the user's FS environment and dump core. */
  893. 18255         tell_fs(CHDIR, slot, FALSE, 0);
  894. 18256         dump_core(rmp);
  895. 18257   }
  896. 18258   mm_exit(rmp, 0);              /* terminate process */
  897. 18259 }
  898. 18262 /*===========================================================================*
  899. 18263  *                              check_sig                                    *
  900. 18264  *===========================================================================*/
  901. 18265 PUBLIC int check_sig(proc_id, signo)
  902. 18266 pid_t proc_id;                  /* pid of proc to sig, or 0 or -1, or -pgrp */
  903. 18267 int signo;                      /* signal to send to process (0 to _NSIG) */
  904. 18268 {
  905. 18269 /* Check to see if it is possible to send a signal.  The signal may have to be
  906. 18270  * sent to a group of processes.  This routine is invoked by the KILL system
  907. 18271  * call, and also when the kernel catches a DEL or other signal.
  908. 18272  */
  909. 18273
  910. 18274   register struct mproc *rmp;
  911. 18275   int count;                    /* count # of signals sent */
  912. 18276   int error_code;
  913. 18277
  914. 18278   if (signo < 0 || signo > _NSIG) return(EINVAL);
  915. 18279
  916. 18280   /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
  917. 18281   if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
  918. 18282
  919. 18283   /* Search the proc table for processes to signal.  (See forkexit.c about
  920. 18284    * pid magic.)
  921. 18285    */
  922. 18286   count = 0;
  923. 18287   error_code = ESRCH;
  924. 18288   for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
  925. 18289         if ( (rmp->mp_flags & IN_USE) == 0) continue;
  926. 18290         if (rmp->mp_flags & HANGING && signo != 0) continue;
  927. 18291
  928. 18292         /* Check for selection. */
  929. 18293         if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
  930. 18294         if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
  931. 18295         if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
  932. 18296         if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
  933. 18297
  934. 18298         /* Check for permission. */
  935. 18299         if (mp->mp_effuid != SUPER_USER
  936. 18300             && mp->mp_realuid != rmp->mp_realuid
  937. 18301             && mp->mp_effuid != rmp->mp_realuid
  938. 18302             && mp->mp_realuid != rmp->mp_effuid
  939. 18303             && mp->mp_effuid != rmp->mp_effuid) {
  940. 18304                 error_code = EPERM;
  941. 18305                 continue;
  942. 18306         }
  943. 18307
  944. 18308         count++;
  945. 18309         if (signo == 0) continue;
  946. 18310
  947. 18311         /* 'sig_proc' will handle the disposition of the signal.  The
  948. 18312          * signal may be caught, blocked, ignored, or cause process
  949. 18313          * termination, possibly with core dump.
  950. 18314          */
  951. 18315         sig_proc(rmp, signo);
  952. 18316
  953. 18317         if (proc_id > 0) break; /* only one process being signaled */
  954. 18318   }
  955. 18319
  956. 18320   /* If the calling process has killed itself, don't reply. */
  957. 18321   if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
  958. 18322         dont_reply = TRUE;
  959. 18323   return(count > 0 ? OK : error_code);
  960. 18324 }
  961. 18327 /*===========================================================================*
  962. 18328  *                               check_pending                               *
  963. 18329  *===========================================================================*/
  964. 18330 PRIVATE void check_pending()
  965. 18331 {
  966. 18332   /* Check to see if any pending signals have been unblocked.  The
  967. 18333    * first such signal found is delivered.
  968. 18334    *
  969. 18335    * If multiple pending unmasked signals are found, they will be
  970. 18336    * delivered sequentially.
  971. 18337    *
  972. 18338    * There are several places in this file where the signal mask is
  973. 18339    * changed.  At each such place, check_pending() should be called to
  974. 18340    * check for newly unblocked signals.
  975. 18341    */
  976. 18342
  977. 18343   int i;
  978. 18344
  979. 18345   for (i = 1; i < _NSIG; i++) {
  980. 18346         if (sigismember(&mp->mp_sigpending, i) &&
  981. 18347                 !sigismember(&mp->mp_sigmask, i)) {
  982. 18348                 sigdelset(&mp->mp_sigpending, i);
  983. 18349                 sig_proc(mp, i);
  984. 18350                 break;
  985. 18351         }
  986. 18352   }
  987. 18353 }
  988. 18356 /*===========================================================================*
  989. 18357  *                              unpause                                      *
  990. 18358  *===========================================================================*/
  991. 18359 PRIVATE void unpause(pro)
  992. 18360 int pro;                        /* which process number */
  993. 18361 {
  994. 18362 /* A signal is to be sent to a process.  If that process is hanging on a
  995. 18363  * system call, the system call must be terminated with EINTR.  Possible
  996. 18364  * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
  997. 18365  * First check if the process is hanging on an MM call.  If not, tell FS,
  998. 18366  * so it can check for READs and WRITEs from pipes, ttys and the like.
  999. 18367  */
  1000. 18368
  1001. 18369   register struct mproc *rmp;
  1002. 18370
  1003. 18371   rmp = &mproc[pro];
  1004. 18372
  1005. 18373   /* Check to see if process is hanging on a PAUSE call. */
  1006. 18374   if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
  1007. 18375         rmp->mp_flags &= ~PAUSED;
  1008. 18376         reply(pro, EINTR, 0, NIL_PTR);
  1009. 18377         return;
  1010. 18378   }
  1011. 18379
  1012. 18380   /* Check to see if process is hanging on a WAIT call. */
  1013. 18381   if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
  1014. 18382         rmp->mp_flags &= ~WAITING;
  1015. 18383         reply(pro, EINTR, 0, NIL_PTR);
  1016. 18384         return;
  1017. 18385   }
  1018. 18386
  1019. 18387   /* Check to see if process is hanging on a SIGSUSPEND call. */
  1020. 18388   if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
  1021. 18389         rmp->mp_flags &= ~SIGSUSPENDED;
  1022. 18390         reply(pro, EINTR, 0, NIL_PTR);
  1023. 18391         return;
  1024. 18392   }
  1025. 18393
  1026. 18394   /* Process is not hanging on an MM call.  Ask FS to take a look. */
  1027. 18395         tell_fs(UNPAUSE, pro, 0, 0);
  1028. 18396 }
  1029. 18399 /*===========================================================================*
  1030. 18400  *                              dump_core                                    *
  1031. 18401  *===========================================================================*/
  1032. 18402 PRIVATE void dump_core(rmp)
  1033. 18403 register struct mproc *rmp;     /* whose core is to be dumped */
  1034. 18404 {
  1035. 18405 /* Make a core dump on the file "core", if possible. */
  1036. 18406
  1037. 18407   int fd, fake_fd, nr_written, seg, slot;
  1038. 18408   char *buf;
  1039. 18409   vir_bytes current_sp;
  1040. 18410   phys_bytes left;              /* careful; 64K might overflow vir_bytes */
  1041. 18411   unsigned nr_to_write;         /* unsigned for arg to write() but < INT_MAX */
  1042. 18412   long trace_data, trace_off;
  1043. 18413
  1044. 18414   slot = (int) (rmp - mproc);
  1045. 18415
  1046. 18416   /* Can core file be written?  We are operating in the user's FS environment,
  1047. 18417    * so no special permission checks are needed.
  1048. 18418    */
  1049. 18419   if (rmp->mp_realuid != rmp->mp_effuid) return;
  1050. 18420   if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
  1051. 18421   rmp->mp_sigstatus |= DUMPED;
  1052. 18422
  1053. 18423   /* Make sure the stack segment is up to date.
  1054. 18424    * We don't want adjust() to fail unless current_sp is preposterous,
  1055. 18425    * but it might fail due to safety checking.  Also, we don't really want 
  1056. 18426    * the adjust() for sending a signal to fail due to safety checking.  
  1057. 18427    * Maybe make SAFETY_BYTES a parameter.
  1058. 18428    */
  1059. 18429   sys_getsp(slot, &current_sp);
  1060. 18430   adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
  1061. 18431
  1062. 18432   /* Write the memory map of all segments to begin the core file. */
  1063. 18433   if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
  1064. 18434       != (unsigned) sizeof rmp->mp_seg) {
  1065. 18435         close(fd);
  1066. 18436         return;
  1067. 18437   }
  1068. 18438
  1069. 18439   /* Write out the whole kernel process table entry to get the regs. */
  1070. 18440   trace_off = 0;
  1071. 18441   while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
  1072. 18442         if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
  1073. 18443             != (unsigned) sizeof (long)) {
  1074. 18444                 close(fd);
  1075. 18445                 return;
  1076. 18446         }
  1077. 18447         trace_off += sizeof (long);
  1078. 18448   }
  1079. 18449
  1080. 18450   /* Loop through segments and write the segments themselves out. */
  1081. 18451   for (seg = 0; seg < NR_SEGS; seg++) {
  1082. 18452         buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
  1083. 18453         left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
  1084. 18454         fake_fd = (slot << 8) | (seg << 6) | fd;
  1085. 18455
  1086. 18456         /* Loop through a segment, dumping it. */
  1087. 18457         while (left != 0) {
  1088. 18458                 nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
  1089. 18459                 if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
  1090. 18460                         close(fd);
  1091. 18461                         return;
  1092. 18462                 }
  1093. 18463                 buf += nr_written;
  1094. 18464                 left -= nr_written;
  1095. 18465         }
  1096. 18466   }
  1097. 18467   close(fd);
  1098. 18468 }
  1099. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1100. src/mm/getset.c    
  1101. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1102. 18500 /* This file handles the 4 system calls that get and set uids and gids.
  1103. 18501  * It also handles getpid(), setsid(), and getpgrp().  The code for each
  1104. 18502  * one is so tiny that it hardly seemed worthwhile to make each a separate
  1105. 18503  * function.
  1106. 18504  */
  1107. 18505
  1108. 18506 #include "mm.h"
  1109. 18507 #include <minix/callnr.h>
  1110. 18508 #include <signal.h>
  1111. 18509 #include "mproc.h"
  1112. 18510 #include "param.h"
  1113. 18511
  1114. 18512 /*===========================================================================*
  1115. 18513  *                              do_getset                                    *
  1116. 18514  *===========================================================================*/
  1117. 18515 PUBLIC int do_getset()
  1118. 18516 {
  1119. 18517 /* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID.  The four
  1120. 18518  * GETs and SETSID return their primary results in 'r'.  GETUID, GETGID, and
  1121. 18519  * GETPID also return secondary results (the effective IDs, or the parent
  1122. 18520  * process ID) in 'result2', which is returned to the user.
  1123. 18521  */
  1124. 18522
  1125. 18523   register struct mproc *rmp = mp;
  1126. 18524   register int r;
  1127. 18525
  1128. 18526   switch(mm_call) {
  1129. 18527         case GETUID:
  1130. 18528                 r = rmp->mp_realuid;
  1131. 18529                 result2 = rmp->mp_effuid;
  1132. 18530                 break;
  1133. 18531
  1134. 18532         case GETGID:
  1135. 18533                 r = rmp->mp_realgid;
  1136. 18534                 result2 = rmp->mp_effgid;
  1137. 18535                 break;
  1138. 18536
  1139. 18537         case GETPID:
  1140. 18538                 r = mproc[who].mp_pid;
  1141. 18539                 result2 = mproc[rmp->mp_parent].mp_pid;
  1142. 18540                 break;
  1143. 18541
  1144. 18542         case SETUID:
  1145. 18543                 if (rmp->mp_realuid != usr_id && rmp->mp_effuid != SUPER_USER)
  1146. 18544                         return(EPERM);
  1147. 18545                 rmp->mp_realuid = usr_id;
  1148. 18546                 rmp->mp_effuid = usr_id;
  1149. 18547                 tell_fs(SETUID, who, usr_id, usr_id);
  1150. 18548                 r = OK;
  1151. 18549                 break;
  1152. 18550
  1153. 18551         case SETGID:
  1154. 18552                 if (rmp->mp_realgid != grpid && rmp->mp_effuid != SUPER_USER)
  1155. 18553                         return(EPERM);
  1156. 18554                 rmp->mp_realgid = grpid;
  1157. 18555                 rmp->mp_effgid = grpid;
  1158. 18556                 tell_fs(SETGID, who, grpid, grpid);
  1159. 18557                 r = OK;
  1160. 18558                 break;
  1161. 18559
  1162. 18560         case SETSID:
  1163. 18561                 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
  1164. 18562                 rmp->mp_procgrp = rmp->mp_pid;
  1165. 18563                 tell_fs(SETSID, who, 0, 0);
  1166. 18564                 /*FALL THROUGH*/
  1167. 18565
  1168. 18566         case GETPGRP:
  1169. 18567                 r = rmp->mp_procgrp;
  1170. 18568                 break;
  1171. 18569
  1172. 18570         default:
  1173. 18571                 r = EINVAL;
  1174. 18572                 break;  
  1175. 18573   }
  1176. 18574   return(r);
  1177. 18575 }
  1178. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1179. src/mm/trace.c    
  1180. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1181. 18600 /* This file handles the memory manager's part of debugging, using the 
  1182. 18601  * ptrace system call. Most of the commands are passed on to the system
  1183. 18602  * task for completion.
  1184. 18603  *
  1185. 18604  * The debugging commands available are:
  1186. 18605  * T_STOP       stop the process 
  1187. 18606  * T_OK         enable tracing by parent for this process
  1188. 18607  * T_GETINS     return value from instruction space 
  1189. 18608  * T_GETDATA    return value from data space 
  1190. 18609  * T_GETUSER    return value from user process table
  1191. 18610  * T_SETINS     set value in instruction space
  1192. 18611  * T_SETDATA    set value in data space
  1193. 18612  * T_SETUSER    set value in user process table 
  1194. 18613  * T_RESUME     resume execution 
  1195. 18614  * T_EXIT       exit
  1196. 18615  * T_STEP       set trace bit 
  1197. 18616  * 
  1198. 18617  * The T_OK and T_EXIT commands are handled here, and the T_RESUME and
  1199. 18618  * T_STEP commands are partially handled here and completed by the system
  1200. 18619  * task. The rest are handled entirely by the system task. 
  1201. 18620  */
  1202. 18621
  1203. 18622 #include "mm.h"
  1204. 18623 #include <sys/ptrace.h>
  1205. 18624 #include <signal.h>
  1206. 18625 #include "mproc.h"
  1207. 18626 #include "param.h"
  1208. 18627
  1209. 18628 #define NIL_MPROC       ((struct mproc *) 0)
  1210. 18629
  1211. 18630 FORWARD _PROTOTYPE( struct mproc *findproc, (pid_t lpid) );
  1212. 18631
  1213. 18632 /*===========================================================================*
  1214. 18633  *                              do_trace                                     *
  1215. 18634  *===========================================================================*/
  1216. 18635 PUBLIC int do_trace()
  1217. 18636 {
  1218. 18637   register struct mproc *child;
  1219. 18638
  1220. 18639   /* the T_OK call is made by the child fork of the debugger before it execs  
  1221. 18640    * the process to be traced
  1222. 18641    */
  1223. 18642   if (request == T_OK) {/* enable tracing by parent for this process */
  1224. 18643         mp->mp_flags |= TRACED;
  1225. 18644         mm_out.m2_l2 = 0;
  1226. 18645         return(OK);
  1227. 18646   }
  1228. 18647   if ((child = findproc(pid)) == NIL_MPROC || !(child->mp_flags & STOPPED)) {
  1229. 18648         return(ESRCH);
  1230. 18649   }
  1231. 18650   /* all the other calls are made by the parent fork of the debugger to 
  1232. 18651    * control execution of the child
  1233. 18652    */
  1234. 18653   switch (request) {
  1235. 18654   case T_EXIT:          /* exit */
  1236. 18655         mm_exit(child, (int)data);
  1237. 18656         mm_out.m2_l2 = 0;
  1238. 18657         return(OK);
  1239. 18658   case T_RESUME: 
  1240. 18659   case T_STEP:          /* resume execution */
  1241. 18660         if (data < 0 || data > _NSIG) return(EIO);
  1242. 18661         if (data > 0) {         /* issue signal */
  1243. 18662                 child->mp_flags &= ~TRACED;  /* so signal is not diverted */
  1244. 18663                 sig_proc(child, (int) data);
  1245. 18664                 child->mp_flags |= TRACED;
  1246. 18665         }
  1247. 18666         child->mp_flags &= ~STOPPED;
  1248. 18667         break;
  1249. 18668   }
  1250. 18669   if (sys_trace(request, (int) (child - mproc), taddr, &data) != OK)
  1251. 18670         return(-errno);
  1252. 18671   mm_out.m2_l2 = data;
  1253. 18672   return(OK);
  1254. 18673 }
  1255. 18675 /*===========================================================================*
  1256. 18676  *                              findproc                                     *
  1257. 18677  *===========================================================================*/
  1258. 18678 PRIVATE struct mproc *findproc(lpid)
  1259. 18679 pid_t lpid;
  1260. 18680 {
  1261. 18681   register struct mproc *rmp;
  1262. 18682
  1263. 18683   for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++)
  1264. 18684         if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
  1265. 18685   return(NIL_MPROC);
  1266. 18686 }
  1267. 18688 /*===========================================================================*
  1268. 18689  *                              stop_proc                                    *
  1269. 18690  *===========================================================================*/
  1270. 18691 PUBLIC void stop_proc(rmp, signo)
  1271. 18692 register struct mproc *rmp;
  1272. 18693 int signo;
  1273. 18694 {
  1274. 18695 /* A traced process got a signal so stop it. */
  1275. 18696
  1276. 18697   register struct mproc *rpmp = mproc + rmp->mp_parent;
  1277. 18698
  1278. 18699   if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return;
  1279. 18700   rmp->mp_flags |= STOPPED;
  1280. 18701   if (rpmp->mp_flags & WAITING) {
  1281. 18702         rpmp->mp_flags &= ~WAITING;     /* parent is no longer waiting */
  1282. 18703         reply(rmp->mp_parent, rmp->mp_pid, 0177 | (signo << 8), NIL_PTR);
  1283. 18704   } else {
  1284. 18705         rmp->mp_sigstatus = signo;
  1285. 18706   }
  1286. 18707   return;
  1287. 18708 }
  1288. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1289. src/mm/alloc.c    
  1290. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1291. 18800 /* This file is concerned with allocating and freeing arbitrary-size blocks of
  1292. 18801  * physical memory on behalf of the FORK and EXEC system calls.  The key data
  1293. 18802  * structure used is the hole table, which maintains a list of holes in memory.
  1294. 18803  * It is kept sorted in order of increasing memory address. The addresses
  1295. 18804  * it contains refer to physical memory, starting at absolute address 0
  1296. 18805  * (i.e., they are not relative to the start of MM).  During system
  1297. 18806  * initialization, that part of memory containing the interrupt vectors,
  1298. 18807  * kernel, and MM are "allocated" to mark them as not available and to
  1299. 18808  * remove them from the hole list.
  1300. 18809  *
  1301. 18810  * The entry points into this file are:
  1302. 18811  *   alloc_mem: allocate a given sized chunk of memory
  1303. 18812  *   free_mem:  release a previously allocated chunk of memory
  1304. 18813  *   mem_init:  initialize the tables when MM start up
  1305. 18814  *   max_hole:  returns the largest hole currently available
  1306. 18815  */
  1307. 18816
  1308. 18817 #include "mm.h"
  1309. 18818 #include <minix/com.h>
  1310. 18819
  1311. 18820 #define NR_HOLES         128    /* max # entries in hole table */
  1312. 18821 #define NIL_HOLE (struct hole *) 0
  1313. 18822
  1314. 18823 PRIVATE struct hole {
  1315. 18824   phys_clicks h_base;           /* where does the hole begin? */
  1316. 18825   phys_clicks h_len;            /* how big is the hole? */
  1317. 18826   struct hole *h_next;          /* pointer to next entry on the list */
  1318. 18827 } hole[NR_HOLES];
  1319. 18828
  1320. 18829
  1321. 18830 PRIVATE struct hole *hole_head; /* pointer to first hole */
  1322. 18831 PRIVATE struct hole *free_slots;        /* ptr to list of unused table slots */
  1323. 18832
  1324. 18833 FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
  1325. 18834 FORWARD _PROTOTYPE( void merge, (struct hole *hp)                           );
  1326. 18835
  1327. 18836
  1328. 18837 /*===========================================================================*
  1329. 18838  *                              alloc_mem                                    *
  1330. 18839  *===========================================================================*/
  1331. 18840 PUBLIC phys_clicks alloc_mem(clicks)
  1332. 18841 phys_clicks clicks;             /* amount of memory requested */
  1333. 18842 {
  1334. 18843 /* Allocate a block of memory from the free list using first fit. The block
  1335. 18844  * consists of a sequence of contiguous bytes, whose length in clicks is
  1336. 18845  * given by 'clicks'.  A pointer to the block is returned.  The block is
  1337. 18846  * always on a click boundary.  This procedure is called when memory is
  1338. 18847  * needed for FORK or EXEC.
  1339. 18848  */
  1340. 18849
  1341. 18850   register struct hole *hp, *prev_ptr;
  1342. 18851   phys_clicks old_base;
  1343. 18852
  1344. 18853   hp = hole_head;
  1345. 18854   while (hp != NIL_HOLE) {
  1346. 18855         if (hp->h_len >= clicks) {
  1347. 18856                 /* We found a hole that is big enough.  Use it. */
  1348. 18857                 old_base = hp->h_base;  /* remember where it started */
  1349. 18858                 hp->h_base += clicks;   /* bite a piece off */
  1350. 18859                 hp->h_len -= clicks;    /* ditto */
  1351. 18860
  1352. 18861                 /* If hole is only partly used, reduce size and return. */
  1353. 18862                 if (hp->h_len != 0) return(old_base);
  1354. 18863
  1355. 18864                 /* The entire hole has been used up.  Manipulate free list. */
  1356. 18865                 del_slot(prev_ptr, hp);
  1357. 18866                 return(old_base);
  1358. 18867         }
  1359. 18868
  1360. 18869         prev_ptr = hp;
  1361. 18870         hp = hp->h_next;
  1362. 18871   }
  1363. 18872   return(NO_MEM);
  1364. 18873 }
  1365. 18876 /*===========================================================================*
  1366. 18877  *                              free_mem                                     *
  1367. 18878  *===========================================================================*/
  1368. 18879 PUBLIC void free_mem(base, clicks)
  1369. 18880 phys_clicks base;               /* base address of block to free */
  1370. 18881 phys_clicks clicks;             /* number of clicks to free */
  1371. 18882 {
  1372. 18883 /* Return a block of free memory to the hole list.  The parameters tell where
  1373. 18884  * the block starts in physical memory and how big it is.  The block is added
  1374. 18885  * to the hole list.  If it is contiguous with an existing hole on either end,
  1375. 18886  * it is merged with the hole or holes.
  1376. 18887  */
  1377. 18888
  1378. 18889   register struct hole *hp, *new_ptr, *prev_ptr;
  1379. 18890
  1380. 18891   if (clicks == 0) return;
  1381. 18892   if ( (new_ptr = free_slots) == NIL_HOLE) panic("Hole table full", NO_NUM);
  1382. 18893   new_ptr->h_base = base;
  1383. 18894   new_ptr->h_len = clicks;
  1384. 18895   free_slots = new_ptr->h_next;
  1385. 18896   hp = hole_head;
  1386. 18897
  1387. 18898   /* If this block's address is numerically less than the lowest hole currently
  1388. 18899    * available, or if no holes are currently available, put this hole on the
  1389. 18900    * front of the hole list.
  1390. 18901    */
  1391. 18902   if (hp == NIL_HOLE || base <= hp->h_base) {
  1392. 18903         /* Block to be freed goes on front of the hole list. */
  1393. 18904         new_ptr->h_next = hp;
  1394. 18905         hole_head = new_ptr;
  1395. 18906         merge(new_ptr);
  1396. 18907         return;
  1397. 18908   }
  1398. 18909
  1399. 18910   /* Block to be returned does not go on front of hole list. */
  1400. 18911   while (hp != NIL_HOLE && base > hp->h_base) {
  1401. 18912         prev_ptr = hp;
  1402. 18913         hp = hp->h_next;
  1403. 18914   }
  1404. 18915
  1405. 18916   /* We found where it goes.  Insert block after 'prev_ptr'. */
  1406. 18917   new_ptr->h_next = prev_ptr->h_next;
  1407. 18918   prev_ptr->h_next = new_ptr;
  1408. 18919   merge(prev_ptr);              /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
  1409. 18920 }
  1410. 18923 /*===========================================================================*
  1411. 18924  *                              del_slot                                     *
  1412. 18925  *===========================================================================*/
  1413. 18926 PRIVATE void del_slot(prev_ptr, hp)
  1414. 18927 register struct hole *prev_ptr; /* pointer to hole entry just ahead of 'hp' */
  1415. 18928 register struct hole *hp;       /* pointer to hole entry to be removed */
  1416. 18929 {
  1417. 18930 /* Remove an entry from the hole list.  This procedure is called when a
  1418. 18931  * request to allocate memory removes a hole in its entirety, thus reducing
  1419. 18932  * the numbers of holes in memory, and requiring the elimination of one
  1420. 18933  * entry in the hole list.
  1421. 18934  */
  1422. 18935
  1423. 18936   if (hp == hole_head)
  1424. 18937         hole_head = hp->h_next;
  1425. 18938   else
  1426. 18939         prev_ptr->h_next = hp->h_next;
  1427. 18940
  1428. 18941   hp->h_next = free_slots;
  1429. 18942   free_slots = hp;
  1430. 18943 }
  1431. 18946 /*===========================================================================*
  1432. 18947  *                              merge                                        *
  1433. 18948  *===========================================================================*/
  1434. 18949 PRIVATE void merge(hp)
  1435. 18950 register struct hole *hp;       /* ptr to hole to merge with its successors */
  1436. 18951 {
  1437. 18952 /* Check for contiguous holes and merge any found.  Contiguous holes can occur
  1438. 18953  * when a block of memory is freed, and it happens to abut another hole on
  1439. 18954  * either or both ends.  The pointer 'hp' points to the first of a series of
  1440. 18955  * three holes that can potentially all be merged together.
  1441. 18956  */
  1442. 18957
  1443. 18958   register struct hole *next_ptr;
  1444. 18959
  1445. 18960   /* If 'hp' points to the last hole, no merging is possible.  If it does not,
  1446. 18961    * try to absorb its successor into it and free the successor's table entry.
  1447. 18962    */
  1448. 18963   if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
  1449. 18964   if (hp->h_base + hp->h_len == next_ptr->h_base) {
  1450. 18965         hp->h_len += next_ptr->h_len;   /* first one gets second one's mem */
  1451. 18966         del_slot(hp, next_ptr);
  1452. 18967   } else {
  1453. 18968         hp = next_ptr;
  1454. 18969   }
  1455. 18970
  1456. 18971   /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
  1457. 18972    * successor into it.
  1458. 18973    */
  1459. 18974   if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
  1460. 18975   if (hp->h_base + hp->h_len == next_ptr->h_base) {
  1461. 18976         hp->h_len += next_ptr->h_len;
  1462. 18977         del_slot(hp, next_ptr);
  1463. 18978   }
  1464. 18979 }
  1465. 18982 /*===========================================================================*
  1466. 18983  *                              max_hole                                     *
  1467. 18984  *===========================================================================*/
  1468. 18985 PUBLIC phys_clicks max_hole()
  1469. 18986 {
  1470. 18987 /* Scan the hole list and return the largest hole. */
  1471. 18988
  1472. 18989   register struct hole *hp;
  1473. 18990   register phys_clicks max;
  1474. 18991
  1475. 18992   hp = hole_head;
  1476. 18993   max = 0;
  1477. 18994   while (hp != NIL_HOLE) {
  1478. 18995         if (hp->h_len > max) max = hp->h_len;
  1479. 18996         hp = hp->h_next;
  1480. 18997   }
  1481. 18998   return(max);
  1482. 18999 }
  1483. 19002 /*===========================================================================*
  1484. 19003  *                              mem_init                                     *
  1485. 19004  *===========================================================================*/
  1486. 19005 PUBLIC void mem_init(total, free)
  1487. 19006 phys_clicks *total, *free;              /* memory size summaries */
  1488. 19007 {
  1489. 19008 /* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
  1490. 19009  * list of all the holes (unused memory) in the system; 'free_slots' points to
  1491. 19010  * a linked list of table entries that are not in use.  Initially, the former
  1492. 19011  * list has one entry for each chunk of physical memory, and the second
  1493. 19012  * list links together the remaining table slots.  As memory becomes more
  1494. 19013  * fragmented in the course of time (i.e., the initial big holes break up into
  1495. 19014  * smaller holes), new table slots are needed to represent them.  These slots
  1496. 19015  * are taken from the list headed by 'free_slots'.
  1497. 19016  */
  1498. 19017
  1499. 19018   register struct hole *hp;
  1500. 19019   phys_clicks base;             /* base address of chunk */
  1501. 19020   phys_clicks size;             /* size of chunk */
  1502. 19021   message mess;
  1503. 19022
  1504. 19023   /* Put all holes on the free list. */
  1505. 19024   for (hp = &hole[0]; hp < &hole[NR_HOLES]; hp++) hp->h_next = hp + 1;
  1506. 19025   hole[NR_HOLES-1].h_next = NIL_HOLE;
  1507. 19026   hole_head = NIL_HOLE;
  1508. 19027   free_slots = &hole[0];
  1509. 19028
  1510. 19029   /* Ask the kernel for chunks of physical memory and allocate a hole for
  1511. 19030    * each of them.  The SYS_MEM call responds with the base and size of the
  1512. 19031    * next chunk and the total amount of memory.
  1513. 19032    */
  1514. 19033   *free = 0;
  1515. 19034   for (;;) {
  1516. 19035         mess.m_type = SYS_MEM;
  1517. 19036         if (sendrec(SYSTASK, &mess) != OK) panic("bad SYS_MEM?", NO_NUM);
  1518. 19037         base = mess.m1_i1;
  1519. 19038         size = mess.m1_i2;
  1520. 19039         if (size == 0) break;           /* no more? */
  1521. 19040
  1522. 19041         free_mem(base, size);
  1523. 19042         *total = mess.m1_i3;
  1524. 19043         *free += size;
  1525. 19044   }
  1526. 19045 }
  1527. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1528. src/mm/utility.c    
  1529. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1530. 19100 /* This file contains some utility routines for MM.
  1531. 19101  *
  1532. 19102  * The entry points are:
  1533. 19103  *   allowed:   see if an access is permitted
  1534. 19104  *   no_sys:    this routine is called for invalid system call numbers
  1535. 19105  *   panic:     MM has run aground of a fatal error and cannot continue
  1536. 19106  *   tell_fs:   interface to FS
  1537. 19107  */
  1538. 19108
  1539. 19109 #include "mm.h"
  1540. 19110 #include <sys/stat.h>
  1541. 19111 #include <minix/callnr.h>
  1542. 19112 #include <minix/com.h>
  1543. 19113 #include <fcntl.h>
  1544. 19114 #include <signal.h>             /* needed only because mproc.h needs it */
  1545. 19115 #include "mproc.h"
  1546. 19116
  1547. 19117 /*===========================================================================*
  1548. 19118  *                              allowed                                      *
  1549. 19119  *===========================================================================*/
  1550. 19120 PUBLIC int allowed(name_buf, s_buf, mask)
  1551. 19121 char *name_buf;                 /* pointer to file name to be EXECed */
  1552. 19122 struct stat *s_buf;             /* buffer for doing and returning stat struct*/
  1553. 19123 int mask;                       /* R_BIT, W_BIT, or X_BIT */
  1554. 19124 {
  1555. 19125 /* Check to see if file can be accessed.  Return EACCES or ENOENT if the access
  1556. 19126  * is prohibited.  If it is legal open the file and return a file descriptor.
  1557. 19127  */
  1558. 19128
  1559. 19129   int fd;
  1560. 19130   int save_errno;
  1561. 19131
  1562. 19132   /* Use the fact that mask for access() is the same as the permissions mask.
  1563. 19133    * E.g., X_BIT in <minix/const.h> is the same as X_OK in <unistd.h> and
  1564. 19134    * S_IXOTH in <sys/stat.h>.  tell_fs(DO_CHDIR, ...) has set MM's real ids
  1565. 19135    * to the user's effective ids, so access() works right for setuid programs.
  1566. 19136    */
  1567. 19137   if (access(name_buf, mask) < 0) return(-errno);
  1568. 19138
  1569. 19139   /* The file is accessible but might not be readable.  Make it readable. */
  1570. 19140   tell_fs(SETUID, MM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
  1571. 19141
  1572. 19142   /* Open the file and fstat it.  Restore the ids early to handle errors. */
  1573. 19143   fd = open(name_buf, O_RDONLY);
  1574. 19144   save_errno = errno;           /* open might fail, e.g. from ENFILE */
  1575. 19145   tell_fs(SETUID, MM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
  1576. 19146   if (fd < 0) return(-save_errno);
  1577. 19147   if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);
  1578. 19148
  1579. 19149   /* Only regular files can be executed. */
  1580. 19150   if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) {
  1581. 19151         close(fd);
  1582. 19152         return(EACCES);
  1583. 19153   }
  1584. 19154   return(fd);
  1585. 19155 }
  1586. 19158 /*===========================================================================*
  1587. 19159  *                              no_sys                                       *
  1588. 19160  *===========================================================================*/
  1589. 19161 PUBLIC int no_sys()
  1590. 19162 {
  1591. 19163 /* A system call number not implemented by MM has been requested. */
  1592. 19164
  1593. 19165   return(EINVAL);
  1594. 19166 }
  1595. 19169 /*===========================================================================*
  1596. 19170  *                              panic                                        *
  1597. 19171  *===========================================================================*/
  1598. 19172 PUBLIC void panic(format, num)
  1599. 19173 char *format;                   /* format string */
  1600. 19174 int num;                        /* number to go with format string */
  1601. 19175 {
  1602. 19176 /* Something awful has happened.  Panics are caused when an internal
  1603. 19177  * inconsistency is detected, e.g., a programming error or illegal value of a
  1604. 19178  * defined constant.
  1605. 19179  */
  1606. 19180
  1607. 19181   printf("Memory manager panic: %s ", format);
  1608. 19182   if (num != NO_NUM) printf("%d",num);
  1609. 19183   printf("n");
  1610. 19184   tell_fs(SYNC, 0, 0, 0);       /* flush the cache to the disk */
  1611. 19185   sys_abort(RBT_PANIC);
  1612. 19186 }
  1613. 19189 /*===========================================================================*
  1614. 19190  *                              tell_fs                                      *
  1615. 19191  *===========================================================================*/
  1616. 19192 PUBLIC void tell_fs(what, p1, p2, p3)
  1617. 19193 int what, p1, p2, p3;
  1618. 19194 {
  1619. 19195 /* This routine is only used by MM to inform FS of certain events:
  1620. 19196  *      tell_fs(CHDIR, slot, dir, 0)
  1621. 19197  *      tell_fs(EXEC, proc, 0, 0)
  1622. 19198  *      tell_fs(EXIT, proc, 0, 0)
  1623. 19199  *      tell_fs(FORK, parent, child, pid)
  1624. 19200  *      tell_fs(SETGID, proc, realgid, effgid)
  1625. 19201  *      tell_fs(SETSID, proc, 0, 0)
  1626. 19202  *      tell_fs(SETUID, proc, realuid, effuid)
  1627. 19203  *      tell_fs(SYNC, 0, 0, 0)
  1628. 19204  *      tell_fs(UNPAUSE, proc, signr, 0)
  1629. 19205  */
  1630. 19206
  1631. 19207   message m;
  1632. 19208
  1633. 19209   m.m1_i1 = p1;
  1634. 19210   m.m1_i2 = p2;
  1635. 19211   m.m1_i3 = p3;
  1636. 19212   _taskcall(FS_PROC_NR, what, &m);
  1637. 19213 }
  1638. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1639. src/mm/putk.c    
  1640. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1641. 19300 /* MM must occasionally print some message.  It uses the standard library
  1642. 19301  * routine printk().  (The name "printf" is really a macro defined as 
  1643. 19302  * "printk"). Printing is done by calling the TTY task directly, not going 
  1644. 19303  * through FS.
  1645. 19304  */
  1646. 19305
  1647. 19306 #include "mm.h"
  1648. 19307 #include <minix/com.h>
  1649. 19308
  1650. 19309 #define BUF_SIZE          100   /* print buffer size */
  1651. 19310
  1652. 19311 PRIVATE int buf_count;          /* # characters in the buffer */
  1653. 19312 PRIVATE char print_buf[BUF_SIZE];       /* output is buffered here */
  1654. 19313 PRIVATE message putch_msg;      /* used for message to TTY task */
  1655. 19314
  1656. 19315 _PROTOTYPE( FORWARD void flush, (void) );
  1657. 19316
  1658. 19317 /*===========================================================================*
  1659. 19318  *                              putk                                         *
  1660. 19319  *===========================================================================*/
  1661. 19320 PUBLIC void putk(c)
  1662. 19321 int c;
  1663. 19322 {
  1664. 19323 /* Accumulate another character.  If 0 or buffer full, print it. */
  1665. 19324
  1666. 19325   if (c == 0 || buf_count == BUF_SIZE) flush();
  1667. 19326   if (c == 'n') putk('r');
  1668. 19327   if (c != 0) print_buf[buf_count++] = c;
  1669. 19328 }
  1670. 19331 /*===========================================================================*
  1671. 19332  *                              flush                                        *
  1672. 19333  *===========================================================================*/
  1673. 19334 PRIVATE void flush()
  1674. 19335 {
  1675. 19336 /* Flush the print buffer by calling TTY task. */
  1676. 19337
  1677. 19338   if (buf_count == 0) return;
  1678. 19339   putch_msg.m_type = DEV_WRITE;
  1679. 19340   putch_msg.PROC_NR  = 0;
  1680. 19341   putch_msg.TTY_LINE = 0;
  1681. 19342   putch_msg.ADDRESS  = print_buf;
  1682. 19343   putch_msg.COUNT = buf_count;
  1683. 19344   sendrec(TTY, &putch_msg);
  1684. 19345   buf_count = 0;
  1685. 19346 }
  1686. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1687. src/fs/fs.h    
  1688. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1689. 19400 /* This is the master header for fs.  It includes some other files
  1690. 19401  * and defines the principal constants.
  1691. 19402  */
  1692. 19403 #define _POSIX_SOURCE      1    /* tell headers to include POSIX stuff */
  1693. 19404 #define _MINIX             1    /* tell headers to include MINIX stuff */
  1694. 19405 #define _SYSTEM            1    /* tell headers that this is the kernel */
  1695. 19406
  1696. 19407 /* The following are so basic, all the *.c files get them automatically. */
  1697. 19408 #include <minix/config.h>       /* MUST be first */
  1698. 19409 #include <ansi.h>               /* MUST be second */
  1699. 19410 #include <sys/types.h>
  1700. 19411 #include <minix/const.h>
  1701. 19412 #include <minix/type.h>
  1702. 19413
  1703. 19414 #include <limits.h>
  1704. 19415 #include <errno.h>
  1705. 19416
  1706. 19417 #include <minix/syslib.h>
  1707. 19418
  1708. 19419 #include "const.h"
  1709. 19420 #include "type.h"
  1710. 19421 #include "proto.h"
  1711. 19422 #include "glo.h"
  1712. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1713. src/fs/const.h    
  1714. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1715. 19500 /* Tables sizes */
  1716. 19501 #define V1_NR_DZONES       7    /* # direct zone numbers in a V1 inode */
  1717. 19502 #define V1_NR_TZONES       9    /* total # zone numbers in a V1 inode */
  1718. 19503 #define V2_NR_DZONES       7    /* # direct zone numbers in a V2 inode */
  1719. 19504 #define V2_NR_TZONES      10    /* total # zone numbers in a V2 inode */
  1720. 19505
  1721. 19506 #define NR_FILPS         128    /* # slots in filp table */
  1722. 19507 #define NR_INODES         64    /* # slots in "in core" inode table */
  1723. 19508 #define NR_SUPERS          8    /* # slots in super block table */
  1724. 19509 #define NR_LOCKS           8    /* # slots in the file locking table */
  1725. 19510
  1726. 19511 /* The type of sizeof may be (unsigned) long.  Use the following macro for
  1727. 19512  * taking the sizes of small objects so that there are no surprises like
  1728. 19513  * (small) long constants being passed to routines expecting an int.
  1729. 19514  */
  1730. 19515 #define usizeof(t) ((unsigned) sizeof(t))
  1731. 19516
  1732. 19517 /* File system types. */
  1733. 19518 #define SUPER_MAGIC   0x137F    /* magic number contained in super-block */
  1734. 19519 #define SUPER_REV     0x7F13    /* magic # when 68000 disk read on PC or vv */
  1735. 19520 #define SUPER_V2      0x2468    /* magic # for V2 file systems */
  1736. 19521 #define SUPER_V2_REV  0x6824    /* V2 magic written on PC, read on 68K or vv */
  1737. 19522
  1738. 19523 #define V1                 1    /* version number of V1 file systems */ 
  1739. 19524 #define V2                 2    /* version number of V2 file systems */ 
  1740. 19525
  1741. 19526 /* Miscellaneous constants */
  1742. 19527 #define SU_UID   ((uid_t) 0)    /* super_user's uid_t */
  1743. 19528 #define SYS_UID  ((uid_t) 0)    /* uid_t for processes MM and INIT */
  1744. 19529 #define SYS_GID  ((gid_t) 0)    /* gid_t for processes MM and INIT */
  1745. 19530 #define NORMAL             0    /* forces get_block to do disk read */
  1746. 19531 #define NO_READ            1    /* prevents get_block from doing disk read */
  1747. 19532 #define PREFETCH           2    /* tells get_block not to read or mark dev */
  1748. 19533
  1749. 19534 #define XPIPE  (-NR_TASKS-1)    /* used in fp_task when susp'd on pipe */
  1750. 19535 #define XOPEN  (-NR_TASKS-2)    /* used in fp_task when susp'd on open */
  1751. 19536 #define XLOCK  (-NR_TASKS-3)    /* used in fp_task when susp'd on lock */
  1752. 19537 #define XPOPEN (-NR_TASKS-4)    /* used in fp_task when susp'd on pipe open */
  1753. 19538
  1754. 19539 #define NO_BIT   ((bit_t) 0)    /* returned by alloc_bit() to signal failure */
  1755. 19540
  1756. 19541 #define DUP_MASK        0100    /* mask to distinguish dup2 from dup */
  1757. 19542
  1758. 19543 #define LOOK_UP            0    /* tells search_dir to lookup string */
  1759. 19544 #define ENTER              1    /* tells search_dir to make dir entry */
  1760. 19545 #define DELETE             2    /* tells search_dir to delete entry */
  1761. 19546 #define IS_EMPTY           3    /* tells search_dir to ret. OK or ENOTEMPTY */  
  1762. 19547
  1763. 19548 #define CLEAN              0    /* disk and memory copies identical */
  1764. 19549 #define DIRTY              1    /* disk and memory copies differ */
  1765. 19550 #define ATIME            002    /* set if atime field needs updating */
  1766. 19551 #define CTIME            004    /* set if ctime field needs updating */
  1767. 19552 #define MTIME            010    /* set if mtime field needs updating */
  1768. 19553
  1769. 19554 #define BYTE_SWAP          0    /* tells conv2/conv4 to swap bytes */
  1770. 19555 #define DONT_SWAP          1    /* tells conv2/conv4 not to swap bytes */
  1771. 19556
  1772. 19557 #define END_OF_FILE   (-104)    /* eof detected */
  1773. 19558
  1774. 19559 #define ROOT_INODE         1    /* inode number for root directory */
  1775. 19560 #define BOOT_BLOCK  ((block_t) 0)       /* block number of boot block */
  1776. 19561 #define SUPER_BLOCK ((block_t) 1)       /* block number of super block */
  1777. 19562
  1778. 19563 #define DIR_ENTRY_SIZE       usizeof (struct direct)  /* # bytes/dir entry   */
  1779. 19564 #define NR_DIR_ENTRIES   (BLOCK_SIZE/DIR_ENTRY_SIZE)  /* # dir entries/blk   */
  1780. 19565 #define SUPER_SIZE      usizeof (struct super_block)  /* super_block size    */
  1781. 19566 #define PIPE_SIZE          (V1_NR_DZONES*BLOCK_SIZE)  /* pipe size in bytes  */
  1782. 19567 #define BITMAP_CHUNKS (BLOCK_SIZE/usizeof (bitchunk_t))/* # map chunks/blk   */
  1783. 19568
  1784. 19569 /* Derived sizes pertaining to the V1 file system. */
  1785. 19570 #define V1_ZONE_NUM_SIZE           usizeof (zone1_t)  /* # bytes in V1 zone  */
  1786. 19571 #define V1_INODE_SIZE             usizeof (d1_inode)  /* bytes in V1 dsk ino */
  1787. 19572 #define V1_INDIRECTS   (BLOCK_SIZE/V1_ZONE_NUM_SIZE)  /* # zones/indir block */
  1788. 19573 #define V1_INODES_PER_BLOCK (BLOCK_SIZE/V1_INODE_SIZE)/* # V1 dsk inodes/blk */
  1789. 19574
  1790. 19575 /* Derived sizes pertaining to the V2 file system. */
  1791. 19576 #define V2_ZONE_NUM_SIZE            usizeof (zone_t)  /* # bytes in V2 zone  */
  1792. 19577 #define V2_INODE_SIZE             usizeof (d2_inode)  /* bytes in V2 dsk ino */
  1793. 19578 #define V2_INDIRECTS   (BLOCK_SIZE/V2_ZONE_NUM_SIZE)  /* # zones/indir block */
  1794. 19579 #define V2_INODES_PER_BLOCK (BLOCK_SIZE/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
  1795. 19580
  1796. 19581 #define printf printk
  1797. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1798. src/fs/type.h    
  1799. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1800. 19600 /* Declaration of the V1 inode as it is on the disk (not in core). */
  1801. 19601 typedef struct {                /* V1.x disk inode */
  1802. 19602   mode_t d1_mode;               /* file type, protection, etc. */
  1803. 19603   uid_t d1_uid;                 /* user id of the file's owner */
  1804. 19604   off_t d1_size;                /* current file size in bytes */
  1805. 19605   time_t d1_mtime;              /* when was file data last changed */
  1806. 19606   gid_t d1_gid;                 /* group number */
  1807. 19607   nlink_t d1_nlinks;            /* how many links to this file */
  1808. 19608   u16_t d1_zone[V1_NR_TZONES];  /* block nums for direct, ind, and dbl ind */
  1809. 19609 } d1_inode;
  1810. 19610
  1811. 19611 /* Declaration of the V2 inode as it is on the disk (not in core). */
  1812. 19612 typedef struct {                /* V2.x disk inode */
  1813. 19613   mode_t d2_mode;               /* file type, protection, etc. */
  1814. 19614   u16_t d2_nlinks;              /* how many links to this file. HACK! */
  1815. 19615   uid_t d2_uid;                 /* user id of the file's owner. */
  1816. 19616   u16_t d2_gid;                 /* group number HACK! */
  1817. 19617   off_t d2_size;                /* current file size in bytes */
  1818. 19618   time_t d2_atime;              /* when was file data last accessed */
  1819. 19619   time_t d2_mtime;              /* when was file data last changed */
  1820. 19620   time_t d2_ctime;              /* when was inode data last changed */
  1821. 19621   zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
  1822. 19622 } d2_inode;
  1823. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1824. src/fs/proto.h    
  1825. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1826. 19700 /* Function prototypes. */
  1827. 19701
  1828. 19702 /* Structs used in prototypes must be declared as such first. */
  1829. 19703 struct buf;
  1830. 19704 struct filp;            
  1831. 19705 struct inode;
  1832. 19706 struct super_block;
  1833. 19707
  1834. 19708 /* cache.c */
  1835. 19709 _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z)                    );
  1836. 19710 _PROTOTYPE( void flushall, (Dev_t dev)                                  );
  1837. 19711 _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb)                    );
  1838. 19712 _PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
  1839. 19713 _PROTOTYPE( void invalidate, (Dev_t device)                             );
  1840. 19714 _PROTOTYPE( void put_block, (struct buf *bp, int block_type)            );
  1841. 19715 _PROTOTYPE( void rw_block, (struct buf *bp, int rw_flag)                );
  1842. 19716 _PROTOTYPE( void rw_scattered, (Dev_t dev,
  1843. 19717                         struct buf **bufq, int bufqsize, int rw_flag)   );
  1844. 19718
  1845. 19719 /* device.c */
  1846. 19720 _PROTOTYPE( void call_task, (int task_nr, message *mess_ptr)            );
  1847. 19721 _PROTOTYPE( void dev_opcl, (int task_nr, message *mess_ptr)             );
  1848. 19722 _PROTOTYPE( int dev_io, (int rw_flag, int nonblock, Dev_t dev,
  1849. 19723                         off_t pos, int bytes, int proc, char *buff)     );
  1850. 19724 _PROTOTYPE( int do_ioctl, (void)                                        );
  1851. 19725 _PROTOTYPE( void no_dev, (int task_nr, message *m_ptr)                  );
  1852. 19726 _PROTOTYPE( void call_ctty, (int task_nr, message *mess_ptr)            );
  1853. 19727 _PROTOTYPE( void tty_open, (int task_nr, message *mess_ptr)             );
  1854. 19728 _PROTOTYPE( void ctty_close, (int task_nr, message *mess_ptr)           );
  1855. 19729 _PROTOTYPE( void ctty_open, (int task_nr, message *mess_ptr)            );
  1856. 19730 _PROTOTYPE( int do_setsid, (void)                                       );
  1857. 19731 #if ENABLE_NETWORKING
  1858. 19732 _PROTOTYPE( void net_open, (int task_nr, message *mess_ptr)             );
  1859. 19733 #else
  1860. 19734 #define net_open  0
  1861. 19735 #endif
  1862. 19736
  1863. 19737 /* filedes.c */
  1864. 19738 _PROTOTYPE( struct filp *find_filp, (struct inode *rip, Mode_t bits)    );
  1865. 19739 _PROTOTYPE( int get_fd, (int start, Mode_t bits, int *k, struct filp **fpt) );
  1866. 19740 _PROTOTYPE( struct filp *get_filp, (int fild)                           );
  1867. 19741
  1868. 19742 /* inode.c */
  1869. 19743 _PROTOTYPE( struct inode *alloc_inode, (Dev_t dev, Mode_t bits)         );
  1870. 19744 _PROTOTYPE( void dup_inode, (struct inode *ip)                          );
  1871. 19745 _PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb)                    );
  1872. 19746 _PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb)              );
  1873. 19747 _PROTOTYPE( void put_inode, (struct inode *rip)                         );
  1874. 19748 _PROTOTYPE( void update_times, (struct inode *rip)                      );
  1875. 19749 _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag)             );
  1876. 19750 _PROTOTYPE( void wipe_inode, (struct inode *rip)                        );
  1877. 19751
  1878. 19752 /* link.c */
  1879. 19753 _PROTOTYPE( int do_link, (void)                                         );
  1880. 19754 _PROTOTYPE( int do_unlink, (void)                                       );
  1881. 19755 _PROTOTYPE( int do_rename, (void)                                       );
  1882. 19756 _PROTOTYPE( void truncate, (struct inode *rip)                          );
  1883. 19757
  1884. 19758 /* lock.c */
  1885. 19759 _PROTOTYPE( int lock_op, (struct filp *f, int req)                      );
  1886. 19760 _PROTOTYPE( void lock_revive, (void)                                    );
  1887. 19761
  1888. 19762 /* main.c */
  1889. 19763 _PROTOTYPE( void main, (void)                                           );
  1890. 19764 _PROTOTYPE( void reply, (int whom, int result)                          );
  1891. 19765
  1892. 19766 /* misc.c */
  1893. 19767 _PROTOTYPE( int do_dup, (void)                                          );
  1894. 19768 _PROTOTYPE( int do_exit, (void)                                         );
  1895. 19769 _PROTOTYPE( int do_fcntl, (void)                                        );
  1896. 19770 _PROTOTYPE( int do_fork, (void)                                         );
  1897. 19771 _PROTOTYPE( int do_exec, (void)                                         );
  1898. 19772 _PROTOTYPE( int do_revive, (void)                                       );
  1899. 19773 _PROTOTYPE( int do_set, (void)                                          );
  1900. 19774 _PROTOTYPE( int do_sync, (void)                                         );
  1901. 19775
  1902. 19776 /* mount.c */
  1903. 19777 _PROTOTYPE( int do_mount, (void)                                        );
  1904. 19778 _PROTOTYPE( int do_umount, (void)                                       );
  1905. 19779
  1906. 19780 /* open.c */
  1907. 19781 _PROTOTYPE( int do_close, (void)                                        );
  1908. 19782 _PROTOTYPE( int do_creat, (void)                                        );
  1909. 19783 _PROTOTYPE( int do_lseek, (void)                                        );
  1910. 19784 _PROTOTYPE( int do_mknod, (void)                                        );
  1911. 19785 _PROTOTYPE( int do_mkdir, (void)                                        );
  1912. 19786 _PROTOTYPE( int do_open, (void)                                         );
  1913. 19787
  1914. 19788 /* path.c */
  1915. 19789 _PROTOTYPE( struct inode *advance,(struct inode *dirp, char string[NAME_MAX]));
  1916. 19790 _PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
  1917. 19791                         char string [NAME_MAX], ino_t *numb, int flag)  );
  1918. 19792 _PROTOTYPE( struct inode *eat_path, (char *path)                        );
  1919. 19793 _PROTOTYPE( struct inode *last_dir, (char *path, char string [NAME_MAX]));
  1920. 19794
  1921. 19795 /* pipe.c */
  1922. 19796 _PROTOTYPE( int do_pipe, (void)                                         );
  1923. 19797 _PROTOTYPE( int do_unpause, (void)                                      );
  1924. 19798 _PROTOTYPE( int pipe_check, (struct inode *rip, int rw_flag,
  1925. 19799                         int oflags, int bytes, off_t position, int *canwrite));
  1926. 19800 _PROTOTYPE( void release, (struct inode *ip, int call_nr, int count)    );
  1927. 19801 _PROTOTYPE( void revive, (int proc_nr, int bytes)                       );
  1928. 19802 _PROTOTYPE( void suspend, (int task)                                    );
  1929. 19803
  1930. 19804 /* protect.c */
  1931. 19805 _PROTOTYPE( int do_access, (void)                                       );
  1932. 19806 _PROTOTYPE( int do_chmod, (void)                                        );
  1933. 19807 _PROTOTYPE( int do_chown, (void)                                        );
  1934. 19808 _PROTOTYPE( int do_umask, (void)                                        );
  1935. 19809 _PROTOTYPE( int forbidden, (struct inode *rip, Mode_t access_desired)   );
  1936. 19810 _PROTOTYPE( int read_only, (struct inode *ip)                           );
  1937. 19811
  1938. 19812 /* putk.c */
  1939. 19813 _PROTOTYPE( void putk, (int c)                                          );
  1940. 19814
  1941. 19815 /* read.c */
  1942. 19816 _PROTOTYPE( int do_read, (void)                                         );
  1943. 19817 _PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
  1944. 19818                         off_t position, unsigned bytes_ahead)           );
  1945. 19819 _PROTOTYPE( void read_ahead, (void)                                     );
  1946. 19820 _PROTOTYPE( block_t read_map, (struct inode *rip, off_t position)       );
  1947. 19821 _PROTOTYPE( int read_write, (int rw_flag)                               );
  1948. 19822 _PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index)                );
  1949. 19823
  1950. 19824 /* stadir.c */
  1951. 19825 _PROTOTYPE( int do_chdir, (void)                                        );
  1952. 19826 _PROTOTYPE( int do_chroot, (void)                                       );
  1953. 19827 _PROTOTYPE( int do_fstat, (void)                                        );
  1954. 19828 _PROTOTYPE( int do_stat, (void)                                         );
  1955. 19829
  1956. 19830 /* super.c */
  1957. 19831 _PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
  1958. 19832 _PROTOTYPE( void free_bit, (struct super_block *sp, int map,
  1959. 19833                                                 bit_t bit_returned)     );
  1960. 19834 _PROTOTYPE( struct super_block *get_super, (Dev_t dev)                  );
  1961. 19835 _PROTOTYPE( int mounted, (struct inode *rip)                            );
  1962. 19836 _PROTOTYPE( int read_super, (struct super_block *sp)                    );
  1963. 19837
  1964. 19838 /* time.c */
  1965. 19839 _PROTOTYPE( int do_stime, (void)                                        );
  1966. 19840 _PROTOTYPE( int do_time, (void)                                         );
  1967. 19841 _PROTOTYPE( int do_tims, (void)                                         );
  1968. 19842 _PROTOTYPE( int do_utime, (void)                                        );
  1969. 19843
  1970. 19844 /* utility.c */
  1971. 19845 _PROTOTYPE( time_t clock_time, (void)                                   );
  1972. 19846 _PROTOTYPE( unsigned conv2, (int norm, int w)                           );
  1973. 19847 _PROTOTYPE( long conv4, (int norm, long x)                              );
  1974. 19848 _PROTOTYPE( int fetch_name, (char *path, int len, int flag)             );
  1975. 19849 _PROTOTYPE( int no_sys, (void)                                          );
  1976. 19850 _PROTOTYPE( void panic, (char *format, int num)                         );
  1977. 19851
  1978. 19852 /* write.c */
  1979. 19853 _PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag)   );
  1980. 19854 _PROTOTYPE( int do_write, (void)                                        );
  1981. 19855 _PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position)  );
  1982. 19856 _PROTOTYPE( void zero_block, (struct buf *bp)                           );
  1983. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1984. src/fs/glo.h    
  1985. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1986. 19900 /* EXTERN should be extern except for the table file */
  1987. 19901 #ifdef _TABLE
  1988. 19902 #undef EXTERN
  1989. 19903 #define EXTERN
  1990. 19904 #endif
  1991. 19905
  1992. 19906 /* File System global variables */
  1993. 19907 EXTERN struct fproc *fp;        /* pointer to caller's fproc struct */
  1994. 19908 EXTERN int super_user;          /* 1 if caller is super_user, else 0 */
  1995. 19909 EXTERN int dont_reply;          /* normally 0; set to 1 to inhibit reply */
  1996. 19910 EXTERN int susp_count;          /* number of procs suspended on pipe */
  1997. 19911 EXTERN int nr_locks;            /* number of locks currently in place */
  1998. 19912 EXTERN int reviving;            /* number of pipe processes to be revived */
  1999. 19913 EXTERN off_t rdahedpos;         /* position to read ahead */
  2000. 19914 EXTERN struct inode *rdahed_inode;      /* pointer to inode to read ahead */
  2001. 19915
  2002. 19916 /* The parameters of the call are kept here. */
  2003. 19917 EXTERN message m;               /* the input message itself */
  2004. 19918 EXTERN message m1;              /* the output message used for reply */
  2005. 19919 EXTERN int who;                 /* caller's proc number */
  2006. 19920 EXTERN int fs_call;             /* system call number */
  2007. 19921 EXTERN char user_path[PATH_MAX];/* storage for user path name */
  2008. 19922
  2009. 19923 /* The following variables are used for returning results to the caller. */
  2010. 19924 EXTERN int err_code;            /* temporary storage for error number */
  2011. 19925 EXTERN int rdwt_err;            /* status of last disk i/o request */
  2012. 19926
  2013. 19927 /* Data which need initialization. */
  2014. 19928 extern _PROTOTYPE (int (*call_vector[]), (void) ); /* sys call table */
  2015. 19929 extern int max_major;  /* maximum major device (+ 1) */
  2016. 19930 extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
  2017. 19931 extern char dot2[3];   /* meaning to search_dir: no access permission check. */
  2018. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2019. src/fs/fproc.h    
  2020. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2021. 20000 /* This is the per-process information.  A slot is reserved for each potential
  2022. 20001  * process. Thus NR_PROCS must be the same as in the kernel. It is not possible
  2023. 20002  * or even necessary to tell when a slot is free here.
  2024. 20003  */
  2025. 20004
  2026. 20005
  2027. 20006 EXTERN struct fproc {
  2028. 20007   mode_t fp_umask;              /* mask set by umask system call */
  2029. 20008   struct inode *fp_workdir;     /* pointer to working directory's inode */
  2030. 20009   struct inode *fp_rootdir;     /* pointer to current root dir (see chroot) */
  2031. 20010   struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
  2032. 20011   uid_t fp_realuid;             /* real user id */
  2033. 20012   uid_t fp_effuid;              /* effective user id */
  2034. 20013   gid_t fp_realgid;             /* real group id */
  2035. 20014   gid_t fp_effgid;              /* effective group id */
  2036. 20015   dev_t fp_tty;                 /* major/minor of controlling tty */
  2037. 20016   int fp_fd;                    /* place to save fd if rd/wr can't finish */
  2038. 20017   char *fp_buffer;              /* place to save buffer if rd/wr can't finish*/
  2039. 20018   int  fp_nbytes;               /* place to save bytes if rd/wr can't finish */
  2040. 20019   int  fp_cum_io_partial;       /* partial byte count if rd/wr can't finish */
  2041. 20020   char fp_suspended;            /* set to indicate process hanging */
  2042. 20021   char fp_revived;              /* set to indicate process being revived */
  2043. 20022   char fp_task;                 /* which task is proc suspended on */
  2044. 20023   char fp_sesldr;               /* true if proc is a session leader */
  2045. 20024   pid_t fp_pid;                 /* process id */
  2046. 20025   long fp_cloexec;              /* bit map for POSIX Table 6-2 FD_CLOEXEC */
  2047. 20026 } fproc[NR_PROCS];
  2048. 20027
  2049. 20028 /* Field values. */
  2050. 20029 #define NOT_SUSPENDED      0    /* process is not suspended on pipe or task */
  2051. 20030 #define SUSPENDED          1    /* process is suspended on pipe or task */
  2052. 20031 #define NOT_REVIVING       0    /* process is not being revived */
  2053. 20032 #define REVIVING           1    /* process is being revived from suspension */
  2054. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2055. src/fs/buf.h    
  2056. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2057. 20100 /* Buffer (block) cache.  To acquire a block, a routine calls get_block(),
  2058. 20101  * telling which block it wants.  The block is then regarded as "in use"
  2059. 20102  * and has its 'b_count' field incremented.  All the blocks that are not
  2060. 20103  * in use are chained together in an LRU list, with 'front' pointing
  2061. 20104  * to the least recently used block, and 'rear' to the most recently used
  2062. 20105  * block.  A reverse chain, using the field b_prev is also maintained.
  2063. 20106  * Usage for LRU is measured by the time the put_block() is done.  The second
  2064. 20107  * parameter to put_block() can violate the LRU order and put a block on the
  2065. 20108  * front of the list, if it will probably not be needed soon.  If a block
  2066. 20109  * is modified, the modifying routine must set b_dirt to DIRTY, so the block
  2067. 20110  * will eventually be rewritten to the disk.
  2068. 20111  */
  2069. 20112
  2070. 20113 #include <sys/dir.h>                    /* need struct direct */
  2071. 20114
  2072. 20115 EXTERN struct buf {
  2073. 20116   /* Data portion of the buffer. */
  2074. 20117   union {
  2075. 20118     char b__data[BLOCK_SIZE];                /* ordinary user data */
  2076. 20119     struct direct b__dir[NR_DIR_ENTRIES];    /* directory block */
  2077. 20120     zone1_t b__v1_ind[V1_INDIRECTS];         /* V1 indirect block */
  2078. 20121     zone_t  b__v2_ind[V2_INDIRECTS];         /* V2 indirect block */
  2079. 20122     d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; /* V1 inode block */
  2080. 20123     d2_inode b__v2_ino[V2_INODES_PER_BLOCK]; /* V2 inode block */
  2081. 20124     bitchunk_t b__bitmap[BITMAP_CHUNKS];     /* bit map block */
  2082. 20125   } b;
  2083. 20126
  2084. 20127   /* Header portion of the buffer. */
  2085. 20128   struct buf *b_next;           /* used to link all free bufs in a chain */
  2086. 20129   struct buf *b_prev;           /* used to link all free bufs the other way */
  2087. 20130   struct buf *b_hash;           /* used to link bufs on hash chains */
  2088. 20131   block_t b_blocknr;            /* block number of its (minor) device */
  2089. 20132   dev_t b_dev;                  /* major | minor device where block resides */
  2090. 20133   char b_dirt;                  /* CLEAN or DIRTY */
  2091. 20134   char b_count;                 /* number of users of this buffer */
  2092. 20135 } buf[NR_BUFS];
  2093. 20136
  2094. 20137 /* A block is free if b_dev == NO_DEV. */
  2095. 20138
  2096. 20139 #define NIL_BUF ((struct buf *) 0)      /* indicates absence of a buffer */
  2097. 20140
  2098. 20141 /* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
  2099. 20142 #define b_data   b.b__data
  2100. 20143 #define b_dir    b.b__dir
  2101. 20144 #define b_v1_ind b.b__v1_ind
  2102. 20145 #define b_v2_ind b.b__v2_ind
  2103. 20146 #define b_v1_ino b.b__v1_ino
  2104. 20147 #define b_v2_ino b.b__v2_ino
  2105. 20148 #define b_bitmap b.b__bitmap
  2106. 20149
  2107. 20150 EXTERN struct buf *buf_hash[NR_BUF_HASH];       /* the buffer hash table */
  2108. 20151
  2109. 20152 EXTERN struct buf *front;       /* points to least recently used free block */
  2110. 20153 EXTERN struct buf *rear;        /* points to most recently used free block */
  2111. 20154 EXTERN int bufs_in_use;         /* # bufs currently in use (not on free list)*/
  2112. 20155
  2113. 20156 /* When a block is released, the type of usage is passed to put_block(). */
  2114. 20157 #define WRITE_IMMED        0100 /* block should be written to disk now */
  2115. 20158 #define ONE_SHOT           0200 /* set if block not likely to be needed soon */
  2116. 20159
  2117. 20160 #define INODE_BLOCK       (0 + MAYBE_WRITE_IMMED)        /* inode block */
  2118. 20161 #define DIRECTORY_BLOCK   (1 + MAYBE_WRITE_IMMED)        /* directory block */
  2119. 20162 #define INDIRECT_BLOCK    (2 + MAYBE_WRITE_IMMED)        /* pointer block */
  2120. 20163 #define MAP_BLOCK         (3 + MAYBE_WRITE_IMMED)        /* bit map */
  2121. 20164 #define ZUPER_BLOCK       (4 + WRITE_IMMED + ONE_SHOT)   /* super block */
  2122. 20165 #define FULL_DATA_BLOCK    5                             /* data, fully used */
  2123. 20166 #define PARTIAL_DATA_BLOCK 6                             /* data, partly used*/
  2124. 20167
  2125. 20168 #define HASH_MASK (NR_BUF_HASH - 1)     /* mask for hashing block numbers */
  2126. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2127. src/fs/dev.h    
  2128. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2129. 20200 /* Device table.  This table is indexed by major device number.  It provides
  2130. 20201  * the link between major device numbers and the routines that process them.
  2131. 20202  */
  2132. 20203
  2133. 20204 typedef _PROTOTYPE (void (*dmap_t), (int task, message *m_ptr) );
  2134. 20205
  2135. 20206 extern struct dmap {
  2136. 20207   dmap_t dmap_open;
  2137. 20208   dmap_t dmap_rw;
  2138. 20209   dmap_t dmap_close;
  2139. 20210   int dmap_task;
  2140. 20211 } dmap[];
  2141. 20212
  2142. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2143. src/fs/file.h    
  2144. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2145. 20300 /* This is the filp table.  It is an intermediary between file descriptors and
  2146. 20301  * inodes.  A slot is free if filp_count == 0.
  2147. 20302  */
  2148. 20303
  2149. 20304 EXTERN struct filp {
  2150. 20305   mode_t filp_mode;             /* RW bits, telling how file is opened */
  2151. 20306   int filp_flags;               /* flags from open and fcntl */
  2152. 20307   int filp_count;               /* how many file descriptors share this slot?*/
  2153. 20308   struct inode *filp_ino;       /* pointer to the inode */
  2154. 20309   off_t filp_pos;               /* file position */
  2155. 20310 } filp[NR_FILPS];
  2156. 20311
  2157. 20312 #define FILP_CLOSED     0       /* filp_mode: associated device closed */
  2158. 20313
  2159. 20314 #define NIL_FILP (struct filp *) 0      /* indicates absence of a filp slot */
  2160. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2161. src/fs/lock.h    
  2162. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2163. 20400 /* This is the file locking table.  Like the filp table, it points to the
  2164. 20401  * inode table, however, in this case to achieve advisory locking.
  2165. 20402  */
  2166. 20403 EXTERN struct file_lock {
  2167. 20404   short lock_type;              /* F_RDLOCK or F_WRLOCK; 0 means unused slot */
  2168. 20405   pid_t lock_pid;               /* pid of the process holding the lock */
  2169. 20406   struct inode *lock_inode;     /* pointer to the inode locked */
  2170. 20407   off_t lock_first;             /* offset of first byte locked */
  2171. 20408   off_t lock_last;              /* offset of last byte locked */
  2172. 20409 } file_lock[NR_LOCKS];
  2173. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2174. src/fs/inode.h    
  2175. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2176. 20500 /* Inode table.  This table holds inodes that are currently in use.  In some
  2177. 20501  * cases they have been opened by an open() or creat() system call, in other
  2178. 20502  * cases the file system itself needs the inode for one reason or another,
  2179. 20503  * such as to search a directory for a path name.
  2180. 20504  * The first part of the struct holds fields that are present on the
  2181. 20505  * disk; the second part holds fields not present on the disk.
  2182. 20506  * The disk inode part is also declared in "type.h" as 'd1_inode' for V1
  2183. 20507  * file systems and 'd2_inode' for V2 file systems.
  2184. 20508  */
  2185. 20509
  2186. 20510 EXTERN struct inode {
  2187. 20511   mode_t i_mode;                /* file type, protection, etc. */
  2188. 20512   nlink_t i_nlinks;             /* how many links to this file */
  2189. 20513   uid_t i_uid;                  /* user id of the file's owner */
  2190. 20514   gid_t i_gid;                  /* group number */
  2191. 20515   off_t i_size;                 /* current file size in bytes */
  2192. 20516   time_t i_atime;               /* time of last access (V2 only) */
  2193. 20517   time_t i_mtime;               /* when was file data last changed */
  2194. 20518   time_t i_ctime;               /* when was inode itself changed (V2 only)*/
  2195. 20519   zone_t i_zone[V2_NR_TZONES];  /* zone numbers for direct, ind, and dbl ind */
  2196. 20520   
  2197. 20521   /* The following items are not present on the disk. */
  2198. 20522   dev_t i_dev;                  /* which device is the inode on */
  2199. 20523   ino_t i_num;                  /* inode number on its (minor) device */
  2200. 20524   int i_count;                  /* # times inode used; 0 means slot is free */
  2201. 20525   int i_ndzones;                /* # direct zones (Vx_NR_DZONES) */
  2202. 20526   int i_nindirs;                /* # indirect zones per indirect block */
  2203. 20527   struct super_block *i_sp;     /* pointer to super block for inode's device */
  2204. 20528   char i_dirt;                  /* CLEAN or DIRTY */
  2205. 20529   char i_pipe;                  /* set to I_PIPE if pipe */
  2206. 20530   char i_mount;                 /* this bit is set if file mounted on */
  2207. 20531   char i_seek;                  /* set on LSEEK, cleared on READ/WRITE */
  2208. 20532   char i_update;                /* the ATIME, CTIME, and MTIME bits are here */
  2209. 20533 } inode[NR_INODES];
  2210. 20534
  2211. 20535
  2212. 20536 #define NIL_INODE (struct inode *) 0    /* indicates absence of inode slot */
  2213. 20537
  2214. 20538 /* Field values.  Note that CLEAN and DIRTY are defined in "const.h" */
  2215. 20539 #define NO_PIPE            0    /* i_pipe is NO_PIPE if inode is not a pipe */
  2216. 20540 #define I_PIPE             1    /* i_pipe is I_PIPE if inode is a pipe */
  2217. 20541 #define NO_MOUNT           0    /* i_mount is NO_MOUNT if file not mounted on*/
  2218. 20542 #define I_MOUNT            1    /* i_mount is I_MOUNT if file mounted on */
  2219. 20543 #define NO_SEEK            0    /* i_seek = NO_SEEK if last op was not SEEK */
  2220. 20544 #define ISEEK              1    /* i_seek = ISEEK if last op was SEEK */
  2221. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2222. src/fs/param.h    
  2223. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2224. 20600 /* The following names are synonyms for the variables in the input message. */
  2225. 20601 #define acc_time      m.m2_l1
  2226. 20602 #define addr          m.m1_i3
  2227. 20603 #define buffer        m.m1_p1
  2228. 20604 #define child         m.m1_i2
  2229. 20605 #define co_mode       m.m1_i1
  2230. 20606 #define eff_grp_id    m.m1_i3
  2231. 20607 #define eff_user_id   m.m1_i3
  2232. 20608 #define erki          m.m1_p1
  2233. 20609 #define fd            m.m1_i1
  2234. 20610 #define fd2           m.m1_i2
  2235. 20611 #define ioflags       m.m1_i3
  2236. 20612 #define group         m.m1_i3
  2237. 20613 #define real_grp_id   m.m1_i2
  2238. 20614 #define ls_fd         m.m2_i1
  2239. 20615 #define mk_mode       m.m1_i2
  2240. 20616 #define mode          m.m3_i2
  2241. 20617 #define c_mode        m.m1_i3
  2242. 20618 #define c_name        m.m1_p1
  2243. 20619 #define name          m.m3_p1
  2244. 20620 #define name1         m.m1_p1
  2245. 20621 #define name2         m.m1_p2
  2246. 20622 #define name_length   m.m3_i1
  2247. 20623 #define name1_length  m.m1_i1
  2248. 20624 #define name2_length  m.m1_i2
  2249. 20625 #define nbytes        m.m1_i2
  2250. 20626 #define offset        m.m2_l1
  2251. 20627 #define owner         m.m1_i2
  2252. 20628 #define parent        m.m1_i1
  2253. 20629 #define pathname      m.m3_ca1
  2254. 20630 #define pid           m.m1_i3
  2255. 20631 #define pro           m.m1_i1
  2256. 20632 #define rd_only       m.m1_i3
  2257. 20633 #define real_user_id  m.m1_i2
  2258. 20634 #define request       m.m1_i2
  2259. 20635 #define sig           m.m1_i2
  2260. 20636 #define slot1         m.m1_i1
  2261. 20637 #define tp            m.m2_l1
  2262. 20638 #define utime_actime  m.m2_l1
  2263. 20639 #define utime_modtime m.m2_l2
  2264. 20640 #define utime_file    m.m2_p1
  2265. 20641 #define utime_length  m.m2_i1
  2266. 20642 #define whence        m.m2_i2
  2267. 20643
  2268. 20644 /* The following names are synonyms for the variables in the output message. */
  2269. 20645 #define reply_type    m1.m_type
  2270. 20646 #define reply_l1      m1.m2_l1
  2271. 20647 #define reply_i1      m1.m1_i1
  2272. 20648 #define reply_i2      m1.m1_i2
  2273. 20649 #define reply_t1      m1.m4_l1
  2274. 20650 #define reply_t2      m1.m4_l2
  2275. 20651 #define reply_t3      m1.m4_l3
  2276. 20652 #define reply_t4      m1.m4_l4
  2277. 20653 #define reply_t5      m1.m4_l5
  2278. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2279. src/fs/super.h    
  2280. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2281. 20700 /* Super block table.  The root file system and every mounted file system
  2282. 20701  * has an entry here.  The entry holds information about the sizes of the bit
  2283. 20702  * maps and inodes.  The s_ninodes field gives the number of inodes available
  2284. 20703  * for files and directories, including the root directory.  Inode 0 is 
  2285. 20704  * on the disk, but not used.  Thus s_ninodes = 4 means that 5 bits will be
  2286. 20705  * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
  2287. 20706  * for files and directories.  The disk layout is:
  2288. 20707  *
  2289. 20708  *      Item        # blocks
  2290. 20709  *    boot block      1
  2291. 20710  *    super block     1
  2292. 20711  *    inode map     s_imap_blocks
  2293. 20712  *    zone map      s_zmap_blocks
  2294. 20713  *    inodes        (s_ninodes + 'inodes per block' - 1)/'inodes per block'
  2295. 20714  *    unused        whatever is needed to fill out the current zone
  2296. 20715  *    data zones    (s_zones - s_firstdatazone) << s_log_zone_size
  2297. 20716  *
  2298. 20717  * A super_block slot is free if s_dev == NO_DEV. 
  2299. 20718  */
  2300. 20719
  2301. 20720
  2302. 20721 EXTERN struct super_block {
  2303. 20722   ino_t s_ninodes;              /* # usable inodes on the minor device */
  2304. 20723   zone1_t  s_nzones;            /* total device size, including bit maps etc */
  2305. 20724   short s_imap_blocks;          /* # of blocks used by inode bit map */
  2306. 20725   short s_zmap_blocks;          /* # of blocks used by zone bit map */
  2307. 20726   zone1_t s_firstdatazone;      /* number of first data zone */
  2308. 20727   short s_log_zone_size;        /* log2 of blocks/zone */
  2309. 20728   off_t s_max_size;             /* maximum file size on this device */
  2310. 20729   short s_magic;                /* magic number to recognize super-blocks */
  2311. 20730   short s_pad;                  /* try to avoid compiler-dependent padding */
  2312. 20731   zone_t s_zones;               /* number of zones (replaces s_nzones in V2) */
  2313. 20732
  2314. 20733   /* The following items are only used when the super_block is in memory. */
  2315. 20734   struct inode *s_isup;         /* inode for root dir of mounted file sys */
  2316. 20735   struct inode *s_imount;       /* inode mounted on */
  2317. 20736   unsigned s_inodes_per_block;  /* precalculated from magic number */
  2318. 20737   dev_t s_dev;                  /* whose super block is this? */
  2319. 20738   int s_rd_only;                /* set to 1 iff file sys mounted read only */
  2320. 20739   int s_native;                 /* set to 1 iff not byte swapped file system */
  2321. 20740   int s_version;                /* file system version, zero means bad magic */
  2322. 20741   int s_ndzones;                /* # direct zones in an inode */
  2323. 20742   int s_nindirs;                /* # indirect zones per indirect block */
  2324. 20743   bit_t s_isearch;              /* inodes below this bit number are in use */
  2325. 20744   bit_t s_zsearch;              /* all zones below this bit number are in use*/
  2326. 20745 } super_block[NR_SUPERS];
  2327. 20746
  2328. 20747 #define NIL_SUPER (struct super_block *) 0
  2329. 20748 #define IMAP            0       /* operating on the inode bit map */
  2330. 20749 #define ZMAP            1       /* operating on the zone bit map */
  2331. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2332. src/fs/table.c    
  2333. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2334. 20800 /* This file contains the table used to map system call numbers onto the
  2335. 20801  * routines that perform them.
  2336. 20802  */
  2337. 20803
  2338. 20804 #define _TABLE
  2339. 20805
  2340. 20806 #include "fs.h"
  2341. 20807 #include <minix/callnr.h>
  2342. 20808 #include <minix/com.h>
  2343. 20809 #include "buf.h"
  2344. 20810 #include "dev.h"
  2345. 20811 #include "file.h"
  2346. 20812 #include "fproc.h"
  2347. 20813 #include "inode.h"
  2348. 20814 #include "lock.h"
  2349. 20815 #include "super.h"
  2350. 20816
  2351. 20817 PUBLIC _PROTOTYPE (int (*call_vector[NCALLS]), (void) ) = {
  2352. 20818         no_sys,         /*  0 = unused  */
  2353. 20819         do_exit,        /*  1 = exit    */
  2354. 20820         do_fork,        /*  2 = fork    */
  2355. 20821         do_read,        /*  3 = read    */
  2356. 20822         do_write,       /*  4 = write   */
  2357. 20823         do_open,        /*  5 = open    */
  2358. 20824         do_close,       /*  6 = close   */
  2359. 20825         no_sys,         /*  7 = wait    */
  2360. 20826         do_creat,       /*  8 = creat   */
  2361. 20827         do_link,        /*  9 = link    */
  2362. 20828         do_unlink,      /* 10 = unlink  */
  2363. 20829         no_sys,         /* 11 = waitpid */
  2364. 20830         do_chdir,       /* 12 = chdir   */
  2365. 20831         do_time,        /* 13 = time    */
  2366. 20832         do_mknod,       /* 14 = mknod   */
  2367. 20833         do_chmod,       /* 15 = chmod   */
  2368. 20834         do_chown,       /* 16 = chown   */
  2369. 20835         no_sys,         /* 17 = break   */
  2370. 20836         do_stat,        /* 18 = stat    */
  2371. 20837         do_lseek,       /* 19 = lseek   */
  2372. 20838         no_sys,         /* 20 = getpid  */
  2373. 20839         do_mount,       /* 21 = mount   */
  2374. 20840         do_umount,      /* 22 = umount  */
  2375. 20841         do_set,         /* 23 = setuid  */
  2376. 20842         no_sys,         /* 24 = getuid  */
  2377. 20843         do_stime,       /* 25 = stime   */
  2378. 20844         no_sys,         /* 26 = ptrace  */
  2379. 20845         no_sys,         /* 27 = alarm   */
  2380. 20846         do_fstat,       /* 28 = fstat   */
  2381. 20847         no_sys,         /* 29 = pause   */
  2382. 20848         do_utime,       /* 30 = utime   */
  2383. 20849         no_sys,         /* 31 = (stty)  */
  2384. 20850         no_sys,         /* 32 = (gtty)  */
  2385. 20851         do_access,      /* 33 = access  */
  2386. 20852         no_sys,         /* 34 = (nice)  */
  2387. 20853         no_sys,         /* 35 = (ftime) */
  2388. 20854         do_sync,        /* 36 = sync    */
  2389. 20855         no_sys,         /* 37 = kill    */
  2390. 20856         do_rename,      /* 38 = rename  */
  2391. 20857         do_mkdir,       /* 39 = mkdir   */
  2392. 20858         do_unlink,      /* 40 = rmdir   */
  2393. 20859         do_dup,         /* 41 = dup     */
  2394. 20860         do_pipe,        /* 42 = pipe    */
  2395. 20861         do_tims,        /* 43 = times   */
  2396. 20862         no_sys,         /* 44 = (prof)  */
  2397. 20863         no_sys,         /* 45 = unused  */
  2398. 20864         do_set,         /* 46 = setgid  */
  2399. 20865         no_sys,         /* 47 = getgid  */
  2400. 20866         no_sys,         /* 48 = (signal)*/
  2401. 20867         no_sys,         /* 49 = unused  */
  2402. 20868         no_sys,         /* 50 = unused  */
  2403. 20869         no_sys,         /* 51 = (acct)  */
  2404. 20870         no_sys,         /* 52 = (phys)  */
  2405. 20871         no_sys,         /* 53 = (lock)  */
  2406. 20872         do_ioctl,       /* 54 = ioctl   */
  2407. 20873         do_fcntl,       /* 55 = fcntl   */
  2408. 20874         no_sys,         /* 56 = (mpx)   */
  2409. 20875         no_sys,         /* 57 = unused  */
  2410. 20876         no_sys,         /* 58 = unused  */
  2411. 20877         do_exec,        /* 59 = execve  */
  2412. 20878         do_umask,       /* 60 = umask   */
  2413. 20879         do_chroot,      /* 61 = chroot  */
  2414. 20880         do_setsid,      /* 62 = setsid  */
  2415. 20881         no_sys,         /* 63 = getpgrp */
  2416. 20882
  2417. 20883         no_sys,         /* 64 = KSIG: signals originating in the kernel */
  2418. 20884         do_unpause,     /* 65 = UNPAUSE */
  2419. 20885         no_sys,         /* 66 = unused  */
  2420. 20886         do_revive,      /* 67 = REVIVE  */
  2421. 20887         no_sys,         /* 68 = TASK_REPLY      */
  2422. 20888         no_sys,         /* 69 = unused */
  2423. 20889         no_sys,         /* 70 = unused */
  2424. 20890         no_sys,         /* 71 = SIGACTION */
  2425. 20891         no_sys,         /* 72 = SIGSUSPEND */
  2426. 20892         no_sys,         /* 73 = SIGPENDING */
  2427. 20893         no_sys,         /* 74 = SIGPROCMASK */
  2428. 20894         no_sys,         /* 75 = SIGRETURN */
  2429. 20895         no_sys,         /* 76 = REBOOT */
  2430. 20896 };
  2431. 20897
  2432. 20898
  2433. 20899 /* Some devices may or may not be there in the next table. */
  2434. 20900 #define DT(enable, open, rw, close, task) 
  2435. 20901         { (enable ? (open) : no_dev), (enable ? (rw) : no_dev), 
  2436. 20902           (enable ? (close) : no_dev), (enable ? (task) : 0) },
  2437. 20903
  2438. 20904 /* The order of the entries here determines the mapping between major device
  2439. 20905  * numbers and tasks.  The first entry (major device 0) is not used.  The
  2440. 20906  * next entry is major device 1, etc.  Character and block devices can be
  2441. 20907  * intermixed at random.  If this ordering is changed, the devices in
  2442. 20908  * <include/minix/boot.h> must be changed to correspond to the new values.
  2443. 20909  * Note that the major device numbers used in /dev are NOT the same as the 
  2444. 20910  * task numbers used inside the kernel (as defined in <include/minix/com.h>).
  2445. 20911  * Also note that if /dev/mem is changed from 1, NULL_MAJOR must be changed
  2446. 20912  * in <include/minix/com.h>.
  2447. 20913  */
  2448. 20914 PUBLIC struct dmap dmap[] = {
  2449. 20915 /*  ?   Open       Read/Write   Close       Task #      Device  File
  2450. 20916     -   ----       ----------   -----       -------     ------  ----       */
  2451. 20917   DT(1, no_dev,    no_dev,      no_dev,     0)           /* 0 = not used   */
  2452. 20918   DT(1, dev_opcl,  call_task,   dev_opcl,   MEM)         /* 1 = /dev/mem   */
  2453. 20919   DT(1, dev_opcl,  call_task,   dev_opcl,   FLOPPY)      /* 2 = /dev/fd0   */
  2454. 20920   DT(ENABLE_WINI,
  2455. 20921         dev_opcl,  call_task,   dev_opcl,   WINCHESTER)  /* 3 = /dev/hd0   */
  2456. 20922   DT(1, tty_open,  call_task,   dev_opcl,   TTY)         /* 4 = /dev/tty00 */
  2457. 20923   DT(1, ctty_open, call_ctty,   ctty_close, TTY)         /* 5 = /dev/tty   */
  2458. 20924   DT(1, dev_opcl,  call_task,   dev_opcl,    PRINTER)     /* 6 = /dev/lp    */
  2459. 20925
  2460. 20926 #if (MACHINE == IBM_PC)
  2461. 20927   DT(ENABLE_NETWORKING,
  2462. 20928         net_open,  call_task,   dev_opcl,   INET_PROC_NR)/* 7 = /dev/ip    */
  2463. 20929   DT(ENABLE_CDROM,
  2464. 20930         dev_opcl,  call_task,   dev_opcl,   CDROM)       /* 8 = /dev/cd0   */
  2465. 20931   DT(0, 0,         0,           0,          0)           /* 9 = not used   */
  2466. 20932   DT(ENABLE_SCSI,
  2467. 20933         dev_opcl,  call_task,   dev_opcl,   SCSI)        /*10 = /dev/sd0   */
  2468. 20934   DT(0, 0,         0,           0,          0)           /*11 = not used   */
  2469. 20935   DT(0, 0,         0,           0,          0)           /*12 = not used   */
  2470. 20936   DT(ENABLE_AUDIO,
  2471. 20937         dev_opcl,  call_task,   dev_opcl,   AUDIO)       /*13 = /dev/audio */
  2472. 20938   DT(ENABLE_AUDIO,
  2473. 20939         dev_opcl,  call_task,   dev_opcl,   MIXER)       /*14 = /dev/mixer */
  2474. 20940 #endif /* IBM_PC */
  2475. 20941
  2476. 20942 #if (MACHINE == ATARI)
  2477. 20943   DT(ENABLE_SCSI,
  2478. 20944         dev_opcl,  call_task,   dev_opcl,   SCSI)        /* 7 = /dev/hdscsi0 */
  2479. 20945 #endif
  2480. 20946 };
  2481. 20947
  2482. 20948 PUBLIC int max_major = sizeof(dmap)/sizeof(struct dmap);
  2483. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2484. src/fs/cache.c    
  2485. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2486. 21000 /* The file system maintains a buffer cache to reduce the number of disk
  2487. 21001  * accesses needed.  Whenever a read or write to the disk is done, a check is
  2488. 21002  * first made to see if the block is in the cache.  This file manages the
  2489. 21003  * cache.
  2490. 21004  *
  2491. 21005  * The entry points into this file are:
  2492. 21006  *   get_block:   request to fetch a block for reading or writing from cache
  2493. 21007  *   put_block:   return a block previously requested with get_block
  2494. 21008  *   alloc_zone:  allocate a new zone (to increase the length of a file)
  2495. 21009  *   free_zone:   release a zone (when a file is removed)
  2496. 21010  *   rw_block:    read or write a block from the disk itself
  2497. 21011  *   invalidate:  remove all the cache blocks on some device
  2498. 21012  */
  2499. 21013
  2500. 21014 #include "fs.h"
  2501. 21015 #include <minix/com.h>
  2502. 21016 #include <minix/boot.h>
  2503. 21017 #include "buf.h"
  2504. 21018 #include "file.h"
  2505. 21019 #include "fproc.h"
  2506. 21020 #include "super.h"
  2507. 21021
  2508. 21022 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
  2509. 21023
  2510. 21024 /*===========================================================================*
  2511. 21025  *                              get_block                                    *
  2512. 21026  *===========================================================================*/
  2513. 21027 PUBLIC struct buf *get_block(dev, block, only_search)
  2514. 21028 register dev_t dev;             /* on which device is the block? */
  2515. 21029 register block_t block;         /* which block is wanted? */
  2516. 21030 int only_search;                /* if NO_READ, don't read, else act normal */
  2517. 21031 {
  2518. 21032 /* Check to see if the requested block is in the block cache.  If so, return
  2519. 21033  * a pointer to it.  If not, evict some other block and fetch it (unless
  2520. 21034  * 'only_search' is 1).  All the blocks in the cache that are not in use
  2521. 21035  * are linked together in a chain, with 'front' pointing to the least recently
  2522. 21036  * used block and 'rear' to the most recently used block.  If 'only_search' is
  2523. 21037  * 1, the block being requested will be overwritten in its entirety, so it is
  2524. 21038  * only necessary to see if it is in the cache; if it is not, any free buffer
  2525. 21039  * will do.  It is not necessary to actually read the block in from disk.
  2526. 21040  * If 'only_search' is PREFETCH, the block need not be read from the disk,
  2527. 21041  * and the device is not to be marked on the block, so callers can tell if
  2528. 21042  * the block returned is valid.
  2529. 21043  * In addition to the LRU chain, there is also a hash chain to link together
  2530. 21044  * blocks whose block numbers end with the same bit strings, for fast lookup.
  2531. 21045  */
  2532. 21046
  2533. 21047   int b;
  2534. 21048   register struct buf *bp, *prev_ptr;
  2535. 21049
  2536. 21050   /* Search the hash chain for (dev, block). Do_read() can use 
  2537. 21051    * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
  2538. 21052    * someone wants to read from a hole in a file, in which case this search
  2539. 21053    * is skipped
  2540. 21054    */
  2541. 21055   if (dev != NO_DEV) {
  2542. 21056         b = (int) block & HASH_MASK;
  2543. 21057         bp = buf_hash[b];
  2544. 21058         while (bp != NIL_BUF) {
  2545. 21059                 if (bp->b_blocknr == block && bp->b_dev == dev) {
  2546. 21060                         /* Block needed has been found. */
  2547. 21061                         if (bp->b_count == 0) rm_lru(bp);
  2548. 21062                         bp->b_count++;  /* record that block is in use */
  2549. 21063                         return(bp);
  2550. 21064                 } else {
  2551. 21065                         /* This block is not the one sought. */
  2552. 21066                         bp = bp->b_hash; /* move to next block on hash chain */
  2553. 21067                 }
  2554. 21068         }
  2555. 21069   }
  2556. 21070
  2557. 21071   /* Desired block is not on available chain.  Take oldest block ('front'). */
  2558. 21072   if ((bp = front) == NIL_BUF) panic("all buffers in use", NR_BUFS);
  2559. 21073   rm_lru(bp);
  2560. 21074
  2561. 21075   /* Remove the block that was just taken from its hash chain. */
  2562. 21076   b = (int) bp->b_blocknr & HASH_MASK;
  2563. 21077   prev_ptr = buf_hash[b];
  2564. 21078   if (prev_ptr == bp) {
  2565. 21079         buf_hash[b] = bp->b_hash;
  2566. 21080   } else {
  2567. 21081         /* The block just taken is not on the front of its hash chain. */
  2568. 21082         while (prev_ptr->b_hash != NIL_BUF)
  2569. 21083                 if (prev_ptr->b_hash == bp) {
  2570. 21084                         prev_ptr->b_hash = bp->b_hash;  /* found it */
  2571. 21085                         break;
  2572. 21086                 } else {
  2573. 21087                         prev_ptr = prev_ptr->b_hash;    /* keep looking */
  2574. 21088                 }
  2575. 21089   }
  2576. 21090
  2577. 21091   /* If the block taken is dirty, make it clean by writing it to the disk.
  2578. 21092    * Avoid hysteresis by flushing all other dirty blocks for the same device.
  2579. 21093    */
  2580. 21094   if (bp->b_dev != NO_DEV) {
  2581. 21095         if (bp->b_dirt == DIRTY) flushall(bp->b_dev);
  2582. 21096   }
  2583. 21097
  2584. 21098   /* Fill in block's parameters and add it to the hash chain where it goes. */
  2585. 21099   bp->b_dev = dev;              /* fill in device number */
  2586. 21100   bp->b_blocknr = block;        /* fill in block number */
  2587. 21101   bp->b_count++;                /* record that block is being used */
  2588. 21102   b = (int) bp->b_blocknr & HASH_MASK;
  2589. 21103   bp->b_hash = buf_hash[b];
  2590. 21104   buf_hash[b] = bp;             /* add to hash list */
  2591. 21105
  2592. 21106   /* Go get the requested block unless searching or prefetching. */
  2593. 21107   if (dev != NO_DEV) {
  2594. 21108         if (only_search == PREFETCH) bp->b_dev = NO_DEV;
  2595. 21109         else
  2596. 21110         if (only_search == NORMAL) rw_block(bp, READING);
  2597. 21111   }
  2598. 21112   return(bp);                   /* return the newly acquired block */
  2599. 21113 }
  2600. 21116 /*===========================================================================*
  2601. 21117  *                              put_block                                    *
  2602. 21118  *===========================================================================*/
  2603. 21119 PUBLIC void put_block(bp, block_type)
  2604. 21120 register struct buf *bp;        /* pointer to the buffer to be released */
  2605. 21121 int block_type;                 /* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
  2606. 21122 {
  2607. 21123 /* Return a block to the list of available blocks.   Depending on 'block_type'
  2608. 21124  * it may be put on the front or rear of the LRU chain.  Blocks that are
  2609. 21125  * expected to be needed again shortly (e.g., partially full data blocks)
  2610. 21126  * go on the rear; blocks that are unlikely to be needed again shortly
  2611. 21127  * (e.g., full data blocks) go on the front.  Blocks whose loss can hurt
  2612. 21128  * the integrity of the file system (e.g., inode blocks) are written to
  2613. 21129  * disk immediately if they are dirty.
  2614. 21130  */
  2615. 21131
  2616. 21132   if (bp == NIL_BUF) return;    /* it is easier to check here than in caller */
  2617. 21133
  2618. 21134   bp->b_count--;                /* there is one use fewer now */
  2619. 21135   if (bp->b_count != 0) return; /* block is still in use */
  2620. 21136
  2621. 21137   bufs_in_use--;                /* one fewer block buffers in use */
  2622. 21138
  2623. 21139   /* Put this block back on the LRU chain.  If the ONE_SHOT bit is set in
  2624. 21140    * 'block_type', the block is not likely to be needed again shortly, so put
  2625. 21141    * it on the front of the LRU chain where it will be the first one to be
  2626. 21142    * taken when a free buffer is needed later.
  2627. 21143    */
  2628. 21144   if (block_type & ONE_SHOT) {
  2629. 21145         /* Block probably won't be needed quickly. Put it on front of chain.
  2630. 21146          * It will be the next block to be evicted from the cache.
  2631. 21147          */
  2632. 21148         bp->b_prev = NIL_BUF;
  2633. 21149         bp->b_next = front;
  2634. 21150         if (front == NIL_BUF)
  2635. 21151                 rear = bp;      /* LRU chain was empty */
  2636. 21152         else
  2637. 21153                 front->b_prev = bp;
  2638. 21154         front = bp;
  2639. 21155   } else {
  2640. 21156         /* Block probably will be needed quickly.  Put it on rear of chain.
  2641. 21157          * It will not be evicted from the cache for a long time.
  2642. 21158          */
  2643. 21159         bp->b_prev = rear;
  2644. 21160         bp->b_next = NIL_BUF;
  2645. 21161         if (rear == NIL_BUF)
  2646. 21162                 front = bp;
  2647. 21163         else
  2648. 21164                 rear->b_next = bp;
  2649. 21165         rear = bp;
  2650. 21166   }
  2651. 21167
  2652. 21168   /* Some blocks are so important (e.g., inodes, indirect blocks) that they
  2653. 21169    * should be written to the disk immediately to avoid messing up the file
  2654. 21170    * system in the event of a crash.
  2655. 21171    */
  2656. 21172   if ((block_type & WRITE_IMMED) && bp->b_dirt==DIRTY && bp->b_dev != NO_DEV)
  2657. 21173         rw_block(bp, WRITING);
  2658. 21174 }
  2659. 21177 /*===========================================================================*
  2660. 21178  *                              alloc_zone                                   *
  2661. 21179  *===========================================================================*/
  2662. 21180 PUBLIC zone_t alloc_zone(dev, z)
  2663. 21181 dev_t dev;                      /* device where zone wanted */
  2664. 21182 zone_t z;                       /* try to allocate new zone near this one */
  2665. 21183 {
  2666. 21184 /* Allocate a new zone on the indicated device and return its number. */
  2667. 21185
  2668. 21186   int major, minor;
  2669. 21187   bit_t b, bit;
  2670. 21188   struct super_block *sp;
  2671. 21189
  2672. 21190   /* Note that the routine alloc_bit() returns 1 for the lowest possible
  2673. 21191    * zone, which corresponds to sp->s_firstdatazone.  To convert a value
  2674. 21192    * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
  2675. 21193    * stored in the inode, use the formula:
  2676. 21194    *     z = b + sp->s_firstdatazone - 1
  2677. 21195    * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
  2678. 21196    */
  2679. 21197   sp = get_super(dev);          /* find the super_block for this device */
  2680. 21198
  2681. 21199   /* If z is 0, skip initial part of the map known to be fully in use. */
  2682. 21200   if (z == sp->s_firstdatazone) {
  2683. 21201         bit = sp->s_zsearch;
  2684. 21202   } else {
  2685. 21203         bit = (bit_t) z - (sp->s_firstdatazone - 1);
  2686. 21204   }
  2687. 21205   b = alloc_bit(sp, ZMAP, bit);
  2688. 21206   if (b == NO_BIT) {
  2689. 21207         err_code = ENOSPC;
  2690. 21208         major = (int) (sp->s_dev >> MAJOR) & BYTE;