4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
24 * Copyright (c) 2014 Integros [integros.com]
27 /* Portions Copyright 2007 Jeremy Teo */
28 /* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
31 #include <sys/dmu_objset.h>
32 #include <sys/dmu_tx.h>
33 #include <sys/zfs_refcount.h>
36 #include <sys/zfs_znode.h>
38 #include <sys/zfs_sa.h>
39 #include <sys/zfs_stat.h>
42 #include "zfs_comutil.h"
45 zfs_sa_setup(objset_t
*osp
, sa_attr_type_t
**sa_table
)
50 error
= zap_lookup(osp
, MASTER_NODE_OBJ
, ZFS_SA_ATTRS
, 8, 1, &sa_obj
);
51 if (error
!= 0 && error
!= ENOENT
)
54 error
= sa_setup(osp
, sa_obj
, zfs_attr_table
, ZPL_END
, sa_table
);
59 zfs_grab_sa_handle(objset_t
*osp
, uint64_t obj
, sa_handle_t
**hdlp
,
60 dmu_buf_t
**db
, const void *tag
)
62 dmu_object_info_t doi
;
65 if ((error
= sa_buf_hold(osp
, obj
, tag
, db
)) != 0)
68 dmu_object_info_from_db(*db
, &doi
);
69 if ((doi
.doi_bonus_type
!= DMU_OT_SA
&&
70 doi
.doi_bonus_type
!= DMU_OT_ZNODE
) ||
71 (doi
.doi_bonus_type
== DMU_OT_ZNODE
&&
72 doi
.doi_bonus_size
< sizeof (znode_phys_t
))) {
73 sa_buf_rele(*db
, tag
);
74 return (SET_ERROR(ENOTSUP
));
77 error
= sa_handle_get(osp
, obj
, NULL
, SA_HDL_PRIVATE
, hdlp
);
79 sa_buf_rele(*db
, tag
);
87 zfs_release_sa_handle(sa_handle_t
*hdl
, dmu_buf_t
*db
, const void *tag
)
89 sa_handle_destroy(hdl
);
94 * Given an object number, return its parent object number and whether
95 * or not the object is an extended attribute directory.
98 zfs_obj_to_pobj(objset_t
*osp
, sa_handle_t
*hdl
, sa_attr_type_t
*sa_table
,
99 uint64_t *pobjp
, int *is_xattrdir
)
104 uint64_t parent_mode
;
105 sa_bulk_attr_t bulk
[3];
111 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_PARENT
], NULL
,
112 &parent
, sizeof (parent
));
113 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_FLAGS
], NULL
,
114 &pflags
, sizeof (pflags
));
115 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_MODE
], NULL
,
116 &mode
, sizeof (mode
));
118 if ((error
= sa_bulk_lookup(hdl
, bulk
, count
)) != 0)
122 * When a link is removed its parent pointer is not changed and will
123 * be invalid. There are two cases where a link is removed but the
124 * file stays around, when it goes to the delete queue and when there
125 * are additional links.
127 error
= zfs_grab_sa_handle(osp
, parent
, &sa_hdl
, &sa_db
, FTAG
);
131 error
= sa_lookup(sa_hdl
, ZPL_MODE
, &parent_mode
, sizeof (parent_mode
));
132 zfs_release_sa_handle(sa_hdl
, sa_db
, FTAG
);
136 *is_xattrdir
= ((pflags
& ZFS_XATTR
) != 0) && S_ISDIR(mode
);
139 * Extended attributes can be applied to files, directories, etc.
140 * Otherwise the parent must be a directory.
142 if (!*is_xattrdir
&& !S_ISDIR(parent_mode
))
143 return (SET_ERROR(EINVAL
));
151 * Given an object number, return some zpl level statistics
154 zfs_obj_to_stats_impl(sa_handle_t
*hdl
, sa_attr_type_t
*sa_table
,
157 sa_bulk_attr_t bulk
[4];
160 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_MODE
], NULL
,
161 &sb
->zs_mode
, sizeof (sb
->zs_mode
));
162 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_GEN
], NULL
,
163 &sb
->zs_gen
, sizeof (sb
->zs_gen
));
164 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_LINKS
], NULL
,
165 &sb
->zs_links
, sizeof (sb
->zs_links
));
166 SA_ADD_BULK_ATTR(bulk
, count
, sa_table
[ZPL_CTIME
], NULL
,
167 &sb
->zs_ctime
, sizeof (sb
->zs_ctime
));
169 return (sa_bulk_lookup(hdl
, bulk
, count
));
173 zfs_obj_to_path_impl(objset_t
*osp
, uint64_t obj
, sa_handle_t
*hdl
,
174 sa_attr_type_t
*sa_table
, char *buf
, int len
)
177 sa_handle_t
*prevhdl
= NULL
;
178 dmu_buf_t
*prevdb
= NULL
;
179 dmu_buf_t
*sa_db
= NULL
;
180 char *path
= buf
+ len
- 1;
187 uint64_t deleteq_obj
;
188 VERIFY0(zap_lookup(osp
, MASTER_NODE_OBJ
,
189 ZFS_UNLINKED_SET
, sizeof (uint64_t), 1, &deleteq_obj
));
190 error
= zap_lookup_int(osp
, deleteq_obj
, obj
);
193 } else if (error
!= ENOENT
) {
197 comp_buf
= kmem_alloc(ZAP_MAXNAMELEN_NEW
+ 2, KM_SLEEP
);
200 char *component
= comp_buf
;
205 ASSERT3P(prevhdl
, !=, NULL
);
206 zfs_release_sa_handle(prevhdl
, prevdb
, FTAG
);
209 if ((error
= zfs_obj_to_pobj(osp
, sa_hdl
, sa_table
, &pobj
,
221 strcpy(component
+ 1, "<xattrdir>");
223 error
= zap_value_search(osp
, pobj
, obj
,
224 ZFS_DIRENT_OBJ(-1ULL), component
+ 1,
230 complen
= strlen(component
);
232 ASSERT3P(path
, >=, buf
);
233 memcpy(path
, component
, complen
);
240 error
= zfs_grab_sa_handle(osp
, obj
, &sa_hdl
, &sa_db
, FTAG
);
248 if (sa_hdl
!= NULL
&& sa_hdl
!= hdl
) {
249 ASSERT3P(sa_db
, !=, NULL
);
250 zfs_release_sa_handle(sa_hdl
, sa_db
, FTAG
);
254 (void) memmove(buf
, path
, buf
+ len
- path
);
256 kmem_free(comp_buf
, ZAP_MAXNAMELEN_NEW
+2);
261 zfs_obj_to_path(objset_t
*osp
, uint64_t obj
, char *buf
, int len
)
263 sa_attr_type_t
*sa_table
;
268 error
= zfs_sa_setup(osp
, &sa_table
);
272 error
= zfs_grab_sa_handle(osp
, obj
, &hdl
, &db
, FTAG
);
276 error
= zfs_obj_to_path_impl(osp
, obj
, hdl
, sa_table
, buf
, len
);
278 zfs_release_sa_handle(hdl
, db
, FTAG
);
283 zfs_obj_to_stats(objset_t
*osp
, uint64_t obj
, zfs_stat_t
*sb
,
286 char *path
= buf
+ len
- 1;
287 sa_attr_type_t
*sa_table
;
294 error
= zfs_sa_setup(osp
, &sa_table
);
298 error
= zfs_grab_sa_handle(osp
, obj
, &hdl
, &db
, FTAG
);
302 error
= zfs_obj_to_stats_impl(hdl
, sa_table
, sb
);
304 zfs_release_sa_handle(hdl
, db
, FTAG
);
308 error
= zfs_obj_to_path_impl(osp
, obj
, hdl
, sa_table
, buf
, len
);
310 zfs_release_sa_handle(hdl
, db
, FTAG
);
315 * Read a property stored within the master node.
318 zfs_get_zplprop(objset_t
*os
, zfs_prop_t prop
, uint64_t *value
)
320 uint64_t *cached_copy
= NULL
;
323 * Figure out where in the objset_t the cached copy would live, if it
324 * is available for the requested property.
328 case ZFS_PROP_VERSION
:
329 cached_copy
= &os
->os_version
;
331 case ZFS_PROP_NORMALIZE
:
332 cached_copy
= &os
->os_normalization
;
334 case ZFS_PROP_UTF8ONLY
:
335 cached_copy
= &os
->os_utf8only
;
338 cached_copy
= &os
->os_casesensitivity
;
344 if (cached_copy
!= NULL
&& *cached_copy
!= OBJSET_PROP_UNINITIALIZED
) {
345 *value
= *cached_copy
;
350 * If the property wasn't cached, look up the file system's value for
351 * the property. For the version property, we look up a slightly
356 if (prop
== ZFS_PROP_VERSION
)
357 pname
= ZPL_VERSION_STR
;
359 pname
= zfs_prop_to_name(prop
);
362 ASSERT3U(os
->os_phys
->os_type
, ==, DMU_OST_ZFS
);
363 error
= zap_lookup(os
, MASTER_NODE_OBJ
, pname
, 8, 1, value
);
366 if (error
== ENOENT
) {
367 /* No value set, use the default value */
369 case ZFS_PROP_VERSION
:
370 *value
= ZPL_VERSION
;
372 case ZFS_PROP_NORMALIZE
:
373 case ZFS_PROP_UTF8ONLY
:
377 *value
= ZFS_CASE_SENSITIVE
;
379 case ZFS_PROP_ACLTYPE
:
381 *value
= ZFS_ACLTYPE_NFSV4
;
383 *value
= ZFS_ACLTYPE_OFF
;
393 * If one of the methods for getting the property value above worked,
394 * copy it into the objset_t's cache.
396 if (error
== 0 && cached_copy
!= NULL
) {
397 *cached_copy
= *value
;