diff options
-rw-r--r-- | fs/btrfs/inode.c | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d75ca5cf59b1..f95cf5d4a69d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -46,6 +46,7 @@ struct btrfs_iget_args { | |||
46 | static struct inode_operations btrfs_dir_inode_operations; | 46 | static struct inode_operations btrfs_dir_inode_operations; |
47 | static struct inode_operations btrfs_symlink_inode_operations; | 47 | static struct inode_operations btrfs_symlink_inode_operations; |
48 | static struct inode_operations btrfs_dir_ro_inode_operations; | 48 | static struct inode_operations btrfs_dir_ro_inode_operations; |
49 | static struct inode_operations btrfs_special_inode_operations; | ||
49 | static struct inode_operations btrfs_file_inode_operations; | 50 | static struct inode_operations btrfs_file_inode_operations; |
50 | static struct address_space_operations btrfs_aops; | 51 | static struct address_space_operations btrfs_aops; |
51 | static struct address_space_operations btrfs_symlink_aops; | 52 | static struct address_space_operations btrfs_symlink_aops; |
@@ -75,6 +76,7 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
75 | struct btrfs_root *root = BTRFS_I(inode)->root; | 76 | struct btrfs_root *root = BTRFS_I(inode)->root; |
76 | struct btrfs_key location; | 77 | struct btrfs_key location; |
77 | u64 alloc_group_block; | 78 | u64 alloc_group_block; |
79 | u32 rdev; | ||
78 | int ret; | 80 | int ret; |
79 | 81 | ||
80 | path = btrfs_alloc_path(); | 82 | path = btrfs_alloc_path(); |
@@ -104,6 +106,8 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
104 | inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); | 106 | inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); |
105 | inode->i_blocks = btrfs_inode_nblocks(inode_item); | 107 | inode->i_blocks = btrfs_inode_nblocks(inode_item); |
106 | inode->i_generation = btrfs_inode_generation(inode_item); | 108 | inode->i_generation = btrfs_inode_generation(inode_item); |
109 | inode->i_rdev = 0; | ||
110 | rdev = btrfs_inode_rdev(inode_item); | ||
107 | alloc_group_block = btrfs_inode_block_group(inode_item); | 111 | alloc_group_block = btrfs_inode_block_group(inode_item); |
108 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, | 112 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, |
109 | alloc_group_block); | 113 | alloc_group_block); |
@@ -114,12 +118,6 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
114 | mutex_unlock(&root->fs_info->fs_mutex); | 118 | mutex_unlock(&root->fs_info->fs_mutex); |
115 | 119 | ||
116 | switch (inode->i_mode & S_IFMT) { | 120 | switch (inode->i_mode & S_IFMT) { |
117 | #if 0 | ||
118 | default: | ||
119 | init_special_inode(inode, inode->i_mode, | ||
120 | btrfs_inode_rdev(inode_item)); | ||
121 | break; | ||
122 | #endif | ||
123 | case S_IFREG: | 121 | case S_IFREG: |
124 | inode->i_mapping->a_ops = &btrfs_aops; | 122 | inode->i_mapping->a_ops = &btrfs_aops; |
125 | inode->i_fop = &btrfs_file_operations; | 123 | inode->i_fop = &btrfs_file_operations; |
@@ -136,6 +134,9 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
136 | inode->i_op = &btrfs_symlink_inode_operations; | 134 | inode->i_op = &btrfs_symlink_inode_operations; |
137 | inode->i_mapping->a_ops = &btrfs_symlink_aops; | 135 | inode->i_mapping->a_ops = &btrfs_symlink_aops; |
138 | break; | 136 | break; |
137 | default: | ||
138 | init_special_inode(inode, inode->i_mode, rdev); | ||
139 | break; | ||
139 | } | 140 | } |
140 | return; | 141 | return; |
141 | 142 | ||
@@ -162,6 +163,7 @@ static void fill_inode_item(struct btrfs_inode_item *item, | |||
162 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | 163 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); |
163 | btrfs_set_inode_nblocks(item, inode->i_blocks); | 164 | btrfs_set_inode_nblocks(item, inode->i_blocks); |
164 | btrfs_set_inode_generation(item, inode->i_generation); | 165 | btrfs_set_inode_generation(item, inode->i_generation); |
166 | btrfs_set_inode_rdev(item, inode->i_rdev); | ||
165 | btrfs_set_inode_block_group(item, | 167 | btrfs_set_inode_block_group(item, |
166 | BTRFS_I(inode)->block_group->key.objectid); | 168 | BTRFS_I(inode)->block_group->key.objectid); |
167 | } | 169 | } |
@@ -1070,6 +1072,58 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | |||
1070 | return err; | 1072 | return err; |
1071 | } | 1073 | } |
1072 | 1074 | ||
1075 | static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | ||
1076 | int mode, dev_t rdev) | ||
1077 | { | ||
1078 | struct btrfs_trans_handle *trans; | ||
1079 | struct btrfs_root *root = BTRFS_I(dir)->root; | ||
1080 | struct inode *inode; | ||
1081 | int err; | ||
1082 | int drop_inode = 0; | ||
1083 | u64 objectid; | ||
1084 | |||
1085 | if (!new_valid_dev(rdev)) | ||
1086 | return -EINVAL; | ||
1087 | |||
1088 | mutex_lock(&root->fs_info->fs_mutex); | ||
1089 | trans = btrfs_start_transaction(root, 1); | ||
1090 | btrfs_set_trans_block_group(trans, dir); | ||
1091 | |||
1092 | err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); | ||
1093 | if (err) { | ||
1094 | err = -ENOSPC; | ||
1095 | goto out_unlock; | ||
1096 | } | ||
1097 | |||
1098 | inode = btrfs_new_inode(trans, root, objectid, | ||
1099 | BTRFS_I(dir)->block_group, mode); | ||
1100 | err = PTR_ERR(inode); | ||
1101 | if (IS_ERR(inode)) | ||
1102 | goto out_unlock; | ||
1103 | |||
1104 | btrfs_set_trans_block_group(trans, inode); | ||
1105 | err = btrfs_add_nondir(trans, dentry, inode); | ||
1106 | if (err) | ||
1107 | drop_inode = 1; | ||
1108 | else { | ||
1109 | inode->i_op = &btrfs_special_inode_operations; | ||
1110 | init_special_inode(inode, inode->i_mode, rdev); | ||
1111 | } | ||
1112 | dir->i_sb->s_dirt = 1; | ||
1113 | btrfs_update_inode_block_group(trans, inode); | ||
1114 | btrfs_update_inode_block_group(trans, dir); | ||
1115 | out_unlock: | ||
1116 | btrfs_end_transaction(trans, root); | ||
1117 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1118 | |||
1119 | if (drop_inode) { | ||
1120 | inode_dec_link_count(inode); | ||
1121 | iput(inode); | ||
1122 | } | ||
1123 | btrfs_btree_balance_dirty(root); | ||
1124 | return err; | ||
1125 | } | ||
1126 | |||
1073 | static int btrfs_create(struct inode *dir, struct dentry *dentry, | 1127 | static int btrfs_create(struct inode *dir, struct dentry *dentry, |
1074 | int mode, struct nameidata *nd) | 1128 | int mode, struct nameidata *nd) |
1075 | { | 1129 | { |
@@ -2526,6 +2580,7 @@ static struct inode_operations btrfs_dir_inode_operations = { | |||
2526 | .rename = btrfs_rename, | 2580 | .rename = btrfs_rename, |
2527 | .symlink = btrfs_symlink, | 2581 | .symlink = btrfs_symlink, |
2528 | .setattr = btrfs_setattr, | 2582 | .setattr = btrfs_setattr, |
2583 | .mknod = btrfs_mknod, | ||
2529 | }; | 2584 | }; |
2530 | 2585 | ||
2531 | static struct inode_operations btrfs_dir_ro_inode_operations = { | 2586 | static struct inode_operations btrfs_dir_ro_inode_operations = { |
@@ -2562,6 +2617,11 @@ static struct inode_operations btrfs_file_inode_operations = { | |||
2562 | .setattr = btrfs_setattr, | 2617 | .setattr = btrfs_setattr, |
2563 | }; | 2618 | }; |
2564 | 2619 | ||
2620 | static struct inode_operations btrfs_special_inode_operations = { | ||
2621 | .getattr = btrfs_getattr, | ||
2622 | .setattr = btrfs_setattr, | ||
2623 | }; | ||
2624 | |||
2565 | static struct inode_operations btrfs_symlink_inode_operations = { | 2625 | static struct inode_operations btrfs_symlink_inode_operations = { |
2566 | .readlink = generic_readlink, | 2626 | .readlink = generic_readlink, |
2567 | .follow_link = page_follow_link_light, | 2627 | .follow_link = page_follow_link_light, |