xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 51990)
1 /*
2  * Copyright (c) 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_alloc.c	7.38 (Berkeley) 12/16/91
8  */
9 
10 #include <sys/param.h>
11 #include <sys/kernel.h>
12 #include <sys/buf.h>
13 #include <sys/vnode.h>
14 #include <sys/syslog.h>
15 #include <sys/mount.h>
16 #include <sys/malloc.h>
17 
18 #include <ufs/ufs/quota.h>
19 #include <ufs/ufs/inode.h>
20 #include <ufs/ufs/ufsmount.h>
21 
22 #include <ufs/lfs/lfs.h>
23 #include <ufs/lfs/lfs_extern.h>
24 
25 extern u_long nextgennumber;
26 
27 /* Allocate a new inode. */
28 /* ARGSUSED */
29 int
30 lfs_valloc(pvp, notused, cred, vpp)
31 	VNODE *pvp, **vpp;
32 	int notused;
33 	UCRED *cred;
34 {
35 	struct lfs *fs;
36 	BUF *bp;
37 	IFILE *ifp;
38 	INODE *ip;
39 	VNODE *vp;
40 	ino_t new_ino;
41 	int error;
42 
43 #ifdef VERBOSE
44 	printf("lfs_valloc\n");
45 #endif
46 	/* Get the head of the freelist. */
47 	fs = VTOI(pvp)->i_lfs;
48 	new_ino = fs->lfs_free;
49 	if (new_ino == LFS_UNUSED_INUM) {
50 		/*
51 		 * XXX
52 		 * Currently, no more inodes are allocated if the ifile fills
53 		 * up.  The ifile should be extended instead.
54 		 */
55 		uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt);
56 		log(LOG_ERR, "uid %d on %s: out of inodes\n",
57 		    cred->cr_uid, fs->lfs_fsmnt);
58 		return (ENOSPC);
59 	}
60 #ifdef ALLOCPRINT
61 	printf("lfs_ialloc: allocate inode %d\n", new_ino);
62 #endif
63 
64 	/*
65 	 * Remove the inode from the free list and write the free list
66 	 * back.
67 	 */
68 	LFS_IENTRY(ifp, fs, new_ino, bp);
69 	if (ifp->if_daddr != LFS_UNUSED_DADDR)
70 		panic("lfs_ialloc: inuse inode on the free list");
71 	fs->lfs_free = ifp->if_nextfree;
72 	ifp->if_st_atime = time.tv_sec;
73 	LFS_IWRITE(fs, bp);
74 
75 	/* Create a vnode to associate with the inode. */
76 	if (error = lfs_vcreate(pvp->v_mount, new_ino, &vp))
77 		return (error);
78 	*vpp = vp;
79 	ip = VTOI(vp);
80 	VREF(ip->i_devvp);
81 
82 	/* Set a new generation number for this inode. */
83 	if (++nextgennumber < (u_long)time.tv_sec)
84 		nextgennumber = time.tv_sec;
85 	ip->i_gen = nextgennumber;
86 
87 	/* Insert into the inode hash table. */
88 	ufs_ihashins(ip);
89 
90 	/* Set superblock modified bit and increment file count. */
91 	fs->lfs_fmod = 1;
92 	++fs->lfs_nfiles;
93 	return (0);
94 }
95 
96 /* Create a new vnode/inode pair and initialize what fields we can. */
97 int
98 lfs_vcreate(mp, ino, vpp)
99 	MOUNT *mp;
100 	ino_t ino;
101 	VNODE **vpp;
102 {
103 	extern struct vnodeops lfs_vnodeops;
104 	INODE *ip;
105 	UFSMOUNT *ump;
106 	int error, i;
107 
108 #ifdef VERBOSE
109 	printf("lfs_vcreate: ino %d\n", ino);
110 #endif
111 	/* Create the vnode. */
112 	if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) {
113 		*vpp = NULL;
114 		return (error);
115 	}
116 
117 	/* Get a pointer to the private mount structure. */
118 	ump = VFSTOUFS(mp);
119 
120 	/* Initialize the inode. */
121 	MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK);
122 	(*vpp)->v_data = ip;
123 	ip->i_vnode = *vpp;
124 	ip->i_flag = 0;
125 	ip->i_mode = 0;
126 	ip->i_diroff = 0;
127 	ip->i_lockf = 0;
128 	ip->i_dev = ump->um_dev;
129 	ip->i_number = ip->i_din.di_inum = ino;
130 	ip->i_lfs = ump->um_lfs;
131 	ip->i_devvp = ump->um_devvp;
132 #ifdef QUOTA
133 	for (i = 0; i < MAXQUOTAS; i++)
134 		ip->i_dquot[i] = NODQUOT;
135 #endif
136 	return (0);
137 }
138 
139 /* Free an inode. */
140 /* ARGUSED */
141 void
142 lfs_vfree(vp, notused1, notused2)
143 	VNODE *vp;
144 	ino_t notused1;
145 	int notused2;
146 {
147 	BUF *bp;
148 	IFILE *ifp;
149 	INODE *ip;
150 	struct lfs *fs;
151 	ino_t ino;
152 
153 	ip = VTOI(vp);
154 #ifdef VERBOSE
155 	printf("lfs_vfree: free %d\n", ip->i_number);
156 #endif
157 	/* Get the inode number and file system. */
158 	fs = ip->i_lfs;
159 	ino = ip->i_number;
160 
161 	/*
162 	 * Set the ifile's inode entry to unused, increment its version number
163 	 * and link it into the free chain.
164 	 */
165 	LFS_IENTRY(ifp, fs, ino, bp);
166 	ifp->if_daddr = LFS_UNUSED_DADDR;
167 	++ifp->if_version;
168 	ifp->if_nextfree = fs->lfs_free;
169 	fs->lfs_free = ino;
170 	LFS_IWRITE(fs, bp);
171 
172 	/* Set superblock modified bit and decrement file count. */
173 	fs->lfs_fmod = 1;
174 	--fs->lfs_nfiles;
175 }
176