xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 51215)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_alloc.c	7.30 (Berkeley) 10/02/91
8  */
9 
10 #ifdef LOGFS
11 #include "param.h"
12 #include "kernel.h"
13 #include "buf.h"
14 #include "vnode.h"
15 #include "syslog.h"
16 #include "mount.h"
17 #include "../ufs/quota.h"
18 #include "../ufs/inode.h"
19 #include "../ufs/ufsmount.h"
20 #include "lfs.h"
21 #include "lfs_extern.h"
22 
23 /* Read in the block containing a specific inode from the ifile. */
24 #define	LFS_IENTRY(I, F, IN, BP) \
25 	if (bread((F)->lfs_ivnode, (IN) / IFPB(F) + (F)->lfs_segtabsz, \
26 	    (F)->lfs_bsize, NOCRED, &BP)) \
27 		panic("lfs_ientry: read"); \
28 	(I) = (IFILE *)BP->b_un.b_addr + IN % IFPB(F);
29 
30 /*
31  * Allocate a new inode.
32  */
33 ino_t
34 lfs_ialloc(fs, pip, ipp, cred)
35 	LFS *fs;
36 	INODE *pip, **ipp;
37 	UCRED *cred;
38 {
39 	BUF *bp;
40 	IFILE *ifp;
41 	INODE *ip;
42 	VNODE *vp;
43 	ino_t new_ino;
44 	int error;
45 
46 	/* Get the head of the freelist. */
47 	new_ino = fs->lfs_free;
48 	if (new_ino == LFS_UNUSED_INUM) {
49 		/*
50 		 * XXX
51 		 * Currently, no more inodes are allocated if the ifile fills
52 		 * up.  The ifile should be extended instead.
53 		 */
54 		uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt);
55 		log(LOG_ERR, "uid %d on %s: out of inodes\n",
56 		    cred->cr_uid, fs->lfs_fsmnt);
57 		return (ENOSPC);
58 	}
59 printf("lfs_ialloc: allocate inode %d\n", new_ino);
60 
61 	/* Read the appropriate block from the ifile. */
62 	LFS_IENTRY(ifp, fs, new_ino, bp);
63 
64 	if (ifp->if_daddr != LFS_UNUSED_DADDR)
65 		panic("lfs_ialloc: inuse inode on the free list");
66 
67 	/* Remove from the free list, set the access time, write it back. */
68 	fs->lfs_free = ifp->if_nextfree;
69 	ifp->if_st_atime = time.tv_sec;
70 	lfs_bwrite(bp);
71 
72 	/* Create a vnode to associate with the inode. */
73 	error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp);
74 	if (error)
75 		return (error);
76 	*ipp = ip = VTOI(vp);
77 
78 	/* Set a new generation number for this inode. */
79 	if (++nextgennumber < (u_long)time.tv_sec)
80 		nextgennumber = time.tv_sec;
81 	ip->i_gen = nextgennumber;
82 
83 	/* Insert into the inode hash table. */
84 	lfs_hqueue(ip);
85 
86 	/* Set superblock modified bit and increment file count. */
87 	fs->lfs_fmod = 1;
88 	++fs->lfs_nfiles;
89 	return (0);
90 }
91 
92 /* Free an inode. */
93 void
94 lfs_ifree(ip)
95 	INODE *ip;
96 {
97 	BUF *bp;
98 	IFILE *ifp;
99 	LFS *fs;
100 	ino_t ino;
101 
102 printf("lfs_ifree: free %d\n", ip->i_number);
103 	/* Get the inode number and file system. */
104 	fs = ip->i_lfs;
105 	ino = ip->i_number;
106 
107 	/*
108 	 * Read the appropriate block from the ifile.  Set the inode entry to
109 	 * unused, increment its version number and link it into the free chain.
110 	 */
111 	LFS_IENTRY(ifp, fs, ino, bp);
112 	ifp->if_daddr = LFS_UNUSED_DADDR;
113 	++ifp->if_version;
114 	ifp->if_nextfree = fs->lfs_free;
115 	fs->lfs_free = ino;
116 
117 	lfs_bwrite(bp);
118 
119 	/* Set superblock modified bit and decrement file count. */
120 	fs->lfs_fmod = 1;
121 	--fs->lfs_nfiles;
122 }
123 
124 /* Translate an inode number to a disk address. */
125 daddr_t
126 itod(fs, ino)
127 	LFS *fs;
128 	ino_t ino;
129 {
130 	BUF *bp;
131 	IFILE *ifp;
132 	daddr_t iaddr;
133 
134 	/* Read the appropriate block from the ifile. */
135 	LFS_IENTRY(ifp, fs, ino, bp);
136 
137 	if (ifp->if_daddr == LFS_UNUSED_DADDR)
138 		panic("itod: unused disk address");
139 	iaddr = ifp->if_daddr;
140 	brelse(bp);
141 	return (iaddr);
142 }
143 
144 /* Search a block for a specific dinode. */
145 DINODE *
146 lfs_ifind(fs, ino, page)
147 	LFS *fs;
148 	ino_t ino;
149 	void *page;
150 {
151 	register DINODE *dip;
152 	register int cnt;
153 
154 printf("lfs_ifind: inode %d\n", ino);
155 	dip = page;
156 	for (cnt = INOPB(fs); cnt--; ++dip)
157 		if (dip->di_inum == ino)
158 			return (dip);
159 
160 	panic("lfs_ifind: dinode %%u not found", ino);
161 	/* NOTREACHED */
162 }
163 
164 /* Create a new vnode/inode pair and initialize what fields we can. */
165 lfs_vcreate(mp, ino, vpp)
166 	MOUNT *mp;
167 	ino_t ino;
168 	VNODE **vpp;
169 {
170 	INODE *ip;
171 	UFSMOUNT *ump;
172 	int error, i;
173 
174 printf("lfs_vcreate: ino %d\n", ino);
175 	/* Create the vnode. */
176 	if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp))
177 		return(error);
178 
179 	/* Get a pointer to the private mount structure. */
180 	ump = VFSTOUFS(mp);
181 
182 	/* Initialize the inode. */
183 	ip = VTOI(*vpp);
184 	ip->i_diroff = 0;
185 	ip->i_devvp = ump->um_devvp;
186 	ip->i_dev = ump->um_dev;
187 	ip->i_flag = 0;
188 	ip->i_lfs = ump->um_lfs;
189 	ip->i_lockf = 0;
190 	ip->i_mode = 0;
191 	ip->i_number = ip->i_din.di_inum = ino;
192 	ip->i_vnode = *vpp;
193 #ifdef QUOTA
194 	for (i = 0; i < MAXQUOTAS; i++)
195 		ip->i_dquot[i] = NODQUOT;
196 #endif
197 	VREF(ip->i_devvp);			/* XXX: Why? */
198 	return (0);
199 }
200 
201 /* Return the current version number for a specific inode. */
202 u_long
203 lfs_getversion(fs, ino)
204 	LFS *fs;
205 	ino_t ino;
206 {
207 	BUF *bp;
208 	IFILE *ifp;
209 	u_long version;
210 
211 	/*
212 	 * Read the appropriate block from the ifile.  Return the version
213 	 * number.
214 	 */
215 	LFS_IENTRY(ifp, fs, ino, bp);
216 	version = ifp->if_version;
217 	brelse(bp);
218 	return(version);
219 }
220 
221 /* Set values in the ifile for the inode. */
222 void
223 lfs_iset(ip, daddr, atime)
224 	INODE *ip;
225 	daddr_t daddr;
226 	time_t atime;
227 {
228 	BUF *bp;
229 	IFILE *ifp;
230 	LFS *fs;
231 	ino_t ino;
232 
233 printf("lfs_iset: setting ino %d daddr %lx time %lx\n", ip->i_number, daddr, atime);
234 
235 	fs = ip->i_lfs;
236 	ino = ip->i_number;
237 	LFS_IENTRY(ifp, fs, ino, bp);
238 
239 	ifp->if_daddr = daddr;
240 	ifp->if_st_atime = atime;
241 	lfs_bwrite(bp);
242 }
243 #endif /* LOGFS */
244