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

操作系统开发

开发平台:

C/C++

  1. 21209         minor = (int) (sp->s_dev >> MINOR) & BYTE;
  2. 21210         printf("No space on %sdevice %d/%dn",
  3. 21211                 sp->s_dev == ROOT_DEV ? "root " : "", major, minor);
  4. 21212         return(NO_ZONE);
  5. 21213   }
  6. 21214   if (z == sp->s_firstdatazone) sp->s_zsearch = b;      /* for next time */
  7. 21215   return(sp->s_firstdatazone - 1 + (zone_t) b);
  8. 21216 }
  9. 21219 /*===========================================================================*
  10. 21220  *                              free_zone                                    *
  11. 21221  *===========================================================================*/
  12. 21222 PUBLIC void free_zone(dev, numb)
  13. 21223 dev_t dev;                              /* device where zone located */
  14. 21224 zone_t numb;                            /* zone to be returned */
  15. 21225 {
  16. 21226 /* Return a zone. */
  17. 21227
  18. 21228   register struct super_block *sp;
  19. 21229   bit_t bit;
  20. 21230
  21. 21231   /* Locate the appropriate super_block and return bit. */
  22. 21232   sp = get_super(dev);
  23. 21233   if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
  24. 21234   bit = (bit_t) (numb - (sp->s_firstdatazone - 1));
  25. 21235   free_bit(sp, ZMAP, bit);
  26. 21236   if (bit < sp->s_zsearch) sp->s_zsearch = bit;
  27. 21237 }
  28. 21240 /*===========================================================================*
  29. 21241  *                              rw_block                                     *
  30. 21242  *===========================================================================*/
  31. 21243 PUBLIC void rw_block(bp, rw_flag)
  32. 21244 register struct buf *bp;        /* buffer pointer */
  33. 21245 int rw_flag;                    /* READING or WRITING */
  34. 21246 {
  35. 21247 /* Read or write a disk block. This is the only routine in which actual disk
  36. 21248  * I/O is invoked. If an error occurs, a message is printed here, but the error
  37. 21249  * is not reported to the caller.  If the error occurred while purging a block
  38. 21250  * from the cache, it is not clear what the caller could do about it anyway.
  39. 21251  */
  40. 21252
  41. 21253   int r, op;
  42. 21254   off_t pos;
  43. 21255   dev_t dev;
  44. 21256
  45. 21257   if ( (dev = bp->b_dev) != NO_DEV) {
  46. 21258         pos = (off_t) bp->b_blocknr * BLOCK_SIZE;
  47. 21259         op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
  48. 21260         r = dev_io(op, FALSE, dev, pos, BLOCK_SIZE, FS_PROC_NR, bp->b_data);
  49. 21261         if (r != BLOCK_SIZE) {
  50. 21262             if (r >= 0) r = END_OF_FILE;
  51. 21263             if (r != END_OF_FILE)
  52. 21264               printf("Unrecoverable disk error on device %d/%d, block %ldn",
  53. 21265                         (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
  54. 21266                 bp->b_dev = NO_DEV;     /* invalidate block */
  55. 21267
  56. 21268                 /* Report read errors to interested parties. */
  57. 21269                 if (rw_flag == READING) rdwt_err = r;
  58. 21270         }
  59. 21271   }
  60. 21272
  61. 21273   bp->b_dirt = CLEAN;
  62. 21274 }
  63. 21277 /*===========================================================================*
  64. 21278  *                              invalidate                                   *
  65. 21279  *===========================================================================*/
  66. 21280 PUBLIC void invalidate(device)
  67. 21281 dev_t device;                   /* device whose blocks are to be purged */
  68. 21282 {
  69. 21283 /* Remove all the blocks belonging to some device from the cache. */
  70. 21284
  71. 21285   register struct buf *bp;
  72. 21286
  73. 21287   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
  74. 21288         if (bp->b_dev == device) bp->b_dev = NO_DEV;
  75. 21289 }
  76. 21292 /*==========================================================================*
  77. 21293  *                              flushall                                    *
  78. 21294  *==========================================================================*/
  79. 21295 PUBLIC void flushall(dev)
  80. 21296 dev_t dev;                      /* device to flush */
  81. 21297 {
  82. 21298 /* Flush all dirty blocks for one device. */
  83. 21299
  84. 21300   register struct buf *bp;
  85. 21301   static struct buf *dirty[NR_BUFS];    /* static so it isn't on stack */
  86. 21302   int ndirty;
  87. 21303
  88. 21304   for (bp = &buf[0], ndirty = 0; bp < &buf[NR_BUFS]; bp++)
  89. 21305         if (bp->b_dirt == DIRTY && bp->b_dev == dev) dirty[ndirty++] = bp;
  90. 21306   rw_scattered(dev, dirty, ndirty, WRITING);
  91. 21307 }
  92. 21310 /*===========================================================================*
  93. 21311  *                              rw_scattered                                 *
  94. 21312  *===========================================================================*/
  95. 21313 PUBLIC void rw_scattered(dev, bufq, bufqsize, rw_flag)
  96. 21314 dev_t dev;                      /* major-minor device number */
  97. 21315 struct buf **bufq;              /* pointer to array of buffers */
  98. 21316 int bufqsize;                   /* number of buffers */
  99. 21317 int rw_flag;                    /* READING or WRITING */
  100. 21318 {
  101. 21319 /* Read or write scattered data from a device. */
  102. 21320
  103. 21321   register struct buf *bp;
  104. 21322   int gap;
  105. 21323   register int i;
  106. 21324   register struct iorequest_s *iop;
  107. 21325   static struct iorequest_s iovec[NR_IOREQS];  /* static so it isn't on stack */
  108. 21326   int j;
  109. 21327
  110. 21328   /* (Shell) sort buffers on b_blocknr. */
  111. 21329   gap = 1;
  112. 21330   do
  113. 21331         gap = 3 * gap + 1;
  114. 21332   while (gap <= bufqsize);
  115. 21333   while (gap != 1) {
  116. 21334         gap /= 3;
  117. 21335         for (j = gap; j < bufqsize; j++) {
  118. 21336                 for (i = j - gap;
  119. 21337                      i >= 0 && bufq[i]->b_blocknr > bufq[i + gap]->b_blocknr;
  120. 21338                      i -= gap) {
  121. 21339                         bp = bufq[i];
  122. 21340                         bufq[i] = bufq[i + gap];
  123. 21341                         bufq[i + gap] = bp;
  124. 21342                 }
  125. 21343         }
  126. 21344   }
  127. 21345
  128. 21346   /* Set up i/o vector and do i/o.  The result of dev_io is discarded because
  129. 21347    * all results are returned in the vector.  If dev_io fails completely, the
  130. 21348    * vector is unchanged and all results are taken as errors.
  131. 21349    */  
  132. 21350   while (bufqsize > 0) {
  133. 21351         for (j = 0, iop = iovec; j < NR_IOREQS && j < bufqsize; j++, iop++) {
  134. 21352                 bp = bufq[j];
  135. 21353                 iop->io_position = (off_t) bp->b_blocknr * BLOCK_SIZE;
  136. 21354                 iop->io_buf = bp->b_data;
  137. 21355                 iop->io_nbytes = BLOCK_SIZE;
  138. 21356                 iop->io_request = rw_flag == WRITING ?
  139. 21357                                   DEV_WRITE : DEV_READ | OPTIONAL_IO;
  140. 21358         }
  141. 21359         (void) dev_io(SCATTERED_IO, 0, dev, (off_t) 0, j, FS_PROC_NR,
  142. 21360                                                         (char *) iovec);
  143. 21361
  144. 21362         /* Harvest the results.  Leave read errors for rw_block() to complain. */
  145. 21363         for (i = 0, iop = iovec; i < j; i++, iop++) {
  146. 21364                 bp = bufq[i];
  147. 21365                 if (rw_flag == READING) {
  148. 21366                     if (iop->io_nbytes == 0)
  149. 21367                         bp->b_dev = dev;        /* validate block */
  150. 21368                     put_block(bp, PARTIAL_DATA_BLOCK);
  151. 21369                 } else {
  152. 21370                     if (iop->io_nbytes != 0) {
  153. 21371                      printf("Unrecoverable write error on device %d/%d, block %ldn",
  154. 21372                                 (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
  155. 21373                         bp->b_dev = NO_DEV;     /* invalidate block */
  156. 21374                     }
  157. 21375                     bp->b_dirt = CLEAN;
  158. 21376                 }
  159. 21377         }
  160. 21378         bufq += j;
  161. 21379         bufqsize -= j;
  162. 21380   }
  163. 21381 }
  164. 21384 /*===========================================================================*
  165. 21385  *                              rm_lru                                       *
  166. 21386  *===========================================================================*/
  167. 21387 PRIVATE void rm_lru(bp)
  168. 21388 struct buf *bp;
  169. 21389 {
  170. 21390 /* Remove a block from its LRU chain. */
  171. 21391
  172. 21392   struct buf *next_ptr, *prev_ptr;
  173. 21393
  174. 21394   bufs_in_use++;
  175. 21395   next_ptr = bp->b_next;        /* successor on LRU chain */
  176. 21396   prev_ptr = bp->b_prev;        /* predecessor on LRU chain */
  177. 21397   if (prev_ptr != NIL_BUF)
  178. 21398         prev_ptr->b_next = next_ptr;
  179. 21399   else
  180. 21400         front = next_ptr;       /* this block was at front of chain */
  181. 21401
  182. 21402   if (next_ptr != NIL_BUF)
  183. 21403         next_ptr->b_prev = prev_ptr;
  184. 21404   else
  185. 21405         rear = prev_ptr;        /* this block was at rear of chain */
  186. 21406 }
  187. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  188. src/fs/inode.c    
  189. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  190. 21500 /* This file manages the inode table.  There are procedures to allocate and
  191. 21501  * deallocate inodes, acquire, erase, and release them, and read and write
  192. 21502  * them from the disk.
  193. 21503  *
  194. 21504  * The entry points into this file are
  195. 21505  *   get_inode:    search inode table for a given inode; if not there, read it
  196. 21506  *   put_inode:    indicate that an inode is no longer needed in memory
  197. 21507  *   alloc_inode:  allocate a new, unused inode
  198. 21508  *   wipe_inode:   erase some fields of a newly allocated inode
  199. 21509  *   free_inode:   mark an inode as available for a new file
  200. 21510  *   update_times: update atime, ctime, and mtime
  201. 21511  *   rw_inode:     read a disk block and extract an inode, or corresp. write
  202. 21512  *   old_icopy:    copy to/from in-core inode struct and disk inode (V1.x)
  203. 21513  *   new_icopy:    copy to/from in-core inode struct and disk inode (V2.x)
  204. 21514  *   dup_inode:    indicate that someone else is using an inode table entry
  205. 21515  */
  206. 21516
  207. 21517 #include "fs.h"
  208. 21518 #include <minix/boot.h>
  209. 21519 #include "buf.h"
  210. 21520 #include "file.h"
  211. 21521 #include "fproc.h"
  212. 21522 #include "inode.h"
  213. 21523 #include "super.h"
  214. 21524
  215. 21525 FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
  216. 21526                                                 int direction, int norm));
  217. 21527 FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
  218. 21528                                                 int direction, int norm));
  219. 21529
  220. 21530
  221. 21531 /*===========================================================================*
  222. 21532  *                              get_inode                                    *
  223. 21533  *===========================================================================*/
  224. 21534 PUBLIC struct inode *get_inode(dev, numb)
  225. 21535 dev_t dev;                      /* device on which inode resides */
  226. 21536 int numb;                       /* inode number (ANSI: may not be unshort) */
  227. 21537 {
  228. 21538 /* Find a slot in the inode table, load the specified inode into it, and
  229. 21539  * return a pointer to the slot.  If 'dev' == NO_DEV, just return a free slot.
  230. 21540  */
  231. 21541
  232. 21542   register struct inode *rip, *xp;
  233. 21543
  234. 21544   /* Search the inode table both for (dev, numb) and a free slot. */
  235. 21545   xp = NIL_INODE;
  236. 21546   for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
  237. 21547         if (rip->i_count > 0) { /* only check used slots for (dev, numb) */
  238. 21548                 if (rip->i_dev == dev && rip->i_num == numb) {
  239. 21549                         /* This is the inode that we are looking for. */
  240. 21550                         rip->i_count++;
  241. 21551                         return(rip);    /* (dev, numb) found */
  242. 21552                 }
  243. 21553         } else {
  244. 21554                 xp = rip;       /* remember this free slot for later */
  245. 21555         }
  246. 21556   }
  247. 21557
  248. 21558   /* Inode we want is not currently in use.  Did we find a free slot? */
  249. 21559   if (xp == NIL_INODE) {        /* inode table completely full */
  250. 21560         err_code = ENFILE;
  251. 21561         return(NIL_INODE);
  252. 21562   }
  253. 21563
  254. 21564   /* A free inode slot has been located.  Load the inode into it. */
  255. 21565   xp->i_dev = dev;
  256. 21566   xp->i_num = numb;
  257. 21567   xp->i_count = 1;
  258. 21568   if (dev != NO_DEV) rw_inode(xp, READING);     /* get inode from disk */
  259. 21569   xp->i_update = 0;             /* all the times are initially up-to-date */
  260. 21570
  261. 21571   return(xp);
  262. 21572 }
  263. 21575 /*===========================================================================*
  264. 21576  *                              put_inode                                    *
  265. 21577  *===========================================================================*/
  266. 21578 PUBLIC void put_inode(rip)
  267. 21579 register struct inode *rip;     /* pointer to inode to be released */
  268. 21580 {
  269. 21581 /* The caller is no longer using this inode.  If no one else is using it either
  270. 21582  * write it back to the disk immediately.  If it has no links, truncate it and
  271. 21583  * return it to the pool of available inodes.
  272. 21584  */
  273. 21585
  274. 21586   if (rip == NIL_INODE) return; /* checking here is easier than in caller */
  275. 21587   if (--rip->i_count == 0) {    /* i_count == 0 means no one is using it now */
  276. 21588         if ((rip->i_nlinks & BYTE) == 0) {
  277. 21589                 /* i_nlinks == 0 means free the inode. */
  278. 21590                 truncate(rip);  /* return all the disk blocks */
  279. 21591                 rip->i_mode = I_NOT_ALLOC;      /* clear I_TYPE field */
  280. 21592                 rip->i_dirt = DIRTY;
  281. 21593                 free_inode(rip->i_dev, rip->i_num);
  282. 21594         } else {
  283. 21595                 if (rip->i_pipe == I_PIPE) truncate(rip);
  284. 21596         }
  285. 21597         rip->i_pipe = NO_PIPE;  /* should always be cleared */
  286. 21598         if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
  287. 21599   }
  288. 21600 }
  289. 21602 /*===========================================================================*
  290. 21603  *                              alloc_inode                                  *
  291. 21604  *===========================================================================*/
  292. 21605 PUBLIC struct inode *alloc_inode(dev, bits)
  293. 21606 dev_t dev;                      /* device on which to allocate the inode */
  294. 21607 mode_t bits;                    /* mode of the inode */
  295. 21608 {
  296. 21609 /* Allocate a free inode on 'dev', and return a pointer to it. */
  297. 21610
  298. 21611   register struct inode *rip;
  299. 21612   register struct super_block *sp;
  300. 21613   int major, minor, inumb;
  301. 21614   bit_t b;
  302. 21615
  303. 21616   sp = get_super(dev);  /* get pointer to super_block */
  304. 21617   if (sp->s_rd_only) {  /* can't allocate an inode on a read only device. */
  305. 21618         err_code = EROFS;
  306. 21619         return(NIL_INODE);
  307. 21620   }
  308. 21621
  309. 21622   /* Acquire an inode from the bit map. */
  310. 21623   b = alloc_bit(sp, IMAP, sp->s_isearch);
  311. 21624   if (b == NO_BIT) {
  312. 21625         err_code = ENFILE;
  313. 21626         major = (int) (sp->s_dev >> MAJOR) & BYTE;
  314. 21627         minor = (int) (sp->s_dev >> MINOR) & BYTE;
  315. 21628         printf("Out of i-nodes on %sdevice %d/%dn",
  316. 21629                 sp->s_dev == ROOT_DEV ? "root " : "", major, minor);
  317. 21630         return(NIL_INODE);
  318. 21631   }
  319. 21632   sp->s_isearch = b;            /* next time start here */
  320. 21633   inumb = (int) b;              /* be careful not to pass unshort as param */
  321. 21634
  322. 21635   /* Try to acquire a slot in the inode table. */
  323. 21636   if ((rip = get_inode(NO_DEV, inumb)) == NIL_INODE) {
  324. 21637         /* No inode table slots available.  Free the inode just allocated. */
  325. 21638         free_bit(sp, IMAP, b);
  326. 21639   } else {
  327. 21640         /* An inode slot is available. Put the inode just allocated into it. */
  328. 21641         rip->i_mode = bits;             /* set up RWX bits */
  329. 21642         rip->i_nlinks = (nlink_t) 0;    /* initial no links */
  330. 21643         rip->i_uid = fp->fp_effuid;     /* file's uid is owner's */
  331. 21644         rip->i_gid = fp->fp_effgid;     /* ditto group id */
  332. 21645         rip->i_dev = dev;               /* mark which device it is on */
  333. 21646         rip->i_ndzones = sp->s_ndzones; /* number of direct zones */
  334. 21647         rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/
  335. 21648         rip->i_sp = sp;                 /* pointer to super block */
  336. 21649
  337. 21650         /* Fields not cleared already are cleared in wipe_inode().  They have
  338. 21651          * been put there because truncate() needs to clear the same fields if
  339. 21652          * the file happens to be open while being truncated.  It saves space
  340. 21653          * not to repeat the code twice.
  341. 21654          */
  342. 21655         wipe_inode(rip);
  343. 21656   }
  344. 21657
  345. 21658   return(rip);
  346. 21659 }
  347. 21661 /*===========================================================================*
  348. 21662  *                              wipe_inode                                   *
  349. 21663  *===========================================================================*/
  350. 21664 PUBLIC void wipe_inode(rip)
  351. 21665 register struct inode *rip;     /* the inode to be erased */
  352. 21666 {
  353. 21667 /* Erase some fields in the inode.  This function is called from alloc_inode()
  354. 21668  * when a new inode is to be allocated, and from truncate(), when an existing
  355. 21669  * inode is to be truncated.
  356. 21670  */
  357. 21671
  358. 21672   register int i;
  359. 21673
  360. 21674   rip->i_size = 0;
  361. 21675   rip->i_update = ATIME | CTIME | MTIME;        /* update all times later */
  362. 21676   rip->i_dirt = DIRTY;
  363. 21677   for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
  364. 21678 }
  365. 21681 /*===========================================================================*
  366. 21682  *                              free_inode                                   *
  367. 21683  *===========================================================================*/
  368. 21684 PUBLIC void free_inode(dev, inumb)
  369. 21685 dev_t dev;                      /* on which device is the inode */
  370. 21686 ino_t inumb;                    /* number of inode to be freed */
  371. 21687 {
  372. 21688 /* Return an inode to the pool of unallocated inodes. */
  373. 21689
  374. 21690   register struct super_block *sp;
  375. 21691   bit_t b;
  376. 21692
  377. 21693   /* Locate the appropriate super_block. */
  378. 21694   sp = get_super(dev);
  379. 21695   if (inumb <= 0 || inumb > sp->s_ninodes) return;
  380. 21696   b = inumb;
  381. 21697   free_bit(sp, IMAP, b);
  382. 21698   if (b < sp->s_isearch) sp->s_isearch = b;
  383. 21699 }
  384. 21701 /*===========================================================================*
  385. 21702  *                              update_times                                 *
  386. 21703  *===========================================================================*/
  387. 21704 PUBLIC void update_times(rip)
  388. 21705 register struct inode *rip;     /* pointer to inode to be read/written */
  389. 21706 {
  390. 21707 /* Various system calls are required by the standard to update atime, ctime,
  391. 21708  * or mtime.  Since updating a time requires sending a message to the clock
  392. 21709  * task--an expensive business--the times are marked for update by setting
  393. 21710  * bits in i_update.  When a stat, fstat, or sync is done, or an inode is 
  394. 21711  * released, update_times() may be called to actually fill in the times.
  395. 21712  */
  396. 21713
  397. 21714   time_t cur_time;
  398. 21715   struct super_block *sp;
  399. 21716
  400. 21717   sp = rip->i_sp;               /* get pointer to super block. */
  401. 21718   if (sp->s_rd_only) return;    /* no updates for read-only file systems */
  402. 21719
  403. 21720   cur_time = clock_time();
  404. 21721   if (rip->i_update & ATIME) rip->i_atime = cur_time;
  405. 21722   if (rip->i_update & CTIME) rip->i_ctime = cur_time;
  406. 21723   if (rip->i_update & MTIME) rip->i_mtime = cur_time;
  407. 21724   rip->i_update = 0;            /* they are all up-to-date now */
  408. 21725 }
  409. 21728 /*===========================================================================*
  410. 21729  *                              rw_inode                                     *
  411. 21730  *===========================================================================*/
  412. 21731 PUBLIC void rw_inode(rip, rw_flag)
  413. 21732 register struct inode *rip;     /* pointer to inode to be read/written */
  414. 21733 int rw_flag;                    /* READING or WRITING */
  415. 21734 {
  416. 21735 /* An entry in the inode table is to be copied to or from the disk. */
  417. 21736
  418. 21737   register struct buf *bp;
  419. 21738   register struct super_block *sp;
  420. 21739   d1_inode *dip;
  421. 21740   d2_inode *dip2;
  422. 21741   block_t b, offset;
  423. 21742
  424. 21743   /* Get the block where the inode resides. */
  425. 21744   sp = get_super(rip->i_dev);   /* get pointer to super block */
  426. 21745   rip->i_sp = sp;               /* inode must contain super block pointer */
  427. 21746   offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
  428. 21747   b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
  429. 21748   bp = get_block(rip->i_dev, b, NORMAL);
  430. 21749   dip  = bp->b_v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
  431. 21750   dip2 = bp->b_v2_ino + (rip->i_num - 1) % V2_INODES_PER_BLOCK;
  432. 21751
  433. 21752   /* Do the read or write. */
  434. 21753   if (rw_flag == WRITING) {
  435. 21754         if (rip->i_update) update_times(rip);   /* times need updating */
  436. 21755         if (sp->s_rd_only == FALSE) bp->b_dirt = DIRTY;
  437. 21756   }
  438. 21757
  439. 21758   /* Copy the inode from the disk block to the in-core table or vice versa.
  440. 21759    * If the fourth parameter below is FALSE, the bytes are swapped.
  441. 21760    */
  442. 21761   if (sp->s_version == V1)
  443. 21762         old_icopy(rip, dip,  rw_flag, sp->s_native);
  444. 21763   else
  445. 21764         new_icopy(rip, dip2, rw_flag, sp->s_native);
  446. 21765   
  447. 21766   put_block(bp, INODE_BLOCK);
  448. 21767   rip->i_dirt = CLEAN;
  449. 21768 }
  450. 21771 /*===========================================================================*
  451. 21772  *                              old_icopy                                    *
  452. 21773  *===========================================================================*/
  453. 21774 PRIVATE void old_icopy(rip, dip, direction, norm)
  454. 21775 register struct inode *rip;     /* pointer to the in-core inode struct */
  455. 21776 register d1_inode *dip;         /* pointer to the d1_inode inode struct */
  456. 21777 int direction;                  /* READING (from disk) or WRITING (to disk) */
  457. 21778 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  458. 21779
  459. 21780 {
  460. 21781 /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
  461. 21782  * 68000) all have different inode layouts.  When an inode is read or written
  462. 21783  * this routine handles the conversions so that the information in the inode
  463. 21784  * table is independent of the disk structure from which the inode came.
  464. 21785  * The old_icopy routine copies to and from V1 disks.
  465. 21786  */
  466. 21787
  467. 21788   int i;
  468. 21789
  469. 21790   if (direction == READING) {
  470. 21791         /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
  471. 21792         rip->i_mode    = conv2(norm, (int) dip->d1_mode);
  472. 21793         rip->i_uid     = conv2(norm, (int) dip->d1_uid );
  473. 21794         rip->i_size    = conv4(norm,       dip->d1_size);
  474. 21795         rip->i_mtime   = conv4(norm,       dip->d1_mtime);
  475. 21796         rip->i_atime   = rip->i_mtime;
  476. 21797         rip->i_ctime   = rip->i_mtime;
  477. 21798         rip->i_nlinks  = (nlink_t) dip->d1_nlinks;      /* 1 char */
  478. 21799         rip->i_gid     = (gid_t) dip->d1_gid;           /* 1 char */
  479. 21800         rip->i_ndzones = V1_NR_DZONES;
  480. 21801         rip->i_nindirs = V1_INDIRECTS;
  481. 21802         for (i = 0; i < V1_NR_TZONES; i++)
  482. 21803                 rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
  483. 21804   } else {
  484. 21805         /* Copying V1.x inode to disk from the in-core table. */
  485. 21806         dip->d1_mode   = conv2(norm, (int) rip->i_mode);
  486. 21807         dip->d1_uid    = conv2(norm, (int) rip->i_uid );
  487. 21808         dip->d1_size   = conv4(norm,       rip->i_size);
  488. 21809         dip->d1_mtime  = conv4(norm,       rip->i_mtime);
  489. 21810         dip->d1_nlinks = (nlink_t) rip->i_nlinks;       /* 1 char */
  490. 21811         dip->d1_gid    = (gid_t) rip->i_gid;            /* 1 char */
  491. 21812         for (i = 0; i < V1_NR_TZONES; i++)
  492. 21813                 dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
  493. 21814   }
  494. 21815 }
  495. 21818 /*===========================================================================*
  496. 21819  *                              new_icopy                                    *
  497. 21820  *===========================================================================*/
  498. 21821 PRIVATE void new_icopy(rip, dip, direction, norm)
  499. 21822 register struct inode *rip;     /* pointer to the in-core inode struct */
  500. 21823 register d2_inode *dip; /* pointer to the d2_inode struct */
  501. 21824 int direction;                  /* READING (from disk) or WRITING (to disk) */
  502. 21825 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  503. 21826
  504. 21827 {
  505. 21828 /* Same as old_icopy, but to/from V2 disk layout. */
  506. 21829
  507. 21830   int i;
  508. 21831
  509. 21832   if (direction == READING) {
  510. 21833         /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
  511. 21834         rip->i_mode    = conv2(norm,dip->d2_mode);
  512. 21835         rip->i_uid     = conv2(norm,dip->d2_uid );
  513. 21836         rip->i_nlinks  = conv2(norm,(int) dip->d2_nlinks);
  514. 21837         rip->i_gid     = conv2(norm,(int) dip->d2_gid );
  515. 21838         rip->i_size    = conv4(norm,dip->d2_size);
  516. 21839         rip->i_atime   = conv4(norm,dip->d2_atime);
  517. 21840         rip->i_ctime   = conv4(norm,dip->d2_ctime);
  518. 21841         rip->i_mtime   = conv4(norm,dip->d2_mtime);
  519. 21842         rip->i_ndzones = V2_NR_DZONES;
  520. 21843         rip->i_nindirs = V2_INDIRECTS;
  521. 21844         for (i = 0; i < V2_NR_TZONES; i++)
  522. 21845                 rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
  523. 21846   } else {
  524. 21847         /* Copying V2.x inode to disk from the in-core table. */
  525. 21848         dip->d2_mode   = conv2(norm,rip->i_mode);
  526. 21849         dip->d2_uid    = conv2(norm,rip->i_uid );
  527. 21850         dip->d2_nlinks = conv2(norm,rip->i_nlinks);
  528. 21851         dip->d2_gid    = conv2(norm,rip->i_gid );
  529. 21852         dip->d2_size   = conv4(norm,rip->i_size);
  530. 21853         dip->d2_atime  = conv4(norm,rip->i_atime);
  531. 21854         dip->d2_ctime  = conv4(norm,rip->i_ctime);
  532. 21855         dip->d2_mtime  = conv4(norm,rip->i_mtime);
  533. 21856         for (i = 0; i < V2_NR_TZONES; i++)
  534. 21857                 dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
  535. 21858   }
  536. 21859 }
  537. 21862 /*===========================================================================*
  538. 21863  *                              dup_inode                                    *
  539. 21864  *===========================================================================*/
  540. 21865 PUBLIC void dup_inode(ip)
  541. 21866 struct inode *ip;               /* The inode to be duplicated. */
  542. 21867 {
  543. 21868 /* This routine is a simplified form of get_inode() for the case where
  544. 21869  * the inode pointer is already known.
  545. 21870  */
  546. 21871
  547. 21872   ip->i_count++;
  548. 21873 }
  549. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  550. src/fs/super.c    
  551. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  552. 21900 /* This file manages the super block table and the related data structures,
  553. 21901  * namely, the bit maps that keep track of which zones and which inodes are
  554. 21902  * allocated and which are free.  When a new inode or zone is needed, the
  555. 21903  * appropriate bit map is searched for a free entry.
  556. 21904  *
  557. 21905  * The entry points into this file are
  558. 21906  *   alloc_bit:       somebody wants to allocate a zone or inode; find one
  559. 21907  *   free_bit:        indicate that a zone or inode is available for allocation
  560. 21908  *   get_super:       search the 'superblock' table for a device
  561. 21909  *   mounted:         tells if file inode is on mounted (or ROOT) file system
  562. 21910  *   read_super:      read a superblock
  563. 21911  */
  564. 21912
  565. 21913 #include "fs.h"
  566. 21914 #include <string.h>
  567. 21915 #include <minix/boot.h>
  568. 21916 #include "buf.h"
  569. 21917 #include "inode.h"
  570. 21918 #include "super.h"
  571. 21919
  572. 21920 #define BITCHUNK_BITS   (usizeof(bitchunk_t) * CHAR_BIT)
  573. 21921 #define BITS_PER_BLOCK  (BITMAP_CHUNKS * BITCHUNK_BITS)
  574. 21922
  575. 21923 /*===========================================================================*
  576. 21924  *                              alloc_bit                                    *
  577. 21925  *===========================================================================*/
  578. 21926 PUBLIC bit_t alloc_bit(sp, map, origin)
  579. 21927 struct super_block *sp;         /* the filesystem to allocate from */
  580. 21928 int map;                        /* IMAP (inode map) or ZMAP (zone map) */
  581. 21929 bit_t origin;                   /* number of bit to start searching at */
  582. 21930 {
  583. 21931 /* Allocate a bit from a bit map and return its bit number. */
  584. 21932
  585. 21933   block_t start_block;          /* first bit block */
  586. 21934   bit_t map_bits;               /* how many bits are there in the bit map? */
  587. 21935   unsigned bit_blocks;          /* how many blocks are there in the bit map? */
  588. 21936   unsigned block, word, bcount, wcount;
  589. 21937   struct buf *bp;
  590. 21938   bitchunk_t *wptr, *wlim, k;
  591. 21939   bit_t i, b;
  592. 21940
  593. 21941   if (sp->s_rd_only)
  594. 21942         panic("can't allocate bit on read-only filesys.", NO_NUM);
  595. 21943
  596. 21944   if (map == IMAP) {
  597. 21945         start_block = SUPER_BLOCK + 1;
  598. 21946         map_bits = sp->s_ninodes + 1;
  599. 21947         bit_blocks = sp->s_imap_blocks;
  600. 21948   } else {
  601. 21949         start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
  602. 21950         map_bits = sp->s_zones - (sp->s_firstdatazone - 1);
  603. 21951         bit_blocks = sp->s_zmap_blocks;
  604. 21952   }
  605. 21953
  606. 21954   /* Figure out where to start the bit search (depends on 'origin'). */
  607. 21955   if (origin >= map_bits) origin = 0;   /* for robustness */
  608. 21956
  609. 21957   /* Locate the starting place. */
  610. 21958   block = origin / BITS_PER_BLOCK;
  611. 21959   word = (origin % BITS_PER_BLOCK) / BITCHUNK_BITS;
  612. 21960
  613. 21961   /* Iterate over all blocks plus one, because we start in the middle. */
  614. 21962   bcount = bit_blocks + 1;
  615. 21963   do {
  616. 21964         bp = get_block(sp->s_dev, start_block + block, NORMAL);
  617. 21965         wlim = &bp->b_bitmap[BITMAP_CHUNKS];
  618. 21966
  619. 21967         /* Iterate over the words in block. */
  620. 21968         for (wptr = &bp->b_bitmap[word]; wptr < wlim; wptr++) {
  621. 21969
  622. 21970                 /* Does this word contain a free bit? */
  623. 21971                 if (*wptr == (bitchunk_t) ~0) continue;
  624. 21972
  625. 21973                 /* Find and allocate the free bit. */
  626. 21974                 k = conv2(sp->s_native, (int) *wptr);
  627. 21975                 for (i = 0; (k & (1 << i)) != 0; ++i) {}
  628. 21976
  629. 21977                 /* Bit number from the start of the bit map. */
  630. 21978                 b = ((bit_t) block * BITS_PER_BLOCK)
  631. 21979                     + (wptr - &bp->b_bitmap[0]) * BITCHUNK_BITS
  632. 21980                     + i;
  633. 21981
  634. 21982                 /* Don't allocate bits beyond the end of the map. */
  635. 21983                 if (b >= map_bits) break;
  636. 21984
  637. 21985                 /* Allocate and return bit number. */
  638. 21986                 k |= 1 << i;
  639. 21987                 *wptr = conv2(sp->s_native, (int) k);
  640. 21988                 bp->b_dirt = DIRTY;
  641. 21989                 put_block(bp, MAP_BLOCK);
  642. 21990                 return(b);
  643. 21991         }
  644. 21992         put_block(bp, MAP_BLOCK);
  645. 21993         if (++block >= bit_blocks) block = 0;   /* last block, wrap around */
  646. 21994         word = 0;
  647. 21995   } while (--bcount > 0);
  648. 21996   return(NO_BIT);               /* no bit could be allocated */
  649. 21997 }
  650. 22000 /*===========================================================================*
  651. 22001  *                              free_bit                                     *
  652. 22002  *===========================================================================*/
  653. 22003 PUBLIC void free_bit(sp, map, bit_returned)
  654. 22004 struct super_block *sp;         /* the filesystem to operate on */
  655. 22005 int map;                        /* IMAP (inode map) or ZMAP (zone map) */
  656. 22006 bit_t bit_returned;             /* number of bit to insert into the map */
  657. 22007 {
  658. 22008 /* Return a zone or inode by turning off its bitmap bit. */
  659. 22009
  660. 22010   unsigned block, word, bit;
  661. 22011   struct buf *bp;
  662. 22012   bitchunk_t k, mask;
  663. 22013   block_t start_block;
  664. 22014
  665. 22015   if (sp->s_rd_only)
  666. 22016         panic("can't free bit on read-only filesys.", NO_NUM);
  667. 22017
  668. 22018   if (map == IMAP) {
  669. 22019         start_block = SUPER_BLOCK + 1;
  670. 22020   } else {
  671. 22021         start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
  672. 22022   }
  673. 22023   block = bit_returned / BITS_PER_BLOCK;
  674. 22024   word = (bit_returned % BITS_PER_BLOCK) / BITCHUNK_BITS;
  675. 22025   bit = bit_returned % BITCHUNK_BITS;
  676. 22026   mask = 1 << bit;
  677. 22027
  678. 22028   bp = get_block(sp->s_dev, start_block + block, NORMAL);
  679. 22029
  680. 22030   k = conv2(sp->s_native, (int) bp->b_bitmap[word]);
  681. 22031   if (!(k & mask)) {
  682. 22032         panic(map == IMAP ? "tried to free unused inode" :
  683. 22033               "tried to free unused block", NO_NUM);
  684. 22034   }
  685. 22035
  686. 22036   k &= ~mask;
  687. 22037   bp->b_bitmap[word] = conv2(sp->s_native, (int) k);
  688. 22038   bp->b_dirt = DIRTY;
  689. 22039
  690. 22040   put_block(bp, MAP_BLOCK);
  691. 22041 }
  692. 22044 /*===========================================================================*
  693. 22045  *                              get_super                                    *
  694. 22046  *===========================================================================*/
  695. 22047 PUBLIC struct super_block *get_super(dev)
  696. 22048 dev_t dev;                      /* device number whose super_block is sought */
  697. 22049 {
  698. 22050 /* Search the superblock table for this device.  It is supposed to be there. */
  699. 22051
  700. 22052   register struct super_block *sp;
  701. 22053
  702. 22054   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
  703. 22055         if (sp->s_dev == dev) return(sp);
  704. 22056
  705. 22057   /* Search failed.  Something wrong. */
  706. 22058   panic("can't find superblock for device (in decimal)", (int) dev);
  707. 22059
  708. 22060   return(NIL_SUPER);            /* to keep the compiler and lint quiet */
  709. 22061 }
  710. 22064 /*===========================================================================*
  711. 22065  *                              mounted                                      *
  712. 22066  *===========================================================================*/
  713. 22067 PUBLIC int mounted(rip)
  714. 22068 register struct inode *rip;     /* pointer to inode */
  715. 22069 {
  716. 22070 /* Report on whether the given inode is on a mounted (or ROOT) file system. */
  717. 22071
  718. 22072   register struct super_block *sp;
  719. 22073   register dev_t dev;
  720. 22074
  721. 22075   dev = (dev_t) rip->i_zone[0];
  722. 22076   if (dev == ROOT_DEV) return(TRUE);    /* inode is on root file system */
  723. 22077
  724. 22078   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
  725. 22079         if (sp->s_dev == dev) return(TRUE);
  726. 22080
  727. 22081   return(FALSE);
  728. 22082 }
  729. 22085 /*===========================================================================*
  730. 22086  *                              read_super                                   *
  731. 22087  *===========================================================================*/
  732. 22088 PUBLIC int read_super(sp)
  733. 22089 register struct super_block *sp; /* pointer to a superblock */
  734. 22090 {
  735. 22091 /* Read a superblock. */
  736. 22092
  737. 22093   register struct buf *bp;
  738. 22094   dev_t dev;
  739. 22095   int magic;
  740. 22096   int version, native;
  741. 22097
  742. 22098   dev = sp->s_dev;              /* save device (will be overwritten by copy) */
  743. 22099   bp = get_block(sp->s_dev, SUPER_BLOCK, NORMAL);
  744. 22100   memcpy( (char *) sp, bp->b_data, (size_t) SUPER_SIZE);
  745. 22101   put_block(bp, ZUPER_BLOCK);
  746. 22102   sp->s_dev = NO_DEV;           /* restore later */
  747. 22103   magic = sp->s_magic;          /* determines file system type */
  748. 22104
  749. 22105   /* Get file system version and type. */
  750. 22106   if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP, SUPER_MAGIC)) {
  751. 22107         version = V1;
  752. 22108         native  = (magic == SUPER_MAGIC);
  753. 22109   } else if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP, SUPER_V2)) {
  754. 22110         version = V2;
  755. 22111         native  = (magic == SUPER_V2);
  756. 22112   } else {
  757. 22113         return(EINVAL);
  758. 22114   }
  759. 22115
  760. 22116   /* If the super block has the wrong byte order, swap the fields; the magic
  761. 22117    * number doesn't need conversion. */
  762. 22118   sp->s_ninodes =       conv2(native, (int) sp->s_ninodes);
  763. 22119   sp->s_nzones =        conv2(native, (int) sp->s_nzones);
  764. 22120   sp->s_imap_blocks =   conv2(native, (int) sp->s_imap_blocks);
  765. 22121   sp->s_zmap_blocks =   conv2(native, (int) sp->s_zmap_blocks);
  766. 22122   sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
  767. 22123   sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
  768. 22124   sp->s_max_size =      conv4(native, sp->s_max_size);
  769. 22125   sp->s_zones =         conv4(native, sp->s_zones);
  770. 22126
  771. 22127   /* In V1, the device size was kept in a short, s_nzones, which limited
  772. 22128    * devices to 32K zones.  For V2, it was decided to keep the size as a
  773. 22129    * long.  However, just changing s_nzones to a long would not work, since
  774. 22130    * then the position of s_magic in the super block would not be the same
  775. 22131    * in V1 and V2 file systems, and there would be no way to tell whether
  776. 22132    * a newly mounted file system was V1 or V2.  The solution was to introduce
  777. 22133    * a new variable, s_zones, and copy the size there.
  778. 22134    *
  779. 22135    * Calculate some other numbers that depend on the version here too, to
  780. 22136    * hide some of the differences.
  781. 22137    */
  782. 22138   if (version == V1) {
  783. 22139         sp->s_zones = sp->s_nzones;     /* only V1 needs this copy */
  784. 22140         sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
  785. 22141         sp->s_ndzones = V1_NR_DZONES;
  786. 22142         sp->s_nindirs = V1_INDIRECTS;
  787. 22143   } else {
  788. 22144         sp->s_inodes_per_block = V2_INODES_PER_BLOCK;
  789. 22145         sp->s_ndzones = V2_NR_DZONES;
  790. 22146         sp->s_nindirs = V2_INDIRECTS;
  791. 22147   }
  792. 22148
  793. 22149   sp->s_isearch = 0;            /* inode searches initially start at 0 */
  794. 22150   sp->s_zsearch = 0;            /* zone searches initially start at 0 */
  795. 22151   sp->s_version = version;
  796. 22152   sp->s_native  = native;
  797. 22153
  798. 22154   /* Make a few basic checks to see if super block looks reasonable. */
  799. 22155   if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
  800. 22156                                 || sp->s_ninodes < 1 || sp->s_zones < 1
  801. 22157                                 || (unsigned) sp->s_log_zone_size > 4) {
  802. 22158         return(EINVAL);
  803. 22159   }
  804. 22160   sp->s_dev = dev;              /* restore device number */
  805. 22161   return(OK);
  806. 22162 }
  807. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  808. src/fs/filedes.c    
  809. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  810. 22200 /* This file contains the procedures that manipulate file descriptors.
  811. 22201  *
  812. 22202  * The entry points into this file are
  813. 22203  *   get_fd:    look for free file descriptor and free filp slots
  814. 22204  *   get_filp:  look up the filp entry for a given file descriptor
  815. 22205  *   find_filp: find a filp slot that points to a given inode
  816. 22206  */
  817. 22207
  818. 22208 #include "fs.h"
  819. 22209 #include "file.h"
  820. 22210 #include "fproc.h"
  821. 22211 #include "inode.h"
  822. 22212
  823. 22213 /*===========================================================================*
  824. 22214  *                              get_fd                                       *
  825. 22215  *===========================================================================*/
  826. 22216 PUBLIC int get_fd(start, bits, k, fpt)
  827. 22217 int start;                      /* start of search (used for F_DUPFD) */
  828. 22218 mode_t bits;                    /* mode of the file to be created (RWX bits) */
  829. 22219 int *k;                         /* place to return file descriptor */
  830. 22220 struct filp **fpt;              /* place to return filp slot */
  831. 22221 {
  832. 22222 /* Look for a free file descriptor and a free filp slot.  Fill in the mode word
  833. 22223  * in the latter, but don't claim either one yet, since the open() or creat()
  834. 22224  * may yet fail.
  835. 22225  */
  836. 22226
  837. 22227   register struct filp *f;
  838. 22228   register int i;
  839. 22229
  840. 22230   *k = -1;                      /* we need a way to tell if file desc found */
  841. 22231
  842. 22232   /* Search the fproc fp_filp table for a free file descriptor. */
  843. 22233   for (i = start; i < OPEN_MAX; i++) {
  844. 22234         if (fp->fp_filp[i] == NIL_FILP) {
  845. 22235                 /* A file descriptor has been located. */
  846. 22236                 *k = i;
  847. 22237                 break;
  848. 22238         }
  849. 22239   }
  850. 22240
  851. 22241   /* Check to see if a file descriptor has been found. */
  852. 22242   if (*k < 0) return(EMFILE);   /* this is why we initialized k to -1 */
  853. 22243
  854. 22244   /* Now that a file descriptor has been found, look for a free filp slot. */
  855. 22245   for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
  856. 22246         if (f->filp_count == 0) {
  857. 22247                 f->filp_mode = bits;
  858. 22248                 f->filp_pos = 0L;
  859. 22249                 f->filp_flags = 0;
  860. 22250                 *fpt = f;
  861. 22251                 return(OK);
  862. 22252         }
  863. 22253   }
  864. 22254
  865. 22255   /* If control passes here, the filp table must be full.  Report that back. */
  866. 22256   return(ENFILE);
  867. 22257 }
  868. 22260 /*===========================================================================*
  869. 22261  *                              get_filp                                     *
  870. 22262  *===========================================================================*/
  871. 22263 PUBLIC struct filp *get_filp(fild)
  872. 22264 int fild;                       /* file descriptor */
  873. 22265 {
  874. 22266 /* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
  875. 22267
  876. 22268   err_code = EBADF;
  877. 22269   if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP);
  878. 22270   return(fp->fp_filp[fild]);    /* may also be NIL_FILP */
  879. 22271 }
  880. 22274 /*===========================================================================*
  881. 22275  *                              find_filp                                    *
  882. 22276  *===========================================================================*/
  883. 22277 PUBLIC struct filp *find_filp(rip, bits)
  884. 22278 register struct inode *rip;     /* inode referred to by the filp to be found */
  885. 22279 Mode_t bits;                    /* mode of the filp to be found (RWX bits) */
  886. 22280 {
  887. 22281 /* Find a filp slot that refers to the inode 'rip' in a way as described
  888. 22282  * by the mode bit 'bits'. Used for determining whether somebody is still
  889. 22283  * interested in either end of a pipe.  Also used when opening a FIFO to
  890. 22284  * find partners to share a filp field with (to shared the file position).
  891. 22285  * Like 'get_fd' it performs its job by linear search through the filp table.
  892. 22286  */
  893. 22287
  894. 22288   register struct filp *f;
  895. 22289
  896. 22290   for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
  897. 22291         if (f->filp_count != 0 && f->filp_ino == rip && (f->filp_mode & bits)){
  898. 22292                 return(f);
  899. 22293         }
  900. 22294   }
  901. 22295
  902. 22296   /* If control passes here, the filp wasn't there.  Report that back. */
  903. 22297   return(NIL_FILP);
  904. 22298 }
  905. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  906. src/fs/lock.c    
  907. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  908. 22300 /* This file handles advisory file locking as required by POSIX.
  909. 22301  *
  910. 22302  * The entry points into this file are
  911. 22303  *   lock_op:   perform locking operations for FCNTL system call
  912. 22304  *   lock_revive: revive processes when a lock is released
  913. 22305  */
  914. 22306
  915. 22307 #include "fs.h"
  916. 22308 #include <fcntl.h>
  917. 22309 #include <unistd.h>     /* cc runs out of memory with unistd.h :-( */
  918. 22310 #include "file.h"
  919. 22311 #include "fproc.h"
  920. 22312 #include "inode.h"
  921. 22313 #include "lock.h"
  922. 22314 #include "param.h"
  923. 22315
  924. 22316 /*===========================================================================*
  925. 22317  *                              lock_op                                      *
  926. 22318  *===========================================================================*/
  927. 22319 PUBLIC int lock_op(f, req)
  928. 22320 struct filp *f;
  929. 22321 int req;                        /* either F_SETLK or F_SETLKW */
  930. 22322 {
  931. 22323 /* Perform the advisory locking required by POSIX. */
  932. 22324
  933. 22325   int r, ltype, i, conflict = 0, unlocking = 0;
  934. 22326   mode_t mo;
  935. 22327   off_t first, last;
  936. 22328   struct flock flock;
  937. 22329   vir_bytes user_flock;
  938. 22330   struct file_lock *flp, *flp2, *empty;
  939. 22331
  940. 22332   /* Fetch the flock structure from user space. */
  941. 22333   user_flock = (vir_bytes) name1;
  942. 22334   r = sys_copy(who, D, (phys_bytes) user_flock,
  943. 22335         FS_PROC_NR, D, (phys_bytes) &flock, (phys_bytes) sizeof(flock));
  944. 22336   if (r != OK) return(EINVAL);
  945. 22337
  946. 22338   /* Make some error checks. */
  947. 22339   ltype = flock.l_type;
  948. 22340   mo = f->filp_mode;
  949. 22341   if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
  950. 22342   if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
  951. 22343   if ( (f->filp_ino->i_mode & I_TYPE) != I_REGULAR) return(EINVAL);
  952. 22344   if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
  953. 22345   if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
  954. 22346
  955. 22347   /* Compute the first and last bytes in the lock region. */
  956. 22348   switch (flock.l_whence) {
  957. 22349         case SEEK_SET:  first = 0; break;
  958. 22350         case SEEK_CUR:  first = f->filp_pos; break;
  959. 22351         case SEEK_END:  first = f->filp_ino->i_size; break;
  960. 22352         default:        return(EINVAL);
  961. 22353   }
  962. 22354   /* Check for overflow. */
  963. 22355   if (((long)flock.l_start > 0) && ((first + flock.l_start) < first))
  964. 22356         return(EINVAL);
  965. 22357   if (((long)flock.l_start < 0) && ((first + flock.l_start) > first))
  966. 22358         return(EINVAL);
  967. 22359   first = first + flock.l_start;
  968. 22360   last = first + flock.l_len - 1;
  969. 22361   if (flock.l_len == 0) last = MAX_FILE_POS;
  970. 22362   if (last < first) return(EINVAL);
  971. 22363
  972. 22364   /* Check if this region conflicts with any existing lock. */
  973. 22365   empty = (struct file_lock *) 0;
  974. 22366   for (flp = &file_lock[0]; flp < & file_lock[NR_LOCKS]; flp++) {
  975. 22367         if (flp->lock_type == 0) {
  976. 22368                 if (empty == (struct file_lock *) 0) empty = flp;
  977. 22369                 continue;       /* 0 means unused slot */
  978. 22370         }
  979. 22371         if (flp->lock_inode != f->filp_ino) continue;   /* different file */
  980. 22372         if (last < flp->lock_first) continue;   /* new one is in front */
  981. 22373         if (first > flp->lock_last) continue;   /* new one is afterwards */
  982. 22374         if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
  983. 22375         if (ltype != F_UNLCK && flp->lock_pid == fp->fp_pid) continue;
  984. 22376   
  985. 22377         /* There might be a conflict.  Process it. */
  986. 22378         conflict = 1;
  987. 22379         if (req == F_GETLK) break;
  988. 22380
  989. 22381         /* If we are trying to set a lock, it just failed. */
  990. 22382         if (ltype == F_RDLCK || ltype == F_WRLCK) {
  991. 22383                 if (req == F_SETLK) {
  992. 22384                         /* For F_SETLK, just report back failure. */
  993. 22385                         return(EAGAIN);
  994. 22386                 } else {
  995. 22387                         /* For F_SETLKW, suspend the process. */
  996. 22388                         suspend(XLOCK);
  997. 22389                         return(0);
  998. 22390                 }
  999. 22391         }
  1000. 22392
  1001. 22393         /* We are clearing a lock and we found something that overlaps. */
  1002. 22394         unlocking = 1;
  1003. 22395         if (first <= flp->lock_first && last >= flp->lock_last) {
  1004. 22396                 flp->lock_type = 0;     /* mark slot as unused */
  1005. 22397                 nr_locks--;             /* number of locks is now 1 less */
  1006. 22398                 continue;
  1007. 22399         }
  1008. 22400
  1009. 22401         /* Part of a locked region has been unlocked. */
  1010. 22402         if (first <= flp->lock_first) {
  1011. 22403                 flp->lock_first = last + 1;
  1012. 22404                 continue;
  1013. 22405         }
  1014. 22406
  1015. 22407         if (last >= flp->lock_last) {
  1016. 22408                 flp->lock_last = first - 1;
  1017. 22409                 continue;
  1018. 22410         }
  1019. 22411         
  1020. 22412         /* Bad luck. A lock has been split in two by unlocking the middle. */
  1021. 22413         if (nr_locks == NR_LOCKS) return(ENOLCK);
  1022. 22414         for (i = 0; i < NR_LOCKS; i++)
  1023. 22415                 if (file_lock[i].lock_type == 0) break;
  1024. 22416         flp2 = &file_lock[i];
  1025. 22417         flp2->lock_type = flp->lock_type;
  1026. 22418         flp2->lock_pid = flp->lock_pid;
  1027. 22419         flp2->lock_inode = flp->lock_inode;
  1028. 22420         flp2->lock_first = last + 1;
  1029. 22421         flp2->lock_last = flp->lock_last;
  1030. 22422         flp->lock_last = first - 1;
  1031. 22423         nr_locks++;
  1032. 22424   }
  1033. 22425   if (unlocking) lock_revive();
  1034. 22426
  1035. 22427   if (req == F_GETLK) {
  1036. 22428         if (conflict) {
  1037. 22429                 /* GETLK and conflict. Report on the conflicting lock. */
  1038. 22430                 flock.l_type = flp->lock_type;
  1039. 22431                 flock.l_whence = SEEK_SET;
  1040. 22432                 flock.l_start = flp->lock_first;
  1041. 22433                 flock.l_len = flp->lock_last - flp->lock_first + 1;
  1042. 22434                 flock.l_pid = flp->lock_pid;
  1043. 22435
  1044. 22436         } else {
  1045. 22437                 /* It is GETLK and there is no conflict. */
  1046. 22438                 flock.l_type = F_UNLCK;
  1047. 22439         }
  1048. 22440
  1049. 22441         /* Copy the flock structure back to the caller. */
  1050. 22442         r = sys_copy(FS_PROC_NR, D, (phys_bytes) &flock,
  1051. 22443                 who, D, (phys_bytes) user_flock, (phys_bytes) sizeof(flock));
  1052. 22444         return(r);
  1053. 22445   }
  1054. 22446
  1055. 22447   if (ltype == F_UNLCK) return(OK);     /* unlocked a region with no locks */
  1056. 22448
  1057. 22449   /* There is no conflict.  If space exists, store new lock in the table. */
  1058. 22450   if (empty == (struct file_lock *) 0) return(ENOLCK);  /* table full */
  1059. 22451   empty->lock_type = ltype;
  1060. 22452   empty->lock_pid = fp->fp_pid;
  1061. 22453   empty->lock_inode = f->filp_ino;
  1062. 22454   empty->lock_first = first;
  1063. 22455   empty->lock_last = last;
  1064. 22456   nr_locks++;
  1065. 22457   return(OK);
  1066. 22458 }
  1067. 22460 /*===========================================================================*
  1068. 22461  *                              lock_revive                                  *
  1069. 22462  *===========================================================================*/
  1070. 22463 PUBLIC void lock_revive()
  1071. 22464 {
  1072. 22465 /* Go find all the processes that are waiting for any kind of lock and 
  1073. 22466  * revive them all.  The ones that are still blocked will block again when 
  1074. 22467  * they run.  The others will complete.  This strategy is a space-time 
  1075. 22468  * tradeoff.  Figuring out exactly which ones to unblock now would take 
  1076. 22469  * extra code, and the only thing it would win would be some performance in 
  1077. 22470  * extremely rare circumstances (namely, that somebody actually used 
  1078. 22471  * locking).
  1079. 22472  */
  1080. 22473
  1081. 22474   int task;
  1082. 22475   struct fproc *fptr;
  1083. 22476
  1084. 22477   for (fptr = &fproc[INIT_PROC_NR + 1]; fptr < &fproc[NR_PROCS]; fptr++){
  1085. 22478         task = -fptr->fp_task;
  1086. 22479         if (fptr->fp_suspended == SUSPENDED && task == XLOCK) {
  1087. 22480                 revive( (int) (fptr - fproc), 0);
  1088. 22481         }
  1089. 22482   }
  1090. 22483 }
  1091. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1092. src/fs/main.c    
  1093. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1094. 22500 /* This file contains the main program of the File System.  It consists of
  1095. 22501  * a loop that gets messages requesting work, carries out the work, and sends
  1096. 22502  * replies.
  1097. 22503  *
  1098. 22504  * The entry points into this file are
  1099. 22505  *   main:      main program of the File System
  1100. 22506  *   reply:     send a reply to a process after the requested work is done
  1101. 22507  */
  1102. 22508
  1103. 22509 struct super_block;             /* proto.h needs to know this */
  1104. 22510
  1105. 22511 #include "fs.h"
  1106. 22512 #include <fcntl.h>
  1107. 22513 #include <string.h>
  1108. 22514 #include <sys/ioctl.h>
  1109. 22515 #include <minix/callnr.h>
  1110. 22516 #include <minix/com.h>
  1111. 22517 #include <minix/boot.h>
  1112. 22518 #include "buf.h"
  1113. 22519 #include "dev.h"
  1114. 22520 #include "file.h"
  1115. 22521 #include "fproc.h"
  1116. 22522 #include "inode.h"
  1117. 22523 #include "param.h"
  1118. 22524 #include "super.h"
  1119. 22525
  1120. 22526 FORWARD _PROTOTYPE( void buf_pool, (void)                               );
  1121. 22527 FORWARD _PROTOTYPE( void fs_init, (void)                                );
  1122. 22528 FORWARD _PROTOTYPE( void get_boot_parameters, (void)                    );
  1123. 22529 FORWARD _PROTOTYPE( void get_work, (void)                               );
  1124. 22530 FORWARD _PROTOTYPE( void load_ram, (void)                               );
  1125. 22531 FORWARD _PROTOTYPE( void load_super, (Dev_t super_dev)                  );
  1126. 22532
  1127. 22533
  1128. 22534 /*===========================================================================*
  1129. 22535  *                              main                                         *
  1130. 22536  *===========================================================================*/
  1131. 22537 PUBLIC void main()
  1132. 22538 {
  1133. 22539 /* This is the main program of the file system.  The main loop consists of
  1134. 22540  * three major activities: getting new work, processing the work, and sending
  1135. 22541  * the reply.  This loop never terminates as long as the file system runs.
  1136. 22542  */
  1137. 22543   int error;
  1138. 22544
  1139. 22545   fs_init();
  1140. 22546
  1141. 22547   /* This is the main loop that gets work, processes it, and sends replies. */
  1142. 22548   while (TRUE) {
  1143. 22549         get_work();             /* sets who and fs_call */
  1144. 22550
  1145. 22551         fp = &fproc[who];       /* pointer to proc table struct */
  1146. 22552         super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
  1147. 22553         dont_reply = FALSE;     /* in other words, do reply is default */
  1148. 22554
  1149. 22555         /* Call the internal function that does the work. */
  1150. 22556         if (fs_call < 0 || fs_call >= NCALLS)
  1151. 22557                 error = EBADCALL;
  1152. 22558         else
  1153. 22559                 error = (*call_vector[fs_call])();
  1154. 22560
  1155. 22561         /* Copy the results back to the user and send reply. */
  1156. 22562         if (dont_reply) continue;
  1157. 22563         reply(who, error);
  1158. 22564         if (rdahed_inode != NIL_INODE) read_ahead(); /* do block read ahead */
  1159. 22565   }
  1160. 22566 }
  1161. 22569 /*===========================================================================*
  1162. 22570  *                              get_work                                     *
  1163. 22571  *===========================================================================*/
  1164. 22572 PRIVATE void get_work()
  1165. 22573 {  
  1166. 22574   /* Normally wait for new input.  However, if 'reviving' is
  1167. 22575    * nonzero, a suspended process must be awakened.
  1168. 22576    */
  1169. 22577
  1170. 22578   register struct fproc *rp;
  1171. 22579
  1172. 22580   if (reviving != 0) {
  1173. 22581         /* Revive a suspended process. */
  1174. 22582         for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) 
  1175. 22583                 if (rp->fp_revived == REVIVING) {
  1176. 22584                         who = (int)(rp - fproc);
  1177. 22585                         fs_call = rp->fp_fd & BYTE;
  1178. 22586                         fd = (rp->fp_fd >>8) & BYTE;
  1179. 22587                         buffer = rp->fp_buffer;
  1180. 22588                         nbytes = rp->fp_nbytes;
  1181. 22589                         rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
  1182. 22590                         rp->fp_revived = NOT_REVIVING;
  1183. 22591                         reviving--;
  1184. 22592                         return;
  1185. 22593                 }
  1186. 22594         panic("get_work couldn't revive anyone", NO_NUM);
  1187. 22595   }
  1188. 22596
  1189. 22597   /* Normal case.  No one to revive. */
  1190. 22598   if (receive(ANY, &m) != OK) panic("fs receive error", NO_NUM);
  1191. 22599
  1192. 22600   who = m.m_source;
  1193. 22601   fs_call = m.m_type;
  1194. 22602 }
  1195. 22605 /*===========================================================================*
  1196. 22606  *                              reply                                        *
  1197. 22607  *===========================================================================*/
  1198. 22608 PUBLIC void reply(whom, result)
  1199. 22609 int whom;                       /* process to reply to */
  1200. 22610 int result;                     /* result of the call (usually OK or error #) */
  1201. 22611 {
  1202. 22612 /* Send a reply to a user process. It may fail (if the process has just
  1203. 22613  * been killed by a signal), so don't check the return code.  If the send
  1204. 22614  * fails, just ignore it.
  1205. 22615  */
  1206. 22616
  1207. 22617   reply_type = result;
  1208. 22618   send(whom, &m1);
  1209. 22619 }
  1210. 22622 /*===========================================================================*
  1211. 22623  *                              fs_init                                      *
  1212. 22624  *===========================================================================*/
  1213. 22625 PRIVATE void fs_init()
  1214. 22626 {
  1215. 22627 /* Initialize global variables, tables, etc. */
  1216. 22628
  1217. 22629   register struct inode *rip;
  1218. 22630   int i;
  1219. 22631   message mess;
  1220. 22632   
  1221. 22633   /* The following initializations are needed to let dev_opcl succeed .*/
  1222. 22634   fp = (struct fproc *) NULL;
  1223. 22635   who = FS_PROC_NR;
  1224. 22636
  1225. 22637   buf_pool();                   /* initialize buffer pool */
  1226. 22638   get_boot_parameters();        /* get the parameters from the menu */
  1227. 22639   load_ram();                   /* init RAM disk, load if it is root */
  1228. 22640   load_super(ROOT_DEV);         /* load super block for root device */
  1229. 22641
  1230. 22642   /* Initialize the 'fproc' fields for process 0 .. INIT. */
  1231. 22643   for (i = 0; i <= LOW_USER; i+= 1) {
  1232. 22644         if (i == FS_PROC_NR) continue;  /* do not initialize FS */
  1233. 22645         fp = &fproc[i];
  1234. 22646         rip = get_inode(ROOT_DEV, ROOT_INODE);
  1235. 22647         fp->fp_rootdir = rip;
  1236. 22648         dup_inode(rip);
  1237. 22649         fp->fp_workdir = rip;
  1238. 22650         fp->fp_realuid = (uid_t) SYS_UID;
  1239. 22651         fp->fp_effuid = (uid_t) SYS_UID;
  1240. 22652         fp->fp_realgid = (gid_t) SYS_GID;
  1241. 22653         fp->fp_effgid = (gid_t) SYS_GID;
  1242. 22654         fp->fp_umask = ~0;
  1243. 22655   }
  1244. 22656
  1245. 22657   /* Certain relations must hold for the file system to work at all. */
  1246. 22658   if (SUPER_SIZE > BLOCK_SIZE) panic("SUPER_SIZE > BLOCK_SIZE", NO_NUM);
  1247. 22659   if (BLOCK_SIZE % V2_INODE_SIZE != 0)  /* this checks V1_INODE_SIZE too */
  1248. 22660         panic("BLOCK_SIZE % V2_INODE_SIZE != 0", NO_NUM);
  1249. 22661   if (OPEN_MAX > 127) panic("OPEN_MAX > 127", NO_NUM);
  1250. 22662   if (NR_BUFS < 6) panic("NR_BUFS < 6", NO_NUM);
  1251. 22663   if (V1_INODE_SIZE != 32) panic("V1 inode size != 32", NO_NUM);
  1252. 22664   if (V2_INODE_SIZE != 64) panic("V2 inode size != 64", NO_NUM);
  1253. 22665   if (OPEN_MAX > 8 * sizeof(long)) panic("Too few bits in fp_cloexec", NO_NUM);
  1254. 22666
  1255. 22667   /* Tell the memory task where my process table is for the sake of ps(1). */
  1256. 22668   mess.m_type = DEV_IOCTL;
  1257. 22669   mess.PROC_NR = FS_PROC_NR;
  1258. 22670   mess.REQUEST = MIOCSPSINFO;
  1259. 22671   mess.ADDRESS = (void *) fproc;
  1260. 22672   (void) sendrec(MEM, &mess);
  1261. 22673 }
  1262. 22676 /*===========================================================================*
  1263. 22677  *                              buf_pool                                     *
  1264. 22678  *===========================================================================*/
  1265. 22679 PRIVATE void buf_pool()
  1266. 22680 {
  1267. 22681 /* Initialize the buffer pool. */
  1268. 22682
  1269. 22683   register struct buf *bp;
  1270. 22684
  1271. 22685   bufs_in_use = 0;
  1272. 22686   front = &buf[0];
  1273. 22687   rear = &buf[NR_BUFS - 1];
  1274. 22688
  1275. 22689   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
  1276. 22690         bp->b_blocknr = NO_BLOCK;
  1277. 22691         bp->b_dev = NO_DEV;
  1278. 22692         bp->b_next = bp + 1;
  1279. 22693         bp->b_prev = bp - 1;
  1280. 22694   }
  1281. 22695   buf[0].b_prev = NIL_BUF;
  1282. 22696   buf[NR_BUFS - 1].b_next = NIL_BUF;
  1283. 22697
  1284. 22698   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
  1285. 22699   buf_hash[0] = front;
  1286. 22700 }
  1287. 22703 /*===========================================================================*
  1288. 22704  *                              get_boot_parameters                          *
  1289. 22705  *===========================================================================*/
  1290. 22706 PUBLIC struct bparam_s boot_parameters;
  1291. 22707
  1292. 22708 PRIVATE void get_boot_parameters()
  1293. 22709 {
  1294. 22710 /* Ask kernel for boot parameters. */
  1295. 22711
  1296. 22712   m1.m_type = SYS_GBOOT;
  1297. 22713   m1.PROC1 = FS_PROC_NR;
  1298. 22714   m1.MEM_PTR = (char *) &boot_parameters;
  1299. 22715   (void) sendrec(SYSTASK, &m1);
  1300. 22716 }
  1301. 22719 /*===========================================================================*
  1302. 22720  *                              load_ram                                     *
  1303. 22721  *===========================================================================*/
  1304. 22722 PRIVATE void load_ram()
  1305. 22723 {
  1306. 22724 /* If the root device is the RAM disk, copy the entire root image device
  1307. 22725  * block-by-block to a RAM disk with the same size as the image.
  1308. 22726  * Otherwise, just allocate a RAM disk with size given in the boot parameters.
  1309. 22727  */
  1310. 22728
  1311. 22729   register struct buf *bp, *bp1;
  1312. 22730   long k_loaded, lcount;
  1313. 22731   u32_t ram_size, fsmax;
  1314. 22732   zone_t zones;
  1315. 22733   struct super_block *sp, *dsp;
  1316. 22734   block_t b;
  1317. 22735   int major, task;
  1318. 22736   message dev_mess;
  1319. 22737
  1320. 22738   ram_size = boot_parameters.bp_ramsize;
  1321. 22739
  1322. 22740   /* Open the root device. */
  1323. 22741   major = (ROOT_DEV >> MAJOR) & BYTE;   /* major device nr */
  1324. 22742   task = dmap[major].dmap_task;         /* device task nr */
  1325. 22743   dev_mess.m_type = DEV_OPEN;           /* distinguish from close */
  1326. 22744   dev_mess.DEVICE = ROOT_DEV;
  1327. 22745   dev_mess.COUNT = R_BIT|W_BIT;
  1328. 22746   (*dmap[major].dmap_open)(task, &dev_mess);
  1329. 22747   if (dev_mess.REP_STATUS != OK) panic("Cannot open root device",NO_NUM);
  1330. 22748
  1331. 22749   /* If the root device is the ram disk then fill it from the image device. */
  1332. 22750   if (ROOT_DEV == DEV_RAM) {
  1333. 22751         major = (IMAGE_DEV >> MAJOR) & BYTE;    /* major device nr */
  1334. 22752         task = dmap[major].dmap_task;           /* device task nr */
  1335. 22753         dev_mess.m_type = DEV_OPEN;             /* distinguish from close */
  1336. 22754         dev_mess.DEVICE = IMAGE_DEV;
  1337. 22755         dev_mess.COUNT = R_BIT;
  1338. 22756         (*dmap[major].dmap_open)(task, &dev_mess);
  1339. 22757         if (dev_mess.REP_STATUS != OK) panic("Cannot open root device", NO_NUM);
  1340. 22758
  1341. 22759         /* Get size of RAM disk by reading root file system's super block. */
  1342. 22760         sp = &super_block[0];
  1343. 22761         sp->s_dev = IMAGE_DEV;
  1344. 22762         if (read_super(sp) != OK) panic("Bad root file system", NO_NUM);
  1345. 22763
  1346. 22764         lcount = sp->s_zones << sp->s_log_zone_size;    /* # blks on root dev*/
  1347. 22765
  1348. 22766         /* Stretch the RAM disk file system to the boot parameters size, but
  1349. 22767          * no further than the last zone bit map block allows.
  1350. 22768          */
  1351. 22769         if (ram_size < lcount) ram_size = lcount;
  1352. 22770         fsmax = (u32_t) sp->s_zmap_blocks * CHAR_BIT * BLOCK_SIZE;
  1353. 22771         fsmax = (fsmax + (sp->s_firstdatazone-1)) << sp->s_log_zone_size;
  1354. 22772         if (ram_size > fsmax) ram_size = fsmax;
  1355. 22773   }
  1356. 22774
  1357. 22775   /* Tell RAM driver how big the RAM disk must be. */
  1358. 22776   m1.m_type = DEV_IOCTL;
  1359. 22777   m1.PROC_NR = FS_PROC_NR;
  1360. 22778   m1.REQUEST = MIOCRAMSIZE;
  1361. 22779   m1.POSITION = ram_size;
  1362. 22780   if (sendrec(MEM, &m1) != OK || m1.REP_STATUS != OK)
  1363. 22781         panic("Can't set RAM disk size", NO_NUM);
  1364. 22782
  1365. 22783   /* Tell MM the RAM disk size, and wait for it to come "on-line". */
  1366. 22784   m1.m1_i1 = ((long) ram_size * BLOCK_SIZE) >> CLICK_SHIFT;
  1367. 22785   if (sendrec(MM_PROC_NR, &m1) != OK)
  1368. 22786         panic("FS can't sync up with MM", NO_NUM);
  1369. 22787
  1370. 22788   /* If the root device is not the RAM disk, it doesn't need loading. */
  1371. 22789   if (ROOT_DEV != DEV_RAM) return;
  1372. 22790
  1373. 22791   /* Copy the blocks one at a time from the image to the RAM disk. */
  1374. 22792   printf("Loading RAM disk.33[23CLoaded:    0K ");
  1375. 22793
  1376. 22794   inode[0].i_mode = I_BLOCK_SPECIAL;    /* temp inode for rahead() */
  1377. 22795   inode[0].i_size = LONG_MAX;
  1378. 22796   inode[0].i_dev = IMAGE_DEV;
  1379. 22797   inode[0].i_zone[0] = IMAGE_DEV;
  1380. 22798
  1381. 22799   for (b = 0; b < (block_t) lcount; b++) {
  1382. 22800         bp = rahead(&inode[0], b, (off_t)BLOCK_SIZE * b, BLOCK_SIZE);
  1383. 22801         bp1 = get_block(ROOT_DEV, b, NO_READ);
  1384. 22802         memcpy(bp1->b_data, bp->b_data, (size_t) BLOCK_SIZE);
  1385. 22803         bp1->b_dirt = DIRTY;
  1386. 22804         put_block(bp, FULL_DATA_BLOCK);
  1387. 22805         put_block(bp1, FULL_DATA_BLOCK);
  1388. 22806         k_loaded = ( (long) b * BLOCK_SIZE)/1024L;      /* K loaded so far */
  1389. 22807         if (k_loaded % 5 == 0) printf("bbbbbbb%5ldK ", k_loaded);
  1390. 22808   }
  1391. 22809
  1392. 22810   printf("rRAM disk loaded.33[Knn");
  1393. 22811
  1394. 22812   /* Close and invalidate image device. */
  1395. 22813   dev_mess.m_type = DEV_CLOSE;
  1396. 22814   dev_mess.DEVICE = IMAGE_DEV;
  1397. 22815   (*dmap[major].dmap_close)(task, &dev_mess);
  1398. 22816   invalidate(IMAGE_DEV);
  1399. 22817
  1400. 22818   /* Resize the RAM disk root file system. */
  1401. 22819   bp = get_block(ROOT_DEV, SUPER_BLOCK, NORMAL);
  1402. 22820   dsp = (struct super_block *) bp->b_data;
  1403. 22821   zones = ram_size >> sp->s_log_zone_size;
  1404. 22822   dsp->s_nzones = conv2(sp->s_native, (u16_t) zones);
  1405. 22823   dsp->s_zones = conv4(sp->s_native, zones);
  1406. 22824   bp->b_dirt = DIRTY;
  1407. 22825   put_block(bp, ZUPER_BLOCK);
  1408. 22826 }
  1409. 22829 /*===========================================================================*
  1410. 22830  *                              load_super                                   *
  1411. 22831  *===========================================================================*/
  1412. 22832 PRIVATE void load_super(super_dev)
  1413. 22833 dev_t super_dev;                        /* place to get superblock from */
  1414. 22834 {
  1415. 22835   int bad;
  1416. 22836   register struct super_block *sp;
  1417. 22837   register struct inode *rip;
  1418. 22838
  1419. 22839   /* Initialize the super_block table. */
  1420. 22840   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
  1421. 22841         sp->s_dev = NO_DEV;
  1422. 22842
  1423. 22843   /* Read in super_block for the root file system. */
  1424. 22844   sp = &super_block[0];
  1425. 22845   sp->s_dev = super_dev;
  1426. 22846
  1427. 22847   /* Check super_block for consistency (is it the right diskette?). */
  1428. 22848   bad = (read_super(sp) != OK);
  1429. 22849   if (!bad) {
  1430. 22850         rip = get_inode(super_dev, ROOT_INODE); /* inode for root dir */
  1431. 22851         if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++;
  1432. 22852   }
  1433. 22853   if (bad)panic("Invalid root file system.  Possibly wrong diskette.",NO_NUM);
  1434. 22854
  1435. 22855   sp->s_imount = rip;
  1436. 22856   dup_inode(rip);
  1437. 22857   sp->s_isup = rip;
  1438. 22858   sp->s_rd_only = 0;
  1439. 22859   return;
  1440. 22860 }
  1441. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1442. src/fs/open.c    
  1443. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1444. 22900 /* This file contains the procedures for creating, opening, closing, and
  1445. 22901  * seeking on files.
  1446. 22902  *
  1447. 22903  * The entry points into this file are
  1448. 22904  *   do_creat:  perform the CREAT system call
  1449. 22905  *   do_open:   perform the OPEN system call
  1450. 22906  *   do_mknod:  perform the MKNOD system call
  1451. 22907  *   do_mkdir:  perform the MKDIR system call
  1452. 22908  *   do_close:  perform the CLOSE system call
  1453. 22909  *   do_lseek:  perform the LSEEK system call
  1454. 22910  */
  1455. 22911
  1456. 22912 #include "fs.h"
  1457. 22913 #include <sys/stat.h>
  1458. 22914 #include <fcntl.h>
  1459. 22915 #include <minix/callnr.h>
  1460. 22916 #include <minix/com.h>
  1461. 22917 #include "buf.h"
  1462. 22918 #include "dev.h"
  1463. 22919 #include "file.h"
  1464. 22920 #include "fproc.h"
  1465. 22921 #include "inode.h"
  1466. 22922 #include "lock.h"
  1467. 22923 #include "param.h"
  1468. 22924
  1469. 22925 PRIVATE message dev_mess;
  1470. 22926 PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
  1471. 22927
  1472. 22928 FORWARD _PROTOTYPE( int common_open, (int oflags, Mode_t omode)         );
  1473. 22929 FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,Mode_t bits,int oflags));
  1474. 22930 FORWARD _PROTOTYPE( struct inode *new_node, (char *path, Mode_t bits,
  1475. 22931                                                         zone_t z0)      );
  1476. 22932
  1477. 22933
  1478. 22934 /*===========================================================================*
  1479. 22935  *                              do_creat                                     *
  1480. 22936  *===========================================================================*/
  1481. 22937 PUBLIC int do_creat()
  1482. 22938 {
  1483. 22939 /* Perform the creat(name, mode) system call. */
  1484. 22940   int r;
  1485. 22941
  1486. 22942   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  1487. 22943   r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) mode);
  1488. 22944   return(r);
  1489. 22945 }
  1490. 22948 /*===========================================================================*
  1491. 22949  *                              do_open                                      *
  1492. 22950  *===========================================================================*/
  1493. 22951 PUBLIC int do_open()
  1494. 22952 {
  1495. 22953 /* Perform the open(name, flags,...) system call. */
  1496. 22954
  1497. 22955   int create_mode = 0;          /* is really mode_t but this gives problems */
  1498. 22956   int r;
  1499. 22957
  1500. 22958   /* If O_CREAT is set, open has three parameters, otherwise two. */
  1501. 22959   if (mode & O_CREAT) {
  1502. 22960         create_mode = c_mode;   
  1503. 22961         r = fetch_name(c_name, name1_length, M1);
  1504. 22962   } else {
  1505. 22963         r = fetch_name(name, name_length, M3);
  1506. 22964   }
  1507. 22965
  1508. 22966   if (r != OK) return(err_code); /* name was bad */
  1509. 22967   r = common_open(mode, create_mode);
  1510. 22968   return(r);
  1511. 22969 }
  1512. 22972 /*===========================================================================*
  1513. 22973  *                              common_open                                  *
  1514. 22974  *===========================================================================*/
  1515. 22975 PRIVATE int common_open(oflags, omode)
  1516. 22976 register int oflags;
  1517. 22977 mode_t omode;
  1518. 22978 {
  1519. 22979 /* Common code from do_creat and do_open. */
  1520. 22980
  1521. 22981   register struct inode *rip;
  1522. 22982   int r, b, major, task, exist = TRUE;
  1523. 22983   dev_t dev;
  1524. 22984   mode_t bits;
  1525. 22985   off_t pos;
  1526. 22986   struct filp *fil_ptr, *filp2;
  1527. 22987
  1528. 22988   /* Remap the bottom two bits of oflags. */
  1529. 22989   bits = (mode_t) mode_map[oflags & O_ACCMODE];
  1530. 22990
  1531. 22991   /* See if file descriptor and filp slots are available. */
  1532. 22992   if ( (r = get_fd(0, bits, &fd, &fil_ptr)) != OK) return(r);
  1533. 22993
  1534. 22994   /* If O_CREATE is set, try to make the file. */ 
  1535. 22995   if (oflags & O_CREAT) {
  1536. 22996         /* Create a new inode by calling new_node(). */
  1537. 22997         omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
  1538. 22998         rip = new_node(user_path, omode, NO_ZONE);
  1539. 22999         r = err_code;
  1540. 23000         if (r == OK) exist = FALSE;      /* we just created the file */
  1541. 23001         else if (r != EEXIST) return(r); /* other error */
  1542. 23002         else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
  1543. 23003                                             flag is set this is an error */
  1544. 23004   } else {
  1545. 23005          /* Scan path name. */
  1546. 23006         if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1547. 23007   }
  1548. 23008
  1549. 23009   /* Claim the file descriptor and filp slot and fill them in. */
  1550. 23010   fp->fp_filp[fd] = fil_ptr;
  1551. 23011   fil_ptr->filp_count = 1;
  1552. 23012   fil_ptr->filp_ino = rip;
  1553. 23013   fil_ptr->filp_flags = oflags;
  1554. 23014
  1555. 23015   /* Only do the normal open code if we didn't just create the file. */
  1556. 23016   if (exist) {
  1557. 23017         /* Check protections. */
  1558. 23018         if ((r = forbidden(rip, bits)) == OK) {
  1559. 23019                 /* Opening reg. files directories and special files differ. */
  1560. 23020                 switch (rip->i_mode & I_TYPE) {
  1561. 23021                    case I_REGULAR: 
  1562. 23022                         /* Truncate regular file if O_TRUNC. */
  1563. 23023                         if (oflags & O_TRUNC) {
  1564. 23024                                 if ((r = forbidden(rip, W_BIT)) !=OK) break;
  1565. 23025                                 truncate(rip);
  1566. 23026                                 wipe_inode(rip);
  1567. 23027                                 /* Send the inode from the inode cache to the
  1568. 23028                                  * block cache, so it gets written on the next
  1569. 23029                                  * cache flush.
  1570. 23030                                  */
  1571. 23031                                 rw_inode(rip, WRITING);
  1572. 23032                         }
  1573. 23033                         break;
  1574. 23034  
  1575. 23035                    case I_DIRECTORY: 
  1576. 23036                         /* Directories may be read but not written. */
  1577. 23037                         r = (bits & W_BIT ? EISDIR : OK);
  1578. 23038                         break;
  1579. 23039
  1580. 23040                    case I_CHAR_SPECIAL:
  1581. 23041                    case I_BLOCK_SPECIAL:
  1582. 23042                         /* Invoke the driver for special processing. */
  1583. 23043                         dev_mess.m_type = DEV_OPEN;
  1584. 23044                         dev = (dev_t) rip->i_zone[0];
  1585. 23045                         dev_mess.DEVICE = dev;
  1586. 23046                         dev_mess.COUNT = bits | (oflags & ~O_ACCMODE);
  1587. 23047                         major = (dev >> MAJOR) & BYTE;  /* major device nr */
  1588. 23048                         if (major <= 0 || major >= max_major) {
  1589. 23049                                 r = ENODEV;
  1590. 23050                                 break;
  1591. 23051                         }
  1592. 23052                         task = dmap[major].dmap_task;   /* device task nr */
  1593. 23053                         (*dmap[major].dmap_open)(task, &dev_mess);
  1594. 23054                         r = dev_mess.REP_STATUS;
  1595. 23055                         break;
  1596. 23056
  1597. 23057                    case I_NAMED_PIPE:
  1598. 23058                         oflags |= O_APPEND;     /* force append mode */
  1599. 23059                         fil_ptr->filp_flags = oflags;
  1600. 23060                         r = pipe_open(rip, bits, oflags);
  1601. 23061                         if (r == OK) {
  1602. 23062                                 /* See if someone else is doing a rd or wt on
  1603. 23063                                  * the FIFO.  If so, use its filp entry so the
  1604. 23064                                  * file position will be automatically shared.
  1605. 23065                                  */
  1606. 23066                                 b = (bits & R_BIT ? R_BIT : W_BIT);
  1607. 23067                                 fil_ptr->filp_count = 0; /* don't find self */
  1608. 23068                                 if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
  1609. 23069                                         /* Co-reader or writer found. Use it.*/
  1610. 23070                                         fp->fp_filp[fd] = filp2;
  1611. 23071                                         filp2->filp_count++;
  1612. 23072                                         filp2->filp_ino = rip;
  1613. 23073                                         filp2->filp_flags = oflags;
  1614. 23074
  1615. 23075                                         /* i_count was incremented incorrectly
  1616. 23076                                          * by eatpath above, not knowing that
  1617. 23077                                          * we were going to use an existing
  1618. 23078                                          * filp entry.  Correct this error.
  1619. 23079                                          */
  1620. 23080                                         rip->i_count--;
  1621. 23081                                 } else {
  1622. 23082                                         /* Nobody else found.  Restore filp. */
  1623. 23083                                         fil_ptr->filp_count = 1;
  1624. 23084                                         if (b == R_BIT)
  1625. 23085                                              pos = rip->i_zone[V2_NR_DZONES+1];
  1626. 23086                                         else
  1627. 23087                                              pos = rip->i_zone[V2_NR_DZONES+2];
  1628. 23088                                         fil_ptr->filp_pos = pos;
  1629. 23089                                 }
  1630. 23090                         }
  1631. 23091                         break;
  1632. 23092                 }
  1633. 23093         }
  1634. 23094   }
  1635. 23095
  1636. 23096   /* If error, release inode. */
  1637. 23097   if (r != OK) {
  1638. 23098         fp->fp_filp[fd] = NIL_FILP;
  1639. 23099         fil_ptr->filp_count= 0;
  1640. 23100         put_inode(rip);
  1641. 23101         return(r);
  1642. 23102   }
  1643. 23103   
  1644. 23104   return(fd);
  1645. 23105 }
  1646. 23108 /*===========================================================================*
  1647. 23109  *                              new_node                                     *
  1648. 23110  *===========================================================================*/
  1649. 23111 PRIVATE struct inode *new_node(path, bits, z0)
  1650. 23112 char *path;                     /* pointer to path name */
  1651. 23113 mode_t bits;                    /* mode of the new inode */
  1652. 23114 zone_t z0;                      /* zone number 0 for new inode */
  1653. 23115 {
  1654. 23116 /* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
  1655. 23117  * In all cases it allocates a new inode, makes a directory entry for it on 
  1656. 23118  * the path 'path', and initializes it.  It returns a pointer to the inode if 
  1657. 23119  * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
  1658. 23120  * to an appropriate value (OK or an error code).
  1659. 23121  */
  1660. 23122
  1661. 23123   register struct inode *rlast_dir_ptr, *rip;
  1662. 23124   register int r;
  1663. 23125   char string[NAME_MAX];
  1664. 23126
  1665. 23127   /* See if the path can be opened down to the last directory. */
  1666. 23128   if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);
  1667. 23129
  1668. 23130   /* The final directory is accessible. Get final component of the path. */
  1669. 23131   rip = advance(rlast_dir_ptr, string);
  1670. 23132   if ( rip == NIL_INODE && err_code == ENOENT) {
  1671. 23133         /* Last path component does not exist.  Make new directory entry. */
  1672. 23134         if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {
  1673. 23135                 /* Can't creat new inode: out of inodes. */
  1674. 23136                 put_inode(rlast_dir_ptr);
  1675. 23137                 return(NIL_INODE);
  1676. 23138         }
  1677. 23139
  1678. 23140         /* Force inode to the disk before making directory entry to make
  1679. 23141          * the system more robust in the face of a crash: an inode with
  1680. 23142          * no directory entry is much better than the opposite.
  1681. 23143          */
  1682. 23144         rip->i_nlinks++;
  1683. 23145         rip->i_zone[0] = z0;            /* major/minor device numbers */
  1684. 23146         rw_inode(rip, WRITING);         /* force inode to disk now */
  1685. 23147
  1686. 23148         /* New inode acquired.  Try to make directory entry. */
  1687. 23149         if ((r = search_dir(rlast_dir_ptr, string, &rip->i_num,ENTER)) != OK) {
  1688. 23150                 put_inode(rlast_dir_ptr);
  1689. 23151                 rip->i_nlinks--;        /* pity, have to free disk inode */
  1690. 23152                 rip->i_dirt = DIRTY;    /* dirty inodes are written out */
  1691. 23153                 put_inode(rip); /* this call frees the inode */
  1692. 23154                 err_code = r;
  1693. 23155                 return(NIL_INODE);
  1694. 23156         }
  1695. 23157
  1696. 23158   } else {
  1697. 23159         /* Either last component exists, or there is some problem. */
  1698. 23160         if (rip != NIL_INODE)
  1699. 23161                 r = EEXIST;
  1700. 23162         else
  1701. 23163                 r = err_code;
  1702. 23164   }
  1703. 23165
  1704. 23166   /* Return the directory inode and exit. */
  1705. 23167   put_inode(rlast_dir_ptr);
  1706. 23168   err_code = r;
  1707. 23169   return(rip);
  1708. 23170 }
  1709. 23173 /*===========================================================================*
  1710. 23174  *                              pipe_open                                    *
  1711. 23175  *===========================================================================*/
  1712. 23176 PRIVATE int pipe_open(rip, bits, oflags)
  1713. 23177 register struct inode *rip;
  1714. 23178 register mode_t bits;
  1715. 23179 register int oflags;
  1716. 23180 {
  1717. 23181 /*  This function is called from common_open. It checks if
  1718. 23182  *  there is at least one reader/writer pair for the pipe, if not
  1719. 23183  *  it suspends the caller, otherwise it revives all other blocked
  1720. 23184  *  processes hanging on the pipe.
  1721. 23185  */
  1722. 23186
  1723. 23187   if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
  1724. 23188         if (oflags & O_NONBLOCK) {
  1725. 23189                 if (bits & W_BIT) return(ENXIO);
  1726. 23190         } else
  1727. 23191                 suspend(XPOPEN);        /* suspend caller */
  1728. 23192   } else if (susp_count > 0) {/* revive blocked processes */
  1729. 23193         release(rip, OPEN, susp_count);
  1730. 23194         release(rip, CREAT, susp_count);
  1731. 23195   }
  1732. 23196   rip->i_pipe = I_PIPE; 
  1733. 23197
  1734. 23198   return(OK);
  1735. 23199 }
  1736. 23202 /*===========================================================================*
  1737. 23203  *                              do_mknod                                     *
  1738. 23204  *===========================================================================*/
  1739. 23205 PUBLIC int do_mknod()
  1740. 23206 {
  1741. 23207 /* Perform the mknod(name, mode, addr) system call. */
  1742. 23208
  1743. 23209   register mode_t bits, mode_bits;
  1744. 23210   struct inode *ip;
  1745. 23211
  1746. 23212   /* Only the super_user may make nodes other than fifos. */
  1747. 23213   mode_bits = (mode_t) m.m1_i2; /* mode of the inode */
  1748. 23214   if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
  1749. 23215   if (fetch_name(m.m1_p1, m.m1_i1, M1) != OK) return(err_code);
  1750. 23216   bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
  1751. 23217   ip = new_node(user_path, bits, (zone_t) m.m1_i3);
  1752. 23218   put_inode(ip);
  1753. 23219   return(err_code);
  1754. 23220 }
  1755. 23223 /*===========================================================================*
  1756. 23224  *                              do_mkdir                                     *
  1757. 23225  *===========================================================================*/
  1758. 23226 PUBLIC int do_mkdir()
  1759. 23227 {
  1760. 23228 /* Perform the mkdir(name, mode) system call. */
  1761. 23229
  1762. 23230   int r1, r2;                   /* status codes */
  1763. 23231   ino_t dot, dotdot;            /* inode numbers for . and .. */
  1764. 23232   mode_t bits;                  /* mode bits for the new inode */
  1765. 23233   char string[NAME_MAX];        /* last component of the new dir's path name */
  1766. 23234   register struct inode *rip, *ldirp;
  1767. 23235
  1768. 23236   /* Check to see if it is possible to make another link in the parent dir. */
  1769. 23237   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  1770. 23238   ldirp = last_dir(user_path, string);  /* pointer to new dir's parent */
  1771. 23239   if (ldirp == NIL_INODE) return(err_code);
  1772. 23240   if ( (ldirp->i_nlinks & BYTE) >= LINK_MAX) {
  1773. 23241         put_inode(ldirp);       /* return parent */
  1774. 23242         return(EMLINK);
  1775. 23243   }
  1776. 23244
  1777. 23245   /* Next make the inode. If that fails, return error code. */
  1778. 23246   bits = I_DIRECTORY | (mode & RWX_MODES & fp->fp_umask);
  1779. 23247   rip = new_node(user_path, bits, (zone_t) 0);
  1780. 23248   if (rip == NIL_INODE || err_code == EEXIST) {
  1781. 23249         put_inode(rip);         /* can't make dir: it already exists */
  1782. 23250         put_inode(ldirp);       /* return parent too */
  1783. 23251         return(err_code);
  1784. 23252   }
  1785. 23253
  1786. 23254   /* Get the inode numbers for . and .. to enter in the directory. */
  1787. 23255   dotdot = ldirp->i_num;        /* parent's inode number */
  1788. 23256   dot = rip->i_num;             /* inode number of the new dir itself */
  1789. 23257
  1790. 23258   /* Now make dir entries for . and .. unless the disk is completely full. */
  1791. 23259   /* Use dot1 and dot2, so the mode of the directory isn't important. */
  1792. 23260   rip->i_mode = bits;   /* set mode */
  1793. 23261   r1 = search_dir(rip, dot1, &dot, ENTER);      /* enter . in the new dir */
  1794. 23262   r2 = search_dir(rip, dot2, &dotdot, ENTER);   /* enter .. in the new dir */
  1795. 23263
  1796. 23264   /* If both . and .. were successfully entered, increment the link counts. */
  1797. 23265   if (r1 == OK && r2 == OK) {
  1798. 23266         /* Normal case.  It was possible to enter . and .. in the new dir. */
  1799. 23267         rip->i_nlinks++;        /* this accounts for . */
  1800. 23268         ldirp->i_nlinks++;      /* this accounts for .. */
  1801. 23269         ldirp->i_dirt = DIRTY;  /* mark parent's inode as dirty */
  1802. 23270   } else {
  1803. 23271         /* It was not possible to enter . or .. probably disk was full. */
  1804. 23272         (void) search_dir(ldirp, string, (ino_t *) 0, DELETE);
  1805. 23273         rip->i_nlinks--;        /* undo the increment done in new_node() */
  1806. 23274   }
  1807. 23275   rip->i_dirt = DIRTY;          /* either way, i_nlinks has changed */
  1808. 23276
  1809. 23277   put_inode(ldirp);             /* return the inode of the parent dir */
  1810. 23278   put_inode(rip);               /* return the inode of the newly made dir */
  1811. 23279   return(err_code);             /* new_node() always sets 'err_code' */
  1812. 23280 }
  1813. 23283 /*===========================================================================*
  1814. 23284  *                              do_close                                     *
  1815. 23285  *===========================================================================*/
  1816. 23286 PUBLIC int do_close()
  1817. 23287 {
  1818. 23288 /* Perform the close(fd) system call. */
  1819. 23289
  1820. 23290   register struct filp *rfilp;
  1821. 23291   register struct inode *rip;
  1822. 23292   struct file_lock *flp;
  1823. 23293   int rw, mode_word, major, task, lock_count;
  1824. 23294   dev_t dev;
  1825. 23295
  1826. 23296   /* First locate the inode that belongs to the file descriptor. */
  1827. 23297   if ( (rfilp = get_filp(fd)) == NIL_FILP) return(err_code);
  1828. 23298   rip = rfilp->filp_ino;        /* 'rip' points to the inode */
  1829. 23299
  1830. 23300   if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
  1831. 23301         /* Check to see if the file is special. */
  1832. 23302         mode_word = rip->i_mode & I_TYPE;
  1833. 23303         if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
  1834. 23304                 dev = (dev_t) rip->i_zone[0];
  1835. 23305                 if (mode_word == I_BLOCK_SPECIAL)  {
  1836. 23306                         /* Invalidate cache entries unless special is mounted
  1837. 23307                          * or ROOT
  1838. 23308                          */
  1839. 23309                         if (!mounted(rip)) {
  1840. 23310                                 (void) do_sync();       /* purge cache */
  1841. 23311                                 invalidate(dev);
  1842. 23312                         }    
  1843. 23313                 }
  1844. 23314                 /* Use the dmap_close entry to do any special processing
  1845. 23315                  * required.
  1846. 23316                  */
  1847. 23317                 dev_mess.m_type = DEV_CLOSE;
  1848. 23318                 dev_mess.DEVICE = dev;
  1849. 23319                 major = (dev >> MAJOR) & BYTE;  /* major device nr */
  1850. 23320                 task = dmap[major].dmap_task;   /* device task nr */
  1851. 23321                 (*dmap[major].dmap_close)(task, &dev_mess);
  1852. 23322         }
  1853. 23323   }
  1854. 23324
  1855. 23325   /* If the inode being closed is a pipe, release everyone hanging on it. */
  1856. 23326   if (rip->i_pipe == I_PIPE) {
  1857. 23327         rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
  1858. 23328         release(rip, rw, NR_PROCS);
  1859. 23329   }
  1860. 23330
  1861. 23331   /* If a write has been done, the inode is already marked as DIRTY. */
  1862. 23332   if (--rfilp->filp_count == 0) {
  1863. 23333         if (rip->i_pipe == I_PIPE && rip->i_count > 1) {
  1864. 23334                 /* Save the file position in the i-node in case needed later.
  1865. 23335                  * The read and write positions are saved separately.  The
  1866. 23336                  * last 3 zones in the i-node are not used for (named) pipes.
  1867. 23337                  */
  1868. 23338                 if (rfilp->filp_mode == R_BIT)
  1869. 23339                         rip->i_zone[V2_NR_DZONES+1] = (zone_t) rfilp->filp_pos;
  1870. 23340                 else
  1871. 23341                         rip->i_zone[V2_NR_DZONES+2] = (zone_t) rfilp->filp_pos;
  1872. 23342         }
  1873. 23343         put_inode(rip);
  1874. 23344   }
  1875. 23345
  1876. 23346   fp->fp_cloexec &= ~(1L << fd);        /* turn off close-on-exec bit */
  1877. 23347   fp->fp_filp[fd] = NIL_FILP;
  1878. 23348
  1879. 23349   /* Check to see if the file is locked.  If so, release all locks. */
  1880. 23350   if (nr_locks == 0) return(OK);
  1881. 23351   lock_count = nr_locks;        /* save count of locks */
  1882. 23352   for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
  1883. 23353         if (flp->lock_type == 0) continue;      /* slot not in use */
  1884. 23354         if (flp->lock_inode == rip && flp->lock_pid == fp->fp_pid) {
  1885. 23355                 flp->lock_type = 0;
  1886. 23356                 nr_locks--;
  1887. 23357         }
  1888. 23358   }
  1889. 23359   if (nr_locks < lock_count) lock_revive();     /* lock released */
  1890. 23360   return(OK);
  1891. 23361 }
  1892. 23364 /*===========================================================================*
  1893. 23365  *                              do_lseek                                     *
  1894. 23366  *===========================================================================*/
  1895. 23367 PUBLIC int do_lseek()
  1896. 23368 {
  1897. 23369 /* Perform the lseek(ls_fd, offset, whence) system call. */
  1898. 23370
  1899. 23371   register struct filp *rfilp;
  1900. 23372   register off_t pos;
  1901. 23373
  1902. 23374   /* Check to see if the file descriptor is valid. */
  1903. 23375   if ( (rfilp = get_filp(ls_fd)) == NIL_FILP) return(err_code);
  1904. 23376
  1905. 23377   /* No lseek on pipes. */
  1906. 23378   if (rfilp->filp_ino->i_pipe == I_PIPE) return(ESPIPE);
  1907. 23379
  1908. 23380   /* The value of 'whence' determines the start position to use. */
  1909. 23381   switch(whence) {
  1910. 23382         case 0: pos = 0;        break;
  1911. 23383         case 1: pos = rfilp->filp_pos;  break;
  1912. 23384         case 2: pos = rfilp->filp_ino->i_size;  break;
  1913. 23385         default: return(EINVAL);
  1914. 23386   }
  1915. 23387
  1916. 23388   /* Check for overflow. */
  1917. 23389   if (((long)offset > 0) && ((long)(pos + offset) < (long)pos)) return(EINVAL);
  1918. 23390   if (((long)offset < 0) && ((long)(pos + offset) > (long)pos)) return(EINVAL);
  1919. 23391   pos = pos + offset;
  1920. 23392
  1921. 23393   if (pos != rfilp->filp_pos)
  1922. 23394         rfilp->filp_ino->i_seek = ISEEK;        /* inhibit read ahead */
  1923. 23395   rfilp->filp_pos = pos;
  1924. 23396   reply_l1 = pos;               /* insert the long into the output message */
  1925. 23397   return(OK);
  1926. 23398 }
  1927. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1928. src/fs/read.c    
  1929. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1930. 23400 /* This file contains the heart of the mechanism used to read (and write)
  1931. 23401  * files.  Read and write requests are split up into chunks that do not cross
  1932. 23402  * block boundaries.  Each chunk is then processed in turn.  Reads on special
  1933. 23403  * files are also detected and handled.
  1934. 23404  *
  1935. 23405  * The entry points into this file are
  1936. 23406  *   do_read:    perform the READ system call by calling read_write
  1937. 23407  *   read_write: actually do the work of READ and WRITE
  1938. 23408  *   read_map:   given an inode and file position, look up its zone number
  1939. 23409  *   rd_indir:   read an entry in an indirect block 
  1940. 23410  *   read_ahead: manage the block read ahead business
  1941. 23411  */
  1942. 23412
  1943. 23413 #include "fs.h"
  1944. 23414 #include <fcntl.h>
  1945. 23415 #include <minix/com.h>
  1946. 23416 #include "buf.h"
  1947. 23417 #include "file.h"
  1948. 23418 #include "fproc.h"
  1949. 23419 #include "inode.h"
  1950. 23420 #include "param.h"
  1951. 23421 #include "super.h"
  1952. 23422
  1953. 23423 #define FD_MASK          077    /* max file descriptor is 63 */
  1954. 23424
  1955. 23425 PRIVATE message umess;          /* message for asking SYSTASK for user copy */
  1956. 23426
  1957. 23427 FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,
  1958. 23428                         unsigned off, int chunk, unsigned left, int rw_flag,
  1959. 23429                         char *buff, int seg, int usr)                   );
  1960. 23430
  1961. 23431 /*===========================================================================*
  1962. 23432  *                              do_read                                      *
  1963. 23433  *===========================================================================*/
  1964. 23434 PUBLIC int do_read()
  1965. 23435 {
  1966. 23436   return(read_write(READING));
  1967. 23437 }
  1968. 23440 /*===========================================================================*
  1969. 23441  *                              read_write                                   *
  1970. 23442  *===========================================================================*/
  1971. 23443 PUBLIC int read_write(rw_flag)
  1972. 23444 int rw_flag;                    /* READING or WRITING */
  1973. 23445 {
  1974. 23446 /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
  1975. 23447
  1976. 23448   register struct inode *rip;
  1977. 23449   register struct filp *f;
  1978. 23450   off_t bytes_left, f_size, position;
  1979. 23451   unsigned int off, cum_io;
  1980. 23452   int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
  1981. 23453   int regular, partial_pipe = 0, partial_cnt = 0;
  1982. 23454   dev_t dev;
  1983. 23455   mode_t mode_word;
  1984. 23456   struct filp *wf;
  1985. 23457
  1986. 23458   /* MM loads segments by putting funny things in upper 10 bits of 'fd'. */
  1987. 23459   if (who == MM_PROC_NR && (fd & (~BYTE)) ) {
  1988. 23460         usr = (fd >> 8) & BYTE;
  1989. 23461         seg = (fd >> 6) & 03;
  1990. 23462         fd &= FD_MASK;          /* get rid of user and segment bits */
  1991. 23463   } else {
  1992. 23464         usr = who;              /* normal case */
  1993. 23465         seg = D;
  1994. 23466   }
  1995. 23467
  1996. 23468   /* If the file descriptor is valid, get the inode, size and mode. */
  1997. 23469   if (nbytes < 0) return(EINVAL);
  1998. 23470   if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
  1999. 23471   if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
  2000. 23472         return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
  2001. 23473   }
  2002. 23474   if (nbytes == 0) return(0);   /* so char special files need not check for 0*/
  2003. 23475   position = f->filp_pos;
  2004. 23476   if (position > MAX_FILE_POS) return(EINVAL);
  2005. 23477   if (position + nbytes < position) return(EINVAL); /* unsigned overflow */
  2006. 23478   oflags = f->filp_flags;
  2007. 23479   rip = f->filp_ino;
  2008. 23480   f_size = rip->i_size;
  2009. 23481   r = OK;
  2010. 23482   if (rip->i_pipe == I_PIPE) {
  2011. 23483         /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
  2012. 23484         cum_io = fp->fp_cum_io_partial; 
  2013. 23485   } else {
  2014. 23486         cum_io = 0;
  2015. 23487   }
  2016. 23488   op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
  2017. 23489   mode_word = rip->i_mode & I_TYPE;
  2018. 23490   regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
  2019. 23491
  2020. 23492   char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0);
  2021. 23493   block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0);
  2022. 23494   if (block_spec) f_size = LONG_MAX;
  2023. 23495   rdwt_err = OK;                /* set to EIO if disk error occurs */
  2024. 23496
  2025. 23497   /* Check for character special files. */
  2026. 23498   if (char_spec) {
  2027. 23499         dev = (dev_t) rip->i_zone[0];
  2028. 23500         r = dev_io(op, oflags & O_NONBLOCK, dev, position, nbytes, who,buffer);
  2029. 23501         if (r >= 0) {
  2030. 23502                 cum_io = r;
  2031. 23503                 position += r;
  2032. 23504                 r = OK;
  2033. 23505         }
  2034. 23506   } else {
  2035. 23507         if (rw_flag == WRITING && block_spec == 0) {
  2036. 23508                 /* Check in advance to see if file will grow too big. */
  2037. 23509                 if (position > rip->i_sp->s_max_size - nbytes) return(EFBIG);
  2038. 23510
  2039. 23511                 /* Check for O_APPEND flag. */
  2040. 23512                 if (oflags & O_APPEND) position = f_size;
  2041. 23513
  2042. 23514                 /* Clear the zone containing present EOF if hole about
  2043. 23515                  * to be created.  This is necessary because all unwritten
  2044. 23516                  * blocks prior to the EOF must read as zeros.
  2045. 23517                  */
  2046. 23518                 if (position > f_size) clear_zone(rip, f_size, 0);
  2047. 23519         }
  2048. 23520
  2049. 23521         /* Pipes are a little different.  Check. */
  2050. 23522         if (rip->i_pipe == I_PIPE) {
  2051. 23523                r = pipe_check(rip,rw_flag,oflags,nbytes,position,&partial_cnt);
  2052. 23524                if (r <= 0) return(r);
  2053. 23525         }
  2054. 23526
  2055. 23527         if (partial_cnt > 0) partial_pipe = 1;
  2056. 23528
  2057. 23529         /* Split the transfer into chunks that don't span two blocks. */
  2058. 23530         while (nbytes != 0) {
  2059. 23531                 off = (unsigned int) (position % BLOCK_SIZE);/* offset in blk*/
  2060. 23532                 if (partial_pipe) {  /* pipes only */
  2061. 23533                         chunk = MIN(partial_cnt, BLOCK_SIZE - off);
  2062. 23534                 } else
  2063. 23535                         chunk = MIN(nbytes, BLOCK_SIZE - off);
  2064. 23536                 if (chunk < 0) chunk = BLOCK_SIZE - off;
  2065. 23537
  2066. 23538                 if (rw_flag == READING) {
  2067. 23539                         bytes_left = f_size - position;
  2068. 23540                         if (position >= f_size) break;  /* we are beyond EOF */
  2069. 23541                         if (chunk > bytes_left) chunk = (int) bytes_left;
  2070. 23542                 }
  2071. 23543
  2072. 23544                 /* Read or write 'chunk' bytes. */
  2073. 23545                 r = rw_chunk(rip, position, off, chunk, (unsigned) nbytes,
  2074. 23546                              rw_flag, buffer, seg, usr);
  2075. 23547                 if (r != OK) break;     /* EOF reached */
  2076. 23548                 if (rdwt_err < 0) break;
  2077. 23549
  2078. 23550                 /* Update counters and pointers. */
  2079. 23551                 buffer += chunk;        /* user buffer address */
  2080. 23552                 nbytes -= chunk;        /* bytes yet to be read */
  2081. 23553                 cum_io += chunk;        /* bytes read so far */
  2082. 23554                 position += chunk;      /* position within the file */
  2083. 23555
  2084. 23556                 if (partial_pipe) {
  2085. 23557                         partial_cnt -= chunk;
  2086. 23558                         if (partial_cnt <= 0)  break;
  2087. 23559                 }
  2088. 23560         }
  2089. 23561   }
  2090. 23562
  2091. 23563   /* On write, update file size and access time. */
  2092. 23564   if (rw_flag == WRITING) {
  2093. 23565         if (regular || mode_word == I_DIRECTORY) {
  2094. 23566                 if (position > f_size) rip->i_size = position;
  2095. 23567         }
  2096. 23568   } else {
  2097. 23569         if (rip->i_pipe == I_PIPE && position >= rip->i_size) {
  2098. 23570                 /* Reset pipe pointers. */
  2099. 23571                 rip->i_size = 0;        /* no data left */
  2100. 23572                 position = 0;           /* reset reader(s) */
  2101. 23573                 if ( (wf = find_filp(rip, W_BIT)) != NIL_FILP) wf->filp_pos =0;
  2102. 23574         }
  2103. 23575   }
  2104. 23576   f->filp_pos = position;
  2105. 23577
  2106. 23578   /* Check to see if read-ahead is called for, and if so, set it up. */
  2107. 23579   if (rw_flag == READING && rip->i_seek == NO_SEEK && position % BLOCK_SIZE== 0
  2108. 23580                 && (regular || mode_word == I_DIRECTORY)) {
  2109. 23581         rdahed_inode = rip;
  2110. 23582         rdahedpos = position;
  2111. 23583   }
  2112. 23584   rip->i_seek = NO_SEEK;
  2113. 23585
  2114. 23586   if (rdwt_err != OK) r = rdwt_err;     /* check for disk error */
  2115. 23587   if (rdwt_err == END_OF_FILE) r = OK;
  2116. 23588   if (r == OK) {
  2117. 23589         if (rw_flag == READING) rip->i_update |= ATIME;
  2118. 23590         if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
  2119. 23591         rip->i_dirt = DIRTY;            /* inode is thus now dirty */
  2120. 23592         if (partial_pipe) {
  2121. 23593                 partial_pipe = 0;
  2122. 23594                         /* partial write on pipe with */
  2123. 23595                         /* O_NONBLOCK, return write count */
  2124. 23596                 if (!(oflags & O_NONBLOCK)) {
  2125. 23597                         fp->fp_cum_io_partial = cum_io;
  2126. 23598                         suspend(XPIPE); /* partial write on pipe with */
  2127. 23599                         return(0);      /* nbyte > PIPE_SIZE - non-atomic */
  2128. 23600                 }
  2129. 23601         }
  2130. 23602         fp->fp_cum_io_partial = 0;
  2131. 23603         return(cum_io);
  2132. 23604   } else {
  2133. 23605         return(r);
  2134. 23606   }
  2135. 23607 }
  2136. 23610 /*===========================================================================*
  2137. 23611  *                              rw_chunk                                     *
  2138. 23612  *===========================================================================*/
  2139. 23613 PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, seg, usr)
  2140. 23614 register struct inode *rip;     /* pointer to inode for file to be rd/wr */
  2141. 23615 off_t position;                 /* position within file to read or write */
  2142. 23616 unsigned off;                   /* off within the current block */
  2143. 23617 int chunk;                      /* number of bytes to read or write */
  2144. 23618 unsigned left;                  /* max number of bytes wanted after position */
  2145. 23619 int rw_flag;                    /* READING or WRITING */
  2146. 23620 char *buff;                     /* virtual address of the user buffer */
  2147. 23621 int seg;                        /* T or D segment in user space */
  2148. 23622 int usr;                        /* which user process */
  2149. 23623 {
  2150. 23624 /* Read or write (part of) a block. */
  2151. 23625
  2152. 23626   register struct buf *bp;
  2153. 23627   register int r;
  2154. 23628   int n, block_spec;
  2155. 23629   block_t b;
  2156. 23630   dev_t dev;
  2157. 23631
  2158. 23632   block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
  2159. 23633   if (block_spec) {
  2160. 23634         b = position/BLOCK_SIZE;
  2161. 23635         dev = (dev_t) rip->i_zone[0];
  2162. 23636   } else {
  2163. 23637         b = read_map(rip, position);
  2164. 23638         dev = rip->i_dev;
  2165. 23639   }
  2166. 23640
  2167. 23641   if (!block_spec && b == NO_BLOCK) {
  2168. 23642         if (rw_flag == READING) {
  2169. 23643                 /* Reading from a nonexistent block.  Must read as all zeros.*/
  2170. 23644                 bp = get_block(NO_DEV, NO_BLOCK, NORMAL);    /* get a buffer */
  2171. 23645                 zero_block(bp);
  2172. 23646         } else {
  2173. 23647                 /* Writing to a nonexistent block. Create and enter in inode.*/
  2174. 23648                 if ((bp= new_block(rip, position)) == NIL_BUF)return(err_code);
  2175. 23649         }
  2176. 23650   } else if (rw_flag == READING) {
  2177. 23651         /* Read and read ahead if convenient. */
  2178. 23652         bp = rahead(rip, b, position, left);
  2179. 23653   } else {
  2180. 23654         /* Normally an existing block to be partially overwritten is first read
  2181. 23655          * in.  However, a full block need not be read in.  If it is already in
  2182. 23656          * the cache, acquire it, otherwise just acquire a free buffer.
  2183. 23657          */
  2184. 23658         n = (chunk == BLOCK_SIZE ? NO_READ : NORMAL);
  2185. 23659         if (!block_spec && off == 0 && position >= rip->i_size) n = NO_READ;
  2186. 23660         bp = get_block(dev, b, n);
  2187. 23661   }
  2188. 23662
  2189. 23663   /* In all cases, bp now points to a valid buffer. */
  2190. 23664   if (rw_flag == WRITING && chunk != BLOCK_SIZE && !block_spec &&
  2191. 23665                                         position >= rip->i_size && off == 0) {
  2192. 23666         zero_block(bp);
  2193. 23667   }
  2194. 23668   if (rw_flag == READING) {
  2195. 23669         /* Copy a chunk from the block buffer to user space. */
  2196. 23670         r = sys_copy(FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
  2197. 23671                         usr, seg, (phys_bytes) buff,
  2198. 23672                         (phys_bytes) chunk);
  2199. 23673   } else {
  2200. 23674         /* Copy a chunk from user space to the block buffer. */
  2201. 23675         r = sys_copy(usr, seg, (phys_bytes) buff,
  2202. 23676                         FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
  2203. 23677                         (phys_bytes) chunk);
  2204. 23678         bp->b_dirt = DIRTY;
  2205. 23679   }
  2206. 23680   n = (off + chunk == BLOCK_SIZE ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK);
  2207. 23681   put_block(bp, n);
  2208. 23682   return(r);
  2209. 23683 }
  2210. 23686 /*===========================================================================*
  2211. 23687  *                              read_map                                     *
  2212. 23688  *===========================================================================*/
  2213. 23689 PUBLIC block_t read_map(rip, position)
  2214. 23690 register struct inode *rip;     /* ptr to inode to map from */
  2215. 23691 off_t position;                 /* position in file whose blk wanted */
  2216. 23692 {
  2217. 23693 /* Given an inode and a position within the corresponding file, locate the
  2218. 23694  * block (not zone) number in which that position is to be found and return it.
  2219. 23695  */
  2220. 23696
  2221. 23697   register struct buf *bp;
  2222. 23698   register zone_t z;
  2223. 23699   int scale, boff, dzones, nr_indirects, index, zind, ex;
  2224. 23700   block_t b;
  2225. 23701   long excess, zone, block_pos;
  2226. 23702   
  2227. 23703   scale = rip->i_sp->s_log_zone_size;   /* for block-zone conversion */
  2228. 23704   block_pos = position/BLOCK_SIZE;      /* relative blk # in file */
  2229. 23705   zone = block_pos >> scale;    /* position's zone */
  2230. 23706   boff = (int) (block_pos - (zone << scale) ); /* relative blk # within zone */
  2231. 23707   dzones = rip->i_ndzones;
  2232. 23708   nr_indirects = rip->i_nindirs;
  2233. 23709
  2234. 23710   /* Is 'position' to be found in the inode itself? */
  2235. 23711   if (zone < dzones) {
  2236. 23712         zind = (int) zone;      /* index should be an int */
  2237. 23713         z = rip->i_zone[zind];
  2238. 23714         if (z == NO_ZONE) return(NO_BLOCK);
  2239. 23715         b = ((block_t) z << scale) + boff;
  2240. 23716         return(b);
  2241. 23717   }
  2242. 23718
  2243. 23719   /* It is not in the inode, so it must be single or double indirect. */
  2244. 23720   excess = zone - dzones;       /* first Vx_NR_DZONES don't count */
  2245. 23721
  2246. 23722   if (excess < nr_indirects) {
  2247. 23723         /* 'position' can be located via the single indirect block. */
  2248. 23724         z = rip->i_zone[dzones];
  2249. 23725   } else {
  2250. 23726         /* 'position' can be located via the double indirect block. */
  2251. 23727         if ( (z = rip->i_zone[dzones+1]) == NO_ZONE) return(NO_BLOCK);
  2252. 23728         excess -= nr_indirects;                 /* single indir doesn't count*/
  2253. 23729         b = (block_t) z << scale;
  2254. 23730         bp = get_block(rip->i_dev, b, NORMAL);  /* get double indirect block */
  2255. 23731         index = (int) (excess/nr_indirects);
  2256. 23732         z = rd_indir(bp, index);                /* z= zone for single*/
  2257. 23733         put_block(bp, INDIRECT_BLOCK);          /* release double ind block */
  2258. 23734         excess = excess % nr_indirects;         /* index into single ind blk */
  2259. 23735   }
  2260. 23736
  2261. 23737   /* 'z' is zone num for single indirect block; 'excess' is index into it. */
  2262. 23738   if (z == NO_ZONE) return(NO_BLOCK);
  2263. 23739   b = (block_t) z << scale;                     /* b is blk # for single ind */
  2264. 23740   bp = get_block(rip->i_dev, b, NORMAL);        /* get single indirect block */
  2265. 23741   ex = (int) excess;                            /* need an integer */
  2266. 23742   z = rd_indir(bp, ex);                         /* get block pointed to */
  2267. 23743   put_block(bp, INDIRECT_BLOCK);                /* release single indir blk */
  2268. 23744   if (z == NO_ZONE) return(NO_BLOCK);
  2269. 23745   b = ((block_t) z << scale) + boff;
  2270. 23746   return(b);
  2271. 23747 }
  2272. 23750 /*===========================================================================*
  2273. 23751  *                              rd_indir                                     *
  2274. 23752  *===========================================================================*/
  2275. 23753 PUBLIC zone_t rd_indir(bp, index)
  2276. 23754 struct buf *bp;                 /* pointer to indirect block */
  2277. 23755 int index;                      /* index into *bp */
  2278. 23756 {
  2279. 23757 /* Given a pointer to an indirect block, read one entry.  The reason for
  2280. 23758  * making a separate routine out of this is that there are four cases:
  2281. 23759  * V1 (IBM and 68000), and V2 (IBM and 68000).
  2282. 23760  */
  2283. 23761
  2284. 23762   struct super_block *sp;
  2285. 23763   zone_t zone;                  /* V2 zones are longs (shorts in V1) */
  2286. 23764
  2287. 23765   sp = get_super(bp->b_dev);    /* need super block to find file sys type */
  2288. 23766
  2289. 23767   /* read a zone from an indirect block */
  2290. 23768   if (sp->s_version == V1)
  2291. 23769         zone = (zone_t) conv2(sp->s_native, (int)  bp->b_v1_ind[index]);
  2292. 23770   else
  2293. 23771         zone = (zone_t) conv4(sp->s_native, (long) bp->b_v2_ind[index]);
  2294. 23772
  2295. 23773   if (zone != NO_ZONE &&
  2296. 23774                 (zone < (zone_t) sp->s_firstdatazone || zone >= sp->s_zones)) {
  2297. 23775         printf("Illegal zone number %ld in indirect block, index %dn",
  2298. 23776                (long) zone, index);
  2299. 23777         panic("check file system", NO_NUM);
  2300. 23778   }
  2301. 23779   return(zone);
  2302. 23780 }
  2303. 23783 /*===========================================================================*
  2304. 23784  *                              read_ahead                                   *
  2305. 23785  *===========================================================================*/
  2306. 23786 PUBLIC void read_ahead()
  2307. 23787 {
  2308. 23788 /* Read a block into the cache before it is needed. */
  2309. 23789
  2310. 23790   register struct inode *rip;
  2311. 23791   struct buf *bp;
  2312. 23792   block_t b;
  2313. 23793
  2314. 23794   rip = rdahed_inode;           /* pointer to inode to read ahead from */
  2315. 23795   rdahed_inode = NIL_INODE;     /* turn off read ahead */
  2316. 23796   if ( (b = read_map(rip, rdahedpos)) == NO_BLOCK) return;      /* at EOF */
  2317. 23797   bp = rahead(rip, b, rdahedpos, BLOCK_SIZE);
  2318. 23798   put_block(bp, PARTIAL_DATA_BLOCK);
  2319. 23799 }
  2320. 23802 /*===========================================================================*
  2321. 23803  *                              rahead                                       *
  2322. 23804  *===========================================================================*/
  2323. 23805 PUBLIC struct buf *rahead(rip, baseblock, position, bytes_ahead)
  2324. 23806 register struct inode *rip;     /* pointer to inode for file to be read */
  2325. 23807 block_t baseblock;              /* block at current position */
  2326. 23808 off_t position;                 /* position within file */
  2327. 23809 unsigned bytes_ahead;           /* bytes beyond position for immediate use */
  2328. 23810 {
  2329. 23811 /* Fetch a block from the cache or the device.  If a physical read is
  2330. 23812  * required, prefetch as many more blocks as convenient into the cache.
  2331. 23813  * This usually covers bytes_ahead and is at least BLOCKS_MINIMUM.
  2332. 23814  * The device driver may decide it knows better and stop reading at a
  2333. 23815  * cylinder boundary (or after an error).  Rw_scattered() puts an optional
  2334. 23816  * flag on all reads to allow this.
  2335. 23817  */
  2336. 23818
  2337. 23819 /* Minimum number of blocks to prefetch. */
  2338. 23820 # define BLOCKS_MINIMUM         (NR_BUFS < 50 ? 18 : 32)
  2339. 23821
  2340. 23822   int block_spec, scale, read_q_size;
  2341. 23823   unsigned int blocks_ahead, fragment;
  2342. 23824   block_t block, blocks_left;
  2343. 23825   off_t ind1_pos;
  2344. 23826   dev_t dev;
  2345. 23827   struct buf *bp;
  2346. 23828   static struct buf *read_q[NR_BUFS];
  2347. 23829
  2348. 23830   block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
  2349. 23831   if (block_spec) {
  2350. 23832         dev = (dev_t) rip->i_zone[0];
  2351. 23833   } else {
  2352. 23834         dev = rip->i_dev;
  2353. 23835   }
  2354. 23836
  2355. 23837   block = baseblock;
  2356. 23838   bp = get_block(dev, block, PREFETCH);
  2357. 23839   if (bp->b_dev != NO_DEV) return(bp);
  2358. 23840
  2359. 23841   /* The best guess for the number of blocks to prefetch:  A lot.
  2360. 23842    * It is impossible to tell what the device looks like, so we don't even
  2361. 23843    * try to guess the geometry, but leave it to the driver.
  2362. 23844    *
  2363. 23845    * The floppy driver can read a full track with no rotational delay, and it
  2364. 23846    * avoids reading partial tracks if it can, so handing it enough buffers to
  2365. 23847    * read two tracks is perfect.  (Two, because some diskette types have
  2366. 23848    * an odd number of sectors per track, so a block may span tracks.)
  2367. 23849    *
  2368. 23850    * The disk drivers don't try to be smart.  With todays disks it is
  2369. 23851    * impossible to tell what the real geometry looks like, so it is best to
  2370. 23852    * read as much as you can.  With luck the caching on the drive allows
  2371. 23853    * for a little time to start the next read.
  2372. 23854    *
  2373. 23855    * The current solution below is a bit of a hack, it just reads blocks from
  2374. 23856    * the current file position hoping that more of the file can be found.  A
  2375. 23857    * better solution must look at the already available zone pointers and
  2376. 23858    * indirect blocks (but don't call read_map!).
  2377. 23859    */
  2378. 23860
  2379. 23861   fragment = position % BLOCK_SIZE;
  2380. 23862   position -= fragment;
  2381. 23863   bytes_ahead += fragment;
  2382. 23864
  2383. 23865   blocks_ahead = (bytes_ahead + BLOCK_SIZE - 1) / BLOCK_SIZE;
  2384. 23866
  2385. 23867   if (block_spec && rip->i_size == 0) {
  2386. 23868         blocks_left = NR_IOREQS;
  2387. 23869   } else {
  2388. 23870         blocks_left = (rip->i_size - position + BLOCK_SIZE - 1) / BLOCK_SIZE;
  2389. 23871
  2390. 23872         /* Go for the first indirect block if we are in its neighborhood. */
  2391. 23873         if (!block_spec) {
  2392. 23874                 scale = rip->i_sp->s_log_zone_size;
  2393. 23875                 ind1_pos = (off_t) rip->i_ndzones * (BLOCK_SIZE << scale);
  2394. 23876                 if (position <= ind1_pos && rip->i_size > ind1_pos) {
  2395. 23877                         blocks_ahead++;
  2396. 23878                         blocks_left++;
  2397. 23879                 }
  2398. 23880         }
  2399. 23881   }
  2400. 23882
  2401. 23883   /* No more than the maximum request. */
  2402. 23884   if (blocks_ahead > NR_IOREQS) blocks_ahead = NR_IOREQS;
  2403. 23885
  2404. 23886   /* Read at least the minimum number of blocks, but not after a seek. */
  2405. 23887   if (blocks_ahead < BLOCKS_MINIMUM && rip->i_seek == NO_SEEK)
  2406. 23888         blocks_ahead = BLOCKS_MINIMUM;
  2407. 23889
  2408. 23890   /* Can't go past end of file. */
  2409. 23891   if (blocks_ahead > blocks_left) blocks_ahead = blocks_left;
  2410. 23892
  2411. 23893   read_q_size = 0;
  2412. 23894
  2413. 23895   /* Acquire block buffers. */
  2414. 23896   for (;;) {
  2415. 23897         read_q[read_q_size++] = bp;
  2416. 23898
  2417. 23899         if (--blocks_ahead == 0) break;
  2418. 23900
  2419. 23901         /* Don't trash the cache, leave 4 free. */
  2420. 23902         if (bufs_in_use >= NR_BUFS - 4) break;
  2421. 23903
  2422. 23904         block++;
  2423. 23905
  2424. 23906         bp = get_block(dev, block, PREFETCH);
  2425. 23907         if (bp->b_dev != NO_DEV) {
  2426. 23908                 /* Oops, block already in the cache, get out. */
  2427. 23909                 put_block(bp, FULL_DATA_BLOCK);
  2428. 23910                 break;
  2429. 23911         }
  2430. 23912   }
  2431. 23913   rw_scattered(dev, read_q, read_q_size, READING);
  2432. 23914   return(get_block(dev, baseblock, NORMAL));
  2433. 23915 }
  2434. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2435. src/fs/write.c    
  2436. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2437. 24000 /* This file is the counterpart of "read.c".  It contains the code for writing
  2438. 24001  * insofar as this is not contained in read_write().
  2439. 24002  *
  2440. 24003  * The entry points into this file are
  2441. 24004  *   do_write:     call read_write to perform the WRITE system call
  2442. 24005  *   clear_zone:   erase a zone in the middle of a file
  2443. 24006  *   new_block:    acquire a new block
  2444. 24007  */
  2445. 24008
  2446. 24009 #include "fs.h"
  2447. 24010 #include <string.h>
  2448. 24011 #include "buf.h"
  2449. 24012 #include "file.h"
  2450. 24013 #include "fproc.h"
  2451. 24014 #include "inode.h"
  2452. 24015 #include "super.h"
  2453. 24016
  2454. 24017 FORWARD _PROTOTYPE( int write_map, (struct inode *rip, off_t position,
  2455. 24018                         zone_t new_zone)                                );
  2456. 24019
  2457. 24020 FORWARD _PROTOTYPE( void wr_indir, (struct buf *bp, int index, zone_t zone) );
  2458. 24021
  2459. 24022 /*===========================================================================*
  2460. 24023  *                              do_write                                     *
  2461. 24024  *===========================================================================*/
  2462. 24025 PUBLIC int do_write()
  2463. 24026 {
  2464. 24027 /* Perform the write(fd, buffer, nbytes) system call. */
  2465. 24028
  2466. 24029   return(read_write(WRITING));
  2467. 24030 }
  2468. 24033 /*===========================================================================*
  2469. 24034  *                              write_map                                    *
  2470. 24035  *===========================================================================*/
  2471. 24036 PRIVATE int write_map(rip, position, new_zone)
  2472. 24037 register struct inode *rip;     /* pointer to inode to be changed */
  2473. 24038 off_t position;                 /* file address to be mapped */
  2474. 24039 zone_t new_zone;                /* zone # to be inserted */
  2475. 24040 {
  2476. 24041 /* Write a new zone into an inode. */
  2477. 24042   int scale, ind_ex, new_ind, new_dbl, zones, nr_indirects, single, zindex, ex;
  2478. 24043   zone_t z, z1;
  2479. 24044   register block_t b;
  2480. 24045   long excess, zone;
  2481. 24046   struct buf *bp;
  2482. 24047
  2483. 24048   rip->i_dirt = DIRTY;          /* inode will be changed */
  2484. 24049   bp = NIL_BUF;
  2485. 24050   scale = rip->i_sp->s_log_zone_size;           /* for zone-block conversion */
  2486. 24051   zone = (position/BLOCK_SIZE) >> scale;        /* relative zone # to insert */
  2487. 24052   zones = rip->i_ndzones;       /* # direct zones in the inode */
  2488. 24053   nr_indirects = rip->i_nindirs;/* # indirect zones per indirect block */
  2489. 24054
  2490. 24055   /* Is 'position' to be found in the inode itself? */
  2491. 24056   if (zone < zones) {
  2492. 24057         zindex = (int) zone;    /* we need an integer here */
  2493. 24058         rip->i_zone[zindex] = new_zone;
  2494. 24059         return(OK);
  2495. 24060   }
  2496. 24061
  2497. 24062   /* It is not in the inode, so it must be single or double indirect. */
  2498. 24063   excess = zone - zones;        /* first Vx_NR_DZONES don't count */
  2499. 24064   new_ind = FALSE;
  2500. 24065   new_dbl = FALSE;
  2501. 24066
  2502. 24067   if (excess < nr_indirects) {
  2503. 24068         /* 'position' can be located via the single indirect block. */
  2504. 24069         z1 = rip->i_zone[zones];        /* single indirect zone */
  2505. 24070         single = TRUE;
  2506. 24071   } else {
  2507. 24072         /* 'position' can be located via the double indirect block. */
  2508. 24073         if ( (z = rip->i_zone[zones+1]) == NO_ZONE) {
  2509. 24074                 /* Create the double indirect block. */
  2510. 24075                 if ( (z = alloc_zone(rip->i_dev, rip->i_zone[0])) == NO_ZONE)
  2511. 24076                         return(err_code);
  2512. 24077                 rip->i_zone[zones+1] = z;
  2513. 24078                 new_dbl = TRUE; /* set flag for later */
  2514. 24079         }
  2515. 24080
  2516. 24081         /* Either way, 'z' is zone number for double indirect block. */
  2517. 24082         excess -= nr_indirects; /* single indirect doesn't count */
  2518. 24083         ind_ex = (int) (excess / nr_indirects);
  2519. 24084         excess = excess % nr_indirects;
  2520. 24085         if (ind_ex >= nr_indirects) return(EFBIG);
  2521. 24086         b = (block_t) z << scale;
  2522. 24087         bp = get_block(rip->i_dev, b, (new_dbl ? NO_READ : NORMAL));
  2523. 24088         if (new_dbl) zero_block(bp);
  2524. 24089         z1 = rd_indir(bp, ind_ex);
  2525. 24090         single = FALSE;
  2526. 24091   }
  2527. 24092
  2528. 24093   /* z1 is now single indirect zone; 'excess' is index. */
  2529. 24094   if (z1 == NO_ZONE) {
  2530. 24095         /* Create indirect block and store zone # in inode or dbl indir blk. */
  2531. 24096         z1 = alloc_zone(rip->i_dev, rip->i_zone[0]);
  2532. 24097         if (single)
  2533. 24098                 rip->i_zone[zones] = z1;        /* update inode */
  2534. 24099         else
  2535. 24100                 wr_indir(bp, ind_ex, z1);       /* update dbl indir */
  2536. 24101
  2537. 24102         new_ind = TRUE;
  2538. 24103         if (bp != NIL_BUF) bp->b_dirt = DIRTY;  /* if double ind, it is dirty*/
  2539. 24104         if (z1 == NO_ZONE) {
  2540. 24105                 put_block(bp, INDIRECT_BLOCK);  /* release dbl indirect blk */
  2541. 24106                 return(err_code);       /* couldn't create single ind */
  2542. 24107         }
  2543. 24108   }
  2544. 24109   put_block(bp, INDIRECT_BLOCK);        /* release double indirect blk */
  2545. 24110
  2546. 24111   /* z1 is indirect block's zone number. */
  2547. 24112   b = (block_t) z1 << scale;
  2548. 24113   bp = get_block(rip->i_dev, b, (new_ind ? NO_READ : NORMAL) );
  2549. 24114   if (new_ind) zero_block(bp);
  2550. 24115   ex = (int) excess;                    /* we need an int here */
  2551. 24116   wr_indir(bp, ex, new_zone);
  2552. 24117   bp->b_dirt = DIRTY;
  2553. 24118   put_block(bp, INDIRECT_BLOCK);
  2554. 24119
  2555. 24120   return(OK);
  2556. 24121 }
  2557. 24124 /*===========================================================================*
  2558. 24125  *                              wr_indir                                     *
  2559. 24126  *===========================================================================*/
  2560. 24127 PRIVATE void wr_indir(bp, index, zone)
  2561. 24128 struct buf *bp;                 /* pointer to indirect block */
  2562. 24129 int index;                      /* index into *bp */
  2563. 24130 zone_t zone;                    /* zone to write */
  2564. 24131 {
  2565. 24132 /* Given a pointer to an indirect block, write one entry. */
  2566. 24133
  2567. 24134   struct super_block *sp;
  2568. 24135
  2569. 24136   sp = get_super(bp->b_dev);    /* need super block to find file sys type */
  2570. 24137
  2571. 24138   /* write a zone into an indirect block */
  2572. 24139   if (sp->s_version == V1)
  2573. 24140         bp->b_v1_ind[index] = (zone1_t) conv2(sp->s_native, (int)  zone);
  2574. 24141   else
  2575. 24142         bp->b_v2_ind[index] = (zone_t)  conv4(sp->s_native, (long) zone);
  2576. 24143 }
  2577. 24146 /*===========================================================================*
  2578. 24147  *                              clear_zone                                   *
  2579. 24148  *===========================================================================*/
  2580. 24149 PUBLIC void clear_zone(rip, pos, flag)
  2581. 24150 register struct inode *rip;     /* inode to clear */
  2582. 24151 off_t pos;                      /* points to block to clear */
  2583. 24152 int flag;                       /* 0 if called by read_write, 1 by new_block */
  2584. 24153 {
  2585. 24154 /* Zero a zone, possibly starting in the middle.  The parameter 'pos' gives
  2586. 24155  * a byte in the first block to be zeroed.  Clearzone() is called from 
  2587. 24156  * read_write and new_block().
  2588. 24157  */
  2589. 24158
  2590. 24159   register struct buf *bp;
  2591. 24160   register block_t b, blo, bhi;
  2592. 24161   register off_t next;
  2593. 24162   register int scale;
  2594. 24163   register zone_t zone_size;
  2595. 24164
  2596. 24165   /* If the block size and zone size are the same, clear_zone() not needed. */
  2597. 24166   scale = rip->i_sp->s_log_zone_size;
  2598. 24167   if (scale == 0) return;
  2599. 24168
  2600. 24169   zone_size = (zone_t) BLOCK_SIZE << scale;
  2601. 24170   if (flag == 1) pos = (pos/zone_size) * zone_size;
  2602. 24171   next = pos + BLOCK_SIZE - 1;
  2603. 24172
  2604. 24173   /* If 'pos' is in the last block of a zone, do not clear the zone. */
  2605. 24174   if (next/zone_size != pos/zone_size) return;
  2606. 24175   if ( (blo = read_map(rip, next)) == NO_BLOCK) return;
  2607. 24176   bhi = (  ((blo>>scale)+1) << scale)   - 1;
  2608. 24177
  2609. 24178   /* Clear all the blocks between 'blo' and 'bhi'. */
  2610. 24179   for (b = blo; b <= bhi; b++) {
  2611. 24180         bp = get_block(rip->i_dev, b, NO_READ);
  2612. 24181         zero_block(bp);
  2613. 24182         put_block(bp, FULL_DATA_BLOCK);
  2614. 24183   }
  2615. 24184 }
  2616. 24187 /*===========================================================================*
  2617. 24188  *                              new_block                                    *
  2618. 24189  *===========================================================================*/
  2619. 24190 PUBLIC struct buf *new_block(rip, position)
  2620. 24191 register struct inode *rip;     /* pointer to inode */
  2621. 24192 off_t position;                 /* file pointer */
  2622. 24193 {
  2623. 24194 /* Acquire a new block and return a pointer to it.  Doing so may require
  2624. 24195  * allocating a complete zone, and then returning the initial block.
  2625. 24196  * On the other hand, the current zone may still have some unused blocks.
  2626. 24197  */
  2627. 24198
  2628. 24199   register struct buf *bp;
  2629. 24200   block_t b, base_block;
  2630. 24201   zone_t z;
  2631. 24202   zone_t zone_size;
  2632. 24203   int scale, r;
  2633. 24204   struct super_block *sp;
  2634. 24205
  2635. 24206   /* Is another block available in the current zone? */
  2636. 24207   if ( (b = read_map(rip, position)) == NO_BLOCK) {
  2637. 24208         /* Choose first zone if possible. */
  2638. 24209         /* Lose if the file is nonempty but the first zone number is NO_ZONE
  2639. 24210          * corresponding to a zone full of zeros.  It would be better to
  2640. 24211          * search near the last real zone.
  2641. 24212          */
  2642. 24213         if (rip->i_zone[0] == NO_ZONE) {
  2643. 24214                 sp = rip->i_sp;
  2644. 24215                 z = sp->s_firstdatazone;
  2645. 24216         } else {
  2646. 24217                 z = rip->i_zone[0];     /* hunt near first zone */
  2647. 24218         }
  2648. 24219         if ( (z = alloc_zone(rip->i_dev, z)) == NO_ZONE) return(NIL_BUF);
  2649. 24220         if ( (r = write_map(rip, position, z)) != OK) {
  2650. 24221                 free_zone(rip->i_dev, z);
  2651. 24222                 err_code = r;
  2652. 24223                 return(NIL_BUF);
  2653. 24224         }
  2654. 24225
  2655. 24226         /* If we are not writing at EOF, clear the zone, just to be safe. */
  2656. 24227         if ( position != rip->i_size) clear_zone(rip, position, 1);
  2657. 24228         scale = rip->i_sp->s_log_zone_size;
  2658. 24229         base_block = (block_t) z << scale;
  2659. 24230         zone_size = (zone_t) BLOCK_SIZE << scale;
  2660. 24231         b = base_block + (block_t)((position % zone_size)/BLOCK_SIZE);
  2661. 24232   }
  2662. 24233
  2663. 24234   bp = get_block(rip->i_dev, b, NO_READ);
  2664. 24235   zero_block(bp);
  2665. 24236   return(bp);
  2666. 24237 }
  2667. 24240 /*===========================================================================*
  2668. 24241  *                              zero_block                                   *
  2669. 24242  *===========================================================================*/
  2670. 24243 PUBLIC void zero_block(bp)
  2671. 24244 register struct buf *bp;        /* pointer to buffer to zero */
  2672. 24245 {
  2673. 24246 /* Zero a block. */
  2674. 24247
  2675. 24248   memset(bp->b_data, 0, BLOCK_SIZE);
  2676. 24249   bp->b_dirt = DIRTY;
  2677. 24250 }
  2678. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2679. src/fs/pipe.c    
  2680. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2681. 24300 /* This file deals with the suspension and revival of processes.  A process can
  2682. 24301  * be suspended because it wants to read or write from a pipe and can't, or
  2683. 24302  * because it wants to read or write from a special file and can't.  When a
  2684. 24303  * process can't continue it is suspended, and revived later when it is able
  2685. 24304  * to continue.
  2686. 24305  *
  2687. 24306  * The entry points into this file are
  2688. 24307  *   do_pipe:     perform the PIPE system call
  2689. 24308  *   pipe_check:  check to see that a read or write on a pipe is feasible now
  2690. 24309  *   suspend:     suspend a process that cannot do a requested read or write