1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com> 4 */ 5 6 #include <linux/hashtable.h> 7 #include "props.h" 8 #include "btrfs_inode.h" 9 #include "transaction.h" 10 #include "ctree.h" 11 #include "xattr.h" 12 #include "compression.h" 13 14 #define BTRFS_PROP_HANDLERS_HT_BITS 8 15 static DEFINE_HASHTABLE(prop_handlers_ht, BTRFS_PROP_HANDLERS_HT_BITS); 16 17 struct prop_handler { 18 struct hlist_node node; 19 const char *xattr_name; 20 int (*validate)(const char *value, size_t len); 21 int (*apply)(struct inode *inode, const char *value, size_t len); 22 const char *(*extract)(struct inode *inode); 23 int inheritable; 24 }; 25 26 static const struct hlist_head *find_prop_handlers_by_hash(const u64 hash) 27 { 28 struct hlist_head *h; 29 30 h = &prop_handlers_ht[hash_min(hash, BTRFS_PROP_HANDLERS_HT_BITS)]; 31 if (hlist_empty(h)) 32 return NULL; 33 34 return h; 35 } 36 37 static const struct prop_handler * 38 find_prop_handler(const char *name, 39 const struct hlist_head *handlers) 40 { 41 struct prop_handler *h; 42 43 if (!handlers) { 44 u64 hash = btrfs_name_hash(name, strlen(name)); 45 46 handlers = find_prop_handlers_by_hash(hash); 47 if (!handlers) 48 return NULL; 49 } 50 51 hlist_for_each_entry(h, handlers, node) 52 if (!strcmp(h->xattr_name, name)) 53 return h; 54 55 return NULL; 56 } 57 58 int btrfs_validate_prop(const char *name, const char *value, size_t value_len) 59 { 60 const struct prop_handler *handler; 61 62 if (strlen(name) <= XATTR_BTRFS_PREFIX_LEN) 63 return -EINVAL; 64 65 handler = find_prop_handler(name, NULL); 66 if (!handler) 67 return -EINVAL; 68 69 if (value_len == 0) 70 return 0; 71 72 return handler->validate(value, value_len); 73 } 74 75 int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode, 76 const char *name, const char *value, size_t value_len, 77 int flags) 78 { 79 const struct prop_handler *handler; 80 int ret; 81 82 handler = find_prop_handler(name, NULL); 83 if (!handler) 84 return -EINVAL; 85 86 if (value_len == 0) { 87 ret = btrfs_setxattr(trans, inode, handler->xattr_name, 88 NULL, 0, flags); 89 if (ret) 90 return ret; 91 92 ret = handler->apply(inode, NULL, 0); 93 ASSERT(ret == 0); 94 95 return ret; 96 } 97 98 ret = btrfs_setxattr(trans, inode, handler->xattr_name, value, 99 value_len, flags); 100 if (ret) 101 return ret; 102 ret = handler->apply(inode, value, value_len); 103 if (ret) { 104 btrfs_setxattr(trans, inode, handler->xattr_name, NULL, 105 0, flags); 106 return ret; 107 } 108 109 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags); 110 111 return 0; 112 } 113 114 static int iterate_object_props(struct btrfs_root *root, 115 struct btrfs_path *path, 116 u64 objectid, 117 void (*iterator)(void *, 118 const struct prop_handler *, 119 const char *, 120 size_t), 121 void *ctx) 122 { 123 int ret; 124 char *name_buf = NULL; 125 char *value_buf = NULL; 126 int name_buf_len = 0; 127 int value_buf_len = 0; 128 129 while (1) { 130 struct btrfs_key key; 131 struct btrfs_dir_item *di; 132 struct extent_buffer *leaf; 133 u32 total_len, cur, this_len; 134 int slot; 135 const struct hlist_head *handlers; 136 137 slot = path->slots[0]; 138 leaf = path->nodes[0]; 139 140 if (slot >= btrfs_header_nritems(leaf)) { 141 ret = btrfs_next_leaf(root, path); 142 if (ret < 0) 143 goto out; 144 else if (ret > 0) 145 break; 146 continue; 147 } 148 149 btrfs_item_key_to_cpu(leaf, &key, slot); 150 if (key.objectid != objectid) 151 break; 152 if (key.type != BTRFS_XATTR_ITEM_KEY) 153 break; 154 155 handlers = find_prop_handlers_by_hash(key.offset); 156 if (!handlers) 157 goto next_slot; 158 159 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 160 cur = 0; 161 total_len = btrfs_item_size_nr(leaf, slot); 162 163 while (cur < total_len) { 164 u32 name_len = btrfs_dir_name_len(leaf, di); 165 u32 data_len = btrfs_dir_data_len(leaf, di); 166 unsigned long name_ptr, data_ptr; 167 const struct prop_handler *handler; 168 169 this_len = sizeof(*di) + name_len + data_len; 170 name_ptr = (unsigned long)(di + 1); 171 data_ptr = name_ptr + name_len; 172 173 if (name_len <= XATTR_BTRFS_PREFIX_LEN || 174 memcmp_extent_buffer(leaf, XATTR_BTRFS_PREFIX, 175 name_ptr, 176 XATTR_BTRFS_PREFIX_LEN)) 177 goto next_dir_item; 178 179 if (name_len >= name_buf_len) { 180 kfree(name_buf); 181 name_buf_len = name_len + 1; 182 name_buf = kmalloc(name_buf_len, GFP_NOFS); 183 if (!name_buf) { 184 ret = -ENOMEM; 185 goto out; 186 } 187 } 188 read_extent_buffer(leaf, name_buf, name_ptr, name_len); 189 name_buf[name_len] = '\0'; 190 191 handler = find_prop_handler(name_buf, handlers); 192 if (!handler) 193 goto next_dir_item; 194 195 if (data_len > value_buf_len) { 196 kfree(value_buf); 197 value_buf_len = data_len; 198 value_buf = kmalloc(data_len, GFP_NOFS); 199 if (!value_buf) { 200 ret = -ENOMEM; 201 goto out; 202 } 203 } 204 read_extent_buffer(leaf, value_buf, data_ptr, data_len); 205 206 iterator(ctx, handler, value_buf, data_len); 207 next_dir_item: 208 cur += this_len; 209 di = (struct btrfs_dir_item *)((char *) di + this_len); 210 } 211 212 next_slot: 213 path->slots[0]++; 214 } 215 216 ret = 0; 217 out: 218 btrfs_release_path(path); 219 kfree(name_buf); 220 kfree(value_buf); 221 222 return ret; 223 } 224 225 static void inode_prop_iterator(void *ctx, 226 const struct prop_handler *handler, 227 const char *value, 228 size_t len) 229 { 230 struct inode *inode = ctx; 231 struct btrfs_root *root = BTRFS_I(inode)->root; 232 int ret; 233 234 ret = handler->apply(inode, value, len); 235 if (unlikely(ret)) 236 btrfs_warn(root->fs_info, 237 "error applying prop %s to ino %llu (root %llu): %d", 238 handler->xattr_name, btrfs_ino(BTRFS_I(inode)), 239 root->root_key.objectid, ret); 240 else 241 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags); 242 } 243 244 int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path) 245 { 246 struct btrfs_root *root = BTRFS_I(inode)->root; 247 u64 ino = btrfs_ino(BTRFS_I(inode)); 248 int ret; 249 250 ret = iterate_object_props(root, path, ino, inode_prop_iterator, inode); 251 252 return ret; 253 } 254 255 static int prop_compression_validate(const char *value, size_t len) 256 { 257 if (!value) 258 return 0; 259 260 if (btrfs_compress_is_valid_type(value, len)) 261 return 0; 262 263 if ((len == 2 && strncmp("no", value, 2) == 0) || 264 (len == 4 && strncmp("none", value, 4) == 0)) 265 return 0; 266 267 return -EINVAL; 268 } 269 270 static int prop_compression_apply(struct inode *inode, const char *value, 271 size_t len) 272 { 273 struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); 274 int type; 275 276 /* Reset to defaults */ 277 if (len == 0) { 278 BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS; 279 BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; 280 BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE; 281 return 0; 282 } 283 284 /* Set NOCOMPRESS flag */ 285 if ((len == 2 && strncmp("no", value, 2) == 0) || 286 (len == 4 && strncmp("none", value, 4) == 0)) { 287 BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; 288 BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS; 289 BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE; 290 291 return 0; 292 } 293 294 if (!strncmp("lzo", value, 3)) { 295 type = BTRFS_COMPRESS_LZO; 296 btrfs_set_fs_incompat(fs_info, COMPRESS_LZO); 297 } else if (!strncmp("zlib", value, 4)) { 298 type = BTRFS_COMPRESS_ZLIB; 299 } else if (!strncmp("zstd", value, 4)) { 300 type = BTRFS_COMPRESS_ZSTD; 301 btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD); 302 } else { 303 return -EINVAL; 304 } 305 306 BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; 307 BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; 308 BTRFS_I(inode)->prop_compress = type; 309 310 return 0; 311 } 312 313 static const char *prop_compression_extract(struct inode *inode) 314 { 315 switch (BTRFS_I(inode)->prop_compress) { 316 case BTRFS_COMPRESS_ZLIB: 317 case BTRFS_COMPRESS_LZO: 318 case BTRFS_COMPRESS_ZSTD: 319 return btrfs_compress_type2str(BTRFS_I(inode)->prop_compress); 320 default: 321 break; 322 } 323 324 return NULL; 325 } 326 327 static struct prop_handler prop_handlers[] = { 328 { 329 .xattr_name = XATTR_BTRFS_PREFIX "compression", 330 .validate = prop_compression_validate, 331 .apply = prop_compression_apply, 332 .extract = prop_compression_extract, 333 .inheritable = 1 334 }, 335 }; 336 337 static int inherit_props(struct btrfs_trans_handle *trans, 338 struct inode *inode, 339 struct inode *parent) 340 { 341 struct btrfs_root *root = BTRFS_I(inode)->root; 342 struct btrfs_fs_info *fs_info = root->fs_info; 343 int ret; 344 int i; 345 bool need_reserve = false; 346 347 if (!test_bit(BTRFS_INODE_HAS_PROPS, 348 &BTRFS_I(parent)->runtime_flags)) 349 return 0; 350 351 for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) { 352 const struct prop_handler *h = &prop_handlers[i]; 353 const char *value; 354 u64 num_bytes = 0; 355 356 if (!h->inheritable) 357 continue; 358 359 value = h->extract(parent); 360 if (!value) 361 continue; 362 363 /* 364 * This is not strictly necessary as the property should be 365 * valid, but in case it isn't, don't propagate it further. 366 */ 367 ret = h->validate(value, strlen(value)); 368 if (ret) 369 continue; 370 371 /* 372 * Currently callers should be reserving 1 item for properties, 373 * since we only have 1 property that we currently support. If 374 * we add more in the future we need to try and reserve more 375 * space for them. But we should also revisit how we do space 376 * reservations if we do add more properties in the future. 377 */ 378 if (need_reserve) { 379 num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1); 380 ret = btrfs_block_rsv_add(root, trans->block_rsv, 381 num_bytes, BTRFS_RESERVE_NO_FLUSH); 382 if (ret) 383 return ret; 384 } 385 386 ret = btrfs_setxattr(trans, inode, h->xattr_name, value, 387 strlen(value), 0); 388 if (!ret) { 389 ret = h->apply(inode, value, strlen(value)); 390 if (ret) 391 btrfs_setxattr(trans, inode, h->xattr_name, 392 NULL, 0, 0); 393 else 394 set_bit(BTRFS_INODE_HAS_PROPS, 395 &BTRFS_I(inode)->runtime_flags); 396 } 397 398 if (need_reserve) { 399 btrfs_block_rsv_release(fs_info, trans->block_rsv, 400 num_bytes, NULL); 401 if (ret) 402 return ret; 403 } 404 need_reserve = true; 405 } 406 407 return 0; 408 } 409 410 int btrfs_inode_inherit_props(struct btrfs_trans_handle *trans, 411 struct inode *inode, 412 struct inode *dir) 413 { 414 if (!dir) 415 return 0; 416 417 return inherit_props(trans, inode, dir); 418 } 419 420 int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans, 421 struct btrfs_root *root, 422 struct btrfs_root *parent_root) 423 { 424 struct super_block *sb = root->fs_info->sb; 425 struct inode *parent_inode, *child_inode; 426 int ret; 427 428 parent_inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, parent_root); 429 if (IS_ERR(parent_inode)) 430 return PTR_ERR(parent_inode); 431 432 child_inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, root); 433 if (IS_ERR(child_inode)) { 434 iput(parent_inode); 435 return PTR_ERR(child_inode); 436 } 437 438 ret = inherit_props(trans, child_inode, parent_inode); 439 iput(child_inode); 440 iput(parent_inode); 441 442 return ret; 443 } 444 445 void __init btrfs_props_init(void) 446 { 447 int i; 448 449 for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) { 450 struct prop_handler *p = &prop_handlers[i]; 451 u64 h = btrfs_name_hash(p->xattr_name, strlen(p->xattr_name)); 452 453 hash_add(prop_handlers_ht, &p->node, h); 454 } 455 } 456 457