fs: Provide infrastructure for dynamic BDIs in filesystems
Provide helper functions for setting up dynamically allocated backing_dev_info structures for filesystems and cleaning them up on superblock destruction. CC: linux-mtd@lists.infradead.org CC: linux-nfs@vger.kernel.org CC: Petr Vandrovec <petr@vandrovec.name> CC: linux-nilfs@vger.kernel.org CC: cluster-devel@redhat.com CC: osd-dev@open-osd.org CC: codalist@coda.cs.cmu.edu CC: linux-afs@lists.infradead.org CC: ecryptfs@vger.kernel.org CC: linux-cifs@vger.kernel.org CC: ceph-devel@vger.kernel.org CC: linux-btrfs@vger.kernel.org CC: v9fs-developer@lists.sourceforge.net CC: lustre-devel@lists.lustre.org Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
62bf42adc4
commit
fca39346a5
3 changed files with 56 additions and 1 deletions
49
fs/super.c
49
fs/super.c
|
@ -446,6 +446,11 @@ void generic_shutdown_super(struct super_block *sb)
|
||||||
hlist_del_init(&sb->s_instances);
|
hlist_del_init(&sb->s_instances);
|
||||||
spin_unlock(&sb_lock);
|
spin_unlock(&sb_lock);
|
||||||
up_write(&sb->s_umount);
|
up_write(&sb->s_umount);
|
||||||
|
if (sb->s_iflags & SB_I_DYNBDI) {
|
||||||
|
bdi_put(sb->s_bdi);
|
||||||
|
sb->s_bdi = &noop_backing_dev_info;
|
||||||
|
sb->s_iflags &= ~SB_I_DYNBDI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(generic_shutdown_super);
|
EXPORT_SYMBOL(generic_shutdown_super);
|
||||||
|
@ -1255,6 +1260,50 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup private BDI for given superblock. It gets automatically cleaned up
|
||||||
|
* in generic_shutdown_super().
|
||||||
|
*/
|
||||||
|
int super_setup_bdi_name(struct super_block *sb, char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct backing_dev_info *bdi;
|
||||||
|
int err;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
bdi = bdi_alloc(GFP_KERNEL);
|
||||||
|
if (!bdi)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
bdi->name = sb->s_type->name;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
err = bdi_register_va(bdi, NULL, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
if (err) {
|
||||||
|
bdi_put(bdi);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
WARN_ON(sb->s_bdi != &noop_backing_dev_info);
|
||||||
|
sb->s_bdi = bdi;
|
||||||
|
sb->s_iflags |= SB_I_DYNBDI;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(super_setup_bdi_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup private BDI for given superblock. I gets automatically cleaned up
|
||||||
|
* in generic_shutdown_super().
|
||||||
|
*/
|
||||||
|
int super_setup_bdi(struct super_block *sb)
|
||||||
|
{
|
||||||
|
static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
|
||||||
|
|
||||||
|
return super_setup_bdi_name(sb, "%.28s-%ld", sb->s_type->name,
|
||||||
|
atomic_long_inc_return(&bdi_seq));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(super_setup_bdi);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an internal function, please use sb_end_{write,pagefault,intwrite}
|
* This is an internal function, please use sb_end_{write,pagefault,intwrite}
|
||||||
* instead.
|
* instead.
|
||||||
|
|
|
@ -146,7 +146,7 @@ struct backing_dev_info {
|
||||||
congested_fn *congested_fn; /* Function pointer if device is md/dm */
|
congested_fn *congested_fn; /* Function pointer if device is md/dm */
|
||||||
void *congested_data; /* Pointer to aux data for congested func */
|
void *congested_data; /* Pointer to aux data for congested func */
|
||||||
|
|
||||||
char *name;
|
const char *name;
|
||||||
|
|
||||||
struct kref refcnt; /* Reference counter for the structure */
|
struct kref refcnt; /* Reference counter for the structure */
|
||||||
unsigned int capabilities; /* Device capabilities */
|
unsigned int capabilities; /* Device capabilities */
|
||||||
|
|
|
@ -1272,6 +1272,9 @@ struct mm_struct;
|
||||||
/* sb->s_iflags to limit user namespace mounts */
|
/* sb->s_iflags to limit user namespace mounts */
|
||||||
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
|
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
|
||||||
|
|
||||||
|
/* Temporary flag until all filesystems are converted to dynamic bdis */
|
||||||
|
#define SB_I_DYNBDI 0x00000100
|
||||||
|
|
||||||
/* Possible states of 'frozen' field */
|
/* Possible states of 'frozen' field */
|
||||||
enum {
|
enum {
|
||||||
SB_UNFROZEN = 0, /* FS is unfrozen */
|
SB_UNFROZEN = 0, /* FS is unfrozen */
|
||||||
|
@ -2121,6 +2124,9 @@ extern int vfs_ustat(dev_t, struct kstatfs *);
|
||||||
extern int freeze_super(struct super_block *super);
|
extern int freeze_super(struct super_block *super);
|
||||||
extern int thaw_super(struct super_block *super);
|
extern int thaw_super(struct super_block *super);
|
||||||
extern bool our_mnt(struct vfsmount *mnt);
|
extern bool our_mnt(struct vfsmount *mnt);
|
||||||
|
extern __printf(2, 3)
|
||||||
|
int super_setup_bdi_name(struct super_block *sb, char *fmt, ...);
|
||||||
|
extern int super_setup_bdi(struct super_block *sb);
|
||||||
|
|
||||||
extern int current_umask(void);
|
extern int current_umask(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue