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