mkfs, mkproto: minor improvements
[minix.git] / servers / mfs / inode.c
blob8ae695faaa95eb1ba01f446dcb59f73c0243b491
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.
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 * alloc_inode: allocate a new, unused inode
10 * wipe_inode: erase some fields of a newly allocated inode
11 * free_inode: mark an inode as available for a new file
12 * update_times: update atime, ctime, and mtime
13 * rw_inode: read a disk block and extract an inode, or corresp. write
14 * dup_inode: indicate that someone else is using an inode table entry
15 * find_inode: retrieve pointer to inode in inode cache
19 #include "fs.h"
20 #include "buf.h"
21 #include "inode.h"
22 #include "super.h"
23 #include <minix/vfsif.h>
25 static void addhash_inode(struct inode *node);
27 static void free_inode(dev_t dev, ino_t numb);
28 static void new_icopy(struct inode *rip, d2_inode *dip, int direction,
29 int norm);
30 static void old_icopy(struct inode *rip, d1_inode *dip, int direction,
31 int norm);
32 static void unhash_inode(struct inode *node);
33 static void wipe_inode(struct inode *rip);
36 /*===========================================================================*
37 * fs_putnode *
38 *===========================================================================*/
39 int fs_putnode(void)
41 /* Find the inode specified by the request message and decrease its counter.*/
43 struct inode *rip;
44 int count;
46 rip = find_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR);
48 if(!rip) {
49 printf("%s:%d put_inode: inode #%lu dev: %d not found\n", __FILE__,
50 __LINE__, (ino_t) fs_m_in.REQ_INODE_NR, fs_dev);
51 panic("fs_putnode failed");
54 count = fs_m_in.REQ_COUNT;
55 if (count <= 0) {
56 printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
57 __LINE__, count);
58 panic("fs_putnode failed");
59 } else if(count > rip->i_count) {
60 printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
61 __LINE__, count, rip->i_count);
62 panic("fs_putnode failed");
65 /* Decrease reference counter, but keep one reference; it will be consumed by
66 * put_inode(). */
67 rip->i_count -= count - 1;
68 put_inode(rip);
70 return(OK);
74 /*===========================================================================*
75 * init_inode_cache *
76 *===========================================================================*/
77 void init_inode_cache()
79 struct inode *rip;
80 struct inodelist *rlp;
82 inode_cache_hit = 0;
83 inode_cache_miss = 0;
85 /* init free/unused list */
86 TAILQ_INIT(&unused_inodes);
88 /* init hash lists */
89 for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp)
90 LIST_INIT(rlp);
92 /* add free inodes to unused/free list */
93 for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
94 rip->i_num = NO_ENTRY;
95 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
100 /*===========================================================================*
101 * addhash_inode *
102 *===========================================================================*/
103 static void addhash_inode(struct inode *node)
105 int hashi = (int) (node->i_num & INODE_HASH_MASK);
107 /* insert into hash table */
108 LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
112 /*===========================================================================*
113 * unhash_inode *
114 *===========================================================================*/
115 static void unhash_inode(struct inode *node)
117 /* remove from hash table */
118 LIST_REMOVE(node, i_hash);
122 /*===========================================================================*
123 * get_inode *
124 *===========================================================================*/
125 struct inode *get_inode(
126 dev_t dev, /* device on which inode resides */
127 ino_t numb /* inode number */
130 /* Find the inode in the hash table. If it is not there, get a free inode
131 * load it from the disk if it's necessary and put on the hash list
133 register struct inode *rip;
134 int hashi;
136 hashi = (int) (numb & INODE_HASH_MASK);
138 /* Search inode in the hash table */
139 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
140 if (rip->i_num == numb && rip->i_dev == dev) {
141 /* If unused, remove it from the unused/free list */
142 if (rip->i_count == 0) {
143 inode_cache_hit++;
144 TAILQ_REMOVE(&unused_inodes, rip, i_unused);
146 ++rip->i_count;
147 return(rip);
151 inode_cache_miss++;
153 /* Inode is not on the hash, get a free one */
154 if (TAILQ_EMPTY(&unused_inodes)) {
155 err_code = ENFILE;
156 return(NULL);
158 rip = TAILQ_FIRST(&unused_inodes);
160 /* If not free unhash it */
161 if (rip->i_num != NO_ENTRY)
162 unhash_inode(rip);
164 /* Inode is not unused any more */
165 TAILQ_REMOVE(&unused_inodes, rip, i_unused);
167 /* Load the inode. */
168 rip->i_dev = dev;
169 rip->i_num = numb;
170 rip->i_count = 1;
171 if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */
172 rip->i_update = 0; /* all the times are initially up-to-date */
173 rip->i_zsearch = NO_ZONE; /* no zones searched for yet */
174 rip->i_mountpoint= FALSE;
175 rip->i_last_dpos = 0; /* no dentries searched for yet */
177 /* Add to hash */
178 addhash_inode(rip);
180 return(rip);
184 /*===========================================================================*
185 * find_inode *
186 *===========================================================================*/
187 struct inode *find_inode(
188 dev_t dev, /* device on which inode resides */
189 ino_t numb /* inode number */
192 /* Find the inode specified by the inode and device number.
194 struct inode *rip;
195 int hashi;
197 hashi = (int) (numb & INODE_HASH_MASK);
199 /* Search inode in the hash table */
200 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
201 if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) {
202 return(rip);
206 return(NULL);
210 /*===========================================================================*
211 * put_inode *
212 *===========================================================================*/
213 void put_inode(rip)
214 register struct inode *rip; /* pointer to inode to be released */
216 /* The caller is no longer using this inode. If no one else is using it either
217 * write it back to the disk immediately. If it has no links, truncate it and
218 * return it to the pool of available inodes.
221 if (rip == NULL) return; /* checking here is easier than in caller */
223 if (rip->i_count < 1)
224 panic("put_inode: i_count already below 1: %d", rip->i_count);
226 if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */
227 if (rip->i_nlinks == NO_LINK) {
228 /* i_nlinks == NO_LINK means free the inode. */
229 /* return all the disk blocks */
231 /* Ignore errors by truncate_inode in case inode is a block
232 * special or character special file.
234 (void) truncate_inode(rip, (off_t) 0);
235 rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */
236 IN_MARKDIRTY(rip);
237 free_inode(rip->i_dev, rip->i_num);
240 rip->i_mountpoint = FALSE;
241 if (IN_ISDIRTY(rip)) rw_inode(rip, WRITING);
243 if (rip->i_nlinks == NO_LINK) {
244 /* free, put at the front of the LRU list */
245 unhash_inode(rip);
246 rip->i_num = NO_ENTRY;
247 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
248 } else {
249 /* unused, put at the back of the LRU (cache it) */
250 TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
256 /*===========================================================================*
257 * alloc_inode *
258 *===========================================================================*/
259 struct inode *alloc_inode(dev_t dev, mode_t bits)
261 /* Allocate a free inode on 'dev', and return a pointer to it. */
263 register struct inode *rip;
264 register struct super_block *sp;
265 int major, minor, inumb;
266 bit_t b;
268 sp = get_super(dev); /* get pointer to super_block */
269 if (sp->s_rd_only) { /* can't allocate an inode on a read only device. */
270 err_code = EROFS;
271 return(NULL);
274 /* Acquire an inode from the bit map. */
275 b = alloc_bit(sp, IMAP, sp->s_isearch);
276 if (b == NO_BIT) {
277 err_code = ENOSPC;
278 major = (int) (sp->s_dev >> MAJOR) & BYTE;
279 minor = (int) (sp->s_dev >> MINOR) & BYTE;
280 printf("Out of i-nodes on device %d/%d\n", major, minor);
281 return(NULL);
283 sp->s_isearch = b; /* next time start here */
284 inumb = (int) b; /* be careful not to pass unshort as param */
286 /* Try to acquire a slot in the inode table. */
287 if ((rip = get_inode(NO_DEV, inumb)) == NULL) {
288 /* No inode table slots available. Free the inode just allocated. */
289 free_bit(sp, IMAP, b);
290 } else {
291 /* An inode slot is available. Put the inode just allocated into it. */
292 rip->i_mode = bits; /* set up RWX bits */
293 rip->i_nlinks = NO_LINK; /* initial no links */
294 rip->i_uid = caller_uid; /* file's uid is owner's */
295 rip->i_gid = caller_gid; /* ditto group id */
296 rip->i_dev = dev; /* mark which device it is on */
297 rip->i_ndzones = sp->s_ndzones; /* number of direct zones */
298 rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/
299 rip->i_sp = sp; /* pointer to super block */
301 /* Fields not cleared already are cleared in wipe_inode(). They have
302 * been put there because truncate() needs to clear the same fields if
303 * the file happens to be open while being truncated. It saves space
304 * not to repeat the code twice.
306 wipe_inode(rip);
309 return(rip);
313 /*===========================================================================*
314 * wipe_inode *
315 *===========================================================================*/
316 static void wipe_inode(rip)
317 register struct inode *rip; /* the inode to be erased */
319 /* Erase some fields in the inode. This function is called from alloc_inode()
320 * when a new inode is to be allocated, and from truncate(), when an existing
321 * inode is to be truncated.
324 register int i;
326 rip->i_size = 0;
327 rip->i_update = ATIME | CTIME | MTIME; /* update all times later */
328 IN_MARKDIRTY(rip);
329 for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
332 /*===========================================================================*
333 * free_inode *
334 *===========================================================================*/
335 static void free_inode(
336 dev_t dev, /* on which device is the inode? */
337 ino_t inumb /* number of the inode to be freed */
340 /* Return an inode to the pool of unallocated inodes. */
342 register struct super_block *sp;
343 bit_t b;
345 /* Locate the appropriate super_block. */
346 sp = get_super(dev);
347 if (inumb == NO_ENTRY || inumb > sp->s_ninodes) return;
348 b = (bit_t) inumb;
349 free_bit(sp, IMAP, b);
350 if (b < sp->s_isearch) sp->s_isearch = b;
354 /*===========================================================================*
355 * update_times *
356 *===========================================================================*/
357 void update_times(rip)
358 register struct inode *rip; /* pointer to inode to be read/written */
360 /* Various system calls are required by the standard to update atime, ctime,
361 * or mtime. Since updating a time requires sending a message to the clock
362 * task--an expensive business--the times are marked for update by setting
363 * bits in i_update. When a stat, fstat, or sync is done, or an inode is
364 * released, update_times() may be called to actually fill in the times.
367 time_t cur_time;
368 struct super_block *sp;
370 sp = rip->i_sp; /* get pointer to super block. */
371 if (sp->s_rd_only) return; /* no updates for read-only file systems */
373 cur_time = clock_time();
374 if (rip->i_update & ATIME) rip->i_atime = cur_time;
375 if (rip->i_update & CTIME) rip->i_ctime = cur_time;
376 if (rip->i_update & MTIME) rip->i_mtime = cur_time;
377 rip->i_update = 0; /* they are all up-to-date now */
380 /*===========================================================================*
381 * rw_inode *
382 *===========================================================================*/
383 void rw_inode(rip, rw_flag)
384 register struct inode *rip; /* pointer to inode to be read/written */
385 int rw_flag; /* READING or WRITING */
387 /* An entry in the inode table is to be copied to or from the disk. */
389 register struct buf *bp;
390 register struct super_block *sp;
391 d1_inode *dip;
392 d2_inode *dip2;
393 block_t b, offset;
395 /* Get the block where the inode resides. */
396 sp = get_super(rip->i_dev); /* get pointer to super block */
397 rip->i_sp = sp; /* inode must contain super block pointer */
398 offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks;
399 b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
400 bp = get_block(rip->i_dev, b, NORMAL);
401 dip = b_v1_ino(bp) + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
402 dip2 = b_v2_ino(bp) + (rip->i_num - 1) %
403 V2_INODES_PER_BLOCK(sp->s_block_size);
405 /* Do the read or write. */
406 if (rw_flag == WRITING) {
407 if (rip->i_update) update_times(rip); /* times need updating */
408 if (sp->s_rd_only == FALSE) MARKDIRTY(bp);
411 /* Copy the inode from the disk block to the in-core table or vice versa.
412 * If the fourth parameter below is FALSE, the bytes are swapped.
414 if (sp->s_version == V1)
415 old_icopy(rip, dip, rw_flag, sp->s_native);
416 else
417 new_icopy(rip, dip2, rw_flag, sp->s_native);
419 put_block(bp, INODE_BLOCK);
420 IN_MARKCLEAN(rip);
424 /*===========================================================================*
425 * old_icopy *
426 *===========================================================================*/
427 static void old_icopy(rip, dip, direction, norm)
428 register struct inode *rip; /* pointer to the in-core inode struct */
429 register d1_inode *dip; /* pointer to the d1_inode inode struct */
430 int direction; /* READING (from disk) or WRITING (to disk) */
431 int norm; /* TRUE = do not swap bytes; FALSE = swap */
433 /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
434 * 68000) all have different inode layouts. When an inode is read or written
435 * this routine handles the conversions so that the information in the inode
436 * table is independent of the disk structure from which the inode came.
437 * The old_icopy routine copies to and from V1 disks.
440 int i;
442 if (direction == READING) {
443 /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
444 rip->i_mode = (mode_t) conv2(norm, (int) dip->d1_mode);
445 rip->i_uid = (uid_t) conv2(norm, (int) dip->d1_uid );
446 rip->i_size = (off_t) conv4(norm, dip->d1_size);
447 rip->i_mtime = (time_t) conv4(norm, dip->d1_mtime);
448 rip->i_atime = (time_t) rip->i_mtime;
449 rip->i_ctime = (time_t) rip->i_mtime;
450 rip->i_nlinks = (nlink_t) dip->d1_nlinks; /* 1 char */
451 rip->i_gid = (gid_t) dip->d1_gid; /* 1 char */
452 rip->i_ndzones = V1_NR_DZONES;
453 rip->i_nindirs = V1_INDIRECTS;
454 for (i = 0; i < V1_NR_TZONES; i++)
455 rip->i_zone[i] = (zone_t) conv2(norm, (int) dip->d1_zone[i]);
456 } else {
457 /* Copying V1.x inode to disk from the in-core table. */
458 dip->d1_mode = (u16_t) conv2(norm, (int) rip->i_mode);
459 dip->d1_uid = (i16_t) conv2(norm, (int) rip->i_uid );
460 dip->d1_size = (i32_t) conv4(norm, rip->i_size);
461 dip->d1_mtime = (i32_t) conv4(norm, rip->i_mtime);
462 dip->d1_nlinks = (u8_t) rip->i_nlinks; /* 1 char */
463 dip->d1_gid = (u8_t) rip->i_gid; /* 1 char */
464 for (i = 0; i < V1_NR_TZONES; i++)
465 dip->d1_zone[i] = (u16_t) conv2(norm, (int) rip->i_zone[i]);
470 /*===========================================================================*
471 * new_icopy *
472 *===========================================================================*/
473 static void new_icopy(rip, dip, direction, norm)
474 register struct inode *rip; /* pointer to the in-core inode struct */
475 register d2_inode *dip; /* pointer to the d2_inode struct */
476 int direction; /* READING (from disk) or WRITING (to disk) */
477 int norm; /* TRUE = do not swap bytes; FALSE = swap */
479 /* Same as old_icopy, but to/from V2 disk layout. */
481 int i;
483 if (direction == READING) {
484 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
485 rip->i_mode = (mode_t) conv2(norm,dip->d2_mode);
486 rip->i_uid = (uid_t) conv2(norm,dip->d2_uid);
487 rip->i_nlinks = (nlink_t) conv2(norm,dip->d2_nlinks);
488 rip->i_gid = (gid_t) conv2(norm,dip->d2_gid);
489 rip->i_size = (off_t) conv4(norm,dip->d2_size);
490 rip->i_atime = (time_t) conv4(norm,dip->d2_atime);
491 rip->i_ctime = (time_t) conv4(norm,dip->d2_ctime);
492 rip->i_mtime = (time_t) conv4(norm,dip->d2_mtime);
493 rip->i_ndzones = V2_NR_DZONES;
494 rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size);
495 for (i = 0; i < V2_NR_TZONES; i++)
496 rip->i_zone[i] = (zone_t) conv4(norm, (long) dip->d2_zone[i]);
497 } else {
498 /* Copying V2.x inode to disk from the in-core table. */
499 dip->d2_mode = (u16_t) conv2(norm,rip->i_mode);
500 dip->d2_uid = (i16_t) conv2(norm,rip->i_uid);
501 dip->d2_nlinks = (u16_t) conv2(norm,rip->i_nlinks);
502 dip->d2_gid = (u16_t) conv2(norm,rip->i_gid);
503 dip->d2_size = (i32_t) conv4(norm,rip->i_size);
504 dip->d2_atime = (i32_t) conv4(norm,rip->i_atime);
505 dip->d2_ctime = (i32_t) conv4(norm,rip->i_ctime);
506 dip->d2_mtime = (i32_t) conv4(norm,rip->i_mtime);
507 for (i = 0; i < V2_NR_TZONES; i++)
508 dip->d2_zone[i] = (zone_t) conv4(norm, (long) rip->i_zone[i]);
513 /*===========================================================================*
514 * dup_inode *
515 *===========================================================================*/
516 void dup_inode(ip)
517 struct inode *ip; /* The inode to be duplicated. */
519 /* This routine is a simplified form of get_inode() for the case where
520 * the inode pointer is already known.
523 ip->i_count++;