The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/servers/fs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* This file manages the inode table.  There are procedures to allocate and
    2  * deallocate inodes, acquire, erase, and release them, and read and write
    3  * them from the disk.
    4  *
    5  * The entry points into this file are
    6  *   get_inode:    search inode table for a given inode; if not there,
    7  *                 read it
    8  *   put_inode:    indicate that an inode is no longer needed in memory
    9  *   alloc_inode:  allocate a new, unused inode
   10  *   wipe_inode:   erase some fields of a newly allocated inode
   11  *   free_inode:   mark an inode as available for a new file
   12  *   update_times: update atime, ctime, and mtime
   13  *   rw_inode:     read a disk block and extract an inode, or corresp. write
   14  *   old_icopy:    copy to/from in-core inode struct and disk inode (V1.x)
   15  *   new_icopy:    copy to/from in-core inode struct and disk inode (V2.x)
   16  *   dup_inode:    indicate that someone else is using an inode table entry
   17  */
   18 
   19 #include "fs.h"
   20 #include "buf.h"
   21 #include "file.h"
   22 #include "fproc.h"
   23 #include "inode.h"
   24 #include "super.h"
   25 
   26 FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
   27                                                 int direction, int norm));
   28 FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
   29                                                 int direction, int norm));
   30 
   31 /*===========================================================================*
   32  *                              get_inode                                    *
   33  *===========================================================================*/
   34 PUBLIC struct inode *get_inode(dev, numb)
   35 dev_t dev;                      /* device on which inode resides */
   36 int numb;                       /* inode number (ANSI: may not be unshort) */
   37 {
   38 /* Find a slot in the inode table, load the specified inode into it, and
   39  * return a pointer to the slot.  If 'dev' == NO_DEV, just return a free slot.
   40  */
   41 
   42   register struct inode *rip, *xp;
   43 
   44   /* Search the inode table both for (dev, numb) and a free slot. */
   45   xp = NIL_INODE;
   46   for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
   47         if (rip->i_count > 0) { /* only check used slots for (dev, numb) */
   48                 if (rip->i_dev == dev && rip->i_num == numb) {
   49                         /* This is the inode that we are looking for. */
   50                         rip->i_count++;
   51                         return(rip);    /* (dev, numb) found */
   52                 }
   53         } else {
   54                 xp = rip;       /* remember this free slot for later */
   55         }
   56   }
   57 
   58   /* Inode we want is not currently in use.  Did we find a free slot? */
   59   if (xp == NIL_INODE) {        /* inode table completely full */
   60         err_code = ENFILE;
   61         return(NIL_INODE);
   62   }
   63 
   64   /* A free inode slot has been located.  Load the inode into it. */
   65   xp->i_dev = dev;
   66   xp->i_num = numb;
   67   xp->i_count = 1;
   68   if (dev != NO_DEV) rw_inode(xp, READING);     /* get inode from disk */
   69   xp->i_update = 0;             /* all the times are initially up-to-date */
   70 
   71   return(xp);
   72 }
   73 
   74 /*===========================================================================*
   75  *                              put_inode                                    *
   76  *===========================================================================*/
   77 PUBLIC void put_inode(rip)
   78 register struct inode *rip;     /* pointer to inode to be released */
   79 {
   80 /* The caller is no longer using this inode.  If no one else is using it either
   81  * write it back to the disk immediately.  If it has no links, truncate it and
   82  * return it to the pool of available inodes.
   83  */
   84 
   85   if (rip == NIL_INODE) return; /* checking here is easier than in caller */
   86   if (--rip->i_count == 0) {    /* i_count == 0 means no one is using it now */
   87         if (rip->i_nlinks == 0) {
   88                 /* i_nlinks == 0 means free the inode. */
   89                 truncate(rip);  /* return all the disk blocks */
   90                 rip->i_mode = I_NOT_ALLOC;      /* clear I_TYPE field */
   91                 rip->i_dirt = DIRTY;
   92                 free_inode(rip->i_dev, rip->i_num);
   93         } else {
   94                 if (rip->i_pipe == I_PIPE) truncate(rip);
   95         }
   96         rip->i_pipe = NO_PIPE;  /* should always be cleared */
   97         if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
   98   }
   99 }
  100 
  101 /*===========================================================================*
  102  *                              alloc_inode                                  *
  103  *===========================================================================*/
  104 PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
  105 {
  106 /* Allocate a free inode on 'dev', and return a pointer to it. */
  107 
  108   register struct inode *rip;
  109   register struct super_block *sp;
  110   int major, minor, inumb;
  111   bit_t b;
  112 
  113   sp = get_super(dev);  /* get pointer to super_block */
  114   if (sp->s_rd_only) {  /* can't allocate an inode on a read only device. */
  115         err_code = EROFS;
  116         return(NIL_INODE);
  117   }
  118 
  119   /* Acquire an inode from the bit map. */
  120   b = alloc_bit(sp, IMAP, sp->s_isearch);
  121   if (b == NO_BIT) {
  122         err_code = ENFILE;
  123         major = (int) (sp->s_dev >> MAJOR) & BYTE;
  124         minor = (int) (sp->s_dev >> MINOR) & BYTE;
  125         printf("Out of i-nodes on %sdevice %d/%d\n",
  126                 sp->s_dev == root_dev ? "root " : "", major, minor);
  127         return(NIL_INODE);
  128   }
  129   sp->s_isearch = b;            /* next time start here */
  130   inumb = (int) b;              /* be careful not to pass unshort as param */
  131 
  132   /* Try to acquire a slot in the inode table. */
  133   if ((rip = get_inode(NO_DEV, inumb)) == NIL_INODE) {
  134         /* No inode table slots available.  Free the inode just allocated. */
  135         free_bit(sp, IMAP, b);
  136   } else {
  137         /* An inode slot is available. Put the inode just allocated into it. */
  138         rip->i_mode = bits;             /* set up RWX bits */
  139         rip->i_nlinks = 0;              /* initial no links */
  140         rip->i_uid = fp->fp_effuid;     /* file's uid is owner's */
  141         rip->i_gid = fp->fp_effgid;     /* ditto group id */
  142         rip->i_dev = dev;               /* mark which device it is on */
  143         rip->i_ndzones = sp->s_ndzones; /* number of direct zones */
  144         rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/
  145         rip->i_sp = sp;                 /* pointer to super block */
  146 
  147         /* Fields not cleared already are cleared in wipe_inode().  They have
  148          * been put there because truncate() needs to clear the same fields if
  149          * the file happens to be open while being truncated.  It saves space
  150          * not to repeat the code twice.
  151          */
  152         wipe_inode(rip);
  153   }
  154 
  155   return(rip);
  156 }
  157 
  158 /*===========================================================================*
  159  *                              wipe_inode                                   *
  160  *===========================================================================*/
  161 PUBLIC void wipe_inode(rip)
  162 register struct inode *rip;     /* the inode to be erased */
  163 {
  164 /* Erase some fields in the inode.  This function is called from alloc_inode()
  165  * when a new inode is to be allocated, and from truncate(), when an existing
  166  * inode is to be truncated.
  167  */
  168 
  169   register int i;
  170 
  171   rip->i_size = 0;
  172   rip->i_update = ATIME | CTIME | MTIME;        /* update all times later */
  173   rip->i_dirt = DIRTY;
  174   for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
  175 }
  176 
  177 /*===========================================================================*
  178  *                              free_inode                                   *
  179  *===========================================================================*/
  180 PUBLIC void free_inode(dev, inumb)
  181 dev_t dev;                      /* on which device is the inode */
  182 ino_t inumb;                    /* number of inode to be freed */
  183 {
  184 /* Return an inode to the pool of unallocated inodes. */
  185 
  186   register struct super_block *sp;
  187   bit_t b;
  188 
  189   /* Locate the appropriate super_block. */
  190   sp = get_super(dev);
  191   if (inumb <= 0 || inumb > sp->s_ninodes) return;
  192   b = inumb;
  193   free_bit(sp, IMAP, b);
  194   if (b < sp->s_isearch) sp->s_isearch = b;
  195 }
  196 
  197 /*===========================================================================*
  198  *                              update_times                                 *
  199  *===========================================================================*/
  200 PUBLIC void update_times(rip)
  201 register struct inode *rip;     /* pointer to inode to be read/written */
  202 {
  203 /* Various system calls are required by the standard to update atime, ctime,
  204  * or mtime.  Since updating a time requires sending a message to the clock
  205  * task--an expensive business--the times are marked for update by setting
  206  * bits in i_update.  When a stat, fstat, or sync is done, or an inode is 
  207  * released, update_times() may be called to actually fill in the times.
  208  */
  209 
  210   time_t cur_time;
  211   struct super_block *sp;
  212 
  213   sp = rip->i_sp;               /* get pointer to super block. */
  214   if (sp->s_rd_only) return;    /* no updates for read-only file systems */
  215 
  216   cur_time = clock_time();
  217   if (rip->i_update & ATIME) rip->i_atime = cur_time;
  218   if (rip->i_update & CTIME) rip->i_ctime = cur_time;
  219   if (rip->i_update & MTIME) rip->i_mtime = cur_time;
  220   rip->i_update = 0;            /* they are all up-to-date now */
  221 }
  222 
  223 /*===========================================================================*
  224  *                              rw_inode                                     *
  225  *===========================================================================*/
  226 PUBLIC void rw_inode(rip, rw_flag)
  227 register struct inode *rip;     /* pointer to inode to be read/written */
  228 int rw_flag;                    /* READING or WRITING */
  229 {
  230 /* An entry in the inode table is to be copied to or from the disk. */
  231 
  232   register struct buf *bp;
  233   register struct super_block *sp;
  234   d1_inode *dip;
  235   d2_inode *dip2;
  236   block_t b, offset;
  237 
  238   /* Get the block where the inode resides. */
  239   sp = get_super(rip->i_dev);   /* get pointer to super block */
  240   rip->i_sp = sp;               /* inode must contain super block pointer */
  241   offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
  242   b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
  243   bp = get_block(rip->i_dev, b, NORMAL);
  244   dip  = bp->b_v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
  245   dip2 = bp->b_v2_ino + (rip->i_num - 1) %
  246          V2_INODES_PER_BLOCK(sp->s_block_size);
  247 
  248   /* Do the read or write. */
  249   if (rw_flag == WRITING) {
  250         if (rip->i_update) update_times(rip);   /* times need updating */
  251         if (sp->s_rd_only == FALSE) bp->b_dirt = DIRTY;
  252   }
  253 
  254   /* Copy the inode from the disk block to the in-core table or vice versa.
  255    * If the fourth parameter below is FALSE, the bytes are swapped.
  256    */
  257   if (sp->s_version == V1)
  258         old_icopy(rip, dip,  rw_flag, sp->s_native);
  259   else
  260         new_icopy(rip, dip2, rw_flag, sp->s_native);
  261   
  262   put_block(bp, INODE_BLOCK);
  263   rip->i_dirt = CLEAN;
  264 }
  265 
  266 /*===========================================================================*
  267  *                              old_icopy                                    *
  268  *===========================================================================*/
  269 PRIVATE void old_icopy(rip, dip, direction, norm)
  270 register struct inode *rip;     /* pointer to the in-core inode struct */
  271 register d1_inode *dip;         /* pointer to the d1_inode inode struct */
  272 int direction;                  /* READING (from disk) or WRITING (to disk) */
  273 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  274 
  275 {
  276 /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
  277  * 68000) all have different inode layouts.  When an inode is read or written
  278  * this routine handles the conversions so that the information in the inode
  279  * table is independent of the disk structure from which the inode came.
  280  * The old_icopy routine copies to and from V1 disks.
  281  */
  282 
  283   int i;
  284 
  285   if (direction == READING) {
  286         /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
  287         rip->i_mode    = conv2(norm, (int) dip->d1_mode);
  288         rip->i_uid     = conv2(norm, (int) dip->d1_uid );
  289         rip->i_size    = conv4(norm,       dip->d1_size);
  290         rip->i_mtime   = conv4(norm,       dip->d1_mtime);
  291         rip->i_atime   = rip->i_mtime;
  292         rip->i_ctime   = rip->i_mtime;
  293         rip->i_nlinks  = dip->d1_nlinks;                /* 1 char */
  294         rip->i_gid     = dip->d1_gid;                   /* 1 char */
  295         rip->i_ndzones = V1_NR_DZONES;
  296         rip->i_nindirs = V1_INDIRECTS;
  297         for (i = 0; i < V1_NR_TZONES; i++)
  298                 rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
  299   } else {
  300         /* Copying V1.x inode to disk from the in-core table. */
  301         dip->d1_mode   = conv2(norm, (int) rip->i_mode);
  302         dip->d1_uid    = conv2(norm, (int) rip->i_uid );
  303         dip->d1_size   = conv4(norm,       rip->i_size);
  304         dip->d1_mtime  = conv4(norm,       rip->i_mtime);
  305         dip->d1_nlinks = rip->i_nlinks;                 /* 1 char */
  306         dip->d1_gid    = rip->i_gid;                    /* 1 char */
  307         for (i = 0; i < V1_NR_TZONES; i++)
  308                 dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
  309   }
  310 }
  311 
  312 /*===========================================================================*
  313  *                              new_icopy                                    *
  314  *===========================================================================*/
  315 PRIVATE void new_icopy(rip, dip, direction, norm)
  316 register struct inode *rip;     /* pointer to the in-core inode struct */
  317 register d2_inode *dip; /* pointer to the d2_inode struct */
  318 int direction;                  /* READING (from disk) or WRITING (to disk) */
  319 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  320 
  321 {
  322 /* Same as old_icopy, but to/from V2 disk layout. */
  323 
  324   int i;
  325 
  326   if (direction == READING) {
  327         /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
  328         rip->i_mode    = conv2(norm,dip->d2_mode);
  329         rip->i_uid     = conv2(norm,dip->d2_uid);
  330         rip->i_nlinks  = conv2(norm,dip->d2_nlinks);
  331         rip->i_gid     = conv2(norm,dip->d2_gid);
  332         rip->i_size    = conv4(norm,dip->d2_size);
  333         rip->i_atime   = conv4(norm,dip->d2_atime);
  334         rip->i_ctime   = conv4(norm,dip->d2_ctime);
  335         rip->i_mtime   = conv4(norm,dip->d2_mtime);
  336         rip->i_ndzones = V2_NR_DZONES;
  337         rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size);
  338         for (i = 0; i < V2_NR_TZONES; i++)
  339                 rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
  340   } else {
  341         /* Copying V2.x inode to disk from the in-core table. */
  342         dip->d2_mode   = conv2(norm,rip->i_mode);
  343         dip->d2_uid    = conv2(norm,rip->i_uid);
  344         dip->d2_nlinks = conv2(norm,rip->i_nlinks);
  345         dip->d2_gid    = conv2(norm,rip->i_gid);
  346         dip->d2_size   = conv4(norm,rip->i_size);
  347         dip->d2_atime  = conv4(norm,rip->i_atime);
  348         dip->d2_ctime  = conv4(norm,rip->i_ctime);
  349         dip->d2_mtime  = conv4(norm,rip->i_mtime);
  350         for (i = 0; i < V2_NR_TZONES; i++)
  351                 dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
  352   }
  353 }
  354 
  355 /*===========================================================================*
  356  *                              dup_inode                                    *
  357  *===========================================================================*/
  358 PUBLIC void dup_inode(ip)
  359 struct inode *ip;               /* The inode to be duplicated. */
  360 {
  361 /* This routine is a simplified form of get_inode() for the case where
  362  * the inode pointer is already known.
  363  */
  364 
  365   ip->i_count++;
  366 }

Cache object: c4d7450d96d7de27d323e6d5044507c6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.