16cbd5570SChris Mason /* 26cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 36cbd5570SChris Mason * 46cbd5570SChris Mason * This program is free software; you can redistribute it and/or 56cbd5570SChris Mason * modify it under the terms of the GNU General Public 66cbd5570SChris Mason * License v2 as published by the Free Software Foundation. 76cbd5570SChris Mason * 86cbd5570SChris Mason * This program is distributed in the hope that it will be useful, 96cbd5570SChris Mason * but WITHOUT ANY WARRANTY; without even the implied warranty of 106cbd5570SChris Mason * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 116cbd5570SChris Mason * General Public License for more details. 126cbd5570SChris Mason * 136cbd5570SChris Mason * You should have received a copy of the GNU General Public 146cbd5570SChris Mason * License along with this program; if not, write to the 156cbd5570SChris Mason * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 166cbd5570SChris Mason * Boston, MA 021110-1307, USA. 176cbd5570SChris Mason */ 186cbd5570SChris Mason 194b82d6e4SYan #include <linux/blkdev.h> 202e635a27SChris Mason #include <linux/module.h> 21e20d96d6SChris Mason #include <linux/buffer_head.h> 222e635a27SChris Mason #include <linux/fs.h> 232e635a27SChris Mason #include <linux/pagemap.h> 242e635a27SChris Mason #include <linux/highmem.h> 252e635a27SChris Mason #include <linux/time.h> 262e635a27SChris Mason #include <linux/init.h> 272e635a27SChris Mason #include <linux/string.h> 282e635a27SChris Mason #include <linux/smp_lock.h> 292e635a27SChris Mason #include <linux/backing-dev.h> 304b82d6e4SYan #include <linux/mount.h> 31dee26a9fSChris Mason #include <linux/mpage.h> 3275dfe396SChris Mason #include <linux/swap.h> 3375dfe396SChris Mason #include <linux/writeback.h> 348fd17795SChris Mason #include <linux/statfs.h> 3508607c1bSChris Mason #include <linux/compat.h> 3695e05289SChris Mason #include <linux/parser.h> 372e635a27SChris Mason #include "ctree.h" 38e20d96d6SChris Mason #include "disk-io.h" 39d5719762SChris Mason #include "transaction.h" 402c90e5d6SChris Mason #include "btrfs_inode.h" 41c5739bbaSChris Mason #include "ioctl.h" 423a686375SChris Mason #include "print-tree.h" 435103e947SJosef Bacik #include "xattr.h" 442e635a27SChris Mason 455f39d397SChris Mason #define BTRFS_SUPER_MAGIC 0x9123683E 46e20d96d6SChris Mason 47e20d96d6SChris Mason static struct super_operations btrfs_super_ops; 48e20d96d6SChris Mason 49e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb) 50e20d96d6SChris Mason { 51e20d96d6SChris Mason struct btrfs_root *root = btrfs_sb(sb); 5258176a96SJosef Bacik struct btrfs_fs_info *fs = root->fs_info; 53e20d96d6SChris Mason int ret; 54e20d96d6SChris Mason 55e20d96d6SChris Mason ret = close_ctree(root); 56e20d96d6SChris Mason if (ret) { 57e20d96d6SChris Mason printk("close ctree returns %d\n", ret); 58e20d96d6SChris Mason } 5958176a96SJosef Bacik btrfs_sysfs_del_super(fs); 60e20d96d6SChris Mason sb->s_fs_info = NULL; 61e20d96d6SChris Mason } 622e635a27SChris Mason 6395e05289SChris Mason enum { 64*be20aa9dSChris Mason Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_err, 6595e05289SChris Mason }; 6695e05289SChris Mason 6795e05289SChris Mason static match_table_t tokens = { 6895e05289SChris Mason {Opt_subvol, "subvol=%s"}, 69b6cda9bcSChris Mason {Opt_nodatasum, "nodatasum"}, 70*be20aa9dSChris Mason {Opt_nodatacow, "nodatacow"}, 7195e05289SChris Mason {Opt_err, NULL} 7295e05289SChris Mason }; 7395e05289SChris Mason 7495e05289SChris Mason static int parse_options (char * options, 7595e05289SChris Mason struct btrfs_root *root, 7695e05289SChris Mason char **subvol_name) 7795e05289SChris Mason { 7895e05289SChris Mason char * p; 79b6cda9bcSChris Mason struct btrfs_fs_info *info = NULL; 8095e05289SChris Mason substring_t args[MAX_OPT_ARGS]; 81b6cda9bcSChris Mason 8295e05289SChris Mason if (!options) 8395e05289SChris Mason return 1; 8495e05289SChris Mason 85*be20aa9dSChris Mason /* 86*be20aa9dSChris Mason * strsep changes the string, duplicate it because parse_options 87*be20aa9dSChris Mason * gets called twice 88*be20aa9dSChris Mason */ 89*be20aa9dSChris Mason options = kstrdup(options, GFP_NOFS); 90*be20aa9dSChris Mason if (!options) 91*be20aa9dSChris Mason return -ENOMEM; 92*be20aa9dSChris Mason 93*be20aa9dSChris Mason if (root) 94*be20aa9dSChris Mason info = root->fs_info; 95*be20aa9dSChris Mason 9695e05289SChris Mason while ((p = strsep (&options, ",")) != NULL) { 9795e05289SChris Mason int token; 9895e05289SChris Mason if (!*p) 9995e05289SChris Mason continue; 10095e05289SChris Mason 10195e05289SChris Mason token = match_token(p, tokens, args); 10295e05289SChris Mason switch (token) { 10395e05289SChris Mason case Opt_subvol: 104*be20aa9dSChris Mason if (subvol_name) { 10595e05289SChris Mason *subvol_name = match_strdup(&args[0]); 106*be20aa9dSChris Mason } 10795e05289SChris Mason break; 108b6cda9bcSChris Mason case Opt_nodatasum: 109*be20aa9dSChris Mason if (info) { 110*be20aa9dSChris Mason printk("btrfs: setting nodatacsum\n"); 111b6cda9bcSChris Mason btrfs_set_opt(info->mount_opt, NODATASUM); 112*be20aa9dSChris Mason } 113*be20aa9dSChris Mason break; 114*be20aa9dSChris Mason case Opt_nodatacow: 115*be20aa9dSChris Mason if (info) { 116*be20aa9dSChris Mason printk("btrfs: setting nodatacow\n"); 117*be20aa9dSChris Mason btrfs_set_opt(info->mount_opt, NODATACOW); 118*be20aa9dSChris Mason btrfs_set_opt(info->mount_opt, NODATASUM); 119*be20aa9dSChris Mason } 120b6cda9bcSChris Mason break; 12195e05289SChris Mason default: 122*be20aa9dSChris Mason break; 12395e05289SChris Mason } 12495e05289SChris Mason } 125*be20aa9dSChris Mason kfree(options); 12695e05289SChris Mason return 1; 12795e05289SChris Mason } 12895e05289SChris Mason 1292e635a27SChris Mason static int btrfs_fill_super(struct super_block * sb, void * data, int silent) 1302e635a27SChris Mason { 1312e635a27SChris Mason struct inode * inode; 132e20d96d6SChris Mason struct dentry * root_dentry; 133e20d96d6SChris Mason struct btrfs_super_block *disk_super; 1340f7d52f4SChris Mason struct btrfs_root *tree_root; 135d6e4a428SChris Mason struct btrfs_inode *bi; 13639279cc3SChris Mason int err; 1372e635a27SChris Mason 1382e635a27SChris Mason sb->s_maxbytes = MAX_LFS_FILESIZE; 1392e635a27SChris Mason sb->s_magic = BTRFS_SUPER_MAGIC; 140e20d96d6SChris Mason sb->s_op = &btrfs_super_ops; 1415103e947SJosef Bacik sb->s_xattr = btrfs_xattr_handlers; 1422e635a27SChris Mason sb->s_time_gran = 1; 143e20d96d6SChris Mason 1440f7d52f4SChris Mason tree_root = open_ctree(sb); 145d98237b3SChris Mason 14639279cc3SChris Mason if (!tree_root || IS_ERR(tree_root)) { 147e20d96d6SChris Mason printk("btrfs: open_ctree failed\n"); 148e20d96d6SChris Mason return -EIO; 149e20d96d6SChris Mason } 1500f7d52f4SChris Mason sb->s_fs_info = tree_root; 1515f39d397SChris Mason disk_super = &tree_root->fs_info->super_copy; 152c5739bbaSChris Mason inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super), 153c5739bbaSChris Mason tree_root); 154d6e4a428SChris Mason bi = BTRFS_I(inode); 155d6e4a428SChris Mason bi->location.objectid = inode->i_ino; 156d6e4a428SChris Mason bi->location.offset = 0; 1570f7d52f4SChris Mason bi->root = tree_root; 158b888db2bSChris Mason 159d6e4a428SChris Mason btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); 160d6e4a428SChris Mason 16139279cc3SChris Mason if (!inode) { 16239279cc3SChris Mason err = -ENOMEM; 16339279cc3SChris Mason goto fail_close; 16439279cc3SChris Mason } 165e20d96d6SChris Mason if (inode->i_state & I_NEW) { 166e20d96d6SChris Mason btrfs_read_locked_inode(inode); 167e20d96d6SChris Mason unlock_new_inode(inode); 168e20d96d6SChris Mason } 1692e635a27SChris Mason 170e20d96d6SChris Mason root_dentry = d_alloc_root(inode); 171e20d96d6SChris Mason if (!root_dentry) { 1722e635a27SChris Mason iput(inode); 17339279cc3SChris Mason err = -ENOMEM; 17439279cc3SChris Mason goto fail_close; 1752e635a27SChris Mason } 17658176a96SJosef Bacik 177b6cda9bcSChris Mason parse_options((char *)data, tree_root, NULL); 178b6cda9bcSChris Mason 17958176a96SJosef Bacik /* this does the super kobj at the same time */ 18058176a96SJosef Bacik err = btrfs_sysfs_add_super(tree_root->fs_info); 18158176a96SJosef Bacik if (err) 18258176a96SJosef Bacik goto fail_close; 18358176a96SJosef Bacik 184e20d96d6SChris Mason sb->s_root = root_dentry; 18508607c1bSChris Mason btrfs_transaction_queue_work(tree_root, HZ * 30); 1862e635a27SChris Mason return 0; 1872e635a27SChris Mason 18839279cc3SChris Mason fail_close: 18939279cc3SChris Mason close_ctree(tree_root); 190d5719762SChris Mason return err; 191d5719762SChris Mason } 192d5719762SChris Mason 193d5719762SChris Mason static int btrfs_sync_fs(struct super_block *sb, int wait) 194d5719762SChris Mason { 195d5719762SChris Mason struct btrfs_trans_handle *trans; 196d5719762SChris Mason struct btrfs_root *root; 197d5719762SChris Mason int ret; 198d98237b3SChris Mason root = btrfs_sb(sb); 199df2ce34cSChris Mason 200d5719762SChris Mason sb->s_dirt = 0; 201d561c025SChris Mason if (!wait) { 2027cfcc17eSChris Mason filemap_flush(root->fs_info->btree_inode->i_mapping); 203df2ce34cSChris Mason return 0; 204d561c025SChris Mason } 205e9d0b13bSChris Mason btrfs_clean_old_snapshots(root); 206d561c025SChris Mason mutex_lock(&root->fs_info->fs_mutex); 207e9d0b13bSChris Mason btrfs_defrag_dirty_roots(root->fs_info); 208d5719762SChris Mason trans = btrfs_start_transaction(root, 1); 209d5719762SChris Mason ret = btrfs_commit_transaction(trans, root); 210d5719762SChris Mason sb->s_dirt = 0; 211d561c025SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 21254aa1f4dSChris Mason return ret; 213d5719762SChris Mason } 214d5719762SChris Mason 215d561c025SChris Mason static void btrfs_write_super(struct super_block *sb) 216d561c025SChris Mason { 21708607c1bSChris Mason sb->s_dirt = 0; 218d561c025SChris Mason } 219d561c025SChris Mason 2204b82d6e4SYan /* 2214b82d6e4SYan * This is almost a copy of get_sb_bdev in fs/super.c. 2224b82d6e4SYan * We need the local copy to allow direct mounting of 2234b82d6e4SYan * subvolumes, but this could be easily integrated back 2244b82d6e4SYan * into the generic version. --hch 2254b82d6e4SYan */ 2264b82d6e4SYan 2274b82d6e4SYan /* start copy & paste */ 2284b82d6e4SYan static int set_bdev_super(struct super_block *s, void *data) 2292e635a27SChris Mason { 2304b82d6e4SYan s->s_bdev = data; 2314b82d6e4SYan s->s_dev = s->s_bdev->bd_dev; 2324b82d6e4SYan return 0; 2334b82d6e4SYan } 2344b82d6e4SYan 2354b82d6e4SYan static int test_bdev_super(struct super_block *s, void *data) 2364b82d6e4SYan { 2374b82d6e4SYan return (void *)s->s_bdev == data; 2384b82d6e4SYan } 2394b82d6e4SYan 2404b82d6e4SYan int btrfs_get_sb_bdev(struct file_system_type *fs_type, 2414b82d6e4SYan int flags, const char *dev_name, void *data, 2424b82d6e4SYan int (*fill_super)(struct super_block *, void *, int), 2434b82d6e4SYan struct vfsmount *mnt, const char *subvol) 2444b82d6e4SYan { 2454b82d6e4SYan struct block_device *bdev = NULL; 2464b82d6e4SYan struct super_block *s; 2474b82d6e4SYan struct dentry *root; 2484b82d6e4SYan int error = 0; 2494b82d6e4SYan 2504b82d6e4SYan bdev = open_bdev_excl(dev_name, flags, fs_type); 2514b82d6e4SYan if (IS_ERR(bdev)) 2524b82d6e4SYan return PTR_ERR(bdev); 2534b82d6e4SYan 2544b82d6e4SYan /* 2554b82d6e4SYan * once the super is inserted into the list by sget, s_umount 2564b82d6e4SYan * will protect the lockfs code from trying to start a snapshot 2574b82d6e4SYan * while we are mounting 2584b82d6e4SYan */ 2594b82d6e4SYan down(&bdev->bd_mount_sem); 2604b82d6e4SYan s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); 2614b82d6e4SYan up(&bdev->bd_mount_sem); 2624b82d6e4SYan if (IS_ERR(s)) 2634b82d6e4SYan goto error_s; 2644b82d6e4SYan 2654b82d6e4SYan if (s->s_root) { 2664b82d6e4SYan if ((flags ^ s->s_flags) & MS_RDONLY) { 2674b82d6e4SYan up_write(&s->s_umount); 2684b82d6e4SYan deactivate_super(s); 2694b82d6e4SYan error = -EBUSY; 2704b82d6e4SYan goto error_bdev; 2714b82d6e4SYan } 2724b82d6e4SYan 2734b82d6e4SYan close_bdev_excl(bdev); 2744b82d6e4SYan } else { 2754b82d6e4SYan char b[BDEVNAME_SIZE]; 2764b82d6e4SYan 2774b82d6e4SYan s->s_flags = flags; 2784b82d6e4SYan strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); 2794b82d6e4SYan sb_set_blocksize(s, block_size(bdev)); 2804b82d6e4SYan error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); 2814b82d6e4SYan if (error) { 2824b82d6e4SYan up_write(&s->s_umount); 2834b82d6e4SYan deactivate_super(s); 2844b82d6e4SYan goto error; 2854b82d6e4SYan } 2864b82d6e4SYan 2874b82d6e4SYan s->s_flags |= MS_ACTIVE; 2884b82d6e4SYan } 2894b82d6e4SYan 2904b82d6e4SYan if (subvol) { 2914b82d6e4SYan root = lookup_one_len(subvol, s->s_root, strlen(subvol)); 2924b82d6e4SYan if (IS_ERR(root)) { 2934b82d6e4SYan up_write(&s->s_umount); 2944b82d6e4SYan deactivate_super(s); 2954b82d6e4SYan error = PTR_ERR(root); 2964b82d6e4SYan goto error; 2974b82d6e4SYan } 2984b82d6e4SYan if (!root->d_inode) { 2994b82d6e4SYan dput(root); 3004b82d6e4SYan up_write(&s->s_umount); 3014b82d6e4SYan deactivate_super(s); 3024b82d6e4SYan error = -ENXIO; 3034b82d6e4SYan goto error; 3044b82d6e4SYan } 3054b82d6e4SYan } else { 3064b82d6e4SYan root = dget(s->s_root); 3074b82d6e4SYan } 3084b82d6e4SYan 3094b82d6e4SYan mnt->mnt_sb = s; 3104b82d6e4SYan mnt->mnt_root = root; 3114b82d6e4SYan return 0; 3124b82d6e4SYan 3134b82d6e4SYan error_s: 3144b82d6e4SYan error = PTR_ERR(s); 3154b82d6e4SYan error_bdev: 3164b82d6e4SYan close_bdev_excl(bdev); 3174b82d6e4SYan error: 3184b82d6e4SYan return error; 3194b82d6e4SYan } 3204b82d6e4SYan /* end copy & paste */ 3214b82d6e4SYan 3224b82d6e4SYan static int btrfs_get_sb(struct file_system_type *fs_type, 32395e05289SChris Mason int flags, const char *dev_name, void *data, struct vfsmount *mnt) 3244b82d6e4SYan { 3254b82d6e4SYan int ret; 32695e05289SChris Mason char *subvol_name = NULL; 3274b82d6e4SYan 32895e05289SChris Mason parse_options((char *)data, NULL, &subvol_name); 3294b82d6e4SYan ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, 3304b82d6e4SYan btrfs_fill_super, mnt, 3314b82d6e4SYan subvol_name ? subvol_name : "default"); 3324b82d6e4SYan return ret; 3332e635a27SChris Mason } 3342e635a27SChris Mason 3358fd17795SChris Mason static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) 3368fd17795SChris Mason { 3378fd17795SChris Mason struct btrfs_root *root = btrfs_sb(dentry->d_sb); 3384b52dff6SChris Mason struct btrfs_super_block *disk_super = &root->fs_info->super_copy; 339db94535dSChris Mason int bits = dentry->d_sb->s_blocksize_bits; 3408fd17795SChris Mason 3418fd17795SChris Mason buf->f_namelen = BTRFS_NAME_LEN; 342db94535dSChris Mason buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; 343db94535dSChris Mason buf->f_bfree = buf->f_blocks - 344db94535dSChris Mason (btrfs_super_bytes_used(disk_super) >> bits); 3458fd17795SChris Mason buf->f_bavail = buf->f_bfree; 3468fd17795SChris Mason buf->f_bsize = dentry->d_sb->s_blocksize; 3478fd17795SChris Mason buf->f_type = BTRFS_SUPER_MAGIC; 3488fd17795SChris Mason return 0; 3498fd17795SChris Mason } 350b5133862SChris Mason 3512e635a27SChris Mason static struct file_system_type btrfs_fs_type = { 3522e635a27SChris Mason .owner = THIS_MODULE, 3532e635a27SChris Mason .name = "btrfs", 3542e635a27SChris Mason .get_sb = btrfs_get_sb, 3552e635a27SChris Mason .kill_sb = kill_block_super, 3562e635a27SChris Mason .fs_flags = FS_REQUIRES_DEV, 3572e635a27SChris Mason }; 3582e635a27SChris Mason 359e20d96d6SChris Mason static struct super_operations btrfs_super_ops = { 360134e9731SChris Mason .delete_inode = btrfs_delete_inode, 361e20d96d6SChris Mason .put_super = btrfs_put_super, 362e20d96d6SChris Mason .read_inode = btrfs_read_locked_inode, 363d5719762SChris Mason .write_super = btrfs_write_super, 364d5719762SChris Mason .sync_fs = btrfs_sync_fs, 3654730a4bcSChris Mason .write_inode = btrfs_write_inode, 366b5133862SChris Mason .dirty_inode = btrfs_dirty_inode, 3672c90e5d6SChris Mason .alloc_inode = btrfs_alloc_inode, 3682c90e5d6SChris Mason .destroy_inode = btrfs_destroy_inode, 3698fd17795SChris Mason .statfs = btrfs_statfs, 370e20d96d6SChris Mason }; 371e20d96d6SChris Mason 3722e635a27SChris Mason static int __init init_btrfs_fs(void) 3732e635a27SChris Mason { 3742c90e5d6SChris Mason int err; 37558176a96SJosef Bacik 37658176a96SJosef Bacik err = btrfs_init_sysfs(); 37758176a96SJosef Bacik if (err) 37858176a96SJosef Bacik return err; 37958176a96SJosef Bacik 38008607c1bSChris Mason btrfs_init_transaction_sys(); 38139279cc3SChris Mason err = btrfs_init_cachep(); 3822c90e5d6SChris Mason if (err) 3832f4cbe64SWyatt Banks goto free_transaction_sys; 3842f4cbe64SWyatt Banks err = extent_map_init(); 3852f4cbe64SWyatt Banks if (err) 3862f4cbe64SWyatt Banks goto free_cachep; 3872f4cbe64SWyatt Banks 3882f4cbe64SWyatt Banks err = register_filesystem(&btrfs_fs_type); 3892f4cbe64SWyatt Banks if (err) 3902f4cbe64SWyatt Banks goto free_extent_map; 3912f4cbe64SWyatt Banks return 0; 3922f4cbe64SWyatt Banks 3932f4cbe64SWyatt Banks free_extent_map: 3942f4cbe64SWyatt Banks extent_map_exit(); 3952f4cbe64SWyatt Banks free_cachep: 3962f4cbe64SWyatt Banks btrfs_destroy_cachep(); 3972f4cbe64SWyatt Banks free_transaction_sys: 3982f4cbe64SWyatt Banks btrfs_exit_transaction_sys(); 3992f4cbe64SWyatt Banks btrfs_exit_sysfs(); 4002c90e5d6SChris Mason return err; 4012e635a27SChris Mason } 4022e635a27SChris Mason 4032e635a27SChris Mason static void __exit exit_btrfs_fs(void) 4042e635a27SChris Mason { 40508607c1bSChris Mason btrfs_exit_transaction_sys(); 40639279cc3SChris Mason btrfs_destroy_cachep(); 407a52d9a80SChris Mason extent_map_exit(); 4082e635a27SChris Mason unregister_filesystem(&btrfs_fs_type); 40958176a96SJosef Bacik btrfs_exit_sysfs(); 4102e635a27SChris Mason } 4112e635a27SChris Mason 4122e635a27SChris Mason module_init(init_btrfs_fs) 4132e635a27SChris Mason module_exit(exit_btrfs_fs) 4142e635a27SChris Mason 4152e635a27SChris Mason MODULE_LICENSE("GPL"); 416