5838dd6269e55ccc7b6089959a8906fe4ca90b83
[dragonfly.git] / sys / vfs / hammer2 / hammer2_vnops.c
1 /*
2  * Copyright (c) 2011-2015 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7  * by Daniel Flores (GSOC 2013 - mentored by Matthew Dillon, compression) 
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  * 3. Neither the name of The DragonFly Project nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific, prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
27  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 /*
37  * Kernel Filesystem interface
38  *
39  * NOTE! local ipdata pointers must be reloaded on any modifying operation
40  *       to the inode as its underlying chain may have changed.
41  */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/fcntl.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/namei.h>
50 #include <sys/mount.h>
51 #include <sys/vnode.h>
52 #include <sys/mountctl.h>
53 #include <sys/dirent.h>
54 #include <sys/uio.h>
55 #include <sys/objcache.h>
56 #include <sys/event.h>
57 #include <sys/file.h>
58 #include <vfs/fifofs/fifo.h>
59
60 #include "hammer2.h"
61
62 static int hammer2_read_file(hammer2_inode_t *ip, struct uio *uio,
63                                 int seqcount);
64 static int hammer2_write_file(hammer2_inode_t *ip, struct uio *uio,
65                                 int ioflag, int seqcount);
66 static void hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize);
67 static void hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize);
68
69 struct objcache *cache_xops;
70
71 static __inline
72 void
73 hammer2_knote(struct vnode *vp, int flags)
74 {
75         if (flags)
76                 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags);
77 }
78
79 /*
80  * Last reference to a vnode is going away but it is still cached.
81  */
82 static
83 int
84 hammer2_vop_inactive(struct vop_inactive_args *ap)
85 {
86         hammer2_inode_t *ip;
87         struct vnode *vp;
88
89         LOCKSTART;
90         vp = ap->a_vp;
91         ip = VTOI(vp);
92
93         /*
94          * Degenerate case
95          */
96         if (ip == NULL) {
97                 vrecycle(vp);
98                 LOCKSTOP;
99                 return (0);
100         }
101
102         /*
103          * Check for deleted inodes and recycle immediately on the last
104          * release.  Be sure to destroy any left-over buffer cache buffers
105          * so we do not waste time trying to flush them.
106          *
107          * WARNING: nvtruncbuf() can only be safely called without the inode
108          *          lock held due to the way our write thread works.
109          */
110         if (ip->flags & HAMMER2_INODE_ISUNLINKED) {
111                 hammer2_key_t lbase;
112                 int nblksize;
113
114                 /*
115                  * Detect updates to the embedded data which may be
116                  * synchronized by the strategy code.  Simply mark the
117                  * inode modified so it gets picked up by our normal flush.
118                  */
119                 nblksize = hammer2_calc_logical(ip, 0, &lbase, NULL);
120                 nvtruncbuf(vp, 0, nblksize, 0, 0);
121                 vrecycle(vp);
122         }
123         LOCKSTOP;
124         return (0);
125 }
126
127 /*
128  * Reclaim a vnode so that it can be reused; after the inode is
129  * disassociated, the filesystem must manage it alone.
130  */
131 static
132 int
133 hammer2_vop_reclaim(struct vop_reclaim_args *ap)
134 {
135         hammer2_inode_t *ip;
136         hammer2_pfs_t *pmp;
137         struct vnode *vp;
138
139         LOCKSTART;
140         vp = ap->a_vp;
141         ip = VTOI(vp);
142         if (ip == NULL) {
143                 LOCKSTOP;
144                 return(0);
145         }
146         pmp = ip->pmp;
147
148         /*
149          * The final close of a deleted file or directory marks it for
150          * destruction.  The DELETED flag allows the flusher to shortcut
151          * any modified blocks still unflushed (that is, just ignore them).
152          *
153          * HAMMER2 usually does not try to optimize the freemap by returning
154          * deleted blocks to it as it does not usually know how many snapshots
155          * might be referencing portions of the file/dir.
156          */
157         vp->v_data = NULL;
158         ip->vp = NULL;
159
160         /*
161          * NOTE! We do not attempt to flush chains here, flushing is
162          *       really fragile and could also deadlock.
163          */
164         vclrisdirty(vp);
165
166         /*
167          * An unlinked inode may have been relinked to the ihidden directory.
168          * This occurs if the inode was unlinked while open.  Reclamation of
169          * these inodes requires processing we cannot safely do here so add
170          * the inode to the unlinkq in that situation.
171          *
172          * A reclaim can occur at any time so we cannot safely start a
173          * transaction to handle reclamation of unlinked files.  Instead,
174          * the ip is left with a reference and placed on a linked list and
175          * handled later on.
176          */
177         if ((ip->flags & HAMMER2_INODE_ISUNLINKED) &&
178             (ip->flags & HAMMER2_INODE_ISDELETED) == 0) {
179                 hammer2_inode_unlink_t *ipul;
180
181                 ipul = kmalloc(sizeof(*ipul), pmp->minode, M_WAITOK | M_ZERO);
182                 ipul->ip = ip;
183
184                 hammer2_spin_ex(&pmp->list_spin);
185                 TAILQ_INSERT_TAIL(&pmp->unlinkq, ipul, entry);
186                 hammer2_spin_unex(&pmp->list_spin);
187                 /* retain ref from vp for ipul */
188         } else {
189                 hammer2_inode_drop(ip);                 /* vp ref */
190         }
191
192         /*
193          * XXX handle background sync when ip dirty, kernel will no longer
194          * notify us regarding this inode because there is no longer a
195          * vnode attached to it.
196          */
197
198         LOCKSTOP;
199         return (0);
200 }
201
202 static
203 int
204 hammer2_vop_fsync(struct vop_fsync_args *ap)
205 {
206         hammer2_inode_t *ip;
207         struct vnode *vp;
208
209         LOCKSTART;
210         vp = ap->a_vp;
211         ip = VTOI(vp);
212
213 #if 0
214         /* XXX can't do this yet */
215         hammer2_trans_init(ip->pmp, HAMMER2_TRANS_ISFLUSH);
216         vfsync(vp, ap->a_waitfor, 1, NULL, NULL);
217 #endif
218         hammer2_trans_init(ip->pmp, 0);
219         vfsync(vp, ap->a_waitfor, 1, NULL, NULL);
220
221         /*
222          * Calling chain_flush here creates a lot of duplicative
223          * COW operations due to non-optimal vnode ordering.
224          *
225          * Only do it for an actual fsync() syscall.  The other forms
226          * which call this function will eventually call chain_flush
227          * on the volume root as a catch-all, which is far more optimal.
228          */
229         hammer2_inode_lock(ip, 0);
230         if (ip->flags & HAMMER2_INODE_MODIFIED)
231                 hammer2_inode_fsync(ip);
232         hammer2_inode_unlock(ip);
233         hammer2_trans_done(ip->pmp);
234
235         LOCKSTOP;
236         return (0);
237 }
238
239 static
240 int
241 hammer2_vop_access(struct vop_access_args *ap)
242 {
243         hammer2_inode_t *ip = VTOI(ap->a_vp);
244         uid_t uid;
245         gid_t gid;
246         int error;
247
248         LOCKSTART;
249         hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED);
250         uid = hammer2_to_unix_xid(&ip->meta.uid);
251         gid = hammer2_to_unix_xid(&ip->meta.gid);
252         error = vop_helper_access(ap, uid, gid, ip->meta.mode, ip->meta.uflags);
253         hammer2_inode_unlock(ip);
254
255         LOCKSTOP;
256         return (error);
257 }
258
259 static
260 int
261 hammer2_vop_getattr(struct vop_getattr_args *ap)
262 {
263         hammer2_pfs_t *pmp;
264         hammer2_inode_t *ip;
265         struct vnode *vp;
266         struct vattr *vap;
267         hammer2_chain_t *chain;
268         int i;
269
270         LOCKSTART;
271         vp = ap->a_vp;
272         vap = ap->a_vap;
273
274         ip = VTOI(vp);
275         pmp = ip->pmp;
276
277         hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED);
278
279         vap->va_fsid = pmp->mp->mnt_stat.f_fsid.val[0];
280         vap->va_fileid = ip->meta.inum;
281         vap->va_mode = ip->meta.mode;
282         vap->va_nlink = ip->meta.nlinks;
283         vap->va_uid = hammer2_to_unix_xid(&ip->meta.uid);
284         vap->va_gid = hammer2_to_unix_xid(&ip->meta.gid);
285         vap->va_rmajor = 0;
286         vap->va_rminor = 0;
287         vap->va_size = ip->meta.size;   /* protected by shared lock */
288         vap->va_blocksize = HAMMER2_PBUFSIZE;
289         vap->va_flags = ip->meta.uflags;
290         hammer2_time_to_timespec(ip->meta.ctime, &vap->va_ctime);
291         hammer2_time_to_timespec(ip->meta.mtime, &vap->va_mtime);
292         hammer2_time_to_timespec(ip->meta.mtime, &vap->va_atime);
293         vap->va_gen = 1;
294         vap->va_bytes = 0;
295         if (ip->meta.type == HAMMER2_OBJTYPE_DIRECTORY) {
296                 /*
297                  * Can't really calculate directory use sans the files under
298                  * it, just assume one block for now.
299                  */
300                 vap->va_bytes += HAMMER2_INODE_BYTES;
301         } else {
302                 for (i = 0; i < ip->cluster.nchains; ++i) {
303                         if ((chain = ip->cluster.array[i].chain) != NULL) {
304                                 if (vap->va_bytes < chain->bref.data_count)
305                                         vap->va_bytes = chain->bref.data_count;
306                         }
307                 }
308         }
309         vap->va_type = hammer2_get_vtype(ip->meta.type);
310         vap->va_filerev = 0;
311         vap->va_uid_uuid = ip->meta.uid;
312         vap->va_gid_uuid = ip->meta.gid;
313         vap->va_vaflags = VA_UID_UUID_VALID | VA_GID_UUID_VALID |
314                           VA_FSID_UUID_VALID;
315
316         hammer2_inode_unlock(ip);
317
318         LOCKSTOP;
319         return (0);
320 }
321
322 static
323 int
324 hammer2_vop_setattr(struct vop_setattr_args *ap)
325 {
326         hammer2_inode_t *ip;
327         struct vnode *vp;
328         struct vattr *vap;
329         int error;
330         int kflags = 0;
331         uint64_t ctime;
332
333         LOCKSTART;
334         vp = ap->a_vp;
335         vap = ap->a_vap;
336         hammer2_update_time(&ctime);
337
338         ip = VTOI(vp);
339
340         if (ip->pmp->ronly) {
341                 LOCKSTOP;
342                 return(EROFS);
343         }
344
345         hammer2_pfs_memory_wait(ip->pmp);
346         hammer2_trans_init(ip->pmp, 0);
347         hammer2_inode_lock(ip, 0);
348         error = 0;
349
350         if (vap->va_flags != VNOVAL) {
351                 u_int32_t flags;
352
353                 flags = ip->meta.uflags;
354                 error = vop_helper_setattr_flags(&flags, vap->va_flags,
355                                      hammer2_to_unix_xid(&ip->meta.uid),
356                                      ap->a_cred);
357                 if (error == 0) {
358                         if (ip->meta.uflags != flags) {
359                                 hammer2_inode_modify(ip);
360                                 ip->meta.uflags = flags;
361                                 ip->meta.ctime = ctime;
362                                 kflags |= NOTE_ATTRIB;
363                         }
364                         if (ip->meta.uflags & (IMMUTABLE | APPEND)) {
365                                 error = 0;
366                                 goto done;
367                         }
368                 }
369                 goto done;
370         }
371         if (ip->meta.uflags & (IMMUTABLE | APPEND)) {
372                 error = EPERM;
373                 goto done;
374         }
375         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
376                 mode_t cur_mode = ip->meta.mode;
377                 uid_t cur_uid = hammer2_to_unix_xid(&ip->meta.uid);
378                 gid_t cur_gid = hammer2_to_unix_xid(&ip->meta.gid);
379                 uuid_t uuid_uid;
380                 uuid_t uuid_gid;
381
382                 error = vop_helper_chown(ap->a_vp, vap->va_uid, vap->va_gid,
383                                          ap->a_cred,
384                                          &cur_uid, &cur_gid, &cur_mode);
385                 if (error == 0) {
386                         hammer2_guid_to_uuid(&uuid_uid, cur_uid);
387                         hammer2_guid_to_uuid(&uuid_gid, cur_gid);
388                         if (bcmp(&uuid_uid, &ip->meta.uid, sizeof(uuid_uid)) ||
389                             bcmp(&uuid_gid, &ip->meta.gid, sizeof(uuid_gid)) ||
390                             ip->meta.mode != cur_mode
391                         ) {
392                                 hammer2_inode_modify(ip);
393                                 ip->meta.uid = uuid_uid;
394                                 ip->meta.gid = uuid_gid;
395                                 ip->meta.mode = cur_mode;
396                                 ip->meta.ctime = ctime;
397                         }
398                         kflags |= NOTE_ATTRIB;
399                 }
400         }
401
402         /*
403          * Resize the file
404          */
405         if (vap->va_size != VNOVAL && ip->meta.size != vap->va_size) {
406                 switch(vp->v_type) {
407                 case VREG:
408                         if (vap->va_size == ip->meta.size)
409                                 break;
410                         if (vap->va_size < ip->meta.size) {
411                                 hammer2_truncate_file(ip, vap->va_size);
412                         } else {
413                                 hammer2_extend_file(ip, vap->va_size);
414                         }
415                         hammer2_inode_modify(ip);
416                         ip->meta.mtime = ctime;
417                         break;
418                 default:
419                         error = EINVAL;
420                         goto done;
421                 }
422         }
423 #if 0
424         /* atime not supported */
425         if (vap->va_atime.tv_sec != VNOVAL) {
426                 hammer2_inode_modify(ip);
427                 ip->meta.atime = hammer2_timespec_to_time(&vap->va_atime);
428                 kflags |= NOTE_ATTRIB;
429         }
430 #endif
431         if (vap->va_mode != (mode_t)VNOVAL) {
432                 mode_t cur_mode = ip->meta.mode;
433                 uid_t cur_uid = hammer2_to_unix_xid(&ip->meta.uid);
434                 gid_t cur_gid = hammer2_to_unix_xid(&ip->meta.gid);
435
436                 error = vop_helper_chmod(ap->a_vp, vap->va_mode, ap->a_cred,
437                                          cur_uid, cur_gid, &cur_mode);
438                 if (error == 0 && ip->meta.mode != cur_mode) {
439                         hammer2_inode_modify(ip);
440                         ip->meta.mode = cur_mode;
441                         ip->meta.ctime = ctime;
442                         kflags |= NOTE_ATTRIB;
443                 }
444         }
445
446         if (vap->va_mtime.tv_sec != VNOVAL) {
447                 hammer2_inode_modify(ip);
448                 ip->meta.mtime = hammer2_timespec_to_time(&vap->va_mtime);
449                 kflags |= NOTE_ATTRIB;
450         }
451
452 done:
453         /*
454          * If a truncation occurred we must call inode_fsync() now in order
455          * to trim the related data chains, otherwise a later expansion can
456          * cause havoc.
457          *
458          * If an extend occured that changed the DIRECTDATA state, we must
459          * call inode_fsync now in order to prepare the inode's indirect
460          * block table.
461          */
462         if (ip->flags & HAMMER2_INODE_RESIZED)
463                 hammer2_inode_fsync(ip);
464
465         /*
466          * Cleanup.
467          */
468         hammer2_inode_unlock(ip);
469         hammer2_trans_done(ip->pmp);
470         hammer2_knote(ip->vp, kflags);
471
472         LOCKSTOP;
473         return (error);
474 }
475
476 static
477 int
478 hammer2_vop_readdir(struct vop_readdir_args *ap)
479 {
480         hammer2_xop_readdir_t *xop;
481         hammer2_blockref_t bref;
482         hammer2_inode_t *ip;
483         hammer2_tid_t inum;
484         hammer2_key_t lkey;
485         struct uio *uio;
486         off_t *cookies;
487         off_t saveoff;
488         int cookie_index;
489         int ncookies;
490         int error;
491         int eofflag;
492         int dtype;
493         int r;
494
495         LOCKSTART;
496         ip = VTOI(ap->a_vp);
497         uio = ap->a_uio;
498         saveoff = uio->uio_offset;
499         eofflag = 0;
500         error = 0;
501
502         /*
503          * Setup cookies directory entry cookies if requested
504          */
505         if (ap->a_ncookies) {
506                 ncookies = uio->uio_resid / 16 + 1;
507                 if (ncookies > 1024)
508                         ncookies = 1024;
509                 cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
510         } else {
511                 ncookies = -1;
512                 cookies = NULL;
513         }
514         cookie_index = 0;
515
516         hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED);
517
518         /*
519          * Handle artificial entries.  To ensure that only positive 64 bit
520          * quantities are returned to userland we always strip off bit 63.
521          * The hash code is designed such that codes 0x0000-0x7FFF are not
522          * used, allowing us to use these codes for articial entries.
523          *
524          * Entry 0 is used for '.' and entry 1 is used for '..'.  Do not
525          * allow '..' to cross the mount point into (e.g.) the super-root.
526          */
527         if (saveoff == 0) {
528                 inum = ip->meta.inum & HAMMER2_DIRHASH_USERMSK;
529                 r = vop_write_dirent(&error, uio, inum, DT_DIR, 1, ".");
530                 if (r)
531                         goto done;
532                 if (cookies)
533                         cookies[cookie_index] = saveoff;
534                 ++saveoff;
535                 ++cookie_index;
536                 if (cookie_index == ncookies)
537                         goto done;
538         }
539
540         if (saveoff == 1) {
541                 /*
542                  * Be careful with lockorder when accessing ".."
543                  *
544                  * (ip is the current dir. xip is the parent dir).
545                  */
546                 inum = ip->meta.inum & HAMMER2_DIRHASH_USERMSK;
547                 if (ip->pip && ip != ip->pmp->iroot)
548                         inum = ip->pip->meta.inum & HAMMER2_DIRHASH_USERMSK;
549                 r = vop_write_dirent(&error, uio, inum, DT_DIR, 2, "..");
550                 if (r)
551                         goto done;
552                 if (cookies)
553                         cookies[cookie_index] = saveoff;
554                 ++saveoff;
555                 ++cookie_index;
556                 if (cookie_index == ncookies)
557                         goto done;
558         }
559
560         lkey = saveoff | HAMMER2_DIRHASH_VISIBLE;
561         if (hammer2_debug & 0x0020)
562                 kprintf("readdir: lkey %016jx\n", lkey);
563         if (error)
564                 goto done;
565
566         /*
567          * Use XOP for cluster scan.
568          *
569          * parent is the inode cluster, already locked for us.  Don't
570          * double lock shared locks as this will screw up upgrades.
571          */
572         xop = hammer2_xop_alloc(ip, 0);
573         xop->lkey = lkey;
574         hammer2_xop_start(&xop->head, hammer2_xop_readdir);
575
576         for (;;) {
577                 const hammer2_inode_data_t *ripdata;
578
579                 error = hammer2_xop_collect(&xop->head, 0);
580                 if (error)
581                         break;
582                 if (cookie_index == ncookies)
583                         break;
584                 if (hammer2_debug & 0x0020)
585                 kprintf("cluster chain %p %p\n",
586                         xop->head.cluster.focus,
587                         (xop->head.cluster.focus ?
588                          xop->head.cluster.focus->data : (void *)-1));
589                 ripdata = &hammer2_cluster_rdata(&xop->head.cluster)->ipdata;
590                 hammer2_cluster_bref(&xop->head.cluster, &bref);
591                 if (bref.type == HAMMER2_BREF_TYPE_INODE) {
592                         dtype = hammer2_get_dtype(ripdata);
593                         saveoff = bref.key & HAMMER2_DIRHASH_USERMSK;
594                         r = vop_write_dirent(&error, uio,
595                                              ripdata->meta.inum &
596                                               HAMMER2_DIRHASH_USERMSK,
597                                              dtype,
598                                              ripdata->meta.name_len,
599                                              ripdata->filename);
600                         if (r)
601                                 break;
602                         if (cookies)
603                                 cookies[cookie_index] = saveoff;
604                         ++cookie_index;
605                 } else {
606                         /* XXX chain error */
607                         kprintf("bad chain type readdir %d\n", bref.type);
608                 }
609         }
610         hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
611         if (error == ENOENT) {
612                 error = 0;
613                 eofflag = 1;
614                 saveoff = (hammer2_key_t)-1;
615         } else {
616                 saveoff = bref.key & HAMMER2_DIRHASH_USERMSK;
617         }
618 done:
619         hammer2_inode_unlock(ip);
620         if (ap->a_eofflag)
621                 *ap->a_eofflag = eofflag;
622         if (hammer2_debug & 0x0020)
623                 kprintf("readdir: done at %016jx\n", saveoff);
624         uio->uio_offset = saveoff & ~HAMMER2_DIRHASH_VISIBLE;
625         if (error && cookie_index == 0) {
626                 if (cookies) {
627                         kfree(cookies, M_TEMP);
628                         *ap->a_ncookies = 0;
629                         *ap->a_cookies = NULL;
630                 }
631         } else {
632                 if (cookies) {
633                         *ap->a_ncookies = cookie_index;
634                         *ap->a_cookies = cookies;
635                 }
636         }
637         LOCKSTOP;
638         return (error);
639 }
640
641 /*
642  * hammer2_vop_readlink { vp, uio, cred }
643  */
644 static
645 int
646 hammer2_vop_readlink(struct vop_readlink_args *ap)
647 {
648         struct vnode *vp;
649         hammer2_inode_t *ip;
650         int error;
651
652         vp = ap->a_vp;
653         if (vp->v_type != VLNK)
654                 return (EINVAL);
655         ip = VTOI(vp);
656
657         error = hammer2_read_file(ip, ap->a_uio, 0);
658         return (error);
659 }
660
661 static
662 int
663 hammer2_vop_read(struct vop_read_args *ap)
664 {
665         struct vnode *vp;
666         hammer2_inode_t *ip;
667         struct uio *uio;
668         int error;
669         int seqcount;
670         int bigread;
671
672         /*
673          * Read operations supported on this vnode?
674          */
675         vp = ap->a_vp;
676         if (vp->v_type != VREG)
677                 return (EINVAL);
678
679         /*
680          * Misc
681          */
682         ip = VTOI(vp);
683         uio = ap->a_uio;
684         error = 0;
685
686         seqcount = ap->a_ioflag >> 16;
687         bigread = (uio->uio_resid > 100 * 1024 * 1024);
688
689         error = hammer2_read_file(ip, uio, seqcount);
690         return (error);
691 }
692
693 static
694 int
695 hammer2_vop_write(struct vop_write_args *ap)
696 {
697         hammer2_inode_t *ip;
698         thread_t td;
699         struct vnode *vp;
700         struct uio *uio;
701         int error;
702         int seqcount;
703
704         /*
705          * Read operations supported on this vnode?
706          */
707         vp = ap->a_vp;
708         if (vp->v_type != VREG)
709                 return (EINVAL);
710
711         /*
712          * Misc
713          */
714         ip = VTOI(vp);
715         uio = ap->a_uio;
716         error = 0;
717         if (ip->pmp->ronly) {
718                 return (EROFS);
719         }
720
721         seqcount = ap->a_ioflag >> 16;
722
723         /*
724          * Check resource limit
725          */
726         if (uio->uio_resid > 0 && (td = uio->uio_td) != NULL && td->td_proc &&
727             uio->uio_offset + uio->uio_resid >
728              td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
729                 lwpsignal(td->td_proc, td->td_lwp, SIGXFSZ);
730                 return (EFBIG);
731         }
732
733         /*
734          * The transaction interlocks against flushes initiations
735          * (note: but will run concurrently with the actual flush).
736          */
737         hammer2_trans_init(ip->pmp, 0);
738         error = hammer2_write_file(ip, uio, ap->a_ioflag, seqcount);
739         hammer2_trans_done(ip->pmp);
740
741         return (error);
742 }
743
744 /*
745  * Perform read operations on a file or symlink given an UNLOCKED
746  * inode and uio.
747  *
748  * The passed ip is not locked.
749  */
750 static
751 int
752 hammer2_read_file(hammer2_inode_t *ip, struct uio *uio, int seqcount)
753 {
754         hammer2_off_t size;
755         struct buf *bp;
756         int error;
757
758         error = 0;
759
760         /*
761          * UIO read loop.
762          *
763          * WARNING! Assumes that the kernel interlocks size changes at the
764          *          vnode level.
765          */
766         hammer2_mtx_sh(&ip->lock);
767         size = ip->meta.size;
768         hammer2_mtx_unlock(&ip->lock);
769
770         while (uio->uio_resid > 0 && uio->uio_offset < size) {
771                 hammer2_key_t lbase;
772                 hammer2_key_t leof;
773                 int lblksize;
774                 int loff;
775                 int n;
776
777                 lblksize = hammer2_calc_logical(ip, uio->uio_offset,
778                                                 &lbase, &leof);
779
780                 error = cluster_read(ip->vp, leof, lbase, lblksize,
781                                      uio->uio_resid, seqcount * BKVASIZE,
782                                      &bp);
783
784                 if (error)
785                         break;
786                 loff = (int)(uio->uio_offset - lbase);
787                 n = lblksize - loff;
788                 if (n > uio->uio_resid)
789                         n = uio->uio_resid;
790                 if (n > size - uio->uio_offset)
791                         n = (int)(size - uio->uio_offset);
792                 bp->b_flags |= B_AGE;
793                 uiomove((char *)bp->b_data + loff, n, uio);
794                 bqrelse(bp);
795         }
796         return (error);
797 }
798
799 /*
800  * Write to the file represented by the inode via the logical buffer cache.
801  * The inode may represent a regular file or a symlink.
802  *
803  * The inode must not be locked.
804  */
805 static
806 int
807 hammer2_write_file(hammer2_inode_t *ip, struct uio *uio,
808                    int ioflag, int seqcount)
809 {
810         hammer2_key_t old_eof;
811         hammer2_key_t new_eof;
812         struct buf *bp;
813         int kflags;
814         int error;
815         int modified;
816
817         /*
818          * Setup if append
819          *
820          * WARNING! Assumes that the kernel interlocks size changes at the
821          *          vnode level.
822          */
823         hammer2_mtx_ex(&ip->lock);
824         if (ioflag & IO_APPEND)
825                 uio->uio_offset = ip->meta.size;
826         old_eof = ip->meta.size;
827
828         /*
829          * Extend the file if necessary.  If the write fails at some point
830          * we will truncate it back down to cover as much as we were able
831          * to write.
832          *
833          * Doing this now makes it easier to calculate buffer sizes in
834          * the loop.
835          */
836         kflags = 0;
837         error = 0;
838         modified = 0;
839
840         if (uio->uio_offset + uio->uio_resid > old_eof) {
841                 new_eof = uio->uio_offset + uio->uio_resid;
842                 modified = 1;
843                 hammer2_extend_file(ip, new_eof);
844                 kflags |= NOTE_EXTEND;
845         } else {
846                 new_eof = old_eof;
847         }
848         hammer2_mtx_unlock(&ip->lock);
849         
850         /*
851          * UIO write loop
852          */
853         while (uio->uio_resid > 0) {
854                 hammer2_key_t lbase;
855                 int trivial;
856                 int endofblk;
857                 int lblksize;
858                 int loff;
859                 int n;
860
861                 /*
862                  * Don't allow the buffer build to blow out the buffer
863                  * cache.
864                  */
865                 if ((ioflag & IO_RECURSE) == 0)
866                         bwillwrite(HAMMER2_PBUFSIZE);
867
868                 /*
869                  * This nominally tells us how much we can cluster and
870                  * what the logical buffer size needs to be.  Currently
871                  * we don't try to cluster the write and just handle one
872                  * block at a time.
873                  */
874                 lblksize = hammer2_calc_logical(ip, uio->uio_offset,
875                                                 &lbase, NULL);
876                 loff = (int)(uio->uio_offset - lbase);
877                 
878                 KKASSERT(lblksize <= 65536);
879
880                 /*
881                  * Calculate bytes to copy this transfer and whether the
882                  * copy completely covers the buffer or not.
883                  */
884                 trivial = 0;
885                 n = lblksize - loff;
886                 if (n > uio->uio_resid) {
887                         n = uio->uio_resid;
888                         if (loff == lbase && uio->uio_offset + n == new_eof)
889                                 trivial = 1;
890                         endofblk = 0;
891                 } else {
892                         if (loff == 0)
893                                 trivial = 1;
894                         endofblk = 1;
895                 }
896
897                 /*
898                  * Get the buffer
899                  */
900                 if (uio->uio_segflg == UIO_NOCOPY) {
901                         /*
902                          * Issuing a write with the same data backing the
903                          * buffer.  Instantiate the buffer to collect the
904                          * backing vm pages, then read-in any missing bits.
905                          *
906                          * This case is used by vop_stdputpages().
907                          */
908                         bp = getblk(ip->vp, lbase, lblksize, GETBLK_BHEAVY, 0);
909                         if ((bp->b_flags & B_CACHE) == 0) {
910                                 bqrelse(bp);
911                                 error = bread(ip->vp, lbase, lblksize, &bp);
912                         }
913                 } else if (trivial) {
914                         /*
915                          * Even though we are entirely overwriting the buffer
916                          * we may still have to zero it out to avoid a
917                          * mmap/write visibility issue.
918                          */
919                         bp = getblk(ip->vp, lbase, lblksize, GETBLK_BHEAVY, 0);
920                         if ((bp->b_flags & B_CACHE) == 0)
921                                 vfs_bio_clrbuf(bp);
922                 } else {
923                         /*
924                          * Partial overwrite, read in any missing bits then
925                          * replace the portion being written.
926                          *
927                          * (The strategy code will detect zero-fill physical
928                          * blocks for this case).
929                          */
930                         error = bread(ip->vp, lbase, lblksize, &bp);
931                         if (error == 0)
932                                 bheavy(bp);
933                 }
934
935                 if (error) {
936                         brelse(bp);
937                         break;
938                 }
939
940                 /*
941                  * Ok, copy the data in
942                  */
943                 error = uiomove(bp->b_data + loff, n, uio);
944                 kflags |= NOTE_WRITE;
945                 modified = 1;
946                 if (error) {
947                         brelse(bp);
948                         break;
949                 }
950
951                 /*
952                  * WARNING: Pageout daemon will issue UIO_NOCOPY writes
953                  *          with IO_SYNC or IO_ASYNC set.  These writes
954                  *          must be handled as the pageout daemon expects.
955                  */
956                 if (ioflag & IO_SYNC) {
957                         bwrite(bp);
958                 } else if ((ioflag & IO_DIRECT) && endofblk) {
959                         bawrite(bp);
960                 } else if (ioflag & IO_ASYNC) {
961                         bawrite(bp);
962                 } else {
963                         bdwrite(bp);
964                 }
965         }
966
967         /*
968          * Cleanup.  If we extended the file EOF but failed to write through
969          * the entire write is a failure and we have to back-up.
970          */
971         if (error && new_eof != old_eof) {
972                 hammer2_mtx_ex(&ip->lock);
973                 hammer2_truncate_file(ip, old_eof);
974                 if (ip->flags & HAMMER2_INODE_MODIFIED)
975                         hammer2_inode_fsync(ip);
976                 hammer2_mtx_unlock(&ip->lock);
977         } else if (modified) {
978                 hammer2_mtx_ex(&ip->lock);
979                 hammer2_inode_modify(ip);
980                 hammer2_update_time(&ip->meta.mtime);
981                 if (ip->flags & HAMMER2_INODE_MODIFIED)
982                         hammer2_inode_fsync(ip);
983                 hammer2_mtx_unlock(&ip->lock);
984                 hammer2_knote(ip->vp, kflags);
985         }
986         hammer2_trans_assert_strategy(ip->pmp);
987
988         return error;
989 }
990
991 /*
992  * Truncate the size of a file.  The inode must not be locked.
993  *
994  * We must unconditionally set HAMMER2_INODE_RESIZED to properly
995  * ensure that any on-media data beyond the new file EOF has been destroyed.
996  *
997  * WARNING: nvtruncbuf() can only be safely called without the inode lock
998  *          held due to the way our write thread works.  If the truncation
999  *          occurs in the middle of a buffer, nvtruncbuf() is responsible
1000  *          for dirtying that buffer and zeroing out trailing bytes.
1001  *
1002  * WARNING! Assumes that the kernel interlocks size changes at the
1003  *          vnode level.
1004  *
1005  * WARNING! Caller assumes responsibility for removing dead blocks
1006  *          if INODE_RESIZED is set.
1007  */
1008 static
1009 void
1010 hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize)
1011 {
1012         hammer2_key_t lbase;
1013         int nblksize;
1014
1015         LOCKSTART;
1016         hammer2_mtx_unlock(&ip->lock);
1017         if (ip->vp) {
1018                 nblksize = hammer2_calc_logical(ip, nsize, &lbase, NULL);
1019                 nvtruncbuf(ip->vp, nsize,
1020                            nblksize, (int)nsize & (nblksize - 1),
1021                            0);
1022         }
1023         hammer2_mtx_ex(&ip->lock);
1024         KKASSERT((ip->flags & HAMMER2_INODE_RESIZED) == 0);
1025         ip->osize = ip->meta.size;
1026         ip->meta.size = nsize;
1027         atomic_set_int(&ip->flags, HAMMER2_INODE_MODIFIED |
1028                                    HAMMER2_INODE_RESIZED);
1029         LOCKSTOP;
1030 }
1031
1032 /*
1033  * Extend the size of a file.  The inode must not be locked.
1034  *
1035  * Even though the file size is changing, we do not have to set the
1036  * INODE_RESIZED bit unless the file size crosses the EMBEDDED_BYTES
1037  * boundary.  When this occurs a hammer2_inode_fsync() is required
1038  * to prepare the inode cluster's indirect block table.
1039  *
1040  * WARNING! Assumes that the kernel interlocks size changes at the
1041  *          vnode level.
1042  *
1043  * WARNING! Caller assumes responsibility for transitioning out
1044  *          of the inode DIRECTDATA mode if INODE_RESIZED is set.
1045  */
1046 static
1047 void
1048 hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize)
1049 {
1050         hammer2_key_t lbase;
1051         hammer2_key_t osize;
1052         int oblksize;
1053         int nblksize;
1054
1055         LOCKSTART;
1056
1057         KKASSERT((ip->flags & HAMMER2_INODE_RESIZED) == 0);
1058         osize = ip->meta.size;
1059         ip->osize = osize;
1060         ip->meta.size = nsize;
1061         atomic_set_int(&ip->flags, HAMMER2_INODE_MODIFIED);
1062
1063         if (osize <= HAMMER2_EMBEDDED_BYTES && nsize > HAMMER2_EMBEDDED_BYTES)
1064                 atomic_set_int(&ip->flags, HAMMER2_INODE_RESIZED);
1065
1066         hammer2_mtx_unlock(&ip->lock);
1067         if (ip->vp) {
1068                 oblksize = hammer2_calc_logical(ip, osize, &lbase, NULL);
1069                 nblksize = hammer2_calc_logical(ip, nsize, &lbase, NULL);
1070                 nvextendbuf(ip->vp,
1071                             osize, nsize,
1072                             oblksize, nblksize,
1073                             -1, -1, 0);
1074         }
1075         hammer2_mtx_ex(&ip->lock);
1076
1077         LOCKSTOP;
1078 }
1079
1080 static
1081 int
1082 hammer2_vop_nresolve(struct vop_nresolve_args *ap)
1083 {
1084         hammer2_xop_nresolve_t *xop;
1085         hammer2_inode_t *ip;
1086         hammer2_inode_t *dip;
1087         struct namecache *ncp;
1088         struct vnode *vp;
1089         int error;
1090
1091         LOCKSTART;
1092         dip = VTOI(ap->a_dvp);
1093         xop = hammer2_xop_alloc(dip, 0);
1094
1095         ncp = ap->a_nch->ncp;
1096         hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
1097
1098         /*
1099          * Note: In DragonFly the kernel handles '.' and '..'.
1100          */
1101         hammer2_inode_lock(dip, HAMMER2_RESOLVE_SHARED);
1102         hammer2_xop_start(&xop->head, hammer2_xop_nresolve);
1103
1104         error = hammer2_xop_collect(&xop->head, 0);
1105         if (error) {
1106                 ip = NULL;
1107         } else {
1108                 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1);
1109         }
1110         hammer2_inode_unlock(dip);
1111
1112         /*
1113          * Acquire the related vnode
1114          *
1115          * NOTE: For error processing, only ENOENT resolves the namecache
1116          *       entry to NULL, otherwise we just return the error and
1117          *       leave the namecache unresolved.
1118          *
1119          * NOTE: multiple hammer2_inode structures can be aliased to the
1120          *       same chain element, for example for hardlinks.  This
1121          *       use case does not 'reattach' inode associations that
1122          *       might already exist, but always allocates a new one.
1123          *
1124          * WARNING: inode structure is locked exclusively via inode_get
1125          *          but chain was locked shared.  inode_unlock()
1126          *          will handle it properly.
1127          */
1128         if (ip) {
1129                 vp = hammer2_igetv(ip, &error);
1130                 if (error == 0) {
1131                         vn_unlock(vp);
1132                         cache_setvp(ap->a_nch, vp);
1133                 } else if (error == ENOENT) {
1134                         cache_setvp(ap->a_nch, NULL);
1135                 }
1136                 hammer2_inode_unlock(ip);
1137
1138                 /*
1139                  * The vp should not be released until after we've disposed
1140                  * of our locks, because it might cause vop_inactive() to
1141                  * be called.
1142                  */
1143                 if (vp)
1144                         vrele(vp);
1145         } else {
1146                 error = ENOENT;
1147                 cache_setvp(ap->a_nch, NULL);
1148         }
1149         hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
1150         KASSERT(error || ap->a_nch->ncp->nc_vp != NULL,
1151                 ("resolve error %d/%p ap %p\n",
1152                  error, ap->a_nch->ncp->nc_vp, ap));
1153         LOCKSTOP;
1154
1155         return error;
1156 }
1157
1158 static
1159 int
1160 hammer2_vop_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
1161 {
1162         hammer2_inode_t *dip;
1163         hammer2_inode_t *ip;
1164         int error;
1165
1166         LOCKSTART;
1167         dip = VTOI(ap->a_dvp);
1168
1169         if ((ip = dip->pip) == NULL) {
1170                 *ap->a_vpp = NULL;
1171                 LOCKSTOP;
1172                 return ENOENT;
1173         }
1174         hammer2_inode_lock(ip, 0);
1175         *ap->a_vpp = hammer2_igetv(ip, &error);
1176         hammer2_inode_unlock(ip);
1177
1178         LOCKSTOP;
1179         return error;
1180 }
1181
1182 static
1183 int
1184 hammer2_vop_nmkdir(struct vop_nmkdir_args *ap)
1185 {
1186         hammer2_inode_t *dip;
1187         hammer2_inode_t *nip;
1188         struct namecache *ncp;
1189         const uint8_t *name;
1190         size_t name_len;
1191         int error;
1192
1193         LOCKSTART;
1194         dip = VTOI(ap->a_dvp);
1195         if (dip->pmp->ronly) {
1196                 LOCKSTOP;
1197                 return (EROFS);
1198         }
1199
1200         ncp = ap->a_nch->ncp;
1201         name = ncp->nc_name;
1202         name_len = ncp->nc_nlen;
1203
1204         hammer2_pfs_memory_wait(dip->pmp);
1205         hammer2_trans_init(dip->pmp, 0);
1206         nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
1207                                    name, name_len, 0,
1208                                    hammer2_trans_newinum(dip->pmp), 0, 0,
1209                                    0, &error);
1210         if (error) {
1211                 KKASSERT(nip == NULL);
1212                 *ap->a_vpp = NULL;
1213         } else {
1214                 *ap->a_vpp = hammer2_igetv(nip, &error);
1215                 hammer2_inode_unlock(nip);
1216         }
1217         hammer2_trans_done(dip->pmp);
1218
1219         if (error == 0) {
1220                 cache_setunresolved(ap->a_nch);
1221                 cache_setvp(ap->a_nch, *ap->a_vpp);
1222         }
1223         LOCKSTOP;
1224         return error;
1225 }
1226
1227 static
1228 int
1229 hammer2_vop_open(struct vop_open_args *ap)
1230 {
1231         return vop_stdopen(ap);
1232 }
1233
1234 /*
1235  * hammer2_vop_advlock { vp, id, op, fl, flags }
1236  */
1237 static
1238 int
1239 hammer2_vop_advlock(struct vop_advlock_args *ap)
1240 {
1241         hammer2_inode_t *ip = VTOI(ap->a_vp);
1242         hammer2_off_t size;
1243
1244         size = ip->meta.size;
1245         return (lf_advlock(ap, &ip->advlock, size));
1246 }
1247
1248 static
1249 int
1250 hammer2_vop_close(struct vop_close_args *ap)
1251 {
1252         return vop_stdclose(ap);
1253 }
1254
1255 /*
1256  * hammer2_vop_nlink { nch, dvp, vp, cred }
1257  *
1258  * Create a hardlink from (vp) to {dvp, nch}.
1259  */
1260 static
1261 int
1262 hammer2_vop_nlink(struct vop_nlink_args *ap)
1263 {
1264         hammer2_xop_nlink_t *xop1;
1265         hammer2_inode_t *fdip;  /* target directory to create link in */
1266         hammer2_inode_t *tdip;  /* target directory to create link in */
1267         hammer2_inode_t *cdip;  /* common parent directory */
1268         hammer2_inode_t *ip;    /* inode we are hardlinking to */
1269         struct namecache *ncp;
1270         const uint8_t *name;
1271         size_t name_len;
1272         int error;
1273
1274         LOCKSTART;
1275         tdip = VTOI(ap->a_dvp);
1276         if (tdip->pmp->ronly) {
1277                 LOCKSTOP;
1278                 return (EROFS);
1279         }
1280
1281         ncp = ap->a_nch->ncp;
1282         name = ncp->nc_name;
1283         name_len = ncp->nc_nlen;
1284
1285         /*
1286          * ip represents the file being hardlinked.  The file could be a
1287          * normal file or a hardlink target if it has already been hardlinked.
1288          * If ip is a hardlinked target then ip->pip represents the location
1289          * of the hardlinked target, NOT the location of the hardlink pointer.
1290          *
1291          * Bump nlinks and potentially also create or move the hardlink
1292          * target in the parent directory common to (ip) and (tdip).  The
1293          * consolidation code can modify ip->cluster and ip->pip.  The
1294          * returned cluster is locked.
1295          */
1296         ip = VTOI(ap->a_vp);
1297         hammer2_pfs_memory_wait(ip->pmp);
1298         hammer2_trans_init(ip->pmp, 0);
1299
1300         /*
1301          * The common parent directory must be locked first to avoid deadlocks.
1302          * Also note that fdip and/or tdip might match cdip.
1303          */
1304         fdip = ip->pip;
1305         cdip = hammer2_inode_common_parent(fdip, tdip);
1306         hammer2_inode_lock(cdip, 0);
1307         hammer2_inode_lock(fdip, 0);
1308         hammer2_inode_lock(tdip, 0);
1309         hammer2_inode_lock(ip, 0);
1310         error = 0;
1311
1312         /*
1313          * If ip is not a hardlink target we must convert it to a hardlink.
1314          * If fdip != cdip we must shift the inode to cdip.
1315          */
1316         if (fdip != cdip || (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1317                 xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
1318                 hammer2_xop_setip2(&xop1->head, ip);
1319                 hammer2_xop_setip3(&xop1->head, cdip);
1320
1321                 hammer2_xop_start(&xop1->head, hammer2_xop_nlink);
1322                 error = hammer2_xop_collect(&xop1->head, 0);
1323                 hammer2_xop_retire(&xop1->head, HAMMER2_XOPMASK_VOP);
1324                 if (error == ENOENT)
1325                         error = 0;
1326         }
1327
1328         /*
1329          * Must synchronize original inode whos chains are now a hardlink
1330          * target.  We must match what the backend XOP did to the
1331          * chains.
1332          */
1333         if (error == 0 && (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1334                 hammer2_inode_modify(ip);
1335                 ip->meta.name_key = ip->meta.inum;
1336                 ip->meta.name_len = 18; /* "0x%016jx" */
1337         }
1338
1339         /*
1340          * Create the hardlink target and bump nlinks.
1341          */
1342         if (error == 0) {
1343                 hammer2_inode_create(tdip, NULL, NULL,
1344                                      name, name_len, 0,
1345                                      ip->meta.inum,
1346                                      HAMMER2_OBJTYPE_HARDLINK, ip->meta.type,
1347                                      0, &error);
1348                 hammer2_inode_modify(ip);
1349                 ++ip->meta.nlinks;
1350         }
1351         if (error == 0) {
1352                 cache_setunresolved(ap->a_nch);
1353                 cache_setvp(ap->a_nch, ap->a_vp);
1354         }
1355         hammer2_inode_unlock(ip);
1356         hammer2_inode_unlock(tdip);
1357         hammer2_inode_unlock(fdip);
1358         hammer2_inode_unlock(cdip);
1359         hammer2_inode_drop(cdip);
1360         hammer2_trans_done(ip->pmp);
1361
1362         LOCKSTOP;
1363         return error;
1364 }
1365
1366 /*
1367  * hammer2_vop_ncreate { nch, dvp, vpp, cred, vap }
1368  *
1369  * The operating system has already ensured that the directory entry
1370  * does not exist and done all appropriate namespace locking.
1371  */
1372 static
1373 int
1374 hammer2_vop_ncreate(struct vop_ncreate_args *ap)
1375 {
1376         hammer2_inode_t *dip;
1377         hammer2_inode_t *nip;
1378         struct namecache *ncp;
1379         const uint8_t *name;
1380         size_t name_len;
1381         int error;
1382
1383         LOCKSTART;
1384         dip = VTOI(ap->a_dvp);
1385         if (dip->pmp->ronly) {
1386                 LOCKSTOP;
1387                 return (EROFS);
1388         }
1389
1390         ncp = ap->a_nch->ncp;
1391         name = ncp->nc_name;
1392         name_len = ncp->nc_nlen;
1393         hammer2_pfs_memory_wait(dip->pmp);
1394         hammer2_trans_init(dip->pmp, 0);
1395
1396         nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
1397                                    name, name_len, 0,
1398                                    hammer2_trans_newinum(dip->pmp), 0, 0,
1399                                    0, &error);
1400         if (error) {
1401                 KKASSERT(nip == NULL);
1402                 *ap->a_vpp = NULL;
1403         } else {
1404                 *ap->a_vpp = hammer2_igetv(nip, &error);
1405                 hammer2_inode_unlock(nip);
1406         }
1407         hammer2_trans_done(dip->pmp);
1408
1409         if (error == 0) {
1410                 cache_setunresolved(ap->a_nch);
1411                 cache_setvp(ap->a_nch, *ap->a_vpp);
1412         }
1413         LOCKSTOP;
1414         return error;
1415 }
1416
1417 /*
1418  * Make a device node (typically a fifo)
1419  */
1420 static
1421 int
1422 hammer2_vop_nmknod(struct vop_nmknod_args *ap)
1423 {
1424         hammer2_inode_t *dip;
1425         hammer2_inode_t *nip;
1426         struct namecache *ncp;
1427         const uint8_t *name;
1428         size_t name_len;
1429         int error;
1430
1431         LOCKSTART;
1432         dip = VTOI(ap->a_dvp);
1433         if (dip->pmp->ronly) {
1434                 LOCKSTOP;
1435                 return (EROFS);
1436         }
1437
1438         ncp = ap->a_nch->ncp;
1439         name = ncp->nc_name;
1440         name_len = ncp->nc_nlen;
1441         hammer2_pfs_memory_wait(dip->pmp);
1442         hammer2_trans_init(dip->pmp, 0);
1443
1444         nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
1445                                    name, name_len, 0,
1446                                    hammer2_trans_newinum(dip->pmp), 0, 0,
1447                                    0, &error);
1448         if (error) {
1449                 KKASSERT(nip == NULL);
1450                 *ap->a_vpp = NULL;
1451         } else {
1452                 *ap->a_vpp = hammer2_igetv(nip, &error);
1453                 hammer2_inode_unlock(nip);
1454         }
1455         hammer2_trans_done(dip->pmp);
1456
1457         if (error == 0) {
1458                 cache_setunresolved(ap->a_nch);
1459                 cache_setvp(ap->a_nch, *ap->a_vpp);
1460         }
1461         LOCKSTOP;
1462         return error;
1463 }
1464
1465 /*
1466  * hammer2_vop_nsymlink { nch, dvp, vpp, cred, vap, target }
1467  */
1468 static
1469 int
1470 hammer2_vop_nsymlink(struct vop_nsymlink_args *ap)
1471 {
1472         hammer2_inode_t *dip;
1473         hammer2_inode_t *nip;
1474         struct namecache *ncp;
1475         const uint8_t *name;
1476         size_t name_len;
1477         int error;
1478         
1479         dip = VTOI(ap->a_dvp);
1480         if (dip->pmp->ronly)
1481                 return (EROFS);
1482
1483         ncp = ap->a_nch->ncp;
1484         name = ncp->nc_name;
1485         name_len = ncp->nc_nlen;
1486         hammer2_pfs_memory_wait(dip->pmp);
1487         hammer2_trans_init(dip->pmp, 0);
1488
1489         ap->a_vap->va_type = VLNK;      /* enforce type */
1490
1491         nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
1492                                    name, name_len, 0,
1493                                    hammer2_trans_newinum(dip->pmp), 0, 0,
1494                                    0, &error);
1495         if (error) {
1496                 KKASSERT(nip == NULL);
1497                 *ap->a_vpp = NULL;
1498                 hammer2_trans_done(dip->pmp);
1499                 return error;
1500         }
1501         *ap->a_vpp = hammer2_igetv(nip, &error);
1502
1503         /*
1504          * Build the softlink (~like file data) and finalize the namecache.
1505          */
1506         if (error == 0) {
1507                 size_t bytes;
1508                 struct uio auio;
1509                 struct iovec aiov;
1510
1511                 bytes = strlen(ap->a_target);
1512
1513                 hammer2_inode_unlock(nip);
1514                 bzero(&auio, sizeof(auio));
1515                 bzero(&aiov, sizeof(aiov));
1516                 auio.uio_iov = &aiov;
1517                 auio.uio_segflg = UIO_SYSSPACE;
1518                 auio.uio_rw = UIO_WRITE;
1519                 auio.uio_resid = bytes;
1520                 auio.uio_iovcnt = 1;
1521                 auio.uio_td = curthread;
1522                 aiov.iov_base = ap->a_target;
1523                 aiov.iov_len = bytes;
1524                 error = hammer2_write_file(nip, &auio, IO_APPEND, 0);
1525                 /* XXX handle error */
1526                 error = 0;
1527         } else {
1528                 hammer2_inode_unlock(nip);
1529         }
1530         hammer2_trans_done(dip->pmp);
1531
1532         /*
1533          * Finalize namecache
1534          */
1535         if (error == 0) {
1536                 cache_setunresolved(ap->a_nch);
1537                 cache_setvp(ap->a_nch, *ap->a_vpp);
1538                 /* hammer2_knote(ap->a_dvp, NOTE_WRITE); */
1539         }
1540         return error;
1541 }
1542
1543 /*
1544  * hammer2_vop_nremove { nch, dvp, cred }
1545  */
1546 static
1547 int
1548 hammer2_vop_nremove(struct vop_nremove_args *ap)
1549 {
1550         hammer2_xop_unlink_t *xop;
1551         hammer2_inode_t *dip;
1552         hammer2_inode_t *ip;
1553         struct namecache *ncp;
1554         int error;
1555         int isopen;
1556
1557         LOCKSTART;
1558         dip = VTOI(ap->a_dvp);
1559         if (dip->pmp->ronly) {
1560                 LOCKSTOP;
1561                 return(EROFS);
1562         }
1563
1564         ncp = ap->a_nch->ncp;
1565
1566         hammer2_pfs_memory_wait(dip->pmp);
1567         hammer2_trans_init(dip->pmp, 0);
1568         hammer2_inode_lock(dip, 0);
1569
1570         /*
1571          * The unlink XOP unlinks the path from the directory and
1572          * locates and returns the cluster associated with the real inode.
1573          * We have to handle nlinks here on the frontend.
1574          */
1575         xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
1576         hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
1577         isopen = cache_isopen(ap->a_nch);
1578         xop->isdir = 0;
1579         xop->dopermanent = isopen ?  0 : HAMMER2_DELETE_PERMANENT;
1580         hammer2_xop_start(&xop->head, hammer2_xop_unlink);
1581
1582         /*
1583          * Collect the real inode and adjust nlinks, destroy the real
1584          * inode if nlinks transitions to 0 and it was the real inode
1585          * (else it has already been removed).
1586          */
1587         error = hammer2_xop_collect(&xop->head, 0);
1588         hammer2_inode_unlock(dip);
1589
1590         if (error == 0) {
1591                 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1);
1592                 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
1593                 if (ip) {
1594                         hammer2_inode_unlink_finisher(ip, isopen);
1595                         hammer2_inode_unlock(ip);
1596                 }
1597         } else {
1598                 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
1599         }
1600
1601         hammer2_inode_run_unlinkq(dip->pmp);
1602         hammer2_trans_done(dip->pmp);
1603         if (error == 0)
1604                 cache_unlink(ap->a_nch);
1605         LOCKSTOP;
1606         return (error);
1607 }
1608
1609 /*
1610  * hammer2_vop_nrmdir { nch, dvp, cred }
1611  */
1612 static
1613 int
1614 hammer2_vop_nrmdir(struct vop_nrmdir_args *ap)
1615 {
1616         hammer2_xop_unlink_t *xop;
1617         hammer2_inode_t *dip;
1618         hammer2_inode_t *ip;
1619         struct namecache *ncp;
1620         int isopen;
1621         int error;
1622
1623         LOCKSTART;
1624         dip = VTOI(ap->a_dvp);
1625         if (dip->pmp->ronly) {
1626                 LOCKSTOP;
1627                 return(EROFS);
1628         }
1629
1630         hammer2_pfs_memory_wait(dip->pmp);
1631         hammer2_trans_init(dip->pmp, 0);
1632         hammer2_inode_lock(dip, 0);
1633
1634         xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
1635
1636         ncp = ap->a_nch->ncp;
1637         hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
1638         isopen = cache_isopen(ap->a_nch);
1639         xop->isdir = 1;
1640         xop->dopermanent = isopen ?  0 : HAMMER2_DELETE_PERMANENT;
1641         hammer2_xop_start(&xop->head, hammer2_xop_unlink);
1642
1643         /*
1644          * Collect the real inode and adjust nlinks, destroy the real
1645          * inode if nlinks transitions to 0 and it was the real inode
1646          * (else it has already been removed).
1647          */
1648         error = hammer2_xop_collect(&xop->head, 0);
1649         hammer2_inode_unlock(dip);
1650
1651         if (error == 0) {
1652                 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1);
1653                 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
1654                 if (ip) {
1655                         hammer2_inode_unlink_finisher(ip, isopen);
1656                         hammer2_inode_unlock(ip);
1657                 }
1658         } else {
1659                 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
1660         }
1661         hammer2_inode_run_unlinkq(dip->pmp);
1662         hammer2_trans_done(dip->pmp);
1663         if (error == 0)
1664                 cache_unlink(ap->a_nch);
1665         LOCKSTOP;
1666         return (error);
1667 }
1668
1669 /*
1670  * hammer2_vop_nrename { fnch, tnch, fdvp, tdvp, cred }
1671  */
1672 static
1673 int
1674 hammer2_vop_nrename(struct vop_nrename_args *ap)
1675 {
1676         struct namecache *fncp;
1677         struct namecache *tncp;
1678         hammer2_inode_t *cdip;
1679         hammer2_inode_t *fdip;
1680         hammer2_inode_t *tdip;
1681         hammer2_inode_t *ip;
1682         const uint8_t *fname;
1683         size_t fname_len;
1684         const uint8_t *tname;
1685         size_t tname_len;
1686         int error;
1687         int tnch_error;
1688         hammer2_key_t tlhc;
1689
1690         if (ap->a_fdvp->v_mount != ap->a_tdvp->v_mount)
1691                 return(EXDEV);
1692         if (ap->a_fdvp->v_mount != ap->a_fnch->ncp->nc_vp->v_mount)
1693                 return(EXDEV);
1694
1695         fdip = VTOI(ap->a_fdvp);        /* source directory */
1696         tdip = VTOI(ap->a_tdvp);        /* target directory */
1697
1698         if (fdip->pmp->ronly)
1699                 return(EROFS);
1700
1701         LOCKSTART;
1702         fncp = ap->a_fnch->ncp;         /* entry name in source */
1703         fname = fncp->nc_name;
1704         fname_len = fncp->nc_nlen;
1705
1706         tncp = ap->a_tnch->ncp;         /* entry name in target */
1707         tname = tncp->nc_name;
1708         tname_len = tncp->nc_nlen;
1709
1710         hammer2_pfs_memory_wait(tdip->pmp);
1711         hammer2_trans_init(tdip->pmp, 0);
1712
1713         /*
1714          * ip is the inode being renamed.  If this is a hardlink then
1715          * ip represents the actual file and not the hardlink marker.
1716          */
1717         ip = VTOI(fncp->nc_vp);
1718
1719         /*
1720          * The common parent directory must be locked first to avoid deadlocks.
1721          * Also note that fdip and/or tdip might match cdip.
1722          */
1723         cdip = hammer2_inode_common_parent(ip->pip, tdip);
1724         hammer2_inode_lock(cdip, 0);
1725         hammer2_inode_lock(fdip, 0);
1726         hammer2_inode_lock(tdip, 0);
1727         hammer2_inode_ref(ip);          /* extra ref */
1728         error = 0;
1729
1730         /*
1731          * If ip is a hardlink target and fdip != cdip we must shift the
1732          * inode to cdip.
1733          */
1734         if (fdip != cdip &&
1735             (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) {
1736                 hammer2_xop_nlink_t *xop1;
1737
1738                 xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
1739                 hammer2_xop_setip2(&xop1->head, ip);
1740                 hammer2_xop_setip3(&xop1->head, cdip);
1741
1742                 hammer2_xop_start(&xop1->head, hammer2_xop_nlink);
1743                 error = hammer2_xop_collect(&xop1->head, 0);
1744                 hammer2_xop_retire(&xop1->head, HAMMER2_XOPMASK_VOP);
1745         }
1746
1747         /*
1748          * Delete the target namespace.
1749          */
1750         {
1751                 hammer2_xop_unlink_t *xop2;
1752                 hammer2_inode_t *tip;
1753                 int isopen;
1754
1755                 /*
1756                  * The unlink XOP unlinks the path from the directory and
1757                  * locates and returns the cluster associated with the real
1758                  * inode.  We have to handle nlinks here on the frontend.
1759                  */
1760                 xop2 = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING);
1761                 hammer2_xop_setname(&xop2->head, tname, tname_len);
1762                 isopen = cache_isopen(ap->a_tnch);
1763                 xop2->isdir = -1;
1764                 xop2->dopermanent = isopen ?  0 : HAMMER2_DELETE_PERMANENT;
1765                 hammer2_xop_start(&xop2->head, hammer2_xop_unlink);
1766
1767                 /*
1768                  * Collect the real inode and adjust nlinks, destroy the real
1769                  * inode if nlinks transitions to 0 and it was the real inode
1770                  * (else it has already been removed).
1771                  */
1772                 tnch_error = hammer2_xop_collect(&xop2->head, 0);
1773                 /* hammer2_inode_unlock(tdip); */
1774
1775                 if (tnch_error == 0) {
1776                         tip = hammer2_inode_get(tdip->pmp, NULL,
1777                                                 &xop2->head.cluster, -1);
1778                         hammer2_xop_retire(&xop2->head, HAMMER2_XOPMASK_VOP);
1779                         if (tip) {
1780                                 hammer2_inode_unlink_finisher(tip, isopen);
1781                                 hammer2_inode_unlock(tip);
1782                         }
1783                 } else {
1784                         hammer2_xop_retire(&xop2->head, HAMMER2_XOPMASK_VOP);
1785                 }
1786                 /* hammer2_inode_lock(tdip, 0); */
1787
1788                 if (tnch_error && tnch_error != ENOENT) {
1789                         error = tnch_error;
1790                         goto done2;
1791                 }
1792         }
1793
1794         /*
1795          * Resolve the collision space for (tdip, tname, tname_len)
1796          *
1797          * tdip must be held exclusively locked to prevent races.
1798          */
1799         {
1800                 hammer2_xop_scanlhc_t *sxop;
1801                 hammer2_tid_t lhcbase;
1802
1803                 tlhc = hammer2_dirhash(tname, tname_len);
1804                 lhcbase = tlhc;
1805                 sxop = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING);
1806                 sxop->lhc = tlhc;
1807                 hammer2_xop_start(&sxop->head, hammer2_xop_scanlhc);
1808                 while ((error = hammer2_xop_collect(&sxop->head, 0)) == 0) {
1809                         if (tlhc != sxop->head.cluster.focus->bref.key)
1810                                 break;
1811                         ++tlhc;
1812                 }
1813                 hammer2_xop_retire(&sxop->head, HAMMER2_XOPMASK_VOP);
1814
1815                 if (error) {
1816                         if (error != ENOENT)
1817                                 goto done2;
1818                         ++tlhc;
1819                         error = 0;
1820                 }
1821                 if ((lhcbase ^ tlhc) & ~HAMMER2_DIRHASH_LOMASK) {
1822                         error = ENOSPC;
1823                         goto done2;
1824                 }
1825         }
1826
1827         /*
1828          * Everything is setup, do the rename.
1829          *
1830          * We have to synchronize ip->meta to the underlying operation.
1831          *
1832          * NOTE: To avoid deadlocks we cannot lock (ip) while we are
1833          *       unlinking elements from their directories.  Locking
1834          *       the nlinks field does not lock the whole inode.
1835          */
1836         hammer2_inode_lock(ip, 0);
1837         if (error == 0) {
1838                 hammer2_xop_nrename_t *xop4;
1839
1840                 xop4 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
1841                 xop4->lhc = tlhc;
1842                 xop4->ip_key = ip->meta.name_key;
1843                 hammer2_xop_setip2(&xop4->head, ip);
1844                 hammer2_xop_setip3(&xop4->head, tdip);
1845                 hammer2_xop_setname(&xop4->head, fname, fname_len);
1846                 hammer2_xop_setname2(&xop4->head, tname, tname_len);
1847                 hammer2_xop_start(&xop4->head, hammer2_xop_nrename);
1848
1849                 error = hammer2_xop_collect(&xop4->head, 0);
1850                 hammer2_xop_retire(&xop4->head, HAMMER2_XOPMASK_VOP);
1851
1852                 if (error == ENOENT)
1853                         error = 0;
1854                 if (error == 0 &&
1855                     (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1856                         hammer2_inode_modify(ip);
1857                         ip->meta.name_len = tname_len;
1858                         ip->meta.name_key = tlhc;
1859
1860                 }
1861         }
1862
1863         /*
1864          * Fixup ip->pip if we were renaming the actual file and not a
1865          * hardlink pointer.
1866          */
1867         if (error == 0 && (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1868                 hammer2_inode_t *opip;
1869
1870                 if (ip->pip != tdip) {
1871                         hammer2_inode_ref(tdip);
1872                         opip = ip->pip;
1873                         ip->pip = tdip;
1874                         if (opip)
1875                                 hammer2_inode_drop(opip);
1876                 }
1877         }
1878         hammer2_inode_unlock(ip);
1879 done2:
1880         hammer2_inode_unlock(tdip);
1881         hammer2_inode_unlock(fdip);
1882         hammer2_inode_unlock(cdip);
1883         hammer2_inode_drop(ip);
1884         hammer2_inode_drop(cdip);
1885         hammer2_inode_run_unlinkq(fdip->pmp);
1886         hammer2_trans_done(tdip->pmp);
1887
1888         /*
1889          * Issue the namecache update after unlocking all the internal
1890          * hammer structures, otherwise we might deadlock.
1891          */
1892         if (tnch_error == 0) {
1893                 cache_unlink(ap->a_tnch);
1894                 cache_setunresolved(ap->a_tnch);
1895         }
1896         if (error == 0)
1897                 cache_rename(ap->a_fnch, ap->a_tnch);
1898
1899         LOCKSTOP;
1900         return (error);
1901 }
1902
1903 /*
1904  * hammer2_vop_ioctl { vp, command, data, fflag, cred }
1905  */
1906 static
1907 int
1908 hammer2_vop_ioctl(struct vop_ioctl_args *ap)
1909 {
1910         hammer2_inode_t *ip;
1911         int error;
1912
1913         LOCKSTART;
1914         ip = VTOI(ap->a_vp);
1915
1916         error = hammer2_ioctl(ip, ap->a_command, (void *)ap->a_data,
1917                               ap->a_fflag, ap->a_cred);
1918         LOCKSTOP;
1919         return (error);
1920 }
1921
1922 static
1923 int 
1924 hammer2_vop_mountctl(struct vop_mountctl_args *ap)
1925 {
1926         struct mount *mp;
1927         hammer2_pfs_t *pmp;
1928         int rc;
1929
1930         LOCKSTART;
1931         switch (ap->a_op) {
1932         case (MOUNTCTL_SET_EXPORT):
1933                 mp = ap->a_head.a_ops->head.vv_mount;
1934                 pmp = MPTOPMP(mp);
1935
1936                 if (ap->a_ctllen != sizeof(struct export_args))
1937                         rc = (EINVAL);
1938                 else
1939                         rc = vfs_export(mp, &pmp->export,
1940                                         (const struct export_args *)ap->a_ctl);
1941                 break;
1942         default:
1943                 rc = vop_stdmountctl(ap);
1944                 break;
1945         }
1946         LOCKSTOP;
1947         return (rc);
1948 }
1949
1950 /*
1951  * KQFILTER
1952  */
1953 static void filt_hammer2detach(struct knote *kn);
1954 static int filt_hammer2read(struct knote *kn, long hint);
1955 static int filt_hammer2write(struct knote *kn, long hint);
1956 static int filt_hammer2vnode(struct knote *kn, long hint);
1957
1958 static struct filterops hammer2read_filtops =
1959         { FILTEROP_ISFD | FILTEROP_MPSAFE,
1960           NULL, filt_hammer2detach, filt_hammer2read };
1961 static struct filterops hammer2write_filtops =
1962         { FILTEROP_ISFD | FILTEROP_MPSAFE,
1963           NULL, filt_hammer2detach, filt_hammer2write };
1964 static struct filterops hammer2vnode_filtops =
1965         { FILTEROP_ISFD | FILTEROP_MPSAFE,
1966           NULL, filt_hammer2detach, filt_hammer2vnode };
1967
1968 static
1969 int
1970 hammer2_vop_kqfilter(struct vop_kqfilter_args *ap)
1971 {
1972         struct vnode *vp = ap->a_vp;
1973         struct knote *kn = ap->a_kn;
1974
1975         switch (kn->kn_filter) {
1976         case EVFILT_READ:
1977                 kn->kn_fop = &hammer2read_filtops;
1978                 break;
1979         case EVFILT_WRITE:
1980                 kn->kn_fop = &hammer2write_filtops;
1981                 break;
1982         case EVFILT_VNODE:
1983                 kn->kn_fop = &hammer2vnode_filtops;
1984                 break;
1985         default:
1986                 return (EOPNOTSUPP);
1987         }
1988
1989         kn->kn_hook = (caddr_t)vp;
1990
1991         knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1992
1993         return(0);
1994 }
1995
1996 static void
1997 filt_hammer2detach(struct knote *kn)
1998 {
1999         struct vnode *vp = (void *)kn->kn_hook;
2000
2001         knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
2002 }
2003
2004 static int
2005 filt_hammer2read(struct knote *kn, long hint)
2006 {
2007         struct vnode *vp = (void *)kn->kn_hook;
2008         hammer2_inode_t *ip = VTOI(vp);
2009         off_t off;
2010
2011         if (hint == NOTE_REVOKE) {
2012                 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
2013                 return(1);
2014         }
2015         off = ip->meta.size - kn->kn_fp->f_offset;
2016         kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
2017         if (kn->kn_sfflags & NOTE_OLDAPI)
2018                 return(1);
2019         return (kn->kn_data != 0);
2020 }
2021
2022
2023 static int
2024 filt_hammer2write(struct knote *kn, long hint)
2025 {
2026         if (hint == NOTE_REVOKE)
2027                 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
2028         kn->kn_data = 0;
2029         return (1);
2030 }
2031
2032 static int
2033 filt_hammer2vnode(struct knote *kn, long hint)
2034 {
2035         if (kn->kn_sfflags & hint)
2036                 kn->kn_fflags |= hint;
2037         if (hint == NOTE_REVOKE) {
2038                 kn->kn_flags |= (EV_EOF | EV_NODATA);
2039                 return (1);
2040         }
2041         return (kn->kn_fflags != 0);
2042 }
2043
2044 /*
2045  * FIFO VOPS
2046  */
2047 static
2048 int
2049 hammer2_vop_markatime(struct vop_markatime_args *ap)
2050 {
2051         hammer2_inode_t *ip;
2052         struct vnode *vp;
2053
2054         vp = ap->a_vp;
2055         ip = VTOI(vp);
2056
2057         if (ip->pmp->ronly)
2058                 return(EROFS);
2059         return(0);
2060 }
2061
2062 static
2063 int
2064 hammer2_vop_fifokqfilter(struct vop_kqfilter_args *ap)
2065 {
2066         int error;
2067
2068         error = VOCALL(&fifo_vnode_vops, &ap->a_head);
2069         if (error)
2070                 error = hammer2_vop_kqfilter(ap);
2071         return(error);
2072 }
2073
2074 /*
2075  * VOPS vector
2076  */
2077 struct vop_ops hammer2_vnode_vops = {
2078         .vop_default    = vop_defaultop,
2079         .vop_fsync      = hammer2_vop_fsync,
2080         .vop_getpages   = vop_stdgetpages,
2081         .vop_putpages   = vop_stdputpages,
2082         .vop_access     = hammer2_vop_access,
2083         .vop_advlock    = hammer2_vop_advlock,
2084         .vop_close      = hammer2_vop_close,
2085         .vop_nlink      = hammer2_vop_nlink,
2086         .vop_ncreate    = hammer2_vop_ncreate,
2087         .vop_nsymlink   = hammer2_vop_nsymlink,
2088         .vop_nremove    = hammer2_vop_nremove,
2089         .vop_nrmdir     = hammer2_vop_nrmdir,
2090         .vop_nrename    = hammer2_vop_nrename,
2091         .vop_getattr    = hammer2_vop_getattr,
2092         .vop_setattr    = hammer2_vop_setattr,
2093         .vop_readdir    = hammer2_vop_readdir,
2094         .vop_readlink   = hammer2_vop_readlink,
2095         .vop_getpages   = vop_stdgetpages,
2096         .vop_putpages   = vop_stdputpages,
2097         .vop_read       = hammer2_vop_read,
2098         .vop_write      = hammer2_vop_write,
2099         .vop_open       = hammer2_vop_open,
2100         .vop_inactive   = hammer2_vop_inactive,
2101         .vop_reclaim    = hammer2_vop_reclaim,
2102         .vop_nresolve   = hammer2_vop_nresolve,
2103         .vop_nlookupdotdot = hammer2_vop_nlookupdotdot,
2104         .vop_nmkdir     = hammer2_vop_nmkdir,
2105         .vop_nmknod     = hammer2_vop_nmknod,
2106         .vop_ioctl      = hammer2_vop_ioctl,
2107         .vop_mountctl   = hammer2_vop_mountctl,
2108         .vop_bmap       = hammer2_vop_bmap,
2109         .vop_strategy   = hammer2_vop_strategy,
2110         .vop_kqfilter   = hammer2_vop_kqfilter
2111 };
2112
2113 struct vop_ops hammer2_spec_vops = {
2114         .vop_default =          vop_defaultop,
2115         .vop_fsync =            hammer2_vop_fsync,
2116         .vop_read =             vop_stdnoread,
2117         .vop_write =            vop_stdnowrite,
2118         .vop_access =           hammer2_vop_access,
2119         .vop_close =            hammer2_vop_close,
2120         .vop_markatime =        hammer2_vop_markatime,
2121         .vop_getattr =          hammer2_vop_getattr,
2122         .vop_inactive =         hammer2_vop_inactive,
2123         .vop_reclaim =          hammer2_vop_reclaim,
2124         .vop_setattr =          hammer2_vop_setattr
2125 };
2126
2127 struct vop_ops hammer2_fifo_vops = {
2128         .vop_default =          fifo_vnoperate,
2129         .vop_fsync =            hammer2_vop_fsync,
2130 #if 0
2131         .vop_read =             hammer2_vop_fiforead,
2132         .vop_write =            hammer2_vop_fifowrite,
2133 #endif
2134         .vop_access =           hammer2_vop_access,
2135 #if 0
2136         .vop_close =            hammer2_vop_fifoclose,
2137 #endif
2138         .vop_markatime =        hammer2_vop_markatime,
2139         .vop_getattr =          hammer2_vop_getattr,
2140         .vop_inactive =         hammer2_vop_inactive,
2141         .vop_reclaim =          hammer2_vop_reclaim,
2142         .vop_setattr =          hammer2_vop_setattr,
2143         .vop_kqfilter =         hammer2_vop_fifokqfilter
2144 };
2145