author | ek110237 |
Wed, 24 Oct 2007 16:54:46 -0700 | |
changeset 5326 | 6752aa2bd5bc |
parent 4831 | 41ec732c6d9f |
child 5331 | 3047ad28a67b |
permissions | -rw-r--r-- |
789 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1544 | 5 |
* Common Development and Distribution License (the "License"). |
6 |
* You may not use this file except in compliance with the License. |
|
789 | 7 |
* |
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
21 |
/* |
|
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
22 |
* Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
789 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
4144
068f395736ad
6465105 ZFS does not update timestamps upon the creat() of an existing file
peteh
parents:
4105
diff
changeset
|
26 |
/* Portions Copyright 2007 Jeremy Teo */ |
068f395736ad
6465105 ZFS does not update timestamps upon the creat() of an existing file
peteh
parents:
4105
diff
changeset
|
27 |
|
789 | 28 |
#pragma ident "%Z%%M% %I% %E% SMI" |
29 |
||
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
30 |
#ifdef _KERNEL |
789 | 31 |
#include <sys/types.h> |
32 |
#include <sys/param.h> |
|
33 |
#include <sys/time.h> |
|
34 |
#include <sys/systm.h> |
|
35 |
#include <sys/sysmacros.h> |
|
36 |
#include <sys/resource.h> |
|
37 |
#include <sys/mntent.h> |
|
1816
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
38 |
#include <sys/mkdev.h> |
789 | 39 |
#include <sys/vfs.h> |
3898
c788126f2a20
PSARC/2007/124 Strong Type-Checking for VFS Operation Registration Mechanism
rsb
parents:
3897
diff
changeset
|
40 |
#include <sys/vfs_opreg.h> |
789 | 41 |
#include <sys/vnode.h> |
42 |
#include <sys/file.h> |
|
43 |
#include <sys/kmem.h> |
|
44 |
#include <sys/errno.h> |
|
45 |
#include <sys/unistd.h> |
|
46 |
#include <sys/mode.h> |
|
47 |
#include <sys/atomic.h> |
|
48 |
#include <vm/pvn.h> |
|
49 |
#include "fs/fs_subr.h" |
|
50 |
#include <sys/zfs_dir.h> |
|
51 |
#include <sys/zfs_acl.h> |
|
52 |
#include <sys/zfs_ioctl.h> |
|
1669 | 53 |
#include <sys/zfs_rlock.h> |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
54 |
#include <sys/fs/zfs.h> |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
55 |
#endif /* _KERNEL */ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
56 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
57 |
#include <sys/dmu.h> |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
58 |
#include <sys/refcount.h> |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
59 |
#include <sys/stat.h> |
789 | 60 |
#include <sys/zap.h> |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
61 |
#include <sys/zfs_znode.h> |
789 | 62 |
|
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
63 |
/* |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
64 |
* Functions needed for userland (ie: libzpool) are not put under |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
65 |
* #ifdef_KERNEL; the rest of the functions have dependencies |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
66 |
* (such as VFS logic) that will not compile easily in userland. |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
67 |
*/ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
68 |
#ifdef _KERNEL |
789 | 69 |
struct kmem_cache *znode_cache = NULL; |
70 |
||
71 |
/*ARGSUSED*/ |
|
72 |
static void |
|
73 |
znode_pageout_func(dmu_buf_t *dbuf, void *user_ptr) |
|
74 |
{ |
|
75 |
znode_t *zp = user_ptr; |
|
76 |
vnode_t *vp = ZTOV(zp); |
|
77 |
||
1544 | 78 |
mutex_enter(&zp->z_lock); |
789 | 79 |
if (vp->v_count == 0) { |
1544 | 80 |
mutex_exit(&zp->z_lock); |
789 | 81 |
vn_invalid(vp); |
82 |
zfs_znode_free(zp); |
|
1544 | 83 |
} else { |
84 |
/* signal force unmount that this znode can be freed */ |
|
85 |
zp->z_dbuf = NULL; |
|
86 |
mutex_exit(&zp->z_lock); |
|
789 | 87 |
} |
88 |
} |
|
89 |
||
90 |
/*ARGSUSED*/ |
|
91 |
static int |
|
92 |
zfs_znode_cache_constructor(void *buf, void *cdrarg, int kmflags) |
|
93 |
{ |
|
94 |
znode_t *zp = buf; |
|
95 |
||
96 |
zp->z_vnode = vn_alloc(KM_SLEEP); |
|
97 |
zp->z_vnode->v_data = (caddr_t)zp; |
|
98 |
mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL); |
|
99 |
rw_init(&zp->z_map_lock, NULL, RW_DEFAULT, NULL); |
|
1669 | 100 |
rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL); |
3897
278bade789ba
6437750 panic: db->db_buf==0||arc_referenced(db->db_buf), file: dbuf.c,line:1539
maybee
parents:
3461
diff
changeset
|
101 |
rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL); |
789 | 102 |
mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL); |
1669 | 103 |
|
104 |
mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL); |
|
105 |
avl_create(&zp->z_range_avl, zfs_range_compare, |
|
106 |
sizeof (rl_t), offsetof(rl_t, r_node)); |
|
107 |
||
789 | 108 |
zp->z_dbuf_held = 0; |
109 |
zp->z_dirlocks = 0; |
|
110 |
return (0); |
|
111 |
} |
|
112 |
||
113 |
/*ARGSUSED*/ |
|
114 |
static void |
|
115 |
zfs_znode_cache_destructor(void *buf, void *cdarg) |
|
116 |
{ |
|
117 |
znode_t *zp = buf; |
|
118 |
||
119 |
ASSERT(zp->z_dirlocks == 0); |
|
120 |
mutex_destroy(&zp->z_lock); |
|
121 |
rw_destroy(&zp->z_map_lock); |
|
1669 | 122 |
rw_destroy(&zp->z_parent_lock); |
3897
278bade789ba
6437750 panic: db->db_buf==0||arc_referenced(db->db_buf), file: dbuf.c,line:1539
maybee
parents:
3461
diff
changeset
|
123 |
rw_destroy(&zp->z_name_lock); |
789 | 124 |
mutex_destroy(&zp->z_acl_lock); |
1669 | 125 |
avl_destroy(&zp->z_range_avl); |
4831
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
126 |
mutex_destroy(&zp->z_range_lock); |
789 | 127 |
|
128 |
ASSERT(zp->z_dbuf_held == 0); |
|
129 |
ASSERT(ZTOV(zp)->v_count == 0); |
|
130 |
vn_free(ZTOV(zp)); |
|
131 |
} |
|
132 |
||
133 |
void |
|
134 |
zfs_znode_init(void) |
|
135 |
{ |
|
136 |
/* |
|
137 |
* Initialize zcache |
|
138 |
*/ |
|
139 |
ASSERT(znode_cache == NULL); |
|
140 |
znode_cache = kmem_cache_create("zfs_znode_cache", |
|
141 |
sizeof (znode_t), 0, zfs_znode_cache_constructor, |
|
142 |
zfs_znode_cache_destructor, NULL, NULL, NULL, 0); |
|
143 |
} |
|
144 |
||
145 |
void |
|
146 |
zfs_znode_fini(void) |
|
147 |
{ |
|
148 |
/* |
|
149 |
* Cleanup vfs & vnode ops |
|
150 |
*/ |
|
151 |
zfs_remove_op_tables(); |
|
152 |
||
153 |
/* |
|
154 |
* Cleanup zcache |
|
155 |
*/ |
|
156 |
if (znode_cache) |
|
157 |
kmem_cache_destroy(znode_cache); |
|
158 |
znode_cache = NULL; |
|
159 |
} |
|
160 |
||
161 |
struct vnodeops *zfs_dvnodeops; |
|
162 |
struct vnodeops *zfs_fvnodeops; |
|
163 |
struct vnodeops *zfs_symvnodeops; |
|
164 |
struct vnodeops *zfs_xdvnodeops; |
|
165 |
struct vnodeops *zfs_evnodeops; |
|
166 |
||
167 |
void |
|
168 |
zfs_remove_op_tables() |
|
169 |
{ |
|
170 |
/* |
|
171 |
* Remove vfs ops |
|
172 |
*/ |
|
173 |
ASSERT(zfsfstype); |
|
174 |
(void) vfs_freevfsops_by_type(zfsfstype); |
|
175 |
zfsfstype = 0; |
|
176 |
||
177 |
/* |
|
178 |
* Remove vnode ops |
|
179 |
*/ |
|
180 |
if (zfs_dvnodeops) |
|
181 |
vn_freevnodeops(zfs_dvnodeops); |
|
182 |
if (zfs_fvnodeops) |
|
183 |
vn_freevnodeops(zfs_fvnodeops); |
|
184 |
if (zfs_symvnodeops) |
|
185 |
vn_freevnodeops(zfs_symvnodeops); |
|
186 |
if (zfs_xdvnodeops) |
|
187 |
vn_freevnodeops(zfs_xdvnodeops); |
|
188 |
if (zfs_evnodeops) |
|
189 |
vn_freevnodeops(zfs_evnodeops); |
|
190 |
||
191 |
zfs_dvnodeops = NULL; |
|
192 |
zfs_fvnodeops = NULL; |
|
193 |
zfs_symvnodeops = NULL; |
|
194 |
zfs_xdvnodeops = NULL; |
|
195 |
zfs_evnodeops = NULL; |
|
196 |
} |
|
197 |
||
198 |
extern const fs_operation_def_t zfs_dvnodeops_template[]; |
|
199 |
extern const fs_operation_def_t zfs_fvnodeops_template[]; |
|
200 |
extern const fs_operation_def_t zfs_xdvnodeops_template[]; |
|
201 |
extern const fs_operation_def_t zfs_symvnodeops_template[]; |
|
202 |
extern const fs_operation_def_t zfs_evnodeops_template[]; |
|
203 |
||
204 |
int |
|
205 |
zfs_create_op_tables() |
|
206 |
{ |
|
207 |
int error; |
|
208 |
||
209 |
/* |
|
210 |
* zfs_dvnodeops can be set if mod_remove() calls mod_installfs() |
|
211 |
* due to a failure to remove the the 2nd modlinkage (zfs_modldrv). |
|
212 |
* In this case we just return as the ops vectors are already set up. |
|
213 |
*/ |
|
214 |
if (zfs_dvnodeops) |
|
215 |
return (0); |
|
216 |
||
217 |
error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template, |
|
218 |
&zfs_dvnodeops); |
|
219 |
if (error) |
|
220 |
return (error); |
|
221 |
||
222 |
error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template, |
|
223 |
&zfs_fvnodeops); |
|
224 |
if (error) |
|
225 |
return (error); |
|
226 |
||
227 |
error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template, |
|
228 |
&zfs_symvnodeops); |
|
229 |
if (error) |
|
230 |
return (error); |
|
231 |
||
232 |
error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template, |
|
233 |
&zfs_xdvnodeops); |
|
234 |
if (error) |
|
235 |
return (error); |
|
236 |
||
237 |
error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template, |
|
238 |
&zfs_evnodeops); |
|
239 |
||
240 |
return (error); |
|
241 |
} |
|
242 |
||
243 |
/* |
|
244 |
* zfs_init_fs - Initialize the zfsvfs struct and the file system |
|
245 |
* incore "master" object. Verify version compatibility. |
|
246 |
*/ |
|
247 |
int |
|
248 |
zfs_init_fs(zfsvfs_t *zfsvfs, znode_t **zpp, cred_t *cr) |
|
249 |
{ |
|
250 |
extern int zfsfstype; |
|
251 |
||
252 |
objset_t *os = zfsvfs->z_os; |
|
253 |
int i, error; |
|
254 |
dmu_object_info_t doi; |
|
2885 | 255 |
uint64_t fsid_guid; |
789 | 256 |
|
257 |
*zpp = NULL; |
|
258 |
||
259 |
/* |
|
260 |
* XXX - hack to auto-create the pool root filesystem at |
|
261 |
* the first attempted mount. |
|
262 |
*/ |
|
263 |
if (dmu_object_info(os, MASTER_NODE_OBJ, &doi) == ENOENT) { |
|
264 |
dmu_tx_t *tx = dmu_tx_create(os); |
|
265 |
||
1544 | 266 |
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, NULL); /* master */ |
267 |
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, NULL); /* del queue */ |
|
789 | 268 |
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); /* root node */ |
269 |
error = dmu_tx_assign(tx, TXG_WAIT); |
|
270 |
ASSERT3U(error, ==, 0); |
|
4577 | 271 |
zfs_create_fs(os, cr, ZPL_VERSION, tx); |
789 | 272 |
dmu_tx_commit(tx); |
273 |
} |
|
274 |
||
4577 | 275 |
error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1, |
276 |
&zfsvfs->z_version); |
|
1544 | 277 |
if (error) { |
278 |
return (error); |
|
4577 | 279 |
} else if (zfsvfs->z_version > ZPL_VERSION) { |
789 | 280 |
(void) printf("Mismatched versions: File system " |
281 |
"is version %lld on-disk format, which is " |
|
282 |
"incompatible with this software version %lld!", |
|
4577 | 283 |
(u_longlong_t)zfsvfs->z_version, ZPL_VERSION); |
789 | 284 |
return (ENOTSUP); |
285 |
} |
|
286 |
||
287 |
/* |
|
288 |
* The fsid is 64 bits, composed of an 8-bit fs type, which |
|
289 |
* separates our fsid from any other filesystem types, and a |
|
290 |
* 56-bit objset unique ID. The objset unique ID is unique to |
|
291 |
* all objsets open on this system, provided by unique_create(). |
|
292 |
* The 8-bit fs type must be put in the low bits of fsid[1] |
|
293 |
* because that's where other Solaris filesystems put it. |
|
294 |
*/ |
|
2885 | 295 |
fsid_guid = dmu_objset_fsid_guid(os); |
296 |
ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0); |
|
297 |
zfsvfs->z_vfs->vfs_fsid.val[0] = fsid_guid; |
|
298 |
zfsvfs->z_vfs->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) | |
|
789 | 299 |
zfsfstype & 0xFF; |
300 |
||
3461 | 301 |
error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, |
302 |
&zfsvfs->z_root); |
|
1544 | 303 |
if (error) |
304 |
return (error); |
|
3461 | 305 |
ASSERT(zfsvfs->z_root != 0); |
789 | 306 |
|
4831
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
307 |
error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1, |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
308 |
&zfsvfs->z_unlinkedobj); |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
309 |
if (error) |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
310 |
return (error); |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
311 |
|
789 | 312 |
/* |
313 |
* Initialize zget mutex's |
|
314 |
*/ |
|
315 |
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) |
|
316 |
mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); |
|
317 |
||
3461 | 318 |
error = zfs_zget(zfsvfs, zfsvfs->z_root, zpp); |
4831
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
319 |
if (error) { |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
320 |
/* |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
321 |
* On error, we destroy the mutexes here since it's not |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
322 |
* possible for the caller to determine if the mutexes were |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
323 |
* initialized properly. |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
324 |
*/ |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
325 |
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) |
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
326 |
mutex_destroy(&zfsvfs->z_hold_mtx[i]); |
1544 | 327 |
return (error); |
4831
41ec732c6d9f
6584470 zdb needs to initialize the bpl_lock mutex
gw25295
parents:
4577
diff
changeset
|
328 |
} |
3461 | 329 |
ASSERT3U((*zpp)->z_id, ==, zfsvfs->z_root); |
789 | 330 |
return (0); |
331 |
} |
|
332 |
||
333 |
/* |
|
1816
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
334 |
* define a couple of values we need available |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
335 |
* for both 64 and 32 bit environments. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
336 |
*/ |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
337 |
#ifndef NBITSMINOR64 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
338 |
#define NBITSMINOR64 32 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
339 |
#endif |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
340 |
#ifndef MAXMAJ64 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
341 |
#define MAXMAJ64 0xffffffffUL |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
342 |
#endif |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
343 |
#ifndef MAXMIN64 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
344 |
#define MAXMIN64 0xffffffffUL |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
345 |
#endif |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
346 |
|
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
347 |
/* |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
348 |
* Create special expldev for ZFS private use. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
349 |
* Can't use standard expldev since it doesn't do |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
350 |
* what we want. The standard expldev() takes a |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
351 |
* dev32_t in LP64 and expands it to a long dev_t. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
352 |
* We need an interface that takes a dev32_t in ILP32 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
353 |
* and expands it to a long dev_t. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
354 |
*/ |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
355 |
static uint64_t |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
356 |
zfs_expldev(dev_t dev) |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
357 |
{ |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
358 |
#ifndef _LP64 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
359 |
major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32; |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
360 |
return (((uint64_t)major << NBITSMINOR64) | |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
361 |
((minor_t)dev & MAXMIN32)); |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
362 |
#else |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
363 |
return (dev); |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
364 |
#endif |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
365 |
} |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
366 |
|
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
367 |
/* |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
368 |
* Special cmpldev for ZFS private use. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
369 |
* Can't use standard cmpldev since it takes |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
370 |
* a long dev_t and compresses it to dev32_t in |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
371 |
* LP64. We need to do a compaction of a long dev_t |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
372 |
* to a dev32_t in ILP32. |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
373 |
*/ |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
374 |
dev_t |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
375 |
zfs_cmpldev(uint64_t dev) |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
376 |
{ |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
377 |
#ifndef _LP64 |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
378 |
minor_t minor = (minor_t)dev & MAXMIN64; |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
379 |
major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64; |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
380 |
|
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
381 |
if (major > MAXMAJ32 || minor > MAXMIN32) |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
382 |
return (NODEV32); |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
383 |
|
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
384 |
return (((dev32_t)major << NBITSMINOR32) | minor); |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
385 |
#else |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
386 |
return (dev); |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
387 |
#endif |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
388 |
} |
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
389 |
|
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
390 |
/* |
789 | 391 |
* Construct a new znode/vnode and intialize. |
392 |
* |
|
393 |
* This does not do a call to dmu_set_user() that is |
|
394 |
* up to the caller to do, in case you don't want to |
|
395 |
* return the znode |
|
396 |
*/ |
|
1544 | 397 |
static znode_t * |
789 | 398 |
zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, uint64_t obj_num, int blksz) |
399 |
{ |
|
400 |
znode_t *zp; |
|
401 |
vnode_t *vp; |
|
402 |
||
403 |
zp = kmem_cache_alloc(znode_cache, KM_SLEEP); |
|
404 |
||
405 |
ASSERT(zp->z_dirlocks == NULL); |
|
406 |
||
407 |
zp->z_phys = db->db_data; |
|
408 |
zp->z_zfsvfs = zfsvfs; |
|
3461 | 409 |
zp->z_unlinked = 0; |
789 | 410 |
zp->z_atime_dirty = 0; |
411 |
zp->z_dbuf_held = 0; |
|
412 |
zp->z_mapcnt = 0; |
|
413 |
zp->z_last_itx = 0; |
|
414 |
zp->z_dbuf = db; |
|
415 |
zp->z_id = obj_num; |
|
416 |
zp->z_blksz = blksz; |
|
417 |
zp->z_seq = 0x7A4653; |
|
3063
b252896b372b
6341569 zio_alloc_blk() vdev distribution performs badly
perrin
parents:
2885
diff
changeset
|
418 |
zp->z_sync_cnt = 0; |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
419 |
zp->z_gen = zp->z_phys->zp_gen; |
789 | 420 |
|
421 |
mutex_enter(&zfsvfs->z_znodes_lock); |
|
422 |
list_insert_tail(&zfsvfs->z_all_znodes, zp); |
|
423 |
mutex_exit(&zfsvfs->z_znodes_lock); |
|
424 |
||
425 |
vp = ZTOV(zp); |
|
426 |
vn_reinit(vp); |
|
427 |
||
428 |
vp->v_vfsp = zfsvfs->z_parent->z_vfs; |
|
429 |
vp->v_type = IFTOVT((mode_t)zp->z_phys->zp_mode); |
|
430 |
||
431 |
switch (vp->v_type) { |
|
432 |
case VDIR: |
|
433 |
if (zp->z_phys->zp_flags & ZFS_XATTR) { |
|
434 |
vn_setops(vp, zfs_xdvnodeops); |
|
435 |
vp->v_flag |= V_XATTRDIR; |
|
436 |
} else |
|
437 |
vn_setops(vp, zfs_dvnodeops); |
|
869
dc133b87dfb3
6297285 znode prefetching in zfs_readdir causes 5x performance degradation for 'ls'
perrin
parents:
789
diff
changeset
|
438 |
zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */ |
789 | 439 |
break; |
440 |
case VBLK: |
|
441 |
case VCHR: |
|
1816
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
442 |
vp->v_rdev = zfs_cmpldev(zp->z_phys->zp_rdev); |
789 | 443 |
/*FALLTHROUGH*/ |
444 |
case VFIFO: |
|
445 |
case VSOCK: |
|
446 |
case VDOOR: |
|
447 |
vn_setops(vp, zfs_fvnodeops); |
|
448 |
break; |
|
449 |
case VREG: |
|
450 |
vp->v_flag |= VMODSORT; |
|
451 |
vn_setops(vp, zfs_fvnodeops); |
|
452 |
break; |
|
453 |
case VLNK: |
|
454 |
vn_setops(vp, zfs_symvnodeops); |
|
455 |
break; |
|
456 |
default: |
|
457 |
vn_setops(vp, zfs_evnodeops); |
|
458 |
break; |
|
459 |
} |
|
460 |
||
461 |
return (zp); |
|
462 |
} |
|
463 |
||
464 |
static void |
|
465 |
zfs_znode_dmu_init(znode_t *zp) |
|
466 |
{ |
|
467 |
znode_t *nzp; |
|
468 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
|
469 |
dmu_buf_t *db = zp->z_dbuf; |
|
470 |
||
471 |
mutex_enter(&zp->z_lock); |
|
472 |
||
4105
d90754357495
6543706 znodes should be immediatley freed, allowing the ARC to hold onto less memory
ek110237
parents:
3898
diff
changeset
|
473 |
nzp = dmu_buf_set_user_ie(db, zp, &zp->z_phys, znode_pageout_func); |
789 | 474 |
|
475 |
/* |
|
476 |
* there should be no |
|
477 |
* concurrent zgets on this object. |
|
478 |
*/ |
|
479 |
ASSERT3P(nzp, ==, NULL); |
|
480 |
||
481 |
/* |
|
482 |
* Slap on VROOT if we are the root znode |
|
483 |
*/ |
|
484 |
if (zp->z_id == zfsvfs->z_root) { |
|
485 |
ZTOV(zp)->v_flag |= VROOT; |
|
486 |
} |
|
487 |
||
488 |
ASSERT(zp->z_dbuf_held == 0); |
|
489 |
zp->z_dbuf_held = 1; |
|
490 |
VFS_HOLD(zfsvfs->z_vfs); |
|
491 |
mutex_exit(&zp->z_lock); |
|
492 |
vn_exists(ZTOV(zp)); |
|
493 |
} |
|
494 |
||
495 |
/* |
|
496 |
* Create a new DMU object to hold a zfs znode. |
|
497 |
* |
|
498 |
* IN: dzp - parent directory for new znode |
|
499 |
* vap - file attributes for new znode |
|
500 |
* tx - dmu transaction id for zap operations |
|
501 |
* cr - credentials of caller |
|
502 |
* flag - flags: |
|
503 |
* IS_ROOT_NODE - new object will be root |
|
504 |
* IS_XATTR - new object is an attribute |
|
505 |
* IS_REPLAY - intent log replay |
|
506 |
* |
|
507 |
* OUT: oid - ID of created object |
|
508 |
* |
|
509 |
*/ |
|
510 |
void |
|
511 |
zfs_mknode(znode_t *dzp, vattr_t *vap, uint64_t *oid, dmu_tx_t *tx, cred_t *cr, |
|
512 |
uint_t flag, znode_t **zpp, int bonuslen) |
|
513 |
{ |
|
514 |
dmu_buf_t *dbp; |
|
515 |
znode_phys_t *pzp; |
|
516 |
znode_t *zp; |
|
517 |
zfsvfs_t *zfsvfs = dzp->z_zfsvfs; |
|
518 |
timestruc_t now; |
|
519 |
uint64_t gen; |
|
520 |
int err; |
|
521 |
||
522 |
ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); |
|
523 |
||
524 |
if (zfsvfs->z_assign >= TXG_INITIAL) { /* ZIL replay */ |
|
525 |
*oid = vap->va_nodeid; |
|
526 |
flag |= IS_REPLAY; |
|
527 |
now = vap->va_ctime; /* see zfs_replay_create() */ |
|
528 |
gen = vap->va_nblocks; /* ditto */ |
|
529 |
} else { |
|
530 |
*oid = 0; |
|
531 |
gethrestime(&now); |
|
532 |
gen = dmu_tx_get_txg(tx); |
|
533 |
} |
|
534 |
||
535 |
/* |
|
536 |
* Create a new DMU object. |
|
537 |
*/ |
|
1544 | 538 |
/* |
539 |
* There's currently no mechanism for pre-reading the blocks that will |
|
540 |
* be to needed allocate a new object, so we accept the small chance |
|
541 |
* that there will be an i/o error and we will fail one of the |
|
542 |
* assertions below. |
|
543 |
*/ |
|
789 | 544 |
if (vap->va_type == VDIR) { |
545 |
if (flag & IS_REPLAY) { |
|
546 |
err = zap_create_claim(zfsvfs->z_os, *oid, |
|
547 |
DMU_OT_DIRECTORY_CONTENTS, |
|
548 |
DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx); |
|
549 |
ASSERT3U(err, ==, 0); |
|
550 |
} else { |
|
551 |
*oid = zap_create(zfsvfs->z_os, |
|
552 |
DMU_OT_DIRECTORY_CONTENTS, |
|
553 |
DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx); |
|
554 |
} |
|
555 |
} else { |
|
556 |
if (flag & IS_REPLAY) { |
|
557 |
err = dmu_object_claim(zfsvfs->z_os, *oid, |
|
558 |
DMU_OT_PLAIN_FILE_CONTENTS, 0, |
|
559 |
DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx); |
|
560 |
ASSERT3U(err, ==, 0); |
|
561 |
} else { |
|
562 |
*oid = dmu_object_alloc(zfsvfs->z_os, |
|
563 |
DMU_OT_PLAIN_FILE_CONTENTS, 0, |
|
564 |
DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx); |
|
565 |
} |
|
566 |
} |
|
1544 | 567 |
VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, *oid, NULL, &dbp)); |
789 | 568 |
dmu_buf_will_dirty(dbp, tx); |
569 |
||
570 |
/* |
|
571 |
* Initialize the znode physical data to zero. |
|
572 |
*/ |
|
573 |
ASSERT(dbp->db_size >= sizeof (znode_phys_t)); |
|
574 |
bzero(dbp->db_data, dbp->db_size); |
|
575 |
pzp = dbp->db_data; |
|
576 |
||
577 |
/* |
|
578 |
* If this is the root, fix up the half-initialized parent pointer |
|
579 |
* to reference the just-allocated physical data area. |
|
580 |
*/ |
|
581 |
if (flag & IS_ROOT_NODE) { |
|
582 |
dzp->z_phys = pzp; |
|
583 |
dzp->z_id = *oid; |
|
584 |
} |
|
585 |
||
586 |
/* |
|
587 |
* If parent is an xattr, so am I. |
|
588 |
*/ |
|
589 |
if (dzp->z_phys->zp_flags & ZFS_XATTR) |
|
590 |
flag |= IS_XATTR; |
|
591 |
||
592 |
if (vap->va_type == VBLK || vap->va_type == VCHR) { |
|
1816
8c14b56c8515
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
marks
parents:
1760
diff
changeset
|
593 |
pzp->zp_rdev = zfs_expldev(vap->va_rdev); |
789 | 594 |
} |
595 |
||
596 |
if (vap->va_type == VDIR) { |
|
597 |
pzp->zp_size = 2; /* contents ("." and "..") */ |
|
598 |
pzp->zp_links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1; |
|
599 |
} |
|
600 |
||
601 |
pzp->zp_parent = dzp->z_id; |
|
602 |
if (flag & IS_XATTR) |
|
603 |
pzp->zp_flags |= ZFS_XATTR; |
|
604 |
||
605 |
pzp->zp_gen = gen; |
|
606 |
||
607 |
ZFS_TIME_ENCODE(&now, pzp->zp_crtime); |
|
608 |
ZFS_TIME_ENCODE(&now, pzp->zp_ctime); |
|
609 |
||
610 |
if (vap->va_mask & AT_ATIME) { |
|
611 |
ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); |
|
612 |
} else { |
|
613 |
ZFS_TIME_ENCODE(&now, pzp->zp_atime); |
|
614 |
} |
|
615 |
||
616 |
if (vap->va_mask & AT_MTIME) { |
|
617 |
ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime); |
|
618 |
} else { |
|
619 |
ZFS_TIME_ENCODE(&now, pzp->zp_mtime); |
|
620 |
} |
|
621 |
||
622 |
pzp->zp_mode = MAKEIMODE(vap->va_type, vap->va_mode); |
|
623 |
zp = zfs_znode_alloc(zfsvfs, dbp, *oid, 0); |
|
624 |
||
625 |
zfs_perm_init(zp, dzp, flag, vap, tx, cr); |
|
626 |
||
627 |
if (zpp) { |
|
628 |
kmutex_t *hash_mtx = ZFS_OBJ_MUTEX(zp); |
|
629 |
||
630 |
mutex_enter(hash_mtx); |
|
631 |
zfs_znode_dmu_init(zp); |
|
1544 | 632 |
mutex_exit(hash_mtx); |
633 |
||
789 | 634 |
*zpp = zp; |
635 |
} else { |
|
636 |
ZTOV(zp)->v_count = 0; |
|
1544 | 637 |
dmu_buf_rele(dbp, NULL); |
789 | 638 |
zfs_znode_free(zp); |
639 |
} |
|
640 |
} |
|
641 |
||
642 |
int |
|
643 |
zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp) |
|
644 |
{ |
|
645 |
dmu_object_info_t doi; |
|
646 |
dmu_buf_t *db; |
|
647 |
znode_t *zp; |
|
1544 | 648 |
int err; |
789 | 649 |
|
650 |
*zpp = NULL; |
|
651 |
||
652 |
ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); |
|
653 |
||
1544 | 654 |
err = dmu_bonus_hold(zfsvfs->z_os, obj_num, NULL, &db); |
655 |
if (err) { |
|
789 | 656 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
1544 | 657 |
return (err); |
789 | 658 |
} |
659 |
||
660 |
dmu_object_info_from_db(db, &doi); |
|
661 |
if (doi.doi_bonus_type != DMU_OT_ZNODE || |
|
662 |
doi.doi_bonus_size < sizeof (znode_phys_t)) { |
|
1544 | 663 |
dmu_buf_rele(db, NULL); |
789 | 664 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
665 |
return (EINVAL); |
|
666 |
} |
|
667 |
||
668 |
ASSERT(db->db_object == obj_num); |
|
669 |
ASSERT(db->db_offset == -1); |
|
670 |
ASSERT(db->db_data != NULL); |
|
671 |
||
672 |
zp = dmu_buf_get_user(db); |
|
673 |
||
674 |
if (zp != NULL) { |
|
675 |
mutex_enter(&zp->z_lock); |
|
676 |
||
677 |
ASSERT3U(zp->z_id, ==, obj_num); |
|
3461 | 678 |
if (zp->z_unlinked) { |
1544 | 679 |
dmu_buf_rele(db, NULL); |
789 | 680 |
mutex_exit(&zp->z_lock); |
681 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
|
682 |
return (ENOENT); |
|
683 |
} else if (zp->z_dbuf_held) { |
|
1544 | 684 |
dmu_buf_rele(db, NULL); |
789 | 685 |
} else { |
686 |
zp->z_dbuf_held = 1; |
|
687 |
VFS_HOLD(zfsvfs->z_vfs); |
|
688 |
} |
|
689 |
||
1544 | 690 |
|
789 | 691 |
VN_HOLD(ZTOV(zp)); |
692 |
mutex_exit(&zp->z_lock); |
|
1544 | 693 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
789 | 694 |
*zpp = zp; |
695 |
return (0); |
|
696 |
} |
|
697 |
||
698 |
/* |
|
699 |
* Not found create new znode/vnode |
|
700 |
*/ |
|
701 |
zp = zfs_znode_alloc(zfsvfs, db, obj_num, doi.doi_data_block_size); |
|
702 |
ASSERT3U(zp->z_id, ==, obj_num); |
|
703 |
zfs_znode_dmu_init(zp); |
|
1544 | 704 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
789 | 705 |
*zpp = zp; |
706 |
return (0); |
|
707 |
} |
|
708 |
||
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
709 |
int |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
710 |
zfs_rezget(znode_t *zp) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
711 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
712 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
713 |
dmu_object_info_t doi; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
714 |
dmu_buf_t *db; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
715 |
uint64_t obj_num = zp->z_id; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
716 |
int err; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
717 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
718 |
ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
719 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
720 |
err = dmu_bonus_hold(zfsvfs->z_os, obj_num, NULL, &db); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
721 |
if (err) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
722 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
723 |
return (err); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
724 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
725 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
726 |
dmu_object_info_from_db(db, &doi); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
727 |
if (doi.doi_bonus_type != DMU_OT_ZNODE || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
728 |
doi.doi_bonus_size < sizeof (znode_phys_t)) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
729 |
dmu_buf_rele(db, NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
730 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
731 |
return (EINVAL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
732 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
733 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
734 |
ASSERT(db->db_object == obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
735 |
ASSERT(db->db_offset == -1); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
736 |
ASSERT(db->db_data != NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
737 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
738 |
if (((znode_phys_t *)db->db_data)->zp_gen != zp->z_gen) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
739 |
dmu_buf_rele(db, NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
740 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
741 |
return (EIO); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
742 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
743 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
744 |
zp->z_dbuf = db; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
745 |
zp->z_phys = db->db_data; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
746 |
zfs_znode_dmu_init(zp); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
747 |
zp->z_unlinked = (zp->z_phys->zp_links == 0); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
748 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
749 |
/* release the hold from zfs_znode_dmu_init() */ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
750 |
VFS_RELE(zfsvfs->z_vfs); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
751 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
752 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
753 |
return (0); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
754 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
4831
diff
changeset
|
755 |
|
789 | 756 |
void |
757 |
zfs_znode_delete(znode_t *zp, dmu_tx_t *tx) |
|
758 |
{ |
|
759 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
|
760 |
int error; |
|
761 |
||
762 |
ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id); |
|
763 |
if (zp->z_phys->zp_acl.z_acl_extern_obj) { |
|
764 |
error = dmu_object_free(zfsvfs->z_os, |
|
765 |
zp->z_phys->zp_acl.z_acl_extern_obj, tx); |
|
766 |
ASSERT3U(error, ==, 0); |
|
767 |
} |
|
768 |
error = dmu_object_free(zfsvfs->z_os, zp->z_id, tx); |
|
769 |
ASSERT3U(error, ==, 0); |
|
770 |
zp->z_dbuf_held = 0; |
|
771 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id); |
|
1544 | 772 |
dmu_buf_rele(zp->z_dbuf, NULL); |
789 | 773 |
} |
774 |
||
775 |
void |
|
776 |
zfs_zinactive(znode_t *zp) |
|
777 |
{ |
|
778 |
vnode_t *vp = ZTOV(zp); |
|
779 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
|
780 |
uint64_t z_id = zp->z_id; |
|
781 |
||
782 |
ASSERT(zp->z_dbuf_held && zp->z_phys); |
|
783 |
||
784 |
/* |
|
785 |
* Don't allow a zfs_zget() while were trying to release this znode |
|
786 |
*/ |
|
787 |
ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id); |
|
788 |
||
789 |
mutex_enter(&zp->z_lock); |
|
790 |
mutex_enter(&vp->v_lock); |
|
791 |
vp->v_count--; |
|
792 |
if (vp->v_count > 0 || vn_has_cached_data(vp)) { |
|
793 |
/* |
|
794 |
* If the hold count is greater than zero, somebody has |
|
795 |
* obtained a new reference on this znode while we were |
|
796 |
* processing it here, so we are done. If we still have |
|
797 |
* mapped pages then we are also done, since we don't |
|
798 |
* want to inactivate the znode until the pages get pushed. |
|
799 |
* |
|
800 |
* XXX - if vn_has_cached_data(vp) is true, but count == 0, |
|
801 |
* this seems like it would leave the znode hanging with |
|
802 |
* no chance to go inactive... |
|
803 |
*/ |
|
804 |
mutex_exit(&vp->v_lock); |
|
805 |
mutex_exit(&zp->z_lock); |
|
806 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); |
|
807 |
return; |
|
808 |
} |
|
809 |
mutex_exit(&vp->v_lock); |
|
810 |
||
811 |
/* |
|
812 |
* If this was the last reference to a file with no links, |
|
813 |
* remove the file from the file system. |
|
814 |
*/ |
|
3461 | 815 |
if (zp->z_unlinked) { |
789 | 816 |
mutex_exit(&zp->z_lock); |
817 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); |
|
3461 | 818 |
zfs_rmnode(zp); |
789 | 819 |
VFS_RELE(zfsvfs->z_vfs); |
820 |
return; |
|
821 |
} |
|
1544 | 822 |
ASSERT(zp->z_phys); |
823 |
ASSERT(zp->z_dbuf_held); |
|
789 | 824 |
|
1544 | 825 |
zp->z_dbuf_held = 0; |
789 | 826 |
mutex_exit(&zp->z_lock); |
1544 | 827 |
dmu_buf_rele(zp->z_dbuf, NULL); |
789 | 828 |
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); |
1544 | 829 |
VFS_RELE(zfsvfs->z_vfs); |
789 | 830 |
} |
831 |
||
832 |
void |
|
833 |
zfs_znode_free(znode_t *zp) |
|
834 |
{ |
|
835 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
|
836 |
||
837 |
mutex_enter(&zfsvfs->z_znodes_lock); |
|
838 |
list_remove(&zfsvfs->z_all_znodes, zp); |
|
839 |
mutex_exit(&zfsvfs->z_znodes_lock); |
|
840 |
||
841 |
kmem_cache_free(znode_cache, zp); |
|
842 |
} |
|
843 |
||
844 |
void |
|
845 |
zfs_time_stamper_locked(znode_t *zp, uint_t flag, dmu_tx_t *tx) |
|
846 |
{ |
|
847 |
timestruc_t now; |
|
848 |
||
849 |
ASSERT(MUTEX_HELD(&zp->z_lock)); |
|
850 |
||
851 |
gethrestime(&now); |
|
852 |
||
853 |
if (tx) { |
|
854 |
dmu_buf_will_dirty(zp->z_dbuf, tx); |
|
855 |
zp->z_atime_dirty = 0; |
|
856 |
zp->z_seq++; |
|
857 |
} else { |
|
858 |
zp->z_atime_dirty = 1; |
|
859 |
} |
|
860 |
||
861 |
if (flag & AT_ATIME) |
|
862 |
ZFS_TIME_ENCODE(&now, zp->z_phys->zp_atime); |
|
863 |
||
864 |
if (flag & AT_MTIME) |
|
865 |
ZFS_TIME_ENCODE(&now, zp->z_phys->zp_mtime); |
|
866 |
||
867 |
if (flag & AT_CTIME) |
|
868 |
ZFS_TIME_ENCODE(&now, zp->z_phys->zp_ctime); |
|
869 |
} |
|
870 |
||
871 |
/* |
|
872 |
* Update the requested znode timestamps with the current time. |
|
873 |
* If we are in a transaction, then go ahead and mark the znode |
|
874 |
* dirty in the transaction so the timestamps will go to disk. |
|
875 |
* Otherwise, we will get pushed next time the znode is updated |
|
876 |
* in a transaction, or when this znode eventually goes inactive. |
|
877 |
* |
|
878 |
* Why is this OK? |
|
879 |
* 1 - Only the ACCESS time is ever updated outside of a transaction. |
|
880 |
* 2 - Multiple consecutive updates will be collapsed into a single |
|
881 |
* znode update by the transaction grouping semantics of the DMU. |
|
882 |
*/ |
|
883 |
void |
|
884 |
zfs_time_stamper(znode_t *zp, uint_t flag, dmu_tx_t *tx) |
|
885 |
{ |
|
886 |
mutex_enter(&zp->z_lock); |
|
887 |
zfs_time_stamper_locked(zp, flag, tx); |
|
888 |
mutex_exit(&zp->z_lock); |
|
889 |
} |
|
890 |
||
891 |
/* |
|
1669 | 892 |
* Grow the block size for a file. |
789 | 893 |
* |
894 |
* IN: zp - znode of file to free data in. |
|
895 |
* size - requested block size |
|
896 |
* tx - open transaction. |
|
897 |
* |
|
898 |
* NOTE: this function assumes that the znode is write locked. |
|
899 |
*/ |
|
1669 | 900 |
void |
789 | 901 |
zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx) |
902 |
{ |
|
903 |
int error; |
|
904 |
u_longlong_t dummy; |
|
905 |
||
906 |
if (size <= zp->z_blksz) |
|
1669 | 907 |
return; |
789 | 908 |
/* |
909 |
* If the file size is already greater than the current blocksize, |
|
910 |
* we will not grow. If there is more than one block in a file, |
|
911 |
* the blocksize cannot change. |
|
912 |
*/ |
|
913 |
if (zp->z_blksz && zp->z_phys->zp_size > zp->z_blksz) |
|
1669 | 914 |
return; |
789 | 915 |
|
916 |
error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id, |
|
917 |
size, 0, tx); |
|
918 |
if (error == ENOTSUP) |
|
1669 | 919 |
return; |
789 | 920 |
ASSERT3U(error, ==, 0); |
921 |
||
922 |
/* What blocksize did we actually get? */ |
|
923 |
dmu_object_size_from_db(zp->z_dbuf, &zp->z_blksz, &dummy); |
|
924 |
} |
|
925 |
||
926 |
/* |
|
927 |
* This is a dummy interface used when pvn_vplist_dirty() should *not* |
|
928 |
* be calling back into the fs for a putpage(). E.g.: when truncating |
|
929 |
* a file, the pages being "thrown away* don't need to be written out. |
|
930 |
*/ |
|
931 |
/* ARGSUSED */ |
|
932 |
static int |
|
933 |
zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, |
|
934 |
int flags, cred_t *cr) |
|
935 |
{ |
|
936 |
ASSERT(0); |
|
937 |
return (0); |
|
938 |
} |
|
939 |
||
940 |
/* |
|
1669 | 941 |
* Free space in a file. |
789 | 942 |
* |
943 |
* IN: zp - znode of file to free data in. |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
944 |
* off - start of section to free. |
789 | 945 |
* len - length of section to free (0 => to EOF). |
946 |
* flag - current file open mode flags. |
|
947 |
* |
|
948 |
* RETURN: 0 if success |
|
949 |
* error code if failure |
|
950 |
*/ |
|
951 |
int |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
952 |
zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log) |
789 | 953 |
{ |
954 |
vnode_t *vp = ZTOV(zp); |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
955 |
dmu_tx_t *tx; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
956 |
zfsvfs_t *zfsvfs = zp->z_zfsvfs; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
957 |
zilog_t *zilog = zfsvfs->z_log; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
958 |
rl_t *rl; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
959 |
uint64_t end = off + len; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
960 |
uint64_t size, new_blksz; |
1669 | 961 |
int error; |
789 | 962 |
|
1394
e8d500b79ced
6381600 tc_open.021 in mstc testsuite is returning -1 when run on a zfs
marks
parents:
869
diff
changeset
|
963 |
if (ZTOV(zp)->v_type == VFIFO) |
e8d500b79ced
6381600 tc_open.021 in mstc testsuite is returning -1 when run on a zfs
marks
parents:
869
diff
changeset
|
964 |
return (0); |
e8d500b79ced
6381600 tc_open.021 in mstc testsuite is returning -1 when run on a zfs
marks
parents:
869
diff
changeset
|
965 |
|
789 | 966 |
/* |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
967 |
* If we will change zp_size then lock the whole file, |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
968 |
* otherwise just lock the range being freed. |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
969 |
*/ |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
970 |
if (len == 0 || off + len > zp->z_phys->zp_size) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
971 |
rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
972 |
} else { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
973 |
rl = zfs_range_lock(zp, off, len, RL_WRITER); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
974 |
/* recheck, in case zp_size changed */ |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
975 |
if (off + len > zp->z_phys->zp_size) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
976 |
/* lost race: file size changed, lock whole file */ |
2237 | 977 |
zfs_range_unlock(rl); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
978 |
rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
979 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
980 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
981 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
982 |
/* |
789 | 983 |
* Nothing to do if file already at desired length. |
984 |
*/ |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
985 |
size = zp->z_phys->zp_size; |
4144
068f395736ad
6465105 ZFS does not update timestamps upon the creat() of an existing file
peteh
parents:
4105
diff
changeset
|
986 |
if (len == 0 && size == off && off != 0) { |
2237 | 987 |
zfs_range_unlock(rl); |
789 | 988 |
return (0); |
989 |
} |
|
990 |
||
991 |
/* |
|
992 |
* Check for any locks in the region to be freed. |
|
993 |
*/ |
|
994 |
if (MANDLOCK(vp, (mode_t)zp->z_phys->zp_mode)) { |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
995 |
uint64_t start = off; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
996 |
uint64_t extent = len; |
789 | 997 |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
998 |
if (off > size) { |
789 | 999 |
start = size; |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1000 |
extent += off - size; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1001 |
} else if (len == 0) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1002 |
extent = size - off; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1003 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1004 |
if (error = chklock(vp, FWRITE, start, extent, flag, NULL)) { |
2237 | 1005 |
zfs_range_unlock(rl); |
789 | 1006 |
return (error); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1007 |
} |
789 | 1008 |
} |
1009 |
||
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1010 |
tx = dmu_tx_create(zfsvfs->z_os); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1011 |
dmu_tx_hold_bonus(tx, zp->z_id); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1012 |
new_blksz = 0; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1013 |
if (end > size && |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1014 |
(!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) { |
789 | 1015 |
/* |
1016 |
* We are growing the file past the current block size. |
|
1017 |
*/ |
|
1018 |
if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) { |
|
1019 |
ASSERT(!ISP2(zp->z_blksz)); |
|
1020 |
new_blksz = MIN(end, SPA_MAXBLOCKSIZE); |
|
1021 |
} else { |
|
1022 |
new_blksz = MIN(end, zp->z_zfsvfs->z_max_blksz); |
|
1023 |
} |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1024 |
dmu_tx_hold_write(tx, zp->z_id, 0, MIN(end, new_blksz)); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1025 |
} else if (off < size) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1026 |
/* |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1027 |
* If len == 0, we are truncating the file. |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1028 |
*/ |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1029 |
dmu_tx_hold_free(tx, zp->z_id, off, len ? len : DMU_OBJECT_END); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1030 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1031 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1032 |
error = dmu_tx_assign(tx, zfsvfs->z_assign); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1033 |
if (error) { |
2113
0510bb40c993
6430121 3-way deadlock involving tc_lock within zfs
ahrens
parents:
1936
diff
changeset
|
1034 |
if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) |
0510bb40c993
6430121 3-way deadlock involving tc_lock within zfs
ahrens
parents:
1936
diff
changeset
|
1035 |
dmu_tx_wait(tx); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1036 |
dmu_tx_abort(tx); |
2237 | 1037 |
zfs_range_unlock(rl); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1038 |
return (error); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1039 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1040 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1041 |
if (new_blksz) |
1669 | 1042 |
zfs_grow_blocksize(zp, new_blksz, tx); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1043 |
|
789 | 1044 |
if (end > size || len == 0) |
1045 |
zp->z_phys->zp_size = end; |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1046 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1047 |
if (off < size) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1048 |
objset_t *os = zfsvfs->z_os; |
1936
b6ded90e4d4b
6398177 zfs: poor nightly build performance in 32-bit mode (high disk activity)
maybee
parents:
1878
diff
changeset
|
1049 |
uint64_t rlen = len; |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1050 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1051 |
if (len == 0) |
1936
b6ded90e4d4b
6398177 zfs: poor nightly build performance in 32-bit mode (high disk activity)
maybee
parents:
1878
diff
changeset
|
1052 |
rlen = -1; |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1053 |
else if (end > size) |
1936
b6ded90e4d4b
6398177 zfs: poor nightly build performance in 32-bit mode (high disk activity)
maybee
parents:
1878
diff
changeset
|
1054 |
rlen = size - off; |
b6ded90e4d4b
6398177 zfs: poor nightly build performance in 32-bit mode (high disk activity)
maybee
parents:
1878
diff
changeset
|
1055 |
VERIFY(0 == dmu_free_range(os, zp->z_id, off, rlen, tx)); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1056 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1057 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1058 |
if (log) { |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1059 |
zfs_time_stamper(zp, CONTENT_MODIFIED, tx); |
2638
4f583dfeae92
6413510 zfs: writing to ZFS filesystem slows down fsync() on other files in the same FS
perrin
parents:
2597
diff
changeset
|
1060 |
zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1061 |
} |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1062 |
|
2237 | 1063 |
zfs_range_unlock(rl); |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1064 |
|
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1065 |
dmu_tx_commit(tx); |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1066 |
|
789 | 1067 |
/* |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1068 |
* Clear any mapped pages in the truncated region. This has to |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1069 |
* happen outside of the transaction to avoid the possibility of |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1070 |
* a deadlock with someone trying to push a page that we are |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1071 |
* about to invalidate. |
789 | 1072 |
*/ |
1073 |
rw_enter(&zp->z_map_lock, RW_WRITER); |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1074 |
if (off < size && vn_has_cached_data(vp)) { |
789 | 1075 |
page_t *pp; |
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1076 |
uint64_t start = off & PAGEMASK; |
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1077 |
int poff = off & PAGEOFFSET; |
789 | 1078 |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1079 |
if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) { |
789 | 1080 |
/* |
1081 |
* We need to zero a partial page. |
|
1082 |
*/ |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1083 |
pagezero(pp, poff, PAGESIZE - poff); |
789 | 1084 |
start += PAGESIZE; |
1085 |
page_unlock(pp); |
|
1086 |
} |
|
1087 |
error = pvn_vplist_dirty(vp, start, zfs_no_putpage, |
|
1878
c22df0f5603f
6413573 deadlock between fsflush() and zfs_create()
maybee
parents:
1816
diff
changeset
|
1088 |
B_INVAL | B_TRUNC, NULL); |
789 | 1089 |
ASSERT(error == 0); |
1090 |
} |
|
1091 |
rw_exit(&zp->z_map_lock); |
|
1092 |
||
1093 |
return (0); |
|
1094 |
} |
|
1095 |
||
1096 |
void |
|
4577 | 1097 |
zfs_create_fs(objset_t *os, cred_t *cr, uint64_t version, dmu_tx_t *tx) |
789 | 1098 |
{ |
1099 |
zfsvfs_t zfsvfs; |
|
1100 |
uint64_t moid, doid, roid = 0; |
|
1101 |
int error; |
|
1102 |
znode_t *rootzp = NULL; |
|
1103 |
vnode_t *vp; |
|
1104 |
vattr_t vattr; |
|
1105 |
||
1106 |
/* |
|
1107 |
* First attempt to create master node. |
|
1108 |
*/ |
|
1544 | 1109 |
/* |
1110 |
* In an empty objset, there are no blocks to read and thus |
|
1111 |
* there can be no i/o errors (which we assert below). |
|
1112 |
*/ |
|
789 | 1113 |
moid = MASTER_NODE_OBJ; |
1114 |
error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE, |
|
1115 |
DMU_OT_NONE, 0, tx); |
|
1116 |
ASSERT(error == 0); |
|
1117 |
||
1118 |
/* |
|
1119 |
* Set starting attributes. |
|
1120 |
*/ |
|
1121 |
||
4577 | 1122 |
error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx); |
789 | 1123 |
ASSERT(error == 0); |
1124 |
||
1125 |
/* |
|
1126 |
* Create a delete queue. |
|
1127 |
*/ |
|
3461 | 1128 |
doid = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx); |
789 | 1129 |
|
3461 | 1130 |
error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &doid, tx); |
789 | 1131 |
ASSERT(error == 0); |
1132 |
||
1133 |
/* |
|
1134 |
* Create root znode. Create minimal znode/vnode/zfsvfs |
|
1135 |
* to allow zfs_mknode to work. |
|
1136 |
*/ |
|
1137 |
vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; |
|
1138 |
vattr.va_type = VDIR; |
|
1139 |
vattr.va_mode = S_IFDIR|0755; |
|
4543 | 1140 |
vattr.va_uid = crgetuid(cr); |
1141 |
vattr.va_gid = crgetgid(cr); |
|
789 | 1142 |
|
1143 |
rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP); |
|
1144 |
rootzp->z_zfsvfs = &zfsvfs; |
|
3461 | 1145 |
rootzp->z_unlinked = 0; |
789 | 1146 |
rootzp->z_atime_dirty = 0; |
1147 |
rootzp->z_dbuf_held = 0; |
|
1148 |
||
1149 |
vp = ZTOV(rootzp); |
|
1150 |
vn_reinit(vp); |
|
1151 |
vp->v_type = VDIR; |
|
1152 |
||
1153 |
bzero(&zfsvfs, sizeof (zfsvfs_t)); |
|
1154 |
||
1155 |
zfsvfs.z_os = os; |
|
1156 |
zfsvfs.z_assign = TXG_NOWAIT; |
|
1157 |
zfsvfs.z_parent = &zfsvfs; |
|
1158 |
||
1159 |
mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); |
|
1160 |
list_create(&zfsvfs.z_all_znodes, sizeof (znode_t), |
|
1161 |
offsetof(znode_t, z_link_node)); |
|
1162 |
||
1163 |
zfs_mknode(rootzp, &vattr, &roid, tx, cr, IS_ROOT_NODE, NULL, 0); |
|
1164 |
ASSERT3U(rootzp->z_id, ==, roid); |
|
1165 |
error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &roid, tx); |
|
1166 |
ASSERT(error == 0); |
|
1167 |
||
1168 |
ZTOV(rootzp)->v_count = 0; |
|
1169 |
kmem_cache_free(znode_cache, rootzp); |
|
1170 |
} |
|
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1171 |
#endif /* _KERNEL */ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1172 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1173 |
/* |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1174 |
* Given an object number, return its parent object number and whether |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1175 |
* or not the object is an extended attribute directory. |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1176 |
*/ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1177 |
static int |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1178 |
zfs_obj_to_pobj(objset_t *osp, uint64_t obj, uint64_t *pobjp, int *is_xattrdir) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1179 |
{ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1180 |
dmu_buf_t *db; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1181 |
dmu_object_info_t doi; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1182 |
znode_phys_t *zp; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1183 |
int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1184 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1185 |
if ((error = dmu_bonus_hold(osp, obj, FTAG, &db)) != 0) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1186 |
return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1187 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1188 |
dmu_object_info_from_db(db, &doi); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1189 |
if (doi.doi_bonus_type != DMU_OT_ZNODE || |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1190 |
doi.doi_bonus_size < sizeof (znode_phys_t)) { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1191 |
dmu_buf_rele(db, FTAG); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1192 |
return (EINVAL); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1193 |
} |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1194 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1195 |
zp = db->db_data; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1196 |
*pobjp = zp->zp_parent; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1197 |
*is_xattrdir = ((zp->zp_flags & ZFS_XATTR) != 0) && |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1198 |
S_ISDIR(zp->zp_mode); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1199 |
dmu_buf_rele(db, FTAG); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1200 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1201 |
return (0); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1202 |
} |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1203 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1204 |
int |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1205 |
zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1206 |
{ |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1207 |
char *path = buf + len - 1; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1208 |
int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1209 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1210 |
*path = '\0'; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1211 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1212 |
for (;;) { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1213 |
uint64_t pobj; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1214 |
char component[MAXNAMELEN + 2]; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1215 |
size_t complen; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1216 |
int is_xattrdir; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1217 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1218 |
if ((error = zfs_obj_to_pobj(osp, obj, &pobj, |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1219 |
&is_xattrdir)) != 0) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1220 |
break; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1221 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1222 |
if (pobj == obj) { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1223 |
if (path[0] != '/') |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1224 |
*--path = '/'; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1225 |
break; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1226 |
} |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1227 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1228 |
component[0] = '/'; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1229 |
if (is_xattrdir) { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1230 |
(void) sprintf(component + 1, "<xattrdir>"); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1231 |
} else { |
4577 | 1232 |
error = zap_value_search(osp, pobj, obj, |
1233 |
ZFS_DIRENT_OBJ(-1ULL), component + 1); |
|
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1234 |
if (error != 0) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1235 |
break; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1236 |
} |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1237 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1238 |
complen = strlen(component); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1239 |
path -= complen; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1240 |
ASSERT(path >= buf); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1241 |
bcopy(component, path, complen); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1242 |
obj = pobj; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1243 |
} |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1244 |
|
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1245 |
if (error == 0) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1246 |
(void) memmove(buf, path, buf + len - path); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1247 |
return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3063
diff
changeset
|
1248 |
} |