Add quirk for SONY SMO drive. This (pre SCSI-2) drive returns a mystic
[dragonfly.git] / sys / vfs / hammer / hammer_vnops.c
CommitLineData
427e5fc6
MD
1/*
2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
66325755 34 * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.2 2007/11/07 00:43:24 dillon Exp $
427e5fc6
MD
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/fcntl.h>
41#include <sys/namecache.h>
42#include <sys/vnode.h>
43#include <sys/lockf.h>
44#include <sys/event.h>
45#include <sys/stat.h>
46#include "hammer.h"
47
48/*
49 * USERFS VNOPS
50 */
51/*static int hammer_vop_vnoperate(struct vop_generic_args *);*/
66325755
MD
52static int hammer_vop_fsync(struct vop_fsync_args *);
53static int hammer_vop_read(struct vop_read_args *);
54static int hammer_vop_write(struct vop_write_args *);
55static int hammer_vop_access(struct vop_access_args *);
56static int hammer_vop_advlock(struct vop_advlock_args *);
57static int hammer_vop_close(struct vop_close_args *);
58static int hammer_vop_ncreate(struct vop_ncreate_args *);
59static int hammer_vop_getattr(struct vop_getattr_args *);
60static int hammer_vop_nresolve(struct vop_nresolve_args *);
61static int hammer_vop_nlookupdotdot(struct vop_nlookupdotdot_args *);
62static int hammer_vop_nlink(struct vop_nlink_args *);
63static int hammer_vop_nmkdir(struct vop_nmkdir_args *);
64static int hammer_vop_nmknod(struct vop_nmknod_args *);
65static int hammer_vop_open(struct vop_open_args *);
66static int hammer_vop_pathconf(struct vop_pathconf_args *);
67static int hammer_vop_print(struct vop_print_args *);
68static int hammer_vop_readdir(struct vop_readdir_args *);
69static int hammer_vop_readlink(struct vop_readlink_args *);
70static int hammer_vop_nremove(struct vop_nremove_args *);
71static int hammer_vop_nrename(struct vop_nrename_args *);
72static int hammer_vop_nrmdir(struct vop_nrmdir_args *);
73static int hammer_vop_setattr(struct vop_setattr_args *);
74static int hammer_vop_strategy(struct vop_strategy_args *);
75static int hammer_vop_nsymlink(struct vop_nsymlink_args *);
76static int hammer_vop_nwhiteout(struct vop_nwhiteout_args *);
427e5fc6
MD
77
78struct vop_ops hammer_vnode_vops = {
79 .vop_default = vop_defaultop,
80 .vop_fsync = hammer_vop_fsync,
81 .vop_read = hammer_vop_read,
82 .vop_write = hammer_vop_write,
83 .vop_access = hammer_vop_access,
84 .vop_advlock = hammer_vop_advlock,
85 .vop_close = hammer_vop_close,
86 .vop_ncreate = hammer_vop_ncreate,
87 .vop_getattr = hammer_vop_getattr,
88 .vop_inactive = hammer_vop_inactive,
89 .vop_reclaim = hammer_vop_reclaim,
90 .vop_nresolve = hammer_vop_nresolve,
91 .vop_nlookupdotdot = hammer_vop_nlookupdotdot,
92 .vop_nlink = hammer_vop_nlink,
93 .vop_nmkdir = hammer_vop_nmkdir,
94 .vop_nmknod = hammer_vop_nmknod,
95 .vop_open = hammer_vop_open,
96 .vop_pathconf = hammer_vop_pathconf,
97 .vop_print = hammer_vop_print,
98 .vop_readdir = hammer_vop_readdir,
99 .vop_readlink = hammer_vop_readlink,
100 .vop_nremove = hammer_vop_nremove,
101 .vop_nrename = hammer_vop_nrename,
102 .vop_nrmdir = hammer_vop_nrmdir,
103 .vop_setattr = hammer_vop_setattr,
104 .vop_strategy = hammer_vop_strategy,
105 .vop_nsymlink = hammer_vop_nsymlink,
106 .vop_nwhiteout = hammer_vop_nwhiteout
107};
108
109#if 0
110static
111int
112hammer_vop_vnoperate(struct vop_generic_args *)
113{
114 return (VOCALL(&hammer_vnode_vops, ap));
115}
116#endif
117
66325755
MD
118/*
119 * hammer_vop_fsync { vp, waitfor }
120 */
427e5fc6
MD
121static
122int
66325755 123hammer_vop_fsync(struct vop_fsync_args *ap)
427e5fc6
MD
124{
125 return EOPNOTSUPP;
126}
127
66325755
MD
128/*
129 * hammer_vop_read { vp, uio, ioflag, cred }
130 */
427e5fc6
MD
131static
132int
66325755 133hammer_vop_read(struct vop_read_args *ap)
427e5fc6 134{
66325755
MD
135 struct hammer_transaction trans;
136 struct hammer_inode *ip;
137 off_t offset;
138 struct buf *bp;
139 struct uio *uio;
140 int error;
141 int n;
142
143 if (ap->a_vp->v_type != VREG)
144 return (EINVAL);
145 ip = VTOI(ap->a_vp);
146 error = 0;
147
148 hammer_start_transaction(ip->hmp, &trans);
149
150 /*
151 * Access the data in HAMMER_BUFSIZE blocks via the buffer cache.
152 */
153 uio = ap->a_uio;
154 while (uio->uio_resid > 0 && uio->uio_offset < ip->ino_rec.ino_size) {
155 offset = uio->uio_offset & HAMMER_BUFMASK;
156 error = bread(ap->a_vp, uio->uio_offset - offset,
157 HAMMER_BUFSIZE, &bp);
158 if (error) {
159 brelse(bp);
160 break;
161 }
162 n = HAMMER_BUFSIZE - offset;
163 if (n > uio->uio_resid)
164 n = uio->uio_resid;
165 if (n > ip->ino_rec.ino_size - uio->uio_offset)
166 n = (int)(ip->ino_rec.ino_size - uio->uio_offset);
167 error = uiomove((char *)bp->b_data + offset, n, uio);
168 if (error) {
169 brelse(bp);
170 break;
171 }
172 ip->ino_rec.ino_atime = trans.tid;
173 hammer_modify_inode(&trans, ip, HAMMER_INODE_ITIMES);
174 bqrelse(bp);
175 }
176 hammer_commit_transaction(&trans);
177 return (error);
427e5fc6
MD
178}
179
66325755
MD
180/*
181 * hammer_vop_write { vp, uio, ioflag, cred }
182 */
427e5fc6
MD
183static
184int
66325755 185hammer_vop_write(struct vop_write_args *ap)
427e5fc6 186{
66325755
MD
187 struct hammer_transaction trans;
188 struct hammer_inode *ip;
189 struct uio *uio;
190 off_t offset;
191 struct buf *bp;
192 int error;
193 int n;
194
195 if (ap->a_vp->v_type != VREG)
196 return (EINVAL);
197 ip = VTOI(ap->a_vp);
198 error = 0;
199
200 /*
201 * Create a transaction to cover the operations we perform.
202 */
203 hammer_start_transaction(ip->hmp, &trans);
204 uio = ap->a_uio;
205
206 /*
207 * Check append mode
208 */
209 if (ap->a_ioflag & IO_APPEND)
210 uio->uio_offset = ip->ino_rec.ino_size;
211
212 /*
213 * Check for illegal write offsets. Valid range is 0...2^63-1
214 */
215 if (uio->uio_offset < 0 || uio->uio_offset + uio->uio_resid <= 0)
216 return (EFBIG);
217
218 /*
219 * Access the data in HAMMER_BUFSIZE blocks via the buffer cache.
220 */
221 while (uio->uio_resid > 0) {
222 offset = uio->uio_offset & HAMMER_BUFMASK;
223 if (offset == 0 && uio->uio_resid >= HAMMER_BUFSIZE) {
224 bp = getblk(ap->a_vp, uio->uio_offset, HAMMER_BUFSIZE,
225 0, 0);
226 } else if (offset == 0 && uio->uio_offset >= ip->ino_rec.ino_size) {
227 bp = getblk(ap->a_vp, uio->uio_offset, HAMMER_BUFSIZE,
228 0, 0);
229 vfs_bio_clrbuf(bp);
230 } else {
231 error = bread(ap->a_vp, uio->uio_offset - offset,
232 HAMMER_BUFSIZE, &bp);
233 if (error) {
234 brelse(bp);
235 break;
236 }
237 }
238 n = HAMMER_BUFSIZE - offset;
239 if (n > uio->uio_resid)
240 n = uio->uio_resid;
241 error = uiomove((char *)bp->b_data + offset, n, uio);
242 if (error) {
243 brelse(bp);
244 break;
245 }
246 if (ip->ino_rec.ino_size < uio->uio_offset) {
247 ip->ino_rec.ino_size = uio->uio_offset;
248 ip->ino_rec.ino_mtime = trans.tid;
249 hammer_modify_inode(&trans, ip,
250 HAMMER_INODE_RDIRTY | HAMMER_INODE_ITIMES);
251 }
252 if (ap->a_ioflag & IO_SYNC) {
253 bwrite(bp);
254 } else if (ap->a_ioflag & IO_DIRECT) {
255 /* XXX B_CLUSTEROK SUPPORT */
256 bawrite(bp);
257 } else {
258 /* XXX B_CLUSTEROK SUPPORT */
259 bdwrite(bp);
260 }
261 }
262 if (error)
263 hammer_abort_transaction(&trans);
264 else
265 hammer_commit_transaction(&trans);
266 return (error);
427e5fc6
MD
267}
268
66325755
MD
269/*
270 * hammer_vop_access { vp, mode, cred }
271 */
427e5fc6
MD
272static
273int
66325755 274hammer_vop_access(struct vop_access_args *ap)
427e5fc6 275{
66325755
MD
276 struct hammer_inode *ip = VTOI(ap->a_vp);
277 uid_t uid;
278 gid_t gid;
279 int error;
280
281 uid = hammer_to_unix_xid(&ip->ino_data.uid);
282 gid = hammer_to_unix_xid(&ip->ino_data.gid);
283
284 error = vop_helper_access(ap, uid, gid, ip->ino_data.mode,
285 ip->ino_data.uflags);
286 return (error);
427e5fc6
MD
287}
288
66325755
MD
289/*
290 * hammer_vop_advlock { vp, id, op, fl, flags }
291 */
427e5fc6
MD
292static
293int
66325755 294hammer_vop_advlock(struct vop_advlock_args *ap)
427e5fc6 295{
66325755
MD
296 struct hammer_inode *ip = VTOI(ap->a_vp);
297
298 return (lf_advlock(ap, &ip->advlock, ip->ino_rec.ino_size));
427e5fc6
MD
299}
300
66325755
MD
301/*
302 * hammer_vop_close { vp, fflag }
303 */
427e5fc6
MD
304static
305int
66325755 306hammer_vop_close(struct vop_close_args *ap)
427e5fc6
MD
307{
308 return EOPNOTSUPP;
309}
310
66325755
MD
311/*
312 * hammer_vop_ncreate { nch, dvp, vpp, cred, vap }
313 *
314 * The operating system has already ensured that the directory entry
315 * does not exist and done all appropriate namespace locking.
316 */
427e5fc6
MD
317static
318int
66325755 319hammer_vop_ncreate(struct vop_ncreate_args *ap)
427e5fc6 320{
66325755
MD
321 struct hammer_transaction trans;
322 struct hammer_inode *dip;
323 struct hammer_inode *nip;
324 struct nchandle *nch;
325 int error;
326
327 nch = ap->a_nch;
328 dip = VTOI(ap->a_dvp);
329
330 /*
331 * Create a transaction to cover the operations we perform.
332 */
333 hammer_start_transaction(dip->hmp, &trans);
334
335 /*
336 * Create a new filesystem object of the requested type. The
337 * returned inode will be locked. We cannot hold the new
338 * inode locked while doing other manipulations.
339 */
340 error = hammer_alloc_inode(&trans, ap->a_vap, ap->a_cred, &nip);
341 if (error) {
342 hammer_abort_transaction(&trans);
343 *ap->a_vpp = NULL;
344 return (error);
345 }
346 hammer_lock_to_ref(&nip->lock);
347
348 /*
349 * Add the new filesystem object to the directory. This will also
350 * bump the inode's link count.
351 */
352 error = hammer_add_directory(&trans, dip, nch->ncp, nip);
353
354 /*
355 * Finish up.
356 */
357 if (error) {
358 hammer_put_inode_ref(nip);
359 hammer_abort_transaction(&trans);
360 *ap->a_vpp = NULL;
361 } else {
362 hammer_commit_transaction(&trans);
363 error = hammer_get_vnode(nip, LK_EXCLUSIVE, ap->a_vpp);
364 hammer_put_inode_ref(nip);
365 }
366 return (error);
427e5fc6
MD
367}
368
66325755
MD
369/*
370 * hammer_vop_getattr { vp, vap }
371 */
427e5fc6
MD
372static
373int
66325755 374hammer_vop_getattr(struct vop_getattr_args *ap)
427e5fc6 375{
66325755
MD
376 struct hammer_inode *ip = VTOI(ap->a_vp);
377 struct vattr *vap = ap->a_vap;
378
379#if 0
380 if (cache_check_fsmid_vp(ap->a_vp, &ip->fsmid) &&
381 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0 &&
382 ip->obj_asof == 0
383 ) {
384 /* LAZYMOD XXX */
385 }
386 hammer_itimes(ap->a_vp);
387#endif
388
389 vap->va_fsid = ip->hmp->fsid_udev;
390 vap->va_fileid = ip->ino_rec.base.base.obj_id;
391 vap->va_mode = ip->ino_data.mode;
392 vap->va_nlink = ip->ino_rec.ino_nlinks;
393 vap->va_uid = hammer_to_unix_xid(&ip->ino_data.uid);
394 vap->va_gid = hammer_to_unix_xid(&ip->ino_data.gid);
395 vap->va_rmajor = 0;
396 vap->va_rminor = 0;
397 vap->va_size = ip->ino_rec.ino_size;
398 hammer_to_timespec(ip->ino_rec.ino_atime, &vap->va_atime);
399 hammer_to_timespec(ip->ino_rec.ino_mtime, &vap->va_mtime);
400 hammer_to_timespec(ip->ino_data.ctime, &vap->va_ctime);
401 vap->va_flags = ip->ino_data.uflags;
402 vap->va_gen = 1; /* hammer inums are unique for all time */
403 vap->va_blocksize = 32768; /* XXX - extract from root volume */
404 vap->va_bytes = ip->ino_rec.ino_size;
405 vap->va_type = hammer_get_vnode_type(ip->ino_rec.base.base.obj_type);
406 vap->va_filerev = 0; /* XXX */
407 /* mtime uniquely identifies any adjustments made to the file */
408 vap->va_fsmid = ip->ino_rec.ino_mtime;
409 vap->va_uid_uuid = ip->ino_data.uid;
410 vap->va_gid_uuid = ip->ino_data.gid;
411 vap->va_fsid_uuid = ip->hmp->fsid;
412 vap->va_vaflags = VA_UID_UUID_VALID | VA_GID_UUID_VALID |
413 VA_FSID_UUID_VALID;
414 return(0);
427e5fc6
MD
415}
416
66325755
MD
417/*
418 * hammer_vop_nresolve { nch, dvp, cred }
419 *
420 * Locate the requested directory entry.
421 */
427e5fc6
MD
422static
423int
66325755 424hammer_vop_nresolve(struct vop_nresolve_args *ap)
427e5fc6 425{
66325755
MD
426 struct hammer_base_elm key;
427 struct namecache *ncp;
428 struct hammer_inode *dip;
429 struct hammer_btree_info info;
430 struct vnode *vp;
431 int64_t namekey;
432 int error;
433 const int flags = HAMMER_BTREE_GET_RECORD | HAMMER_BTREE_GET_DATA;
434
435 dip = VTOI(ap->a_dvp);
436 ncp = ap->a_nch->ncp;
437 namekey = hammer_directory_namekey(ncp->nc_name, ncp->nc_nlen);
438
439 hammer_btree_info_init(&info, dip->hmp->rootcl);
440 key.obj_id = dip->obj_id;
441 key.key = namekey;
442 key.create_tid = dip->obj_asof;
443 key.delete_tid = 0;
444 key.rec_type = HAMMER_RECTYPE_DIRENTRY;
445 key.obj_type = 0;
446
447 /*
448 * Issue a lookup on the namekey. The entry should not be found
449 * since the low bits of the key are 0. This positions our cursor
450 * properly for the iteration.
451 */
452 error = hammer_btree_lookup(&info, &key, 0);
453 if (error != ENOENT) {
454 if (error == 0)
455 error = EIO;
456 goto done;
457 }
458
459 /*
460 * Iterate through the keys as long as the upper 32 bits are
461 * the same.
462 */
463 while ((error = hammer_btree_iterate(&info.cursor, &key)) == 0) {
464 if ((error = hammer_btree_extract(&info, flags)) != 0)
465 break;
466 if ((namekey ^ info.rec->base.base.key) &
467 (int64_t)0xFFFFFFFF00000000ULL) {
468 error = ENOENT;
469 break;
470 }
471 if (ncp->nc_nlen == info.rec->base.data_len &&
472 bcmp(ncp->nc_name, (void *)info.data, ncp->nc_nlen) == 0) {
473 break;
474 }
475 }
476 if (error == 0) {
477 error = hammer_vfs_vget(dip->hmp->mp, info.rec->entry.obj_id, &vp);
478 if (error == 0) {
479 vn_unlock(vp);
480 cache_setvp(ap->a_nch, vp);
481 vrele(vp);
482 }
483 } else if (error == ENOENT) {
484 cache_setvp(ap->a_nch, NULL);
485 }
486done:
487 hammer_btree_info_done(&info);
488 return (error);
427e5fc6
MD
489}
490
66325755
MD
491/*
492 * hammer_vop_nlookupdotdot { dvp, vpp, cred }
493 *
494 * Locate the parent directory of a directory vnode.
495 *
496 * dvp is referenced but not locked. *vpp must be returned referenced and
497 * locked. A parent_obj_id of 0 does not necessarily indicate that we are
498 * at the root, instead it could indicate that the directory we were in was
499 * removed.
500 */
427e5fc6
MD
501static
502int
66325755 503hammer_vop_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
427e5fc6 504{
66325755
MD
505 struct hammer_inode *dip;
506 u_int64_t parent_obj_id;
507
508 dip = VTOI(ap->a_dvp);
509 if ((parent_obj_id = dip->ino_data.parent_obj_id) == 0) {
510 *ap->a_vpp = NULL;
511 return ENOENT;
512 }
513 return(hammer_vfs_vget(dip->hmp->mp, parent_obj_id, ap->a_vpp));
427e5fc6
MD
514}
515
66325755
MD
516/*
517 * hammer_vop_nlink { nch, dvp, vp, cred }
518 */
427e5fc6
MD
519static
520int
66325755 521hammer_vop_nlink(struct vop_nlink_args *ap)
427e5fc6 522{
66325755
MD
523 struct hammer_transaction trans;
524 struct hammer_inode *dip;
525 struct hammer_inode *ip;
526 struct nchandle *nch;
527 int error;
528
529 nch = ap->a_nch;
530 dip = VTOI(ap->a_dvp);
531 ip = VTOI(ap->a_vp);
532
533 /*
534 * Create a transaction to cover the operations we perform.
535 */
536 hammer_start_transaction(dip->hmp, &trans);
537
538 /*
539 * Add the filesystem object to the directory. Note that neither
540 * dip nor ip are referenced or locked, but their vnodes are
541 * referenced. This function will bump the inode's link count.
542 */
543 error = hammer_add_directory(&trans, dip, nch->ncp, ip);
544
545 /*
546 * Finish up.
547 */
548 if (error) {
549 hammer_abort_transaction(&trans);
550 } else {
551 hammer_commit_transaction(&trans);
552 }
553 return (error);
427e5fc6
MD
554}
555
66325755
MD
556/*
557 * hammer_vop_nmkdir { nch, dvp, vpp, cred, vap }
558 *
559 * The operating system has already ensured that the directory entry
560 * does not exist and done all appropriate namespace locking.
561 */
427e5fc6
MD
562static
563int
66325755 564hammer_vop_nmkdir(struct vop_nmkdir_args *ap)
427e5fc6 565{
66325755
MD
566 struct hammer_transaction trans;
567 struct hammer_inode *dip;
568 struct hammer_inode *nip;
569 struct nchandle *nch;
570 int error;
571
572 nch = ap->a_nch;
573 dip = VTOI(ap->a_dvp);
574
575 /*
576 * Create a transaction to cover the operations we perform.
577 */
578 hammer_start_transaction(dip->hmp, &trans);
579
580 /*
581 * Create a new filesystem object of the requested type. The
582 * returned inode will be locked. We cannot hold the new
583 * inode locked while doing other manipulations.
584 */
585 error = hammer_alloc_inode(&trans, ap->a_vap, ap->a_cred, &nip);
586 if (error) {
587 hammer_abort_transaction(&trans);
588 *ap->a_vpp = NULL;
589 return (error);
590 }
591 hammer_lock_to_ref(&nip->lock);
592
593 /*
594 * Add the new filesystem object to the directory. This will also
595 * bump the inode's link count.
596 */
597 error = hammer_add_directory(&trans, dip, nch->ncp, nip);
598
599 /*
600 * Finish up.
601 */
602 if (error) {
603 hammer_put_inode_ref(nip);
604 hammer_abort_transaction(&trans);
605 *ap->a_vpp = NULL;
606 } else {
607 hammer_commit_transaction(&trans);
608 error = hammer_get_vnode(nip, LK_EXCLUSIVE, ap->a_vpp);
609 hammer_put_inode_ref(nip);
610 }
611 return (error);
427e5fc6
MD
612}
613
66325755
MD
614/*
615 * hammer_vop_nmknod { nch, dvp, vpp, cred, vap }
616 *
617 * The operating system has already ensured that the directory entry
618 * does not exist and done all appropriate namespace locking.
619 */
427e5fc6
MD
620static
621int
66325755 622hammer_vop_nmknod(struct vop_nmknod_args *ap)
427e5fc6 623{
66325755
MD
624 struct hammer_transaction trans;
625 struct hammer_inode *dip;
626 struct hammer_inode *nip;
627 struct nchandle *nch;
628 int error;
629
630 nch = ap->a_nch;
631 dip = VTOI(ap->a_dvp);
632
633 /*
634 * Create a transaction to cover the operations we perform.
635 */
636 hammer_start_transaction(dip->hmp, &trans);
637
638 /*
639 * Create a new filesystem object of the requested type. The
640 * returned inode will be locked. We cannot hold the new
641 * inode locked while doing other manipulations.
642 */
643 error = hammer_alloc_inode(&trans, ap->a_vap, ap->a_cred, &nip);
644 if (error) {
645 hammer_abort_transaction(&trans);
646 *ap->a_vpp = NULL;
647 return (error);
648 }
649 hammer_lock_to_ref(&nip->lock);
650
651 /*
652 * Add the new filesystem object to the directory. This will also
653 * bump the inode's link count.
654 */
655 error = hammer_add_directory(&trans, dip, nch->ncp, nip);
656
657 /*
658 * Finish up.
659 */
660 if (error) {
661 hammer_put_inode_ref(nip);
662 hammer_abort_transaction(&trans);
663 *ap->a_vpp = NULL;
664 } else {
665 hammer_commit_transaction(&trans);
666 error = hammer_get_vnode(nip, LK_EXCLUSIVE, ap->a_vpp);
667 hammer_put_inode_ref(nip);
668 }
669 return (error);
427e5fc6
MD
670}
671
66325755
MD
672/*
673 * hammer_vop_open { vp, mode, cred, fp }
674 */
427e5fc6
MD
675static
676int
66325755 677hammer_vop_open(struct vop_open_args *ap)
427e5fc6
MD
678{
679 return EOPNOTSUPP;
680}
681
66325755
MD
682/*
683 * hammer_vop_pathconf { vp, name, retval }
684 */
427e5fc6
MD
685static
686int
66325755 687hammer_vop_pathconf(struct vop_pathconf_args *ap)
427e5fc6
MD
688{
689 return EOPNOTSUPP;
690}
691
66325755
MD
692/*
693 * hammer_vop_print { vp }
694 */
427e5fc6
MD
695static
696int
66325755 697hammer_vop_print(struct vop_print_args *ap)
427e5fc6
MD
698{
699 return EOPNOTSUPP;
700}
701
66325755
MD
702/*
703 * hammer_vop_readdir { vp, uio, cred, *eofflag }
704 */
427e5fc6
MD
705static
706int
66325755 707hammer_vop_readdir(struct vop_readdir_args *ap)
427e5fc6
MD
708{
709 return EOPNOTSUPP;
710}
711
66325755
MD
712/*
713 * hammer_vop_readlink { vp, uio, cred }
714 */
427e5fc6
MD
715static
716int
66325755 717hammer_vop_readlink(struct vop_readlink_args *ap)
427e5fc6
MD
718{
719 return EOPNOTSUPP;
720}
721
66325755
MD
722/*
723 * hammer_vop_nremove { nch, dvp, cred }
724 */
427e5fc6
MD
725static
726int
66325755 727hammer_vop_nremove(struct vop_nremove_args *ap)
427e5fc6
MD
728{
729 return EOPNOTSUPP;
730}
731
66325755
MD
732/*
733 * hammer_vop_nrename { fnch, tnch, fdvp, tdvp, cred }
734 */
427e5fc6
MD
735static
736int
66325755 737hammer_vop_nrename(struct vop_nrename_args *ap)
427e5fc6
MD
738{
739 return EOPNOTSUPP;
740}
741
66325755
MD
742/*
743 * hammer_vop_nrmdir { nch, dvp, cred }
744 */
427e5fc6
MD
745static
746int
66325755 747hammer_vop_nrmdir(struct vop_nrmdir_args *ap)
427e5fc6
MD
748{
749 return EOPNOTSUPP;
750}
751
66325755
MD
752/*
753 * hammer_vop_setattr { vp, vap, cred }
754 */
427e5fc6
MD
755static
756int
66325755 757hammer_vop_setattr(struct vop_setattr_args *ap)
427e5fc6
MD
758{
759 return EOPNOTSUPP;
760}
761
66325755
MD
762/*
763 * hammer_vop_nsymlink { nch, dvp, vpp, cred, vap, target }
764 */
427e5fc6
MD
765static
766int
66325755 767hammer_vop_nsymlink(struct vop_nsymlink_args *ap)
427e5fc6
MD
768{
769 return EOPNOTSUPP;
770}
771
66325755
MD
772/*
773 * hammer_vop_nwhiteout { nch, dvp, cred, flags }
774 */
427e5fc6
MD
775static
776int
66325755 777hammer_vop_nwhiteout(struct vop_nwhiteout_args *ap)
427e5fc6
MD
778{
779 return EOPNOTSUPP;
780}
781
66325755
MD
782/*
783 * hammer_vop_strategy { vp, bio }
784 */
427e5fc6
MD
785static
786int
66325755 787hammer_vop_strategy(struct vop_strategy_args *ap)
427e5fc6
MD
788{
789 return EOPNOTSUPP;
790}
791
66325755
MD
792#if 0
793 struct hammer_data_record *data;
794 struct hammer_base_elm_t key;
795 hammer_btree_info info;
796 const int flags = HAMMER_BTREE_GET_RECORD | HAMMER_BTREE_GET_DATA;
797 int64_t base_offset;
798 int didinit;
799 int o;
800
801 hammer_btree_info_init(&info, ip->hmp->rootcl);
802 key.obj_id = ip->obj_id;
803 key.create_tid = ip->obj_asof;
804 key.delete_tid = 0;
805 key.rec_type = HAMMER_RECTYPE_DATA;
806 key.obj_type = 0;
807 key.key = uio->uio_offset;
808
809 /*
810 * Iterate through matching records. Note that for data records
811 * the base offset is the key - data_len, NOT the key. This way
812 * we don't have to special case a ranged search.
813 */
814 error = hammer_btree_lookup(&info, &key, 0);
815 if (error && error != ENOENT)
816 goto done;
817 while (uio->uio_resid > 0 && uio->uio_offset < ip->ino_rec.ino_size) {
818 if ((error = hammer_btree_iterate(&info.cursor, &key)) != 0)
819 break;
820 /*
821 * XXX - possible to optimize the extract
822 */
823 if ((error = hammer_btree_extract(&info, flags)) != 0)
824 break;
825 data = &info.rec->data;
826 base_offset = data->base.key - data->base.data_len;
827 if (uio->uio_offset < base_offset) {
828 if (base_offset - uio->uio_offset > HAMMER_BUFSIZE)
829 n = HAMMER_BUFSIZE;
830 else
831 n = (int)(base_offset - uio->uio_offset);
832 error = uiomove(ip->hmp->zbuf, n, uio);
833 } else {
834 o = (int)uio->uio_offset - base_offset;
835 if (o < data->base.data_len) {
836 n = data->base.data_len - o;
837 if (n > uio->uio_resid)
838 n = uio->uio_resid;
839 error = uiomove((char *)info.data + o, n, uio);
840 }
841 }
842 if (error)
843 break;
844 }
845
846 /*
847 * Issue a lookup on the namekey. The entry should not be found
848 * since the low bits of the key are 0. This positions our cursor
849 * properly for the iteration.
850 */
851 if (error != ENOENT) {
852 if (error == 0)
853 error = EIO;
854 goto done;
855 }
856
857 /*
858 * Iterate through the keys as long as the upper 32 bits are
859 * the same.
860 */
861 while ((error = hammer_btree_iterate(&info, &key, flags)) == 0) {
862 if ((namekey ^ info.rec->base.base.key) &
863 (int64_t)0xFFFFFFFF00000000ULL) {
864 error = ENOENT;
865 break;
866 }
867 if (ncp->nc_nlen == info.rec->base.data_len &&
868 bcmp(ncp->nc_name, (void *)info->data, ncp->nc_nlen) == 0) {
869 break;
870 }
871 }
872 if (error == 0) {
873 error = hammer_vfs_vget(dip->hmp->mp, info->rec->entry.obj_id, &vp);
874 if (error == 0) {
875 vn_unlock(vp);
876 cache_setvp(nch, vp);
877 vrele(vp);
878 }
879 } else if (error == ENOENT) {
880 cache_setvp(nch, NULL);
881 }
882done:
883 hammer_btree_info_done(&info);
884 return (error);
885
886
887 return EOPNOTSUPP;
888}
889
890#endif