diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-14 10:10:53 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-14 10:10:53 -0700 |
commit | 9fc0178caa30070f65bded433f91756491a3cf26 (patch) | |
tree | 0100c8f5a4b7a18450765f529e946d22164c5e49 /fs | |
parent | 2b6b6d385d2933c105e27f2d25fdb36d392d7f59 (diff) | |
parent | c85399c2da8b86de8f6877980294fa1a4a88a5a4 (diff) | |
download | linux-3.10-9fc0178caa30070f65bded433f91756491a3cf26.tar.gz linux-3.10-9fc0178caa30070f65bded433f91756491a3cf26.tar.bz2 linux-3.10-9fc0178caa30070f65bded433f91756491a3cf26.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2:
nilfs2: fix possible mismatch of sufile counters on recovery
nilfs2: segment usage file cleanups
nilfs2: fix wrong accounting and duplicate brelse in nilfs_sufile_set_error
nilfs2: simplify handling of active state of segments fix
nilfs2: remove module version
nilfs2: fix lockdep recursive locking warning on meta data files
nilfs2: fix lockdep recursive locking warning on bmap
nilfs2: return f_fsid for statfs2
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nilfs2/bmap.c | 5 | ||||
-rw-r--r-- | fs/nilfs2/nilfs.h | 5 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 20 | ||||
-rw-r--r-- | fs/nilfs2/sufile.c | 290 | ||||
-rw-r--r-- | fs/nilfs2/sufile.h | 79 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 7 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 4 |
7 files changed, 197 insertions, 213 deletions
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 24638e059bf..064279e33bb 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -688,6 +688,8 @@ static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_gc = { .bpop_translate = NULL, }; +static struct lock_class_key nilfs_bmap_dat_lock_key; + /** * nilfs_bmap_read - read a bmap from an inode * @bmap: bmap @@ -715,6 +717,7 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) bmap->b_pops = &nilfs_bmap_ptr_ops_p; bmap->b_last_allocated_key = 0; /* XXX: use macro */ bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT; + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); break; case NILFS_CPFILE_INO: case NILFS_SUFILE_INO: @@ -772,6 +775,7 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) { memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union)); init_rwsem(&gcbmap->b_sem); + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; } @@ -779,5 +783,6 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) { memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union)); init_rwsem(&bmap->b_sem); + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; } diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 7558c977db0..3d0c18a16db 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -35,11 +35,6 @@ #include "bmap_union.h" /* - * NILFS filesystem version - */ -#define NILFS_VERSION "2.0.5" - -/* * nilfs inode data in memory */ struct nilfs_inode_info { diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 6ade0963fc1..4fc081e47d7 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -413,7 +413,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, struct nilfs_segment_entry *ent, *n; struct inode *sufile = nilfs->ns_sufile; __u64 segnum[4]; - time_t mtime; int err; int i; @@ -442,24 +441,13 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, * Collecting segments written after the latest super root. * These are marked dirty to avoid being reallocated in the next write. */ - mtime = get_seconds(); list_for_each_entry_safe(ent, n, head, list) { - if (ent->segnum == segnum[0]) { - list_del(&ent->list); - nilfs_free_segment_entry(ent); - continue; - } - err = nilfs_open_segment_entry(ent, sufile); - if (unlikely(err)) - goto failed; - if (!nilfs_segment_usage_dirty(ent->raw_su)) { - /* make the segment garbage */ - ent->raw_su->su_nblocks = cpu_to_le32(0); - ent->raw_su->su_lastmod = cpu_to_le32(mtime); - nilfs_segment_usage_set_dirty(ent->raw_su); + if (ent->segnum != segnum[0]) { + err = nilfs_sufile_scrap(sufile, ent->segnum); + if (unlikely(err)) + goto failed; } list_del(&ent->list); - nilfs_close_segment_entry(ent, sufile); nilfs_free_segment_entry(ent); } diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index c774cf397e2..98e68677f04 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c @@ -93,6 +93,52 @@ nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum, create, NULL, bhp); } +static void nilfs_sufile_mod_counter(struct buffer_head *header_bh, + u64 ncleanadd, u64 ndirtyadd) +{ + struct nilfs_sufile_header *header; + void *kaddr; + + kaddr = kmap_atomic(header_bh->b_page, KM_USER0); + header = kaddr + bh_offset(header_bh); + le64_add_cpu(&header->sh_ncleansegs, ncleanadd); + le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd); + kunmap_atomic(kaddr, KM_USER0); + + nilfs_mdt_mark_buffer_dirty(header_bh); +} + +int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create, + void (*dofunc)(struct inode *, __u64, + struct buffer_head *, + struct buffer_head *)) +{ + struct buffer_head *header_bh, *bh; + int ret; + + if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) { + printk(KERN_WARNING "%s: invalid segment number: %llu\n", + __func__, (unsigned long long)segnum); + return -EINVAL; + } + down_write(&NILFS_MDT(sufile)->mi_sem); + + ret = nilfs_sufile_get_header_block(sufile, &header_bh); + if (ret < 0) + goto out_sem; + + ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, create, &bh); + if (!ret) { + dofunc(sufile, segnum, header_bh, bh); + brelse(bh); + } + brelse(header_bh); + + out_sem: + up_write(&NILFS_MDT(sufile)->mi_sem); + return ret; +} + /** * nilfs_sufile_alloc - allocate a segment * @sufile: inode of segment usage file @@ -113,7 +159,6 @@ nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum, int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) { struct buffer_head *header_bh, *su_bh; - struct the_nilfs *nilfs; struct nilfs_sufile_header *header; struct nilfs_segment_usage *su; size_t susz = NILFS_MDT(sufile)->mi_entry_size; @@ -124,8 +169,6 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) down_write(&NILFS_MDT(sufile)->mi_sem); - nilfs = NILFS_MDT(sufile)->mi_nilfs; - ret = nilfs_sufile_get_header_block(sufile, &header_bh); if (ret < 0) goto out_sem; @@ -192,165 +235,84 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) return ret; } -/** - * nilfs_sufile_cancel_free - - * @sufile: inode of segment usage file - * @segnum: segment number - * - * Description: - * - * Return Value: On success, 0 is returned. On error, one of the following - * negative error codes is returned. - * - * %-EIO - I/O error. - * - * %-ENOMEM - Insufficient amount of memory available. - */ -int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum) +void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, + struct buffer_head *header_bh, + struct buffer_head *su_bh) { - struct buffer_head *header_bh, *su_bh; - struct the_nilfs *nilfs; - struct nilfs_sufile_header *header; struct nilfs_segment_usage *su; void *kaddr; - int ret; - - down_write(&NILFS_MDT(sufile)->mi_sem); - - nilfs = NILFS_MDT(sufile)->mi_nilfs; - - ret = nilfs_sufile_get_header_block(sufile, &header_bh); - if (ret < 0) - goto out_sem; - - ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &su_bh); - if (ret < 0) - goto out_header; kaddr = kmap_atomic(su_bh->b_page, KM_USER0); - su = nilfs_sufile_block_get_segment_usage( - sufile, segnum, su_bh, kaddr); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); if (unlikely(!nilfs_segment_usage_clean(su))) { printk(KERN_WARNING "%s: segment %llu must be clean\n", __func__, (unsigned long long)segnum); kunmap_atomic(kaddr, KM_USER0); - goto out_su_bh; + return; } nilfs_segment_usage_set_dirty(su); kunmap_atomic(kaddr, KM_USER0); - kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr); - le64_add_cpu(&header->sh_ncleansegs, -1); - le64_add_cpu(&header->sh_ndirtysegs, 1); - kunmap_atomic(kaddr, KM_USER0); - - nilfs_mdt_mark_buffer_dirty(header_bh); + nilfs_sufile_mod_counter(header_bh, -1, 1); nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); - - out_su_bh: - brelse(su_bh); - out_header: - brelse(header_bh); - out_sem: - up_write(&NILFS_MDT(sufile)->mi_sem); - return ret; } -/** - * nilfs_sufile_freev - free segments - * @sufile: inode of segment usage file - * @segnum: array of segment numbers - * @nsegs: number of segments - * - * Description: nilfs_sufile_freev() frees segments specified by @segnum and - * @nsegs, which must have been returned by a previous call to - * nilfs_sufile_alloc(). - * - * Return Value: On success, 0 is returned. On error, one of the following - * negative error codes is returned. - * - * %-EIO - I/O error. - * - * %-ENOMEM - Insufficient amount of memory available. - */ -#define NILFS_SUFILE_FREEV_PREALLOC 16 -int nilfs_sufile_freev(struct inode *sufile, __u64 *segnum, size_t nsegs) +void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum, + struct buffer_head *header_bh, + struct buffer_head *su_bh) { - struct buffer_head *header_bh, **su_bh, - *su_bh_prealloc[NILFS_SUFILE_FREEV_PREALLOC]; - struct the_nilfs *nilfs; - struct nilfs_sufile_header *header; struct nilfs_segment_usage *su; void *kaddr; - int ret, i; + int clean, dirty; - down_write(&NILFS_MDT(sufile)->mi_sem); - - nilfs = NILFS_MDT(sufile)->mi_nilfs; - - /* prepare resources */ - if (nsegs <= NILFS_SUFILE_FREEV_PREALLOC) - su_bh = su_bh_prealloc; - else { - su_bh = kmalloc(sizeof(*su_bh) * nsegs, GFP_NOFS); - if (su_bh == NULL) { - ret = -ENOMEM; - goto out_sem; - } - } - - ret = nilfs_sufile_get_header_block(sufile, &header_bh); - if (ret < 0) - goto out_su_bh; - for (i = 0; i < nsegs; i++) { - ret = nilfs_sufile_get_segment_usage_block(sufile, segnum[i], - 0, &su_bh[i]); - if (ret < 0) - goto out_bh; - } - - /* free segments */ - for (i = 0; i < nsegs; i++) { - kaddr = kmap_atomic(su_bh[i]->b_page, KM_USER0); - su = nilfs_sufile_block_get_segment_usage( - sufile, segnum[i], su_bh[i], kaddr); - WARN_ON(nilfs_segment_usage_error(su)); - nilfs_segment_usage_set_clean(su); + kaddr = kmap_atomic(su_bh->b_page, KM_USER0); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); + if (su->su_flags == cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY) && + su->su_nblocks == cpu_to_le32(0)) { kunmap_atomic(kaddr, KM_USER0); - nilfs_mdt_mark_buffer_dirty(su_bh[i]); + return; } - kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr); - le64_add_cpu(&header->sh_ncleansegs, nsegs); - le64_add_cpu(&header->sh_ndirtysegs, -(u64)nsegs); + clean = nilfs_segment_usage_clean(su); + dirty = nilfs_segment_usage_dirty(su); + + /* make the segment garbage */ + su->su_lastmod = cpu_to_le64(0); + su->su_nblocks = cpu_to_le32(0); + su->su_flags = cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY); kunmap_atomic(kaddr, KM_USER0); - nilfs_mdt_mark_buffer_dirty(header_bh); + + nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1); + nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); +} - out_bh: - for (i--; i >= 0; i--) - brelse(su_bh[i]); - brelse(header_bh); +void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, + struct buffer_head *header_bh, + struct buffer_head *su_bh) +{ + struct nilfs_segment_usage *su; + void *kaddr; + int sudirty; - out_su_bh: - if (su_bh != su_bh_prealloc) - kfree(su_bh); + kaddr = kmap_atomic(su_bh->b_page, KM_USER0); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); + if (nilfs_segment_usage_clean(su)) { + printk(KERN_WARNING "%s: segment %llu is already clean\n", + __func__, (unsigned long long)segnum); + kunmap_atomic(kaddr, KM_USER0); + return; + } + WARN_ON(nilfs_segment_usage_error(su)); + WARN_ON(!nilfs_segment_usage_dirty(su)); - out_sem: - up_write(&NILFS_MDT(sufile)->mi_sem); - return ret; -} + sudirty = nilfs_segment_usage_dirty(su); + nilfs_segment_usage_set_clean(su); + kunmap_atomic(kaddr, KM_USER0); + nilfs_mdt_mark_buffer_dirty(su_bh); -/** - * nilfs_sufile_free - - * @sufile: - * @segnum: - */ -int nilfs_sufile_free(struct inode *sufile, __u64 segnum) -{ - return nilfs_sufile_freev(sufile, &segnum, 1); + nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0); + nilfs_mdt_mark_dirty(sufile); } /** @@ -500,72 +462,28 @@ int nilfs_sufile_get_ncleansegs(struct inode *sufile, unsigned long *nsegsp) return ret; } -/** - * nilfs_sufile_set_error - mark a segment as erroneous - * @sufile: inode of segment usage file - * @segnum: segment number - * - * Description: nilfs_sufile_set_error() marks the segment specified by - * @segnum as erroneous. The error segment will never be used again. - * - * Return Value: On success, 0 is returned. On error, one of the following - * negative error codes is returned. - * - * %-EIO - I/O error. - * - * %-ENOMEM - Insufficient amount of memory available. - * - * %-EINVAL - Invalid segment usage number. - */ -int nilfs_sufile_set_error(struct inode *sufile, __u64 segnum) +void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, + struct buffer_head *header_bh, + struct buffer_head *su_bh) { - struct buffer_head *header_bh, *su_bh; struct nilfs_segment_usage *su; - struct nilfs_sufile_header *header; void *kaddr; - int ret; - - if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) { - printk(KERN_WARNING "%s: invalid segment number: %llu\n", - __func__, (unsigned long long)segnum); - return -EINVAL; - } - down_write(&NILFS_MDT(sufile)->mi_sem); - - ret = nilfs_sufile_get_header_block(sufile, &header_bh); - if (ret < 0) - goto out_sem; - ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &su_bh); - if (ret < 0) - goto out_header; + int suclean; kaddr = kmap_atomic(su_bh->b_page, KM_USER0); su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); if (nilfs_segment_usage_error(su)) { kunmap_atomic(kaddr, KM_USER0); - brelse(su_bh); - goto out_header; + return; } - + suclean = nilfs_segment_usage_clean(su); nilfs_segment_usage_set_error(su); kunmap_atomic(kaddr, KM_USER0); - brelse(su_bh); - kaddr = kmap_atomic(header_bh->b_page, KM_USER0); - header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr); - le64_add_cpu(&header->sh_ndirtysegs, -1); - kunmap_atomic(kaddr, KM_USER0); - nilfs_mdt_mark_buffer_dirty(header_bh); + if (suclean) + nilfs_sufile_mod_counter(header_bh, -1, 0); nilfs_mdt_mark_buffer_dirty(su_bh); nilfs_mdt_mark_dirty(sufile); - brelse(su_bh); - - out_header: - brelse(header_bh); - - out_sem: - up_write(&NILFS_MDT(sufile)->mi_sem); - return ret; } /** @@ -625,7 +543,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, si[i + j].sui_nblocks = le32_to_cpu(su->su_nblocks); si[i + j].sui_flags = le32_to_cpu(su->su_flags) & ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); - if (nilfs_segment_is_active(nilfs, segnum + i + j)) + if (nilfs_segment_is_active(nilfs, segnum + j)) si[i + j].sui_flags |= (1UL << NILFS_SEGMENT_USAGE_ACTIVE); } diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index d595f33a768..a2e2efd4ade 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h @@ -36,9 +36,6 @@ static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) } int nilfs_sufile_alloc(struct inode *, __u64 *); -int nilfs_sufile_cancel_free(struct inode *, __u64); -int nilfs_sufile_freev(struct inode *, __u64 *, size_t); -int nilfs_sufile_free(struct inode *, __u64); int nilfs_sufile_get_segment_usage(struct inode *, __u64, struct nilfs_segment_usage **, struct buffer_head **); @@ -46,9 +43,83 @@ void nilfs_sufile_put_segment_usage(struct inode *, __u64, struct buffer_head *); int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *); int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *); -int nilfs_sufile_set_error(struct inode *, __u64); ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, struct nilfs_suinfo *, size_t); +int nilfs_sufile_update(struct inode *, __u64, int, + void (*dofunc)(struct inode *, __u64, + struct buffer_head *, + struct buffer_head *)); +void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *, + struct buffer_head *); +void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *, + struct buffer_head *); +void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *, + struct buffer_head *); +void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, + struct buffer_head *); + +/** + * nilfs_sufile_cancel_free - + * @sufile: inode of segment usage file + * @segnum: segment number + * + * Description: + * + * Return Value: On success, 0 is returned. On error, one of the following + * negative error codes is returned. + * + * %-EIO - I/O error. + * + * %-ENOMEM - Insufficient amount of memory available. + */ +static inline int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum) +{ + return nilfs_sufile_update(sufile, segnum, 0, + nilfs_sufile_do_cancel_free); +} + +/** + * nilfs_sufile_scrap - make a segment garbage + * @sufile: inode of segment usage file + * @segnum: segment number to be freed + */ +static inline int nilfs_sufile_scrap(struct inode *sufile, __u64 segnum) +{ + return nilfs_sufile_update(sufile, segnum, 1, nilfs_sufile_do_scrap); +} + +/** + * nilfs_sufile_free - free segment + * @sufile: inode of segment usage file + * @segnum: segment number to be freed + */ +static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum) +{ + return nilfs_sufile_update(sufile, segnum, 0, nilfs_sufile_do_free); +} + +/** + * nilfs_sufile_set_error - mark a segment as erroneous + * @sufile: inode of segment usage file + * @segnum: segment number + * + * Description: nilfs_sufile_set_error() marks the segment specified by + * @segnum as erroneous. The error segment will never be used again. + * + * Return Value: On success, 0 is returned. On error, one of the following + * negative error codes is returned. + * + * %-EIO - I/O error. + * + * %-ENOMEM - Insufficient amount of memory available. + * + * %-EINVAL - Invalid segment usage number. + */ +static inline int nilfs_sufile_set_error(struct inode *sufile, __u64 segnum) +{ + return nilfs_sufile_update(sufile, segnum, 0, + nilfs_sufile_do_set_error); +} #endif /* _NILFS_SUFILE_H */ diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index e117e1ea9bf..6989b03e97a 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -63,7 +63,6 @@ MODULE_AUTHOR("NTT Corp."); MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " "(NILFS)"); -MODULE_VERSION(NILFS_VERSION); MODULE_LICENSE("GPL"); static int nilfs_remount(struct super_block *sb, int *flags, char *data); @@ -476,11 +475,12 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = sbi->s_nilfs; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); unsigned long long blocks; unsigned long overhead; unsigned long nrsvblocks; sector_t nfreeblocks; - struct the_nilfs *nilfs = sbi->s_nilfs; int err; /* @@ -514,6 +514,9 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = atomic_read(&sbi->s_inodes_count); buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ buf->f_namelen = NILFS_NAME_LEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + return 0; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 33400cf0bbe..7f65b3be4aa 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -115,6 +115,7 @@ void put_nilfs(struct the_nilfs *nilfs) static int nilfs_load_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, sector_t sr_block) { + static struct lock_class_key dat_lock_key; struct buffer_head *bh_sr; struct nilfs_super_root *raw_sr; struct nilfs_super_block **sbp = nilfs->ns_sbp; @@ -163,6 +164,9 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, if (unlikely(err)) goto failed_sufile; + lockdep_set_class(&NILFS_MDT(nilfs->ns_dat)->mi_sem, &dat_lock_key); + lockdep_set_class(&NILFS_MDT(nilfs->ns_gc_dat)->mi_sem, &dat_lock_key); + nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); nilfs_mdt_set_entry_size(nilfs->ns_cpfile, checkpoint_size, sizeof(struct nilfs_cpfile_header)); |