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;
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;
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;
.lookup = btrfs_lookup,
.create = btrfs_create,
.unlink = btrfs_unlink,
+ .mkdir = btrfs_mkdir,
};
static struct file_operations btrfs_dir_file_operations = {