/* lfs_inode.c 4.11 82/06/07 */
/* merged into kernel: @(#)iget.c 2.2 4/8/82 */
#define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ)
* Initialize hash links for inodes
* and build inode free list.
register struct inode
*ip
= inode
;
for (i
= 0; i
< ninode
-1; i
++, ip
++)
for (i
= 0; i
< INOHSZ
; i
++)
* Look up an inode by device,inumber.
* If it is in core (in the inode structure),
* honor the locking protocol.
* If it is not in core, read it in from the
* If the inode is mounted on, perform
* the indicated indirection.
* In all cases, a pointer to a locked
* inode structure is returned.
* panic: no imt -- if the mounted file
* system is not in the mount table.
register struct inode
*ip
;
register struct mount
*mp
;
register struct dinode
*dp
;
slot
= INOHASH(dev
, ino
);
ip
= &inode
[inohash
[slot
]];
while (ip
!= &inode
[-1]) {
if (ino
== ip
->i_number
&& dev
== ip
->i_dev
) {
if ((ip
->i_flag
&ILOCK
) != 0) {
sleep((caddr_t
)ip
, PINOD
);
if ((ip
->i_flag
&IMOUNT
) != 0) {
for (mp
= &mount
[0]; mp
< &mount
[NMOUNT
]; mp
++)
fs
= mp
->m_bufp
->b_un
.b_fs
;
ip
= &inode
[ip
->i_hlink
];
ip
->i_hlink
= inohash
[slot
];
inohash
[slot
] = ip
- inode
;
bp
= bread(dev
, fsbtodb(fs
, itod(fs
, ino
)), fs
->fs_bsize
);
if ((bp
->b_flags
&B_ERROR
) != 0) {
* Decrement reference count of
* write the inode out and if necessary,
* truncate and deallocate the file.
register struct inode
*ip
;
if ((ip
->i_flag
& ILOCK
) == 0)
register struct inode
*ip
;
register struct inode
*jp
;
ifree(ip
, ip
->i_number
, mode
);
IUPDAT(ip
, &time
, &time
, 0);
i
= INOHASH(ip
->i_dev
, ip
->i_number
);
inohash
[i
] = ip
->i_hlink
;
for (jp
= &inode
[inohash
[i
]]; jp
!= &inode
[-1];
jp
= &inode
[jp
->i_hlink
])
jp
->i_hlink
= ip
->i_hlink
;
* Check accessed and update flags on
* If any is on, update the inode
* If waitfor is given, then must insure
* i/o order so wait for write to complete.
iupdat(ip
, ta
, tm
, waitfor
)
register struct inode
*ip
;
if ((ip
->i_flag
& (IUPD
|IACC
|ICHG
)) != 0) {
bp
= bread(ip
->i_dev
, fsbtodb(fp
, itod(fp
, ip
->i_number
)),
if (bp
->b_flags
& B_ERROR
) {
ip
->i_flag
&= ~(IUPD
|IACC
|ICHG
);
dp
= bp
->b_un
.b_dino
+ itoo(fp
, ip
->i_number
);
* Free all the disk blocks associated
* with the specified inode structure.
* The blocks of the file are removed
* in reverse order. This FILO
* algorithm will tend to maintain
* a contiguous free list much longer
register struct inode
*ip
;
if (i
!= IFREG
&& i
!= IFDIR
&& i
!= IFLNK
)
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
for (i
= 0; i
< NDADDR
; i
++)
for (i
= 0; i
< NIADDR
; i
++)
itmp
.i_flag
|= ICHG
|IUPD
;
iupdat(&itmp
, &time
, &time
, 1);
ip
->i_flag
&= ~(IUPD
|IACC
|ICHG
);
* Now return blocks to free list... if machine
* crashes, they will be harmless MISSING blocks.
* release double indirect block first
ip
->i_ib
[NIADDR
- 1] = (daddr_t
)0;
* release single indirect blocks second
for (i
= NIADDR
- 2; i
>= 0; i
--) {
ip
->i_ib
[i
] = (daddr_t
)0;
* finally release direct blocks
for (i
= NDADDR
- 1; i
>=0; i
--) {
ip
->i_db
[i
] = (daddr_t
)0;
fre(ip
, bn
, (off_t
)blksize(fs
, ip
, i
));
* Inode was written and flags updated above.
* No need to modify flags here.
register struct inode
*ip
;
for (i
= NINDIR(fs
) - 1; i
>= 0; i
--) {
bp
= bread(ip
->i_dev
, fsbtodb(fs
, bn
), fs
->fs_bsize
);
if (bp
->b_flags
& B_ERROR
) {
fre(ip
, nb
, fs
->fs_bsize
);
fre(ip
, bn
, fs
->fs_bsize
);
register struct inode
*ip
;
if ((mode
& IFMT
) == IFDIR
)
ipref
= dirpref(u
.u_pdir
->i_fs
);
ipref
= u
.u_pdir
->i_number
;
ip
= ialloc(u
.u_pdir
, ipref
, mode
);
ip
->i_flag
|= IACC
|IUPD
|ICHG
;
ip
->i_mode
= mode
& ~u
.u_cmask
;
ip
->i_gid
= u
.u_pdir
->i_gid
;
* Make sure inode goes to disk before directory entry.
iupdat(ip
, &time
, &time
, 1);
* write error occurred trying to update directory
* so must deallocate the inode
* Write a directory entry with
* parameters left as side effects
register struct direct
*dp
, *ndp
;
int loc
, dsize
, spccnt
, newsize
;
u
.u_dent
.d_ino
= ip
->i_number
;
newsize
= DIRSIZ(&u
.u_dent
);
* if u.u_count == 0, a new directory block must be allocated.
u
.u_dent
.d_reclen
= DIRBLKSIZ
;
u
.u_base
= (caddr_t
)&u
.u_dent
;
* must read in an existing directory block
* to prepare to place the new entry into it.
lbn
= lblkno(fs
, u
.u_offset
);
base
= blkoff(fs
, u
.u_offset
);
bn
= fsbtodb(fs
, bmap(u
.u_pdir
, lbn
, B_WRITE
, base
+ u
.u_count
));
if (u
.u_offset
+ u
.u_count
> u
.u_pdir
->i_size
)
u
.u_pdir
->i_size
= u
.u_offset
+ u
.u_count
;
bp
= bread(u
.u_pdir
->i_dev
, bn
, blksize(fs
, u
.u_pdir
, lbn
));
if (bp
->b_flags
& B_ERROR
) {
dirbuf
= bp
->b_un
.b_addr
+ base
;
dp
= (struct direct
*)dirbuf
;
spccnt
= dp
->d_reclen
- dsize
;
* if there is insufficient room to make an entry at this point
* namei insures that compacting from u.u_offset for u.u_count
* bytes will provide the necessary space.
for (loc
= dp
->d_reclen
; loc
< u
.u_count
; ) {
ndp
= (struct direct
*)(dirbuf
+ loc
);
dp
= (struct direct
*)((char *)dp
+ dsize
);
spccnt
+= ndp
->d_reclen
- dsize
;
* Update the pointer fields in the previous entry (if any),
* copy in the new entry, and write out the block.
if (spccnt
+ dsize
< newsize
)
panic("wdir: compact failed");
u
.u_dent
.d_reclen
= spccnt
+ dsize
;
panic("wdir: compact failed");
u
.u_dent
.d_reclen
= spccnt
;
dp
= (struct direct
*)((char *)dp
+ dsize
);
bcopy(&u
.u_dent
, dp
, newsize
);
u
.u_pdir
->i_flag
|= IUPD
|ICHG
;
* Lock an inode. If its already locked, set the WANT bit and sleep.
register struct inode
*ip
;
while (ip
->i_flag
&ILOCK
) {
sleep((caddr_t
)ip
, PINOD
);
* Unlock an inode. If WANT bit is on, wakeup.
register struct inode
*ip
;