xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 51311)
123394Smckusick /*
237735Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
334432Sbostic  * All rights reserved.
423394Smckusick  *
544536Sbostic  * %sccs.include.redist.c%
634432Sbostic  *
7*51311Sbostic  *	@(#)lfs_alloc.c	7.31 (Berkeley) 10/03/91
823394Smckusick  */
94359Smckusick 
1051215Sbostic #ifdef LOGFS
1117097Sbloom #include "param.h"
1251155Sbostic #include "kernel.h"
1317097Sbloom #include "buf.h"
1437735Smckusick #include "vnode.h"
1518307Sralph #include "syslog.h"
1651215Sbostic #include "mount.h"
1751155Sbostic #include "../ufs/quota.h"
1851155Sbostic #include "../ufs/inode.h"
1951155Sbostic #include "../ufs/ufsmount.h"
2051155Sbostic #include "lfs.h"
2151155Sbostic #include "lfs_extern.h"
224359Smckusick 
2351215Sbostic /* Read in the block containing a specific inode from the ifile. */
2451155Sbostic #define	LFS_IENTRY(I, F, IN, BP) \
2551155Sbostic 	if (bread((F)->lfs_ivnode, (IN) / IFPB(F) + (F)->lfs_segtabsz, \
2651155Sbostic 	    (F)->lfs_bsize, NOCRED, &BP)) \
2751215Sbostic 		panic("lfs_ientry: read"); \
2851155Sbostic 	(I) = (IFILE *)BP->b_un.b_addr + IN % IFPB(F);
2947571Skarels 
3051215Sbostic /*
3151215Sbostic  * Allocate a new inode.
3251215Sbostic  */
3351155Sbostic ino_t
3451155Sbostic lfs_ialloc(fs, pip, ipp, cred)
3551155Sbostic 	LFS *fs;
3651183Sbostic 	INODE *pip, **ipp;
3751183Sbostic 	UCRED *cred;
3851155Sbostic {
3951183Sbostic 	BUF *bp;
4051155Sbostic 	IFILE *ifp;
4151183Sbostic 	INODE *ip;
4251183Sbostic 	VNODE *vp;
4351155Sbostic 	ino_t new_ino;
4451155Sbostic 	int error;
454359Smckusick 
4651215Sbostic 	/* Get the head of the freelist. */
4751155Sbostic 	new_ino = fs->lfs_free;
4851215Sbostic 	if (new_ino == LFS_UNUSED_INUM) {
4951215Sbostic 		/*
5051215Sbostic 		 * XXX
5151215Sbostic 		 * Currently, no more inodes are allocated if the ifile fills
5251215Sbostic 		 * up.  The ifile should be extended instead.
5351215Sbostic 		 */
5451155Sbostic 		uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt);
5551155Sbostic 		log(LOG_ERR, "uid %d on %s: out of inodes\n",
5651155Sbostic 		    cred->cr_uid, fs->lfs_fsmnt);
5751155Sbostic 		return (ENOSPC);
586716Smckusick 	}
5951215Sbostic printf("lfs_ialloc: allocate inode %d\n", new_ino);
604359Smckusick 
6151215Sbostic 	/* Read the appropriate block from the ifile. */
6251155Sbostic 	LFS_IENTRY(ifp, fs, new_ino, bp);
6351155Sbostic 
6451155Sbostic 	if (ifp->if_daddr != LFS_UNUSED_DADDR)
6551215Sbostic 		panic("lfs_ialloc: inuse inode on the free list");
6651155Sbostic 
6751215Sbostic 	/* Remove from the free list, set the access time, write it back. */
6851183Sbostic 	fs->lfs_free = ifp->if_nextfree;
6951155Sbostic 	ifp->if_st_atime = time.tv_sec;
7051215Sbostic 	lfs_bwrite(bp);
714426Smckusic 
7251215Sbostic 	/* Create a vnode to associate with the inode. */
7351155Sbostic 	error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp);
7451155Sbostic 	if (error)
7537735Smckusick 		return (error);
7651215Sbostic 	*ipp = ip = VTOI(vp);
7751155Sbostic 
7851215Sbostic 	/* Set a new generation number for this inode. */
7938255Smckusick 	if (++nextgennumber < (u_long)time.tv_sec)
8038255Smckusick 		nextgennumber = time.tv_sec;
8138255Smckusick 	ip->i_gen = nextgennumber;
824359Smckusick 
8351215Sbostic 	/* Insert into the inode hash table. */
8451155Sbostic 	lfs_hqueue(ip);
854359Smckusick 
8651215Sbostic 	/* Set superblock modified bit and increment file count. */
8751215Sbostic 	fs->lfs_fmod = 1;
8851215Sbostic 	++fs->lfs_nfiles;
8951155Sbostic 	return (0);
904359Smckusick }
914359Smckusick 
9251215Sbostic /* Free an inode. */
9351155Sbostic void
9451155Sbostic lfs_ifree(ip)
9551183Sbostic 	INODE *ip;
969163Ssam {
9751183Sbostic 	BUF *bp;
9851155Sbostic 	IFILE *ifp;
9951155Sbostic 	LFS *fs;
10051155Sbostic 	ino_t ino;
1014651Smckusic 
10251155Sbostic printf("lfs_ifree: free %d\n", ip->i_number);
10351215Sbostic 	/* Get the inode number and file system. */
10451155Sbostic 	fs = ip->i_lfs;
10551155Sbostic 	ino = ip->i_number;
10651215Sbostic 
10751215Sbostic 	/*
10851215Sbostic 	 * Read the appropriate block from the ifile.  Set the inode entry to
10951215Sbostic 	 * unused, increment its version number and link it into the free chain.
11051215Sbostic 	 */
11151155Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
11251155Sbostic 	ifp->if_daddr = LFS_UNUSED_DADDR;
11351155Sbostic 	++ifp->if_version;
11451155Sbostic 	ifp->if_nextfree = fs->lfs_free;
11551155Sbostic 	fs->lfs_free = ino;
11651215Sbostic 
11751215Sbostic 	lfs_bwrite(bp);
11851215Sbostic 
11951215Sbostic 	/* Set superblock modified bit and decrement file count. */
12051155Sbostic 	fs->lfs_fmod = 1;
12151215Sbostic 	--fs->lfs_nfiles;
1224359Smckusick }
1234359Smckusick 
12451215Sbostic /* Translate an inode number to a disk address. */
1254359Smckusick daddr_t
12651155Sbostic itod(fs, ino)
12751155Sbostic 	LFS *fs;
12851155Sbostic 	ino_t ino;
1294426Smckusic {
13051183Sbostic 	BUF *bp;
13151155Sbostic 	IFILE *ifp;
13251155Sbostic 	daddr_t iaddr;
1334426Smckusic 
13451215Sbostic 	/* Read the appropriate block from the ifile. */
13551155Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
1364426Smckusic 
13751155Sbostic 	if (ifp->if_daddr == LFS_UNUSED_DADDR)
13851215Sbostic 		panic("itod: unused disk address");
13951183Sbostic 	iaddr = ifp->if_daddr;
14051183Sbostic 	brelse(bp);
14151183Sbostic 	return (iaddr);
1424463Smckusic }
1434463Smckusic 
14451215Sbostic /* Search a block for a specific dinode. */
14551183Sbostic DINODE *
14651155Sbostic lfs_ifind(fs, ino, page)
14751155Sbostic 	LFS *fs;
14851155Sbostic 	ino_t ino;
14951155Sbostic 	void *page;
1504463Smckusic {
15151183Sbostic 	register DINODE *dip;
15251155Sbostic 	register int cnt;
1534463Smckusic 
15451155Sbostic printf("lfs_ifind: inode %d\n", ino);
15551155Sbostic 	dip = page;
15651155Sbostic 	for (cnt = INOPB(fs); cnt--; ++dip)
15751155Sbostic 		if (dip->di_inum == ino)
15851155Sbostic 			return (dip);
15934143Smckusick 
16051215Sbostic 	panic("lfs_ifind: dinode %%u not found", ino);
16116784Smckusick 	/* NOTREACHED */
1624359Smckusick }
1634359Smckusick 
16451215Sbostic /* Create a new vnode/inode pair and initialize what fields we can. */
16551155Sbostic lfs_vcreate(mp, ino, vpp)
16651183Sbostic 	MOUNT *mp;
16751155Sbostic 	ino_t ino;
16851183Sbostic 	VNODE **vpp;
1694359Smckusick {
17051183Sbostic 	INODE *ip;
17151183Sbostic 	UFSMOUNT *ump;
17251155Sbostic 	int error, i;
1734359Smckusick 
17451155Sbostic printf("lfs_vcreate: ino %d\n", ino);
17551215Sbostic 	/* Create the vnode. */
17651215Sbostic 	if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp))
177*51311Sbostic 		return (error);
1784359Smckusick 
17951215Sbostic 	/* Get a pointer to the private mount structure. */
18051155Sbostic 	ump = VFSTOUFS(mp);
1814651Smckusic 
18251155Sbostic 	/* Initialize the inode. */
18351155Sbostic 	ip = VTOI(*vpp);
18451155Sbostic 	ip->i_diroff = 0;
18551155Sbostic 	ip->i_devvp = ump->um_devvp;
18651155Sbostic 	ip->i_dev = ump->um_dev;
18751155Sbostic 	ip->i_flag = 0;
18851155Sbostic 	ip->i_lfs = ump->um_lfs;
18951155Sbostic 	ip->i_lockf = 0;
19051155Sbostic 	ip->i_mode = 0;
19151183Sbostic 	ip->i_number = ip->i_din.di_inum = ino;
19251155Sbostic 	ip->i_vnode = *vpp;
19351155Sbostic #ifdef QUOTA
19451155Sbostic 	for (i = 0; i < MAXQUOTAS; i++)
19551155Sbostic 		ip->i_dquot[i] = NODQUOT;
19651155Sbostic #endif
19751215Sbostic 	VREF(ip->i_devvp);			/* XXX: Why? */
19851155Sbostic 	return (0);
1994651Smckusic }
20051183Sbostic 
20151215Sbostic /* Return the current version number for a specific inode. */
20251183Sbostic u_long
20351183Sbostic lfs_getversion(fs, ino)
20451183Sbostic 	LFS *fs;
20551183Sbostic 	ino_t ino;
20651183Sbostic {
20751215Sbostic 	BUF *bp;
20851183Sbostic 	IFILE *ifp;
20951215Sbostic 	u_long version;
21051183Sbostic 
21151215Sbostic 	/*
212*51311Sbostic 	 * Read the appropriate block from the ifile.  Return the
213*51311Sbostic 	 * version number.
21451215Sbostic 	 */
21551183Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
21651183Sbostic 	version = ifp->if_version;
21751183Sbostic 	brelse(bp);
218*51311Sbostic 	return (version);
21951183Sbostic }
22051215Sbostic 
22151215Sbostic /* Set values in the ifile for the inode. */
22251215Sbostic void
22351215Sbostic lfs_iset(ip, daddr, atime)
22451215Sbostic 	INODE *ip;
22551215Sbostic 	daddr_t daddr;
22651215Sbostic 	time_t atime;
22751215Sbostic {
22851215Sbostic 	BUF *bp;
22951215Sbostic 	IFILE *ifp;
23051215Sbostic 	LFS *fs;
23151215Sbostic 	ino_t ino;
23251215Sbostic 
233*51311Sbostic printf("lfs_iset: setting ino %d daddr %lx time %lx\n",
234*51311Sbostic ip->i_number, daddr, atime);
23551215Sbostic 
23651215Sbostic 	fs = ip->i_lfs;
23751215Sbostic 	ino = ip->i_number;
23851215Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
23951215Sbostic 
24051215Sbostic 	ifp->if_daddr = daddr;
24151215Sbostic 	ifp->if_st_atime = atime;
24251215Sbostic 	lfs_bwrite(bp);
24351215Sbostic }
24451215Sbostic #endif /* LOGFS */
245