Re: [PATCH 2/7] Assign bdi in super_block

Jan Kara
2009-09-14T13:02:30Z

On Mon 14-09-09 11:36:29, Jens Axboe wrote:
> We do this automatically in get_sb_bdev() from the set_bdev_super()
> callback. Filesystems that have their own private backing_dev_info
> must assign that in ->fill_super().
>
> Note that ->s_bdi assignment is required for proper writeback!
>
> Acked-by: Christoph Hellwig <hch@infradead.org>
> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Hmm, looking at this again, I'm not sure this will work for NFS. It seems
to set mapping->backing_dev_info to its private backing dev info for
regular files while it leaves it intact for other inodes (e.g.
directories). I'm not sure why it does so but it seems its inodes end up on
two different BDI lists and thus they wouldn't be synced properly. Trond,
do I read the code properly?
Also we definitely need to set *some* bdi in nfs_get_sb as otherwise sync
won't work for it.

Honza
> ---
> fs/btrfs/disk-io.c | 1 +
> fs/fuse/inode.c | 2 ++
> fs/super.c | 6 ++++++
> fs/sync.c | 9 ++++++++-
> fs/ubifs/super.c | 1 +
> include/linux/fs.h | 1 +
> 6 files changed, 19 insertions(+), 1 deletions(-)
>
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 15831d5..8b81927 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -1600,6 +1600,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
>
> sb->s_blocksize = 4096;
> sb->s_blocksize_bits = blksize_bits(4096);
> + sb->s_bdi = &fs_info->bdi;
>
> /*
> * we set the i_size on the btree inode to the max possible int.
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 4567db6..e5dbecd 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -894,6 +894,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
> if (err)
> goto err_put_conn;
>
> + sb->s_bdi = &fc->bdi;
> +
> /* Handle umasking inside the fuse code */
> if (sb->s_flags & MS_POSIXACL)
> fc->dont_mask = 1;
> diff --git a/fs/super.c b/fs/super.c
> index 9cda337..b03fea8 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -707,6 +707,12 @@ static int set_bdev_super(struct super_block *s, void *data)
> {
> s->s_bdev = data;
> s->s_dev = s->s_bdev->bd_dev;
> +
> + /*
> + * We set the bdi here to the queue backing, file systems can
> + * overwrite this in ->fill_super()
> + */
> + s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info;
> return 0;
> }
>
> diff --git a/fs/sync.c b/fs/sync.c
> index 103cc7f..8582c34 100644
> --- a/fs/sync.c
> +++ b/fs/sync.c
> @@ -27,6 +27,13 @@
> */
> static int __sync_filesystem(struct super_block *sb, int wait)
> {
> + /*
> + * This should be safe, as we require bdi backing to actually
> + * write out data in the first place
> + */
> + if (!sb->s_bdi)
> + return 0;
> +
> /* Avoid doing twice syncing and cache pruning for quota sync */
> if (!wait) {
> writeout_quota_sb(sb, -1);
> @@ -101,7 +108,7 @@ restart:
> spin_unlock(&sb_lock);
>
> down_read(&sb->s_umount);
> - if (!(sb->s_flags & MS_RDONLY) && sb->s_root)
> + if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
> __sync_filesystem(sb, wait);
> up_read(&sb->s_umount);
>
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index 51763aa..c4af069 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -1980,6 +1980,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
> if (err)
> goto out_bdi;
>
> + sb->s_bdi = &c->bdi;
> sb->s_fs_info = c;
> sb->s_magic = UBIFS_SUPER_MAGIC;
> sb->s_blocksize = UBIFS_BLOCK_SIZE;
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index a79f483..f998adc 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1343,6 +1343,7 @@ struct super_block {
> int s_nr_dentry_unused; /* # of dentry on lru */
>
> struct block_device *s_bdev;
> + struct backing_dev_info *s_bdi;
> struct mtd_info *s_mtd;
> struct list_head s_instances;
> struct quota_info s_dquot; /* Diskquota specific options */
> --
> 1.6.4.1.207.g68ea
>
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR