OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [sysv/] [ialloc.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
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
        if (!inode)
60
                return;
61
        if (!inode->i_dev) {
62
                printk("sysv_free_inode: inode has no device\n");
63
                return;
64
        }
65
        if (inode->i_count != 1) {
66
                printk("sysv_free_inode: inode has count=%ld\n", inode->i_count);
67
                return;
68
        }
69
        if (inode->i_nlink) {
70
                printk("sysv_free_inode: inode has nlink=%d\n", inode->i_nlink);
71
                return;
72
        }
73
        if (!(sb = inode->i_sb)) {
74
                printk("sysv_free_inode: inode on nonexistent device\n");
75
                return;
76
        }
77
        ino = inode->i_ino;
78
        if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) {
79
                printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
80
                return;
81
        }
82
        if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) {
83
                printk("sysv_free_inode: unable to read inode block on device "
84
                       "%s\n", kdevname(inode->i_dev));
85
                clear_inode(inode);
86
                return;
87
        }
88
        raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
89
        lock_super(sb);
90
        if (*sb->sv_sb_fic_count < sb->sv_fic_size)
91
                *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino;
92
        (*sb->sv_sb_total_free_inodes)++;
93
        mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
94
        if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
95
        sb->s_dirt = 1; /* and needs time stamp */
96
        memset(raw_inode, 0, sizeof(struct sysv_inode));
97
        mark_buffer_dirty(bh, 1);
98
        unlock_super(sb);
99
        brelse(bh);
100
        clear_inode(inode);
101
}
102
 
103
struct inode * sysv_new_inode(const struct inode * dir)
104
{
105
        struct inode * inode;
106
        struct super_block * sb;
107
        struct buffer_head * bh;
108
        struct sysv_inode * raw_inode;
109
        int i,j,ino,block;
110
 
111
        if (!dir || !(inode = get_empty_inode()))
112
                return NULL;
113
        sb = dir->i_sb;
114
        inode->i_sb = sb;
115
        inode->i_flags = inode->i_sb->s_flags;
116
        lock_super(sb);         /* protect against task switches */
117
        if ((*sb->sv_sb_fic_count == 0)
118
            || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */
119
           ) {
120
                /* Rebuild cache of free inodes: */
121
                /* i : index into cache slot being filled            */
122
                /* ino : inode we are trying                         */
123
                /* block : firstinodezone + (ino-1)/inodes_per_block */
124
                /* j : (ino-1)%inodes_per_block                      */
125
                /* bh : buffer for block                             */
126
                /* raw_inode : pointer to inode ino in the block     */
127
                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) {
128
                        if (!(bh = sv_bread(sb, sb->s_dev, block))) {
129
                                printk("sysv_new_inode: unable to read inode table\n");
130
                                break;  /* go with what we've got */
131
                                /* FIXME: Perhaps try the next block? */
132
                        }
133
                        raw_inode = (struct sysv_inode *) bh->b_data + j;
134
                        for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
135
                                if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
136
                                        *sv_sb_fic_inode(sb,i++) = ino;
137
                        }
138
                        brelse(bh);
139
                }
140
                if (i == 0) {
141
                        iput(inode);
142
                        unlock_super(sb);
143
                        return NULL;    /* no inodes available */
144
                }
145
                *sb->sv_sb_fic_count = i;
146
        }
147
        /* Now *sb->sv_sb_fic_count > 0. */
148
        ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count));
149
        mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
150
        if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
151
        sb->s_dirt = 1; /* and needs time stamp */
152
        inode->i_count = 1;
153
        inode->i_nlink = 1;
154
        inode->i_dev = sb->s_dev;
155
        inode->i_uid = current->fsuid;
156
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
157
        inode->i_dirt = 1;
158
        inode->i_ino = ino;
159
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
160
        inode->i_op = NULL;
161
        inode->i_blocks = inode->i_blksize = 0;
162
        insert_inode_hash(inode);
163
        /* Change directory entry: */
164
        inode->i_mode = 0;               /* for sysv_write_inode() */
165
        inode->i_size = 0;               /* ditto */
166
        sysv_write_inode(inode);        /* ensure inode not allocated again */
167
                                        /* FIXME: caller may call this too. */
168
        inode->i_dirt = 1;              /* cleared by sysv_write_inode() */
169
        /* That's it. */
170
        (*sb->sv_sb_total_free_inodes)--;
171
        mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */
172
        sb->s_dirt = 1; /* and needs time stamp again */
173
        unlock_super(sb);
174
        return inode;
175
}
176
 
177
unsigned long sysv_count_free_inodes(struct super_block * sb)
178
{
179
#if 1 /* test */
180
        struct buffer_head * bh;
181
        struct sysv_inode * raw_inode;
182
        int j,block,count;
183
 
184
        /* this causes a lot of disk traffic ... */
185
        count = 0;
186
        lock_super(sb);
187
        /* i : index into cache slot being filled            */
188
        /* ino : inode we are trying                         */
189
        /* block : firstinodezone + (ino-1)/inodes_per_block */
190
        /* j : (ino-1)%inodes_per_block                      */
191
        /* bh : buffer for block                             */
192
        /* raw_inode : pointer to inode ino in the block     */
193
        for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
194
                if (!(bh = sv_bread(sb, sb->s_dev, block))) {
195
                        printk("sysv_count_free_inodes: unable to read inode table\n");
196
                        break;  /* go with what we've got */
197
                        /* FIXME: Perhaps try the next block? */
198
                }
199
                raw_inode = (struct sysv_inode *) bh->b_data + j;
200
                for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
201
                        if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
202
                                count++;
203
                brelse(bh);
204
        }
205
        if (count != *sb->sv_sb_total_free_inodes) {
206
                printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
207
                if (!(sb->s_flags & MS_RDONLY)) {
208
                        *sb->sv_sb_total_free_inodes = count;
209
                        mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */
210
                        sb->s_dirt = 1; /* and needs time stamp */
211
                }
212
        }
213
        unlock_super(sb);
214
        return count;
215
#else
216
        return *sb->sv_sb_total_free_inodes;
217
#endif
218
}
219
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.