xref: /minix3/minix/fs/ext2/inode.c (revision ccaeedb267288a9eea9fd8cd1c553aa98bdef60d)
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  *   update_times: update atime, ctime, and mtime
10  *   rw_inode:       read a disk block and extract an inode, or corresp. write
11  *   dup_inode:       indicate that someone else is using an inode table entry
12  *   find_inode:   retrieve pointer to inode in inode cache
13  *
14  * Created (MFS based):
15  *   February 2010 (Evgeniy Ivanov)
16  */
17 
18 #include "fs.h"
19 #include <string.h>
20 #include "buf.h"
21 #include "inode.h"
22 #include "super.h"
23 #include <minix/vfsif.h>
24 
25 static void icopy(struct inode *rip, d_inode *dip, int direction, int
26 	norm);
27 static void addhash_inode(struct inode *node);
28 static void unhash_inode(struct inode *node);
29 
30 
31 /*===========================================================================*
32  *                fs_putnode                                                 *
33  *===========================================================================*/
34 int fs_putnode(void)
35 {
36 /* Find the inode specified by the request message and decrease its counter.*/
37 
38   struct inode *rip;
39   int count;
40 
41   rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_putnode.inode);
42 
43   if (!rip) {
44 	printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__,
45 		__LINE__, fs_m_in.m_vfs_fs_putnode.inode, fs_dev);
46 	panic("fs_putnode failed");
47   }
48 
49   count = fs_m_in.m_vfs_fs_putnode.count;
50   if (count <= 0) {
51 	printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
52 		__LINE__, count);
53 	panic("fs_putnode failed");
54   } else if (count > rip->i_count) {
55 	printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
56 		__LINE__, count, rip->i_count);
57 	panic("fs_putnode failed");
58   }
59 
60   /* Decrease reference counter, but keep one reference;
61    * it will be consumed by put_inode().
62    */
63   rip->i_count -= count - 1;
64   put_inode(rip);
65 
66   return(OK);
67 }
68 
69 
70 /*===========================================================================*
71  *                init_inode_cache                                           *
72  *===========================================================================*/
73 void init_inode_cache()
74 {
75   struct inode *rip;
76   struct inodelist *rlp;
77 
78   inode_cache_hit = 0;
79   inode_cache_miss = 0;
80 
81   /* init free/unused list */
82   TAILQ_INIT(&unused_inodes);
83 
84   /* init hash lists */
85   for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp)
86 	LIST_INIT(rlp);
87 
88   /* add free inodes to unused/free list */
89   for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
90 	rip->i_num = NO_ENTRY;
91 	TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
92   }
93 }
94 
95 
96 /*===========================================================================*
97  *                addhash_inode                                              *
98  *===========================================================================*/
99 static void addhash_inode(struct inode *node)
100 {
101   int hashi = node->i_num & INODE_HASH_MASK;
102 
103   /* insert into hash table */
104   LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
105 }
106 
107 
108 /*===========================================================================*
109  *                unhash_inode                                               *
110  *===========================================================================*/
111 static void unhash_inode(struct inode *node)
112 {
113   /* remove from hash table */
114   LIST_REMOVE(node, i_hash);
115 }
116 
117 
118 /*===========================================================================*
119  *                get_inode                                                  *
120  *===========================================================================*/
121 struct inode *get_inode(
122   dev_t dev,          /* device on which inode resides */
123   ino_t numb         /* inode number (ANSI: may not be unshort) */
124 )
125 {
126 /* Find the inode in the hash table. If it is not there, get a free inode
127  * load it from the disk if it's necessary and put on the hash list
128  */
129   register struct inode *rip;
130   int hashi;
131   int i;
132 
133   hashi = (int) numb & INODE_HASH_MASK;
134 
135   /* Search inode in the hash table */
136   LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
137 	if (rip->i_num == numb && rip->i_dev == dev) {
138 		/* If unused, remove it from the unused/free list */
139 		if (rip->i_count == 0) {
140 			inode_cache_hit++;
141 			TAILQ_REMOVE(&unused_inodes, rip, i_unused);
142 		}
143 		++rip->i_count;
144 		return(rip);
145 	}
146   }
147 
148   inode_cache_miss++;
149 
150   /* Inode is not on the hash, get a free one */
151   if (TAILQ_EMPTY(&unused_inodes)) {
152 	err_code = ENFILE;
153 	return(NULL);
154   }
155   rip = TAILQ_FIRST(&unused_inodes);
156 
157   /* If not free unhash it */
158   if (rip->i_num != NO_ENTRY)
159 	unhash_inode(rip);
160 
161   /* Inode is not unused any more */
162   TAILQ_REMOVE(&unused_inodes, rip, i_unused);
163 
164   /* Load the inode. */
165   rip->i_dev = dev;
166   rip->i_num = numb;
167   rip->i_count = 1;
168   if (dev != NO_DEV)
169 	rw_inode(rip, READING);    /* get inode from disk */
170   rip->i_update = 0;        /* all the times are initially up-to-date */
171   rip->i_last_dpos = 0;     /* no dentries searched for yet */
172   rip->i_bsearch = NO_BLOCK;
173   rip->i_last_pos_bl_alloc = 0;
174   rip->i_last_dentry_size = 0;
175   rip->i_mountpoint= FALSE;
176 
177   rip->i_preallocation = opt.use_prealloc;
178   rip->i_prealloc_count = rip->i_prealloc_index = 0;
179 
180   for (i = 0; i < EXT2_PREALLOC_BLOCKS; i++) {
181 	if (rip->i_prealloc_blocks[i] != NO_BLOCK) {
182 		/* Actually this should never happen */
183 		free_block(rip->i_sp, rip->i_prealloc_blocks[i]);
184 		rip->i_prealloc_blocks[i] = NO_BLOCK;
185 		ext2_debug("Warning: Unexpected preallocated block.");
186 	}
187   }
188 
189   /* Add to hash */
190   addhash_inode(rip);
191 
192   return(rip);
193 }
194 
195 
196 /*===========================================================================*
197  *                find_inode                                                 *
198  *===========================================================================*/
199 struct inode *find_inode(
200   dev_t dev,          /* device on which inode resides */
201   ino_t numb         /* inode number (ANSI: may not be unshort) */
202 )
203 {
204 /* Find the inode specified by the inode and device number. */
205   struct inode *rip;
206   int hashi;
207 
208   hashi = (int) numb & INODE_HASH_MASK;
209 
210   /* Search inode in the hash table */
211   LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
212 	if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) {
213 		return(rip);
214 	}
215   }
216 
217   return(NULL);
218 }
219 
220 
221 /*===========================================================================*
222  *                put_inode                                                  *
223  *===========================================================================*/
224 void put_inode(
225   register struct inode *rip     /* pointer to inode to be released */
226 )
227 {
228 /* The caller is no longer using this inode. If no one else is using it either
229  * write it back to the disk immediately. If it has no links, truncate it and
230  * return it to the pool of available inodes.
231  */
232 
233   if (rip == NULL)
234 	return;    /* checking here is easier than in caller */
235 
236   if (rip->i_count < 1)
237 	panic("put_inode: i_count already below 1: %d", rip->i_count);
238 
239   if (--rip->i_count == 0) {    /* i_count == 0 means no one is using it now */
240 	if (rip->i_links_count == NO_LINK) {
241 		/* i_nlinks == NO_LINK means free the inode. */
242 		/* return all the disk blocks */
243 
244 		/* Ignore errors by truncate_inode in case inode is a block
245 		 * special or character special file.
246 		 */
247 		(void) truncate_inode(rip, (off_t) 0);
248 		/* free inode clears I_TYPE field, since it's used there */
249 		rip->i_dirt = IN_DIRTY;
250 		free_inode(rip);
251 	}
252 
253 	rip->i_mountpoint = FALSE;
254 	if (rip->i_dirt == IN_DIRTY) rw_inode(rip, WRITING);
255 
256 	discard_preallocated_blocks(rip); /* Return blocks to the filesystem */
257 
258 	if (rip->i_links_count == NO_LINK) {
259 		/* free, put at the front of the LRU list */
260 		unhash_inode(rip);
261 		rip->i_num = NO_ENTRY;
262 		TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
263 	} else {
264 		/* unused, put at the back of the LRU (cache it) */
265 		TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
266 	}
267   }
268 }
269 
270 
271 /*===========================================================================*
272  *                update_times                                               *
273  *===========================================================================*/
274 void update_times(
275   register struct inode *rip     /* pointer to inode to be read/written */
276 )
277 {
278 /* Various system calls are required by the standard to update atime, ctime,
279  * or mtime.  Since updating a time requires sending a message to the clock
280  * task--an expensive business--the times are marked for update by setting
281  * bits in i_update. When a stat, fstat, or sync is done, or an inode is
282  * released, update_times() may be called to actually fill in the times.
283  */
284 
285   time_t cur_time;
286   struct super_block *sp;
287 
288   sp = rip->i_sp;         /* get pointer to super block. */
289   if (sp->s_rd_only)
290 	return;             /* no updates for read-only file systems */
291 
292   cur_time = clock_time(NULL);
293   if (rip->i_update & ATIME)
294 	rip->i_atime = cur_time;
295   if (rip->i_update & CTIME)
296 	rip->i_ctime = cur_time;
297   if (rip->i_update & MTIME)
298 	rip->i_mtime = cur_time;
299   rip->i_update = 0;          /* they are all up-to-date now */
300 }
301 
302 /*===========================================================================*
303  *                rw_inode                                                   *
304  *===========================================================================*/
305 void rw_inode(
306   register struct inode *rip,         /* pointer to inode to be read/written */
307   int rw_flag                         /* READING or WRITING */
308 )
309 {
310 /* An entry in the inode table is to be copied to or from the disk. */
311 
312   register struct buf *bp;
313   register struct super_block *sp;
314   register struct group_desc *gd;
315   register d_inode *dip;
316   u32_t block_group_number;
317   block_t b, offset;
318 
319   /* Get the block where the inode resides. */
320   sp = get_super(rip->i_dev);     /* get pointer to super block */
321   rip->i_sp = sp;        /* inode must contain super block pointer */
322 
323   block_group_number = (rip->i_num - 1) / sp->s_inodes_per_group;
324 
325   gd = get_group_desc(block_group_number);
326 
327   if (gd == NULL)
328 	panic("can't get group_desc to read/write inode");
329 
330   offset = ((rip->i_num - 1) % sp->s_inodes_per_group) * EXT2_INODE_SIZE(sp);
331   /* offset requires shifting, since each block contains several inodes,
332    * e.g. inode 2 is stored in bklock 0.
333    */
334   b = (block_t) gd->inode_table + (offset >> sp->s_blocksize_bits);
335   bp = get_block(rip->i_dev, b, NORMAL);
336 
337   offset &= (sp->s_block_size - 1);
338   dip = (d_inode*) (b_data(bp) + offset);
339 
340   /* Do the read or write. */
341   if (rw_flag == WRITING) {
342 	if (rip->i_update)
343 		update_times(rip);    /* times need updating */
344 	if (sp->s_rd_only == FALSE)
345 		lmfs_markdirty(bp);
346   }
347 
348   icopy(rip, dip, rw_flag, TRUE);
349 
350   put_block(bp, INODE_BLOCK);
351   rip->i_dirt = IN_CLEAN;
352 }
353 
354 
355 /*===========================================================================*
356  *				icopy					     *
357  *===========================================================================*/
358 static void icopy(
359   register struct inode *rip,	/* pointer to the in-core inode struct */
360   register d_inode *dip,	/* pointer to the on-disk struct */
361   int direction,		/* READING (from disk) or WRITING (to disk) */
362   int norm			/* TRUE = do not swap bytes; FALSE = swap */
363 )
364 {
365   int i;
366 
367   if (direction == READING) {
368 	/* Copy inode to the in-core table, swapping bytes if need be. */
369 	rip->i_mode    = conv2(norm,dip->i_mode);
370 	rip->i_uid     = conv2(norm,dip->i_uid);
371 	rip->i_size    = conv4(norm,dip->i_size);
372 	rip->i_atime   = conv4(norm,dip->i_atime);
373 	rip->i_ctime   = conv4(norm,dip->i_ctime);
374 	rip->i_mtime   = conv4(norm,dip->i_mtime);
375 	rip->i_dtime   = conv4(norm,dip->i_dtime);
376 	rip->i_gid     = conv2(norm,dip->i_gid);
377 	rip->i_links_count  = conv2(norm,dip->i_links_count);
378 	rip->i_blocks	= conv4(norm,dip->i_blocks);
379 	rip->i_flags	= conv4(norm,dip->i_flags);
380 	/* Minix doesn't touch osd1 and osd2 either, so just copy. */
381 	memcpy(&rip->osd1, &dip->osd1, sizeof(rip->osd1));
382 	for (i = 0; i < EXT2_N_BLOCKS; i++)
383 		rip->i_block[i] = conv4(norm, dip->i_block[i]);
384 	rip->i_generation = conv4(norm,dip->i_generation);
385 	rip->i_file_acl	= conv4(norm,dip->i_file_acl);
386 	rip->i_dir_acl  = conv4(norm,dip->i_dir_acl);
387 	rip->i_faddr	= conv4(norm,dip->i_faddr);
388 	memcpy(&rip->osd2, &dip->osd2, sizeof(rip->osd2));
389   } else {
390 	/* Copying inode to disk from the in-core table. */
391 	dip->i_mode    = conv2(norm,rip->i_mode);
392 	dip->i_uid     = conv2(norm,rip->i_uid);
393 	dip->i_size    = conv4(norm,rip->i_size);
394 	dip->i_atime   = conv4(norm,rip->i_atime);
395 	dip->i_ctime   = conv4(norm,rip->i_ctime);
396 	dip->i_mtime   = conv4(norm,rip->i_mtime);
397 	dip->i_dtime   = conv4(norm,rip->i_dtime);
398 	dip->i_gid     = conv2(norm,rip->i_gid);
399 	dip->i_links_count  = conv2(norm,rip->i_links_count);
400 	dip->i_blocks	= conv4(norm,rip->i_blocks);
401 	dip->i_flags	= conv4(norm,rip->i_flags);
402 	/* Minix doesn't touch osd1 and osd2 either, so just copy. */
403 	memcpy(&dip->osd1, &rip->osd1, sizeof(dip->osd1));
404 	for (i = 0; i < EXT2_N_BLOCKS; i++)
405 		dip->i_block[i] = conv4(norm, rip->i_block[i]);
406 	dip->i_generation  = conv4(norm,rip->i_generation);
407 	dip->i_file_acl = conv4(norm,rip->i_file_acl);
408 	dip->i_dir_acl	= conv4(norm,rip->i_dir_acl);
409 	dip->i_faddr	= conv4(norm,rip->i_faddr);
410 	memcpy(&dip->osd2, &rip->osd2, sizeof(dip->osd2));
411   }
412 }
413 
414 
415 /*===========================================================================*
416  *                dup_inode                                                  *
417  *===========================================================================*/
418 void dup_inode(
419   struct inode *ip         /* The inode to be duplicated. */
420 )
421 {
422 /* This routine is a simplified form of get_inode() for the case where
423  * the inode pointer is already known.
424  */
425   ip->i_count++;
426 }
427