xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 51347)
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*51347Sbostic  *	@(#)lfs_alloc.c	7.32 (Berkeley) 10/09/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. */
165*51347Sbostic int
16651155Sbostic lfs_vcreate(mp, ino, vpp)
16751183Sbostic 	MOUNT *mp;
16851155Sbostic 	ino_t ino;
16951183Sbostic 	VNODE **vpp;
1704359Smckusick {
17151183Sbostic 	INODE *ip;
17251183Sbostic 	UFSMOUNT *ump;
17351155Sbostic 	int error, i;
1744359Smckusick 
17551155Sbostic printf("lfs_vcreate: ino %d\n", ino);
17651215Sbostic 	/* Create the vnode. */
17751215Sbostic 	if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp))
17851311Sbostic 		return (error);
1794359Smckusick 
18051215Sbostic 	/* Get a pointer to the private mount structure. */
18151155Sbostic 	ump = VFSTOUFS(mp);
1824651Smckusic 
18351155Sbostic 	/* Initialize the inode. */
18451155Sbostic 	ip = VTOI(*vpp);
18551155Sbostic 	ip->i_diroff = 0;
18651155Sbostic 	ip->i_devvp = ump->um_devvp;
18751155Sbostic 	ip->i_dev = ump->um_dev;
18851155Sbostic 	ip->i_flag = 0;
18951155Sbostic 	ip->i_lfs = ump->um_lfs;
19051155Sbostic 	ip->i_lockf = 0;
19151155Sbostic 	ip->i_mode = 0;
19251183Sbostic 	ip->i_number = ip->i_din.di_inum = ino;
19351155Sbostic 	ip->i_vnode = *vpp;
19451155Sbostic #ifdef QUOTA
19551155Sbostic 	for (i = 0; i < MAXQUOTAS; i++)
19651155Sbostic 		ip->i_dquot[i] = NODQUOT;
19751155Sbostic #endif
19851215Sbostic 	VREF(ip->i_devvp);			/* XXX: Why? */
19951155Sbostic 	return (0);
2004651Smckusic }
20151183Sbostic 
20251215Sbostic /* Return the current version number for a specific inode. */
20351183Sbostic u_long
20451183Sbostic lfs_getversion(fs, ino)
20551183Sbostic 	LFS *fs;
20651183Sbostic 	ino_t ino;
20751183Sbostic {
20851215Sbostic 	BUF *bp;
20951183Sbostic 	IFILE *ifp;
21051215Sbostic 	u_long version;
21151183Sbostic 
21251215Sbostic 	/*
21351311Sbostic 	 * Read the appropriate block from the ifile.  Return the
21451311Sbostic 	 * version number.
21551215Sbostic 	 */
21651183Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
21751183Sbostic 	version = ifp->if_version;
21851183Sbostic 	brelse(bp);
21951311Sbostic 	return (version);
22051183Sbostic }
22151215Sbostic 
22251215Sbostic /* Set values in the ifile for the inode. */
22351215Sbostic void
22451215Sbostic lfs_iset(ip, daddr, atime)
22551215Sbostic 	INODE *ip;
22651215Sbostic 	daddr_t daddr;
22751215Sbostic 	time_t atime;
22851215Sbostic {
22951215Sbostic 	BUF *bp;
23051215Sbostic 	IFILE *ifp;
23151215Sbostic 	LFS *fs;
23251215Sbostic 	ino_t ino;
23351215Sbostic 
23451311Sbostic printf("lfs_iset: setting ino %d daddr %lx time %lx\n",
23551311Sbostic ip->i_number, daddr, atime);
23651215Sbostic 
23751215Sbostic 	fs = ip->i_lfs;
23851215Sbostic 	ino = ip->i_number;
23951215Sbostic 	LFS_IENTRY(ifp, fs, ino, bp);
24051215Sbostic 
24151215Sbostic 	ifp->if_daddr = daddr;
24251215Sbostic 	ifp->if_st_atime = atime;
24351215Sbostic 	lfs_bwrite(bp);
24451215Sbostic }
24551215Sbostic #endif /* LOGFS */
246