root/fs/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_on_inode
  2. lock_inode
  3. unlock_inode
  4. write_inode
  5. read_inode
  6. bmap
  7. invalidate_inodes
  8. sync_inodes
  9. iput
  10. get_empty_inode
  11. get_pipe_inode
  12. iget

   1 /*
   2  *  linux/fs/inode.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/stat.h>
   8 #include <linux/sched.h>
   9 #include <linux/kernel.h>
  10 #include <linux/mm.h>
  11 #include <linux/string.h>
  12 
  13 #include <asm/system.h>
  14 
  15 struct inode inode_table[NR_INODE]={{0,},};
  16 
  17 static inline void wait_on_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  18 {
  19         cli();
  20         while (inode->i_lock)
  21                 sleep_on(&inode->i_wait);
  22         sti();
  23 }
  24 
  25 static inline void lock_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         cli();
  28         while (inode->i_lock)
  29                 sleep_on(&inode->i_wait);
  30         inode->i_lock=1;
  31         sti();
  32 }
  33 
  34 static inline void unlock_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36         inode->i_lock=0;
  37         wake_up(&inode->i_wait);
  38 }
  39 
  40 static void write_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         if (!inode->i_dirt)
  43                 return;
  44         inode->i_dirt = 0;
  45         lock_inode(inode);
  46         if (inode->i_dev && inode->i_sb &&
  47             inode->i_sb->s_op && inode->i_sb->s_op->write_inode)
  48                 inode->i_sb->s_op->write_inode(inode);
  49         unlock_inode(inode);
  50 }
  51 
  52 static void read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         lock_inode(inode);
  55         if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->read_inode)
  56                 inode->i_sb->s_op->read_inode(inode);
  57         unlock_inode(inode);
  58 }
  59 
  60 /*
  61  * bmap is needed for demand-loading and paging: if this function
  62  * doesn't exist for a filesystem, then those things are impossible:
  63  * executables cannot be run from the filesystem etc...
  64  *
  65  * This isn't as bad as it sounds: the read-routines might still work,
  66  * so the filesystem would be otherwise ok (for example, you might have
  67  * a DOS filesystem, which doesn't lend itself to bmap very well, but
  68  * you could still transfer files to/from the filesystem)
  69  */
  70 int bmap(struct inode * inode, int block)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         if (inode->i_op && inode->i_op->bmap)
  73                 return inode->i_op->bmap(inode,block);
  74         return 0;
  75 }
  76 
  77 void invalidate_inodes(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         int i;
  80         struct inode * inode;
  81 
  82         inode = 0+inode_table;
  83         for(i=0 ; i<NR_INODE ; i++,inode++) {
  84                 wait_on_inode(inode);
  85                 if (inode->i_dev == dev) {
  86                         if (inode->i_count) {
  87                                 printk("inode in use on removed disk\n\r");
  88                                 continue;
  89                         }
  90                         inode->i_dev = inode->i_dirt = 0;
  91                 }
  92         }
  93 }
  94 
  95 void sync_inodes(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         int i;
  98         struct inode * inode;
  99 
 100         inode = 0+inode_table;
 101         for(i=0 ; i<NR_INODE ; i++,inode++) {
 102                 wait_on_inode(inode);
 103                 if (inode->i_dirt)
 104                         write_inode(inode);
 105         }
 106 }
 107 
 108 void iput(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110         if (!inode)
 111                 return;
 112         wait_on_inode(inode);
 113         if (!inode->i_count) {
 114                 printk("iput: trying to free free inode\n");
 115                 printk("device %04x, inode %d, mode=%07o\n",inode->i_rdev,
 116                         inode->i_ino,inode->i_mode);
 117                 return;
 118         }
 119         if (inode->i_pipe) {
 120                 wake_up(&inode->i_wait);
 121                 wake_up(&inode->i_wait2);
 122         }
 123 repeat:
 124         if (inode->i_count>1) {
 125                 inode->i_count--;
 126                 return;
 127         }
 128         if (inode->i_pipe) {
 129                 free_page(inode->i_size);
 130                 inode->i_size = 0;
 131         }
 132         if (!inode->i_dev) {
 133                 inode->i_count--;
 134                 return;
 135         }
 136         if (!inode->i_nlink) {
 137                 if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
 138                         inode->i_sb->s_op->put_inode(inode);
 139                         return;
 140                 }
 141         }
 142         if (inode->i_dirt) {
 143                 write_inode(inode);     /* we can sleep - so do again */
 144                 wait_on_inode(inode);
 145                 goto repeat;
 146         }
 147         inode->i_count--;
 148         return;
 149 }
 150 
 151 struct inode * get_empty_inode(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         struct inode * inode;
 154         static struct inode * last_inode = inode_table;
 155         int i;
 156 
 157         do {
 158                 inode = NULL;
 159                 for (i = NR_INODE; i ; i--) {
 160                         if (++last_inode >= inode_table + NR_INODE)
 161                                 last_inode = inode_table;
 162                         if (!last_inode->i_count) {
 163                                 inode = last_inode;
 164                                 if (!inode->i_dirt && !inode->i_lock)
 165                                         break;
 166                         }
 167                 }
 168                 if (!inode) {
 169                         for (i=0 ; i<NR_INODE ; i++)
 170                                 printk("(%04x: %d (%o)) ",inode_table[i].i_dev,
 171                                         inode_table[i].i_ino,inode_table[i].i_mode);
 172                         panic("No free inodes in mem");
 173                 }
 174                 wait_on_inode(inode);
 175                 while (inode->i_dirt) {
 176                         write_inode(inode);
 177                         wait_on_inode(inode);
 178                 }
 179         } while (inode->i_count);
 180         memset(inode,0,sizeof(*inode));
 181         inode->i_count = 1;
 182         return inode;
 183 }
 184 
 185 struct inode * get_pipe_inode(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         struct inode * inode;
 188 
 189         if (!(inode = get_empty_inode()))
 190                 return NULL;
 191         if (!(inode->i_size = get_free_page(GFP_USER))) {
 192                 inode->i_count = 0;
 193                 return NULL;
 194         }
 195         inode->i_count = 2;     /* sum of readers/writers */
 196         PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
 197         PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
 198         inode->i_pipe = 1;
 199         return inode;
 200 }
 201 
 202 struct inode * iget(int dev,int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         struct inode * inode, * empty;
 205 
 206         if (!dev)
 207                 panic("iget with dev==0");
 208         empty = get_empty_inode();
 209         inode = inode_table;
 210         while (inode < NR_INODE+inode_table) {
 211                 if (inode->i_dev != dev || inode->i_ino != nr) {
 212                         inode++;
 213                         continue;
 214                 }
 215                 wait_on_inode(inode);
 216                 if (inode->i_dev != dev || inode->i_ino != nr) {
 217                         inode = inode_table;
 218                         continue;
 219                 }
 220                 inode->i_count++;
 221                 if (inode->i_mount) {
 222                         int i;
 223 
 224                         for (i = 0 ; i<NR_SUPER ; i++)
 225                                 if (super_block[i].s_covered==inode)
 226                                         break;
 227                         if (i >= NR_SUPER) {
 228                                 printk("Mounted inode hasn't got sb\n");
 229                                 if (empty)
 230                                         iput(empty);
 231                                 return inode;
 232                         }
 233                         iput(inode);
 234                         if (!(inode = super_block[i].s_mounted))
 235                                 printk("iget: mounted dev has no rootinode\n");
 236                         else {
 237                                 inode->i_count++;
 238                                 wait_on_inode(inode);
 239                         }
 240                 }
 241                 if (empty)
 242                         iput(empty);
 243                 return inode;
 244         }
 245         if (!empty)
 246                 return (NULL);
 247         inode = empty;
 248         if (!(inode->i_sb = get_super(dev))) {
 249                 printk("iget: gouldn't get super-block\n\t");
 250                 iput(inode);
 251                 return NULL;
 252         }
 253         inode->i_dev = dev;
 254         inode->i_ino = nr;
 255         inode->i_flags = inode->i_sb->s_flags;
 256         read_inode(inode);
 257         return inode;
 258 }

/* [previous][next][first][last][top][bottom][index][help] */