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 * old_icopy: copy to/from in-core inode struct and disk inode (V1.x)
15 * new_icopy: copy to/from in-core inode struct and disk inode (V2.x)
16 * dup_inode: indicate that someone else is using an inode table entry
24 #include <minix/vfsif.h>
26 FORWARD
_PROTOTYPE( void old_icopy
, (struct inode
*rip
, d1_inode
*dip
,
27 int direction
, int norm
));
28 FORWARD
_PROTOTYPE( void new_icopy
, (struct inode
*rip
, d2_inode
*dip
,
29 int direction
, int norm
));
30 FORWARD
_PROTOTYPE( void put_inode2
, (struct inode
*rip
, int count
));
33 /*===========================================================================*
35 *===========================================================================*/
36 PUBLIC
int fs_putnode()
38 /* Find the inode specified by the request message and decrease its counter.
43 /* Sanity check for the direct index */
44 if (fs_m_in
.REQ_INODE_INDEX
>= 0 &&
45 fs_m_in
.REQ_INODE_INDEX
< NR_INODES
&&
46 inode
[fs_m_in
.REQ_INODE_INDEX
].i_num
== fs_m_in
.REQ_INODE_NR
) {
47 rip
= &inode
[fs_m_in
.REQ_INODE_INDEX
];
49 /* Otherwise find it */
51 rip
= find_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
);
56 printf("FSput_inode: inode #%d dev: %d couldn't be put, req_nr: %d\n",
57 fs_m_in
.REQ_INODE_NR
, fs_dev
, req_nr
);
58 panic(__FILE__
, "fs_putnode failed", NO_NUM
);
61 count
= fs_m_in
.REQ_COUNT
;
64 printf("put_inode: bad value for count: %d\n", count
);
65 panic(__FILE__
, "fs_putnode failed", NO_NUM
);
68 if (count
> rip
->i_count
)
70 printf("put_inode: count too high: %d > %d\n", count
, rip
->i_count
);
71 panic(__FILE__
, "fs_putnode failed", NO_NUM
);
75 put_inode2(rip
, count
);
80 /*===========================================================================*
82 *===========================================================================*/
83 PUBLIC
int fs_getnode()
85 /* Increase the inode's counter specified in the request message
89 rip
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
);
92 printf("FS: inode #%d couldn't be found\n", fs_m_in
.REQ_INODE_NR
);
96 /* Transfer back the inode's details */
97 fs_m_out
.m_source
= rip
->i_dev
;
98 fs_m_out
.RES_INODE_NR
= rip
->i_num
;
99 fs_m_out
.RES_MODE
= rip
->i_mode
;
100 fs_m_out
.RES_FILE_SIZE
= rip
->i_size
;
101 fs_m_out
.RES_DEV
= (Dev_t
) rip
->i_zone
[0];
102 fs_m_out
.RES_UID
= rip
->i_uid
;
103 fs_m_out
.RES_GID
= rip
->i_gid
;
109 /*===========================================================================*
111 *===========================================================================*/
112 PUBLIC
void init_inode_cache()
115 struct inodelist
*rlp
;
118 inode_cache_miss
= 0;
120 /* init free/unused list */
121 TAILQ_INIT(&unused_inodes
);
123 /* init hash lists */
124 for (rlp
= &hash_inodes
[0]; rlp
< &hash_inodes
[INODE_HASH_SIZE
]; ++rlp
)
127 /* add free inodes to unused/free list */
128 for (rip
= &inode
[0]; rip
< &inode
[NR_INODES
]; ++rip
) {
130 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
135 /*===========================================================================*
137 *===========================================================================*/
138 PRIVATE
int addhash_inode(struct inode
*node
)
140 int hashi
= node
->i_num
& INODE_HASH_MASK
;
142 /* insert into hash table */
143 LIST_INSERT_HEAD(&hash_inodes
[hashi
], node
, i_hash
);
147 /*===========================================================================*
149 *===========================================================================*/
150 PRIVATE
int unhash_inode(struct inode
*node
)
152 /* remove from hash table */
153 LIST_REMOVE(node
, i_hash
);
157 /*===========================================================================*
159 *===========================================================================*/
160 PUBLIC
struct inode
*get_inode(dev
, numb
)
161 dev_t dev
; /* device on which inode resides */
162 int numb
; /* inode number (ANSI: may not be unshort) */
164 /* Find the inode in the hash table. If it is not there, get a free inode
165 * load it from the disk if it's necessary and put on the hash list
167 register struct inode
*rip
, *xp
;
170 hashi
= numb
& INODE_HASH_MASK
;
172 /* Search inode in the hash table */
173 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
174 if (rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
175 /* If unused, remove it from the unused/free list */
176 if (rip
->i_count
== 0) {
178 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
187 /* Inode is not on the hash, get a free one */
188 if (TAILQ_EMPTY(&unused_inodes
)) {
192 rip
= TAILQ_FIRST(&unused_inodes
);
194 /* If not free unhash it */
198 /* Inode is not unused any more */
199 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
201 /* Load the inode. */
205 if (dev
!= NO_DEV
) rw_inode(rip
, READING
); /* get inode from disk */
206 rip
->i_update
= 0; /* all the times are initially up-to-date */
207 if ((rip
->i_mode
& I_TYPE
) == I_NAMED_PIPE
)
208 rip
->i_pipe
= I_PIPE
;
210 rip
->i_pipe
= NO_PIPE
;
218 /*===========================================================================*
220 *===========================================================================*/
221 PUBLIC
struct inode
*find_inode(dev
, numb
)
222 dev_t dev
; /* device on which inode resides */
223 int numb
; /* inode number (ANSI: may not be unshort) */
225 /* Find the inode specified by the inode and device number.
230 hashi
= numb
& INODE_HASH_MASK
;
232 /* Search inode in the hash table */
233 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
234 if (rip
->i_count
> 0 && rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
243 /*===========================================================================*
245 *===========================================================================*/
246 PUBLIC
void put_inode(rip
)
247 register struct inode
*rip
; /* pointer to inode to be released */
249 /* The caller is no longer using this inode. If no one else is using it either
250 * write it back to the disk immediately. If it has no links, truncate it and
251 * return it to the pool of available inodes.
254 if (rip
== NIL_INODE
) return; /* checking here is easier than in caller */
256 if (--rip
->i_count
== 0) { /* i_count == 0 means no one is using it now */
257 if (rip
->i_nlinks
== 0) {
258 /* i_nlinks == 0 means free the inode. */
259 truncate_inode(rip
, 0); /* return all the disk blocks */
260 rip
->i_mode
= I_NOT_ALLOC
; /* clear I_TYPE field */
262 free_inode(rip
->i_dev
, rip
->i_num
);
265 if (rip
->i_pipe
== I_PIPE
) truncate_inode(rip
, 0);
267 rip
->i_mount
= NO_MOUNT
;
268 if (rip
->i_dirt
== DIRTY
) rw_inode(rip
, WRITING
);
270 if (rip
->i_nlinks
== 0) {
271 /* free, put at the front of the LRU list */
274 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
277 /* unused, put at the back of the LRU (cache it) */
278 TAILQ_INSERT_TAIL(&unused_inodes
, rip
, i_unused
);
284 /*===========================================================================*
286 *===========================================================================*/
287 PRIVATE
void put_inode2(rip
, count
)
288 register struct inode
*rip
; /* pointer to inode to be released */
291 /* The caller is no longer using this inode. If no one else is using it either
292 * write it back to the disk immediately. If it has no links, truncate it and
293 * return it to the pool of available inodes.
296 if (rip
== NIL_INODE
) return; /* checking here is easier than in caller */
298 if (rip
->i_count
< count
)
299 panic(__FILE__
, "put_inode2: bad value for count", count
);
300 rip
->i_count
-= count
;
301 if (rip
->i_count
== 0) { /* i_count == 0 means no one is using it now */
302 if (rip
->i_nlinks
== 0) {
303 /* i_nlinks == 0 means free the inode. */
304 truncate_inode(rip
, 0); /* return all the disk blocks */
305 rip
->i_mode
= I_NOT_ALLOC
; /* clear I_TYPE field */
307 free_inode(rip
->i_dev
, rip
->i_num
);
310 if (rip
->i_pipe
== I_PIPE
)
311 truncate_inode(rip
, 0);
313 rip
->i_mount
= NO_MOUNT
;
314 if (rip
->i_dirt
== DIRTY
) rw_inode(rip
, WRITING
);
316 if (rip
->i_nlinks
== 0) {
317 /* free, put at the front of the LRU list */
320 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
323 /* unused, put at the back of the LRU (cache it) */
324 TAILQ_INSERT_TAIL(&unused_inodes
, rip
, i_unused
);
330 /*===========================================================================*
332 *===========================================================================*/
333 PUBLIC
struct inode
*alloc_inode(dev_t dev
, mode_t bits
)
335 /* Allocate a free inode on 'dev', and return a pointer to it. */
337 register struct inode
*rip
;
338 register struct super_block
*sp
;
339 int major
, minor
, inumb
;
342 sp
= get_super(dev
); /* get pointer to super_block */
343 if (sp
->s_rd_only
) { /* can't allocate an inode on a read only device. */
348 /* Acquire an inode from the bit map. */
349 b
= alloc_bit(sp
, IMAP
, sp
->s_isearch
);
352 major
= (int) (sp
->s_dev
>> MAJOR
) & BYTE
;
353 minor
= (int) (sp
->s_dev
>> MINOR
) & BYTE
;
354 printf("Out of i-nodes on device %d/%d\n", major
, minor
);
357 sp
->s_isearch
= b
; /* next time start here */
358 inumb
= (int) b
; /* be careful not to pass unshort as param */
360 /* Try to acquire a slot in the inode table. */
361 if ((rip
= get_inode(NO_DEV
, inumb
)) == NIL_INODE
) {
362 /* No inode table slots available. Free the inode just allocated. */
363 free_bit(sp
, IMAP
, b
);
365 /* An inode slot is available. Put the inode just allocated into it. */
366 rip
->i_mode
= bits
; /* set up RWX bits */
367 rip
->i_nlinks
= 0; /* initial no links */
368 rip
->i_uid
= caller_uid
; /* file's uid is owner's */
369 rip
->i_gid
= caller_gid
; /* ditto group id */
370 rip
->i_dev
= dev
; /* mark which device it is on */
371 rip
->i_ndzones
= sp
->s_ndzones
; /* number of direct zones */
372 rip
->i_nindirs
= sp
->s_nindirs
; /* number of indirect zones per blk*/
373 rip
->i_sp
= sp
; /* pointer to super block */
375 /* Fields not cleared already are cleared in wipe_inode(). They have
376 * been put there because truncate() needs to clear the same fields if
377 * the file happens to be open while being truncated. It saves space
378 * not to repeat the code twice.
386 /*===========================================================================*
388 *===========================================================================*/
389 PUBLIC
void wipe_inode(rip
)
390 register struct inode
*rip
; /* the inode to be erased */
392 /* Erase some fields in the inode. This function is called from alloc_inode()
393 * when a new inode is to be allocated, and from truncate(), when an existing
394 * inode is to be truncated.
400 rip
->i_update
= ATIME
| CTIME
| MTIME
; /* update all times later */
402 for (i
= 0; i
< V2_NR_TZONES
; i
++) rip
->i_zone
[i
] = NO_ZONE
;
405 /*===========================================================================*
407 *===========================================================================*/
408 PUBLIC
void free_inode(dev
, inumb
)
409 dev_t dev
; /* on which device is the inode */
410 ino_t inumb
; /* number of inode to be freed */
412 /* Return an inode to the pool of unallocated inodes. */
414 register struct super_block
*sp
;
417 /* Locate the appropriate super_block. */
419 if (inumb
<= 0 || inumb
> sp
->s_ninodes
) return;
421 free_bit(sp
, IMAP
, b
);
422 if (b
< sp
->s_isearch
) sp
->s_isearch
= b
;
425 /*===========================================================================*
427 *===========================================================================*/
428 PUBLIC
void update_times(rip
)
429 register struct inode
*rip
; /* pointer to inode to be read/written */
431 /* Various system calls are required by the standard to update atime, ctime,
432 * or mtime. Since updating a time requires sending a message to the clock
433 * task--an expensive business--the times are marked for update by setting
434 * bits in i_update. When a stat, fstat, or sync is done, or an inode is
435 * released, update_times() may be called to actually fill in the times.
439 struct super_block
*sp
;
441 sp
= rip
->i_sp
; /* get pointer to super block. */
442 if (sp
->s_rd_only
) return; /* no updates for read-only file systems */
444 cur_time
= clock_time();
445 if (rip
->i_update
& ATIME
) rip
->i_atime
= cur_time
;
446 if (rip
->i_update
& CTIME
) rip
->i_ctime
= cur_time
;
447 if (rip
->i_update
& MTIME
) rip
->i_mtime
= cur_time
;
448 rip
->i_update
= 0; /* they are all up-to-date now */
451 /*===========================================================================*
453 *===========================================================================*/
454 PUBLIC
void rw_inode(rip
, rw_flag
)
455 register struct inode
*rip
; /* pointer to inode to be read/written */
456 int rw_flag
; /* READING or WRITING */
458 /* An entry in the inode table is to be copied to or from the disk. */
460 register struct buf
*bp
;
461 register struct super_block
*sp
;
466 /* Get the block where the inode resides. */
467 sp
= get_super(rip
->i_dev
); /* get pointer to super block */
468 rip
->i_sp
= sp
; /* inode must contain super block pointer */
469 offset
= sp
->s_imap_blocks
+ sp
->s_zmap_blocks
+ 2;
470 b
= (block_t
) (rip
->i_num
- 1)/sp
->s_inodes_per_block
+ offset
;
471 bp
= get_block(rip
->i_dev
, b
, NORMAL
);
472 dip
= bp
->b_v1_ino
+ (rip
->i_num
- 1) % V1_INODES_PER_BLOCK
;
473 dip2
= bp
->b_v2_ino
+ (rip
->i_num
- 1) %
474 V2_INODES_PER_BLOCK(sp
->s_block_size
);
476 /* Do the read or write. */
477 if (rw_flag
== WRITING
) {
478 if (rip
->i_update
) update_times(rip
); /* times need updating */
479 if (sp
->s_rd_only
== FALSE
) bp
->b_dirt
= DIRTY
;
482 /* Copy the inode from the disk block to the in-core table or vice versa.
483 * If the fourth parameter below is FALSE, the bytes are swapped.
485 if (sp
->s_version
== V1
)
486 old_icopy(rip
, dip
, rw_flag
, sp
->s_native
);
488 new_icopy(rip
, dip2
, rw_flag
, sp
->s_native
);
490 put_block(bp
, INODE_BLOCK
);
494 /*===========================================================================*
496 *===========================================================================*/
497 PRIVATE
void old_icopy(rip
, dip
, direction
, norm
)
498 register struct inode
*rip
; /* pointer to the in-core inode struct */
499 register d1_inode
*dip
; /* pointer to the d1_inode inode struct */
500 int direction
; /* READING (from disk) or WRITING (to disk) */
501 int norm
; /* TRUE = do not swap bytes; FALSE = swap */
504 /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
505 * 68000) all have different inode layouts. When an inode is read or written
506 * this routine handles the conversions so that the information in the inode
507 * table is independent of the disk structure from which the inode came.
508 * The old_icopy routine copies to and from V1 disks.
513 if (direction
== READING
) {
514 /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
515 rip
->i_mode
= conv2(norm
, (int) dip
->d1_mode
);
516 rip
->i_uid
= conv2(norm
, (int) dip
->d1_uid
);
517 rip
->i_size
= conv4(norm
, dip
->d1_size
);
518 rip
->i_mtime
= conv4(norm
, dip
->d1_mtime
);
519 rip
->i_atime
= rip
->i_mtime
;
520 rip
->i_ctime
= rip
->i_mtime
;
521 rip
->i_nlinks
= dip
->d1_nlinks
; /* 1 char */
522 rip
->i_gid
= dip
->d1_gid
; /* 1 char */
523 rip
->i_ndzones
= V1_NR_DZONES
;
524 rip
->i_nindirs
= V1_INDIRECTS
;
525 for (i
= 0; i
< V1_NR_TZONES
; i
++)
526 rip
->i_zone
[i
] = conv2(norm
, (int) dip
->d1_zone
[i
]);
528 /* Copying V1.x inode to disk from the in-core table. */
529 dip
->d1_mode
= conv2(norm
, (int) rip
->i_mode
);
530 dip
->d1_uid
= conv2(norm
, (int) rip
->i_uid
);
531 dip
->d1_size
= conv4(norm
, rip
->i_size
);
532 dip
->d1_mtime
= conv4(norm
, rip
->i_mtime
);
533 dip
->d1_nlinks
= rip
->i_nlinks
; /* 1 char */
534 dip
->d1_gid
= rip
->i_gid
; /* 1 char */
535 for (i
= 0; i
< V1_NR_TZONES
; i
++)
536 dip
->d1_zone
[i
] = conv2(norm
, (int) rip
->i_zone
[i
]);
540 /*===========================================================================*
542 *===========================================================================*/
543 PRIVATE
void new_icopy(rip
, dip
, direction
, norm
)
544 register struct inode
*rip
; /* pointer to the in-core inode struct */
545 register d2_inode
*dip
; /* pointer to the d2_inode struct */
546 int direction
; /* READING (from disk) or WRITING (to disk) */
547 int norm
; /* TRUE = do not swap bytes; FALSE = swap */
550 /* Same as old_icopy, but to/from V2 disk layout. */
554 if (direction
== READING
) {
555 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
556 rip
->i_mode
= conv2(norm
,dip
->d2_mode
);
557 rip
->i_uid
= conv2(norm
,dip
->d2_uid
);
558 rip
->i_nlinks
= conv2(norm
,dip
->d2_nlinks
);
559 rip
->i_gid
= conv2(norm
,dip
->d2_gid
);
560 rip
->i_size
= conv4(norm
,dip
->d2_size
);
561 rip
->i_atime
= conv4(norm
,dip
->d2_atime
);
562 rip
->i_ctime
= conv4(norm
,dip
->d2_ctime
);
563 rip
->i_mtime
= conv4(norm
,dip
->d2_mtime
);
564 rip
->i_ndzones
= V2_NR_DZONES
;
565 rip
->i_nindirs
= V2_INDIRECTS(rip
->i_sp
->s_block_size
);
566 for (i
= 0; i
< V2_NR_TZONES
; i
++)
567 rip
->i_zone
[i
] = conv4(norm
, (long) dip
->d2_zone
[i
]);
569 /* Copying V2.x inode to disk from the in-core table. */
570 dip
->d2_mode
= conv2(norm
,rip
->i_mode
);
571 dip
->d2_uid
= conv2(norm
,rip
->i_uid
);
572 dip
->d2_nlinks
= conv2(norm
,rip
->i_nlinks
);
573 dip
->d2_gid
= conv2(norm
,rip
->i_gid
);
574 dip
->d2_size
= conv4(norm
,rip
->i_size
);
575 dip
->d2_atime
= conv4(norm
,rip
->i_atime
);
576 dip
->d2_ctime
= conv4(norm
,rip
->i_ctime
);
577 dip
->d2_mtime
= conv4(norm
,rip
->i_mtime
);
578 for (i
= 0; i
< V2_NR_TZONES
; i
++)
579 dip
->d2_zone
[i
] = conv4(norm
, (long) rip
->i_zone
[i
]);
583 /*===========================================================================*
585 *===========================================================================*/
586 PUBLIC
void dup_inode(ip
)
587 struct inode
*ip
; /* The inode to be duplicated. */
589 /* This routine is a simplified form of get_inode() for the case where
590 * the inode pointer is already known.