386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / isofs / isofs_node.c
CommitLineData
7977dadd
WJ
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)isofs_inode.c
34 */
35
36#include "param.h"
37#include "systm.h"
38#include "mount.h"
39#include "proc.h"
40#include "file.h"
41#include "buf.h"
42#include "vnode.h"
43#include "kernel.h"
44#include "malloc.h"
45
46#include "iso.h"
47#include "isofs_node.h"
48
49#define INOHSZ 512
50#if ((INOHSZ&(INOHSZ-1)) == 0)
51#define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1))
52#else
53#define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ)
54#endif
55
56union iso_ihead {
57 union iso_ihead *ih_head[2];
58 struct iso_node *ih_chain[2];
59} iso_ihead[INOHSZ];
60
61int prtactive; /* 1 => print out reclaim of active vnodes */
62
63/*
64 * Initialize hash links for inodes.
65 */
66isofs_init()
67{
68 register int i;
69 register union iso_ihead *ih = iso_ihead;
70
71#ifndef lint
72 if (VN_MAXPRIVATE < sizeof(struct iso_node))
73 panic("ihinit: too small");
74#endif /* not lint */
75 for (i = INOHSZ; --i >= 0; ih++) {
76 ih->ih_head[0] = ih;
77 ih->ih_head[1] = ih;
78 }
79}
80
81/*
82 * Look up a ISOFS dinode number to find its incore vnode.
83 * If it is not in core, read it in from the specified device.
84 * If it is in core, wait for the lock bit to clear, then
85 * return the inode locked. Detection and handling of mount
86 * points must be done by the calling routine.
87 */
88iso_iget(xp, ino, ipp, isodir)
89 struct iso_node *xp;
90 ino_t ino;
91 struct iso_node **ipp;
92 struct iso_directory_record *isodir;
93{
94 dev_t dev = xp->i_dev;
95 struct mount *mntp = ITOV(xp)->v_mount;
96 extern struct vnodeops isofs_vnodeops, spec_inodeops;
97 register struct iso_node *ip, *iq;
98 register struct vnode *vp;
99 struct vnode *nvp;
100 struct buf *bp;
101 struct dinode *dp;
102 union iso_ihead *ih;
103 int i, error;
104 struct iso_mnt *imp;
105
106 ih = &iso_ihead[INOHASH(dev, ino)];
107loop:
108 for (ip = ih->ih_chain[0];
109 ip != (struct iso_node *)ih;
110 ip = ip->i_forw) {
111 if (ino != ip->i_number || dev != ip->i_dev)
112 continue;
113 if ((ip->i_flag&ILOCKED) != 0) {
114 ip->i_flag |= IWANT;
115 sleep((caddr_t)ip, PINOD);
116 goto loop;
117 }
118 if (vget(ITOV(ip)))
119 goto loop;
120 *ipp = ip;
121 return(0);
122 }
123 /*
124 * Allocate a new inode.
125 */
126 if (error = getnewvnode(VT_ISOFS, mntp, &isofs_vnodeops, &nvp)) {
127 *ipp = 0;
128 return (error);
129 }
130 ip = VTOI(nvp);
131 ip->i_vnode = nvp;
132 ip->i_flag = 0;
133 ip->i_devvp = 0;
134 ip->i_diroff = 0;
135 ip->i_lockf = 0;
136 /*
137 * Put it onto its hash chain and lock it so that other requests for
138 * this inode will block if they arrive while we are sleeping waiting
139 * for old data structures to be purged or for the contents of the
140 * disk portion of this inode to be read.
141 */
142 ip->i_dev = dev;
143 ip->i_number = ino;
144 insque(ip, ih);
145 ISO_ILOCK(ip);
146
147 ip->iso_reclen = isonum_711 (isodir->length);
148 ip->iso_extlen = isonum_711 (isodir->ext_attr_length);
149 ip->iso_extent = isonum_733 (isodir->extent);
150 ip->i_size = isonum_733 (isodir->size);
151 bcopy (isodir->date, ip->iso_time, sizeof ip->iso_time);
152 ip->iso_flags = isonum_711 (isodir->flags);
153 ip->iso_unit_size = isonum_711 (isodir->file_unit_size);
154 ip->iso_interleave_gap = isonum_711 (isodir->interleave);
155 ip->iso_volume_seq = isonum_723 (isodir->volume_sequence_number);
156 ip->iso_namelen = isonum_711 (isodir->name_len);
157
158 /*
159 * Initialize the associated vnode
160 */
161 vp = ITOV(ip);
162
163 if (ip->iso_flags & 2)
164 vp->v_type = VDIR;
165 else
166 vp->v_type = VREG;
167
168 imp = VFSTOISOFS (mntp);
169
170 if (ino == imp->root_extent)
171 vp->v_flag |= VROOT;
172 /*
173 * Finish inode initialization.
174 */
175 ip->i_mnt = imp;
176 ip->i_devvp = imp->im_devvp;
177 VREF(ip->i_devvp);
178 *ipp = ip;
179 return (0);
180}
181
182/*
183 * Unlock and decrement the reference count of an inode structure.
184 */
185iso_iput(ip)
186 register struct iso_node *ip;
187{
188
189 if ((ip->i_flag & ILOCKED) == 0)
190 panic("iso_iput");
191 ISO_IUNLOCK(ip);
192 vrele(ITOV(ip));
193}
194
195/*
196 * Last reference to an inode, write the inode out and if necessary,
197 * truncate and deallocate the file.
198 */
199isofs_inactive(vp, p)
200 struct vnode *vp;
201 struct proc *p;
202{
203 register struct iso_node *ip = VTOI(vp);
204 int mode, error = 0;
205
206 if (prtactive && vp->v_usecount != 0)
207 vprint("isofs_inactive: pushing active", vp);
208
209 ip->i_flag = 0;
210 /*
211 * If we are done with the inode, reclaim it
212 * so that it can be reused immediately.
213 */
214 if (vp->v_usecount == 0 /* && ip->i_mode == 0 */)
215 vgone(vp);
216 return (error);
217}
218
219/*
220 * Reclaim an inode so that it can be used for other purposes.
221 */
222isofs_reclaim(vp)
223 register struct vnode *vp;
224{
225 register struct iso_node *ip = VTOI(vp);
226 int i;
227
228 if (prtactive && vp->v_usecount != 0)
229 vprint("isofs_reclaim: pushing active", vp);
230 /*
231 * Remove the inode from its hash chain.
232 */
233 remque(ip);
234 ip->i_forw = ip;
235 ip->i_back = ip;
236 /*
237 * Purge old data structures associated with the inode.
238 */
239 cache_purge(vp);
240 if (ip->i_devvp) {
241 vrele(ip->i_devvp);
242 ip->i_devvp = 0;
243 }
244 ip->i_flag = 0;
245 return (0);
246}
247
248/*
249 * Lock an inode. If its already locked, set the WANT bit and sleep.
250 */
251iso_ilock(ip)
252 register struct iso_node *ip;
253{
254
255 while (ip->i_flag & ILOCKED) {
256 ip->i_flag |= IWANT;
257 if (ip->i_spare0 == curproc->p_pid)
258 panic("locking against myself");
259 ip->i_spare1 = curproc->p_pid;
260 (void) sleep((caddr_t)ip, PINOD);
261 }
262 ip->i_spare1 = 0;
263 ip->i_spare0 = curproc->p_pid;
264 ip->i_flag |= ILOCKED;
265}
266
267/*
268 * Unlock an inode. If WANT bit is on, wakeup.
269 */
270iso_iunlock(ip)
271 register struct iso_node *ip;
272{
273
274 if ((ip->i_flag & ILOCKED) == 0)
275 vprint("iso_iunlock: unlocked inode", ITOV(ip));
276 ip->i_spare0 = 0;
277 ip->i_flag &= ~ILOCKED;
278 if (ip->i_flag&IWANT) {
279 ip->i_flag &= ~IWANT;
280 wakeup((caddr_t)ip);
281 }
282}