Commit f11459ad authored by Ryusuke Konishi's avatar Ryusuke Konishi

nilfs2: do not allocate multiple super block instances for a device

This stops allocating multiple super block instances for a device.

All snapshots and a current mode mount (i.e. latest tree) will be
controlled with nilfs_root objects that are kept within an sb
instance.

nilfs_get_sb() is rewritten so that it always has a root object for
the latest tree and snapshots make additional root objects.

The root dentry of the latest tree is binded to sb->s_root even if it
isn't attached on a directory.  Root dentries of snapshots or the
latest tree are binded to mnt->mnt_root on which they are mounted.

With this patch, nilfs_find_sbinfo() function, nilfs->ns_supers list,
and nilfs->ns_current back pointer, are deleted.  In addition,
init_nilfs() and load_nilfs() are simplified since they will be called
once for a device, not repeatedly called for mount points.
Signed-off-by: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
parent ab4d8f7e
...@@ -42,9 +42,6 @@ struct nilfs_sc_info; ...@@ -42,9 +42,6 @@ struct nilfs_sc_info;
* NILFS super-block data in memory * NILFS super-block data in memory
*/ */
struct nilfs_sb_info { struct nilfs_sb_info {
/* Snapshot status */
__u64 s_snapshot_cno; /* Checkpoint number */
/* Mount options */ /* Mount options */
unsigned long s_mount_opt; unsigned long s_mount_opt;
uid_t s_resuid; uid_t s_resuid;
...@@ -57,8 +54,6 @@ struct nilfs_sb_info { ...@@ -57,8 +54,6 @@ struct nilfs_sb_info {
/* Fundamental members */ /* Fundamental members */
struct super_block *s_super; /* reverse pointer to super_block */ struct super_block *s_super; /* reverse pointer to super_block */
struct the_nilfs *s_nilfs; struct the_nilfs *s_nilfs;
struct list_head s_list; /* list head for nilfs->ns_supers */
atomic_t s_count; /* reference count */
/* Segment constructor */ /* Segment constructor */
struct list_head s_dirty_files; /* dirty files list */ struct list_head s_dirty_files; /* dirty files list */
......
This diff is collapsed.
...@@ -82,11 +82,9 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev) ...@@ -82,11 +82,9 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
atomic_set(&nilfs->ns_count, 1); atomic_set(&nilfs->ns_count, 1);
atomic_set(&nilfs->ns_ndirtyblks, 0); atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem); init_rwsem(&nilfs->ns_sem);
init_rwsem(&nilfs->ns_super_sem);
mutex_init(&nilfs->ns_mount_mutex); mutex_init(&nilfs->ns_mount_mutex);
init_rwsem(&nilfs->ns_writer_sem); init_rwsem(&nilfs->ns_writer_sem);
INIT_LIST_HEAD(&nilfs->ns_list); INIT_LIST_HEAD(&nilfs->ns_list);
INIT_LIST_HEAD(&nilfs->ns_supers);
INIT_LIST_HEAD(&nilfs->ns_gc_inodes); INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
spin_lock_init(&nilfs->ns_last_segment_lock); spin_lock_init(&nilfs->ns_last_segment_lock);
nilfs->ns_cptree = RB_ROOT; nilfs->ns_cptree = RB_ROOT;
...@@ -307,15 +305,6 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -307,15 +305,6 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
int valid_fs = nilfs_valid_fs(nilfs); int valid_fs = nilfs_valid_fs(nilfs);
int err; int err;
if (nilfs_loaded(nilfs)) {
if (valid_fs ||
((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY)))
return 0;
printk(KERN_ERR "NILFS: the filesystem is in an incomplete "
"recovery state.\n");
return -EINVAL;
}
if (!valid_fs) { if (!valid_fs) {
printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n");
if (s_flags & MS_RDONLY) { if (s_flags & MS_RDONLY) {
...@@ -632,12 +621,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, ...@@ -632,12 +621,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
* *
* init_nilfs() performs common initialization per block device (e.g. * init_nilfs() performs common initialization per block device (e.g.
* reading the super block, getting disk layout information, initializing * reading the super block, getting disk layout information, initializing
* shared fields in the_nilfs). It takes on some portion of the jobs * shared fields in the_nilfs).
* typically done by a fill_super() routine. This division arises from
* the nature that multiple NILFS instances may be simultaneously
* mounted on a device.
* For multiple mounts on the same device, only the first mount
* invokes these tasks.
* *
* Return Value: On success, 0 is returned. On error, a negative error * Return Value: On success, 0 is returned. On error, a negative error
* code is returned. * code is returned.
...@@ -651,27 +635,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) ...@@ -651,27 +635,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
int err; int err;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
if (nilfs_init(nilfs)) {
/* Load values from existing the_nilfs */
sbp = nilfs->ns_sbp[0];
err = nilfs_store_magic_and_option(sb, sbp, data);
if (err)
goto out;
err = nilfs_check_feature_compatibility(sb, sbp);
if (err)
goto out;
blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
if (sb->s_blocksize != blocksize &&
!sb_set_blocksize(sb, blocksize)) {
printk(KERN_ERR "NILFS: blocksize %d unfit to device\n",
blocksize);
err = -EINVAL;
}
sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits);
goto out;
}
blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE);
if (!blocksize) { if (!blocksize) {
...@@ -901,56 +864,6 @@ void nilfs_put_root(struct nilfs_root *root) ...@@ -901,56 +864,6 @@ void nilfs_put_root(struct nilfs_root *root)
} }
} }
/**
* nilfs_find_sbinfo - find existing nilfs_sb_info structure
* @nilfs: nilfs object
* @rw_mount: mount type (non-zero value for read/write mount)
* @cno: checkpoint number (zero for read-only mount)
*
* nilfs_find_sbinfo() returns the nilfs_sb_info structure which
* @rw_mount and @cno (in case of snapshots) matched. If no instance
* was found, NULL is returned. Although the super block instance can
* be unmounted after this function returns, the nilfs_sb_info struct
* is kept on memory until nilfs_put_sbinfo() is called.
*/
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs,
int rw_mount, __u64 cno)
{
struct nilfs_sb_info *sbi;
down_read(&nilfs->ns_super_sem);
/*
* The SNAPSHOT flag and sb->s_flags are supposed to be
* protected with nilfs->ns_super_sem.
*/
sbi = nilfs->ns_current;
if (rw_mount) {
if (sbi && !(sbi->s_super->s_flags & MS_RDONLY))
goto found; /* read/write mount */
else
goto out;
} else if (cno == 0) {
if (sbi && (sbi->s_super->s_flags & MS_RDONLY))
goto found; /* read-only mount */
else
goto out;
}
list_for_each_entry(sbi, &nilfs->ns_supers, s_list) {
if (nilfs_test_opt(sbi, SNAPSHOT) &&
sbi->s_snapshot_cno == cno)
goto found; /* snapshot mount */
}
out:
up_read(&nilfs->ns_super_sem);
return NULL;
found:
atomic_inc(&sbi->s_count);
up_read(&nilfs->ns_super_sem);
return sbi;
}
int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno, int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
int snapshot_mount) int snapshot_mount)
{ {
......
...@@ -52,16 +52,13 @@ enum { ...@@ -52,16 +52,13 @@ enum {
* @ns_bdi: backing dev info * @ns_bdi: backing dev info
* @ns_writer: back pointer to writable nilfs_sb_info * @ns_writer: back pointer to writable nilfs_sb_info
* @ns_sem: semaphore for shared states * @ns_sem: semaphore for shared states
* @ns_super_sem: semaphore for global operations across super block instances
* @ns_mount_mutex: mutex protecting mount process of nilfs * @ns_mount_mutex: mutex protecting mount process of nilfs
* @ns_writer_sem: semaphore protecting ns_writer attach/detach * @ns_writer_sem: semaphore protecting ns_writer attach/detach
* @ns_current: back pointer to current mount
* @ns_sbh: buffer heads of on-disk super blocks * @ns_sbh: buffer heads of on-disk super blocks
* @ns_sbp: pointers to super block data * @ns_sbp: pointers to super block data
* @ns_sbwtime: previous write time of super block * @ns_sbwtime: previous write time of super block
* @ns_sbwcount: write count of super block * @ns_sbwcount: write count of super block
* @ns_sbsize: size of valid data in super block * @ns_sbsize: size of valid data in super block
* @ns_supers: list of nilfs super block structs
* @ns_seg_seq: segment sequence counter * @ns_seg_seq: segment sequence counter
* @ns_segnum: index number of the latest full segment. * @ns_segnum: index number of the latest full segment.
* @ns_nextnum: index number of the full segment index to be used next * @ns_nextnum: index number of the full segment index to be used next
...@@ -104,16 +101,9 @@ struct the_nilfs { ...@@ -104,16 +101,9 @@ struct the_nilfs {
struct backing_dev_info *ns_bdi; struct backing_dev_info *ns_bdi;
struct nilfs_sb_info *ns_writer; struct nilfs_sb_info *ns_writer;
struct rw_semaphore ns_sem; struct rw_semaphore ns_sem;
struct rw_semaphore ns_super_sem;
struct mutex ns_mount_mutex; struct mutex ns_mount_mutex;
struct rw_semaphore ns_writer_sem; struct rw_semaphore ns_writer_sem;
/*
* components protected by ns_super_sem
*/
struct nilfs_sb_info *ns_current;
struct list_head ns_supers;
/* /*
* used for * used for
* - loading the latest checkpoint exclusively. * - loading the latest checkpoint exclusively.
...@@ -294,12 +284,6 @@ nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -294,12 +284,6 @@ nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
up_write(&nilfs->ns_writer_sem); up_write(&nilfs->ns_writer_sem);
} }
static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
{
if (atomic_dec_and_test(&sbi->s_count))
kfree(sbi);
}
static inline int nilfs_valid_fs(struct the_nilfs *nilfs) static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
{ {
unsigned valid_fs; unsigned valid_fs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment