12e635a27SChris Mason #include <linux/module.h> 2e20d96d6SChris Mason #include <linux/buffer_head.h> 32e635a27SChris Mason #include <linux/fs.h> 42e635a27SChris Mason #include <linux/pagemap.h> 52e635a27SChris Mason #include <linux/highmem.h> 62e635a27SChris Mason #include <linux/time.h> 72e635a27SChris Mason #include <linux/init.h> 82e635a27SChris Mason #include <linux/string.h> 92e635a27SChris Mason #include <linux/smp_lock.h> 102e635a27SChris Mason #include <linux/backing-dev.h> 112e635a27SChris Mason #include "ctree.h" 12e20d96d6SChris Mason #include "disk-io.h" 13d5719762SChris Mason #include "transaction.h" 142e635a27SChris Mason 152e635a27SChris Mason #define BTRFS_SUPER_MAGIC 0x9123682E 16e20d96d6SChris Mason 17e20d96d6SChris Mason static struct inode_operations btrfs_dir_inode_operations; 18e20d96d6SChris Mason static struct super_operations btrfs_super_ops; 19e20d96d6SChris Mason static struct file_operations btrfs_dir_file_operations; 20e20d96d6SChris Mason 212e635a27SChris Mason #if 0 222e635a27SChris Mason /* some random number */ 232e635a27SChris Mason 242e635a27SChris Mason static struct super_operations ramfs_ops; 252e635a27SChris Mason 262e635a27SChris Mason static struct backing_dev_info ramfs_backing_dev_info = { 272e635a27SChris Mason .ra_pages = 0, /* No readahead */ 282e635a27SChris Mason .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | 292e635a27SChris Mason BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | 302e635a27SChris Mason BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, 312e635a27SChris Mason }; 322e635a27SChris Mason 332e635a27SChris Mason struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) 342e635a27SChris Mason { 352e635a27SChris Mason struct inode * inode = new_inode(sb); 362e635a27SChris Mason 372e635a27SChris Mason if (inode) { 382e635a27SChris Mason inode->i_mode = mode; 392e635a27SChris Mason inode->i_uid = current->fsuid; 402e635a27SChris Mason inode->i_gid = current->fsgid; 412e635a27SChris Mason inode->i_blocks = 0; 422e635a27SChris Mason inode->i_mapping->a_ops = &ramfs_aops; 432e635a27SChris Mason inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; 442e635a27SChris Mason inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 452e635a27SChris Mason switch (mode & S_IFMT) { 462e635a27SChris Mason default: 472e635a27SChris Mason init_special_inode(inode, mode, dev); 482e635a27SChris Mason break; 492e635a27SChris Mason case S_IFREG: 502e635a27SChris Mason inode->i_op = &ramfs_file_inode_operations; 512e635a27SChris Mason inode->i_fop = &ramfs_file_operations; 522e635a27SChris Mason break; 532e635a27SChris Mason case S_IFDIR: 542e635a27SChris Mason inode->i_op = &ramfs_dir_inode_operations; 552e635a27SChris Mason inode->i_fop = &simple_dir_operations; 562e635a27SChris Mason 572e635a27SChris Mason /* directory inodes start off with i_nlink == 2 (for "." entry) */ 582e635a27SChris Mason inc_nlink(inode); 592e635a27SChris Mason break; 602e635a27SChris Mason case S_IFLNK: 612e635a27SChris Mason inode->i_op = &page_symlink_inode_operations; 622e635a27SChris Mason break; 632e635a27SChris Mason } 642e635a27SChris Mason } 652e635a27SChris Mason return inode; 662e635a27SChris Mason } 672e635a27SChris Mason 682e635a27SChris Mason /* 692e635a27SChris Mason * File creation. Allocate an inode, and we're done.. 702e635a27SChris Mason */ 712e635a27SChris Mason /* SMP-safe */ 722e635a27SChris Mason static int 732e635a27SChris Mason ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) 742e635a27SChris Mason { 752e635a27SChris Mason struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev); 762e635a27SChris Mason int error = -ENOSPC; 772e635a27SChris Mason 782e635a27SChris Mason if (inode) { 792e635a27SChris Mason if (dir->i_mode & S_ISGID) { 802e635a27SChris Mason inode->i_gid = dir->i_gid; 812e635a27SChris Mason if (S_ISDIR(mode)) 822e635a27SChris Mason inode->i_mode |= S_ISGID; 832e635a27SChris Mason } 842e635a27SChris Mason d_instantiate(dentry, inode); 852e635a27SChris Mason dget(dentry); /* Extra count - pin the dentry in core */ 862e635a27SChris Mason error = 0; 872e635a27SChris Mason dir->i_mtime = dir->i_ctime = CURRENT_TIME; 882e635a27SChris Mason } 892e635a27SChris Mason return error; 902e635a27SChris Mason } 912e635a27SChris Mason 922e635a27SChris Mason static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) 932e635a27SChris Mason { 942e635a27SChris Mason int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); 952e635a27SChris Mason if (!retval) 962e635a27SChris Mason inc_nlink(dir); 972e635a27SChris Mason return retval; 982e635a27SChris Mason } 992e635a27SChris Mason 1002e635a27SChris Mason static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) 1012e635a27SChris Mason { 1022e635a27SChris Mason return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); 1032e635a27SChris Mason } 1042e635a27SChris Mason 1052e635a27SChris Mason static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) 1062e635a27SChris Mason { 1072e635a27SChris Mason struct inode *inode; 1082e635a27SChris Mason int error = -ENOSPC; 1092e635a27SChris Mason 1102e635a27SChris Mason inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); 1112e635a27SChris Mason if (inode) { 1122e635a27SChris Mason int l = strlen(symname)+1; 1132e635a27SChris Mason error = page_symlink(inode, symname, l); 1142e635a27SChris Mason if (!error) { 1152e635a27SChris Mason if (dir->i_mode & S_ISGID) 1162e635a27SChris Mason inode->i_gid = dir->i_gid; 1172e635a27SChris Mason d_instantiate(dentry, inode); 1182e635a27SChris Mason dget(dentry); 1192e635a27SChris Mason dir->i_mtime = dir->i_ctime = CURRENT_TIME; 1202e635a27SChris Mason } else 1212e635a27SChris Mason iput(inode); 1222e635a27SChris Mason } 1232e635a27SChris Mason return error; 1242e635a27SChris Mason } 1252e635a27SChris Mason 1262e635a27SChris Mason static struct inode_operations ramfs_dir_inode_operations = { 1272e635a27SChris Mason .create = ramfs_create, 1282e635a27SChris Mason .lookup = simple_lookup, 1292e635a27SChris Mason .link = simple_link, 1302e635a27SChris Mason .unlink = simple_unlink, 1312e635a27SChris Mason .symlink = ramfs_symlink, 1322e635a27SChris Mason .mkdir = ramfs_mkdir, 1332e635a27SChris Mason .rmdir = simple_rmdir, 1342e635a27SChris Mason .mknod = ramfs_mknod, 1352e635a27SChris Mason .rename = simple_rename, 1362e635a27SChris Mason }; 1372e635a27SChris Mason #endif 1382e635a27SChris Mason 139e20d96d6SChris Mason static void btrfs_read_locked_inode(struct inode *inode) 1402e635a27SChris Mason { 141e20d96d6SChris Mason struct btrfs_path path; 142e20d96d6SChris Mason struct btrfs_inode_item *inode_item; 143e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(inode->i_sb); 144e20d96d6SChris Mason int ret; 145e20d96d6SChris Mason btrfs_init_path(&path); 146e20d96d6SChris Mason ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0); 147e20d96d6SChris Mason if (ret) { 148e20d96d6SChris Mason make_bad_inode(inode); 149e20d96d6SChris Mason return; 1502e635a27SChris Mason } 151e20d96d6SChris Mason inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), 152e20d96d6SChris Mason path.slots[0], 153e20d96d6SChris Mason struct btrfs_inode_item); 154e20d96d6SChris Mason 155e20d96d6SChris Mason inode->i_mode = btrfs_inode_mode(inode_item); 156e20d96d6SChris Mason inode->i_nlink = btrfs_inode_nlink(inode_item); 157e20d96d6SChris Mason inode->i_uid = btrfs_inode_uid(inode_item); 158e20d96d6SChris Mason inode->i_gid = btrfs_inode_gid(inode_item); 159e20d96d6SChris Mason inode->i_size = btrfs_inode_size(inode_item); 160e20d96d6SChris Mason inode->i_atime.tv_sec = btrfs_timespec_sec(&inode_item->atime); 161e20d96d6SChris Mason inode->i_atime.tv_nsec = btrfs_timespec_nsec(&inode_item->atime); 162e20d96d6SChris Mason inode->i_mtime.tv_sec = btrfs_timespec_sec(&inode_item->mtime); 163e20d96d6SChris Mason inode->i_mtime.tv_nsec = btrfs_timespec_nsec(&inode_item->mtime); 164e20d96d6SChris Mason inode->i_ctime.tv_sec = btrfs_timespec_sec(&inode_item->ctime); 165e20d96d6SChris Mason inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); 166e20d96d6SChris Mason inode->i_blocks = btrfs_inode_nblocks(inode_item); 167e20d96d6SChris Mason inode->i_generation = btrfs_inode_generation(inode_item); 168e20d96d6SChris Mason btrfs_release_path(root, &path); 169e20d96d6SChris Mason switch (inode->i_mode & S_IFMT) { 170e20d96d6SChris Mason #if 0 171e20d96d6SChris Mason default: 172e20d96d6SChris Mason init_special_inode(inode, inode->i_mode, 173e20d96d6SChris Mason btrfs_inode_rdev(inode_item)); 174e20d96d6SChris Mason break; 175e20d96d6SChris Mason #endif 176e20d96d6SChris Mason case S_IFREG: 177e20d96d6SChris Mason break; 178e20d96d6SChris Mason case S_IFDIR: 179e20d96d6SChris Mason inode->i_op = &btrfs_dir_inode_operations; 180e20d96d6SChris Mason inode->i_fop = &btrfs_dir_file_operations; 181e20d96d6SChris Mason break; 182e20d96d6SChris Mason case S_IFLNK: 183e20d96d6SChris Mason // inode->i_op = &page_symlink_inode_operations; 184e20d96d6SChris Mason break; 185e20d96d6SChris Mason } 186e20d96d6SChris Mason return; 1872e635a27SChris Mason } 1882e635a27SChris Mason 189e20d96d6SChris Mason static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, 190e20d96d6SChris Mason ino_t *ino) 191e20d96d6SChris Mason { 192e20d96d6SChris Mason const char *name = dentry->d_name.name; 193e20d96d6SChris Mason int namelen = dentry->d_name.len; 194e20d96d6SChris Mason struct btrfs_dir_item *di; 195e20d96d6SChris Mason struct btrfs_path path; 196e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 197e20d96d6SChris Mason int ret; 198e20d96d6SChris Mason 199e20d96d6SChris Mason btrfs_init_path(&path); 200e20d96d6SChris Mason ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, 201e20d96d6SChris Mason namelen, 0); 2027f5c1516SChris Mason if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) { 203e20d96d6SChris Mason *ino = 0; 204e20d96d6SChris Mason goto out; 205e20d96d6SChris Mason } 206e20d96d6SChris Mason di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], 207e20d96d6SChris Mason struct btrfs_dir_item); 208e20d96d6SChris Mason *ino = btrfs_dir_objectid(di); 209e20d96d6SChris Mason out: 210e20d96d6SChris Mason btrfs_release_path(root, &path); 211e20d96d6SChris Mason return ret; 212e20d96d6SChris Mason } 213e20d96d6SChris Mason 214e20d96d6SChris Mason static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 215e20d96d6SChris Mason struct nameidata *nd) 216e20d96d6SChris Mason { 217e20d96d6SChris Mason struct inode * inode; 218e20d96d6SChris Mason ino_t ino; 219e20d96d6SChris Mason int ret; 220e20d96d6SChris Mason 221e20d96d6SChris Mason if (dentry->d_name.len > BTRFS_NAME_LEN) 222e20d96d6SChris Mason return ERR_PTR(-ENAMETOOLONG); 223e20d96d6SChris Mason 224e20d96d6SChris Mason ret = btrfs_inode_by_name(dir, dentry, &ino); 225e20d96d6SChris Mason if (ret < 0) 226e20d96d6SChris Mason return ERR_PTR(ret); 227e20d96d6SChris Mason inode = NULL; 228e20d96d6SChris Mason if (ino) { 229e20d96d6SChris Mason inode = iget(dir->i_sb, ino); 230e20d96d6SChris Mason if (!inode) 231e20d96d6SChris Mason return ERR_PTR(-EACCES); 232e20d96d6SChris Mason } 233e20d96d6SChris Mason return d_splice_alias(inode, dentry); 234e20d96d6SChris Mason } 235e20d96d6SChris Mason 236e20d96d6SChris Mason static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 237e20d96d6SChris Mason { 238e20d96d6SChris Mason struct inode *inode = filp->f_path.dentry->d_inode; 239e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(inode->i_sb); 240e20d96d6SChris Mason struct btrfs_item *item; 241e20d96d6SChris Mason struct btrfs_dir_item *di; 242e20d96d6SChris Mason struct btrfs_key key; 243e20d96d6SChris Mason struct btrfs_path path; 244e20d96d6SChris Mason int ret; 245e20d96d6SChris Mason u32 nritems; 246e20d96d6SChris Mason struct btrfs_leaf *leaf; 247e20d96d6SChris Mason int slot; 248e20d96d6SChris Mason int advance; 249e20d96d6SChris Mason unsigned char d_type = DT_UNKNOWN; 2507f5c1516SChris Mason int over = 0; 251e20d96d6SChris Mason 252e20d96d6SChris Mason key.objectid = inode->i_ino; 253e20d96d6SChris Mason key.flags = 0; 254e20d96d6SChris Mason btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); 255e20d96d6SChris Mason key.offset = filp->f_pos; 256e20d96d6SChris Mason btrfs_init_path(&path); 257e20d96d6SChris Mason ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); 258e20d96d6SChris Mason if (ret < 0) { 259e20d96d6SChris Mason goto err; 260e20d96d6SChris Mason } 2617f5c1516SChris Mason advance = 0; 262e20d96d6SChris Mason while(1) { 263e20d96d6SChris Mason leaf = btrfs_buffer_leaf(path.nodes[0]); 264e20d96d6SChris Mason nritems = btrfs_header_nritems(&leaf->header); 265e20d96d6SChris Mason slot = path.slots[0]; 266e20d96d6SChris Mason if (advance) { 267e20d96d6SChris Mason if (slot == nritems -1) { 268e20d96d6SChris Mason ret = btrfs_next_leaf(root, &path); 269e20d96d6SChris Mason if (ret) 270e20d96d6SChris Mason break; 271e20d96d6SChris Mason leaf = btrfs_buffer_leaf(path.nodes[0]); 272e20d96d6SChris Mason nritems = btrfs_header_nritems(&leaf->header); 273e20d96d6SChris Mason slot = path.slots[0]; 274e20d96d6SChris Mason } else { 275e20d96d6SChris Mason slot++; 276e20d96d6SChris Mason path.slots[0]++; 277e20d96d6SChris Mason } 278e20d96d6SChris Mason } 279e20d96d6SChris Mason advance = 1; 280e20d96d6SChris Mason item = leaf->items + slot; 281e20d96d6SChris Mason if (btrfs_disk_key_objectid(&item->key) != key.objectid) 282e20d96d6SChris Mason break; 283e20d96d6SChris Mason if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) 284e20d96d6SChris Mason continue; 2857f5c1516SChris Mason if (btrfs_disk_key_offset(&item->key) < filp->f_pos) 2867f5c1516SChris Mason continue; 287e20d96d6SChris Mason di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 288e20d96d6SChris Mason over = filldir(dirent, (const char *)(di + 1), 289e20d96d6SChris Mason btrfs_dir_name_len(di), 290e20d96d6SChris Mason btrfs_disk_key_offset(&item->key), 291e20d96d6SChris Mason btrfs_dir_objectid(di), d_type); 2927f5c1516SChris Mason if (over) { 2937f5c1516SChris Mason filp->f_pos = btrfs_disk_key_offset(&item->key); 294e20d96d6SChris Mason break; 2957f5c1516SChris Mason } 296e20d96d6SChris Mason filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; 297e20d96d6SChris Mason } 298e20d96d6SChris Mason ret = 0; 299e20d96d6SChris Mason err: 300e20d96d6SChris Mason btrfs_release_path(root, &path); 301e20d96d6SChris Mason return ret; 302e20d96d6SChris Mason } 303e20d96d6SChris Mason 304e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb) 305e20d96d6SChris Mason { 306e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(sb); 307e20d96d6SChris Mason int ret; 308e20d96d6SChris Mason 309e20d96d6SChris Mason ret = close_ctree(root); 310e20d96d6SChris Mason if (ret) { 311e20d96d6SChris Mason printk("close ctree returns %d\n", ret); 312e20d96d6SChris Mason } 313e20d96d6SChris Mason sb->s_fs_info = NULL; 314e20d96d6SChris Mason } 3152e635a27SChris Mason 3162e635a27SChris Mason static int btrfs_fill_super(struct super_block * sb, void * data, int silent) 3172e635a27SChris Mason { 3182e635a27SChris Mason struct inode * inode; 319e20d96d6SChris Mason struct dentry * root_dentry; 320e20d96d6SChris Mason struct btrfs_super_block *disk_super; 321e20d96d6SChris Mason struct buffer_head *bh; 322e20d96d6SChris Mason struct btrfs_root *root; 3232e635a27SChris Mason 3242e635a27SChris Mason sb->s_maxbytes = MAX_LFS_FILESIZE; 3252e635a27SChris Mason sb->s_blocksize = PAGE_CACHE_SIZE; 3262e635a27SChris Mason sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 3272e635a27SChris Mason sb->s_magic = BTRFS_SUPER_MAGIC; 328e20d96d6SChris Mason sb->s_op = &btrfs_super_ops; 3292e635a27SChris Mason sb->s_time_gran = 1; 330e20d96d6SChris Mason 331e20d96d6SChris Mason bh = sb_bread(sb, BTRFS_SUPER_INFO_OFFSET / sb->s_blocksize); 332e20d96d6SChris Mason if (!bh) { 333e20d96d6SChris Mason printk("btrfs: unable to read on disk super\n"); 334e20d96d6SChris Mason return -EIO; 335e20d96d6SChris Mason } 336e20d96d6SChris Mason disk_super = (struct btrfs_super_block *)bh->b_data; 337e20d96d6SChris Mason root = open_ctree(sb, bh, disk_super); 338e20d96d6SChris Mason sb->s_fs_info = root; 339e20d96d6SChris Mason if (!root) { 340e20d96d6SChris Mason printk("btrfs: open_ctree failed\n"); 341e20d96d6SChris Mason return -EIO; 342e20d96d6SChris Mason } 343e20d96d6SChris Mason printk("read in super total blocks %Lu root %Lu\n", 344e20d96d6SChris Mason btrfs_super_total_blocks(disk_super), 345e20d96d6SChris Mason btrfs_super_root_dir(disk_super)); 346e20d96d6SChris Mason 347e20d96d6SChris Mason inode = iget_locked(sb, btrfs_super_root_dir(disk_super)); 3482e635a27SChris Mason if (!inode) 3492e635a27SChris Mason return -ENOMEM; 350e20d96d6SChris Mason if (inode->i_state & I_NEW) { 351e20d96d6SChris Mason btrfs_read_locked_inode(inode); 352e20d96d6SChris Mason unlock_new_inode(inode); 353e20d96d6SChris Mason } 3542e635a27SChris Mason 355e20d96d6SChris Mason root_dentry = d_alloc_root(inode); 356e20d96d6SChris Mason if (!root_dentry) { 3572e635a27SChris Mason iput(inode); 3582e635a27SChris Mason return -ENOMEM; 3592e635a27SChris Mason } 360e20d96d6SChris Mason sb->s_root = root_dentry; 361e20d96d6SChris Mason 3622e635a27SChris Mason return 0; 3632e635a27SChris Mason } 3642e635a27SChris Mason 365d5719762SChris Mason static void fill_inode_item(struct btrfs_inode_item *item, 366d5719762SChris Mason struct inode *inode) 367d5719762SChris Mason { 368d5719762SChris Mason btrfs_set_inode_uid(item, inode->i_uid); 369d5719762SChris Mason btrfs_set_inode_gid(item, inode->i_gid); 370d5719762SChris Mason btrfs_set_inode_size(item, inode->i_size); 371d5719762SChris Mason btrfs_set_inode_mode(item, inode->i_mode); 372d5719762SChris Mason btrfs_set_inode_nlink(item, inode->i_nlink); 373d5719762SChris Mason btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); 374d5719762SChris Mason btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); 375d5719762SChris Mason btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); 376d5719762SChris Mason btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); 377d5719762SChris Mason btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); 378d5719762SChris Mason btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); 379d5719762SChris Mason btrfs_set_inode_nblocks(item, inode->i_blocks); 380d5719762SChris Mason btrfs_set_inode_generation(item, inode->i_generation); 381d5719762SChris Mason } 382d5719762SChris Mason 383d5719762SChris Mason static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, 384d5719762SChris Mason struct inode *dir, int mode) 385d5719762SChris Mason { 386d5719762SChris Mason struct inode *inode; 387d5719762SChris Mason struct btrfs_inode_item inode_item; 388d5719762SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 389d5719762SChris Mason struct btrfs_key key; 390d5719762SChris Mason int ret; 391d5719762SChris Mason u64 objectid; 392d5719762SChris Mason 393d5719762SChris Mason inode = new_inode(dir->i_sb); 394d5719762SChris Mason if (!inode) 395d5719762SChris Mason return ERR_PTR(-ENOMEM); 396d5719762SChris Mason 397d5719762SChris Mason ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); 398d5719762SChris Mason BUG_ON(ret); 399d5719762SChris Mason 400d5719762SChris Mason inode->i_uid = current->fsuid; 401d5719762SChris Mason inode->i_gid = current->fsgid; 402d5719762SChris Mason inode->i_mode = mode; 403d5719762SChris Mason inode->i_ino = objectid; 404d5719762SChris Mason inode->i_blocks = 0; 405d5719762SChris Mason inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; 406d5719762SChris Mason fill_inode_item(&inode_item, inode); 407d5719762SChris Mason 408d5719762SChris Mason 409d5719762SChris Mason key.objectid = objectid; 410d5719762SChris Mason key.flags = 0; 411d5719762SChris Mason key.offset = 0; 412d5719762SChris Mason btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); 413d5719762SChris Mason ret = btrfs_insert_inode_map(trans, root, objectid, &key); 414d5719762SChris Mason BUG_ON(ret); 415d5719762SChris Mason 416d5719762SChris Mason ret = btrfs_insert_inode(trans, root, objectid, &inode_item); 417d5719762SChris Mason BUG_ON(ret); 418d5719762SChris Mason 419d5719762SChris Mason insert_inode_hash(inode); 420d5719762SChris Mason // FIXME mark_inode_dirty(inode) 421d5719762SChris Mason return inode; 422d5719762SChris Mason } 423d5719762SChris Mason 424d5719762SChris Mason static int btrfs_add_link(struct btrfs_trans_handle *trans, 425d5719762SChris Mason struct dentry *dentry, struct inode *inode) 426d5719762SChris Mason { 427d5719762SChris Mason int ret; 428d5719762SChris Mason ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb), 429d5719762SChris Mason dentry->d_name.name, dentry->d_name.len, 430d5719762SChris Mason dentry->d_parent->d_inode->i_ino, 431d5719762SChris Mason inode->i_ino, 0); 432d5719762SChris Mason return ret; 433d5719762SChris Mason } 434d5719762SChris Mason 435d5719762SChris Mason static int btrfs_add_nondir(struct btrfs_trans_handle *trans, 436d5719762SChris Mason struct dentry *dentry, struct inode *inode) 437d5719762SChris Mason { 438d5719762SChris Mason int err = btrfs_add_link(trans, dentry, inode); 439d5719762SChris Mason if (!err) { 440d5719762SChris Mason d_instantiate(dentry, inode); 441d5719762SChris Mason return 0; 442d5719762SChris Mason } 443d5719762SChris Mason inode_dec_link_count(inode); 444d5719762SChris Mason iput(inode); 445d5719762SChris Mason return err; 446d5719762SChris Mason } 447d5719762SChris Mason 448d5719762SChris Mason static int btrfs_create(struct inode *dir, struct dentry *dentry, 449d5719762SChris Mason int mode, struct nameidata *nd) 450d5719762SChris Mason { 451d5719762SChris Mason struct btrfs_trans_handle *trans; 452d5719762SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 453d5719762SChris Mason struct inode *inode; 454d5719762SChris Mason int err; 455d5719762SChris Mason 456*d561c025SChris Mason mutex_lock(&root->fs_info->fs_mutex); 457d5719762SChris Mason trans = btrfs_start_transaction(root, 1); 458d5719762SChris Mason inode = btrfs_new_inode(trans, dir, mode); 459d5719762SChris Mason err = PTR_ERR(inode); 460d5719762SChris Mason if (IS_ERR(inode)) 461*d561c025SChris Mason goto out_unlock; 462d5719762SChris Mason // FIXME mark the inode dirty 463d5719762SChris Mason err = btrfs_add_nondir(trans, dentry, inode); 464d5719762SChris Mason dir->i_sb->s_dirt = 1; 465d5719762SChris Mason btrfs_end_transaction(trans, root); 466*d561c025SChris Mason out_unlock: 467*d561c025SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 468d5719762SChris Mason return err; 469d5719762SChris Mason } 470d5719762SChris Mason 471d5719762SChris Mason static int btrfs_sync_fs(struct super_block *sb, int wait) 472d5719762SChris Mason { 473d5719762SChris Mason struct btrfs_trans_handle *trans; 474d5719762SChris Mason struct btrfs_root *root; 475d5719762SChris Mason int ret; 476df2ce34cSChris Mason 477d5719762SChris Mason sb->s_dirt = 0; 478*d561c025SChris Mason if (!wait) { 479*d561c025SChris Mason filemap_flush(sb->s_bdev->bd_inode->i_mapping); 480df2ce34cSChris Mason return 0; 481*d561c025SChris Mason } 482*d561c025SChris Mason filemap_write_and_wait(sb->s_bdev->bd_inode->i_mapping); 483df2ce34cSChris Mason 484d5719762SChris Mason root = btrfs_sb(sb); 485*d561c025SChris Mason mutex_lock(&root->fs_info->fs_mutex); 486d5719762SChris Mason trans = btrfs_start_transaction(root, 1); 487d5719762SChris Mason ret = btrfs_commit_transaction(trans, root); 488d5719762SChris Mason sb->s_dirt = 0; 489d5719762SChris Mason BUG_ON(ret); 490d5719762SChris Mason printk("btrfs sync_fs\n"); 491*d561c025SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 492d5719762SChris Mason return 0; 493d5719762SChris Mason } 494d5719762SChris Mason 495*d561c025SChris Mason static void btrfs_write_super(struct super_block *sb) 496*d561c025SChris Mason { 497*d561c025SChris Mason btrfs_sync_fs(sb, 1); 498*d561c025SChris Mason } 499*d561c025SChris Mason 500*d561c025SChris Mason 5012e635a27SChris Mason static int btrfs_get_sb(struct file_system_type *fs_type, 5022e635a27SChris Mason int flags, const char *dev_name, void *data, struct vfsmount *mnt) 5032e635a27SChris Mason { 5042e635a27SChris Mason return get_sb_bdev(fs_type, flags, dev_name, data, 5052e635a27SChris Mason btrfs_fill_super, mnt); 5062e635a27SChris Mason } 5072e635a27SChris Mason 5082e635a27SChris Mason static struct file_system_type btrfs_fs_type = { 5092e635a27SChris Mason .owner = THIS_MODULE, 5102e635a27SChris Mason .name = "btrfs", 5112e635a27SChris Mason .get_sb = btrfs_get_sb, 5122e635a27SChris Mason .kill_sb = kill_block_super, 5132e635a27SChris Mason .fs_flags = FS_REQUIRES_DEV, 5142e635a27SChris Mason }; 5152e635a27SChris Mason 516e20d96d6SChris Mason static struct super_operations btrfs_super_ops = { 517e20d96d6SChris Mason .statfs = simple_statfs, 518e20d96d6SChris Mason .drop_inode = generic_delete_inode, 519e20d96d6SChris Mason .put_super = btrfs_put_super, 520e20d96d6SChris Mason .read_inode = btrfs_read_locked_inode, 521d5719762SChris Mason .write_super = btrfs_write_super, 522d5719762SChris Mason .sync_fs = btrfs_sync_fs, 523e20d96d6SChris Mason }; 524e20d96d6SChris Mason 525e20d96d6SChris Mason static struct inode_operations btrfs_dir_inode_operations = { 526e20d96d6SChris Mason .lookup = btrfs_lookup, 527d5719762SChris Mason .create = btrfs_create, 528e20d96d6SChris Mason }; 529e20d96d6SChris Mason 530e20d96d6SChris Mason static struct file_operations btrfs_dir_file_operations = { 531e20d96d6SChris Mason .llseek = generic_file_llseek, 532e20d96d6SChris Mason .read = generic_read_dir, 533e20d96d6SChris Mason .readdir = btrfs_readdir, 534e20d96d6SChris Mason }; 535e20d96d6SChris Mason 536e20d96d6SChris Mason 5372e635a27SChris Mason static int __init init_btrfs_fs(void) 5382e635a27SChris Mason { 5392e635a27SChris Mason printk("btrfs loaded!\n"); 5402e635a27SChris Mason return register_filesystem(&btrfs_fs_type); 5412e635a27SChris Mason } 5422e635a27SChris Mason 5432e635a27SChris Mason static void __exit exit_btrfs_fs(void) 5442e635a27SChris Mason { 5452e635a27SChris Mason unregister_filesystem(&btrfs_fs_type); 5462e635a27SChris Mason printk("btrfs unloaded\n"); 5472e635a27SChris Mason } 5482e635a27SChris Mason 5492e635a27SChris Mason module_init(init_btrfs_fs) 5502e635a27SChris Mason module_exit(exit_btrfs_fs) 5512e635a27SChris Mason 5522e635a27SChris Mason MODULE_LICENSE("GPL"); 553