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