kbd: use a better get_key method
[thunix.git] / fs / tfs / inode.c
blob53a6e68bba08f9a1755e1848c759400152ddc06a
1 #include <stdio.h>
2 #include <string.h>
3 #include <malloc.h>
4 #include <thunix.h>
5 #include <err.h>
6 #include <fs.h>
7 #include <tfs.h>
8 #include <cache.h>
9 #include <dirent.h>
11 #define current_time 0
14 * release all the stuff related to the inode
16 int tfs_release_inode(struct tfs_sb_info *sbi, struct inode *inode)
18 int inr = inode->i_ino;
19 int index = 0;
20 int block;
21 int res = 0;
23 if (!inode) {
24 printk("ERROR: trying to free a NULL inode!\n");
25 return -1;
28 TFS_DEBUG("trying to release inode: %d\n", inr);
30 res = tfs_free_inode(sbi, inr);
31 if (res < 0) {
32 TFS_DEBUG("ERROR: trying to free inode %d failed!\n", inr);
33 return res;
36 while ((block = tfs_bmap(inode, index++))) {
37 res = tfs_free_block(sbi, block);
38 if (res < 0)
39 break;
42 free_inode(inode);
43 return res;
47 struct inode * tfs_new_inode(struct inode *dir, int mode, int data_size)
49 struct inode *inode;
50 int inr;
52 inode = new_inode(mode, data_size);
53 if (!inode)
54 return ERR_PTR(-ENOMEM);
56 /*
57 * allocate it start from TFS_ROOT_INODE, so only the first one
58 * will get it:)
59 */
60 inr = tfs_alloc_inode(TFS_SBI(dir->i_fs), TFS_ROOT_INODE);
61 if (inr < 0) {
62 free(inode);
63 return ERR_PTR(inr);
66 inode->i_ino = inr;
69 * FIXME: new_inode() doesn't init the i_blksize filed. And in
70 * here, we assign this filed with the dir's i_blksize; this is
71 * out design. But in iget_...() function, then are assigned from
72 * fs->block_size.
74 * We should make the assigment be constant.
76 inode->i_blksize = dir->i_blksize;
78 inode->i_op = &tfs_inode_ops;
79 inode->i_fop = &tfs_file_ops;
81 return inode;
85 static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode)
87 //inode->i_mode = get_mode(tinode->i_mode);
88 inode->i_mode = tinode->i_mode;
89 inode->i_size = tinode->i_size;
90 inode->i_atime = tinode->i_atime;
91 inode->i_ctime = tinode->i_ctime;
92 inode->i_mtime = tinode->i_mtime;
93 inode->i_dtime = tinode->i_dtime;
94 inode->i_flags = tinode->i_flags;
96 memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *));
99 static int tfs_read_inode(struct fs *fs, struct tfs_inode *tinode, int inr)
101 uint32_t inode_block;
102 struct cache_struct *cs;
103 struct tfs_sb_info *sbi = TFS_SBI(fs);
105 inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi);
106 cs = get_cache_block(fs, inode_block);
107 if (IS_ERR(cs))
108 return -EIO;
110 memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode));
112 return 0;
115 struct inode * tfs_iget_by_inr(struct fs *fs, int inr)
117 struct inode *inode;
118 struct tfs_inode tinode;
119 int err;
121 err = tfs_read_inode(fs, &tinode, inr);
122 if (err)
123 return ERR_PTR(err);
125 inode = new_inode(0, TFS_N_BLOCKS * sizeof(uint32_t *));
126 if (inode) {
127 tfs_fill_inode(inode, &tinode);
128 inode->i_blksize = BLOCK_SIZE(fs);
129 inode->i_ino = inr;
130 } else {
131 return ERR_PTR(-ENOMEM);
134 inode->i_op = &tfs_inode_ops;
135 inode->i_fop = &tfs_file_ops;
137 return inode;
140 struct inode *tfs_iget_root(struct fs *fs)
142 return tfs_iget_by_inr(fs, TFS_ROOT_INODE);
145 struct inode *tfs_iget(const char *dname, struct inode *dir)
147 struct tfs_dir_entry *de;
148 struct cache_struct *cs;
150 cs = tfs_find_entry(dir, dname, &de);
151 if (IS_ERR_OR_NULL(cs))
152 return cs ? ERR_CAST(cs) : ERR_PTR(-ENOENT);
154 return tfs_iget_by_inr(dir->i_fs, de->d_inode);
157 static void tfs_write_inode(struct tfs_inode *tinode, struct inode *inode)
159 tinode->i_mode = inode->i_mode;
160 tinode->i_size = inode->i_size;
161 tinode->i_atime = inode->i_atime;
162 tinode->i_ctime = inode->i_ctime;
163 tinode->i_mtime = inode->i_mtime;
164 tinode->i_dtime = inode->i_dtime;
165 tinode->i_flags = inode->i_flags;
167 memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *));
168 tinode->i_reserved[0] = 0;
172 int tfs_iwrite(struct inode *inode)
174 struct cache_struct *cs;
175 struct tfs_inode *tinode;
176 struct tfs_sb_info *sbi = TFS_SBI(inode->i_fs);
177 uint32_t inode_block;
178 int err = 0;
180 inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi);
181 cs = get_cache_block(inode->i_fs, inode_block);
182 if (!cs)
183 return -EIO;
184 tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi));
185 tfs_write_inode(tinode, inode);
186 err = tfs_bwrite(sbi, inode_block, cs->data);
188 return err;
191 uint32_t tfs_bmap(struct inode *inode, int index)
193 if (index >= TFS_N_BLOCKS)
194 return 0;
196 return inode->i_data[index];
200 struct inode * tfs_mknod(struct inode *dir, const char *dname, int mode)
202 struct inode *inode;
203 struct tfs_dir_entry *de;
204 struct cache_struct *cs;
205 struct tfs_sb_info *sbi = TFS_SBI(dir->i_fs);
206 int dirty = 0;
207 int err;
209 TFS_DEBUG("mknod: dir->inode: %d, name: %s\n", dir->i_ino, dname);
211 cs = tfs_find_entry(dir, dname, &de);
212 if (!IS_ERR_OR_NULL(cs))
213 return ERR_PTR(-EEXIST);
215 inode = tfs_new_inode(dir, mode, TFS_N_BLOCKS * sizeof(uint32_t *));
216 if (IS_ERR(inode))
217 return ERR_CAST(inode);
218 inode->i_mtime = inode->i_atime = current_time;
219 if (tfs_iwrite(inode)) {
220 err = -EIO;
221 goto error;
223 err = tfs_add_entry(dir, dname, inode->i_ino, &dirty);
224 if (err) {
225 TFS_DEBUG("trying to add a new entry: %s faild!\n", dname);
226 goto error;
228 if (dirty) {
229 err = -EIO;
230 if (tfs_iwrite(dir))
231 goto error;
234 return inode;
235 error:
236 free_inode(inode);
237 return ERR_PTR(err);
240 struct inode_operations tfs_inode_ops = {
241 .iget = tfs_iget,
242 .iget_root = tfs_iget_root,
243 .iwrite = tfs_iwrite,
244 .mkdir = tfs_mkdir,
245 .rmdir = tfs_rmdir,
246 .unlink = tfs_unlink,
247 .mknod = tfs_mknod,