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