xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_znode.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or https://opensource.org/licenses/CDDL-1.0.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
25  * Copyright (c) 2014 Integros [integros.com]
26  */
27 
28 /* Portions Copyright 2007 Jeremy Teo */
29 /* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
30 
31 #include <sys/dmu.h>
32 #include <sys/dmu_objset.h>
33 #include <sys/dmu_tx.h>
34 #include <sys/zfs_refcount.h>
35 #include <sys/stat.h>
36 #include <sys/zap.h>
37 #include <sys/zfs_znode.h>
38 #include <sys/sa.h>
39 #include <sys/zfs_sa.h>
40 #include <sys/zfs_stat.h>
41 
42 #include "zfs_prop.h"
43 #include "zfs_comutil.h"
44 
45 static int
zfs_sa_setup(objset_t * osp,sa_attr_type_t ** sa_table)46 zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
47 {
48 	uint64_t sa_obj = 0;
49 	int error;
50 
51 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
52 	if (error != 0 && error != ENOENT)
53 		return (error);
54 
55 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
56 	return (error);
57 }
58 
59 static int
zfs_grab_sa_handle(objset_t * osp,uint64_t obj,sa_handle_t ** hdlp,dmu_buf_t ** db,const void * tag)60 zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
61     dmu_buf_t **db, const void *tag)
62 {
63 	dmu_object_info_t doi;
64 	int error;
65 
66 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
67 		return (error);
68 
69 	dmu_object_info_from_db(*db, &doi);
70 	if ((doi.doi_bonus_type != DMU_OT_SA &&
71 	    doi.doi_bonus_type != DMU_OT_ZNODE) ||
72 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
73 	    doi.doi_bonus_size < sizeof (znode_phys_t))) {
74 		sa_buf_rele(*db, tag);
75 		return (SET_ERROR(ENOTSUP));
76 	}
77 
78 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
79 	if (error != 0) {
80 		sa_buf_rele(*db, tag);
81 		return (error);
82 	}
83 
84 	return (0);
85 }
86 
87 static void
zfs_release_sa_handle(sa_handle_t * hdl,dmu_buf_t * db,const void * tag)88 zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
89 {
90 	sa_handle_destroy(hdl);
91 	sa_buf_rele(db, tag);
92 }
93 
94 /*
95  * Given an object number, return its parent object number and whether
96  * or not the object is an extended attribute directory.
97  */
98 int
zfs_obj_to_pobj(objset_t * osp,sa_handle_t * hdl,sa_attr_type_t * sa_table,uint64_t * pobjp,int * is_xattrdir)99 zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
100     uint64_t *pobjp, int *is_xattrdir)
101 {
102 	uint64_t parent;
103 	uint64_t pflags;
104 	uint64_t mode;
105 	uint64_t parent_mode;
106 	sa_bulk_attr_t bulk[3];
107 	sa_handle_t *sa_hdl;
108 	dmu_buf_t *sa_db;
109 	int count = 0;
110 	int error;
111 
112 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
113 	    &parent, sizeof (parent));
114 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
115 	    &pflags, sizeof (pflags));
116 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
117 	    &mode, sizeof (mode));
118 
119 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
120 		return (error);
121 
122 	/*
123 	 * When a link is removed its parent pointer is not changed and will
124 	 * be invalid.  There are two cases where a link is removed but the
125 	 * file stays around, when it goes to the delete queue and when there
126 	 * are additional links.
127 	 */
128 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
129 	if (error != 0)
130 		return (error);
131 
132 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
133 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
134 	if (error != 0)
135 		return (error);
136 
137 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
138 
139 	/*
140 	 * Extended attributes can be applied to files, directories, etc.
141 	 * Otherwise the parent must be a directory.
142 	 */
143 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
144 		return (SET_ERROR(EINVAL));
145 
146 	*pobjp = parent;
147 
148 	return (0);
149 }
150 
151 /*
152  * Given an object number, return some zpl level statistics
153  */
154 static int
zfs_obj_to_stats_impl(sa_handle_t * hdl,sa_attr_type_t * sa_table,zfs_stat_t * sb)155 zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
156     zfs_stat_t *sb)
157 {
158 	sa_bulk_attr_t bulk[4];
159 	int count = 0;
160 
161 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
162 	    &sb->zs_mode, sizeof (sb->zs_mode));
163 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
164 	    &sb->zs_gen, sizeof (sb->zs_gen));
165 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
166 	    &sb->zs_links, sizeof (sb->zs_links));
167 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
168 	    &sb->zs_ctime, sizeof (sb->zs_ctime));
169 
170 	return (sa_bulk_lookup(hdl, bulk, count));
171 }
172 
173 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)174 zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
175     sa_attr_type_t *sa_table, char *buf, int len)
176 {
177 	sa_handle_t *sa_hdl;
178 	sa_handle_t *prevhdl = NULL;
179 	dmu_buf_t *prevdb = NULL;
180 	dmu_buf_t *sa_db = NULL;
181 	char *path = buf + len - 1;
182 	char *comp_buf;
183 	int error;
184 
185 	*path = '\0';
186 	sa_hdl = hdl;
187 
188 	uint64_t deleteq_obj;
189 	VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
190 	    ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
191 	error = zap_lookup_int(osp, deleteq_obj, obj);
192 	if (error == 0) {
193 		return (ESTALE);
194 	} else if (error != ENOENT) {
195 		return (error);
196 	}
197 
198 	comp_buf = kmem_alloc(ZAP_MAXNAMELEN_NEW + 2, KM_SLEEP);
199 	for (;;) {
200 		uint64_t pobj = 0;
201 		char *component = comp_buf;
202 		size_t complen;
203 		int is_xattrdir = 0;
204 
205 		if (prevdb) {
206 			ASSERT3P(prevhdl, !=, NULL);
207 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
208 		}
209 
210 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
211 		    &is_xattrdir)) != 0)
212 			break;
213 
214 		if (pobj == obj) {
215 			if (path[0] != '/')
216 				*--path = '/';
217 			break;
218 		}
219 
220 		component[0] = '/';
221 		if (is_xattrdir) {
222 			strcpy(component + 1, "<xattrdir>");
223 		} else {
224 			error = zap_value_search(osp, pobj, obj,
225 			    ZFS_DIRENT_OBJ(-1ULL), component + 1,
226 			    ZAP_MAXNAMELEN_NEW);
227 			if (error != 0)
228 				break;
229 		}
230 
231 		complen = strlen(component);
232 		path -= complen;
233 		ASSERT3P(path, >=, buf);
234 		memcpy(path, component, complen);
235 		obj = pobj;
236 
237 		if (sa_hdl != hdl) {
238 			prevhdl = sa_hdl;
239 			prevdb = sa_db;
240 		}
241 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
242 		if (error != 0) {
243 			sa_hdl = prevhdl;
244 			sa_db = prevdb;
245 			break;
246 		}
247 	}
248 
249 	if (sa_hdl != NULL && sa_hdl != hdl) {
250 		ASSERT3P(sa_db, !=, NULL);
251 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
252 	}
253 
254 	if (error == 0)
255 		(void) memmove(buf, path, buf + len - path);
256 
257 	kmem_free(comp_buf, ZAP_MAXNAMELEN_NEW +2);
258 	return (error);
259 }
260 
261 int
zfs_obj_to_path(objset_t * osp,uint64_t obj,char * buf,int len)262 zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
263 {
264 	sa_attr_type_t *sa_table;
265 	sa_handle_t *hdl;
266 	dmu_buf_t *db;
267 	int error;
268 
269 	error = zfs_sa_setup(osp, &sa_table);
270 	if (error != 0)
271 		return (error);
272 
273 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
274 	if (error != 0)
275 		return (error);
276 
277 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
278 
279 	zfs_release_sa_handle(hdl, db, FTAG);
280 	return (error);
281 }
282 
283 int
zfs_obj_to_stats(objset_t * osp,uint64_t obj,zfs_stat_t * sb,char * buf,int len)284 zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
285     char *buf, int len)
286 {
287 	char *path = buf + len - 1;
288 	sa_attr_type_t *sa_table;
289 	sa_handle_t *hdl;
290 	dmu_buf_t *db;
291 	int error;
292 
293 	*path = '\0';
294 
295 	error = zfs_sa_setup(osp, &sa_table);
296 	if (error != 0)
297 		return (error);
298 
299 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
300 	if (error != 0)
301 		return (error);
302 
303 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
304 	if (error != 0) {
305 		zfs_release_sa_handle(hdl, db, FTAG);
306 		return (error);
307 	}
308 
309 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
310 
311 	zfs_release_sa_handle(hdl, db, FTAG);
312 	return (error);
313 }
314 
315 /*
316  * Read a property stored within the master node.
317  */
318 int
zfs_get_zplprop(objset_t * os,zfs_prop_t prop,uint64_t * value)319 zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
320 {
321 	uint64_t *cached_copy = NULL;
322 
323 	/*
324 	 * Figure out where in the objset_t the cached copy would live, if it
325 	 * is available for the requested property.
326 	 */
327 	if (os != NULL) {
328 		switch (prop) {
329 		case ZFS_PROP_VERSION:
330 			cached_copy = &os->os_version;
331 			break;
332 		case ZFS_PROP_NORMALIZE:
333 			cached_copy = &os->os_normalization;
334 			break;
335 		case ZFS_PROP_UTF8ONLY:
336 			cached_copy = &os->os_utf8only;
337 			break;
338 		case ZFS_PROP_CASE:
339 			cached_copy = &os->os_casesensitivity;
340 			break;
341 		default:
342 			break;
343 		}
344 	}
345 	if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
346 		*value = *cached_copy;
347 		return (0);
348 	}
349 
350 	/*
351 	 * If the property wasn't cached, look up the file system's value for
352 	 * the property. For the version property, we look up a slightly
353 	 * different string.
354 	 */
355 	const char *pname;
356 	int error = ENOENT;
357 	if (prop == ZFS_PROP_VERSION)
358 		pname = ZPL_VERSION_STR;
359 	else
360 		pname = zfs_prop_to_name(prop);
361 
362 	if (os != NULL) {
363 		ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
364 		error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
365 	}
366 
367 	if (error == ENOENT) {
368 		/* No value set, use the default value */
369 		switch (prop) {
370 		case ZFS_PROP_VERSION:
371 			*value = ZPL_VERSION;
372 			break;
373 		case ZFS_PROP_NORMALIZE:
374 		case ZFS_PROP_UTF8ONLY:
375 			*value = 0;
376 			break;
377 		case ZFS_PROP_CASE:
378 			*value = ZFS_CASE_SENSITIVE;
379 			break;
380 		case ZFS_PROP_ACLTYPE:
381 #ifdef __FreeBSD__
382 			*value = ZFS_ACLTYPE_NFSV4;
383 #else
384 			*value = ZFS_ACLTYPE_OFF;
385 #endif
386 			break;
387 		default:
388 			return (error);
389 		}
390 		error = 0;
391 	}
392 
393 	/*
394 	 * If one of the methods for getting the property value above worked,
395 	 * copy it into the objset_t's cache.
396 	 */
397 	if (error == 0 && cached_copy != NULL) {
398 		*cached_copy = *value;
399 	}
400 
401 	return (error);
402 }
403