xref: /freebsd-14-stable/sys/contrib/openzfs/module/zfs/zfs_znode.c (revision 2ec8b69480708185a273254e4e254140eb2ce633)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
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 /*
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]
25  */
26 
27 /* Portions Copyright 2007 Jeremy Teo */
28 /* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
29 
30 #include <sys/dmu.h>
31 #include <sys/dmu_objset.h>
32 #include <sys/dmu_tx.h>
33 #include <sys/zfs_refcount.h>
34 #include <sys/stat.h>
35 #include <sys/zap.h>
36 #include <sys/zfs_znode.h>
37 #include <sys/sa.h>
38 #include <sys/zfs_sa.h>
39 #include <sys/zfs_stat.h>
40 
41 #include "zfs_prop.h"
42 #include "zfs_comutil.h"
43 
44 static int
zfs_sa_setup(objset_t * osp,sa_attr_type_t ** sa_table)45 zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
46 {
47 	uint64_t sa_obj = 0;
48 	int error;
49 
50 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
51 	if (error != 0 && error != ENOENT)
52 		return (error);
53 
54 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
55 	return (error);
56 }
57 
58 static int
zfs_grab_sa_handle(objset_t * osp,uint64_t obj,sa_handle_t ** hdlp,dmu_buf_t ** db,const void * tag)59 zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
60     dmu_buf_t **db, const void *tag)
61 {
62 	dmu_object_info_t doi;
63 	int error;
64 
65 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
66 		return (error);
67 
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));
75 	}
76 
77 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
78 	if (error != 0) {
79 		sa_buf_rele(*db, tag);
80 		return (error);
81 	}
82 
83 	return (0);
84 }
85 
86 static void
zfs_release_sa_handle(sa_handle_t * hdl,dmu_buf_t * db,const void * tag)87 zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
88 {
89 	sa_handle_destroy(hdl);
90 	sa_buf_rele(db, tag);
91 }
92 
93 /*
94  * Given an object number, return its parent object number and whether
95  * or not the object is an extended attribute directory.
96  */
97 int
zfs_obj_to_pobj(objset_t * osp,sa_handle_t * hdl,sa_attr_type_t * sa_table,uint64_t * pobjp,int * is_xattrdir)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)
100 {
101 	uint64_t parent;
102 	uint64_t pflags;
103 	uint64_t mode;
104 	uint64_t parent_mode;
105 	sa_bulk_attr_t bulk[3];
106 	sa_handle_t *sa_hdl;
107 	dmu_buf_t *sa_db;
108 	int count = 0;
109 	int error;
110 
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));
117 
118 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
119 		return (error);
120 
121 	/*
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.
126 	 */
127 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
128 	if (error != 0)
129 		return (error);
130 
131 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
132 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
133 	if (error != 0)
134 		return (error);
135 
136 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
137 
138 	/*
139 	 * Extended attributes can be applied to files, directories, etc.
140 	 * Otherwise the parent must be a directory.
141 	 */
142 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
143 		return (SET_ERROR(EINVAL));
144 
145 	*pobjp = parent;
146 
147 	return (0);
148 }
149 
150 /*
151  * Given an object number, return some zpl level statistics
152  */
153 static int
zfs_obj_to_stats_impl(sa_handle_t * hdl,sa_attr_type_t * sa_table,zfs_stat_t * sb)154 zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
155     zfs_stat_t *sb)
156 {
157 	sa_bulk_attr_t bulk[4];
158 	int count = 0;
159 
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));
168 
169 	return (sa_bulk_lookup(hdl, bulk, count));
170 }
171 
172 static int
zfs_obj_to_path_impl(objset_t * osp,uint64_t obj,sa_handle_t * hdl,sa_attr_type_t * sa_table,char * buf,int len)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)
175 {
176 	sa_handle_t *sa_hdl;
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;
181 	int error;
182 
183 	*path = '\0';
184 	sa_hdl = hdl;
185 
186 	uint64_t deleteq_obj;
187 	VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
188 	    ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
189 	error = zap_lookup_int(osp, deleteq_obj, obj);
190 	if (error == 0) {
191 		return (ESTALE);
192 	} else if (error != ENOENT) {
193 		return (error);
194 	}
195 
196 	for (;;) {
197 		uint64_t pobj = 0;
198 		char component[MAXNAMELEN + 2];
199 		size_t complen;
200 		int is_xattrdir = 0;
201 
202 		if (prevdb) {
203 			ASSERT3P(prevhdl, !=, NULL);
204 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
205 		}
206 
207 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
208 		    &is_xattrdir)) != 0)
209 			break;
210 
211 		if (pobj == obj) {
212 			if (path[0] != '/')
213 				*--path = '/';
214 			break;
215 		}
216 
217 		component[0] = '/';
218 		if (is_xattrdir) {
219 			strcpy(component + 1, "<xattrdir>");
220 		} else {
221 			error = zap_value_search(osp, pobj, obj,
222 			    ZFS_DIRENT_OBJ(-1ULL), component + 1);
223 			if (error != 0)
224 				break;
225 		}
226 
227 		complen = strlen(component);
228 		path -= complen;
229 		ASSERT3P(path, >=, buf);
230 		memcpy(path, component, complen);
231 		obj = pobj;
232 
233 		if (sa_hdl != hdl) {
234 			prevhdl = sa_hdl;
235 			prevdb = sa_db;
236 		}
237 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
238 		if (error != 0) {
239 			sa_hdl = prevhdl;
240 			sa_db = prevdb;
241 			break;
242 		}
243 	}
244 
245 	if (sa_hdl != NULL && sa_hdl != hdl) {
246 		ASSERT3P(sa_db, !=, NULL);
247 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
248 	}
249 
250 	if (error == 0)
251 		(void) memmove(buf, path, buf + len - path);
252 
253 	return (error);
254 }
255 
256 int
zfs_obj_to_path(objset_t * osp,uint64_t obj,char * buf,int len)257 zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
258 {
259 	sa_attr_type_t *sa_table;
260 	sa_handle_t *hdl;
261 	dmu_buf_t *db;
262 	int error;
263 
264 	error = zfs_sa_setup(osp, &sa_table);
265 	if (error != 0)
266 		return (error);
267 
268 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
269 	if (error != 0)
270 		return (error);
271 
272 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
273 
274 	zfs_release_sa_handle(hdl, db, FTAG);
275 	return (error);
276 }
277 
278 int
zfs_obj_to_stats(objset_t * osp,uint64_t obj,zfs_stat_t * sb,char * buf,int len)279 zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
280     char *buf, int len)
281 {
282 	char *path = buf + len - 1;
283 	sa_attr_type_t *sa_table;
284 	sa_handle_t *hdl;
285 	dmu_buf_t *db;
286 	int error;
287 
288 	*path = '\0';
289 
290 	error = zfs_sa_setup(osp, &sa_table);
291 	if (error != 0)
292 		return (error);
293 
294 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
295 	if (error != 0)
296 		return (error);
297 
298 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
299 	if (error != 0) {
300 		zfs_release_sa_handle(hdl, db, FTAG);
301 		return (error);
302 	}
303 
304 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
305 
306 	zfs_release_sa_handle(hdl, db, FTAG);
307 	return (error);
308 }
309 
310 /*
311  * Read a property stored within the master node.
312  */
313 int
zfs_get_zplprop(objset_t * os,zfs_prop_t prop,uint64_t * value)314 zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
315 {
316 	uint64_t *cached_copy = NULL;
317 
318 	/*
319 	 * Figure out where in the objset_t the cached copy would live, if it
320 	 * is available for the requested property.
321 	 */
322 	if (os != NULL) {
323 		switch (prop) {
324 		case ZFS_PROP_VERSION:
325 			cached_copy = &os->os_version;
326 			break;
327 		case ZFS_PROP_NORMALIZE:
328 			cached_copy = &os->os_normalization;
329 			break;
330 		case ZFS_PROP_UTF8ONLY:
331 			cached_copy = &os->os_utf8only;
332 			break;
333 		case ZFS_PROP_CASE:
334 			cached_copy = &os->os_casesensitivity;
335 			break;
336 		default:
337 			break;
338 		}
339 	}
340 	if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
341 		*value = *cached_copy;
342 		return (0);
343 	}
344 
345 	/*
346 	 * If the property wasn't cached, look up the file system's value for
347 	 * the property. For the version property, we look up a slightly
348 	 * different string.
349 	 */
350 	const char *pname;
351 	int error = ENOENT;
352 	if (prop == ZFS_PROP_VERSION)
353 		pname = ZPL_VERSION_STR;
354 	else
355 		pname = zfs_prop_to_name(prop);
356 
357 	if (os != NULL) {
358 		ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
359 		error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
360 	}
361 
362 	if (error == ENOENT) {
363 		/* No value set, use the default value */
364 		switch (prop) {
365 		case ZFS_PROP_VERSION:
366 			*value = ZPL_VERSION;
367 			break;
368 		case ZFS_PROP_NORMALIZE:
369 		case ZFS_PROP_UTF8ONLY:
370 			*value = 0;
371 			break;
372 		case ZFS_PROP_CASE:
373 			*value = ZFS_CASE_SENSITIVE;
374 			break;
375 		case ZFS_PROP_ACLTYPE:
376 #ifdef __FreeBSD__
377 			*value = ZFS_ACLTYPE_NFSV4;
378 #else
379 			*value = ZFS_ACLTYPE_OFF;
380 #endif
381 			break;
382 		default:
383 			return (error);
384 		}
385 		error = 0;
386 	}
387 
388 	/*
389 	 * If one of the methods for getting the property value above worked,
390 	 * copy it into the objset_t's cache.
391 	 */
392 	if (error == 0 && cached_copy != NULL) {
393 		*cached_copy = *value;
394 	}
395 
396 	return (error);
397 }
398