BOOK.TXT
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:999k
源码类别:
操作系统开发
开发平台:
C/C++
- 21209 minor = (int) (sp->s_dev >> MINOR) & BYTE;
- 21210 printf("No space on %sdevice %d/%dn",
- 21211 sp->s_dev == ROOT_DEV ? "root " : "", major, minor);
- 21212 return(NO_ZONE);
- 21213 }
- 21214 if (z == sp->s_firstdatazone) sp->s_zsearch = b; /* for next time */
- 21215 return(sp->s_firstdatazone - 1 + (zone_t) b);
- 21216 }
- 21219 /*===========================================================================*
- 21220 * free_zone *
- 21221 *===========================================================================*/
- 21222 PUBLIC void free_zone(dev, numb)
- 21223 dev_t dev; /* device where zone located */
- 21224 zone_t numb; /* zone to be returned */
- 21225 {
- 21226 /* Return a zone. */
- 21227
- 21228 register struct super_block *sp;
- 21229 bit_t bit;
- 21230
- 21231 /* Locate the appropriate super_block and return bit. */
- 21232 sp = get_super(dev);
- 21233 if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
- 21234 bit = (bit_t) (numb - (sp->s_firstdatazone - 1));
- 21235 free_bit(sp, ZMAP, bit);
- 21236 if (bit < sp->s_zsearch) sp->s_zsearch = bit;
- 21237 }
- 21240 /*===========================================================================*
- 21241 * rw_block *
- 21242 *===========================================================================*/
- 21243 PUBLIC void rw_block(bp, rw_flag)
- 21244 register struct buf *bp; /* buffer pointer */
- 21245 int rw_flag; /* READING or WRITING */
- 21246 {
- 21247 /* Read or write a disk block. This is the only routine in which actual disk
- 21248 * I/O is invoked. If an error occurs, a message is printed here, but the error
- 21249 * is not reported to the caller. If the error occurred while purging a block
- 21250 * from the cache, it is not clear what the caller could do about it anyway.
- 21251 */
- 21252
- 21253 int r, op;
- 21254 off_t pos;
- 21255 dev_t dev;
- 21256
- 21257 if ( (dev = bp->b_dev) != NO_DEV) {
- 21258 pos = (off_t) bp->b_blocknr * BLOCK_SIZE;
- 21259 op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
- 21260 r = dev_io(op, FALSE, dev, pos, BLOCK_SIZE, FS_PROC_NR, bp->b_data);
- 21261 if (r != BLOCK_SIZE) {
- 21262 if (r >= 0) r = END_OF_FILE;
- 21263 if (r != END_OF_FILE)
- 21264 printf("Unrecoverable disk error on device %d/%d, block %ldn",
- 21265 (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
- 21266 bp->b_dev = NO_DEV; /* invalidate block */
- 21267
- 21268 /* Report read errors to interested parties. */
- 21269 if (rw_flag == READING) rdwt_err = r;
- 21270 }
- 21271 }
- 21272
- 21273 bp->b_dirt = CLEAN;
- 21274 }
- 21277 /*===========================================================================*
- 21278 * invalidate *
- 21279 *===========================================================================*/
- 21280 PUBLIC void invalidate(device)
- 21281 dev_t device; /* device whose blocks are to be purged */
- 21282 {
- 21283 /* Remove all the blocks belonging to some device from the cache. */
- 21284
- 21285 register struct buf *bp;
- 21286
- 21287 for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
- 21288 if (bp->b_dev == device) bp->b_dev = NO_DEV;
- 21289 }
- 21292 /*==========================================================================*
- 21293 * flushall *
- 21294 *==========================================================================*/
- 21295 PUBLIC void flushall(dev)
- 21296 dev_t dev; /* device to flush */
- 21297 {
- 21298 /* Flush all dirty blocks for one device. */
- 21299
- 21300 register struct buf *bp;
- 21301 static struct buf *dirty[NR_BUFS]; /* static so it isn't on stack */
- 21302 int ndirty;
- 21303
- 21304 for (bp = &buf[0], ndirty = 0; bp < &buf[NR_BUFS]; bp++)
- 21305 if (bp->b_dirt == DIRTY && bp->b_dev == dev) dirty[ndirty++] = bp;
- 21306 rw_scattered(dev, dirty, ndirty, WRITING);
- 21307 }
- 21310 /*===========================================================================*
- 21311 * rw_scattered *
- 21312 *===========================================================================*/
- 21313 PUBLIC void rw_scattered(dev, bufq, bufqsize, rw_flag)
- 21314 dev_t dev; /* major-minor device number */
- 21315 struct buf **bufq; /* pointer to array of buffers */
- 21316 int bufqsize; /* number of buffers */
- 21317 int rw_flag; /* READING or WRITING */
- 21318 {
- 21319 /* Read or write scattered data from a device. */
- 21320
- 21321 register struct buf *bp;
- 21322 int gap;
- 21323 register int i;
- 21324 register struct iorequest_s *iop;
- 21325 static struct iorequest_s iovec[NR_IOREQS]; /* static so it isn't on stack */
- 21326 int j;
- 21327
- 21328 /* (Shell) sort buffers on b_blocknr. */
- 21329 gap = 1;
- 21330 do
- 21331 gap = 3 * gap + 1;
- 21332 while (gap <= bufqsize);
- 21333 while (gap != 1) {
- 21334 gap /= 3;
- 21335 for (j = gap; j < bufqsize; j++) {
- 21336 for (i = j - gap;
- 21337 i >= 0 && bufq[i]->b_blocknr > bufq[i + gap]->b_blocknr;
- 21338 i -= gap) {
- 21339 bp = bufq[i];
- 21340 bufq[i] = bufq[i + gap];
- 21341 bufq[i + gap] = bp;
- 21342 }
- 21343 }
- 21344 }
- 21345
- 21346 /* Set up i/o vector and do i/o. The result of dev_io is discarded because
- 21347 * all results are returned in the vector. If dev_io fails completely, the
- 21348 * vector is unchanged and all results are taken as errors.
- 21349 */
- 21350 while (bufqsize > 0) {
- 21351 for (j = 0, iop = iovec; j < NR_IOREQS && j < bufqsize; j++, iop++) {
- 21352 bp = bufq[j];
- 21353 iop->io_position = (off_t) bp->b_blocknr * BLOCK_SIZE;
- 21354 iop->io_buf = bp->b_data;
- 21355 iop->io_nbytes = BLOCK_SIZE;
- 21356 iop->io_request = rw_flag == WRITING ?
- 21357 DEV_WRITE : DEV_READ | OPTIONAL_IO;
- 21358 }
- 21359 (void) dev_io(SCATTERED_IO, 0, dev, (off_t) 0, j, FS_PROC_NR,
- 21360 (char *) iovec);
- 21361
- 21362 /* Harvest the results. Leave read errors for rw_block() to complain. */
- 21363 for (i = 0, iop = iovec; i < j; i++, iop++) {
- 21364 bp = bufq[i];
- 21365 if (rw_flag == READING) {
- 21366 if (iop->io_nbytes == 0)
- 21367 bp->b_dev = dev; /* validate block */
- 21368 put_block(bp, PARTIAL_DATA_BLOCK);
- 21369 } else {
- 21370 if (iop->io_nbytes != 0) {
- 21371 printf("Unrecoverable write error on device %d/%d, block %ldn",
- 21372 (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
- 21373 bp->b_dev = NO_DEV; /* invalidate block */
- 21374 }
- 21375 bp->b_dirt = CLEAN;
- 21376 }
- 21377 }
- 21378 bufq += j;
- 21379 bufqsize -= j;
- 21380 }
- 21381 }
- 21384 /*===========================================================================*
- 21385 * rm_lru *
- 21386 *===========================================================================*/
- 21387 PRIVATE void rm_lru(bp)
- 21388 struct buf *bp;
- 21389 {
- 21390 /* Remove a block from its LRU chain. */
- 21391
- 21392 struct buf *next_ptr, *prev_ptr;
- 21393
- 21394 bufs_in_use++;
- 21395 next_ptr = bp->b_next; /* successor on LRU chain */
- 21396 prev_ptr = bp->b_prev; /* predecessor on LRU chain */
- 21397 if (prev_ptr != NIL_BUF)
- 21398 prev_ptr->b_next = next_ptr;
- 21399 else
- 21400 front = next_ptr; /* this block was at front of chain */
- 21401
- 21402 if (next_ptr != NIL_BUF)
- 21403 next_ptr->b_prev = prev_ptr;
- 21404 else
- 21405 rear = prev_ptr; /* this block was at rear of chain */
- 21406 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/inode.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 21500 /* This file manages the inode table. There are procedures to allocate and
- 21501 * deallocate inodes, acquire, erase, and release them, and read and write
- 21502 * them from the disk.
- 21503 *
- 21504 * The entry points into this file are
- 21505 * get_inode: search inode table for a given inode; if not there, read it
- 21506 * put_inode: indicate that an inode is no longer needed in memory
- 21507 * alloc_inode: allocate a new, unused inode
- 21508 * wipe_inode: erase some fields of a newly allocated inode
- 21509 * free_inode: mark an inode as available for a new file
- 21510 * update_times: update atime, ctime, and mtime
- 21511 * rw_inode: read a disk block and extract an inode, or corresp. write
- 21512 * old_icopy: copy to/from in-core inode struct and disk inode (V1.x)
- 21513 * new_icopy: copy to/from in-core inode struct and disk inode (V2.x)
- 21514 * dup_inode: indicate that someone else is using an inode table entry
- 21515 */
- 21516
- 21517 #include "fs.h"
- 21518 #include <minix/boot.h>
- 21519 #include "buf.h"
- 21520 #include "file.h"
- 21521 #include "fproc.h"
- 21522 #include "inode.h"
- 21523 #include "super.h"
- 21524
- 21525 FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
- 21526 int direction, int norm));
- 21527 FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
- 21528 int direction, int norm));
- 21529
- 21530
- 21531 /*===========================================================================*
- 21532 * get_inode *
- 21533 *===========================================================================*/
- 21534 PUBLIC struct inode *get_inode(dev, numb)
- 21535 dev_t dev; /* device on which inode resides */
- 21536 int numb; /* inode number (ANSI: may not be unshort) */
- 21537 {
- 21538 /* Find a slot in the inode table, load the specified inode into it, and
- 21539 * return a pointer to the slot. If 'dev' == NO_DEV, just return a free slot.
- 21540 */
- 21541
- 21542 register struct inode *rip, *xp;
- 21543
- 21544 /* Search the inode table both for (dev, numb) and a free slot. */
- 21545 xp = NIL_INODE;
- 21546 for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
- 21547 if (rip->i_count > 0) { /* only check used slots for (dev, numb) */
- 21548 if (rip->i_dev == dev && rip->i_num == numb) {
- 21549 /* This is the inode that we are looking for. */
- 21550 rip->i_count++;
- 21551 return(rip); /* (dev, numb) found */
- 21552 }
- 21553 } else {
- 21554 xp = rip; /* remember this free slot for later */
- 21555 }
- 21556 }
- 21557
- 21558 /* Inode we want is not currently in use. Did we find a free slot? */
- 21559 if (xp == NIL_INODE) { /* inode table completely full */
- 21560 err_code = ENFILE;
- 21561 return(NIL_INODE);
- 21562 }
- 21563
- 21564 /* A free inode slot has been located. Load the inode into it. */
- 21565 xp->i_dev = dev;
- 21566 xp->i_num = numb;
- 21567 xp->i_count = 1;
- 21568 if (dev != NO_DEV) rw_inode(xp, READING); /* get inode from disk */
- 21569 xp->i_update = 0; /* all the times are initially up-to-date */
- 21570
- 21571 return(xp);
- 21572 }
- 21575 /*===========================================================================*
- 21576 * put_inode *
- 21577 *===========================================================================*/
- 21578 PUBLIC void put_inode(rip)
- 21579 register struct inode *rip; /* pointer to inode to be released */
- 21580 {
- 21581 /* The caller is no longer using this inode. If no one else is using it either
- 21582 * write it back to the disk immediately. If it has no links, truncate it and
- 21583 * return it to the pool of available inodes.
- 21584 */
- 21585
- 21586 if (rip == NIL_INODE) return; /* checking here is easier than in caller */
- 21587 if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */
- 21588 if ((rip->i_nlinks & BYTE) == 0) {
- 21589 /* i_nlinks == 0 means free the inode. */
- 21590 truncate(rip); /* return all the disk blocks */
- 21591 rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */
- 21592 rip->i_dirt = DIRTY;
- 21593 free_inode(rip->i_dev, rip->i_num);
- 21594 } else {
- 21595 if (rip->i_pipe == I_PIPE) truncate(rip);
- 21596 }
- 21597 rip->i_pipe = NO_PIPE; /* should always be cleared */
- 21598 if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
- 21599 }
- 21600 }
- 21602 /*===========================================================================*
- 21603 * alloc_inode *
- 21604 *===========================================================================*/
- 21605 PUBLIC struct inode *alloc_inode(dev, bits)
- 21606 dev_t dev; /* device on which to allocate the inode */
- 21607 mode_t bits; /* mode of the inode */
- 21608 {
- 21609 /* Allocate a free inode on 'dev', and return a pointer to it. */
- 21610
- 21611 register struct inode *rip;
- 21612 register struct super_block *sp;
- 21613 int major, minor, inumb;
- 21614 bit_t b;
- 21615
- 21616 sp = get_super(dev); /* get pointer to super_block */
- 21617 if (sp->s_rd_only) { /* can't allocate an inode on a read only device. */
- 21618 err_code = EROFS;
- 21619 return(NIL_INODE);
- 21620 }
- 21621
- 21622 /* Acquire an inode from the bit map. */
- 21623 b = alloc_bit(sp, IMAP, sp->s_isearch);
- 21624 if (b == NO_BIT) {
- 21625 err_code = ENFILE;
- 21626 major = (int) (sp->s_dev >> MAJOR) & BYTE;
- 21627 minor = (int) (sp->s_dev >> MINOR) & BYTE;
- 21628 printf("Out of i-nodes on %sdevice %d/%dn",
- 21629 sp->s_dev == ROOT_DEV ? "root " : "", major, minor);
- 21630 return(NIL_INODE);
- 21631 }
- 21632 sp->s_isearch = b; /* next time start here */
- 21633 inumb = (int) b; /* be careful not to pass unshort as param */
- 21634
- 21635 /* Try to acquire a slot in the inode table. */
- 21636 if ((rip = get_inode(NO_DEV, inumb)) == NIL_INODE) {
- 21637 /* No inode table slots available. Free the inode just allocated. */
- 21638 free_bit(sp, IMAP, b);
- 21639 } else {
- 21640 /* An inode slot is available. Put the inode just allocated into it. */
- 21641 rip->i_mode = bits; /* set up RWX bits */
- 21642 rip->i_nlinks = (nlink_t) 0; /* initial no links */
- 21643 rip->i_uid = fp->fp_effuid; /* file's uid is owner's */
- 21644 rip->i_gid = fp->fp_effgid; /* ditto group id */
- 21645 rip->i_dev = dev; /* mark which device it is on */
- 21646 rip->i_ndzones = sp->s_ndzones; /* number of direct zones */
- 21647 rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/
- 21648 rip->i_sp = sp; /* pointer to super block */
- 21649
- 21650 /* Fields not cleared already are cleared in wipe_inode(). They have
- 21651 * been put there because truncate() needs to clear the same fields if
- 21652 * the file happens to be open while being truncated. It saves space
- 21653 * not to repeat the code twice.
- 21654 */
- 21655 wipe_inode(rip);
- 21656 }
- 21657
- 21658 return(rip);
- 21659 }
- 21661 /*===========================================================================*
- 21662 * wipe_inode *
- 21663 *===========================================================================*/
- 21664 PUBLIC void wipe_inode(rip)
- 21665 register struct inode *rip; /* the inode to be erased */
- 21666 {
- 21667 /* Erase some fields in the inode. This function is called from alloc_inode()
- 21668 * when a new inode is to be allocated, and from truncate(), when an existing
- 21669 * inode is to be truncated.
- 21670 */
- 21671
- 21672 register int i;
- 21673
- 21674 rip->i_size = 0;
- 21675 rip->i_update = ATIME | CTIME | MTIME; /* update all times later */
- 21676 rip->i_dirt = DIRTY;
- 21677 for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
- 21678 }
- 21681 /*===========================================================================*
- 21682 * free_inode *
- 21683 *===========================================================================*/
- 21684 PUBLIC void free_inode(dev, inumb)
- 21685 dev_t dev; /* on which device is the inode */
- 21686 ino_t inumb; /* number of inode to be freed */
- 21687 {
- 21688 /* Return an inode to the pool of unallocated inodes. */
- 21689
- 21690 register struct super_block *sp;
- 21691 bit_t b;
- 21692
- 21693 /* Locate the appropriate super_block. */
- 21694 sp = get_super(dev);
- 21695 if (inumb <= 0 || inumb > sp->s_ninodes) return;
- 21696 b = inumb;
- 21697 free_bit(sp, IMAP, b);
- 21698 if (b < sp->s_isearch) sp->s_isearch = b;
- 21699 }
- 21701 /*===========================================================================*
- 21702 * update_times *
- 21703 *===========================================================================*/
- 21704 PUBLIC void update_times(rip)
- 21705 register struct inode *rip; /* pointer to inode to be read/written */
- 21706 {
- 21707 /* Various system calls are required by the standard to update atime, ctime,
- 21708 * or mtime. Since updating a time requires sending a message to the clock
- 21709 * task--an expensive business--the times are marked for update by setting
- 21710 * bits in i_update. When a stat, fstat, or sync is done, or an inode is
- 21711 * released, update_times() may be called to actually fill in the times.
- 21712 */
- 21713
- 21714 time_t cur_time;
- 21715 struct super_block *sp;
- 21716
- 21717 sp = rip->i_sp; /* get pointer to super block. */
- 21718 if (sp->s_rd_only) return; /* no updates for read-only file systems */
- 21719
- 21720 cur_time = clock_time();
- 21721 if (rip->i_update & ATIME) rip->i_atime = cur_time;
- 21722 if (rip->i_update & CTIME) rip->i_ctime = cur_time;
- 21723 if (rip->i_update & MTIME) rip->i_mtime = cur_time;
- 21724 rip->i_update = 0; /* they are all up-to-date now */
- 21725 }
- 21728 /*===========================================================================*
- 21729 * rw_inode *
- 21730 *===========================================================================*/
- 21731 PUBLIC void rw_inode(rip, rw_flag)
- 21732 register struct inode *rip; /* pointer to inode to be read/written */
- 21733 int rw_flag; /* READING or WRITING */
- 21734 {
- 21735 /* An entry in the inode table is to be copied to or from the disk. */
- 21736
- 21737 register struct buf *bp;
- 21738 register struct super_block *sp;
- 21739 d1_inode *dip;
- 21740 d2_inode *dip2;
- 21741 block_t b, offset;
- 21742
- 21743 /* Get the block where the inode resides. */
- 21744 sp = get_super(rip->i_dev); /* get pointer to super block */
- 21745 rip->i_sp = sp; /* inode must contain super block pointer */
- 21746 offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
- 21747 b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
- 21748 bp = get_block(rip->i_dev, b, NORMAL);
- 21749 dip = bp->b_v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
- 21750 dip2 = bp->b_v2_ino + (rip->i_num - 1) % V2_INODES_PER_BLOCK;
- 21751
- 21752 /* Do the read or write. */
- 21753 if (rw_flag == WRITING) {
- 21754 if (rip->i_update) update_times(rip); /* times need updating */
- 21755 if (sp->s_rd_only == FALSE) bp->b_dirt = DIRTY;
- 21756 }
- 21757
- 21758 /* Copy the inode from the disk block to the in-core table or vice versa.
- 21759 * If the fourth parameter below is FALSE, the bytes are swapped.
- 21760 */
- 21761 if (sp->s_version == V1)
- 21762 old_icopy(rip, dip, rw_flag, sp->s_native);
- 21763 else
- 21764 new_icopy(rip, dip2, rw_flag, sp->s_native);
- 21765
- 21766 put_block(bp, INODE_BLOCK);
- 21767 rip->i_dirt = CLEAN;
- 21768 }
- 21771 /*===========================================================================*
- 21772 * old_icopy *
- 21773 *===========================================================================*/
- 21774 PRIVATE void old_icopy(rip, dip, direction, norm)
- 21775 register struct inode *rip; /* pointer to the in-core inode struct */
- 21776 register d1_inode *dip; /* pointer to the d1_inode inode struct */
- 21777 int direction; /* READING (from disk) or WRITING (to disk) */
- 21778 int norm; /* TRUE = do not swap bytes; FALSE = swap */
- 21779
- 21780 {
- 21781 /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
- 21782 * 68000) all have different inode layouts. When an inode is read or written
- 21783 * this routine handles the conversions so that the information in the inode
- 21784 * table is independent of the disk structure from which the inode came.
- 21785 * The old_icopy routine copies to and from V1 disks.
- 21786 */
- 21787
- 21788 int i;
- 21789
- 21790 if (direction == READING) {
- 21791 /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
- 21792 rip->i_mode = conv2(norm, (int) dip->d1_mode);
- 21793 rip->i_uid = conv2(norm, (int) dip->d1_uid );
- 21794 rip->i_size = conv4(norm, dip->d1_size);
- 21795 rip->i_mtime = conv4(norm, dip->d1_mtime);
- 21796 rip->i_atime = rip->i_mtime;
- 21797 rip->i_ctime = rip->i_mtime;
- 21798 rip->i_nlinks = (nlink_t) dip->d1_nlinks; /* 1 char */
- 21799 rip->i_gid = (gid_t) dip->d1_gid; /* 1 char */
- 21800 rip->i_ndzones = V1_NR_DZONES;
- 21801 rip->i_nindirs = V1_INDIRECTS;
- 21802 for (i = 0; i < V1_NR_TZONES; i++)
- 21803 rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
- 21804 } else {
- 21805 /* Copying V1.x inode to disk from the in-core table. */
- 21806 dip->d1_mode = conv2(norm, (int) rip->i_mode);
- 21807 dip->d1_uid = conv2(norm, (int) rip->i_uid );
- 21808 dip->d1_size = conv4(norm, rip->i_size);
- 21809 dip->d1_mtime = conv4(norm, rip->i_mtime);
- 21810 dip->d1_nlinks = (nlink_t) rip->i_nlinks; /* 1 char */
- 21811 dip->d1_gid = (gid_t) rip->i_gid; /* 1 char */
- 21812 for (i = 0; i < V1_NR_TZONES; i++)
- 21813 dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
- 21814 }
- 21815 }
- 21818 /*===========================================================================*
- 21819 * new_icopy *
- 21820 *===========================================================================*/
- 21821 PRIVATE void new_icopy(rip, dip, direction, norm)
- 21822 register struct inode *rip; /* pointer to the in-core inode struct */
- 21823 register d2_inode *dip; /* pointer to the d2_inode struct */
- 21824 int direction; /* READING (from disk) or WRITING (to disk) */
- 21825 int norm; /* TRUE = do not swap bytes; FALSE = swap */
- 21826
- 21827 {
- 21828 /* Same as old_icopy, but to/from V2 disk layout. */
- 21829
- 21830 int i;
- 21831
- 21832 if (direction == READING) {
- 21833 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
- 21834 rip->i_mode = conv2(norm,dip->d2_mode);
- 21835 rip->i_uid = conv2(norm,dip->d2_uid );
- 21836 rip->i_nlinks = conv2(norm,(int) dip->d2_nlinks);
- 21837 rip->i_gid = conv2(norm,(int) dip->d2_gid );
- 21838 rip->i_size = conv4(norm,dip->d2_size);
- 21839 rip->i_atime = conv4(norm,dip->d2_atime);
- 21840 rip->i_ctime = conv4(norm,dip->d2_ctime);
- 21841 rip->i_mtime = conv4(norm,dip->d2_mtime);
- 21842 rip->i_ndzones = V2_NR_DZONES;
- 21843 rip->i_nindirs = V2_INDIRECTS;
- 21844 for (i = 0; i < V2_NR_TZONES; i++)
- 21845 rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
- 21846 } else {
- 21847 /* Copying V2.x inode to disk from the in-core table. */
- 21848 dip->d2_mode = conv2(norm,rip->i_mode);
- 21849 dip->d2_uid = conv2(norm,rip->i_uid );
- 21850 dip->d2_nlinks = conv2(norm,rip->i_nlinks);
- 21851 dip->d2_gid = conv2(norm,rip->i_gid );
- 21852 dip->d2_size = conv4(norm,rip->i_size);
- 21853 dip->d2_atime = conv4(norm,rip->i_atime);
- 21854 dip->d2_ctime = conv4(norm,rip->i_ctime);
- 21855 dip->d2_mtime = conv4(norm,rip->i_mtime);
- 21856 for (i = 0; i < V2_NR_TZONES; i++)
- 21857 dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
- 21858 }
- 21859 }
- 21862 /*===========================================================================*
- 21863 * dup_inode *
- 21864 *===========================================================================*/
- 21865 PUBLIC void dup_inode(ip)
- 21866 struct inode *ip; /* The inode to be duplicated. */
- 21867 {
- 21868 /* This routine is a simplified form of get_inode() for the case where
- 21869 * the inode pointer is already known.
- 21870 */
- 21871
- 21872 ip->i_count++;
- 21873 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/super.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 21900 /* This file manages the super block table and the related data structures,
- 21901 * namely, the bit maps that keep track of which zones and which inodes are
- 21902 * allocated and which are free. When a new inode or zone is needed, the
- 21903 * appropriate bit map is searched for a free entry.
- 21904 *
- 21905 * The entry points into this file are
- 21906 * alloc_bit: somebody wants to allocate a zone or inode; find one
- 21907 * free_bit: indicate that a zone or inode is available for allocation
- 21908 * get_super: search the 'superblock' table for a device
- 21909 * mounted: tells if file inode is on mounted (or ROOT) file system
- 21910 * read_super: read a superblock
- 21911 */
- 21912
- 21913 #include "fs.h"
- 21914 #include <string.h>
- 21915 #include <minix/boot.h>
- 21916 #include "buf.h"
- 21917 #include "inode.h"
- 21918 #include "super.h"
- 21919
- 21920 #define BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT)
- 21921 #define BITS_PER_BLOCK (BITMAP_CHUNKS * BITCHUNK_BITS)
- 21922
- 21923 /*===========================================================================*
- 21924 * alloc_bit *
- 21925 *===========================================================================*/
- 21926 PUBLIC bit_t alloc_bit(sp, map, origin)
- 21927 struct super_block *sp; /* the filesystem to allocate from */
- 21928 int map; /* IMAP (inode map) or ZMAP (zone map) */
- 21929 bit_t origin; /* number of bit to start searching at */
- 21930 {
- 21931 /* Allocate a bit from a bit map and return its bit number. */
- 21932
- 21933 block_t start_block; /* first bit block */
- 21934 bit_t map_bits; /* how many bits are there in the bit map? */
- 21935 unsigned bit_blocks; /* how many blocks are there in the bit map? */
- 21936 unsigned block, word, bcount, wcount;
- 21937 struct buf *bp;
- 21938 bitchunk_t *wptr, *wlim, k;
- 21939 bit_t i, b;
- 21940
- 21941 if (sp->s_rd_only)
- 21942 panic("can't allocate bit on read-only filesys.", NO_NUM);
- 21943
- 21944 if (map == IMAP) {
- 21945 start_block = SUPER_BLOCK + 1;
- 21946 map_bits = sp->s_ninodes + 1;
- 21947 bit_blocks = sp->s_imap_blocks;
- 21948 } else {
- 21949 start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
- 21950 map_bits = sp->s_zones - (sp->s_firstdatazone - 1);
- 21951 bit_blocks = sp->s_zmap_blocks;
- 21952 }
- 21953
- 21954 /* Figure out where to start the bit search (depends on 'origin'). */
- 21955 if (origin >= map_bits) origin = 0; /* for robustness */
- 21956
- 21957 /* Locate the starting place. */
- 21958 block = origin / BITS_PER_BLOCK;
- 21959 word = (origin % BITS_PER_BLOCK) / BITCHUNK_BITS;
- 21960
- 21961 /* Iterate over all blocks plus one, because we start in the middle. */
- 21962 bcount = bit_blocks + 1;
- 21963 do {
- 21964 bp = get_block(sp->s_dev, start_block + block, NORMAL);
- 21965 wlim = &bp->b_bitmap[BITMAP_CHUNKS];
- 21966
- 21967 /* Iterate over the words in block. */
- 21968 for (wptr = &bp->b_bitmap[word]; wptr < wlim; wptr++) {
- 21969
- 21970 /* Does this word contain a free bit? */
- 21971 if (*wptr == (bitchunk_t) ~0) continue;
- 21972
- 21973 /* Find and allocate the free bit. */
- 21974 k = conv2(sp->s_native, (int) *wptr);
- 21975 for (i = 0; (k & (1 << i)) != 0; ++i) {}
- 21976
- 21977 /* Bit number from the start of the bit map. */
- 21978 b = ((bit_t) block * BITS_PER_BLOCK)
- 21979 + (wptr - &bp->b_bitmap[0]) * BITCHUNK_BITS
- 21980 + i;
- 21981
- 21982 /* Don't allocate bits beyond the end of the map. */
- 21983 if (b >= map_bits) break;
- 21984
- 21985 /* Allocate and return bit number. */
- 21986 k |= 1 << i;
- 21987 *wptr = conv2(sp->s_native, (int) k);
- 21988 bp->b_dirt = DIRTY;
- 21989 put_block(bp, MAP_BLOCK);
- 21990 return(b);
- 21991 }
- 21992 put_block(bp, MAP_BLOCK);
- 21993 if (++block >= bit_blocks) block = 0; /* last block, wrap around */
- 21994 word = 0;
- 21995 } while (--bcount > 0);
- 21996 return(NO_BIT); /* no bit could be allocated */
- 21997 }
- 22000 /*===========================================================================*
- 22001 * free_bit *
- 22002 *===========================================================================*/
- 22003 PUBLIC void free_bit(sp, map, bit_returned)
- 22004 struct super_block *sp; /* the filesystem to operate on */
- 22005 int map; /* IMAP (inode map) or ZMAP (zone map) */
- 22006 bit_t bit_returned; /* number of bit to insert into the map */
- 22007 {
- 22008 /* Return a zone or inode by turning off its bitmap bit. */
- 22009
- 22010 unsigned block, word, bit;
- 22011 struct buf *bp;
- 22012 bitchunk_t k, mask;
- 22013 block_t start_block;
- 22014
- 22015 if (sp->s_rd_only)
- 22016 panic("can't free bit on read-only filesys.", NO_NUM);
- 22017
- 22018 if (map == IMAP) {
- 22019 start_block = SUPER_BLOCK + 1;
- 22020 } else {
- 22021 start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
- 22022 }
- 22023 block = bit_returned / BITS_PER_BLOCK;
- 22024 word = (bit_returned % BITS_PER_BLOCK) / BITCHUNK_BITS;
- 22025 bit = bit_returned % BITCHUNK_BITS;
- 22026 mask = 1 << bit;
- 22027
- 22028 bp = get_block(sp->s_dev, start_block + block, NORMAL);
- 22029
- 22030 k = conv2(sp->s_native, (int) bp->b_bitmap[word]);
- 22031 if (!(k & mask)) {
- 22032 panic(map == IMAP ? "tried to free unused inode" :
- 22033 "tried to free unused block", NO_NUM);
- 22034 }
- 22035
- 22036 k &= ~mask;
- 22037 bp->b_bitmap[word] = conv2(sp->s_native, (int) k);
- 22038 bp->b_dirt = DIRTY;
- 22039
- 22040 put_block(bp, MAP_BLOCK);
- 22041 }
- 22044 /*===========================================================================*
- 22045 * get_super *
- 22046 *===========================================================================*/
- 22047 PUBLIC struct super_block *get_super(dev)
- 22048 dev_t dev; /* device number whose super_block is sought */
- 22049 {
- 22050 /* Search the superblock table for this device. It is supposed to be there. */
- 22051
- 22052 register struct super_block *sp;
- 22053
- 22054 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
- 22055 if (sp->s_dev == dev) return(sp);
- 22056
- 22057 /* Search failed. Something wrong. */
- 22058 panic("can't find superblock for device (in decimal)", (int) dev);
- 22059
- 22060 return(NIL_SUPER); /* to keep the compiler and lint quiet */
- 22061 }
- 22064 /*===========================================================================*
- 22065 * mounted *
- 22066 *===========================================================================*/
- 22067 PUBLIC int mounted(rip)
- 22068 register struct inode *rip; /* pointer to inode */
- 22069 {
- 22070 /* Report on whether the given inode is on a mounted (or ROOT) file system. */
- 22071
- 22072 register struct super_block *sp;
- 22073 register dev_t dev;
- 22074
- 22075 dev = (dev_t) rip->i_zone[0];
- 22076 if (dev == ROOT_DEV) return(TRUE); /* inode is on root file system */
- 22077
- 22078 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
- 22079 if (sp->s_dev == dev) return(TRUE);
- 22080
- 22081 return(FALSE);
- 22082 }
- 22085 /*===========================================================================*
- 22086 * read_super *
- 22087 *===========================================================================*/
- 22088 PUBLIC int read_super(sp)
- 22089 register struct super_block *sp; /* pointer to a superblock */
- 22090 {
- 22091 /* Read a superblock. */
- 22092
- 22093 register struct buf *bp;
- 22094 dev_t dev;
- 22095 int magic;
- 22096 int version, native;
- 22097
- 22098 dev = sp->s_dev; /* save device (will be overwritten by copy) */
- 22099 bp = get_block(sp->s_dev, SUPER_BLOCK, NORMAL);
- 22100 memcpy( (char *) sp, bp->b_data, (size_t) SUPER_SIZE);
- 22101 put_block(bp, ZUPER_BLOCK);
- 22102 sp->s_dev = NO_DEV; /* restore later */
- 22103 magic = sp->s_magic; /* determines file system type */
- 22104
- 22105 /* Get file system version and type. */
- 22106 if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP, SUPER_MAGIC)) {
- 22107 version = V1;
- 22108 native = (magic == SUPER_MAGIC);
- 22109 } else if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP, SUPER_V2)) {
- 22110 version = V2;
- 22111 native = (magic == SUPER_V2);
- 22112 } else {
- 22113 return(EINVAL);
- 22114 }
- 22115
- 22116 /* If the super block has the wrong byte order, swap the fields; the magic
- 22117 * number doesn't need conversion. */
- 22118 sp->s_ninodes = conv2(native, (int) sp->s_ninodes);
- 22119 sp->s_nzones = conv2(native, (int) sp->s_nzones);
- 22120 sp->s_imap_blocks = conv2(native, (int) sp->s_imap_blocks);
- 22121 sp->s_zmap_blocks = conv2(native, (int) sp->s_zmap_blocks);
- 22122 sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
- 22123 sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
- 22124 sp->s_max_size = conv4(native, sp->s_max_size);
- 22125 sp->s_zones = conv4(native, sp->s_zones);
- 22126
- 22127 /* In V1, the device size was kept in a short, s_nzones, which limited
- 22128 * devices to 32K zones. For V2, it was decided to keep the size as a
- 22129 * long. However, just changing s_nzones to a long would not work, since
- 22130 * then the position of s_magic in the super block would not be the same
- 22131 * in V1 and V2 file systems, and there would be no way to tell whether
- 22132 * a newly mounted file system was V1 or V2. The solution was to introduce
- 22133 * a new variable, s_zones, and copy the size there.
- 22134 *
- 22135 * Calculate some other numbers that depend on the version here too, to
- 22136 * hide some of the differences.
- 22137 */
- 22138 if (version == V1) {
- 22139 sp->s_zones = sp->s_nzones; /* only V1 needs this copy */
- 22140 sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
- 22141 sp->s_ndzones = V1_NR_DZONES;
- 22142 sp->s_nindirs = V1_INDIRECTS;
- 22143 } else {
- 22144 sp->s_inodes_per_block = V2_INODES_PER_BLOCK;
- 22145 sp->s_ndzones = V2_NR_DZONES;
- 22146 sp->s_nindirs = V2_INDIRECTS;
- 22147 }
- 22148
- 22149 sp->s_isearch = 0; /* inode searches initially start at 0 */
- 22150 sp->s_zsearch = 0; /* zone searches initially start at 0 */
- 22151 sp->s_version = version;
- 22152 sp->s_native = native;
- 22153
- 22154 /* Make a few basic checks to see if super block looks reasonable. */
- 22155 if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
- 22156 || sp->s_ninodes < 1 || sp->s_zones < 1
- 22157 || (unsigned) sp->s_log_zone_size > 4) {
- 22158 return(EINVAL);
- 22159 }
- 22160 sp->s_dev = dev; /* restore device number */
- 22161 return(OK);
- 22162 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/filedes.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 22200 /* This file contains the procedures that manipulate file descriptors.
- 22201 *
- 22202 * The entry points into this file are
- 22203 * get_fd: look for free file descriptor and free filp slots
- 22204 * get_filp: look up the filp entry for a given file descriptor
- 22205 * find_filp: find a filp slot that points to a given inode
- 22206 */
- 22207
- 22208 #include "fs.h"
- 22209 #include "file.h"
- 22210 #include "fproc.h"
- 22211 #include "inode.h"
- 22212
- 22213 /*===========================================================================*
- 22214 * get_fd *
- 22215 *===========================================================================*/
- 22216 PUBLIC int get_fd(start, bits, k, fpt)
- 22217 int start; /* start of search (used for F_DUPFD) */
- 22218 mode_t bits; /* mode of the file to be created (RWX bits) */
- 22219 int *k; /* place to return file descriptor */
- 22220 struct filp **fpt; /* place to return filp slot */
- 22221 {
- 22222 /* Look for a free file descriptor and a free filp slot. Fill in the mode word
- 22223 * in the latter, but don't claim either one yet, since the open() or creat()
- 22224 * may yet fail.
- 22225 */
- 22226
- 22227 register struct filp *f;
- 22228 register int i;
- 22229
- 22230 *k = -1; /* we need a way to tell if file desc found */
- 22231
- 22232 /* Search the fproc fp_filp table for a free file descriptor. */
- 22233 for (i = start; i < OPEN_MAX; i++) {
- 22234 if (fp->fp_filp[i] == NIL_FILP) {
- 22235 /* A file descriptor has been located. */
- 22236 *k = i;
- 22237 break;
- 22238 }
- 22239 }
- 22240
- 22241 /* Check to see if a file descriptor has been found. */
- 22242 if (*k < 0) return(EMFILE); /* this is why we initialized k to -1 */
- 22243
- 22244 /* Now that a file descriptor has been found, look for a free filp slot. */
- 22245 for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
- 22246 if (f->filp_count == 0) {
- 22247 f->filp_mode = bits;
- 22248 f->filp_pos = 0L;
- 22249 f->filp_flags = 0;
- 22250 *fpt = f;
- 22251 return(OK);
- 22252 }
- 22253 }
- 22254
- 22255 /* If control passes here, the filp table must be full. Report that back. */
- 22256 return(ENFILE);
- 22257 }
- 22260 /*===========================================================================*
- 22261 * get_filp *
- 22262 *===========================================================================*/
- 22263 PUBLIC struct filp *get_filp(fild)
- 22264 int fild; /* file descriptor */
- 22265 {
- 22266 /* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
- 22267
- 22268 err_code = EBADF;
- 22269 if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP);
- 22270 return(fp->fp_filp[fild]); /* may also be NIL_FILP */
- 22271 }
- 22274 /*===========================================================================*
- 22275 * find_filp *
- 22276 *===========================================================================*/
- 22277 PUBLIC struct filp *find_filp(rip, bits)
- 22278 register struct inode *rip; /* inode referred to by the filp to be found */
- 22279 Mode_t bits; /* mode of the filp to be found (RWX bits) */
- 22280 {
- 22281 /* Find a filp slot that refers to the inode 'rip' in a way as described
- 22282 * by the mode bit 'bits'. Used for determining whether somebody is still
- 22283 * interested in either end of a pipe. Also used when opening a FIFO to
- 22284 * find partners to share a filp field with (to shared the file position).
- 22285 * Like 'get_fd' it performs its job by linear search through the filp table.
- 22286 */
- 22287
- 22288 register struct filp *f;
- 22289
- 22290 for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
- 22291 if (f->filp_count != 0 && f->filp_ino == rip && (f->filp_mode & bits)){
- 22292 return(f);
- 22293 }
- 22294 }
- 22295
- 22296 /* If control passes here, the filp wasn't there. Report that back. */
- 22297 return(NIL_FILP);
- 22298 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/lock.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 22300 /* This file handles advisory file locking as required by POSIX.
- 22301 *
- 22302 * The entry points into this file are
- 22303 * lock_op: perform locking operations for FCNTL system call
- 22304 * lock_revive: revive processes when a lock is released
- 22305 */
- 22306
- 22307 #include "fs.h"
- 22308 #include <fcntl.h>
- 22309 #include <unistd.h> /* cc runs out of memory with unistd.h :-( */
- 22310 #include "file.h"
- 22311 #include "fproc.h"
- 22312 #include "inode.h"
- 22313 #include "lock.h"
- 22314 #include "param.h"
- 22315
- 22316 /*===========================================================================*
- 22317 * lock_op *
- 22318 *===========================================================================*/
- 22319 PUBLIC int lock_op(f, req)
- 22320 struct filp *f;
- 22321 int req; /* either F_SETLK or F_SETLKW */
- 22322 {
- 22323 /* Perform the advisory locking required by POSIX. */
- 22324
- 22325 int r, ltype, i, conflict = 0, unlocking = 0;
- 22326 mode_t mo;
- 22327 off_t first, last;
- 22328 struct flock flock;
- 22329 vir_bytes user_flock;
- 22330 struct file_lock *flp, *flp2, *empty;
- 22331
- 22332 /* Fetch the flock structure from user space. */
- 22333 user_flock = (vir_bytes) name1;
- 22334 r = sys_copy(who, D, (phys_bytes) user_flock,
- 22335 FS_PROC_NR, D, (phys_bytes) &flock, (phys_bytes) sizeof(flock));
- 22336 if (r != OK) return(EINVAL);
- 22337
- 22338 /* Make some error checks. */
- 22339 ltype = flock.l_type;
- 22340 mo = f->filp_mode;
- 22341 if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
- 22342 if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
- 22343 if ( (f->filp_ino->i_mode & I_TYPE) != I_REGULAR) return(EINVAL);
- 22344 if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
- 22345 if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
- 22346
- 22347 /* Compute the first and last bytes in the lock region. */
- 22348 switch (flock.l_whence) {
- 22349 case SEEK_SET: first = 0; break;
- 22350 case SEEK_CUR: first = f->filp_pos; break;
- 22351 case SEEK_END: first = f->filp_ino->i_size; break;
- 22352 default: return(EINVAL);
- 22353 }
- 22354 /* Check for overflow. */
- 22355 if (((long)flock.l_start > 0) && ((first + flock.l_start) < first))
- 22356 return(EINVAL);
- 22357 if (((long)flock.l_start < 0) && ((first + flock.l_start) > first))
- 22358 return(EINVAL);
- 22359 first = first + flock.l_start;
- 22360 last = first + flock.l_len - 1;
- 22361 if (flock.l_len == 0) last = MAX_FILE_POS;
- 22362 if (last < first) return(EINVAL);
- 22363
- 22364 /* Check if this region conflicts with any existing lock. */
- 22365 empty = (struct file_lock *) 0;
- 22366 for (flp = &file_lock[0]; flp < & file_lock[NR_LOCKS]; flp++) {
- 22367 if (flp->lock_type == 0) {
- 22368 if (empty == (struct file_lock *) 0) empty = flp;
- 22369 continue; /* 0 means unused slot */
- 22370 }
- 22371 if (flp->lock_inode != f->filp_ino) continue; /* different file */
- 22372 if (last < flp->lock_first) continue; /* new one is in front */
- 22373 if (first > flp->lock_last) continue; /* new one is afterwards */
- 22374 if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
- 22375 if (ltype != F_UNLCK && flp->lock_pid == fp->fp_pid) continue;
- 22376
- 22377 /* There might be a conflict. Process it. */
- 22378 conflict = 1;
- 22379 if (req == F_GETLK) break;
- 22380
- 22381 /* If we are trying to set a lock, it just failed. */
- 22382 if (ltype == F_RDLCK || ltype == F_WRLCK) {
- 22383 if (req == F_SETLK) {
- 22384 /* For F_SETLK, just report back failure. */
- 22385 return(EAGAIN);
- 22386 } else {
- 22387 /* For F_SETLKW, suspend the process. */
- 22388 suspend(XLOCK);
- 22389 return(0);
- 22390 }
- 22391 }
- 22392
- 22393 /* We are clearing a lock and we found something that overlaps. */
- 22394 unlocking = 1;
- 22395 if (first <= flp->lock_first && last >= flp->lock_last) {
- 22396 flp->lock_type = 0; /* mark slot as unused */
- 22397 nr_locks--; /* number of locks is now 1 less */
- 22398 continue;
- 22399 }
- 22400
- 22401 /* Part of a locked region has been unlocked. */
- 22402 if (first <= flp->lock_first) {
- 22403 flp->lock_first = last + 1;
- 22404 continue;
- 22405 }
- 22406
- 22407 if (last >= flp->lock_last) {
- 22408 flp->lock_last = first - 1;
- 22409 continue;
- 22410 }
- 22411
- 22412 /* Bad luck. A lock has been split in two by unlocking the middle. */
- 22413 if (nr_locks == NR_LOCKS) return(ENOLCK);
- 22414 for (i = 0; i < NR_LOCKS; i++)
- 22415 if (file_lock[i].lock_type == 0) break;
- 22416 flp2 = &file_lock[i];
- 22417 flp2->lock_type = flp->lock_type;
- 22418 flp2->lock_pid = flp->lock_pid;
- 22419 flp2->lock_inode = flp->lock_inode;
- 22420 flp2->lock_first = last + 1;
- 22421 flp2->lock_last = flp->lock_last;
- 22422 flp->lock_last = first - 1;
- 22423 nr_locks++;
- 22424 }
- 22425 if (unlocking) lock_revive();
- 22426
- 22427 if (req == F_GETLK) {
- 22428 if (conflict) {
- 22429 /* GETLK and conflict. Report on the conflicting lock. */
- 22430 flock.l_type = flp->lock_type;
- 22431 flock.l_whence = SEEK_SET;
- 22432 flock.l_start = flp->lock_first;
- 22433 flock.l_len = flp->lock_last - flp->lock_first + 1;
- 22434 flock.l_pid = flp->lock_pid;
- 22435
- 22436 } else {
- 22437 /* It is GETLK and there is no conflict. */
- 22438 flock.l_type = F_UNLCK;
- 22439 }
- 22440
- 22441 /* Copy the flock structure back to the caller. */
- 22442 r = sys_copy(FS_PROC_NR, D, (phys_bytes) &flock,
- 22443 who, D, (phys_bytes) user_flock, (phys_bytes) sizeof(flock));
- 22444 return(r);
- 22445 }
- 22446
- 22447 if (ltype == F_UNLCK) return(OK); /* unlocked a region with no locks */
- 22448
- 22449 /* There is no conflict. If space exists, store new lock in the table. */
- 22450 if (empty == (struct file_lock *) 0) return(ENOLCK); /* table full */
- 22451 empty->lock_type = ltype;
- 22452 empty->lock_pid = fp->fp_pid;
- 22453 empty->lock_inode = f->filp_ino;
- 22454 empty->lock_first = first;
- 22455 empty->lock_last = last;
- 22456 nr_locks++;
- 22457 return(OK);
- 22458 }
- 22460 /*===========================================================================*
- 22461 * lock_revive *
- 22462 *===========================================================================*/
- 22463 PUBLIC void lock_revive()
- 22464 {
- 22465 /* Go find all the processes that are waiting for any kind of lock and
- 22466 * revive them all. The ones that are still blocked will block again when
- 22467 * they run. The others will complete. This strategy is a space-time
- 22468 * tradeoff. Figuring out exactly which ones to unblock now would take
- 22469 * extra code, and the only thing it would win would be some performance in
- 22470 * extremely rare circumstances (namely, that somebody actually used
- 22471 * locking).
- 22472 */
- 22473
- 22474 int task;
- 22475 struct fproc *fptr;
- 22476
- 22477 for (fptr = &fproc[INIT_PROC_NR + 1]; fptr < &fproc[NR_PROCS]; fptr++){
- 22478 task = -fptr->fp_task;
- 22479 if (fptr->fp_suspended == SUSPENDED && task == XLOCK) {
- 22480 revive( (int) (fptr - fproc), 0);
- 22481 }
- 22482 }
- 22483 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/main.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 22500 /* This file contains the main program of the File System. It consists of
- 22501 * a loop that gets messages requesting work, carries out the work, and sends
- 22502 * replies.
- 22503 *
- 22504 * The entry points into this file are
- 22505 * main: main program of the File System
- 22506 * reply: send a reply to a process after the requested work is done
- 22507 */
- 22508
- 22509 struct super_block; /* proto.h needs to know this */
- 22510
- 22511 #include "fs.h"
- 22512 #include <fcntl.h>
- 22513 #include <string.h>
- 22514 #include <sys/ioctl.h>
- 22515 #include <minix/callnr.h>
- 22516 #include <minix/com.h>
- 22517 #include <minix/boot.h>
- 22518 #include "buf.h"
- 22519 #include "dev.h"
- 22520 #include "file.h"
- 22521 #include "fproc.h"
- 22522 #include "inode.h"
- 22523 #include "param.h"
- 22524 #include "super.h"
- 22525
- 22526 FORWARD _PROTOTYPE( void buf_pool, (void) );
- 22527 FORWARD _PROTOTYPE( void fs_init, (void) );
- 22528 FORWARD _PROTOTYPE( void get_boot_parameters, (void) );
- 22529 FORWARD _PROTOTYPE( void get_work, (void) );
- 22530 FORWARD _PROTOTYPE( void load_ram, (void) );
- 22531 FORWARD _PROTOTYPE( void load_super, (Dev_t super_dev) );
- 22532
- 22533
- 22534 /*===========================================================================*
- 22535 * main *
- 22536 *===========================================================================*/
- 22537 PUBLIC void main()
- 22538 {
- 22539 /* This is the main program of the file system. The main loop consists of
- 22540 * three major activities: getting new work, processing the work, and sending
- 22541 * the reply. This loop never terminates as long as the file system runs.
- 22542 */
- 22543 int error;
- 22544
- 22545 fs_init();
- 22546
- 22547 /* This is the main loop that gets work, processes it, and sends replies. */
- 22548 while (TRUE) {
- 22549 get_work(); /* sets who and fs_call */
- 22550
- 22551 fp = &fproc[who]; /* pointer to proc table struct */
- 22552 super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
- 22553 dont_reply = FALSE; /* in other words, do reply is default */
- 22554
- 22555 /* Call the internal function that does the work. */
- 22556 if (fs_call < 0 || fs_call >= NCALLS)
- 22557 error = EBADCALL;
- 22558 else
- 22559 error = (*call_vector[fs_call])();
- 22560
- 22561 /* Copy the results back to the user and send reply. */
- 22562 if (dont_reply) continue;
- 22563 reply(who, error);
- 22564 if (rdahed_inode != NIL_INODE) read_ahead(); /* do block read ahead */
- 22565 }
- 22566 }
- 22569 /*===========================================================================*
- 22570 * get_work *
- 22571 *===========================================================================*/
- 22572 PRIVATE void get_work()
- 22573 {
- 22574 /* Normally wait for new input. However, if 'reviving' is
- 22575 * nonzero, a suspended process must be awakened.
- 22576 */
- 22577
- 22578 register struct fproc *rp;
- 22579
- 22580 if (reviving != 0) {
- 22581 /* Revive a suspended process. */
- 22582 for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
- 22583 if (rp->fp_revived == REVIVING) {
- 22584 who = (int)(rp - fproc);
- 22585 fs_call = rp->fp_fd & BYTE;
- 22586 fd = (rp->fp_fd >>8) & BYTE;
- 22587 buffer = rp->fp_buffer;
- 22588 nbytes = rp->fp_nbytes;
- 22589 rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
- 22590 rp->fp_revived = NOT_REVIVING;
- 22591 reviving--;
- 22592 return;
- 22593 }
- 22594 panic("get_work couldn't revive anyone", NO_NUM);
- 22595 }
- 22596
- 22597 /* Normal case. No one to revive. */
- 22598 if (receive(ANY, &m) != OK) panic("fs receive error", NO_NUM);
- 22599
- 22600 who = m.m_source;
- 22601 fs_call = m.m_type;
- 22602 }
- 22605 /*===========================================================================*
- 22606 * reply *
- 22607 *===========================================================================*/
- 22608 PUBLIC void reply(whom, result)
- 22609 int whom; /* process to reply to */
- 22610 int result; /* result of the call (usually OK or error #) */
- 22611 {
- 22612 /* Send a reply to a user process. It may fail (if the process has just
- 22613 * been killed by a signal), so don't check the return code. If the send
- 22614 * fails, just ignore it.
- 22615 */
- 22616
- 22617 reply_type = result;
- 22618 send(whom, &m1);
- 22619 }
- 22622 /*===========================================================================*
- 22623 * fs_init *
- 22624 *===========================================================================*/
- 22625 PRIVATE void fs_init()
- 22626 {
- 22627 /* Initialize global variables, tables, etc. */
- 22628
- 22629 register struct inode *rip;
- 22630 int i;
- 22631 message mess;
- 22632
- 22633 /* The following initializations are needed to let dev_opcl succeed .*/
- 22634 fp = (struct fproc *) NULL;
- 22635 who = FS_PROC_NR;
- 22636
- 22637 buf_pool(); /* initialize buffer pool */
- 22638 get_boot_parameters(); /* get the parameters from the menu */
- 22639 load_ram(); /* init RAM disk, load if it is root */
- 22640 load_super(ROOT_DEV); /* load super block for root device */
- 22641
- 22642 /* Initialize the 'fproc' fields for process 0 .. INIT. */
- 22643 for (i = 0; i <= LOW_USER; i+= 1) {
- 22644 if (i == FS_PROC_NR) continue; /* do not initialize FS */
- 22645 fp = &fproc[i];
- 22646 rip = get_inode(ROOT_DEV, ROOT_INODE);
- 22647 fp->fp_rootdir = rip;
- 22648 dup_inode(rip);
- 22649 fp->fp_workdir = rip;
- 22650 fp->fp_realuid = (uid_t) SYS_UID;
- 22651 fp->fp_effuid = (uid_t) SYS_UID;
- 22652 fp->fp_realgid = (gid_t) SYS_GID;
- 22653 fp->fp_effgid = (gid_t) SYS_GID;
- 22654 fp->fp_umask = ~0;
- 22655 }
- 22656
- 22657 /* Certain relations must hold for the file system to work at all. */
- 22658 if (SUPER_SIZE > BLOCK_SIZE) panic("SUPER_SIZE > BLOCK_SIZE", NO_NUM);
- 22659 if (BLOCK_SIZE % V2_INODE_SIZE != 0) /* this checks V1_INODE_SIZE too */
- 22660 panic("BLOCK_SIZE % V2_INODE_SIZE != 0", NO_NUM);
- 22661 if (OPEN_MAX > 127) panic("OPEN_MAX > 127", NO_NUM);
- 22662 if (NR_BUFS < 6) panic("NR_BUFS < 6", NO_NUM);
- 22663 if (V1_INODE_SIZE != 32) panic("V1 inode size != 32", NO_NUM);
- 22664 if (V2_INODE_SIZE != 64) panic("V2 inode size != 64", NO_NUM);
- 22665 if (OPEN_MAX > 8 * sizeof(long)) panic("Too few bits in fp_cloexec", NO_NUM);
- 22666
- 22667 /* Tell the memory task where my process table is for the sake of ps(1). */
- 22668 mess.m_type = DEV_IOCTL;
- 22669 mess.PROC_NR = FS_PROC_NR;
- 22670 mess.REQUEST = MIOCSPSINFO;
- 22671 mess.ADDRESS = (void *) fproc;
- 22672 (void) sendrec(MEM, &mess);
- 22673 }
- 22676 /*===========================================================================*
- 22677 * buf_pool *
- 22678 *===========================================================================*/
- 22679 PRIVATE void buf_pool()
- 22680 {
- 22681 /* Initialize the buffer pool. */
- 22682
- 22683 register struct buf *bp;
- 22684
- 22685 bufs_in_use = 0;
- 22686 front = &buf[0];
- 22687 rear = &buf[NR_BUFS - 1];
- 22688
- 22689 for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
- 22690 bp->b_blocknr = NO_BLOCK;
- 22691 bp->b_dev = NO_DEV;
- 22692 bp->b_next = bp + 1;
- 22693 bp->b_prev = bp - 1;
- 22694 }
- 22695 buf[0].b_prev = NIL_BUF;
- 22696 buf[NR_BUFS - 1].b_next = NIL_BUF;
- 22697
- 22698 for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
- 22699 buf_hash[0] = front;
- 22700 }
- 22703 /*===========================================================================*
- 22704 * get_boot_parameters *
- 22705 *===========================================================================*/
- 22706 PUBLIC struct bparam_s boot_parameters;
- 22707
- 22708 PRIVATE void get_boot_parameters()
- 22709 {
- 22710 /* Ask kernel for boot parameters. */
- 22711
- 22712 m1.m_type = SYS_GBOOT;
- 22713 m1.PROC1 = FS_PROC_NR;
- 22714 m1.MEM_PTR = (char *) &boot_parameters;
- 22715 (void) sendrec(SYSTASK, &m1);
- 22716 }
- 22719 /*===========================================================================*
- 22720 * load_ram *
- 22721 *===========================================================================*/
- 22722 PRIVATE void load_ram()
- 22723 {
- 22724 /* If the root device is the RAM disk, copy the entire root image device
- 22725 * block-by-block to a RAM disk with the same size as the image.
- 22726 * Otherwise, just allocate a RAM disk with size given in the boot parameters.
- 22727 */
- 22728
- 22729 register struct buf *bp, *bp1;
- 22730 long k_loaded, lcount;
- 22731 u32_t ram_size, fsmax;
- 22732 zone_t zones;
- 22733 struct super_block *sp, *dsp;
- 22734 block_t b;
- 22735 int major, task;
- 22736 message dev_mess;
- 22737
- 22738 ram_size = boot_parameters.bp_ramsize;
- 22739
- 22740 /* Open the root device. */
- 22741 major = (ROOT_DEV >> MAJOR) & BYTE; /* major device nr */
- 22742 task = dmap[major].dmap_task; /* device task nr */
- 22743 dev_mess.m_type = DEV_OPEN; /* distinguish from close */
- 22744 dev_mess.DEVICE = ROOT_DEV;
- 22745 dev_mess.COUNT = R_BIT|W_BIT;
- 22746 (*dmap[major].dmap_open)(task, &dev_mess);
- 22747 if (dev_mess.REP_STATUS != OK) panic("Cannot open root device",NO_NUM);
- 22748
- 22749 /* If the root device is the ram disk then fill it from the image device. */
- 22750 if (ROOT_DEV == DEV_RAM) {
- 22751 major = (IMAGE_DEV >> MAJOR) & BYTE; /* major device nr */
- 22752 task = dmap[major].dmap_task; /* device task nr */
- 22753 dev_mess.m_type = DEV_OPEN; /* distinguish from close */
- 22754 dev_mess.DEVICE = IMAGE_DEV;
- 22755 dev_mess.COUNT = R_BIT;
- 22756 (*dmap[major].dmap_open)(task, &dev_mess);
- 22757 if (dev_mess.REP_STATUS != OK) panic("Cannot open root device", NO_NUM);
- 22758
- 22759 /* Get size of RAM disk by reading root file system's super block. */
- 22760 sp = &super_block[0];
- 22761 sp->s_dev = IMAGE_DEV;
- 22762 if (read_super(sp) != OK) panic("Bad root file system", NO_NUM);
- 22763
- 22764 lcount = sp->s_zones << sp->s_log_zone_size; /* # blks on root dev*/
- 22765
- 22766 /* Stretch the RAM disk file system to the boot parameters size, but
- 22767 * no further than the last zone bit map block allows.
- 22768 */
- 22769 if (ram_size < lcount) ram_size = lcount;
- 22770 fsmax = (u32_t) sp->s_zmap_blocks * CHAR_BIT * BLOCK_SIZE;
- 22771 fsmax = (fsmax + (sp->s_firstdatazone-1)) << sp->s_log_zone_size;
- 22772 if (ram_size > fsmax) ram_size = fsmax;
- 22773 }
- 22774
- 22775 /* Tell RAM driver how big the RAM disk must be. */
- 22776 m1.m_type = DEV_IOCTL;
- 22777 m1.PROC_NR = FS_PROC_NR;
- 22778 m1.REQUEST = MIOCRAMSIZE;
- 22779 m1.POSITION = ram_size;
- 22780 if (sendrec(MEM, &m1) != OK || m1.REP_STATUS != OK)
- 22781 panic("Can't set RAM disk size", NO_NUM);
- 22782
- 22783 /* Tell MM the RAM disk size, and wait for it to come "on-line". */
- 22784 m1.m1_i1 = ((long) ram_size * BLOCK_SIZE) >> CLICK_SHIFT;
- 22785 if (sendrec(MM_PROC_NR, &m1) != OK)
- 22786 panic("FS can't sync up with MM", NO_NUM);
- 22787
- 22788 /* If the root device is not the RAM disk, it doesn't need loading. */
- 22789 if (ROOT_DEV != DEV_RAM) return;
- 22790
- 22791 /* Copy the blocks one at a time from the image to the RAM disk. */
- 22792 printf("Loading RAM disk.33[23CLoaded: 0K ");
- 22793
- 22794 inode[0].i_mode = I_BLOCK_SPECIAL; /* temp inode for rahead() */
- 22795 inode[0].i_size = LONG_MAX;
- 22796 inode[0].i_dev = IMAGE_DEV;
- 22797 inode[0].i_zone[0] = IMAGE_DEV;
- 22798
- 22799 for (b = 0; b < (block_t) lcount; b++) {
- 22800 bp = rahead(&inode[0], b, (off_t)BLOCK_SIZE * b, BLOCK_SIZE);
- 22801 bp1 = get_block(ROOT_DEV, b, NO_READ);
- 22802 memcpy(bp1->b_data, bp->b_data, (size_t) BLOCK_SIZE);
- 22803 bp1->b_dirt = DIRTY;
- 22804 put_block(bp, FULL_DATA_BLOCK);
- 22805 put_block(bp1, FULL_DATA_BLOCK);
- 22806 k_loaded = ( (long) b * BLOCK_SIZE)/1024L; /* K loaded so far */
- 22807 if (k_loaded % 5 == 0) printf("bbbbbbb%5ldK ", k_loaded);
- 22808 }
- 22809
- 22810 printf("rRAM disk loaded.33[Knn");
- 22811
- 22812 /* Close and invalidate image device. */
- 22813 dev_mess.m_type = DEV_CLOSE;
- 22814 dev_mess.DEVICE = IMAGE_DEV;
- 22815 (*dmap[major].dmap_close)(task, &dev_mess);
- 22816 invalidate(IMAGE_DEV);
- 22817
- 22818 /* Resize the RAM disk root file system. */
- 22819 bp = get_block(ROOT_DEV, SUPER_BLOCK, NORMAL);
- 22820 dsp = (struct super_block *) bp->b_data;
- 22821 zones = ram_size >> sp->s_log_zone_size;
- 22822 dsp->s_nzones = conv2(sp->s_native, (u16_t) zones);
- 22823 dsp->s_zones = conv4(sp->s_native, zones);
- 22824 bp->b_dirt = DIRTY;
- 22825 put_block(bp, ZUPER_BLOCK);
- 22826 }
- 22829 /*===========================================================================*
- 22830 * load_super *
- 22831 *===========================================================================*/
- 22832 PRIVATE void load_super(super_dev)
- 22833 dev_t super_dev; /* place to get superblock from */
- 22834 {
- 22835 int bad;
- 22836 register struct super_block *sp;
- 22837 register struct inode *rip;
- 22838
- 22839 /* Initialize the super_block table. */
- 22840 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
- 22841 sp->s_dev = NO_DEV;
- 22842
- 22843 /* Read in super_block for the root file system. */
- 22844 sp = &super_block[0];
- 22845 sp->s_dev = super_dev;
- 22846
- 22847 /* Check super_block for consistency (is it the right diskette?). */
- 22848 bad = (read_super(sp) != OK);
- 22849 if (!bad) {
- 22850 rip = get_inode(super_dev, ROOT_INODE); /* inode for root dir */
- 22851 if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++;
- 22852 }
- 22853 if (bad)panic("Invalid root file system. Possibly wrong diskette.",NO_NUM);
- 22854
- 22855 sp->s_imount = rip;
- 22856 dup_inode(rip);
- 22857 sp->s_isup = rip;
- 22858 sp->s_rd_only = 0;
- 22859 return;
- 22860 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/open.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 22900 /* This file contains the procedures for creating, opening, closing, and
- 22901 * seeking on files.
- 22902 *
- 22903 * The entry points into this file are
- 22904 * do_creat: perform the CREAT system call
- 22905 * do_open: perform the OPEN system call
- 22906 * do_mknod: perform the MKNOD system call
- 22907 * do_mkdir: perform the MKDIR system call
- 22908 * do_close: perform the CLOSE system call
- 22909 * do_lseek: perform the LSEEK system call
- 22910 */
- 22911
- 22912 #include "fs.h"
- 22913 #include <sys/stat.h>
- 22914 #include <fcntl.h>
- 22915 #include <minix/callnr.h>
- 22916 #include <minix/com.h>
- 22917 #include "buf.h"
- 22918 #include "dev.h"
- 22919 #include "file.h"
- 22920 #include "fproc.h"
- 22921 #include "inode.h"
- 22922 #include "lock.h"
- 22923 #include "param.h"
- 22924
- 22925 PRIVATE message dev_mess;
- 22926 PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
- 22927
- 22928 FORWARD _PROTOTYPE( int common_open, (int oflags, Mode_t omode) );
- 22929 FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,Mode_t bits,int oflags));
- 22930 FORWARD _PROTOTYPE( struct inode *new_node, (char *path, Mode_t bits,
- 22931 zone_t z0) );
- 22932
- 22933
- 22934 /*===========================================================================*
- 22935 * do_creat *
- 22936 *===========================================================================*/
- 22937 PUBLIC int do_creat()
- 22938 {
- 22939 /* Perform the creat(name, mode) system call. */
- 22940 int r;
- 22941
- 22942 if (fetch_name(name, name_length, M3) != OK) return(err_code);
- 22943 r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) mode);
- 22944 return(r);
- 22945 }
- 22948 /*===========================================================================*
- 22949 * do_open *
- 22950 *===========================================================================*/
- 22951 PUBLIC int do_open()
- 22952 {
- 22953 /* Perform the open(name, flags,...) system call. */
- 22954
- 22955 int create_mode = 0; /* is really mode_t but this gives problems */
- 22956 int r;
- 22957
- 22958 /* If O_CREAT is set, open has three parameters, otherwise two. */
- 22959 if (mode & O_CREAT) {
- 22960 create_mode = c_mode;
- 22961 r = fetch_name(c_name, name1_length, M1);
- 22962 } else {
- 22963 r = fetch_name(name, name_length, M3);
- 22964 }
- 22965
- 22966 if (r != OK) return(err_code); /* name was bad */
- 22967 r = common_open(mode, create_mode);
- 22968 return(r);
- 22969 }
- 22972 /*===========================================================================*
- 22973 * common_open *
- 22974 *===========================================================================*/
- 22975 PRIVATE int common_open(oflags, omode)
- 22976 register int oflags;
- 22977 mode_t omode;
- 22978 {
- 22979 /* Common code from do_creat and do_open. */
- 22980
- 22981 register struct inode *rip;
- 22982 int r, b, major, task, exist = TRUE;
- 22983 dev_t dev;
- 22984 mode_t bits;
- 22985 off_t pos;
- 22986 struct filp *fil_ptr, *filp2;
- 22987
- 22988 /* Remap the bottom two bits of oflags. */
- 22989 bits = (mode_t) mode_map[oflags & O_ACCMODE];
- 22990
- 22991 /* See if file descriptor and filp slots are available. */
- 22992 if ( (r = get_fd(0, bits, &fd, &fil_ptr)) != OK) return(r);
- 22993
- 22994 /* If O_CREATE is set, try to make the file. */
- 22995 if (oflags & O_CREAT) {
- 22996 /* Create a new inode by calling new_node(). */
- 22997 omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
- 22998 rip = new_node(user_path, omode, NO_ZONE);
- 22999 r = err_code;
- 23000 if (r == OK) exist = FALSE; /* we just created the file */
- 23001 else if (r != EEXIST) return(r); /* other error */
- 23002 else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL
- 23003 flag is set this is an error */
- 23004 } else {
- 23005 /* Scan path name. */
- 23006 if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
- 23007 }
- 23008
- 23009 /* Claim the file descriptor and filp slot and fill them in. */
- 23010 fp->fp_filp[fd] = fil_ptr;
- 23011 fil_ptr->filp_count = 1;
- 23012 fil_ptr->filp_ino = rip;
- 23013 fil_ptr->filp_flags = oflags;
- 23014
- 23015 /* Only do the normal open code if we didn't just create the file. */
- 23016 if (exist) {
- 23017 /* Check protections. */
- 23018 if ((r = forbidden(rip, bits)) == OK) {
- 23019 /* Opening reg. files directories and special files differ. */
- 23020 switch (rip->i_mode & I_TYPE) {
- 23021 case I_REGULAR:
- 23022 /* Truncate regular file if O_TRUNC. */
- 23023 if (oflags & O_TRUNC) {
- 23024 if ((r = forbidden(rip, W_BIT)) !=OK) break;
- 23025 truncate(rip);
- 23026 wipe_inode(rip);
- 23027 /* Send the inode from the inode cache to the
- 23028 * block cache, so it gets written on the next
- 23029 * cache flush.
- 23030 */
- 23031 rw_inode(rip, WRITING);
- 23032 }
- 23033 break;
- 23034
- 23035 case I_DIRECTORY:
- 23036 /* Directories may be read but not written. */
- 23037 r = (bits & W_BIT ? EISDIR : OK);
- 23038 break;
- 23039
- 23040 case I_CHAR_SPECIAL:
- 23041 case I_BLOCK_SPECIAL:
- 23042 /* Invoke the driver for special processing. */
- 23043 dev_mess.m_type = DEV_OPEN;
- 23044 dev = (dev_t) rip->i_zone[0];
- 23045 dev_mess.DEVICE = dev;
- 23046 dev_mess.COUNT = bits | (oflags & ~O_ACCMODE);
- 23047 major = (dev >> MAJOR) & BYTE; /* major device nr */
- 23048 if (major <= 0 || major >= max_major) {
- 23049 r = ENODEV;
- 23050 break;
- 23051 }
- 23052 task = dmap[major].dmap_task; /* device task nr */
- 23053 (*dmap[major].dmap_open)(task, &dev_mess);
- 23054 r = dev_mess.REP_STATUS;
- 23055 break;
- 23056
- 23057 case I_NAMED_PIPE:
- 23058 oflags |= O_APPEND; /* force append mode */
- 23059 fil_ptr->filp_flags = oflags;
- 23060 r = pipe_open(rip, bits, oflags);
- 23061 if (r == OK) {
- 23062 /* See if someone else is doing a rd or wt on
- 23063 * the FIFO. If so, use its filp entry so the
- 23064 * file position will be automatically shared.
- 23065 */
- 23066 b = (bits & R_BIT ? R_BIT : W_BIT);
- 23067 fil_ptr->filp_count = 0; /* don't find self */
- 23068 if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
- 23069 /* Co-reader or writer found. Use it.*/
- 23070 fp->fp_filp[fd] = filp2;
- 23071 filp2->filp_count++;
- 23072 filp2->filp_ino = rip;
- 23073 filp2->filp_flags = oflags;
- 23074
- 23075 /* i_count was incremented incorrectly
- 23076 * by eatpath above, not knowing that
- 23077 * we were going to use an existing
- 23078 * filp entry. Correct this error.
- 23079 */
- 23080 rip->i_count--;
- 23081 } else {
- 23082 /* Nobody else found. Restore filp. */
- 23083 fil_ptr->filp_count = 1;
- 23084 if (b == R_BIT)
- 23085 pos = rip->i_zone[V2_NR_DZONES+1];
- 23086 else
- 23087 pos = rip->i_zone[V2_NR_DZONES+2];
- 23088 fil_ptr->filp_pos = pos;
- 23089 }
- 23090 }
- 23091 break;
- 23092 }
- 23093 }
- 23094 }
- 23095
- 23096 /* If error, release inode. */
- 23097 if (r != OK) {
- 23098 fp->fp_filp[fd] = NIL_FILP;
- 23099 fil_ptr->filp_count= 0;
- 23100 put_inode(rip);
- 23101 return(r);
- 23102 }
- 23103
- 23104 return(fd);
- 23105 }
- 23108 /*===========================================================================*
- 23109 * new_node *
- 23110 *===========================================================================*/
- 23111 PRIVATE struct inode *new_node(path, bits, z0)
- 23112 char *path; /* pointer to path name */
- 23113 mode_t bits; /* mode of the new inode */
- 23114 zone_t z0; /* zone number 0 for new inode */
- 23115 {
- 23116 /* New_node() is called by common_open(), do_mknod(), and do_mkdir().
- 23117 * In all cases it allocates a new inode, makes a directory entry for it on
- 23118 * the path 'path', and initializes it. It returns a pointer to the inode if
- 23119 * it can do this; otherwise it returns NIL_INODE. It always sets 'err_code'
- 23120 * to an appropriate value (OK or an error code).
- 23121 */
- 23122
- 23123 register struct inode *rlast_dir_ptr, *rip;
- 23124 register int r;
- 23125 char string[NAME_MAX];
- 23126
- 23127 /* See if the path can be opened down to the last directory. */
- 23128 if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);
- 23129
- 23130 /* The final directory is accessible. Get final component of the path. */
- 23131 rip = advance(rlast_dir_ptr, string);
- 23132 if ( rip == NIL_INODE && err_code == ENOENT) {
- 23133 /* Last path component does not exist. Make new directory entry. */
- 23134 if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {
- 23135 /* Can't creat new inode: out of inodes. */
- 23136 put_inode(rlast_dir_ptr);
- 23137 return(NIL_INODE);
- 23138 }
- 23139
- 23140 /* Force inode to the disk before making directory entry to make
- 23141 * the system more robust in the face of a crash: an inode with
- 23142 * no directory entry is much better than the opposite.
- 23143 */
- 23144 rip->i_nlinks++;
- 23145 rip->i_zone[0] = z0; /* major/minor device numbers */
- 23146 rw_inode(rip, WRITING); /* force inode to disk now */
- 23147
- 23148 /* New inode acquired. Try to make directory entry. */
- 23149 if ((r = search_dir(rlast_dir_ptr, string, &rip->i_num,ENTER)) != OK) {
- 23150 put_inode(rlast_dir_ptr);
- 23151 rip->i_nlinks--; /* pity, have to free disk inode */
- 23152 rip->i_dirt = DIRTY; /* dirty inodes are written out */
- 23153 put_inode(rip); /* this call frees the inode */
- 23154 err_code = r;
- 23155 return(NIL_INODE);
- 23156 }
- 23157
- 23158 } else {
- 23159 /* Either last component exists, or there is some problem. */
- 23160 if (rip != NIL_INODE)
- 23161 r = EEXIST;
- 23162 else
- 23163 r = err_code;
- 23164 }
- 23165
- 23166 /* Return the directory inode and exit. */
- 23167 put_inode(rlast_dir_ptr);
- 23168 err_code = r;
- 23169 return(rip);
- 23170 }
- 23173 /*===========================================================================*
- 23174 * pipe_open *
- 23175 *===========================================================================*/
- 23176 PRIVATE int pipe_open(rip, bits, oflags)
- 23177 register struct inode *rip;
- 23178 register mode_t bits;
- 23179 register int oflags;
- 23180 {
- 23181 /* This function is called from common_open. It checks if
- 23182 * there is at least one reader/writer pair for the pipe, if not
- 23183 * it suspends the caller, otherwise it revives all other blocked
- 23184 * processes hanging on the pipe.
- 23185 */
- 23186
- 23187 if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) {
- 23188 if (oflags & O_NONBLOCK) {
- 23189 if (bits & W_BIT) return(ENXIO);
- 23190 } else
- 23191 suspend(XPOPEN); /* suspend caller */
- 23192 } else if (susp_count > 0) {/* revive blocked processes */
- 23193 release(rip, OPEN, susp_count);
- 23194 release(rip, CREAT, susp_count);
- 23195 }
- 23196 rip->i_pipe = I_PIPE;
- 23197
- 23198 return(OK);
- 23199 }
- 23202 /*===========================================================================*
- 23203 * do_mknod *
- 23204 *===========================================================================*/
- 23205 PUBLIC int do_mknod()
- 23206 {
- 23207 /* Perform the mknod(name, mode, addr) system call. */
- 23208
- 23209 register mode_t bits, mode_bits;
- 23210 struct inode *ip;
- 23211
- 23212 /* Only the super_user may make nodes other than fifos. */
- 23213 mode_bits = (mode_t) m.m1_i2; /* mode of the inode */
- 23214 if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
- 23215 if (fetch_name(m.m1_p1, m.m1_i1, M1) != OK) return(err_code);
- 23216 bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
- 23217 ip = new_node(user_path, bits, (zone_t) m.m1_i3);
- 23218 put_inode(ip);
- 23219 return(err_code);
- 23220 }
- 23223 /*===========================================================================*
- 23224 * do_mkdir *
- 23225 *===========================================================================*/
- 23226 PUBLIC int do_mkdir()
- 23227 {
- 23228 /* Perform the mkdir(name, mode) system call. */
- 23229
- 23230 int r1, r2; /* status codes */
- 23231 ino_t dot, dotdot; /* inode numbers for . and .. */
- 23232 mode_t bits; /* mode bits for the new inode */
- 23233 char string[NAME_MAX]; /* last component of the new dir's path name */
- 23234 register struct inode *rip, *ldirp;
- 23235
- 23236 /* Check to see if it is possible to make another link in the parent dir. */
- 23237 if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
- 23238 ldirp = last_dir(user_path, string); /* pointer to new dir's parent */
- 23239 if (ldirp == NIL_INODE) return(err_code);
- 23240 if ( (ldirp->i_nlinks & BYTE) >= LINK_MAX) {
- 23241 put_inode(ldirp); /* return parent */
- 23242 return(EMLINK);
- 23243 }
- 23244
- 23245 /* Next make the inode. If that fails, return error code. */
- 23246 bits = I_DIRECTORY | (mode & RWX_MODES & fp->fp_umask);
- 23247 rip = new_node(user_path, bits, (zone_t) 0);
- 23248 if (rip == NIL_INODE || err_code == EEXIST) {
- 23249 put_inode(rip); /* can't make dir: it already exists */
- 23250 put_inode(ldirp); /* return parent too */
- 23251 return(err_code);
- 23252 }
- 23253
- 23254 /* Get the inode numbers for . and .. to enter in the directory. */
- 23255 dotdot = ldirp->i_num; /* parent's inode number */
- 23256 dot = rip->i_num; /* inode number of the new dir itself */
- 23257
- 23258 /* Now make dir entries for . and .. unless the disk is completely full. */
- 23259 /* Use dot1 and dot2, so the mode of the directory isn't important. */
- 23260 rip->i_mode = bits; /* set mode */
- 23261 r1 = search_dir(rip, dot1, &dot, ENTER); /* enter . in the new dir */
- 23262 r2 = search_dir(rip, dot2, &dotdot, ENTER); /* enter .. in the new dir */
- 23263
- 23264 /* If both . and .. were successfully entered, increment the link counts. */
- 23265 if (r1 == OK && r2 == OK) {
- 23266 /* Normal case. It was possible to enter . and .. in the new dir. */
- 23267 rip->i_nlinks++; /* this accounts for . */
- 23268 ldirp->i_nlinks++; /* this accounts for .. */
- 23269 ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */
- 23270 } else {
- 23271 /* It was not possible to enter . or .. probably disk was full. */
- 23272 (void) search_dir(ldirp, string, (ino_t *) 0, DELETE);
- 23273 rip->i_nlinks--; /* undo the increment done in new_node() */
- 23274 }
- 23275 rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */
- 23276
- 23277 put_inode(ldirp); /* return the inode of the parent dir */
- 23278 put_inode(rip); /* return the inode of the newly made dir */
- 23279 return(err_code); /* new_node() always sets 'err_code' */
- 23280 }
- 23283 /*===========================================================================*
- 23284 * do_close *
- 23285 *===========================================================================*/
- 23286 PUBLIC int do_close()
- 23287 {
- 23288 /* Perform the close(fd) system call. */
- 23289
- 23290 register struct filp *rfilp;
- 23291 register struct inode *rip;
- 23292 struct file_lock *flp;
- 23293 int rw, mode_word, major, task, lock_count;
- 23294 dev_t dev;
- 23295
- 23296 /* First locate the inode that belongs to the file descriptor. */
- 23297 if ( (rfilp = get_filp(fd)) == NIL_FILP) return(err_code);
- 23298 rip = rfilp->filp_ino; /* 'rip' points to the inode */
- 23299
- 23300 if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
- 23301 /* Check to see if the file is special. */
- 23302 mode_word = rip->i_mode & I_TYPE;
- 23303 if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
- 23304 dev = (dev_t) rip->i_zone[0];
- 23305 if (mode_word == I_BLOCK_SPECIAL) {
- 23306 /* Invalidate cache entries unless special is mounted
- 23307 * or ROOT
- 23308 */
- 23309 if (!mounted(rip)) {
- 23310 (void) do_sync(); /* purge cache */
- 23311 invalidate(dev);
- 23312 }
- 23313 }
- 23314 /* Use the dmap_close entry to do any special processing
- 23315 * required.
- 23316 */
- 23317 dev_mess.m_type = DEV_CLOSE;
- 23318 dev_mess.DEVICE = dev;
- 23319 major = (dev >> MAJOR) & BYTE; /* major device nr */
- 23320 task = dmap[major].dmap_task; /* device task nr */
- 23321 (*dmap[major].dmap_close)(task, &dev_mess);
- 23322 }
- 23323 }
- 23324
- 23325 /* If the inode being closed is a pipe, release everyone hanging on it. */
- 23326 if (rip->i_pipe == I_PIPE) {
- 23327 rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
- 23328 release(rip, rw, NR_PROCS);
- 23329 }
- 23330
- 23331 /* If a write has been done, the inode is already marked as DIRTY. */
- 23332 if (--rfilp->filp_count == 0) {
- 23333 if (rip->i_pipe == I_PIPE && rip->i_count > 1) {
- 23334 /* Save the file position in the i-node in case needed later.
- 23335 * The read and write positions are saved separately. The
- 23336 * last 3 zones in the i-node are not used for (named) pipes.
- 23337 */
- 23338 if (rfilp->filp_mode == R_BIT)
- 23339 rip->i_zone[V2_NR_DZONES+1] = (zone_t) rfilp->filp_pos;
- 23340 else
- 23341 rip->i_zone[V2_NR_DZONES+2] = (zone_t) rfilp->filp_pos;
- 23342 }
- 23343 put_inode(rip);
- 23344 }
- 23345
- 23346 fp->fp_cloexec &= ~(1L << fd); /* turn off close-on-exec bit */
- 23347 fp->fp_filp[fd] = NIL_FILP;
- 23348
- 23349 /* Check to see if the file is locked. If so, release all locks. */
- 23350 if (nr_locks == 0) return(OK);
- 23351 lock_count = nr_locks; /* save count of locks */
- 23352 for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
- 23353 if (flp->lock_type == 0) continue; /* slot not in use */
- 23354 if (flp->lock_inode == rip && flp->lock_pid == fp->fp_pid) {
- 23355 flp->lock_type = 0;
- 23356 nr_locks--;
- 23357 }
- 23358 }
- 23359 if (nr_locks < lock_count) lock_revive(); /* lock released */
- 23360 return(OK);
- 23361 }
- 23364 /*===========================================================================*
- 23365 * do_lseek *
- 23366 *===========================================================================*/
- 23367 PUBLIC int do_lseek()
- 23368 {
- 23369 /* Perform the lseek(ls_fd, offset, whence) system call. */
- 23370
- 23371 register struct filp *rfilp;
- 23372 register off_t pos;
- 23373
- 23374 /* Check to see if the file descriptor is valid. */
- 23375 if ( (rfilp = get_filp(ls_fd)) == NIL_FILP) return(err_code);
- 23376
- 23377 /* No lseek on pipes. */
- 23378 if (rfilp->filp_ino->i_pipe == I_PIPE) return(ESPIPE);
- 23379
- 23380 /* The value of 'whence' determines the start position to use. */
- 23381 switch(whence) {
- 23382 case 0: pos = 0; break;
- 23383 case 1: pos = rfilp->filp_pos; break;
- 23384 case 2: pos = rfilp->filp_ino->i_size; break;
- 23385 default: return(EINVAL);
- 23386 }
- 23387
- 23388 /* Check for overflow. */
- 23389 if (((long)offset > 0) && ((long)(pos + offset) < (long)pos)) return(EINVAL);
- 23390 if (((long)offset < 0) && ((long)(pos + offset) > (long)pos)) return(EINVAL);
- 23391 pos = pos + offset;
- 23392
- 23393 if (pos != rfilp->filp_pos)
- 23394 rfilp->filp_ino->i_seek = ISEEK; /* inhibit read ahead */
- 23395 rfilp->filp_pos = pos;
- 23396 reply_l1 = pos; /* insert the long into the output message */
- 23397 return(OK);
- 23398 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/read.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 23400 /* This file contains the heart of the mechanism used to read (and write)
- 23401 * files. Read and write requests are split up into chunks that do not cross
- 23402 * block boundaries. Each chunk is then processed in turn. Reads on special
- 23403 * files are also detected and handled.
- 23404 *
- 23405 * The entry points into this file are
- 23406 * do_read: perform the READ system call by calling read_write
- 23407 * read_write: actually do the work of READ and WRITE
- 23408 * read_map: given an inode and file position, look up its zone number
- 23409 * rd_indir: read an entry in an indirect block
- 23410 * read_ahead: manage the block read ahead business
- 23411 */
- 23412
- 23413 #include "fs.h"
- 23414 #include <fcntl.h>
- 23415 #include <minix/com.h>
- 23416 #include "buf.h"
- 23417 #include "file.h"
- 23418 #include "fproc.h"
- 23419 #include "inode.h"
- 23420 #include "param.h"
- 23421 #include "super.h"
- 23422
- 23423 #define FD_MASK 077 /* max file descriptor is 63 */
- 23424
- 23425 PRIVATE message umess; /* message for asking SYSTASK for user copy */
- 23426
- 23427 FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,
- 23428 unsigned off, int chunk, unsigned left, int rw_flag,
- 23429 char *buff, int seg, int usr) );
- 23430
- 23431 /*===========================================================================*
- 23432 * do_read *
- 23433 *===========================================================================*/
- 23434 PUBLIC int do_read()
- 23435 {
- 23436 return(read_write(READING));
- 23437 }
- 23440 /*===========================================================================*
- 23441 * read_write *
- 23442 *===========================================================================*/
- 23443 PUBLIC int read_write(rw_flag)
- 23444 int rw_flag; /* READING or WRITING */
- 23445 {
- 23446 /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
- 23447
- 23448 register struct inode *rip;
- 23449 register struct filp *f;
- 23450 off_t bytes_left, f_size, position;
- 23451 unsigned int off, cum_io;
- 23452 int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
- 23453 int regular, partial_pipe = 0, partial_cnt = 0;
- 23454 dev_t dev;
- 23455 mode_t mode_word;
- 23456 struct filp *wf;
- 23457
- 23458 /* MM loads segments by putting funny things in upper 10 bits of 'fd'. */
- 23459 if (who == MM_PROC_NR && (fd & (~BYTE)) ) {
- 23460 usr = (fd >> 8) & BYTE;
- 23461 seg = (fd >> 6) & 03;
- 23462 fd &= FD_MASK; /* get rid of user and segment bits */
- 23463 } else {
- 23464 usr = who; /* normal case */
- 23465 seg = D;
- 23466 }
- 23467
- 23468 /* If the file descriptor is valid, get the inode, size and mode. */
- 23469 if (nbytes < 0) return(EINVAL);
- 23470 if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
- 23471 if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
- 23472 return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
- 23473 }
- 23474 if (nbytes == 0) return(0); /* so char special files need not check for 0*/
- 23475 position = f->filp_pos;
- 23476 if (position > MAX_FILE_POS) return(EINVAL);
- 23477 if (position + nbytes < position) return(EINVAL); /* unsigned overflow */
- 23478 oflags = f->filp_flags;
- 23479 rip = f->filp_ino;
- 23480 f_size = rip->i_size;
- 23481 r = OK;
- 23482 if (rip->i_pipe == I_PIPE) {
- 23483 /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
- 23484 cum_io = fp->fp_cum_io_partial;
- 23485 } else {
- 23486 cum_io = 0;
- 23487 }
- 23488 op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
- 23489 mode_word = rip->i_mode & I_TYPE;
- 23490 regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
- 23491
- 23492 char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0);
- 23493 block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0);
- 23494 if (block_spec) f_size = LONG_MAX;
- 23495 rdwt_err = OK; /* set to EIO if disk error occurs */
- 23496
- 23497 /* Check for character special files. */
- 23498 if (char_spec) {
- 23499 dev = (dev_t) rip->i_zone[0];
- 23500 r = dev_io(op, oflags & O_NONBLOCK, dev, position, nbytes, who,buffer);
- 23501 if (r >= 0) {
- 23502 cum_io = r;
- 23503 position += r;
- 23504 r = OK;
- 23505 }
- 23506 } else {
- 23507 if (rw_flag == WRITING && block_spec == 0) {
- 23508 /* Check in advance to see if file will grow too big. */
- 23509 if (position > rip->i_sp->s_max_size - nbytes) return(EFBIG);
- 23510
- 23511 /* Check for O_APPEND flag. */
- 23512 if (oflags & O_APPEND) position = f_size;
- 23513
- 23514 /* Clear the zone containing present EOF if hole about
- 23515 * to be created. This is necessary because all unwritten
- 23516 * blocks prior to the EOF must read as zeros.
- 23517 */
- 23518 if (position > f_size) clear_zone(rip, f_size, 0);
- 23519 }
- 23520
- 23521 /* Pipes are a little different. Check. */
- 23522 if (rip->i_pipe == I_PIPE) {
- 23523 r = pipe_check(rip,rw_flag,oflags,nbytes,position,&partial_cnt);
- 23524 if (r <= 0) return(r);
- 23525 }
- 23526
- 23527 if (partial_cnt > 0) partial_pipe = 1;
- 23528
- 23529 /* Split the transfer into chunks that don't span two blocks. */
- 23530 while (nbytes != 0) {
- 23531 off = (unsigned int) (position % BLOCK_SIZE);/* offset in blk*/
- 23532 if (partial_pipe) { /* pipes only */
- 23533 chunk = MIN(partial_cnt, BLOCK_SIZE - off);
- 23534 } else
- 23535 chunk = MIN(nbytes, BLOCK_SIZE - off);
- 23536 if (chunk < 0) chunk = BLOCK_SIZE - off;
- 23537
- 23538 if (rw_flag == READING) {
- 23539 bytes_left = f_size - position;
- 23540 if (position >= f_size) break; /* we are beyond EOF */
- 23541 if (chunk > bytes_left) chunk = (int) bytes_left;
- 23542 }
- 23543
- 23544 /* Read or write 'chunk' bytes. */
- 23545 r = rw_chunk(rip, position, off, chunk, (unsigned) nbytes,
- 23546 rw_flag, buffer, seg, usr);
- 23547 if (r != OK) break; /* EOF reached */
- 23548 if (rdwt_err < 0) break;
- 23549
- 23550 /* Update counters and pointers. */
- 23551 buffer += chunk; /* user buffer address */
- 23552 nbytes -= chunk; /* bytes yet to be read */
- 23553 cum_io += chunk; /* bytes read so far */
- 23554 position += chunk; /* position within the file */
- 23555
- 23556 if (partial_pipe) {
- 23557 partial_cnt -= chunk;
- 23558 if (partial_cnt <= 0) break;
- 23559 }
- 23560 }
- 23561 }
- 23562
- 23563 /* On write, update file size and access time. */
- 23564 if (rw_flag == WRITING) {
- 23565 if (regular || mode_word == I_DIRECTORY) {
- 23566 if (position > f_size) rip->i_size = position;
- 23567 }
- 23568 } else {
- 23569 if (rip->i_pipe == I_PIPE && position >= rip->i_size) {
- 23570 /* Reset pipe pointers. */
- 23571 rip->i_size = 0; /* no data left */
- 23572 position = 0; /* reset reader(s) */
- 23573 if ( (wf = find_filp(rip, W_BIT)) != NIL_FILP) wf->filp_pos =0;
- 23574 }
- 23575 }
- 23576 f->filp_pos = position;
- 23577
- 23578 /* Check to see if read-ahead is called for, and if so, set it up. */
- 23579 if (rw_flag == READING && rip->i_seek == NO_SEEK && position % BLOCK_SIZE== 0
- 23580 && (regular || mode_word == I_DIRECTORY)) {
- 23581 rdahed_inode = rip;
- 23582 rdahedpos = position;
- 23583 }
- 23584 rip->i_seek = NO_SEEK;
- 23585
- 23586 if (rdwt_err != OK) r = rdwt_err; /* check for disk error */
- 23587 if (rdwt_err == END_OF_FILE) r = OK;
- 23588 if (r == OK) {
- 23589 if (rw_flag == READING) rip->i_update |= ATIME;
- 23590 if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
- 23591 rip->i_dirt = DIRTY; /* inode is thus now dirty */
- 23592 if (partial_pipe) {
- 23593 partial_pipe = 0;
- 23594 /* partial write on pipe with */
- 23595 /* O_NONBLOCK, return write count */
- 23596 if (!(oflags & O_NONBLOCK)) {
- 23597 fp->fp_cum_io_partial = cum_io;
- 23598 suspend(XPIPE); /* partial write on pipe with */
- 23599 return(0); /* nbyte > PIPE_SIZE - non-atomic */
- 23600 }
- 23601 }
- 23602 fp->fp_cum_io_partial = 0;
- 23603 return(cum_io);
- 23604 } else {
- 23605 return(r);
- 23606 }
- 23607 }
- 23610 /*===========================================================================*
- 23611 * rw_chunk *
- 23612 *===========================================================================*/
- 23613 PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, seg, usr)
- 23614 register struct inode *rip; /* pointer to inode for file to be rd/wr */
- 23615 off_t position; /* position within file to read or write */
- 23616 unsigned off; /* off within the current block */
- 23617 int chunk; /* number of bytes to read or write */
- 23618 unsigned left; /* max number of bytes wanted after position */
- 23619 int rw_flag; /* READING or WRITING */
- 23620 char *buff; /* virtual address of the user buffer */
- 23621 int seg; /* T or D segment in user space */
- 23622 int usr; /* which user process */
- 23623 {
- 23624 /* Read or write (part of) a block. */
- 23625
- 23626 register struct buf *bp;
- 23627 register int r;
- 23628 int n, block_spec;
- 23629 block_t b;
- 23630 dev_t dev;
- 23631
- 23632 block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
- 23633 if (block_spec) {
- 23634 b = position/BLOCK_SIZE;
- 23635 dev = (dev_t) rip->i_zone[0];
- 23636 } else {
- 23637 b = read_map(rip, position);
- 23638 dev = rip->i_dev;
- 23639 }
- 23640
- 23641 if (!block_spec && b == NO_BLOCK) {
- 23642 if (rw_flag == READING) {
- 23643 /* Reading from a nonexistent block. Must read as all zeros.*/
- 23644 bp = get_block(NO_DEV, NO_BLOCK, NORMAL); /* get a buffer */
- 23645 zero_block(bp);
- 23646 } else {
- 23647 /* Writing to a nonexistent block. Create and enter in inode.*/
- 23648 if ((bp= new_block(rip, position)) == NIL_BUF)return(err_code);
- 23649 }
- 23650 } else if (rw_flag == READING) {
- 23651 /* Read and read ahead if convenient. */
- 23652 bp = rahead(rip, b, position, left);
- 23653 } else {
- 23654 /* Normally an existing block to be partially overwritten is first read
- 23655 * in. However, a full block need not be read in. If it is already in
- 23656 * the cache, acquire it, otherwise just acquire a free buffer.
- 23657 */
- 23658 n = (chunk == BLOCK_SIZE ? NO_READ : NORMAL);
- 23659 if (!block_spec && off == 0 && position >= rip->i_size) n = NO_READ;
- 23660 bp = get_block(dev, b, n);
- 23661 }
- 23662
- 23663 /* In all cases, bp now points to a valid buffer. */
- 23664 if (rw_flag == WRITING && chunk != BLOCK_SIZE && !block_spec &&
- 23665 position >= rip->i_size && off == 0) {
- 23666 zero_block(bp);
- 23667 }
- 23668 if (rw_flag == READING) {
- 23669 /* Copy a chunk from the block buffer to user space. */
- 23670 r = sys_copy(FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
- 23671 usr, seg, (phys_bytes) buff,
- 23672 (phys_bytes) chunk);
- 23673 } else {
- 23674 /* Copy a chunk from user space to the block buffer. */
- 23675 r = sys_copy(usr, seg, (phys_bytes) buff,
- 23676 FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
- 23677 (phys_bytes) chunk);
- 23678 bp->b_dirt = DIRTY;
- 23679 }
- 23680 n = (off + chunk == BLOCK_SIZE ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK);
- 23681 put_block(bp, n);
- 23682 return(r);
- 23683 }
- 23686 /*===========================================================================*
- 23687 * read_map *
- 23688 *===========================================================================*/
- 23689 PUBLIC block_t read_map(rip, position)
- 23690 register struct inode *rip; /* ptr to inode to map from */
- 23691 off_t position; /* position in file whose blk wanted */
- 23692 {
- 23693 /* Given an inode and a position within the corresponding file, locate the
- 23694 * block (not zone) number in which that position is to be found and return it.
- 23695 */
- 23696
- 23697 register struct buf *bp;
- 23698 register zone_t z;
- 23699 int scale, boff, dzones, nr_indirects, index, zind, ex;
- 23700 block_t b;
- 23701 long excess, zone, block_pos;
- 23702
- 23703 scale = rip->i_sp->s_log_zone_size; /* for block-zone conversion */
- 23704 block_pos = position/BLOCK_SIZE; /* relative blk # in file */
- 23705 zone = block_pos >> scale; /* position's zone */
- 23706 boff = (int) (block_pos - (zone << scale) ); /* relative blk # within zone */
- 23707 dzones = rip->i_ndzones;
- 23708 nr_indirects = rip->i_nindirs;
- 23709
- 23710 /* Is 'position' to be found in the inode itself? */
- 23711 if (zone < dzones) {
- 23712 zind = (int) zone; /* index should be an int */
- 23713 z = rip->i_zone[zind];
- 23714 if (z == NO_ZONE) return(NO_BLOCK);
- 23715 b = ((block_t) z << scale) + boff;
- 23716 return(b);
- 23717 }
- 23718
- 23719 /* It is not in the inode, so it must be single or double indirect. */
- 23720 excess = zone - dzones; /* first Vx_NR_DZONES don't count */
- 23721
- 23722 if (excess < nr_indirects) {
- 23723 /* 'position' can be located via the single indirect block. */
- 23724 z = rip->i_zone[dzones];
- 23725 } else {
- 23726 /* 'position' can be located via the double indirect block. */
- 23727 if ( (z = rip->i_zone[dzones+1]) == NO_ZONE) return(NO_BLOCK);
- 23728 excess -= nr_indirects; /* single indir doesn't count*/
- 23729 b = (block_t) z << scale;
- 23730 bp = get_block(rip->i_dev, b, NORMAL); /* get double indirect block */
- 23731 index = (int) (excess/nr_indirects);
- 23732 z = rd_indir(bp, index); /* z= zone for single*/
- 23733 put_block(bp, INDIRECT_BLOCK); /* release double ind block */
- 23734 excess = excess % nr_indirects; /* index into single ind blk */
- 23735 }
- 23736
- 23737 /* 'z' is zone num for single indirect block; 'excess' is index into it. */
- 23738 if (z == NO_ZONE) return(NO_BLOCK);
- 23739 b = (block_t) z << scale; /* b is blk # for single ind */
- 23740 bp = get_block(rip->i_dev, b, NORMAL); /* get single indirect block */
- 23741 ex = (int) excess; /* need an integer */
- 23742 z = rd_indir(bp, ex); /* get block pointed to */
- 23743 put_block(bp, INDIRECT_BLOCK); /* release single indir blk */
- 23744 if (z == NO_ZONE) return(NO_BLOCK);
- 23745 b = ((block_t) z << scale) + boff;
- 23746 return(b);
- 23747 }
- 23750 /*===========================================================================*
- 23751 * rd_indir *
- 23752 *===========================================================================*/
- 23753 PUBLIC zone_t rd_indir(bp, index)
- 23754 struct buf *bp; /* pointer to indirect block */
- 23755 int index; /* index into *bp */
- 23756 {
- 23757 /* Given a pointer to an indirect block, read one entry. The reason for
- 23758 * making a separate routine out of this is that there are four cases:
- 23759 * V1 (IBM and 68000), and V2 (IBM and 68000).
- 23760 */
- 23761
- 23762 struct super_block *sp;
- 23763 zone_t zone; /* V2 zones are longs (shorts in V1) */
- 23764
- 23765 sp = get_super(bp->b_dev); /* need super block to find file sys type */
- 23766
- 23767 /* read a zone from an indirect block */
- 23768 if (sp->s_version == V1)
- 23769 zone = (zone_t) conv2(sp->s_native, (int) bp->b_v1_ind[index]);
- 23770 else
- 23771 zone = (zone_t) conv4(sp->s_native, (long) bp->b_v2_ind[index]);
- 23772
- 23773 if (zone != NO_ZONE &&
- 23774 (zone < (zone_t) sp->s_firstdatazone || zone >= sp->s_zones)) {
- 23775 printf("Illegal zone number %ld in indirect block, index %dn",
- 23776 (long) zone, index);
- 23777 panic("check file system", NO_NUM);
- 23778 }
- 23779 return(zone);
- 23780 }
- 23783 /*===========================================================================*
- 23784 * read_ahead *
- 23785 *===========================================================================*/
- 23786 PUBLIC void read_ahead()
- 23787 {
- 23788 /* Read a block into the cache before it is needed. */
- 23789
- 23790 register struct inode *rip;
- 23791 struct buf *bp;
- 23792 block_t b;
- 23793
- 23794 rip = rdahed_inode; /* pointer to inode to read ahead from */
- 23795 rdahed_inode = NIL_INODE; /* turn off read ahead */
- 23796 if ( (b = read_map(rip, rdahedpos)) == NO_BLOCK) return; /* at EOF */
- 23797 bp = rahead(rip, b, rdahedpos, BLOCK_SIZE);
- 23798 put_block(bp, PARTIAL_DATA_BLOCK);
- 23799 }
- 23802 /*===========================================================================*
- 23803 * rahead *
- 23804 *===========================================================================*/
- 23805 PUBLIC struct buf *rahead(rip, baseblock, position, bytes_ahead)
- 23806 register struct inode *rip; /* pointer to inode for file to be read */
- 23807 block_t baseblock; /* block at current position */
- 23808 off_t position; /* position within file */
- 23809 unsigned bytes_ahead; /* bytes beyond position for immediate use */
- 23810 {
- 23811 /* Fetch a block from the cache or the device. If a physical read is
- 23812 * required, prefetch as many more blocks as convenient into the cache.
- 23813 * This usually covers bytes_ahead and is at least BLOCKS_MINIMUM.
- 23814 * The device driver may decide it knows better and stop reading at a
- 23815 * cylinder boundary (or after an error). Rw_scattered() puts an optional
- 23816 * flag on all reads to allow this.
- 23817 */
- 23818
- 23819 /* Minimum number of blocks to prefetch. */
- 23820 # define BLOCKS_MINIMUM (NR_BUFS < 50 ? 18 : 32)
- 23821
- 23822 int block_spec, scale, read_q_size;
- 23823 unsigned int blocks_ahead, fragment;
- 23824 block_t block, blocks_left;
- 23825 off_t ind1_pos;
- 23826 dev_t dev;
- 23827 struct buf *bp;
- 23828 static struct buf *read_q[NR_BUFS];
- 23829
- 23830 block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
- 23831 if (block_spec) {
- 23832 dev = (dev_t) rip->i_zone[0];
- 23833 } else {
- 23834 dev = rip->i_dev;
- 23835 }
- 23836
- 23837 block = baseblock;
- 23838 bp = get_block(dev, block, PREFETCH);
- 23839 if (bp->b_dev != NO_DEV) return(bp);
- 23840
- 23841 /* The best guess for the number of blocks to prefetch: A lot.
- 23842 * It is impossible to tell what the device looks like, so we don't even
- 23843 * try to guess the geometry, but leave it to the driver.
- 23844 *
- 23845 * The floppy driver can read a full track with no rotational delay, and it
- 23846 * avoids reading partial tracks if it can, so handing it enough buffers to
- 23847 * read two tracks is perfect. (Two, because some diskette types have
- 23848 * an odd number of sectors per track, so a block may span tracks.)
- 23849 *
- 23850 * The disk drivers don't try to be smart. With todays disks it is
- 23851 * impossible to tell what the real geometry looks like, so it is best to
- 23852 * read as much as you can. With luck the caching on the drive allows
- 23853 * for a little time to start the next read.
- 23854 *
- 23855 * The current solution below is a bit of a hack, it just reads blocks from
- 23856 * the current file position hoping that more of the file can be found. A
- 23857 * better solution must look at the already available zone pointers and
- 23858 * indirect blocks (but don't call read_map!).
- 23859 */
- 23860
- 23861 fragment = position % BLOCK_SIZE;
- 23862 position -= fragment;
- 23863 bytes_ahead += fragment;
- 23864
- 23865 blocks_ahead = (bytes_ahead + BLOCK_SIZE - 1) / BLOCK_SIZE;
- 23866
- 23867 if (block_spec && rip->i_size == 0) {
- 23868 blocks_left = NR_IOREQS;
- 23869 } else {
- 23870 blocks_left = (rip->i_size - position + BLOCK_SIZE - 1) / BLOCK_SIZE;
- 23871
- 23872 /* Go for the first indirect block if we are in its neighborhood. */
- 23873 if (!block_spec) {
- 23874 scale = rip->i_sp->s_log_zone_size;
- 23875 ind1_pos = (off_t) rip->i_ndzones * (BLOCK_SIZE << scale);
- 23876 if (position <= ind1_pos && rip->i_size > ind1_pos) {
- 23877 blocks_ahead++;
- 23878 blocks_left++;
- 23879 }
- 23880 }
- 23881 }
- 23882
- 23883 /* No more than the maximum request. */
- 23884 if (blocks_ahead > NR_IOREQS) blocks_ahead = NR_IOREQS;
- 23885
- 23886 /* Read at least the minimum number of blocks, but not after a seek. */
- 23887 if (blocks_ahead < BLOCKS_MINIMUM && rip->i_seek == NO_SEEK)
- 23888 blocks_ahead = BLOCKS_MINIMUM;
- 23889
- 23890 /* Can't go past end of file. */
- 23891 if (blocks_ahead > blocks_left) blocks_ahead = blocks_left;
- 23892
- 23893 read_q_size = 0;
- 23894
- 23895 /* Acquire block buffers. */
- 23896 for (;;) {
- 23897 read_q[read_q_size++] = bp;
- 23898
- 23899 if (--blocks_ahead == 0) break;
- 23900
- 23901 /* Don't trash the cache, leave 4 free. */
- 23902 if (bufs_in_use >= NR_BUFS - 4) break;
- 23903
- 23904 block++;
- 23905
- 23906 bp = get_block(dev, block, PREFETCH);
- 23907 if (bp->b_dev != NO_DEV) {
- 23908 /* Oops, block already in the cache, get out. */
- 23909 put_block(bp, FULL_DATA_BLOCK);
- 23910 break;
- 23911 }
- 23912 }
- 23913 rw_scattered(dev, read_q, read_q_size, READING);
- 23914 return(get_block(dev, baseblock, NORMAL));
- 23915 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/write.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 24000 /* This file is the counterpart of "read.c". It contains the code for writing
- 24001 * insofar as this is not contained in read_write().
- 24002 *
- 24003 * The entry points into this file are
- 24004 * do_write: call read_write to perform the WRITE system call
- 24005 * clear_zone: erase a zone in the middle of a file
- 24006 * new_block: acquire a new block
- 24007 */
- 24008
- 24009 #include "fs.h"
- 24010 #include <string.h>
- 24011 #include "buf.h"
- 24012 #include "file.h"
- 24013 #include "fproc.h"
- 24014 #include "inode.h"
- 24015 #include "super.h"
- 24016
- 24017 FORWARD _PROTOTYPE( int write_map, (struct inode *rip, off_t position,
- 24018 zone_t new_zone) );
- 24019
- 24020 FORWARD _PROTOTYPE( void wr_indir, (struct buf *bp, int index, zone_t zone) );
- 24021
- 24022 /*===========================================================================*
- 24023 * do_write *
- 24024 *===========================================================================*/
- 24025 PUBLIC int do_write()
- 24026 {
- 24027 /* Perform the write(fd, buffer, nbytes) system call. */
- 24028
- 24029 return(read_write(WRITING));
- 24030 }
- 24033 /*===========================================================================*
- 24034 * write_map *
- 24035 *===========================================================================*/
- 24036 PRIVATE int write_map(rip, position, new_zone)
- 24037 register struct inode *rip; /* pointer to inode to be changed */
- 24038 off_t position; /* file address to be mapped */
- 24039 zone_t new_zone; /* zone # to be inserted */
- 24040 {
- 24041 /* Write a new zone into an inode. */
- 24042 int scale, ind_ex, new_ind, new_dbl, zones, nr_indirects, single, zindex, ex;
- 24043 zone_t z, z1;
- 24044 register block_t b;
- 24045 long excess, zone;
- 24046 struct buf *bp;
- 24047
- 24048 rip->i_dirt = DIRTY; /* inode will be changed */
- 24049 bp = NIL_BUF;
- 24050 scale = rip->i_sp->s_log_zone_size; /* for zone-block conversion */
- 24051 zone = (position/BLOCK_SIZE) >> scale; /* relative zone # to insert */
- 24052 zones = rip->i_ndzones; /* # direct zones in the inode */
- 24053 nr_indirects = rip->i_nindirs;/* # indirect zones per indirect block */
- 24054
- 24055 /* Is 'position' to be found in the inode itself? */
- 24056 if (zone < zones) {
- 24057 zindex = (int) zone; /* we need an integer here */
- 24058 rip->i_zone[zindex] = new_zone;
- 24059 return(OK);
- 24060 }
- 24061
- 24062 /* It is not in the inode, so it must be single or double indirect. */
- 24063 excess = zone - zones; /* first Vx_NR_DZONES don't count */
- 24064 new_ind = FALSE;
- 24065 new_dbl = FALSE;
- 24066
- 24067 if (excess < nr_indirects) {
- 24068 /* 'position' can be located via the single indirect block. */
- 24069 z1 = rip->i_zone[zones]; /* single indirect zone */
- 24070 single = TRUE;
- 24071 } else {
- 24072 /* 'position' can be located via the double indirect block. */
- 24073 if ( (z = rip->i_zone[zones+1]) == NO_ZONE) {
- 24074 /* Create the double indirect block. */
- 24075 if ( (z = alloc_zone(rip->i_dev, rip->i_zone[0])) == NO_ZONE)
- 24076 return(err_code);
- 24077 rip->i_zone[zones+1] = z;
- 24078 new_dbl = TRUE; /* set flag for later */
- 24079 }
- 24080
- 24081 /* Either way, 'z' is zone number for double indirect block. */
- 24082 excess -= nr_indirects; /* single indirect doesn't count */
- 24083 ind_ex = (int) (excess / nr_indirects);
- 24084 excess = excess % nr_indirects;
- 24085 if (ind_ex >= nr_indirects) return(EFBIG);
- 24086 b = (block_t) z << scale;
- 24087 bp = get_block(rip->i_dev, b, (new_dbl ? NO_READ : NORMAL));
- 24088 if (new_dbl) zero_block(bp);
- 24089 z1 = rd_indir(bp, ind_ex);
- 24090 single = FALSE;
- 24091 }
- 24092
- 24093 /* z1 is now single indirect zone; 'excess' is index. */
- 24094 if (z1 == NO_ZONE) {
- 24095 /* Create indirect block and store zone # in inode or dbl indir blk. */
- 24096 z1 = alloc_zone(rip->i_dev, rip->i_zone[0]);
- 24097 if (single)
- 24098 rip->i_zone[zones] = z1; /* update inode */
- 24099 else
- 24100 wr_indir(bp, ind_ex, z1); /* update dbl indir */
- 24101
- 24102 new_ind = TRUE;
- 24103 if (bp != NIL_BUF) bp->b_dirt = DIRTY; /* if double ind, it is dirty*/
- 24104 if (z1 == NO_ZONE) {
- 24105 put_block(bp, INDIRECT_BLOCK); /* release dbl indirect blk */
- 24106 return(err_code); /* couldn't create single ind */
- 24107 }
- 24108 }
- 24109 put_block(bp, INDIRECT_BLOCK); /* release double indirect blk */
- 24110
- 24111 /* z1 is indirect block's zone number. */
- 24112 b = (block_t) z1 << scale;
- 24113 bp = get_block(rip->i_dev, b, (new_ind ? NO_READ : NORMAL) );
- 24114 if (new_ind) zero_block(bp);
- 24115 ex = (int) excess; /* we need an int here */
- 24116 wr_indir(bp, ex, new_zone);
- 24117 bp->b_dirt = DIRTY;
- 24118 put_block(bp, INDIRECT_BLOCK);
- 24119
- 24120 return(OK);
- 24121 }
- 24124 /*===========================================================================*
- 24125 * wr_indir *
- 24126 *===========================================================================*/
- 24127 PRIVATE void wr_indir(bp, index, zone)
- 24128 struct buf *bp; /* pointer to indirect block */
- 24129 int index; /* index into *bp */
- 24130 zone_t zone; /* zone to write */
- 24131 {
- 24132 /* Given a pointer to an indirect block, write one entry. */
- 24133
- 24134 struct super_block *sp;
- 24135
- 24136 sp = get_super(bp->b_dev); /* need super block to find file sys type */
- 24137
- 24138 /* write a zone into an indirect block */
- 24139 if (sp->s_version == V1)
- 24140 bp->b_v1_ind[index] = (zone1_t) conv2(sp->s_native, (int) zone);
- 24141 else
- 24142 bp->b_v2_ind[index] = (zone_t) conv4(sp->s_native, (long) zone);
- 24143 }
- 24146 /*===========================================================================*
- 24147 * clear_zone *
- 24148 *===========================================================================*/
- 24149 PUBLIC void clear_zone(rip, pos, flag)
- 24150 register struct inode *rip; /* inode to clear */
- 24151 off_t pos; /* points to block to clear */
- 24152 int flag; /* 0 if called by read_write, 1 by new_block */
- 24153 {
- 24154 /* Zero a zone, possibly starting in the middle. The parameter 'pos' gives
- 24155 * a byte in the first block to be zeroed. Clearzone() is called from
- 24156 * read_write and new_block().
- 24157 */
- 24158
- 24159 register struct buf *bp;
- 24160 register block_t b, blo, bhi;
- 24161 register off_t next;
- 24162 register int scale;
- 24163 register zone_t zone_size;
- 24164
- 24165 /* If the block size and zone size are the same, clear_zone() not needed. */
- 24166 scale = rip->i_sp->s_log_zone_size;
- 24167 if (scale == 0) return;
- 24168
- 24169 zone_size = (zone_t) BLOCK_SIZE << scale;
- 24170 if (flag == 1) pos = (pos/zone_size) * zone_size;
- 24171 next = pos + BLOCK_SIZE - 1;
- 24172
- 24173 /* If 'pos' is in the last block of a zone, do not clear the zone. */
- 24174 if (next/zone_size != pos/zone_size) return;
- 24175 if ( (blo = read_map(rip, next)) == NO_BLOCK) return;
- 24176 bhi = ( ((blo>>scale)+1) << scale) - 1;
- 24177
- 24178 /* Clear all the blocks between 'blo' and 'bhi'. */
- 24179 for (b = blo; b <= bhi; b++) {
- 24180 bp = get_block(rip->i_dev, b, NO_READ);
- 24181 zero_block(bp);
- 24182 put_block(bp, FULL_DATA_BLOCK);
- 24183 }
- 24184 }
- 24187 /*===========================================================================*
- 24188 * new_block *
- 24189 *===========================================================================*/
- 24190 PUBLIC struct buf *new_block(rip, position)
- 24191 register struct inode *rip; /* pointer to inode */
- 24192 off_t position; /* file pointer */
- 24193 {
- 24194 /* Acquire a new block and return a pointer to it. Doing so may require
- 24195 * allocating a complete zone, and then returning the initial block.
- 24196 * On the other hand, the current zone may still have some unused blocks.
- 24197 */
- 24198
- 24199 register struct buf *bp;
- 24200 block_t b, base_block;
- 24201 zone_t z;
- 24202 zone_t zone_size;
- 24203 int scale, r;
- 24204 struct super_block *sp;
- 24205
- 24206 /* Is another block available in the current zone? */
- 24207 if ( (b = read_map(rip, position)) == NO_BLOCK) {
- 24208 /* Choose first zone if possible. */
- 24209 /* Lose if the file is nonempty but the first zone number is NO_ZONE
- 24210 * corresponding to a zone full of zeros. It would be better to
- 24211 * search near the last real zone.
- 24212 */
- 24213 if (rip->i_zone[0] == NO_ZONE) {
- 24214 sp = rip->i_sp;
- 24215 z = sp->s_firstdatazone;
- 24216 } else {
- 24217 z = rip->i_zone[0]; /* hunt near first zone */
- 24218 }
- 24219 if ( (z = alloc_zone(rip->i_dev, z)) == NO_ZONE) return(NIL_BUF);
- 24220 if ( (r = write_map(rip, position, z)) != OK) {
- 24221 free_zone(rip->i_dev, z);
- 24222 err_code = r;
- 24223 return(NIL_BUF);
- 24224 }
- 24225
- 24226 /* If we are not writing at EOF, clear the zone, just to be safe. */
- 24227 if ( position != rip->i_size) clear_zone(rip, position, 1);
- 24228 scale = rip->i_sp->s_log_zone_size;
- 24229 base_block = (block_t) z << scale;
- 24230 zone_size = (zone_t) BLOCK_SIZE << scale;
- 24231 b = base_block + (block_t)((position % zone_size)/BLOCK_SIZE);
- 24232 }
- 24233
- 24234 bp = get_block(rip->i_dev, b, NO_READ);
- 24235 zero_block(bp);
- 24236 return(bp);
- 24237 }
- 24240 /*===========================================================================*
- 24241 * zero_block *
- 24242 *===========================================================================*/
- 24243 PUBLIC void zero_block(bp)
- 24244 register struct buf *bp; /* pointer to buffer to zero */
- 24245 {
- 24246 /* Zero a block. */
- 24247
- 24248 memset(bp->b_data, 0, BLOCK_SIZE);
- 24249 bp->b_dirt = DIRTY;
- 24250 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/pipe.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 24300 /* This file deals with the suspension and revival of processes. A process can
- 24301 * be suspended because it wants to read or write from a pipe and can't, or
- 24302 * because it wants to read or write from a special file and can't. When a
- 24303 * process can't continue it is suspended, and revived later when it is able
- 24304 * to continue.
- 24305 *
- 24306 * The entry points into this file are
- 24307 * do_pipe: perform the PIPE system call
- 24308 * pipe_check: check to see that a read or write on a pipe is feasible now
- 24309 * suspend: suspend a process that cannot do a requested read or write