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 int prop_compression_validate(const char *value, size_t len); 27 static int prop_compression_apply(struct inode *inode, 28 const char *value, 29 size_t len); 30 static const char *prop_compression_extract(struct inode *inode); 31 32 static struct prop_handler prop_handlers[] = { 33 { 34 .xattr_name = XATTR_BTRFS_PREFIX "compression", 35 .validate = prop_compression_validate, 36 .apply = prop_compression_apply, 37 .extract = prop_compression_extract, 38 .inheritable = 1 39 }, 40 }; 41 42 void __init btrfs_props_init(void) 43 { 44 int i; 45 46 hash_init(prop_handlers_ht); 47 48 for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) { 49 struct prop_handler *p = &prop_handlers[i]; 50 u64 h = btrfs_name_hash(p->xattr_name, strlen(p->xattr_name)); 51 52 hash_add(prop_handlers_ht, &p->node, h); 53 } 54 } 55 56 static const struct hlist_head *find_prop_handlers_by_hash(const u64 hash) 57 { 58 struct hlist_head *h; 59 60 h = &prop_handlers_ht[hash_min(hash, BTRFS_PROP_HANDLERS_HT_BITS)]; 61 if (hlist_empty(h)) 62 return NULL; 63 64 return h; 65 } 66 67 static const struct prop_handler * 68 find_prop_handler(const char *name, 69 const struct hlist_head *handlers) 70 { 71 struct prop_handler *h; 72 73 if (!handlers) { 74 u64 hash = btrfs_name_hash(name, strlen(name)); 75 76 handlers = find_prop_handlers_by_hash(hash); 77 if (!handlers) 78 return NULL; 79 } 80 81 hlist_for_each_entry(h, handlers, node) 82 if (!strcmp(h->xattr_name, name)) 83 return h; 84 85 return NULL; 86 } 87 88 static int __btrfs_set_prop(struct btrfs_trans_handle *trans, 89 struct inode *inode, 90 const char *name, 91 const char *value, 92 size_t value_len, 93 int flags) 94 { 95 const struct prop_handler *handler; 96 int ret; 97 98 if (strlen(name) <= XATTR_BTRFS_PREFIX_LEN) 99 return -EINVAL; 100 101 handler = find_prop_handler(name, NULL); 102 if (!handler) 103 return -EINVAL; 104 105 if (value_len == 0) { 106 ret = btrfs_setxattr(trans, inode, handler->xattr_name, 107 NULL, 0, flags); 108 if (ret) 109 return ret; 110 111 ret = handler->apply(inode, NULL, 0); 112 ASSERT(ret == 0); 113 114 return ret; 115 } 116 117 ret = handler->validate(value, value_len); 118 if (ret) 119 return ret; 120 ret = btrfs_setxattr(trans, inode, handler->xattr_name, 121 value, value_len, flags); 122 if (ret) 123 return ret; 124 ret = handler->apply(inode, value, value_len); 125 if (ret) { 126 btrfs_setxattr(trans, inode, handler->xattr_name, 127 NULL, 0, flags); 128 return ret; 129 } 130 131 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags); 132 133 return 0; 134 } 135 136 int btrfs_set_prop(struct inode *inode, 137 const char *name, 138 const char *value, 139 size_t value_len, 140 int flags) 141 { 142 return __btrfs_set_prop(NULL, inode, name, value, value_len, flags); 143 } 144 145 static int iterate_object_props(struct btrfs_root *root, 146 struct btrfs_path *path, 147 u64 objectid, 148 void (*iterator)(void *, 149 const struct prop_handler *, 150 const char *, 151 size_t), 152 void *ctx) 153 { 154 int ret; 155 char *name_buf = NULL; 156 char *value_buf = NULL; 157 int name_buf_len = 0; 158 int value_buf_len = 0; 159 160 while (1) { 161 struct btrfs_key key; 162 struct btrfs_dir_item *di; 163 struct extent_buffer *leaf; 164 u32 total_len, cur, this_len; 165 int slot; 166 const struct hlist_head *handlers; 167 168 slot = path->slots[0]; 169 leaf = path->nodes[0]; 170 171 if (slot >= btrfs_header_nritems(leaf)) { 172 ret = btrfs_next_leaf(root, path); 173 if (ret < 0) 174 goto out; 175 else if (ret > 0) 176 break; 177 continue; 178 } 179 180 btrfs_item_key_to_cpu(leaf, &key, slot); 181 if (key.objectid != objectid) 182 break; 183 if (key.type != BTRFS_XATTR_ITEM_KEY) 184 break; 185 186 handlers = find_prop_handlers_by_hash(key.offset); 187 if (!handlers) 188 goto next_slot; 189 190 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 191 cur = 0; 192 total_len = btrfs_item_size_nr(leaf, slot); 193 194 while (cur < total_len) { 195 u32 name_len = btrfs_dir_name_len(leaf, di); 196 u32 data_len = btrfs_dir_data_len(leaf, di); 197 unsigned long name_ptr, data_ptr; 198 const struct prop_handler *handler; 199 200 this_len = sizeof(*di) + name_len + data_len; 201 name_ptr = (unsigned long)(di + 1); 202 data_ptr = name_ptr + name_len; 203 204 if (name_len <= XATTR_BTRFS_PREFIX_LEN || 205 memcmp_extent_buffer(leaf, XATTR_BTRFS_PREFIX, 206 name_ptr, 207 XATTR_BTRFS_PREFIX_LEN)) 208 goto next_dir_item; 209 210 if (name_len >= name_buf_len) { 211 kfree(name_buf); 212 name_buf_len = name_len + 1; 213 name_buf = kmalloc(name_buf_len, GFP_NOFS); 214 if (!name_buf) { 215 ret = -ENOMEM; 216 goto out; 217 } 218 } 219 read_extent_buffer(leaf, name_buf, name_ptr, name_len); 220 name_buf[name_len] = '\0'; 221 222 handler = find_prop_handler(name_buf, handlers); 223 if (!handler) 224 goto next_dir_item; 225 226 if (data_len > value_buf_len) { 227 kfree(value_buf); 228 value_buf_len = data_len; 229 value_buf = kmalloc(data_len, GFP_NOFS); 230 if (!value_buf) { 231 ret = -ENOMEM; 232 goto out; 233 } 234 } 235 read_extent_buffer(leaf, value_buf, data_ptr, data_len); 236 237 iterator(ctx, handler, value_buf, data_len); 238 next_dir_item: 239 cur += this_len; 240 di = (struct btrfs_dir_item *)((char *) di + this_len); 241 } 242 243 next_slot: 244 path->slots[0]++; 245 } 246 247 ret = 0; 248 out: 249 btrfs_release_path(path); 250 kfree(name_buf); 251 kfree(value_buf); 252 253 return ret; 254 } 255 256 static void inode_prop_iterator(void *ctx, 257 const struct prop_handler *handler, 258 const char *value, 259 size_t len) 260 { 261 struct inode *inode = ctx; 262 struct btrfs_root *root = BTRFS_I(inode)->root; 263 int ret; 264 265 ret = handler->apply(inode, value, len); 266 if (unlikely(ret)) 267 btrfs_warn(root->fs_info, 268 "error applying prop %s to ino %llu (root %llu): %d", 269 handler->xattr_name, btrfs_ino(BTRFS_I(inode)), 270 root->root_key.objectid, ret); 271 else 272 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags); 273 } 274 275 int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path) 276 { 277 struct btrfs_root *root = BTRFS_I(inode)->root; 278 u64 ino = btrfs_ino(BTRFS_I(inode)); 279 int ret; 280 281 ret = iterate_object_props(root, path, ino, inode_prop_iterator, inode); 282 283 return ret; 284 } 285 286 static int inherit_props(struct btrfs_trans_handle *trans, 287 struct inode *inode, 288 struct inode *parent) 289 { 290 struct btrfs_root *root = BTRFS_I(inode)->root; 291 struct btrfs_fs_info *fs_info = root->fs_info; 292 int ret; 293 int i; 294 295 if (!test_bit(BTRFS_INODE_HAS_PROPS, 296 &BTRFS_I(parent)->runtime_flags)) 297 return 0; 298 299 for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) { 300 const struct prop_handler *h = &prop_handlers[i]; 301 const char *value; 302 u64 num_bytes; 303 304 if (!h->inheritable) 305 continue; 306 307 value = h->extract(parent); 308 if (!value) 309 continue; 310 311 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); 312 ret = btrfs_block_rsv_add(root, trans->block_rsv, 313 num_bytes, BTRFS_RESERVE_NO_FLUSH); 314 if (ret) 315 goto out; 316 ret = __btrfs_set_prop(trans, inode, h->xattr_name, 317 value, strlen(value), 0); 318 btrfs_block_rsv_release(fs_info, trans->block_rsv, num_bytes); 319 if (ret) 320 goto out; 321 } 322 ret = 0; 323 out: 324 return ret; 325 } 326 327 int btrfs_inode_inherit_props(struct btrfs_trans_handle *trans, 328 struct inode *inode, 329 struct inode *dir) 330 { 331 if (!dir) 332 return 0; 333 334 return inherit_props(trans, inode, dir); 335 } 336 337 int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans, 338 struct btrfs_root *root, 339 struct btrfs_root *parent_root) 340 { 341 struct super_block *sb = root->fs_info->sb; 342 struct btrfs_key key; 343 struct inode *parent_inode, *child_inode; 344 int ret; 345 346 key.objectid = BTRFS_FIRST_FREE_OBJECTID; 347 key.type = BTRFS_INODE_ITEM_KEY; 348 key.offset = 0; 349 350 parent_inode = btrfs_iget(sb, &key, parent_root, NULL); 351 if (IS_ERR(parent_inode)) 352 return PTR_ERR(parent_inode); 353 354 child_inode = btrfs_iget(sb, &key, root, NULL); 355 if (IS_ERR(child_inode)) { 356 iput(parent_inode); 357 return PTR_ERR(child_inode); 358 } 359 360 ret = inherit_props(trans, child_inode, parent_inode); 361 iput(child_inode); 362 iput(parent_inode); 363 364 return ret; 365 } 366 367 static int prop_compression_validate(const char *value, size_t len) 368 { 369 if (!strncmp("lzo", value, len)) 370 return 0; 371 else if (!strncmp("zlib", value, len)) 372 return 0; 373 else if (!strncmp("zstd", value, len)) 374 return 0; 375 376 return -EINVAL; 377 } 378 379 static int prop_compression_apply(struct inode *inode, 380 const char *value, 381 size_t len) 382 { 383 int type; 384 385 if (len == 0) { 386 BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; 387 BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS; 388 BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE; 389 390 return 0; 391 } 392 393 if (!strncmp("lzo", value, 3)) 394 type = BTRFS_COMPRESS_LZO; 395 else if (!strncmp("zlib", value, 4)) 396 type = BTRFS_COMPRESS_ZLIB; 397 else if (!strncmp("zstd", value, len)) 398 type = BTRFS_COMPRESS_ZSTD; 399 else 400 return -EINVAL; 401 402 BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; 403 BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; 404 BTRFS_I(inode)->prop_compress = type; 405 406 return 0; 407 } 408 409 static const char *prop_compression_extract(struct inode *inode) 410 { 411 switch (BTRFS_I(inode)->prop_compress) { 412 case BTRFS_COMPRESS_ZLIB: 413 case BTRFS_COMPRESS_LZO: 414 case BTRFS_COMPRESS_ZSTD: 415 return btrfs_compress_type2str(BTRFS_I(inode)->prop_compress); 416 default: 417 break; 418 } 419 420 return NULL; 421 } 422 423 424