2 * Copyright (c) 2011-2015 The DragonFly Project. All rights reserved.
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)
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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.
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
37 * Per-node backend for kernel filesystem interface.
39 * This executes a VOP concurrently on multiple nodes, each node via its own
40 * thread, and competes to advance the original request. The original
41 * request is retired the moment all requirements are met, even if the
42 * operation is still in-progress on some nodes.
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/fcntl.h>
50 #include <sys/namei.h>
51 #include <sys/mount.h>
52 #include <sys/vnode.h>
53 #include <sys/mountctl.h>
54 #include <sys/dirent.h>
56 #include <sys/objcache.h>
57 #include <sys/event.h>
59 #include <vfs/fifofs/fifo.h>
64 hammer2_xop_readdir(hammer2_xop_t *arg, int clindex)
66 hammer2_xop_readdir_t *xop = &arg->xop_readdir;
67 hammer2_chain_t *parent;
68 hammer2_chain_t *chain;
69 hammer2_key_t key_next;
74 lkey = xop->head.lkey;
75 if (hammer2_debug & 0x0020)
76 kprintf("xop_readdir %p lkey=%016jx\n", xop, lkey);
79 * The inode's chain is the iterator. If we cannot acquire it our
80 * contribution ends here.
82 parent = hammer2_inode_chain(xop->head.ip, clindex,
83 HAMMER2_RESOLVE_ALWAYS |
84 HAMMER2_RESOLVE_SHARED);
86 kprintf("xop_readdir: NULL parent\n");
91 * Directory scan [re]start and loop, the feed inherits the chain's
92 * lock so do not unlock it on the iteration.
94 chain = hammer2_chain_lookup(&parent, &key_next, lkey, lkey,
95 &cache_index, HAMMER2_LOOKUP_SHARED);
97 chain = hammer2_chain_lookup(&parent, &key_next,
98 lkey, (hammer2_key_t)-1,
100 HAMMER2_LOOKUP_SHARED);
103 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
106 chain = hammer2_chain_next(&parent, chain, &key_next,
107 key_next, (hammer2_key_t)-1,
109 HAMMER2_LOOKUP_SHARED |
110 HAMMER2_LOOKUP_NOUNLOCK);
113 hammer2_chain_drop(chain);
114 hammer2_chain_unlock(parent);
115 hammer2_chain_drop(parent);
117 hammer2_xop_feed(&xop->head, NULL, clindex, error);
121 hammer2_xop_nresolve(hammer2_xop_t *arg, int clindex)
123 hammer2_xop_nresolve_t *xop = &arg->xop_nresolve;
124 hammer2_chain_t *parent;
125 hammer2_chain_t *chain;
126 const hammer2_inode_data_t *ripdata;
129 hammer2_key_t key_next;
131 int cache_index = -1; /* XXX */
134 parent = hammer2_inode_chain(xop->head.ip, clindex,
135 HAMMER2_RESOLVE_ALWAYS |
136 HAMMER2_RESOLVE_SHARED);
137 if (parent == NULL) {
138 kprintf("xop_nresolve: NULL parent\n");
143 name = xop->head.name;
144 name_len = xop->head.name_len;
147 * Lookup the directory entry
149 lhc = hammer2_dirhash(name, name_len);
150 chain = hammer2_chain_lookup(&parent, &key_next,
151 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
153 HAMMER2_LOOKUP_ALWAYS |
154 HAMMER2_LOOKUP_SHARED);
156 ripdata = &chain->data->ipdata;
157 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
158 ripdata->meta.name_len == name_len &&
159 bcmp(ripdata->filename, name, name_len) == 0) {
162 chain = hammer2_chain_next(&parent, chain, &key_next,
164 lhc + HAMMER2_DIRHASH_LOMASK,
166 HAMMER2_LOOKUP_ALWAYS |
167 HAMMER2_LOOKUP_SHARED);
171 * If the entry is a hardlink pointer, resolve it.
175 if (chain->data->ipdata.meta.type == HAMMER2_OBJTYPE_HARDLINK) {
176 error = hammer2_chain_hardlink_find(xop->head.ip,
182 error = hammer2_xop_feed(&xop->head, chain, clindex, error);
184 hammer2_chain_drop(chain);
186 hammer2_chain_unlock(parent);
187 hammer2_chain_drop(parent);
192 * Directory collision resolver scan helper (backend, threaded).
194 * Used by the inode create code to locate an unused lhc.
197 hammer2_inode_xop_scanlhc(hammer2_xop_t *arg, int clindex)
199 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
200 hammer2_chain_t *parent;
201 hammer2_chain_t *chain;
202 hammer2_key_t key_next;
203 int cache_index = -1; /* XXX */
206 parent = hammer2_inode_chain(xop->head.ip, clindex,
207 HAMMER2_RESOLVE_ALWAYS |
208 HAMMER2_RESOLVE_SHARED);
209 if (parent == NULL) {
210 kprintf("xop_nresolve: NULL parent\n");
217 * Lookup all possibly conflicting directory entries, the feed
218 * inherits the chain's lock so do not unlock it on the iteration.
220 chain = hammer2_chain_lookup(&parent, &key_next,
222 xop->lhc + HAMMER2_DIRHASH_LOMASK,
224 HAMMER2_LOOKUP_ALWAYS |
225 HAMMER2_LOOKUP_SHARED);
227 error = hammer2_xop_feed(&xop->head, chain, clindex,
230 hammer2_chain_drop(chain);
231 chain = NULL; /* safety */
234 chain = hammer2_chain_next(&parent, chain, &key_next,
236 xop->lhc + HAMMER2_DIRHASH_LOMASK,
238 HAMMER2_LOOKUP_ALWAYS |
239 HAMMER2_LOOKUP_SHARED |
240 HAMMER2_LOOKUP_NOUNLOCK);
243 hammer2_xop_feed(&xop->head, NULL, clindex, error);
245 hammer2_chain_unlock(parent);
246 hammer2_chain_drop(parent);