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 * update_times: update atime, ctime, and mtime
10 * rw_inode: read a disk block and extract an inode, or corresp. write
11 * dup_inode: indicate that someone else is using an inode table entry
12 * find_inode: retrieve pointer to inode in inode cache
14 * Created (MFS based):
15 * February 2010 (Evgeniy Ivanov)
23 #include <minix/vfsif.h>
25 static void icopy(struct inode
*rip
, d_inode
*dip
, int direction
, int
27 static void addhash_inode(struct inode
*node
);
28 static void unhash_inode(struct inode
*node
);
31 /*===========================================================================*
33 *===========================================================================*/
36 /* Find the inode specified by the request message and decrease its counter.*/
41 rip
= find_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
);
44 printf("%s:%d put_inode: inode #%lu dev: %d not found\n", __FILE__
,
45 __LINE__
, (ino_t
) fs_m_in
.REQ_INODE_NR
, fs_dev
);
46 panic("fs_putnode failed");
49 count
= fs_m_in
.REQ_COUNT
;
51 printf("%s:%d put_inode: bad value for count: %d\n", __FILE__
,
53 panic("fs_putnode failed");
54 } else if (count
> rip
->i_count
) {
55 printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__
,
56 __LINE__
, count
, rip
->i_count
);
57 panic("fs_putnode failed");
60 /* Decrease reference counter, but keep one reference;
61 * it will be consumed by put_inode().
63 rip
->i_count
-= count
- 1;
70 /*===========================================================================*
72 *===========================================================================*/
73 void init_inode_cache()
76 struct inodelist
*rlp
;
81 /* init free/unused list */
82 TAILQ_INIT(&unused_inodes
);
85 for (rlp
= &hash_inodes
[0]; rlp
< &hash_inodes
[INODE_HASH_SIZE
]; ++rlp
)
88 /* add free inodes to unused/free list */
89 for (rip
= &inode
[0]; rip
< &inode
[NR_INODES
]; ++rip
) {
90 rip
->i_num
= NO_ENTRY
;
91 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
96 /*===========================================================================*
98 *===========================================================================*/
99 static void addhash_inode(struct inode
*node
)
101 int hashi
= node
->i_num
& INODE_HASH_MASK
;
103 /* insert into hash table */
104 LIST_INSERT_HEAD(&hash_inodes
[hashi
], node
, i_hash
);
108 /*===========================================================================*
110 *===========================================================================*/
111 static void unhash_inode(struct inode
*node
)
113 /* remove from hash table */
114 LIST_REMOVE(node
, i_hash
);
118 /*===========================================================================*
120 *===========================================================================*/
121 struct inode
*get_inode(
122 dev_t dev
, /* device on which inode resides */
123 ino_t numb
/* inode number (ANSI: may not be unshort) */
126 /* Find the inode in the hash table. If it is not there, get a free inode
127 * load it from the disk if it's necessary and put on the hash list
129 register struct inode
*rip
;
133 hashi
= (int) numb
& INODE_HASH_MASK
;
135 /* Search inode in the hash table */
136 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
137 if (rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
138 /* If unused, remove it from the unused/free list */
139 if (rip
->i_count
== 0) {
141 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
150 /* Inode is not on the hash, get a free one */
151 if (TAILQ_EMPTY(&unused_inodes
)) {
155 rip
= TAILQ_FIRST(&unused_inodes
);
157 /* If not free unhash it */
158 if (rip
->i_num
!= NO_ENTRY
)
161 /* Inode is not unused any more */
162 TAILQ_REMOVE(&unused_inodes
, rip
, i_unused
);
164 /* Load the inode. */
169 rw_inode(rip
, READING
); /* get inode from disk */
170 rip
->i_update
= 0; /* all the times are initially up-to-date */
171 rip
->i_last_dpos
= 0; /* no dentries searched for yet */
172 rip
->i_bsearch
= NO_BLOCK
;
173 rip
->i_last_pos_bl_alloc
= 0;
174 rip
->i_last_dentry_size
= 0;
175 rip
->i_mountpoint
= FALSE
;
177 rip
->i_preallocation
= opt
.use_prealloc
;
178 rip
->i_prealloc_count
= rip
->i_prealloc_index
= 0;
180 for (i
= 0; i
< EXT2_PREALLOC_BLOCKS
; i
++) {
181 if (rip
->i_prealloc_blocks
[i
] != NO_BLOCK
) {
182 /* Actually this should never happen */
183 free_block(rip
->i_sp
, rip
->i_prealloc_blocks
[i
]);
184 rip
->i_prealloc_blocks
[i
] = NO_BLOCK
;
185 ext2_debug("Warning: Unexpected preallocated block.");
196 /*===========================================================================*
198 *===========================================================================*/
199 struct inode
*find_inode(
200 dev_t dev
, /* device on which inode resides */
201 ino_t numb
/* inode number (ANSI: may not be unshort) */
204 /* Find the inode specified by the inode and device number. */
208 hashi
= (int) numb
& INODE_HASH_MASK
;
210 /* Search inode in the hash table */
211 LIST_FOREACH(rip
, &hash_inodes
[hashi
], i_hash
) {
212 if (rip
->i_count
> 0 && rip
->i_num
== numb
&& rip
->i_dev
== dev
) {
221 /*===========================================================================*
223 *===========================================================================*/
225 register struct inode
*rip
/* pointer to inode to be released */
228 /* The caller is no longer using this inode. If no one else is using it either
229 * write it back to the disk immediately. If it has no links, truncate it and
230 * return it to the pool of available inodes.
234 return; /* checking here is easier than in caller */
236 if (rip
->i_count
< 1)
237 panic("put_inode: i_count already below 1", rip
->i_count
);
239 if (--rip
->i_count
== 0) { /* i_count == 0 means no one is using it now */
240 if (rip
->i_links_count
== NO_LINK
) {
241 /* i_nlinks == NO_LINK means free the inode. */
242 /* return all the disk blocks */
244 /* Ignore errors by truncate_inode in case inode is a block
245 * special or character special file.
247 (void) truncate_inode(rip
, (off_t
) 0);
248 /* free inode clears I_TYPE field, since it's used there */
253 rip
->i_mountpoint
= FALSE
;
254 if (rip
->i_dirt
== DIRTY
) rw_inode(rip
, WRITING
);
256 discard_preallocated_blocks(rip
); /* Return blocks to the filesystem */
258 if (rip
->i_links_count
== NO_LINK
) {
259 /* free, put at the front of the LRU list */
261 rip
->i_num
= NO_ENTRY
;
262 TAILQ_INSERT_HEAD(&unused_inodes
, rip
, i_unused
);
264 /* unused, put at the back of the LRU (cache it) */
265 TAILQ_INSERT_TAIL(&unused_inodes
, rip
, i_unused
);
271 /*===========================================================================*
273 *===========================================================================*/
275 register struct inode
*rip
/* pointer to inode to be read/written */
278 /* Various system calls are required by the standard to update atime, ctime,
279 * or mtime. Since updating a time requires sending a message to the clock
280 * task--an expensive business--the times are marked for update by setting
281 * bits in i_update. When a stat, fstat, or sync is done, or an inode is
282 * released, update_times() may be called to actually fill in the times.
286 struct super_block
*sp
;
288 sp
= rip
->i_sp
; /* get pointer to super block. */
290 return; /* no updates for read-only file systems */
292 cur_time
= clock_time();
293 if (rip
->i_update
& ATIME
)
294 rip
->i_atime
= cur_time
;
295 if (rip
->i_update
& CTIME
)
296 rip
->i_ctime
= cur_time
;
297 if (rip
->i_update
& MTIME
)
298 rip
->i_mtime
= cur_time
;
299 rip
->i_update
= 0; /* they are all up-to-date now */
302 /*===========================================================================*
304 *===========================================================================*/
306 register struct inode
*rip
, /* pointer to inode to be read/written */
307 int rw_flag
/* READING or WRITING */
310 /* An entry in the inode table is to be copied to or from the disk. */
312 register struct buf
*bp
;
313 register struct super_block
*sp
;
314 register struct group_desc
*gd
;
315 register d_inode
*dip
;
316 u32_t block_group_number
;
319 /* Get the block where the inode resides. */
320 sp
= get_super(rip
->i_dev
); /* get pointer to super block */
321 rip
->i_sp
= sp
; /* inode must contain super block pointer */
323 block_group_number
= (rip
->i_num
- 1) / sp
->s_inodes_per_group
;
325 gd
= get_group_desc(block_group_number
);
328 panic("can't get group_desc to read/write inode");
330 offset
= ((rip
->i_num
- 1) % sp
->s_inodes_per_group
) * EXT2_INODE_SIZE(sp
);
331 /* offset requires shifting, since each block contains several inodes,
332 * e.g. inode 2 is stored in bklock 0.
334 b
= (block_t
) gd
->inode_table
+ (offset
>> sp
->s_blocksize_bits
);
335 bp
= get_block(rip
->i_dev
, b
, NORMAL
);
337 offset
&= (sp
->s_block_size
- 1);
338 dip
= (d_inode
*) (bp
->b_data
+ offset
);
340 /* Do the read or write. */
341 if (rw_flag
== WRITING
) {
343 update_times(rip
); /* times need updating */
344 if (sp
->s_rd_only
== FALSE
)
348 icopy(rip
, dip
, rw_flag
, TRUE
);
350 put_block(bp
, INODE_BLOCK
);
355 /*===========================================================================*
357 *===========================================================================*/
359 register struct inode
*rip
, /* pointer to the in-core inode struct */
360 register d_inode
*dip
, /* pointer to the on-disk struct */
361 int direction
, /* READING (from disk) or WRITING (to disk) */
362 int norm
/* TRUE = do not swap bytes; FALSE = swap */
367 if (direction
== READING
) {
368 /* Copy inode to the in-core table, swapping bytes if need be. */
369 rip
->i_mode
= conv2(norm
,dip
->i_mode
);
370 rip
->i_uid
= conv2(norm
,dip
->i_uid
);
371 rip
->i_size
= conv4(norm
,dip
->i_size
);
372 rip
->i_atime
= conv4(norm
,dip
->i_atime
);
373 rip
->i_ctime
= conv4(norm
,dip
->i_ctime
);
374 rip
->i_mtime
= conv4(norm
,dip
->i_mtime
);
375 rip
->i_dtime
= conv4(norm
,dip
->i_dtime
);
376 rip
->i_gid
= conv2(norm
,dip
->i_gid
);
377 rip
->i_links_count
= conv2(norm
,dip
->i_links_count
);
378 rip
->i_blocks
= conv4(norm
,dip
->i_blocks
);
379 rip
->i_flags
= conv4(norm
,dip
->i_flags
);
380 /* Minix doesn't touch osd1 and osd2 either, so just copy. */
381 memcpy(&rip
->osd1
, &dip
->osd1
, sizeof(rip
->osd1
));
382 for (i
= 0; i
< EXT2_N_BLOCKS
; i
++)
383 rip
->i_block
[i
] = conv4(norm
, dip
->i_block
[i
]);
384 rip
->i_generation
= conv4(norm
,dip
->i_generation
);
385 rip
->i_file_acl
= conv4(norm
,dip
->i_file_acl
);
386 rip
->i_dir_acl
= conv4(norm
,dip
->i_dir_acl
);
387 rip
->i_faddr
= conv4(norm
,dip
->i_faddr
);
388 memcpy(&rip
->osd2
, &dip
->osd2
, sizeof(rip
->osd2
));
390 /* Copying inode to disk from the in-core table. */
391 dip
->i_mode
= conv2(norm
,rip
->i_mode
);
392 dip
->i_uid
= conv2(norm
,rip
->i_uid
);
393 dip
->i_size
= conv4(norm
,rip
->i_size
);
394 dip
->i_atime
= conv4(norm
,rip
->i_atime
);
395 dip
->i_ctime
= conv4(norm
,rip
->i_ctime
);
396 dip
->i_mtime
= conv4(norm
,rip
->i_mtime
);
397 dip
->i_dtime
= conv4(norm
,rip
->i_dtime
);
398 dip
->i_gid
= conv2(norm
,rip
->i_gid
);
399 dip
->i_links_count
= conv2(norm
,rip
->i_links_count
);
400 dip
->i_blocks
= conv4(norm
,rip
->i_blocks
);
401 dip
->i_flags
= conv4(norm
,rip
->i_flags
);
402 /* Minix doesn't touch osd1 and osd2 either, so just copy. */
403 memcpy(&dip
->osd1
, &rip
->osd1
, sizeof(dip
->osd1
));
404 for (i
= 0; i
< EXT2_N_BLOCKS
; i
++)
405 dip
->i_block
[i
] = conv4(norm
, rip
->i_block
[i
]);
406 dip
->i_generation
= conv4(norm
,rip
->i_generation
);
407 dip
->i_file_acl
= conv4(norm
,rip
->i_file_acl
);
408 dip
->i_dir_acl
= conv4(norm
,rip
->i_dir_acl
);
409 dip
->i_faddr
= conv4(norm
,rip
->i_faddr
);
410 memcpy(&dip
->osd2
, &rip
->osd2
, sizeof(dip
->osd2
));
415 /*===========================================================================*
417 *===========================================================================*/
419 struct inode
*ip
/* The inode to be duplicated. */
422 /* This routine is a simplified form of get_inode() for the case where
423 * the inode pointer is already known.