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