This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / isofs / isofs_node.c
CommitLineData
15637ed4
RG
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 *
584fddaa 33 * from: @(#)isofs_inode.c
4c45483e 34 * $Id: isofs_node.c,v 1.5 1993/11/07 21:47:42 wollman Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "systm.h"
39#include "mount.h"
40#include "proc.h"
41#include "file.h"
42#include "buf.h"
43#include "vnode.h"
44#include "kernel.h"
45#include "malloc.h"
46
47#include "iso.h"
48#include "isofs_node.h"
584fddaa 49#include "iso_rrip.h"
15637ed4
RG
50
51#define INOHSZ 512
52#if ((INOHSZ&(INOHSZ-1)) == 0)
53#define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1))
54#else
55#define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ)
56#endif
57
58union iso_ihead {
59 union iso_ihead *ih_head[2];
60 struct iso_node *ih_chain[2];
61} iso_ihead[INOHSZ];
62
63int prtactive; /* 1 => print out reclaim of active vnodes */
64
65/*
66 * Initialize hash links for inodes.
67 */
4c45483e 68void
15637ed4
RG
69isofs_init()
70{
71 register int i;
72 register union iso_ihead *ih = iso_ihead;
73
74#ifndef lint
75 if (VN_MAXPRIVATE < sizeof(struct iso_node))
76 panic("ihinit: too small");
77#endif /* not lint */
78 for (i = INOHSZ; --i >= 0; ih++) {
79 ih->ih_head[0] = ih;
80 ih->ih_head[1] = ih;
81 }
82}
83
84/*
85 * Look up a ISOFS dinode number to find its incore vnode.
86 * If it is not in core, read it in from the specified device.
87 * If it is in core, wait for the lock bit to clear, then
88 * return the inode locked. Detection and handling of mount
89 * points must be done by the calling routine.
90 */
4c45483e 91int
15637ed4
RG
92iso_iget(xp, ino, ipp, isodir)
93 struct iso_node *xp;
94 ino_t ino;
95 struct iso_node **ipp;
96 struct iso_directory_record *isodir;
97{
98 dev_t dev = xp->i_dev;
99 struct mount *mntp = ITOV(xp)->v_mount;
100 extern struct vnodeops isofs_vnodeops, spec_inodeops;
101 register struct iso_node *ip, *iq;
102 register struct vnode *vp;
103 struct vnode *nvp;
104 struct buf *bp;
105 struct dinode *dp;
106 union iso_ihead *ih;
4c45483e 107 int i, error, result = 0;
15637ed4
RG
108 struct iso_mnt *imp;
109
110 ih = &iso_ihead[INOHASH(dev, ino)];
111loop:
112 for (ip = ih->ih_chain[0];
113 ip != (struct iso_node *)ih;
114 ip = ip->i_forw) {
115 if (ino != ip->i_number || dev != ip->i_dev)
116 continue;
117 if ((ip->i_flag&ILOCKED) != 0) {
118 ip->i_flag |= IWANT;
4630f671 119 tsleep((caddr_t)ip, PINOD, "isoiget", 0);
15637ed4
RG
120 goto loop;
121 }
122 if (vget(ITOV(ip)))
123 goto loop;
124 *ipp = ip;
125 return(0);
126 }
127 /*
128 * Allocate a new inode.
129 */
130 if (error = getnewvnode(VT_ISOFS, mntp, &isofs_vnodeops, &nvp)) {
131 *ipp = 0;
132 return (error);
133 }
134 ip = VTOI(nvp);
135 ip->i_vnode = nvp;
136 ip->i_flag = 0;
137 ip->i_devvp = 0;
138 ip->i_diroff = 0;
15637ed4
RG
139 ip->iso_parent = xp->i_diroff; /* Parent directory's */
140 ip->iso_parent_ext = xp->iso_extent;
141 ip->i_lockf = 0;
142 /*
143 * Put it onto its hash chain and lock it so that other requests for
144 * this inode will block if they arrive while we are sleeping waiting
145 * for old data structures to be purged or for the contents of the
146 * disk portion of this inode to be read.
147 */
148 ip->i_dev = dev;
149 ip->i_number = ino;
150 insque(ip, ih);
151 ISO_ILOCK(ip);
152
153 ip->iso_reclen = isonum_711 (isodir->length);
154 ip->iso_extlen = isonum_711 (isodir->ext_attr_length);
155 ip->iso_extent = isonum_733 (isodir->extent);
156 ip->i_size = isonum_733 (isodir->size);
15637ed4
RG
157 ip->iso_flags = isonum_711 (isodir->flags);
158 ip->iso_unit_size = isonum_711 (isodir->file_unit_size);
159 ip->iso_interleave_gap = isonum_711 (isodir->interleave);
160 ip->iso_volume_seq = isonum_723 (isodir->volume_sequence_number);
161 ip->iso_namelen = isonum_711 (isodir->name_len);
162
584fddaa
JH
163 imp = VFSTOISOFS (mntp);
164 vp = ITOV(ip);
165 /*
166 * Setup time stamp, attribute , if CL or PL, set loc but not yet..
167 */
168 switch ( imp->iso_ftype ) {
169 case ISO_FTYPE_9660:
170 isofs_rrip_defattr ( isodir, &(ip->inode) );
171 isofs_rrip_deftstamp( isodir, &(ip->inode) );
172 goto FlameOff;
173 break;
174 case ISO_FTYPE_RRIP:
175 result = isofs_rrip_analyze( isodir, &(ip->inode) );
176 break;
177 default:
178 printf("unknown iso_ftype.. %d\n", imp->iso_ftype );
179 break;
180 }
15637ed4
RG
181 /*
182 * Initialize the associated vnode
183 */
584fddaa
JH
184 if ( result & ISO_SUSP_SLINK ) {
185 vp->v_type = VLNK; /* Symbolic Link */
186 } else {
187FlameOff:
188 if (ip->iso_flags & 2) {
189 vp->v_type = VDIR;
190 } else {
191 vp->v_type = VREG;
192 }
193 }
15637ed4
RG
194
195 imp = VFSTOISOFS (mntp);
196
197 if (ino == imp->root_extent)
198 vp->v_flag |= VROOT;
199 /*
200 * Finish inode initialization.
201 */
202 ip->i_mnt = imp;
203 ip->i_devvp = imp->im_devvp;
204 VREF(ip->i_devvp);
205 *ipp = ip;
206 return (0);
207}
208
209/*
210 * Unlock and decrement the reference count of an inode structure.
211 */
4c45483e 212void
15637ed4
RG
213iso_iput(ip)
214 register struct iso_node *ip;
215{
216
217 if ((ip->i_flag & ILOCKED) == 0)
218 panic("iso_iput");
219 ISO_IUNLOCK(ip);
220 vrele(ITOV(ip));
221}
222
223/*
224 * Last reference to an inode, write the inode out and if necessary,
225 * truncate and deallocate the file.
226 */
4c45483e 227int
15637ed4
RG
228isofs_inactive(vp, p)
229 struct vnode *vp;
230 struct proc *p;
231{
232 register struct iso_node *ip = VTOI(vp);
233 int mode, error = 0;
234
235 if (prtactive && vp->v_usecount != 0)
236 vprint("isofs_inactive: pushing active", vp);
237
238 ip->i_flag = 0;
239 /*
240 * If we are done with the inode, reclaim it
241 * so that it can be reused immediately.
242 */
e394bef8
NW
243
244 /*
c27f072f
RG
245 * Purge symlink entries since they cause problems
246 * when cached. Leave other entries alone since flushing
247 * them every time is a major performance hit.
e394bef8 248 */
c27f072f
RG
249 if (vp->v_usecount == 0 && vp->v_type == VLNK) {
250/* printf("Flushing symlink entry\n");*/
251 vgone(vp);
252 }
15637ed4
RG
253 return (error);
254}
255
256/*
257 * Reclaim an inode so that it can be used for other purposes.
258 */
4c45483e 259int
15637ed4
RG
260isofs_reclaim(vp)
261 register struct vnode *vp;
262{
263 register struct iso_node *ip = VTOI(vp);
264 int i;
265
266 if (prtactive && vp->v_usecount != 0)
267 vprint("isofs_reclaim: pushing active", vp);
268 /*
269 * Remove the inode from its hash chain.
270 */
271 remque(ip);
272 ip->i_forw = ip;
273 ip->i_back = ip;
274 /*
275 * Purge old data structures associated with the inode.
276 */
277 cache_purge(vp);
278 if (ip->i_devvp) {
279 vrele(ip->i_devvp);
280 ip->i_devvp = 0;
281 }
282 ip->i_flag = 0;
283 return (0);
284}
285
286/*
287 * Lock an inode. If its already locked, set the WANT bit and sleep.
288 */
4c45483e 289void
15637ed4
RG
290iso_ilock(ip)
291 register struct iso_node *ip;
292{
293
294 while (ip->i_flag & ILOCKED) {
295 ip->i_flag |= IWANT;
296 if (ip->i_spare0 == curproc->p_pid)
297 panic("locking against myself");
298 ip->i_spare1 = curproc->p_pid;
4630f671 299 (void) tsleep((caddr_t)ip, PINOD, "isoilck", 0);
15637ed4
RG
300 }
301 ip->i_spare1 = 0;
302 ip->i_spare0 = curproc->p_pid;
303 ip->i_flag |= ILOCKED;
304}
305
306/*
307 * Unlock an inode. If WANT bit is on, wakeup.
308 */
4c45483e 309void
15637ed4
RG
310iso_iunlock(ip)
311 register struct iso_node *ip;
312{
313
314 if ((ip->i_flag & ILOCKED) == 0)
315 vprint("iso_iunlock: unlocked inode", ITOV(ip));
316 ip->i_spare0 = 0;
317 ip->i_flag &= ~ILOCKED;
318 if (ip->i_flag&IWANT) {
319 ip->i_flag &= ~IWANT;
320 wakeup((caddr_t)ip);
321 }
322}