. service tells you which device it couldn't stat
[minix3.git] / servers / mfs / inode.c
bloba18ffbe742b47b73b26f7b39e3185c23ecb66cc7
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 * 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
19 #include "fs.h"
20 #include "buf.h"
21 #include "inode.h"
22 #include "super.h"
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 /*===========================================================================*
34 * fs_putnode *
35 *===========================================================================*/
36 PUBLIC int fs_putnode()
38 /* Find the inode specified by the request message and decrease its counter.
40 struct inode *rip;
41 int count;
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 */
50 else {
51 rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR);
54 if (!rip)
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;
62 if (count <= 0)
64 printf("put_inode: bad value for count: %d\n", count);
65 panic(__FILE__, "fs_putnode failed", NO_NUM);
66 return EINVAL;
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);
72 return EINVAL;
75 put_inode2(rip, count);
76 return OK;
80 /*===========================================================================*
81 * fs_getnode *
82 *===========================================================================*/
83 PUBLIC int fs_getnode()
85 /* Increase the inode's counter specified in the request message
87 struct inode *rip;
88 /* Get the inode */
89 rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR);
91 if (!rip) {
92 printf("FS: inode #%d couldn't be found\n", fs_m_in.REQ_INODE_NR);
93 return EINVAL;
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;
105 return OK;
109 /*===========================================================================*
110 * init_inode_cache *
111 *===========================================================================*/
112 PUBLIC void init_inode_cache()
114 struct inode *rip;
115 struct inodelist *rlp;
117 inode_cache_hit = 0;
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)
125 LIST_INIT(rlp);
127 /* add free inodes to unused/free list */
128 for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
129 rip->i_num = 0;
130 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
135 /*===========================================================================*
136 * addhash_inode *
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);
144 return OK;
147 /*===========================================================================*
148 * unhash_inode *
149 *===========================================================================*/
150 PRIVATE int unhash_inode(struct inode *node)
152 /* remove from hash table */
153 LIST_REMOVE(node, i_hash);
154 return OK;
157 /*===========================================================================*
158 * get_inode *
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;
168 int hashi;
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) {
177 inode_cache_hit++;
178 TAILQ_REMOVE(&unused_inodes, rip, i_unused);
180 ++rip->i_count;
181 return rip;
185 inode_cache_miss++;
187 /* Inode is not on the hash, get a free one */
188 if (TAILQ_EMPTY(&unused_inodes)) {
189 err_code = ENFILE;
190 return NIL_INODE;
192 rip = TAILQ_FIRST(&unused_inodes);
194 /* If not free unhash it */
195 if (rip->i_num != 0)
196 unhash_inode(rip);
198 /* Inode is not unused any more */
199 TAILQ_REMOVE(&unused_inodes, rip, i_unused);
201 /* Load the inode. */
202 rip->i_dev = dev;
203 rip->i_num = numb;
204 rip->i_count = 1;
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;
209 else
210 rip->i_pipe = NO_PIPE;
212 /* Add to hash */
213 addhash_inode(rip);
215 return(rip);
218 /*===========================================================================*
219 * find_inode *
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.
227 struct inode *rip;
228 int hashi;
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) {
235 return rip;
239 return NIL_INODE;
243 /*===========================================================================*
244 * put_inode *
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 */
261 rip->i_dirt = DIRTY;
262 free_inode(rip->i_dev, rip->i_num);
264 else {
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 */
272 unhash_inode(rip);
273 rip->i_num = 0;
274 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
276 else {
277 /* unused, put at the back of the LRU (cache it) */
278 TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
284 /*===========================================================================*
285 * put_inode2 *
286 *===========================================================================*/
287 PRIVATE void put_inode2(rip, count)
288 register struct inode *rip; /* pointer to inode to be released */
289 int count;
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 */
306 rip->i_dirt = DIRTY;
307 free_inode(rip->i_dev, rip->i_num);
309 else {
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 */
318 unhash_inode(rip);
319 rip->i_num = 0;
320 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
322 else {
323 /* unused, put at the back of the LRU (cache it) */
324 TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
330 /*===========================================================================*
331 * alloc_inode *
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;
340 bit_t b;
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. */
344 err_code = EROFS;
345 return(NIL_INODE);
348 /* Acquire an inode from the bit map. */
349 b = alloc_bit(sp, IMAP, sp->s_isearch);
350 if (b == NO_BIT) {
351 err_code = ENFILE;
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);
355 return(NIL_INODE);
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);
364 } else {
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.
380 wipe_inode(rip);
383 return(rip);
386 /*===========================================================================*
387 * wipe_inode *
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.
397 register int i;
399 rip->i_size = 0;
400 rip->i_update = ATIME | CTIME | MTIME; /* update all times later */
401 rip->i_dirt = DIRTY;
402 for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
405 /*===========================================================================*
406 * free_inode *
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;
415 bit_t b;
417 /* Locate the appropriate super_block. */
418 sp = get_super(dev);
419 if (inumb <= 0 || inumb > sp->s_ninodes) return;
420 b = inumb;
421 free_bit(sp, IMAP, b);
422 if (b < sp->s_isearch) sp->s_isearch = b;
425 /*===========================================================================*
426 * update_times *
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.
438 time_t cur_time;
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 /*===========================================================================*
452 * rw_inode *
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;
462 d1_inode *dip;
463 d2_inode *dip2;
464 block_t b, offset;
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);
487 else
488 new_icopy(rip, dip2, rw_flag, sp->s_native);
490 put_block(bp, INODE_BLOCK);
491 rip->i_dirt = CLEAN;
494 /*===========================================================================*
495 * old_icopy *
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.
511 int i;
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]);
527 } else {
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 /*===========================================================================*
541 * new_icopy *
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. */
552 int i;
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]);
568 } else {
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 /*===========================================================================*
584 * dup_inode *
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.
593 ip->i_count++;