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>
26 static void addhash_inode(struct inode
*node
);
28 static void free_inode(dev_t dev
, ino_t numb
);
29 static void new_icopy(struct inode
*rip
, d2_inode
*dip
, int direction
,
31 static void unhash_inode(struct inode
*node
);
32 static void wipe_inode(struct inode
*rip
);
35 /*===========================================================================*
37 *===========================================================================*/
38 int fs_putnode(ino_t ino_nr
, unsigned int count
)
40 /* Find the inode specified by the request message and decrease its counter.*/
44 rip
= find_inode(fs_dev
, ino_nr
);
47 printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__
,
48 __LINE__
, ino_nr
, fs_dev
);
49 panic("fs_putnode failed");
52 if (count
> rip
->i_count
) {
53 printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__
,
54 __LINE__
, count
, rip
->i_count
);
55 panic("fs_putnode failed");
58 /* Decrease reference counter, but keep one reference; it will be consumed by
60 rip
->i_count
-= count
- 1;
67 /*===========================================================================*
69 *===========================================================================*/
70 void init_inode_cache()
73 struct inodelist
*rlp
;
78 /* init free/unused list */
79 TAILQ_INIT(&unused_inodes
);
82 for (rlp
= &hash_inodes
[0]; rlp
< &hash_inodes
[INODE_HASH_SIZE
]; ++rlp
)
85 /* add free inodes to unused/free list */
86 for (rip
= &inode
[0]; rip
< &inode
[NR_INODES
]; ++rip
) {
87 rip
->i_num
= NO_ENTRY
;
88 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
93 /*===========================================================================*
95 *===========================================================================*/
96 static void addhash_inode(struct inode
*node
)
98 int hashi
= (int) (node
->i_num
& INODE_HASH_MASK
);
100 /* insert into hash table */
101 LIST_INSERT_HEAD(&hash_inodes
[hashi
], node
, i_hash
);
105 /*===========================================================================*
107 *===========================================================================*/
108 static void unhash_inode(struct inode
*node
)
110 /* remove from hash table */
111 LIST_REMOVE(node
, i_hash
);
115 /*===========================================================================*
117 *===========================================================================*/
118 struct inode
*get_inode(
119 dev_t dev
, /* device on which inode resides */
120 ino_t numb
/* inode number */
123 /* Find the inode in the hash table. If it is not there, get a free inode
124 * load it from the disk if it's necessary and put on the hash list
126 register struct inode
*rip
;
129 hashi
= (int) (numb
& INODE_HASH_MASK
);
131 /* Search inode in the hash table */
132 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
133 if (rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
134 /* If unused, remove it from the unused/free list */
135 if (rip
->i_count
== 0) {
137 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
146 /* Inode is not on the hash, get a free one */
147 if (TAILQ_EMPTY(&unused_inodes
)) {
151 rip
= TAILQ_FIRST(&unused_inodes
);
153 /* If not free unhash it */
154 if (rip
->i_num
!= NO_ENTRY
)
157 /* Inode is not unused any more */
158 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
160 /* Load the inode. */
164 if (dev
!= NO_DEV
) rw_inode(rip
, READING
); /* get inode from disk */
165 rip
->i_update
= 0; /* all the times are initially up-to-date */
166 rip
->i_zsearch
= NO_ZONE
; /* no zones searched for yet */
167 rip
->i_mountpoint
= FALSE
;
168 rip
->i_last_dpos
= 0; /* no dentries searched for yet */
177 /*===========================================================================*
179 *===========================================================================*/
180 struct inode
*find_inode(
181 dev_t dev
, /* device on which inode resides */
182 ino_t numb
/* inode number */
185 /* Find the inode specified by the inode and device number.
190 hashi
= (int) (numb
& INODE_HASH_MASK
);
192 /* Search inode in the hash table */
193 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
194 if (rip
->i_count
> 0 && rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
203 /*===========================================================================*
205 *===========================================================================*/
207 register struct inode
*rip
; /* pointer to inode to be released */
209 /* The caller is no longer using this inode. If no one else is using it either
210 * write it back to the disk immediately. If it has no links, truncate it and
211 * return it to the pool of available inodes.
214 if (rip
== NULL
) return; /* checking here is easier than in caller */
216 if (rip
->i_count
< 1)
217 panic("put_inode: i_count already below 1: %d", rip
->i_count
);
219 if (--rip
->i_count
== 0) { /* i_count == 0 means no one is using it now */
220 if (rip
->i_nlinks
== NO_LINK
) {
221 /* i_nlinks == NO_LINK means free the inode. */
222 /* return all the disk blocks */
224 /* Ignore errors by truncate_inode in case inode is a block
225 * special or character special file.
227 (void) truncate_inode(rip
, (off_t
) 0);
228 rip
->i_mode
= I_NOT_ALLOC
; /* clear I_TYPE field */
230 free_inode(rip
->i_dev
, rip
->i_num
);
233 rip
->i_mountpoint
= FALSE
;
234 if (IN_ISDIRTY(rip
)) rw_inode(rip
, WRITING
);
236 if (rip
->i_nlinks
== NO_LINK
) {
237 /* free, put at the front of the LRU list */
239 rip
->i_num
= NO_ENTRY
;
240 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
242 /* unused, put at the back of the LRU (cache it) */
243 TAILQ_INSERT_TAIL(&unused_inodes
, rip
, i_unused
);
249 /*===========================================================================*
251 *===========================================================================*/
252 struct inode
*alloc_inode(dev_t dev
, mode_t bits
, uid_t uid
, gid_t gid
)
254 /* Allocate a free inode on 'dev', and return a pointer to it. */
256 register struct inode
*rip
;
257 register struct super_block
*sp
;
258 int major
, minor
, inumb
;
262 if (sp
->s_rd_only
) { /* can't allocate an inode on a read only device. */
267 /* Acquire an inode from the bit map. */
268 b
= alloc_bit(sp
, IMAP
, sp
->s_isearch
);
271 major
= major(sp
->s_dev
);
272 minor
= minor(sp
->s_dev
);
273 printf("Out of i-nodes on device %d/%d\n", major
, minor
);
276 sp
->s_isearch
= b
; /* next time start here */
277 inumb
= (int) b
; /* be careful not to pass unshort as param */
279 /* Try to acquire a slot in the inode table. */
280 if ((rip
= get_inode(NO_DEV
, inumb
)) == NULL
) {
281 /* No inode table slots available. Free the inode just allocated. */
282 free_bit(sp
, IMAP
, b
);
284 /* An inode slot is available. Put the inode just allocated into it. */
285 rip
->i_mode
= bits
; /* set up RWX bits */
286 rip
->i_nlinks
= NO_LINK
; /* initial no links */
287 rip
->i_uid
= uid
; /* file's uid is owner's */
288 rip
->i_gid
= gid
; /* ditto group id */
289 rip
->i_dev
= dev
; /* mark which device it is on */
290 rip
->i_ndzones
= sp
->s_ndzones
; /* number of direct zones */
291 rip
->i_nindirs
= sp
->s_nindirs
; /* number of indirect zones per blk*/
292 rip
->i_sp
= sp
; /* pointer to super block */
294 /* Fields not cleared already are cleared in wipe_inode(). They have
295 * been put there because truncate() needs to clear the same fields if
296 * the file happens to be open while being truncated. It saves space
297 * not to repeat the code twice.
306 /*===========================================================================*
308 *===========================================================================*/
309 static void wipe_inode(rip
)
310 register struct inode
*rip
; /* the inode to be erased */
312 /* Erase some fields in the inode. This function is called from alloc_inode()
313 * when a new inode is to be allocated, and from truncate(), when an existing
314 * inode is to be truncated.
320 rip
->i_update
= ATIME
| CTIME
| MTIME
; /* update all times later */
322 for (i
= 0; i
< V2_NR_TZONES
; i
++) rip
->i_zone
[i
] = NO_ZONE
;
325 /*===========================================================================*
327 *===========================================================================*/
328 static void free_inode(
329 dev_t dev
, /* on which device is the inode? */
330 ino_t inumb
/* number of the inode to be freed */
333 /* Return an inode to the pool of unallocated inodes. */
335 register struct super_block
*sp
;
339 if (inumb
== NO_ENTRY
|| inumb
> sp
->s_ninodes
) return;
341 free_bit(sp
, IMAP
, b
);
342 if (b
< sp
->s_isearch
) sp
->s_isearch
= b
;
346 /*===========================================================================*
348 *===========================================================================*/
349 void update_times(rip
)
350 register struct inode
*rip
; /* pointer to inode to be read/written */
352 /* Various system calls are required by the standard to update atime, ctime,
353 * or mtime. Since updating a time requires sending a message to the clock
354 * task--an expensive business--the times are marked for update by setting
355 * bits in i_update. When a stat, fstat, or sync is done, or an inode is
356 * released, update_times() may be called to actually fill in the times.
360 struct super_block
*sp
;
362 sp
= rip
->i_sp
; /* get pointer to super block. */
363 if (sp
->s_rd_only
) return; /* no updates for read-only file systems */
365 cur_time
= clock_time(NULL
);
366 if (rip
->i_update
& ATIME
) rip
->i_atime
= cur_time
;
367 if (rip
->i_update
& CTIME
) rip
->i_ctime
= cur_time
;
368 if (rip
->i_update
& MTIME
) rip
->i_mtime
= cur_time
;
369 rip
->i_update
= 0; /* they are all up-to-date now */
372 /*===========================================================================*
374 *===========================================================================*/
375 void rw_inode(rip
, rw_flag
)
376 register struct inode
*rip
; /* pointer to inode to be read/written */
377 int rw_flag
; /* READING or WRITING */
379 /* An entry in the inode table is to be copied to or from the disk. */
381 register struct buf
*bp
;
382 register struct super_block
*sp
;
386 /* Get the block where the inode resides. */
388 rip
->i_sp
= sp
; /* inode must contain super block pointer */
389 offset
= START_BLOCK
+ sp
->s_imap_blocks
+ sp
->s_zmap_blocks
;
390 b
= (block_t
) (rip
->i_num
- 1)/sp
->s_inodes_per_block
+ offset
;
391 bp
= get_block(rip
->i_dev
, b
, NORMAL
);
392 dip2
= b_v2_ino(bp
) + (rip
->i_num
- 1) %
393 V2_INODES_PER_BLOCK(sp
->s_block_size
);
395 /* Do the read or write. */
396 if (rw_flag
== WRITING
) {
397 if (rip
->i_update
) update_times(rip
); /* times need updating */
398 if (sp
->s_rd_only
== FALSE
) MARKDIRTY(bp
);
401 /* Copy the inode from the disk block to the in-core table or vice versa.
402 * If the fourth parameter below is FALSE, the bytes are swapped.
404 assert(sp
->s_version
== V3
);
405 new_icopy(rip
, dip2
, rw_flag
, sp
->s_native
);
411 /*===========================================================================*
413 *===========================================================================*/
414 static void new_icopy(rip
, dip
, direction
, norm
)
415 register struct inode
*rip
; /* pointer to the in-core inode struct */
416 register d2_inode
*dip
; /* pointer to the d2_inode struct */
417 int direction
; /* READING (from disk) or WRITING (to disk) */
418 int norm
; /* TRUE = do not swap bytes; FALSE = swap */
422 if (direction
== READING
) {
423 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
424 rip
->i_mode
= (mode_t
) conv2(norm
,dip
->d2_mode
);
425 rip
->i_uid
= (uid_t
) conv2(norm
,dip
->d2_uid
);
426 rip
->i_nlinks
= (nlink_t
) conv2(norm
,dip
->d2_nlinks
);
427 rip
->i_gid
= (gid_t
) conv2(norm
,dip
->d2_gid
);
428 rip
->i_size
= (off_t
) conv4(norm
,dip
->d2_size
);
429 rip
->i_atime
= (time_t) conv4(norm
,dip
->d2_atime
);
430 rip
->i_ctime
= (time_t) conv4(norm
,dip
->d2_ctime
);
431 rip
->i_mtime
= (time_t) conv4(norm
,dip
->d2_mtime
);
432 rip
->i_ndzones
= V2_NR_DZONES
;
433 rip
->i_nindirs
= V2_INDIRECTS(rip
->i_sp
->s_block_size
);
434 for (i
= 0; i
< V2_NR_TZONES
; i
++)
435 rip
->i_zone
[i
] = (zone_t
) conv4(norm
, (long) dip
->d2_zone
[i
]);
437 /* Copying V2.x inode to disk from the in-core table. */
438 dip
->d2_mode
= (u16_t
) conv2(norm
,rip
->i_mode
);
439 dip
->d2_uid
= (i16_t
) conv2(norm
,rip
->i_uid
);
440 dip
->d2_nlinks
= (u16_t
) conv2(norm
,rip
->i_nlinks
);
441 dip
->d2_gid
= (u16_t
) conv2(norm
,rip
->i_gid
);
442 dip
->d2_size
= (i32_t
) conv4(norm
,rip
->i_size
);
443 dip
->d2_atime
= (i32_t
) conv4(norm
,rip
->i_atime
);
444 dip
->d2_ctime
= (i32_t
) conv4(norm
,rip
->i_ctime
);
445 dip
->d2_mtime
= (i32_t
) conv4(norm
,rip
->i_mtime
);
446 for (i
= 0; i
< V2_NR_TZONES
; i
++)
447 dip
->d2_zone
[i
] = (zone_t
) conv4(norm
, (long) rip
->i_zone
[i
]);
452 /*===========================================================================*
454 *===========================================================================*/
456 struct inode
*ip
; /* The inode to be duplicated. */
458 /* This routine is a simplified form of get_inode() for the case where
459 * the inode pointer is already known.