]> git.saurik.com Git - apple/xnu.git/blame - bsd/ufs/ffs/ffs_vnops.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / ufs / ffs / ffs_vnops.c
CommitLineData
1c79356b 1/*
55e303ae 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
56 */
57
58#include <rev_endian_fs.h>
59#include <sys/param.h>
60#include <sys/systm.h>
61#include <sys/resourcevar.h>
62#include <sys/kernel.h>
63#include <sys/file.h>
64#include <sys/stat.h>
65#include <sys/buf.h>
66#include <sys/proc.h>
67#include <sys/conf.h>
68#include <sys/mount.h>
69#include <sys/vnode.h>
70#include <sys/malloc.h>
71#include <sys/ubc.h>
9bccf70c 72#include <sys/quota.h>
1c79356b
A
73
74#include <sys/vm.h>
75#include <vfs/vfs_support.h>
76
77#include <miscfs/specfs/specdev.h>
78#include <miscfs/fifofs/fifo.h>
79
80#include <ufs/ufs/lockf.h>
81#include <ufs/ufs/quota.h>
82#include <ufs/ufs/inode.h>
83#include <ufs/ufs/dir.h>
84#include <ufs/ufs/ufsmount.h>
85#include <ufs/ufs/ufs_extern.h>
86
87#include <ufs/ffs/fs.h>
88#include <ufs/ffs/ffs_extern.h>
89#if REV_ENDIAN_FS
90#include <ufs/ufs/ufs_byte_order.h>
91#include <architecture/byte_order.h>
92#endif /* REV_ENDIAN_FS */
93
94#define VOPFUNC int (*)(void *)
95
96/* Global vfs data structures for ufs. */
97int (**ffs_vnodeop_p)(void *);
98struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
99 { &vop_default_desc, (VOPFUNC)vn_default_error },
100 { &vop_lookup_desc, (VOPFUNC)ufs_lookup }, /* lookup */
101 { &vop_create_desc, (VOPFUNC)ufs_create }, /* create */
102 { &vop_whiteout_desc, (VOPFUNC)ufs_whiteout }, /* whiteout */
103 { &vop_mknod_desc, (VOPFUNC)ufs_mknod }, /* mknod */
104 { &vop_open_desc, (VOPFUNC)ufs_open }, /* open */
105 { &vop_close_desc, (VOPFUNC)ufs_close }, /* close */
106 { &vop_access_desc, (VOPFUNC)ufs_access }, /* access */
107 { &vop_getattr_desc, (VOPFUNC)ufs_getattr }, /* getattr */
108 { &vop_setattr_desc, (VOPFUNC)ufs_setattr }, /* setattr */
109 { &vop_read_desc, (VOPFUNC)ffs_read }, /* read */
110 { &vop_write_desc, (VOPFUNC)ffs_write }, /* write */
111 { &vop_lease_desc, (VOPFUNC)ufs_lease_check }, /* lease */
112 { &vop_ioctl_desc, (VOPFUNC)ufs_ioctl }, /* ioctl */
113 { &vop_select_desc, (VOPFUNC)ufs_select }, /* select */
114 { &vop_revoke_desc, (VOPFUNC)ufs_revoke }, /* revoke */
115 { &vop_mmap_desc, (VOPFUNC)ufs_mmap }, /* mmap */
116 { &vop_fsync_desc, (VOPFUNC)ffs_fsync }, /* fsync */
117 { &vop_seek_desc, (VOPFUNC)ufs_seek }, /* seek */
118 { &vop_remove_desc, (VOPFUNC)ufs_remove }, /* remove */
119 { &vop_link_desc, (VOPFUNC)ufs_link }, /* link */
120 { &vop_rename_desc, (VOPFUNC)ufs_rename }, /* rename */
121 { &vop_mkdir_desc, (VOPFUNC)ufs_mkdir }, /* mkdir */
122 { &vop_rmdir_desc, (VOPFUNC)ufs_rmdir }, /* rmdir */
123 { &vop_symlink_desc, (VOPFUNC)ufs_symlink }, /* symlink */
124 { &vop_readdir_desc, (VOPFUNC)ufs_readdir }, /* readdir */
125 { &vop_readlink_desc, (VOPFUNC)ufs_readlink }, /* readlink */
55e303ae 126 { &vop_abortop_desc, (VOPFUNC)nop_abortop }, /* abortop */
1c79356b
A
127 { &vop_inactive_desc, (VOPFUNC)ufs_inactive }, /* inactive */
128 { &vop_reclaim_desc, (VOPFUNC)ffs_reclaim }, /* reclaim */
129 { &vop_lock_desc, (VOPFUNC)ufs_lock }, /* lock */
130 { &vop_unlock_desc, (VOPFUNC)ufs_unlock }, /* unlock */
131 { &vop_bmap_desc, (VOPFUNC)ufs_bmap }, /* bmap */
132 { &vop_strategy_desc, (VOPFUNC)ufs_strategy }, /* strategy */
133 { &vop_print_desc, (VOPFUNC)ufs_print }, /* print */
134 { &vop_islocked_desc, (VOPFUNC)ufs_islocked }, /* islocked */
135 { &vop_pathconf_desc, (VOPFUNC)ufs_pathconf }, /* pathconf */
136 { &vop_advlock_desc, (VOPFUNC)ufs_advlock }, /* advlock */
137 { &vop_blkatoff_desc, (VOPFUNC)ffs_blkatoff }, /* blkatoff */
138 { &vop_valloc_desc, (VOPFUNC)ffs_valloc }, /* valloc */
139 { &vop_reallocblks_desc, (VOPFUNC)ffs_reallocblks }, /* reallocblks */
140 { &vop_vfree_desc, (VOPFUNC)ffs_vfree }, /* vfree */
141 { &vop_truncate_desc, (VOPFUNC)ffs_truncate }, /* truncate */
142 { &vop_update_desc, (VOPFUNC)ffs_update }, /* update */
143 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
144 { &vop_pagein_desc, (VOPFUNC)ffs_pagein }, /* Pagein */
145 { &vop_pageout_desc, (VOPFUNC)ffs_pageout }, /* Pageout */
146 { &vop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copy File */
147 { &vop_blktooff_desc, (VOPFUNC)ffs_blktooff }, /* blktooff */
148 { &vop_offtoblk_desc, (VOPFUNC)ffs_offtoblk }, /* offtoblk */
149 { &vop_cmap_desc, (VOPFUNC)ufs_cmap }, /* cmap */
55e303ae
A
150 { &vop_getattrlist_desc, (VOPFUNC)ufs_getattrlist }, /* getattrlist */
151 { &vop_setattrlist_desc, (VOPFUNC)ufs_setattrlist }, /* setattrlist */
152 { &vop_kqfilt_add_desc, (VOPFUNC)ufs_kqfilt_add }, /* kqfilt_add */
1c79356b
A
153 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
154};
155struct vnodeopv_desc ffs_vnodeop_opv_desc =
156 { &ffs_vnodeop_p, ffs_vnodeop_entries };
157
158int (**ffs_specop_p)(void *);
159struct vnodeopv_entry_desc ffs_specop_entries[] = {
160 { &vop_default_desc, (VOPFUNC)vn_default_error },
161 { &vop_lookup_desc, (VOPFUNC)spec_lookup }, /* lookup */
162 { &vop_create_desc, (VOPFUNC)spec_create }, /* create */
163 { &vop_mknod_desc, (VOPFUNC)spec_mknod }, /* mknod */
164 { &vop_open_desc, (VOPFUNC)spec_open }, /* open */
165 { &vop_close_desc, (VOPFUNC)ufsspec_close }, /* close */
166 { &vop_access_desc, (VOPFUNC)ufs_access }, /* access */
167 { &vop_getattr_desc, (VOPFUNC)ufs_getattr }, /* getattr */
168 { &vop_setattr_desc, (VOPFUNC)ufs_setattr }, /* setattr */
169 { &vop_read_desc, (VOPFUNC)ufsspec_read }, /* read */
170 { &vop_write_desc, (VOPFUNC)ufsspec_write }, /* write */
171 { &vop_lease_desc, (VOPFUNC)spec_lease_check }, /* lease */
172 { &vop_ioctl_desc, (VOPFUNC)spec_ioctl }, /* ioctl */
173 { &vop_select_desc, (VOPFUNC)spec_select }, /* select */
174 { &vop_revoke_desc, (VOPFUNC)spec_revoke }, /* revoke */
175 { &vop_mmap_desc, (VOPFUNC)spec_mmap }, /* mmap */
176 { &vop_fsync_desc, (VOPFUNC)ffs_fsync }, /* fsync */
177 { &vop_seek_desc, (VOPFUNC)spec_seek }, /* seek */
178 { &vop_remove_desc, (VOPFUNC)spec_remove }, /* remove */
179 { &vop_link_desc, (VOPFUNC)spec_link }, /* link */
180 { &vop_rename_desc, (VOPFUNC)spec_rename }, /* rename */
181 { &vop_mkdir_desc, (VOPFUNC)spec_mkdir }, /* mkdir */
182 { &vop_rmdir_desc, (VOPFUNC)spec_rmdir }, /* rmdir */
183 { &vop_symlink_desc, (VOPFUNC)spec_symlink }, /* symlink */
184 { &vop_readdir_desc, (VOPFUNC)spec_readdir }, /* readdir */
185 { &vop_readlink_desc, (VOPFUNC)spec_readlink }, /* readlink */
186 { &vop_abortop_desc, (VOPFUNC)spec_abortop }, /* abortop */
187 { &vop_inactive_desc, (VOPFUNC)ufs_inactive }, /* inactive */
188 { &vop_reclaim_desc, (VOPFUNC)ffs_reclaim }, /* reclaim */
189 { &vop_lock_desc, (VOPFUNC)ufs_lock }, /* lock */
190 { &vop_unlock_desc, (VOPFUNC)ufs_unlock }, /* unlock */
191 { &vop_bmap_desc, (VOPFUNC)spec_bmap }, /* bmap */
192 { &vop_strategy_desc, (VOPFUNC)spec_strategy }, /* strategy */
193 { &vop_print_desc, (VOPFUNC)ufs_print }, /* print */
194 { &vop_islocked_desc, (VOPFUNC)ufs_islocked }, /* islocked */
195 { &vop_pathconf_desc, (VOPFUNC)spec_pathconf }, /* pathconf */
196 { &vop_advlock_desc, (VOPFUNC)spec_advlock }, /* advlock */
197 { &vop_blkatoff_desc, (VOPFUNC)spec_blkatoff }, /* blkatoff */
198 { &vop_valloc_desc, (VOPFUNC)spec_valloc }, /* valloc */
199 { &vop_reallocblks_desc, (VOPFUNC)spec_reallocblks }, /* reallocblks */
200 { &vop_vfree_desc, (VOPFUNC)ffs_vfree }, /* vfree */
201 { &vop_truncate_desc, (VOPFUNC)spec_truncate }, /* truncate */
202 { &vop_update_desc, (VOPFUNC)ffs_update }, /* update */
203 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
204 { &vop_devblocksize_desc, (VOPFUNC)spec_devblocksize }, /* devblocksize */
205 { &vop_pagein_desc, (VOPFUNC)ffs_pagein }, /* Pagein */
206 { &vop_pageout_desc, (VOPFUNC)ffs_pageout }, /* Pageout */
207 { &vop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copy File */
208 { &vop_blktooff_desc, (VOPFUNC)ffs_blktooff }, /* blktooff */
209 { &vop_offtoblk_desc, (VOPFUNC)ffs_offtoblk }, /* offtoblk */
210 { &vop_cmap_desc, (VOPFUNC)spec_cmap }, /* cmap */
211 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
212};
213struct vnodeopv_desc ffs_specop_opv_desc =
214 { &ffs_specop_p, ffs_specop_entries };
215
216#if FIFO
217int (**ffs_fifoop_p)(void *);
218struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
219 { &vop_default_desc, (VOPFUNC)vn_default_error },
220 { &vop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */
221 { &vop_create_desc, (VOPFUNC)fifo_create }, /* create */
222 { &vop_mknod_desc, (VOPFUNC)fifo_mknod }, /* mknod */
223 { &vop_open_desc, (VOPFUNC)fifo_open }, /* open */
224 { &vop_close_desc, (VOPFUNC)ufsfifo_close }, /* close */
225 { &vop_access_desc, (VOPFUNC)ufs_access }, /* access */
226 { &vop_getattr_desc, (VOPFUNC)ufs_getattr }, /* getattr */
227 { &vop_setattr_desc, (VOPFUNC)ufs_setattr }, /* setattr */
228 { &vop_read_desc, (VOPFUNC)ufsfifo_read }, /* read */
229 { &vop_write_desc, (VOPFUNC)ufsfifo_write }, /* write */
230 { &vop_lease_desc, (VOPFUNC)fifo_lease_check }, /* lease */
231 { &vop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */
232 { &vop_select_desc, (VOPFUNC)fifo_select }, /* select */
233 { &vop_revoke_desc, (VOPFUNC)fifo_revoke }, /* revoke */
234 { &vop_mmap_desc, (VOPFUNC)fifo_mmap }, /* mmap */
235 { &vop_fsync_desc, (VOPFUNC)ffs_fsync }, /* fsync */
236 { &vop_seek_desc, (VOPFUNC)fifo_seek }, /* seek */
237 { &vop_remove_desc, (VOPFUNC)fifo_remove }, /* remove */
238 { &vop_link_desc, (VOPFUNC)fifo_link }, /* link */
239 { &vop_rename_desc, (VOPFUNC)fifo_rename }, /* rename */
240 { &vop_mkdir_desc, (VOPFUNC)fifo_mkdir }, /* mkdir */
241 { &vop_rmdir_desc, (VOPFUNC)fifo_rmdir }, /* rmdir */
242 { &vop_symlink_desc, (VOPFUNC)fifo_symlink }, /* symlink */
243 { &vop_readdir_desc, (VOPFUNC)fifo_readdir }, /* readdir */
244 { &vop_readlink_desc, (VOPFUNC)fifo_readlink }, /* readlink */
245 { &vop_abortop_desc, (VOPFUNC)fifo_abortop }, /* abortop */
246 { &vop_inactive_desc, (VOPFUNC)ufs_inactive }, /* inactive */
247 { &vop_reclaim_desc, (VOPFUNC)ffs_reclaim }, /* reclaim */
248 { &vop_lock_desc, (VOPFUNC)ufs_lock }, /* lock */
249 { &vop_unlock_desc, (VOPFUNC)ufs_unlock }, /* unlock */
250 { &vop_bmap_desc, (VOPFUNC)fifo_bmap }, /* bmap */
251 { &vop_strategy_desc, (VOPFUNC)fifo_strategy }, /* strategy */
252 { &vop_print_desc, (VOPFUNC)ufs_print }, /* print */
253 { &vop_islocked_desc, (VOPFUNC)ufs_islocked }, /* islocked */
254 { &vop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */
255 { &vop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */
256 { &vop_blkatoff_desc, (VOPFUNC)fifo_blkatoff }, /* blkatoff */
257 { &vop_valloc_desc, (VOPFUNC)fifo_valloc }, /* valloc */
258 { &vop_reallocblks_desc, (VOPFUNC)fifo_reallocblks }, /* reallocblks */
259 { &vop_vfree_desc, (VOPFUNC)ffs_vfree }, /* vfree */
260 { &vop_truncate_desc, (VOPFUNC)fifo_truncate }, /* truncate */
261 { &vop_update_desc, (VOPFUNC)ffs_update }, /* update */
262 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
263 { &vop_pagein_desc, (VOPFUNC)ffs_pagein }, /* Pagein */
264 { &vop_pageout_desc, (VOPFUNC)ffs_pageout }, /* Pageout */
265 { &vop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copy File */
266 { &vop_blktooff_desc, (VOPFUNC)ffs_blktooff }, /* blktooff */
267 { &vop_offtoblk_desc, (VOPFUNC)ffs_offtoblk }, /* offtoblk */
268 { &vop_cmap_desc, (VOPFUNC)ufs_cmap }, /* cmap */
55e303ae 269 { &vop_kqfilt_add_desc, (VOPFUNC)ufsfifo_kqfilt_add }, /* kqfilt_add */
1c79356b
A
270 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
271};
272struct vnodeopv_desc ffs_fifoop_opv_desc =
273 { &ffs_fifoop_p, ffs_fifoop_entries };
274#endif /* FIFO */
275
276/*
277 * Enabling cluster read/write operations.
278 */
279int doclusterread = 0;
280int doclusterwrite = 0;
281
282#include <ufs/ufs/ufs_readwrite.c>
283
284/*
285 * Synch an open file.
286 */
287/* ARGSUSED */
288int
289ffs_fsync(ap)
290 struct vop_fsync_args /* {
291 struct vnode *a_vp;
292 struct ucred *a_cred;
293 int a_waitfor;
294 struct proc *a_p;
295 } */ *ap;
296{
297 register struct vnode *vp = ap->a_vp;
298 register struct buf *bp;
299 struct timeval tv;
300 struct buf *nbp;
301 int s;
302 struct inode *ip = VTOI(vp);
9bccf70c 303 int retry = 0;
1c79356b
A
304
305 /*
306 * Write out any clusters.
307 */
308 cluster_push(vp);
309
1c79356b
A
310 /*
311 * Flush all dirty buffers associated with a vnode.
312 */
313loop:
314 s = splbio();
315 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
316 nbp = bp->b_vnbufs.le_next;
317 if ((bp->b_flags & B_BUSY))
318 continue;
319 if ((bp->b_flags & B_DELWRI) == 0)
320 panic("ffs_fsync: not dirty");
321 bremfree(bp);
322 bp->b_flags |= B_BUSY;
323 splx(s);
324 /*
325 * Wait for I/O associated with indirect blocks to complete,
326 * since there is no way to quickly wait for them below.
327 */
328 if (bp->b_vp == vp || ap->a_waitfor == MNT_NOWAIT)
329 (void) bawrite(bp);
330 else
331 (void) bwrite(bp);
332 goto loop;
333 }
1c79356b
A
334
335 if (ap->a_waitfor == MNT_WAIT) {
336 while (vp->v_numoutput) {
337 vp->v_flag |= VBWAIT;
338 tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "ffs_fsync", 0);
339 }
340
9bccf70c
A
341 if (vp->v_dirtyblkhd.lh_first) {
342 /* still have some dirty buffers */
343 if (retry++ > 10) {
344 vprint("ffs_fsync: dirty", vp);
345 splx(s);
346 /*
347 * Looks like the requests are not
348 * getting queued to the driver.
349 * Retrying here causes a cpu bound loop.
350 * Yield to the other threads and hope
351 * for the best.
352 */
353 (void)tsleep((caddr_t)&vp->v_numoutput,
354 PRIBIO + 1, "ffs_fsync", hz/10);
355 retry = 0;
356 } else {
357 splx(s);
358 }
359 /* try again */
1c79356b
A
360 goto loop;
361 }
362 }
363 splx(s);
364 tv = time;
365 return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
366}
367
368/*
369 * Reclaim an inode so that it can be used for other purposes.
370 */
371int
372ffs_reclaim(ap)
373 struct vop_reclaim_args /* {
374 struct vnode *a_vp;
375 struct proc *a_p;
376 } */ *ap;
377{
378 register struct vnode *vp = ap->a_vp;
379 int error;
380
381 if (error = ufs_reclaim(vp, ap->a_p))
382 return (error);
383 FREE_ZONE(vp->v_data, sizeof (struct inode),
384 VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ?
385 M_MFSNODE : M_FFSNODE);
386 vp->v_data = NULL;
387 return (0);
388}
389
390/* Blktooff converts a logical block number to a file offset */
391int
392ffs_blktooff(ap)
393 struct vop_blktooff_args /* {
394 struct vnode *a_vp;
395 daddr_t a_lblkno;
396 off_t *a_offset;
397 } */ *ap;
398{
399 register struct inode *ip;
400 register FS *fs;
401 ufs_daddr_t bn;
402
403
404 if (ap->a_vp == NULL)
405 return (EINVAL);
406
407 ip = VTOI(ap->a_vp);
408 fs = ip->I_FS;
409 bn = ap->a_lblkno;
410
411 if ((long)bn < 0) {
412 panic("-ve blkno in ffs_blktooff");
413 bn = -(long)bn;
414 }
415
416 *ap->a_offset = (off_t)lblktosize(fs, bn);
417 return (0);
418}
419
420/* Blktooff converts a logical block number to a file offset */
421int
422ffs_offtoblk(ap)
423 struct vop_offtoblk_args /* {
424 struct vnode *a_vp;
425 off_t a_offset;
426 daddr_t *a_lblkno;
427 } */ *ap;
428{
429 register struct inode *ip;
430 register FS *fs;
431
432 if (ap->a_vp == NULL)
433 return (EINVAL);
434
435 ip = VTOI(ap->a_vp);
436 fs = ip->I_FS;
437
438 *ap->a_lblkno = (daddr_t)lblkno(fs, ap->a_offset);
439 return (0);
440}