[Btrfs-devel] Mknod: Operation not permitted

Josef Bacik jwhiter at redhat.com
Fri Jun 29 08:30:46 PDT 2007


On Fri, Jun 29, 2007 at 04:44:10PM +0200, Frank Groeneveld wrote:
> When trying to move my root to a btrfs filesystem, I found a missing
> feature (or a bug). It's not possible to create device files. To
> reproduce, run this on a btrfs filesystem:
> 
> mknod test c 1 1
> 
> result:
> mknod: `test': Operation not permitted
> 
>

Hello,

Please try this patch, it should work for you, I promise it compiled and
pretended to work for me :).

Josef

diff -r 080c0640a527 inode.c
--- a/inode.c	Thu Jun 28 15:57:36 2007 -0400
+++ b/inode.c	Fri Jun 29 07:18:42 2007 -0400
@@ -47,6 +47,7 @@ static struct inode_operations btrfs_dir
 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;
@@ -1068,6 +1069,58 @@ static int btrfs_add_nondir(struct btrfs
 	}
 	if (err > 0)
 		err = -EEXIST;
+	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;
 }
 
@@ -2527,6 +2580,7 @@ static struct inode_operations btrfs_dir
 	.rename		= btrfs_rename,
 	.symlink	= btrfs_symlink,
 	.setattr	= btrfs_setattr,
+	.mknod		= btrfs_mknod,
 };
 
 static struct inode_operations btrfs_dir_ro_inode_operations = {
@@ -2563,6 +2617,11 @@ static struct inode_operations btrfs_fil
 	.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,



More information about the Btrfs-devel mailing list