~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/sysv/ialloc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/sysv/ialloc.c
  3  *
  4  *  minix/bitmap.c
  5  *  Copyright (C) 1991, 1992  Linus Torvalds
  6  *
  7  *  ext/freelists.c
  8  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  9  *
 10  *  xenix/alloc.c
 11  *  Copyright (C) 1992  Doug Evans
 12  *
 13  *  coh/alloc.c
 14  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
 15  *
 16  *  sysv/ialloc.c
 17  *  Copyright (C) 1993  Bruno Haible
 18  *
 19  *  This file contains code for allocating/freeing inodes.
 20  */
 21 
 22 #include <linux/sched.h>
 23 #include <linux/kernel.h>
 24 #include <linux/fs.h>
 25 #include <linux/sysv_fs.h>
 26 #include <linux/stddef.h>
 27 #include <linux/stat.h>
 28 #include <linux/string.h>
 29 #include <linux/locks.h>
 30 
 31 /* We don't trust the value of
 32    sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes
 33    but we nevertheless keep it up to date. */
 34 
 35 /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
 36 
 37 /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
 38 static inline sysv_ino_t * sv_sb_fic_inode (struct super_block * sb, unsigned int i)
 39 {
 40         if (sb->sv_bh1 == sb->sv_bh2)
 41                 return &sb->sv_sb_fic_inodes[i];
 42         else {
 43                 /* 512 byte Xenix FS */
 44                 unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
 45                 if (offset < 512)
 46                         return (sysv_ino_t*)(sb->sv_sbd1 + offset);
 47                 else
 48                         return (sysv_ino_t*)(sb->sv_sbd2 + offset);
 49         }
 50 }
 51 
 52 void sysv_free_inode(struct inode * inode)
 53 {
 54         struct super_block * sb;
 55         unsigned int ino;
 56         struct buffer_head * bh;
 57         struct sysv_inode * raw_inode;
 58 
 59         sb = inode->i_sb;
 60         ino = inode->i_ino;
 61         if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) {
 62                 printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
 63                 return;
 64         }
 65         if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) {
 66                 printk("sysv_free_inode: unable to read inode block on device "
 67                        "%s\n", kdevname(inode->i_dev));
 68                 clear_inode(inode);
 69                 return;
 70         }
 71         raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
 72         clear_inode(inode);
 73         lock_super(sb);
 74         if (*sb->sv_sb_fic_count < sb->sv_fic_size)
 75                 *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino;
 76         (*sb->sv_sb_total_free_inodes)++;
 77         mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
 78         if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
 79         sb->s_dirt = 1; /* and needs time stamp */
 80         memset(raw_inode, 0, sizeof(struct sysv_inode));
 81         mark_buffer_dirty(bh);
 82         unlock_super(sb);
 83         brelse(bh);
 84 }
 85 
 86 struct inode * sysv_new_inode(const struct inode * dir)
 87 {
 88         struct inode * inode;
 89         struct super_block * sb;
 90         struct buffer_head * bh;
 91         struct sysv_inode * raw_inode;
 92         int i,j,ino,block;
 93 
 94         if (!dir)
 95                 return NULL;
 96         sb = dir->i_sb;
 97         inode = new_inode(sb);
 98         if (!inode)
 99                 return NULL;
100         lock_super(sb);         /* protect against task switches */
101         if ((*sb->sv_sb_fic_count == 0)
102             || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */
103            ) {
104                 /* Rebuild cache of free inodes: */
105                 /* i : index into cache slot being filled            */
106                 /* ino : inode we are trying                         */
107                 /* block : firstinodezone + (ino-1)/inodes_per_block */
108                 /* j : (ino-1)%inodes_per_block                      */
109                 /* bh : buffer for block                             */
110                 /* raw_inode : pointer to inode ino in the block     */
111                 for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) {
112                         if (!(bh = sv_bread(sb, sb->s_dev, block))) {
113                                 printk("sysv_new_inode: unable to read inode table\n");
114                                 break;  /* go with what we've got */
115                                 /* FIXME: Perhaps try the next block? */
116                         }
117                         raw_inode = (struct sysv_inode *) bh->b_data + j;
118                         for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
119                                 if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
120                                         *sv_sb_fic_inode(sb,i++) = ino;
121                         }
122                         brelse(bh);
123                 }
124                 if (i == 0) {
125                         iput(inode);
126                         unlock_super(sb);
127                         return NULL;    /* no inodes available */
128                 }
129                 *sb->sv_sb_fic_count = i;
130         }
131         /* Now *sb->sv_sb_fic_count > 0. */
132         ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count));
133         mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
134         if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
135         sb->s_dirt = 1; /* and needs time stamp */
136         inode->i_uid = current->fsuid;
137         inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
138         inode->i_ino = ino;
139         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
140         inode->i_blocks = inode->i_blksize = 0;
141         insert_inode_hash(inode);
142         mark_inode_dirty(inode);
143         /* Change directory entry: */
144         inode->i_mode = 0;              /* for sysv_write_inode() */
145         sysv_write_inode(inode, 0);     /* ensure inode not allocated again */
146                                         /* FIXME: caller may call this too. */
147         mark_inode_dirty(inode);        /* cleared by sysv_write_inode() */
148         /* That's it. */
149         (*sb->sv_sb_total_free_inodes)--;
150         mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified again */
151         sb->s_dirt = 1; /* and needs time stamp again */
152         unlock_super(sb);
153         return inode;
154 }
155 
156 unsigned long sysv_count_free_inodes(struct super_block * sb)
157 {
158 #if 1 /* test */
159         struct buffer_head * bh;
160         struct sysv_inode * raw_inode;
161         int j,block,count;
162 
163         /* this causes a lot of disk traffic ... */
164         count = 0;
165         lock_super(sb);
166         /* i : index into cache slot being filled            */
167         /* ino : inode we are trying                         */
168         /* block : firstinodezone + (ino-1)/inodes_per_block */
169         /* j : (ino-1)%inodes_per_block                      */
170         /* bh : buffer for block                             */
171         /* raw_inode : pointer to inode ino in the block     */
172         for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
173                 if (!(bh = sv_bread(sb, sb->s_dev, block))) {
174                         printk("sysv_count_free_inodes: unable to read inode table\n");
175                         break;  /* go with what we've got */
176                         /* FIXME: Perhaps try the next block? */
177                 }
178                 raw_inode = (struct sysv_inode *) bh->b_data + j;
179                 for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
180                         if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
181                                 count++;
182                 brelse(bh);
183         }
184         if (count != *sb->sv_sb_total_free_inodes) {
185                 printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
186                 if (!(sb->s_flags & MS_RDONLY)) {
187                         *sb->sv_sb_total_free_inodes = count;
188                         mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */
189                         sb->s_dirt = 1; /* and needs time stamp */
190                 }
191         }
192         unlock_super(sb);
193         return count;
194 #else
195         return *sb->sv_sb_total_free_inodes;
196 #endif
197 }
198 
199 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.