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 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 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 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 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 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 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 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 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 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 case ZFS_PROP_DEFAULTUSERQUOTA: 388 case ZFS_PROP_DEFAULTGROUPQUOTA: 389 case ZFS_PROP_DEFAULTPROJECTQUOTA: 390 case ZFS_PROP_DEFAULTUSEROBJQUOTA: 391 case ZFS_PROP_DEFAULTGROUPOBJQUOTA: 392 case ZFS_PROP_DEFAULTPROJECTOBJQUOTA: 393 *value = 0; 394 return (0); 395 default: 396 return (error); 397 } 398 error = 0; 399 } 400 401 /* 402 * If one of the methods for getting the property value above worked, 403 * copy it into the objset_t's cache. 404 */ 405 if (error == 0 && cached_copy != NULL) { 406 *cached_copy = *value; 407 } 408 409 return (error); 410 } 411