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
5 * The entry points into this file are
6 * get_inode: search inode table for a given inode; if not there,
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
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
,
30 static void old_icopy(struct inode
*rip
, d1_inode
*dip
, int direction
,
32 static void unhash_inode(struct inode
*node
);
33 static void wipe_inode(struct inode
*rip
);
36 /*===========================================================================*
38 *===========================================================================*/
41 /* Find the inode specified by the request message and decrease its counter.*/
46 rip
= find_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
);
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
;
56 printf("%s:%d put_inode: bad value for count: %d\n", __FILE__
,
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
67 rip
->i_count
-= count
- 1;
74 /*===========================================================================*
76 *===========================================================================*/
77 void init_inode_cache()
80 struct inodelist
*rlp
;
85 /* init free/unused list */
86 TAILQ_INIT(&unused_inodes
);
89 for (rlp
= &hash_inodes
[0]; rlp
< &hash_inodes
[INODE_HASH_SIZE
]; ++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 /*===========================================================================*
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 /*===========================================================================*
114 *===========================================================================*/
115 static void unhash_inode(struct inode
*node
)
117 /* remove from hash table */
118 LIST_REMOVE(node
, i_hash
);
122 /*===========================================================================*
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
;
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) {
144 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
153 /* Inode is not on the hash, get a free one */
154 if (TAILQ_EMPTY(&unused_inodes
)) {
158 rip
= TAILQ_FIRST(&unused_inodes
);
160 /* If not free unhash it */
161 if (rip
->i_num
!= NO_ENTRY
)
164 /* Inode is not unused any more */
165 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
167 /* Load the inode. */
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 */
184 /*===========================================================================*
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.
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
) {
210 /*===========================================================================*
212 *===========================================================================*/
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 */
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 */
246 rip
->i_num
= NO_ENTRY
;
247 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
249 /* unused, put at the back of the LRU (cache it) */
250 TAILQ_INSERT_TAIL(&unused_inodes
, rip
, i_unused
);
256 /*===========================================================================*
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
;
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. */
274 /* Acquire an inode from the bit map. */
275 b
= alloc_bit(sp
, IMAP
, sp
->s_isearch
);
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
);
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
);
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.
313 /*===========================================================================*
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.
327 rip
->i_update
= ATIME
| CTIME
| MTIME
; /* update all times later */
329 for (i
= 0; i
< V2_NR_TZONES
; i
++) rip
->i_zone
[i
] = NO_ZONE
;
332 /*===========================================================================*
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
;
345 /* Locate the appropriate super_block. */
347 if (inumb
== NO_ENTRY
|| inumb
> sp
->s_ninodes
) return;
349 free_bit(sp
, IMAP
, b
);
350 if (b
< sp
->s_isearch
) sp
->s_isearch
= b
;
354 /*===========================================================================*
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.
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 /*===========================================================================*
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
;
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
);
417 new_icopy(rip
, dip2
, rw_flag
, sp
->s_native
);
419 put_block(bp
, INODE_BLOCK
);
424 /*===========================================================================*
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.
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
]);
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 /*===========================================================================*
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. */
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
]);
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 /*===========================================================================*
515 *===========================================================================*/
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.