aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-24 08:34:10 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-24 08:34:10 -0400
commit2b8d99a723a3186a69b5bd941a272dbecae9205b (patch)
treec3f87b82450110d2df8ac03032bd2e21b8984f19 /fs/btrfs/super.c
parente06afa839e726959be2166bec4cb85c117e213f1 (diff)
Btrfs: symlinks and hard links
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c163
1 files changed, 147 insertions, 16 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f49cad603ee8..c1a0adde9b1c 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -26,11 +26,13 @@ struct btrfs_iget_args {
26#define BTRFS_SUPER_MAGIC 0x9123682E 26#define BTRFS_SUPER_MAGIC 0x9123682E
27 27
28static struct inode_operations btrfs_dir_inode_operations; 28static struct inode_operations btrfs_dir_inode_operations;
29static struct inode_operations btrfs_symlink_inode_operations;
29static struct inode_operations btrfs_dir_ro_inode_operations; 30static struct inode_operations btrfs_dir_ro_inode_operations;
30static struct super_operations btrfs_super_ops; 31static struct super_operations btrfs_super_ops;
31static struct file_operations btrfs_dir_file_operations; 32static struct file_operations btrfs_dir_file_operations;
32static struct inode_operations btrfs_file_inode_operations; 33static struct inode_operations btrfs_file_inode_operations;
33static struct address_space_operations btrfs_aops; 34static struct address_space_operations btrfs_aops;
35static struct address_space_operations btrfs_symlink_aops;
34static struct file_operations btrfs_file_operations; 36static struct file_operations btrfs_file_operations;
35 37
36static void btrfs_read_locked_inode(struct inode *inode) 38static void btrfs_read_locked_inode(struct inode *inode)
@@ -103,7 +105,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
103 inode->i_op = &btrfs_dir_inode_operations; 105 inode->i_op = &btrfs_dir_inode_operations;
104 break; 106 break;
105 case S_IFLNK: 107 case S_IFLNK:
106 // inode->i_op = &page_symlink_inode_operations; 108 inode->i_op = &btrfs_symlink_inode_operations;
109 inode->i_mapping->a_ops = &btrfs_symlink_aops;
107 break; 110 break;
108 } 111 }
109 return; 112 return;
@@ -940,6 +943,41 @@ out_unlock:
940 return err; 943 return err;
941} 944}
942 945
946static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
947 struct dentry *dentry)
948{
949 struct btrfs_trans_handle *trans;
950 struct btrfs_root *root = BTRFS_I(dir)->root;
951 struct inode *inode = old_dentry->d_inode;
952 int err;
953 int drop_inode = 0;
954
955 if (inode->i_nlink == 0)
956 return -ENOENT;
957
958 inc_nlink(inode);
959 mutex_lock(&root->fs_info->fs_mutex);
960 trans = btrfs_start_transaction(root, 1);
961 btrfs_set_trans_block_group(trans, dir);
962 atomic_inc(&inode->i_count);
963 err = btrfs_add_nondir(trans, dentry, inode);
964 if (err)
965 drop_inode = 1;
966 dir->i_sb->s_dirt = 1;
967 btrfs_update_inode_block_group(trans, dir);
968 btrfs_update_inode(trans, root, inode);
969
970 btrfs_end_transaction(trans, root);
971 mutex_unlock(&root->fs_info->fs_mutex);
972
973 if (drop_inode) {
974 inode_dec_link_count(inode);
975 iput(inode);
976 }
977 btrfs_btree_balance_dirty(root);
978 return err;
979}
980
943static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans, 981static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans,
944 struct btrfs_root *root, 982 struct btrfs_root *root,
945 u64 objectid, u64 dirid) 983 u64 objectid, u64 dirid)
@@ -2577,33 +2615,25 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
2577 } 2615 }
2578 2616
2579 2617
2580 ret = btrfs_add_link(trans, new_dentry, old_inode);
2581 if (ret == -EEXIST && new_inode)
2582 ret = 0;
2583 else if (ret)
2584 goto out_fail;
2585
2586 ret = btrfs_unlink_trans(trans, root, old_dir, old_dentry); 2618 ret = btrfs_unlink_trans(trans, root, old_dir, old_dentry);
2587 if (ret) 2619 if (ret)
2588 goto out_fail; 2620 goto out_fail;
2589 2621
2590 if (new_inode) { 2622 if (new_inode) {
2591 new_inode->i_ctime = CURRENT_TIME; 2623 new_inode->i_ctime = CURRENT_TIME;
2592 di = btrfs_lookup_dir_index_item(trans, root, path, 2624 ret = btrfs_unlink_trans(trans, root, new_dir, new_dentry);
2593 new_dir->i_ino, 2625 if (ret)
2594 new_inode->i_ino, 2626 goto out_fail;
2595 new_dentry->d_name.name,
2596 new_dentry->d_name.len, -1);
2597 if (di && !IS_ERR(di)) {
2598 btrfs_del_item(trans, root, path);
2599 btrfs_release_path(root, path);
2600 }
2601 if (S_ISDIR(new_inode->i_mode)) 2627 if (S_ISDIR(new_inode->i_mode))
2602 clear_nlink(new_inode); 2628 clear_nlink(new_inode);
2603 else 2629 else
2604 drop_nlink(new_inode); 2630 drop_nlink(new_inode);
2605 btrfs_update_inode(trans, root, new_inode); 2631 btrfs_update_inode(trans, root, new_inode);
2606 } 2632 }
2633 ret = btrfs_add_link(trans, new_dentry, old_inode);
2634 if (ret)
2635 goto out_fail;
2636
2607out_fail: 2637out_fail:
2608 btrfs_free_path(path); 2638 btrfs_free_path(path);
2609 btrfs_end_transaction(trans, root); 2639 btrfs_end_transaction(trans, root);
@@ -2611,6 +2641,94 @@ out_fail:
2611 return ret; 2641 return ret;
2612} 2642}
2613 2643
2644static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
2645 const char *symname)
2646{
2647 struct btrfs_trans_handle *trans;
2648 struct btrfs_root *root = BTRFS_I(dir)->root;
2649 struct btrfs_path *path;
2650 struct btrfs_key key;
2651 struct inode *inode;
2652 int err;
2653 int drop_inode = 0;
2654 u64 objectid;
2655 int name_len;
2656 int datasize;
2657 char *ptr;
2658 struct btrfs_file_extent_item *ei;
2659
2660 name_len = strlen(symname) + 1;
2661 if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
2662 return -ENAMETOOLONG;
2663 mutex_lock(&root->fs_info->fs_mutex);
2664 trans = btrfs_start_transaction(root, 1);
2665 btrfs_set_trans_block_group(trans, dir);
2666
2667 err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
2668 if (err) {
2669 err = -ENOSPC;
2670 goto out_unlock;
2671 }
2672
2673 inode = btrfs_new_inode(trans, root, objectid,
2674 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO);
2675 err = PTR_ERR(inode);
2676 if (IS_ERR(inode))
2677 goto out_unlock;
2678
2679 btrfs_set_trans_block_group(trans, inode);
2680 err = btrfs_add_nondir(trans, dentry, inode);
2681 if (err)
2682 drop_inode = 1;
2683 else {
2684 inode->i_mapping->a_ops = &btrfs_aops;
2685 inode->i_fop = &btrfs_file_operations;
2686 inode->i_op = &btrfs_file_inode_operations;
2687 }
2688 dir->i_sb->s_dirt = 1;
2689 btrfs_update_inode_block_group(trans, inode);
2690 btrfs_update_inode_block_group(trans, dir);
2691 if (drop_inode)
2692 goto out_unlock;
2693
2694 path = btrfs_alloc_path();
2695 BUG_ON(!path);
2696 key.objectid = inode->i_ino;
2697 key.offset = 0;
2698 key.flags = 0;
2699 btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
2700 datasize = btrfs_file_extent_calc_inline_size(name_len);
2701 err = btrfs_insert_empty_item(trans, root, path, &key,
2702 datasize);
2703 BUG_ON(err);
2704 ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
2705 path->slots[0], struct btrfs_file_extent_item);
2706 btrfs_set_file_extent_generation(ei, trans->transid);
2707 btrfs_set_file_extent_type(ei,
2708 BTRFS_FILE_EXTENT_INLINE);
2709 ptr = btrfs_file_extent_inline_start(ei);
2710 btrfs_memcpy(root, path->nodes[0]->b_data,
2711 ptr, symname, name_len);
2712 mark_buffer_dirty(path->nodes[0]);
2713 btrfs_free_path(path);
2714 inode->i_op = &btrfs_symlink_inode_operations;
2715 inode->i_mapping->a_ops = &btrfs_symlink_aops;
2716 inode->i_size = name_len - 1;
2717 btrfs_update_inode(trans, root, inode);
2718 err = 0;
2719
2720out_unlock:
2721 btrfs_end_transaction(trans, root);
2722 mutex_unlock(&root->fs_info->fs_mutex);
2723
2724 if (drop_inode) {
2725 inode_dec_link_count(inode);
2726 iput(inode);
2727 }
2728 btrfs_btree_balance_dirty(root);
2729 return err;
2730}
2731
2614static struct file_system_type btrfs_fs_type = { 2732static struct file_system_type btrfs_fs_type = {
2615 .owner = THIS_MODULE, 2733 .owner = THIS_MODULE,
2616 .name = "btrfs", 2734 .name = "btrfs",
@@ -2636,9 +2754,11 @@ static struct inode_operations btrfs_dir_inode_operations = {
2636 .lookup = btrfs_lookup, 2754 .lookup = btrfs_lookup,
2637 .create = btrfs_create, 2755 .create = btrfs_create,
2638 .unlink = btrfs_unlink, 2756 .unlink = btrfs_unlink,
2757 .link = btrfs_link,
2639 .mkdir = btrfs_mkdir, 2758 .mkdir = btrfs_mkdir,
2640 .rmdir = btrfs_rmdir, 2759 .rmdir = btrfs_rmdir,
2641 .rename = btrfs_rename, 2760 .rename = btrfs_rename,
2761 .symlink = btrfs_symlink,
2642}; 2762};
2643 2763
2644static struct inode_operations btrfs_dir_ro_inode_operations = { 2764static struct inode_operations btrfs_dir_ro_inode_operations = {
@@ -2660,6 +2780,11 @@ static struct address_space_operations btrfs_aops = {
2660 .commit_write = btrfs_commit_write, 2780 .commit_write = btrfs_commit_write,
2661}; 2781};
2662 2782
2783static struct address_space_operations btrfs_symlink_aops = {
2784 .readpage = btrfs_readpage,
2785 .writepage = btrfs_writepage,
2786};
2787
2663static struct inode_operations btrfs_file_inode_operations = { 2788static struct inode_operations btrfs_file_inode_operations = {
2664 .truncate = btrfs_truncate, 2789 .truncate = btrfs_truncate,
2665 .getattr = btrfs_getattr, 2790 .getattr = btrfs_getattr,
@@ -2676,6 +2801,12 @@ static struct file_operations btrfs_file_operations = {
2676 .fsync = btrfs_sync_file, 2801 .fsync = btrfs_sync_file,
2677}; 2802};
2678 2803
2804static struct inode_operations btrfs_symlink_inode_operations = {
2805 .readlink = generic_readlink,
2806 .follow_link = page_follow_link_light,
2807 .put_link = page_put_link,
2808};
2809
2679static int __init init_btrfs_fs(void) 2810static int __init init_btrfs_fs(void)
2680{ 2811{
2681 int err; 2812 int err;