📄 inode.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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/%d\n",
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -