X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=fs%2Fbtrfs%2Finode.c;h=f95cf5d4a69d2c209cdf8e20779c63f62377705d;hb=618e21d5957c88c5ea346dfd7d1dbac96410fc5b;hp=9d2a0a3f674d7e7b77aa35ae0336e21990501ebc;hpb=5eda7b5e9b0bed864dd18284c7df9b3c8207dad7;p=linux-2.6-omap-h63xx.git diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9d2a0a3f674..f95cf5d4a69 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -16,7 +16,6 @@ * Boston, MA 021110-1307, USA. */ -#include #include #include #include @@ -47,6 +46,7 @@ struct btrfs_iget_args { static struct inode_operations btrfs_dir_inode_operations; static struct inode_operations btrfs_symlink_inode_operations; static struct inode_operations btrfs_dir_ro_inode_operations; +static struct inode_operations btrfs_special_inode_operations; static struct inode_operations btrfs_file_inode_operations; static struct address_space_operations btrfs_aops; static struct address_space_operations btrfs_symlink_aops; @@ -76,6 +76,7 @@ void btrfs_read_locked_inode(struct inode *inode) struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_key location; u64 alloc_group_block; + u32 rdev; int ret; path = btrfs_alloc_path(); @@ -105,6 +106,8 @@ void btrfs_read_locked_inode(struct inode *inode) inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); inode->i_blocks = btrfs_inode_nblocks(inode_item); inode->i_generation = btrfs_inode_generation(inode_item); + inode->i_rdev = 0; + rdev = btrfs_inode_rdev(inode_item); alloc_group_block = btrfs_inode_block_group(inode_item); BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, alloc_group_block); @@ -115,12 +118,6 @@ void btrfs_read_locked_inode(struct inode *inode) mutex_unlock(&root->fs_info->fs_mutex); switch (inode->i_mode & S_IFMT) { -#if 0 - default: - init_special_inode(inode, inode->i_mode, - btrfs_inode_rdev(inode_item)); - break; -#endif case S_IFREG: inode->i_mapping->a_ops = &btrfs_aops; inode->i_fop = &btrfs_file_operations; @@ -137,6 +134,9 @@ void btrfs_read_locked_inode(struct inode *inode) inode->i_op = &btrfs_symlink_inode_operations; inode->i_mapping->a_ops = &btrfs_symlink_aops; break; + default: + init_special_inode(inode, inode->i_mode, rdev); + break; } return; @@ -163,6 +163,7 @@ static void fill_inode_item(struct btrfs_inode_item *item, btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); btrfs_set_inode_nblocks(item, inode->i_blocks); btrfs_set_inode_generation(item, inode->i_generation); + btrfs_set_inode_rdev(item, inode->i_rdev); btrfs_set_inode_block_group(item, BTRFS_I(inode)->block_group->key.objectid); } @@ -250,6 +251,7 @@ err: btrfs_free_path(path); if (!ret) { dir->i_size -= name_len * 2; + dir->i_mtime = dir->i_ctime = CURRENT_TIME; btrfs_update_inode(trans, root, dir); drop_nlink(dentry->d_inode); ret = btrfs_update_inode(trans, root, dentry->d_inode); @@ -505,7 +507,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, extent_num_blocks); inode->i_blocks -= (orig_num_blocks - extent_num_blocks) << 3; - mark_buffer_dirty(path->nodes[0]); + btrfs_mark_buffer_dirty(path->nodes[0]); } else { extent_start = btrfs_file_extent_disk_blocknr(fi); @@ -1037,6 +1039,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, int ret; struct btrfs_key key; struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; + struct inode *parent_inode; key.objectid = inode->i_ino; key.flags = 0; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); @@ -1047,7 +1050,9 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, dentry->d_parent->d_inode->i_ino, &key, btrfs_inode_type(inode)); if (ret == 0) { - dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2; + parent_inode = dentry->d_parent->d_inode; + parent_inode->i_size += dentry->d_name.len * 2; + parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; ret = btrfs_update_inode(trans, root, dentry->d_parent->d_inode); } @@ -1067,6 +1072,58 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, return err; } +static int btrfs_mknod(struct inode *dir, struct dentry *dentry, + int mode, dev_t rdev) +{ + struct btrfs_trans_handle *trans; + struct btrfs_root *root = BTRFS_I(dir)->root; + struct inode *inode; + int err; + int drop_inode = 0; + u64 objectid; + + if (!new_valid_dev(rdev)) + return -EINVAL; + + mutex_lock(&root->fs_info->fs_mutex); + trans = btrfs_start_transaction(root, 1); + btrfs_set_trans_block_group(trans, dir); + + err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); + if (err) { + err = -ENOSPC; + goto out_unlock; + } + + inode = btrfs_new_inode(trans, root, objectid, + BTRFS_I(dir)->block_group, mode); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out_unlock; + + btrfs_set_trans_block_group(trans, inode); + err = btrfs_add_nondir(trans, dentry, inode); + if (err) + drop_inode = 1; + else { + inode->i_op = &btrfs_special_inode_operations; + init_special_inode(inode, inode->i_mode, rdev); + } + dir->i_sb->s_dirt = 1; + btrfs_update_inode_block_group(trans, inode); + btrfs_update_inode_block_group(trans, dir); +out_unlock: + btrfs_end_transaction(trans, root); + mutex_unlock(&root->fs_info->fs_mutex); + + if (drop_inode) { + inode_dec_link_count(inode); + iput(inode); + } + btrfs_btree_balance_dirty(root); + return err; +} + static int btrfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { @@ -2016,7 +2073,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) btrfs_set_header_owner(&leaf->header, root->root_key.objectid); memcpy(leaf->header.fsid, root->fs_info->disk_super->fsid, sizeof(leaf->header.fsid)); - mark_buffer_dirty(subvol); + btrfs_mark_buffer_dirty(subvol); inode_item = &root_item.inode; memset(inode_item, 0, sizeof(*inode_item)); @@ -2493,7 +2550,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, ptr = btrfs_file_extent_inline_start(ei); btrfs_memcpy(root, path->nodes[0]->b_data, ptr, symname, name_len); - mark_buffer_dirty(path->nodes[0]); + btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_free_path(path); inode->i_op = &btrfs_symlink_inode_operations; inode->i_mapping->a_ops = &btrfs_symlink_aops; @@ -2523,6 +2580,7 @@ static struct inode_operations btrfs_dir_inode_operations = { .rename = btrfs_rename, .symlink = btrfs_symlink, .setattr = btrfs_setattr, + .mknod = btrfs_mknod, }; static struct inode_operations btrfs_dir_ro_inode_operations = { @@ -2559,6 +2617,11 @@ static struct inode_operations btrfs_file_inode_operations = { .setattr = btrfs_setattr, }; +static struct inode_operations btrfs_special_inode_operations = { + .getattr = btrfs_getattr, + .setattr = btrfs_setattr, +}; + static struct inode_operations btrfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light,