btrfs_mkdir

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index e76fcd8..820d21e 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -18,124 +18,6 @@
 static struct super_operations btrfs_super_ops;
 static struct file_operations btrfs_dir_file_operations;
 
-#if 0
-/* some random number */
-
-static struct super_operations ramfs_ops;
-
-static struct backing_dev_info ramfs_backing_dev_info = {
-	.ra_pages	= 0,	/* No readahead */
-	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
-			  BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
-			  BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
-};
-
-struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
-{
-	struct inode * inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
-		inode->i_blocks = 0;
-		inode->i_mapping->a_ops = &ramfs_aops;
-		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		switch (mode & S_IFMT) {
-		default:
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_op = &ramfs_file_inode_operations;
-			inode->i_fop = &ramfs_file_operations;
-			break;
-		case S_IFDIR:
-			inode->i_op = &ramfs_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-
-			/* directory inodes start off with i_nlink == 2 (for "." entry) */
-			inc_nlink(inode);
-			break;
-		case S_IFLNK:
-			inode->i_op = &page_symlink_inode_operations;
-			break;
-		}
-	}
-	return inode;
-}
-
-/*
- * File creation. Allocate an inode, and we're done..
- */
-/* SMP-safe */
-static int
-ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
-	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);
-	int error = -ENOSPC;
-
-	if (inode) {
-		if (dir->i_mode & S_ISGID) {
-			inode->i_gid = dir->i_gid;
-			if (S_ISDIR(mode))
-				inode->i_mode |= S_ISGID;
-		}
-		d_instantiate(dentry, inode);
-		dget(dentry);	/* Extra count - pin the dentry in core */
-		error = 0;
-		dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-	}
-	return error;
-}
-
-static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
-{
-	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
-	if (!retval)
-		inc_nlink(dir);
-	return retval;
-}
-
-static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
-{
-	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
-}
-
-static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
-{
-	struct inode *inode;
-	int error = -ENOSPC;
-
-	inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
-	if (inode) {
-		int l = strlen(symname)+1;
-		error = page_symlink(inode, symname, l);
-		if (!error) {
-			if (dir->i_mode & S_ISGID)
-				inode->i_gid = dir->i_gid;
-			d_instantiate(dentry, inode);
-			dget(dentry);
-			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-		} else
-			iput(inode);
-	}
-	return error;
-}
-
-static struct inode_operations ramfs_dir_inode_operations = {
-	.create		= ramfs_create,
-	.lookup		= simple_lookup,
-	.link		= simple_link,
-	.unlink		= simple_unlink,
-	.symlink	= ramfs_symlink,
-	.mkdir		= ramfs_mkdir,
-	.rmdir		= simple_rmdir,
-	.mknod		= ramfs_mknod,
-	.rename		= simple_rename,
-};
-#endif
-
 static void btrfs_read_locked_inode(struct inode *inode)
 {
 	struct btrfs_path path;
@@ -533,9 +415,11 @@
 	inode->i_ino = objectid;
 	inode->i_blocks = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+	/* FIXME do this on link */
+	if (mode & S_IFDIR)
+		inode->i_size = 3;
 	fill_inode_item(&inode_item, inode);
 
-
 	key.objectid = objectid;
 	key.flags = 0;
 	key.offset = 0;
@@ -603,6 +487,67 @@
 	return err;
 }
 
+static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans,
+				struct inode *inode, struct inode *dir)
+{
+	struct btrfs_root *root = btrfs_sb(inode->i_sb);
+	int ret;
+	char buf[2];
+	buf[0] = '.';
+	buf[1] = '.';
+
+	ret = btrfs_insert_dir_item(trans, root, buf, 1, inode->i_ino,
+				    inode->i_ino, 1);
+	if (ret)
+		goto error;
+	ret = btrfs_insert_dir_item(trans, root, buf, 2, inode->i_ino,
+				    dir->i_ino, 1);
+error:
+	return ret;
+}
+
+static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct inode *inode;
+	struct btrfs_trans_handle *trans;
+	struct btrfs_root *root = btrfs_sb(dir->i_sb);
+	int err = 0;
+	int drop_on_err = 0;
+
+	mutex_lock(&root->fs_info->fs_mutex);
+	trans = btrfs_start_transaction(root, 1);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		goto out_unlock;
+	}
+	inode = btrfs_new_inode(trans, dir, S_IFDIR | mode);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out_fail;
+	}
+	drop_on_err = 1;
+	inode->i_op = &btrfs_dir_inode_operations;
+	inode->i_fop = &btrfs_dir_file_operations;
+
+	err = btrfs_make_empty_dir(trans, inode, dir);
+	if (err)
+		goto out_fail;
+	err = btrfs_add_link(trans, dentry, inode);
+	if (err)
+		goto out_fail;
+	d_instantiate(dentry, inode);
+	mark_inode_dirty(inode);
+	drop_on_err = 0;
+
+out_fail:
+	btrfs_end_transaction(trans, root);
+out_unlock:
+	mutex_unlock(&root->fs_info->fs_mutex);
+	if (drop_on_err)
+		iput(inode);
+	return err;
+}
+
 static int btrfs_sync_fs(struct super_block *sb, int wait)
 {
 	struct btrfs_trans_handle *trans;
@@ -661,6 +606,7 @@
 	.lookup		= btrfs_lookup,
 	.create		= btrfs_create,
 	.unlink		= btrfs_unlink,
+	.mkdir		= btrfs_mkdir,
 };
 
 static struct file_operations btrfs_dir_file_operations = {