lkml.org 
[lkml]   [2007]   [Jun]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [ANNOUNCE] Btrfs: a copy on write, snapshotting FS
    On Tue, Jun 12, 2007 at 04:14:39PM -0400, Chris Mason wrote:
    > > Aside from folding snapshot history into the origin's namespace... It
    > > could be possible to have a mount.btrfs that allows subvolumes and/or
    > > snapshot volumes to be mounted as unique roots? I'd imagine a bind
    > > mount _could_ provide this too? Anyway, I'm just interested in
    > > understanding the vision for managing the potentially complex nature
    > > of a Btrfs namespace.
    >
    > One option is to put the real btrfs root into some directory in
    > (/sys/fs/btrfs/$device?) and then use tools in userland to mount -o bind
    > outside of that. I wanted to wait to get fancy until I had a better
    > idea of how people would use the feature.

    We already support mounting into subdirectories of a filesystem for
    nfs connection sharing. The patch below makes use of this to allow
    mounting any subdirectory of a btrfs filesystem by specifying it in
    the form of /dev/somedevice:directory and when no subdirectory
    is specified uses 'default'. To make this more useful btrfs directories
    should grow some way to be marked head of a subvolume, and we'd need
    a more useful way to actually create subvolumes and snapshots without
    fugly ioctls.

    Btw, do create a subvolume with my patch you need to escape back to
    the global root which is done by specifing /dev/somedevice:. as the
    device on the mount command line.


    Index: btrfs-0.2/super.c
    ===================================================================
    --- btrfs-0.2.orig/super.c 2007-06-13 03:44:38.000000000 +0200
    +++ btrfs-0.2/super.c 2007-06-13 03:48:35.000000000 +0200
    @@ -17,6 +17,7 @@
    */

    #include <linux/module.h>
    +#include <linux/blkdev.h>
    #include <linux/buffer_head.h>
    #include <linux/fs.h>
    #include <linux/pagemap.h>
    @@ -26,6 +27,7 @@
    #include <linux/string.h>
    #include <linux/smp_lock.h>
    #include <linux/backing-dev.h>
    +#include <linux/mount.h>
    #include <linux/mpage.h>
    #include <linux/swap.h>
    #include <linux/writeback.h>
    @@ -135,11 +137,114 @@ static void btrfs_write_super(struct sup
    sb->s_dirt = 0;
    }

    +/*
    + * This is almost a copy of get_sb_bdev in fs/super.c.
    + * We need the local copy to allow direct mounting of
    + * subvolumes, but this could be easily integrated back
    + * into the generic version. --hch
    + */
    +
    +/* start copy & paste */
    +static int set_bdev_super(struct super_block *s, void *data)
    +{
    + s->s_bdev = data;
    + s->s_dev = s->s_bdev->bd_dev;
    + return 0;
    +}
    +
    +static int test_bdev_super(struct super_block *s, void *data)
    +{
    + return (void *)s->s_bdev == data;
    +}
    +
    +int btrfs_get_sb_bdev(struct file_system_type *fs_type,
    + int flags, const char *dev_name, void *data,
    + int (*fill_super)(struct super_block *, void *, int),
    + struct vfsmount *mnt, const char *subvol)
    +{
    + struct block_device *bdev = NULL;
    + struct super_block *s;
    + struct dentry *root;
    + int error = 0;
    +
    + bdev = open_bdev_excl(dev_name, flags, fs_type);
    + if (IS_ERR(bdev))
    + return PTR_ERR(bdev);
    +
    + /*
    + * once the super is inserted into the list by sget, s_umount
    + * will protect the lockfs code from trying to start a snapshot
    + * while we are mounting
    + */
    + down(&bdev->bd_mount_sem);
    + s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
    + up(&bdev->bd_mount_sem);
    + if (IS_ERR(s))
    + goto error_s;
    +
    + if (s->s_root) {
    + if ((flags ^ s->s_flags) & MS_RDONLY) {
    + up_write(&s->s_umount);
    + deactivate_super(s);
    + error = -EBUSY;
    + goto error_bdev;
    + }
    +
    + close_bdev_excl(bdev);
    + bdev = NULL;
    + } else {
    + char b[BDEVNAME_SIZE];
    +
    + s->s_flags = flags;
    + strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
    + sb_set_blocksize(s, block_size(bdev));
    + error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
    + if (error) {
    + up_write(&s->s_umount);
    + deactivate_super(s);
    + goto error;
    + }
    +
    + s->s_flags |= MS_ACTIVE;
    + }
    +
    + if (subvol) {
    + root = lookup_one_len(subvol, s->s_root, strlen(subvol));
    + if (!root) {
    + error = -ENXIO;
    + goto error_bdev;
    + }
    + } else {
    + root = dget(s->s_root);
    + }
    +
    + mnt->mnt_sb = s;
    + mnt->mnt_root = root;
    + return 0;
    +
    +error_s:
    + error = PTR_ERR(s);
    +error_bdev:
    + if (bdev)
    + close_bdev_excl(bdev);
    +error:
    + return error;
    +}
    +/* end copy & paste */
    +
    static int btrfs_get_sb(struct file_system_type *fs_type,
    - int flags, const char *dev_name, void *data, struct vfsmount *mnt)
    + int flags, const char *identifier, void *data, struct vfsmount *mnt)
    {
    - return get_sb_bdev(fs_type, flags, dev_name, data,
    - btrfs_fill_super, mnt);
    + char *_identifier = kstrdup(identifier, GFP_KERNEL);
    + const char *dev_name;
    +
    + dev_name = strsep(&_identifier, ":");
    + if (!dev_name)
    + return -ENOMEM;
    +
    + return btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
    + btrfs_fill_super, mnt,
    + _identifier ? _identifier : "default");
    }

    static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-06-13 05:11    [W:0.028 / U:63.344 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site