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); 14978fae27eSChris Mason btrfs_release_path(root, &path); 150e20d96d6SChris Mason return; 1512e635a27SChris Mason } 152e20d96d6SChris Mason inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), 153e20d96d6SChris Mason path.slots[0], 154e20d96d6SChris Mason struct btrfs_inode_item); 155e20d96d6SChris Mason 156e20d96d6SChris Mason inode->i_mode = btrfs_inode_mode(inode_item); 157e20d96d6SChris Mason inode->i_nlink = btrfs_inode_nlink(inode_item); 158e20d96d6SChris Mason inode->i_uid = btrfs_inode_uid(inode_item); 159e20d96d6SChris Mason inode->i_gid = btrfs_inode_gid(inode_item); 160e20d96d6SChris Mason inode->i_size = btrfs_inode_size(inode_item); 161e20d96d6SChris Mason inode->i_atime.tv_sec = btrfs_timespec_sec(&inode_item->atime); 162e20d96d6SChris Mason inode->i_atime.tv_nsec = btrfs_timespec_nsec(&inode_item->atime); 163e20d96d6SChris Mason inode->i_mtime.tv_sec = btrfs_timespec_sec(&inode_item->mtime); 164e20d96d6SChris Mason inode->i_mtime.tv_nsec = btrfs_timespec_nsec(&inode_item->mtime); 165e20d96d6SChris Mason inode->i_ctime.tv_sec = btrfs_timespec_sec(&inode_item->ctime); 166e20d96d6SChris Mason inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); 167e20d96d6SChris Mason inode->i_blocks = btrfs_inode_nblocks(inode_item); 168e20d96d6SChris Mason inode->i_generation = btrfs_inode_generation(inode_item); 169e20d96d6SChris Mason btrfs_release_path(root, &path); 170e20d96d6SChris Mason switch (inode->i_mode & S_IFMT) { 171e20d96d6SChris Mason #if 0 172e20d96d6SChris Mason default: 173e20d96d6SChris Mason init_special_inode(inode, inode->i_mode, 174e20d96d6SChris Mason btrfs_inode_rdev(inode_item)); 175e20d96d6SChris Mason break; 176e20d96d6SChris Mason #endif 177e20d96d6SChris Mason case S_IFREG: 178e20d96d6SChris Mason break; 179e20d96d6SChris Mason case S_IFDIR: 180e20d96d6SChris Mason inode->i_op = &btrfs_dir_inode_operations; 181e20d96d6SChris Mason inode->i_fop = &btrfs_dir_file_operations; 182e20d96d6SChris Mason break; 183e20d96d6SChris Mason case S_IFLNK: 184e20d96d6SChris Mason // inode->i_op = &page_symlink_inode_operations; 185e20d96d6SChris Mason break; 186e20d96d6SChris Mason } 187e20d96d6SChris Mason return; 1882e635a27SChris Mason } 1892e635a27SChris Mason 190*134e9731SChris Mason static int btrfs_unlink(struct inode *dir, struct dentry *dentry) 191*134e9731SChris Mason { 192*134e9731SChris Mason struct btrfs_path path; 193*134e9731SChris Mason struct btrfs_root *root; 194*134e9731SChris Mason struct btrfs_trans_handle *trans; 195*134e9731SChris Mason const char *name = dentry->d_name.name; 196*134e9731SChris Mason int name_len = dentry->d_name.len; 197*134e9731SChris Mason int ret; 198*134e9731SChris Mason u64 objectid; 199*134e9731SChris Mason struct btrfs_dir_item *di; 200*134e9731SChris Mason 201*134e9731SChris Mason btrfs_init_path(&path); 202*134e9731SChris Mason root = btrfs_sb(dir->i_sb); 203*134e9731SChris Mason mutex_lock(&root->fs_info->fs_mutex); 204*134e9731SChris Mason trans = btrfs_start_transaction(root, 1); 205*134e9731SChris Mason 206*134e9731SChris Mason ret = btrfs_lookup_dir_item(trans, root, &path, dir->i_ino, 207*134e9731SChris Mason name, name_len, -1); 208*134e9731SChris Mason if (ret < 0) 209*134e9731SChris Mason goto err; 210*134e9731SChris Mason if (ret > 0) { 211*134e9731SChris Mason ret = -ENOENT; 212*134e9731SChris Mason goto err; 213*134e9731SChris Mason } 214*134e9731SChris Mason di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], 215*134e9731SChris Mason struct btrfs_dir_item); 216*134e9731SChris Mason objectid = btrfs_dir_objectid(di); 217*134e9731SChris Mason 218*134e9731SChris Mason ret = btrfs_del_item(trans, root, &path); 219*134e9731SChris Mason BUG_ON(ret); 220*134e9731SChris Mason dentry->d_inode->i_ctime = dir->i_ctime; 221*134e9731SChris Mason err: 222*134e9731SChris Mason btrfs_release_path(root, &path); 223*134e9731SChris Mason btrfs_end_transaction(trans, root); 224*134e9731SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 225*134e9731SChris Mason if (ret == 0) 226*134e9731SChris Mason inode_dec_link_count(dentry->d_inode); 227*134e9731SChris Mason return ret; 228*134e9731SChris Mason } 229*134e9731SChris Mason 230*134e9731SChris Mason static int btrfs_free_inode(struct btrfs_trans_handle *trans, 231*134e9731SChris Mason struct btrfs_root *root, 232*134e9731SChris Mason struct inode *inode) 233*134e9731SChris Mason { 234*134e9731SChris Mason u64 objectid = inode->i_ino; 235*134e9731SChris Mason struct btrfs_path path; 236*134e9731SChris Mason struct btrfs_inode_map_item *map; 237*134e9731SChris Mason struct btrfs_key stat_data_key; 238*134e9731SChris Mason int ret; 239*134e9731SChris Mason clear_inode(inode); 240*134e9731SChris Mason btrfs_init_path(&path); 241*134e9731SChris Mason ret = btrfs_lookup_inode_map(trans, root, &path, objectid, -1); 242*134e9731SChris Mason if (ret) { 243*134e9731SChris Mason if (ret > 0) 244*134e9731SChris Mason ret = -ENOENT; 245*134e9731SChris Mason btrfs_release_path(root, &path); 246*134e9731SChris Mason goto error; 247*134e9731SChris Mason } 248*134e9731SChris Mason map = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], 249*134e9731SChris Mason struct btrfs_inode_map_item); 250*134e9731SChris Mason btrfs_disk_key_to_cpu(&stat_data_key, &map->key); 251*134e9731SChris Mason ret = btrfs_del_item(trans, root->fs_info->inode_root, &path); 252*134e9731SChris Mason BUG_ON(ret); 253*134e9731SChris Mason btrfs_release_path(root, &path); 254*134e9731SChris Mason btrfs_init_path(&path); 255*134e9731SChris Mason 256*134e9731SChris Mason ret = btrfs_lookup_inode(trans, root, &path, objectid, -1); 257*134e9731SChris Mason BUG_ON(ret); 258*134e9731SChris Mason ret = btrfs_del_item(trans, root, &path); 259*134e9731SChris Mason BUG_ON(ret); 260*134e9731SChris Mason btrfs_release_path(root, &path); 261*134e9731SChris Mason error: 262*134e9731SChris Mason return ret; 263*134e9731SChris Mason } 264*134e9731SChris Mason 265*134e9731SChris Mason static void btrfs_delete_inode(struct inode *inode) 266*134e9731SChris Mason { 267*134e9731SChris Mason struct btrfs_trans_handle *trans; 268*134e9731SChris Mason struct btrfs_root *root = btrfs_sb(inode->i_sb); 269*134e9731SChris Mason truncate_inode_pages(&inode->i_data, 0); 270*134e9731SChris Mason if (is_bad_inode(inode)) { 271*134e9731SChris Mason goto no_delete; 272*134e9731SChris Mason } 273*134e9731SChris Mason inode->i_size = 0; 274*134e9731SChris Mason if (inode->i_blocks) 275*134e9731SChris Mason WARN_ON(1); 276*134e9731SChris Mason 277*134e9731SChris Mason mutex_lock(&root->fs_info->fs_mutex); 278*134e9731SChris Mason trans = btrfs_start_transaction(root, 1); 279*134e9731SChris Mason btrfs_free_inode(trans, root, inode); 280*134e9731SChris Mason btrfs_end_transaction(trans, root); 281*134e9731SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 282*134e9731SChris Mason return; 283*134e9731SChris Mason no_delete: 284*134e9731SChris Mason clear_inode(inode); 285*134e9731SChris Mason } 286*134e9731SChris Mason 287*134e9731SChris Mason 288e20d96d6SChris Mason static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, 289e20d96d6SChris Mason ino_t *ino) 290e20d96d6SChris Mason { 291e20d96d6SChris Mason const char *name = dentry->d_name.name; 292e20d96d6SChris Mason int namelen = dentry->d_name.len; 293e20d96d6SChris Mason struct btrfs_dir_item *di; 294e20d96d6SChris Mason struct btrfs_path path; 295e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 296e20d96d6SChris Mason int ret; 297e20d96d6SChris Mason 298e20d96d6SChris Mason btrfs_init_path(&path); 299e20d96d6SChris Mason ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, 300e20d96d6SChris Mason namelen, 0); 3017f5c1516SChris Mason if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) { 302e20d96d6SChris Mason *ino = 0; 303e20d96d6SChris Mason goto out; 304e20d96d6SChris Mason } 305e20d96d6SChris Mason di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], 306e20d96d6SChris Mason struct btrfs_dir_item); 307e20d96d6SChris Mason *ino = btrfs_dir_objectid(di); 308e20d96d6SChris Mason out: 309e20d96d6SChris Mason btrfs_release_path(root, &path); 310e20d96d6SChris Mason return ret; 311e20d96d6SChris Mason } 312e20d96d6SChris Mason 313e20d96d6SChris Mason static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 314e20d96d6SChris Mason struct nameidata *nd) 315e20d96d6SChris Mason { 316e20d96d6SChris Mason struct inode * inode; 317e20d96d6SChris Mason ino_t ino; 318e20d96d6SChris Mason int ret; 319e20d96d6SChris Mason 320e20d96d6SChris Mason if (dentry->d_name.len > BTRFS_NAME_LEN) 321e20d96d6SChris Mason return ERR_PTR(-ENAMETOOLONG); 322e20d96d6SChris Mason 323e20d96d6SChris Mason ret = btrfs_inode_by_name(dir, dentry, &ino); 324e20d96d6SChris Mason if (ret < 0) 325e20d96d6SChris Mason return ERR_PTR(ret); 326e20d96d6SChris Mason inode = NULL; 327e20d96d6SChris Mason if (ino) { 328e20d96d6SChris Mason inode = iget(dir->i_sb, ino); 329e20d96d6SChris Mason if (!inode) 330e20d96d6SChris Mason return ERR_PTR(-EACCES); 331e20d96d6SChris Mason } 332e20d96d6SChris Mason return d_splice_alias(inode, dentry); 333e20d96d6SChris Mason } 334e20d96d6SChris Mason 335e20d96d6SChris Mason static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 336e20d96d6SChris Mason { 337e20d96d6SChris Mason struct inode *inode = filp->f_path.dentry->d_inode; 338e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(inode->i_sb); 339e20d96d6SChris Mason struct btrfs_item *item; 340e20d96d6SChris Mason struct btrfs_dir_item *di; 341e20d96d6SChris Mason struct btrfs_key key; 342e20d96d6SChris Mason struct btrfs_path path; 343e20d96d6SChris Mason int ret; 344e20d96d6SChris Mason u32 nritems; 345e20d96d6SChris Mason struct btrfs_leaf *leaf; 346e20d96d6SChris Mason int slot; 347e20d96d6SChris Mason int advance; 348e20d96d6SChris Mason unsigned char d_type = DT_UNKNOWN; 3497f5c1516SChris Mason int over = 0; 350e20d96d6SChris Mason 351e20d96d6SChris Mason key.objectid = inode->i_ino; 352e20d96d6SChris Mason key.flags = 0; 353e20d96d6SChris Mason btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); 354e20d96d6SChris Mason key.offset = filp->f_pos; 355e20d96d6SChris Mason btrfs_init_path(&path); 356e20d96d6SChris Mason ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); 357e20d96d6SChris Mason if (ret < 0) { 358e20d96d6SChris Mason goto err; 359e20d96d6SChris Mason } 3607f5c1516SChris Mason advance = 0; 361e20d96d6SChris Mason while(1) { 362e20d96d6SChris Mason leaf = btrfs_buffer_leaf(path.nodes[0]); 363e20d96d6SChris Mason nritems = btrfs_header_nritems(&leaf->header); 364e20d96d6SChris Mason slot = path.slots[0]; 365e20d96d6SChris Mason if (advance) { 366e20d96d6SChris Mason if (slot == nritems -1) { 367e20d96d6SChris Mason ret = btrfs_next_leaf(root, &path); 368e20d96d6SChris Mason if (ret) 369e20d96d6SChris Mason break; 370e20d96d6SChris Mason leaf = btrfs_buffer_leaf(path.nodes[0]); 371e20d96d6SChris Mason nritems = btrfs_header_nritems(&leaf->header); 372e20d96d6SChris Mason slot = path.slots[0]; 373*134e9731SChris Mason #if 0 374*134e9731SChris Mason page_cache_readahead( 375*134e9731SChris Mason inode->i_sb->s_bdev->bd_inode->i_mapping, 376*134e9731SChris Mason &filp->f_ra, filp, 377*134e9731SChris Mason path.nodes[0]->b_blocknr >> 378*134e9731SChris Mason (PAGE_CACHE_SHIFT - inode->i_blkbits), 1); 379*134e9731SChris Mason #endif 380e20d96d6SChris Mason } else { 381e20d96d6SChris Mason slot++; 382e20d96d6SChris Mason path.slots[0]++; 383e20d96d6SChris Mason } 384e20d96d6SChris Mason } 385e20d96d6SChris Mason advance = 1; 386e20d96d6SChris Mason item = leaf->items + slot; 387e20d96d6SChris Mason if (btrfs_disk_key_objectid(&item->key) != key.objectid) 388e20d96d6SChris Mason break; 389e20d96d6SChris Mason if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) 390e20d96d6SChris Mason continue; 3917f5c1516SChris Mason if (btrfs_disk_key_offset(&item->key) < filp->f_pos) 3927f5c1516SChris Mason continue; 393e20d96d6SChris Mason di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 394e20d96d6SChris Mason over = filldir(dirent, (const char *)(di + 1), 395e20d96d6SChris Mason btrfs_dir_name_len(di), 396e20d96d6SChris Mason btrfs_disk_key_offset(&item->key), 397e20d96d6SChris Mason btrfs_dir_objectid(di), d_type); 3987f5c1516SChris Mason if (over) { 3997f5c1516SChris Mason filp->f_pos = btrfs_disk_key_offset(&item->key); 400e20d96d6SChris Mason break; 4017f5c1516SChris Mason } 402e20d96d6SChris Mason filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; 403e20d96d6SChris Mason } 404e20d96d6SChris Mason ret = 0; 405e20d96d6SChris Mason err: 406e20d96d6SChris Mason btrfs_release_path(root, &path); 407e20d96d6SChris Mason return ret; 408e20d96d6SChris Mason } 409e20d96d6SChris Mason 410e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb) 411e20d96d6SChris Mason { 412e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(sb); 413e20d96d6SChris Mason int ret; 414e20d96d6SChris Mason 415e20d96d6SChris Mason ret = close_ctree(root); 416e20d96d6SChris Mason if (ret) { 417e20d96d6SChris Mason printk("close ctree returns %d\n", ret); 418e20d96d6SChris Mason } 419e20d96d6SChris Mason sb->s_fs_info = NULL; 420e20d96d6SChris Mason } 4212e635a27SChris Mason 4222e635a27SChris Mason static int btrfs_fill_super(struct super_block * sb, void * data, int silent) 4232e635a27SChris Mason { 4242e635a27SChris Mason struct inode * inode; 425e20d96d6SChris Mason struct dentry * root_dentry; 426e20d96d6SChris Mason struct btrfs_super_block *disk_super; 427e20d96d6SChris Mason struct buffer_head *bh; 428e20d96d6SChris Mason struct btrfs_root *root; 4292e635a27SChris Mason 4302e635a27SChris Mason sb->s_maxbytes = MAX_LFS_FILESIZE; 4312e635a27SChris Mason sb->s_blocksize = PAGE_CACHE_SIZE; 4322e635a27SChris Mason sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 4332e635a27SChris Mason sb->s_magic = BTRFS_SUPER_MAGIC; 434e20d96d6SChris Mason sb->s_op = &btrfs_super_ops; 4352e635a27SChris Mason sb->s_time_gran = 1; 436e20d96d6SChris Mason 437e20d96d6SChris Mason bh = sb_bread(sb, BTRFS_SUPER_INFO_OFFSET / sb->s_blocksize); 438e20d96d6SChris Mason if (!bh) { 439e20d96d6SChris Mason printk("btrfs: unable to read on disk super\n"); 440e20d96d6SChris Mason return -EIO; 441e20d96d6SChris Mason } 442e20d96d6SChris Mason disk_super = (struct btrfs_super_block *)bh->b_data; 443e20d96d6SChris Mason root = open_ctree(sb, bh, disk_super); 444e20d96d6SChris Mason sb->s_fs_info = root; 445e20d96d6SChris Mason if (!root) { 446e20d96d6SChris Mason printk("btrfs: open_ctree failed\n"); 447e20d96d6SChris Mason return -EIO; 448e20d96d6SChris Mason } 449e20d96d6SChris Mason printk("read in super total blocks %Lu root %Lu\n", 450e20d96d6SChris Mason btrfs_super_total_blocks(disk_super), 451e20d96d6SChris Mason btrfs_super_root_dir(disk_super)); 452e20d96d6SChris Mason 453e20d96d6SChris Mason inode = iget_locked(sb, btrfs_super_root_dir(disk_super)); 4542e635a27SChris Mason if (!inode) 4552e635a27SChris Mason return -ENOMEM; 456e20d96d6SChris Mason if (inode->i_state & I_NEW) { 457e20d96d6SChris Mason btrfs_read_locked_inode(inode); 458e20d96d6SChris Mason unlock_new_inode(inode); 459e20d96d6SChris Mason } 4602e635a27SChris Mason 461e20d96d6SChris Mason root_dentry = d_alloc_root(inode); 462e20d96d6SChris Mason if (!root_dentry) { 4632e635a27SChris Mason iput(inode); 4642e635a27SChris Mason return -ENOMEM; 4652e635a27SChris Mason } 466e20d96d6SChris Mason sb->s_root = root_dentry; 467e20d96d6SChris Mason 4682e635a27SChris Mason return 0; 4692e635a27SChris Mason } 4702e635a27SChris Mason 471d5719762SChris Mason static void fill_inode_item(struct btrfs_inode_item *item, 472d5719762SChris Mason struct inode *inode) 473d5719762SChris Mason { 474d5719762SChris Mason btrfs_set_inode_uid(item, inode->i_uid); 475d5719762SChris Mason btrfs_set_inode_gid(item, inode->i_gid); 476d5719762SChris Mason btrfs_set_inode_size(item, inode->i_size); 477d5719762SChris Mason btrfs_set_inode_mode(item, inode->i_mode); 478d5719762SChris Mason btrfs_set_inode_nlink(item, inode->i_nlink); 479d5719762SChris Mason btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); 480d5719762SChris Mason btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); 481d5719762SChris Mason btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); 482d5719762SChris Mason btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); 483d5719762SChris Mason btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); 484d5719762SChris Mason btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); 485d5719762SChris Mason btrfs_set_inode_nblocks(item, inode->i_blocks); 486d5719762SChris Mason btrfs_set_inode_generation(item, inode->i_generation); 487d5719762SChris Mason } 488d5719762SChris Mason 489d5719762SChris Mason static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, 490d5719762SChris Mason struct inode *dir, int mode) 491d5719762SChris Mason { 492d5719762SChris Mason struct inode *inode; 493d5719762SChris Mason struct btrfs_inode_item inode_item; 494d5719762SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 495d5719762SChris Mason struct btrfs_key key; 496d5719762SChris Mason int ret; 497d5719762SChris Mason u64 objectid; 498d5719762SChris Mason 499d5719762SChris Mason inode = new_inode(dir->i_sb); 500d5719762SChris Mason if (!inode) 501d5719762SChris Mason return ERR_PTR(-ENOMEM); 502d5719762SChris Mason 503d5719762SChris Mason ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); 504d5719762SChris Mason BUG_ON(ret); 505d5719762SChris Mason 506d5719762SChris Mason inode->i_uid = current->fsuid; 507d5719762SChris Mason inode->i_gid = current->fsgid; 508d5719762SChris Mason inode->i_mode = mode; 509d5719762SChris Mason inode->i_ino = objectid; 510d5719762SChris Mason inode->i_blocks = 0; 511d5719762SChris Mason inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; 512d5719762SChris Mason fill_inode_item(&inode_item, inode); 513d5719762SChris Mason 514d5719762SChris Mason 515d5719762SChris Mason key.objectid = objectid; 516d5719762SChris Mason key.flags = 0; 517d5719762SChris Mason key.offset = 0; 518d5719762SChris Mason btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); 519d5719762SChris Mason ret = btrfs_insert_inode_map(trans, root, objectid, &key); 520d5719762SChris Mason BUG_ON(ret); 521d5719762SChris Mason 522d5719762SChris Mason ret = btrfs_insert_inode(trans, root, objectid, &inode_item); 523d5719762SChris Mason BUG_ON(ret); 524d5719762SChris Mason 525d5719762SChris Mason insert_inode_hash(inode); 526d5719762SChris Mason // FIXME mark_inode_dirty(inode) 527d5719762SChris Mason return inode; 528d5719762SChris Mason } 529d5719762SChris Mason 530d5719762SChris Mason static int btrfs_add_link(struct btrfs_trans_handle *trans, 531d5719762SChris Mason struct dentry *dentry, struct inode *inode) 532d5719762SChris Mason { 533d5719762SChris Mason int ret; 534d5719762SChris Mason ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb), 535d5719762SChris Mason dentry->d_name.name, dentry->d_name.len, 536d5719762SChris Mason dentry->d_parent->d_inode->i_ino, 537d5719762SChris Mason inode->i_ino, 0); 538d5719762SChris Mason return ret; 539d5719762SChris Mason } 540d5719762SChris Mason 541d5719762SChris Mason static int btrfs_add_nondir(struct btrfs_trans_handle *trans, 542d5719762SChris Mason struct dentry *dentry, struct inode *inode) 543d5719762SChris Mason { 544d5719762SChris Mason int err = btrfs_add_link(trans, dentry, inode); 545d5719762SChris Mason if (!err) { 546d5719762SChris Mason d_instantiate(dentry, inode); 547d5719762SChris Mason return 0; 548d5719762SChris Mason } 549d5719762SChris Mason return err; 550d5719762SChris Mason } 551d5719762SChris Mason 552d5719762SChris Mason static int btrfs_create(struct inode *dir, struct dentry *dentry, 553d5719762SChris Mason int mode, struct nameidata *nd) 554d5719762SChris Mason { 555d5719762SChris Mason struct btrfs_trans_handle *trans; 556d5719762SChris Mason struct btrfs_root *root = btrfs_sb(dir->i_sb); 557d5719762SChris Mason struct inode *inode; 558d5719762SChris Mason int err; 559*134e9731SChris Mason int drop_inode = 0; 560d5719762SChris Mason 561d561c025SChris Mason mutex_lock(&root->fs_info->fs_mutex); 562d5719762SChris Mason trans = btrfs_start_transaction(root, 1); 563d5719762SChris Mason inode = btrfs_new_inode(trans, dir, mode); 564d5719762SChris Mason err = PTR_ERR(inode); 565d5719762SChris Mason if (IS_ERR(inode)) 566d561c025SChris Mason goto out_unlock; 567d5719762SChris Mason // FIXME mark the inode dirty 568d5719762SChris Mason err = btrfs_add_nondir(trans, dentry, inode); 569*134e9731SChris Mason if (err) 570*134e9731SChris Mason drop_inode = 1; 571d5719762SChris Mason dir->i_sb->s_dirt = 1; 572d5719762SChris Mason btrfs_end_transaction(trans, root); 573d561c025SChris Mason out_unlock: 574d561c025SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 575*134e9731SChris Mason if (drop_inode) { 576*134e9731SChris Mason inode_dec_link_count(inode); 577*134e9731SChris Mason iput(inode); 578*134e9731SChris Mason } 579d5719762SChris Mason return err; 580d5719762SChris Mason } 581d5719762SChris Mason 582d5719762SChris Mason static int btrfs_sync_fs(struct super_block *sb, int wait) 583d5719762SChris Mason { 584d5719762SChris Mason struct btrfs_trans_handle *trans; 585d5719762SChris Mason struct btrfs_root *root; 586d5719762SChris Mason int ret; 587df2ce34cSChris Mason 588d5719762SChris Mason sb->s_dirt = 0; 589d561c025SChris Mason if (!wait) { 590d561c025SChris Mason filemap_flush(sb->s_bdev->bd_inode->i_mapping); 591df2ce34cSChris Mason return 0; 592d561c025SChris Mason } 593d561c025SChris Mason filemap_write_and_wait(sb->s_bdev->bd_inode->i_mapping); 594df2ce34cSChris Mason 595d5719762SChris Mason root = btrfs_sb(sb); 596d561c025SChris Mason mutex_lock(&root->fs_info->fs_mutex); 597d5719762SChris Mason trans = btrfs_start_transaction(root, 1); 598d5719762SChris Mason ret = btrfs_commit_transaction(trans, root); 599d5719762SChris Mason sb->s_dirt = 0; 600d5719762SChris Mason BUG_ON(ret); 601d5719762SChris Mason printk("btrfs sync_fs\n"); 602d561c025SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 603d5719762SChris Mason return 0; 604d5719762SChris Mason } 605d5719762SChris Mason 606d561c025SChris Mason static void btrfs_write_super(struct super_block *sb) 607d561c025SChris Mason { 608d561c025SChris Mason btrfs_sync_fs(sb, 1); 609d561c025SChris Mason } 610d561c025SChris Mason 611d561c025SChris Mason 6122e635a27SChris Mason static int btrfs_get_sb(struct file_system_type *fs_type, 6132e635a27SChris Mason int flags, const char *dev_name, void *data, struct vfsmount *mnt) 6142e635a27SChris Mason { 6152e635a27SChris Mason return get_sb_bdev(fs_type, flags, dev_name, data, 6162e635a27SChris Mason btrfs_fill_super, mnt); 6172e635a27SChris Mason } 6182e635a27SChris Mason 6192e635a27SChris Mason static struct file_system_type btrfs_fs_type = { 6202e635a27SChris Mason .owner = THIS_MODULE, 6212e635a27SChris Mason .name = "btrfs", 6222e635a27SChris Mason .get_sb = btrfs_get_sb, 6232e635a27SChris Mason .kill_sb = kill_block_super, 6242e635a27SChris Mason .fs_flags = FS_REQUIRES_DEV, 6252e635a27SChris Mason }; 6262e635a27SChris Mason 627e20d96d6SChris Mason static struct super_operations btrfs_super_ops = { 628e20d96d6SChris Mason .statfs = simple_statfs, 629*134e9731SChris Mason .delete_inode = btrfs_delete_inode, 630e20d96d6SChris Mason .put_super = btrfs_put_super, 631e20d96d6SChris Mason .read_inode = btrfs_read_locked_inode, 632d5719762SChris Mason .write_super = btrfs_write_super, 633d5719762SChris Mason .sync_fs = btrfs_sync_fs, 634e20d96d6SChris Mason }; 635e20d96d6SChris Mason 636e20d96d6SChris Mason static struct inode_operations btrfs_dir_inode_operations = { 637e20d96d6SChris Mason .lookup = btrfs_lookup, 638d5719762SChris Mason .create = btrfs_create, 639*134e9731SChris Mason .unlink = btrfs_unlink, 640e20d96d6SChris Mason }; 641e20d96d6SChris Mason 642e20d96d6SChris Mason static struct file_operations btrfs_dir_file_operations = { 643e20d96d6SChris Mason .llseek = generic_file_llseek, 644e20d96d6SChris Mason .read = generic_read_dir, 645e20d96d6SChris Mason .readdir = btrfs_readdir, 646e20d96d6SChris Mason }; 647e20d96d6SChris Mason 648e20d96d6SChris Mason 6492e635a27SChris Mason static int __init init_btrfs_fs(void) 6502e635a27SChris Mason { 6512e635a27SChris Mason printk("btrfs loaded!\n"); 6522e635a27SChris Mason return register_filesystem(&btrfs_fs_type); 6532e635a27SChris Mason } 6542e635a27SChris Mason 6552e635a27SChris Mason static void __exit exit_btrfs_fs(void) 6562e635a27SChris Mason { 6572e635a27SChris Mason unregister_filesystem(&btrfs_fs_type); 6582e635a27SChris Mason printk("btrfs unloaded\n"); 6592e635a27SChris Mason } 6602e635a27SChris Mason 6612e635a27SChris Mason module_init(init_btrfs_fs) 6622e635a27SChris Mason module_exit(exit_btrfs_fs) 6632e635a27SChris Mason 6642e635a27SChris Mason MODULE_LICENSE("GPL"); 665