Rename icache to itable
The inode cache isn't really a cache. The main purpose of it is to allow for synchronization (locking individual inodes), providing long-lived references to inodes, and ensuring that there is only inode in memory.
This commit is contained in:
parent
6e3f75c2aa
commit
077323a8f0
50
kernel/fs.c
50
kernel/fs.c
|
@ -113,9 +113,9 @@ bfree(int dev, uint b)
|
||||||
// sb.startinode. Each inode has a number, indicating its
|
// sb.startinode. Each inode has a number, indicating its
|
||||||
// position on the disk.
|
// position on the disk.
|
||||||
//
|
//
|
||||||
// The kernel keeps a cache of in-use inodes in memory
|
// The kernel keeps a table of in-use inodes in memory
|
||||||
// to provide a place for synchronizing access
|
// to provide a place for synchronizing access
|
||||||
// to inodes used by multiple processes. The cached
|
// to inodes used by multiple processes. The in-memory
|
||||||
// inodes include book-keeping information that is
|
// inodes include book-keeping information that is
|
||||||
// not stored on disk: ip->ref and ip->valid.
|
// not stored on disk: ip->ref and ip->valid.
|
||||||
//
|
//
|
||||||
|
@ -127,15 +127,15 @@ bfree(int dev, uint b)
|
||||||
// is non-zero. ialloc() allocates, and iput() frees if
|
// is non-zero. ialloc() allocates, and iput() frees if
|
||||||
// the reference and link counts have fallen to zero.
|
// the reference and link counts have fallen to zero.
|
||||||
//
|
//
|
||||||
// * Referencing in cache: an entry in the inode cache
|
// * Referencing in table: an entry in the inode table
|
||||||
// is free if ip->ref is zero. Otherwise ip->ref tracks
|
// is free if ip->ref is zero. Otherwise ip->ref tracks
|
||||||
// the number of in-memory pointers to the entry (open
|
// the number of in-memory pointers to the entry (open
|
||||||
// files and current directories). iget() finds or
|
// files and current directories). iget() finds or
|
||||||
// creates a cache entry and increments its ref; iput()
|
// creates a table entry and increments its ref; iput()
|
||||||
// decrements ref.
|
// decrements ref.
|
||||||
//
|
//
|
||||||
// * Valid: the information (type, size, &c) in an inode
|
// * Valid: the information (type, size, &c) in an inode
|
||||||
// cache entry is only correct when ip->valid is 1.
|
// table entry is only correct when ip->valid is 1.
|
||||||
// ilock() reads the inode from
|
// ilock() reads the inode from
|
||||||
// the disk and sets ip->valid, while iput() clears
|
// the disk and sets ip->valid, while iput() clears
|
||||||
// ip->valid if ip->ref has fallen to zero.
|
// ip->valid if ip->ref has fallen to zero.
|
||||||
|
@ -156,16 +156,16 @@ bfree(int dev, uint b)
|
||||||
// and only lock it for short periods (e.g., in read()).
|
// and only lock it for short periods (e.g., in read()).
|
||||||
// The separation also helps avoid deadlock and races during
|
// The separation also helps avoid deadlock and races during
|
||||||
// pathname lookup. iget() increments ip->ref so that the inode
|
// pathname lookup. iget() increments ip->ref so that the inode
|
||||||
// stays cached and pointers to it remain valid.
|
// stays in the table and pointers to it remain valid.
|
||||||
//
|
//
|
||||||
// Many internal file system functions expect the caller to
|
// Many internal file system functions expect the caller to
|
||||||
// have locked the inodes involved; this lets callers create
|
// have locked the inodes involved; this lets callers create
|
||||||
// multi-step atomic operations.
|
// multi-step atomic operations.
|
||||||
//
|
//
|
||||||
// The icache.lock spin-lock protects the allocation of icache
|
// The itable.lock spin-lock protects the allocation of itable
|
||||||
// entries. Since ip->ref indicates whether an entry is free,
|
// entries. Since ip->ref indicates whether an entry is free,
|
||||||
// and ip->dev and ip->inum indicate which i-node an entry
|
// and ip->dev and ip->inum indicate which i-node an entry
|
||||||
// holds, one must hold icache.lock while using any of those fields.
|
// holds, one must hold itable.lock while using any of those fields.
|
||||||
//
|
//
|
||||||
// An ip->lock sleep-lock protects all ip-> fields other than ref,
|
// An ip->lock sleep-lock protects all ip-> fields other than ref,
|
||||||
// dev, and inum. One must hold ip->lock in order to
|
// dev, and inum. One must hold ip->lock in order to
|
||||||
|
@ -174,16 +174,16 @@ bfree(int dev, uint b)
|
||||||
struct {
|
struct {
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
struct inode inode[NINODE];
|
struct inode inode[NINODE];
|
||||||
} icache;
|
} itable;
|
||||||
|
|
||||||
void
|
void
|
||||||
iinit()
|
iinit()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
initlock(&icache.lock, "icache");
|
initlock(&itable.lock, "itable");
|
||||||
for(i = 0; i < NINODE; i++) {
|
for(i = 0; i < NINODE; i++) {
|
||||||
initsleeplock(&icache.inode[i].lock, "inode");
|
initsleeplock(&itable.inode[i].lock, "inode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ ialloc(uint dev, short type)
|
||||||
|
|
||||||
// Copy a modified in-memory inode to disk.
|
// Copy a modified in-memory inode to disk.
|
||||||
// Must be called after every change to an ip->xxx field
|
// Must be called after every change to an ip->xxx field
|
||||||
// that lives on disk, since i-node cache is write-through.
|
// that lives on disk.
|
||||||
// Caller must hold ip->lock.
|
// Caller must hold ip->lock.
|
||||||
void
|
void
|
||||||
iupdate(struct inode *ip)
|
iupdate(struct inode *ip)
|
||||||
|
@ -244,21 +244,21 @@ iget(uint dev, uint inum)
|
||||||
{
|
{
|
||||||
struct inode *ip, *empty;
|
struct inode *ip, *empty;
|
||||||
|
|
||||||
acquire(&icache.lock);
|
acquire(&itable.lock);
|
||||||
|
|
||||||
// Is the inode already cached?
|
// Is the inode already in the table?
|
||||||
empty = 0;
|
empty = 0;
|
||||||
for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){
|
for(ip = &itable.inode[0]; ip < &itable.inode[NINODE]; ip++){
|
||||||
if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
|
if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
|
||||||
ip->ref++;
|
ip->ref++;
|
||||||
release(&icache.lock);
|
release(&itable.lock);
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
if(empty == 0 && ip->ref == 0) // Remember empty slot.
|
if(empty == 0 && ip->ref == 0) // Remember empty slot.
|
||||||
empty = ip;
|
empty = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recycle an inode cache entry.
|
// Recycle an inode entry.
|
||||||
if(empty == 0)
|
if(empty == 0)
|
||||||
panic("iget: no inodes");
|
panic("iget: no inodes");
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ iget(uint dev, uint inum)
|
||||||
ip->inum = inum;
|
ip->inum = inum;
|
||||||
ip->ref = 1;
|
ip->ref = 1;
|
||||||
ip->valid = 0;
|
ip->valid = 0;
|
||||||
release(&icache.lock);
|
release(&itable.lock);
|
||||||
|
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
@ -277,9 +277,9 @@ iget(uint dev, uint inum)
|
||||||
struct inode*
|
struct inode*
|
||||||
idup(struct inode *ip)
|
idup(struct inode *ip)
|
||||||
{
|
{
|
||||||
acquire(&icache.lock);
|
acquire(&itable.lock);
|
||||||
ip->ref++;
|
ip->ref++;
|
||||||
release(&icache.lock);
|
release(&itable.lock);
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ iunlock(struct inode *ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop a reference to an in-memory inode.
|
// Drop a reference to an in-memory inode.
|
||||||
// If that was the last reference, the inode cache entry can
|
// If that was the last reference, the inode table entry can
|
||||||
// be recycled.
|
// be recycled.
|
||||||
// If that was the last reference and the inode has no links
|
// If that was the last reference and the inode has no links
|
||||||
// to it, free the inode (and its content) on disk.
|
// to it, free the inode (and its content) on disk.
|
||||||
|
@ -332,7 +332,7 @@ iunlock(struct inode *ip)
|
||||||
void
|
void
|
||||||
iput(struct inode *ip)
|
iput(struct inode *ip)
|
||||||
{
|
{
|
||||||
acquire(&icache.lock);
|
acquire(&itable.lock);
|
||||||
|
|
||||||
if(ip->ref == 1 && ip->valid && ip->nlink == 0){
|
if(ip->ref == 1 && ip->valid && ip->nlink == 0){
|
||||||
// inode has no links and no other references: truncate and free.
|
// inode has no links and no other references: truncate and free.
|
||||||
|
@ -341,7 +341,7 @@ iput(struct inode *ip)
|
||||||
// so this acquiresleep() won't block (or deadlock).
|
// so this acquiresleep() won't block (or deadlock).
|
||||||
acquiresleep(&ip->lock);
|
acquiresleep(&ip->lock);
|
||||||
|
|
||||||
release(&icache.lock);
|
release(&itable.lock);
|
||||||
|
|
||||||
itrunc(ip);
|
itrunc(ip);
|
||||||
ip->type = 0;
|
ip->type = 0;
|
||||||
|
@ -350,11 +350,11 @@ iput(struct inode *ip)
|
||||||
|
|
||||||
releasesleep(&ip->lock);
|
releasesleep(&ip->lock);
|
||||||
|
|
||||||
acquire(&icache.lock);
|
acquire(&itable.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip->ref--;
|
ip->ref--;
|
||||||
release(&icache.lock);
|
release(&itable.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common idiom: unlock, then put.
|
// Common idiom: unlock, then put.
|
||||||
|
|
Loading…
Reference in a new issue