diff options
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r-- | fs/ocfs2/super.c | 92 |
1 files changed, 61 insertions, 31 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 79ff8d9d37e0..0d3ed7407a04 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/mount.h> | 42 | #include <linux/mount.h> |
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/quotaops.h> | 44 | #include <linux/quotaops.h> |
45 | #include <linux/smp_lock.h> | ||
45 | 46 | ||
46 | #define MLOG_MASK_PREFIX ML_SUPER | 47 | #define MLOG_MASK_PREFIX ML_SUPER |
47 | #include <cluster/masklog.h> | 48 | #include <cluster/masklog.h> |
@@ -118,15 +119,16 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb); | |||
118 | static int ocfs2_check_volume(struct ocfs2_super *osb); | 119 | static int ocfs2_check_volume(struct ocfs2_super *osb); |
119 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 120 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
120 | struct buffer_head *bh, | 121 | struct buffer_head *bh, |
121 | u32 sectsize); | 122 | u32 sectsize, |
123 | struct ocfs2_blockcheck_stats *stats); | ||
122 | static int ocfs2_initialize_super(struct super_block *sb, | 124 | static int ocfs2_initialize_super(struct super_block *sb, |
123 | struct buffer_head *bh, | 125 | struct buffer_head *bh, |
124 | int sector_size); | 126 | int sector_size, |
127 | struct ocfs2_blockcheck_stats *stats); | ||
125 | static int ocfs2_get_sector(struct super_block *sb, | 128 | static int ocfs2_get_sector(struct super_block *sb, |
126 | struct buffer_head **bh, | 129 | struct buffer_head **bh, |
127 | int block, | 130 | int block, |
128 | int sect_size); | 131 | int sect_size); |
129 | static void ocfs2_write_super(struct super_block *sb); | ||
130 | static struct inode *ocfs2_alloc_inode(struct super_block *sb); | 132 | static struct inode *ocfs2_alloc_inode(struct super_block *sb); |
131 | static void ocfs2_destroy_inode(struct inode *inode); | 133 | static void ocfs2_destroy_inode(struct inode *inode); |
132 | static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend); | 134 | static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend); |
@@ -141,7 +143,6 @@ static const struct super_operations ocfs2_sops = { | |||
141 | .clear_inode = ocfs2_clear_inode, | 143 | .clear_inode = ocfs2_clear_inode, |
142 | .delete_inode = ocfs2_delete_inode, | 144 | .delete_inode = ocfs2_delete_inode, |
143 | .sync_fs = ocfs2_sync_fs, | 145 | .sync_fs = ocfs2_sync_fs, |
144 | .write_super = ocfs2_write_super, | ||
145 | .put_super = ocfs2_put_super, | 146 | .put_super = ocfs2_put_super, |
146 | .remount_fs = ocfs2_remount, | 147 | .remount_fs = ocfs2_remount, |
147 | .show_options = ocfs2_show_options, | 148 | .show_options = ocfs2_show_options, |
@@ -208,6 +209,7 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) | |||
208 | int i; | 209 | int i; |
209 | struct ocfs2_cluster_connection *cconn = osb->cconn; | 210 | struct ocfs2_cluster_connection *cconn = osb->cconn; |
210 | struct ocfs2_recovery_map *rm = osb->recovery_map; | 211 | struct ocfs2_recovery_map *rm = osb->recovery_map; |
212 | struct ocfs2_orphan_scan *os; | ||
211 | 213 | ||
212 | out += snprintf(buf + out, len - out, | 214 | out += snprintf(buf + out, len - out, |
213 | "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", | 215 | "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", |
@@ -309,6 +311,13 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) | |||
309 | i, osb->slot_recovery_generations[i]); | 311 | i, osb->slot_recovery_generations[i]); |
310 | } | 312 | } |
311 | 313 | ||
314 | os = &osb->osb_orphan_scan; | ||
315 | out += snprintf(buf + out, len - out, "Orphan Scan=> "); | ||
316 | out += snprintf(buf + out, len - out, "Local: %u Global: %u ", | ||
317 | os->os_count, os->os_seqno); | ||
318 | out += snprintf(buf + out, len - out, " Last Scan: %lu seconds ago\n", | ||
319 | (get_seconds() - os->os_scantime.tv_sec)); | ||
320 | |||
312 | return out; | 321 | return out; |
313 | } | 322 | } |
314 | 323 | ||
@@ -365,24 +374,12 @@ static struct file_operations ocfs2_osb_debug_fops = { | |||
365 | .llseek = generic_file_llseek, | 374 | .llseek = generic_file_llseek, |
366 | }; | 375 | }; |
367 | 376 | ||
368 | /* | ||
369 | * write_super and sync_fs ripped right out of ext3. | ||
370 | */ | ||
371 | static void ocfs2_write_super(struct super_block *sb) | ||
372 | { | ||
373 | if (mutex_trylock(&sb->s_lock) != 0) | ||
374 | BUG(); | ||
375 | sb->s_dirt = 0; | ||
376 | } | ||
377 | |||
378 | static int ocfs2_sync_fs(struct super_block *sb, int wait) | 377 | static int ocfs2_sync_fs(struct super_block *sb, int wait) |
379 | { | 378 | { |
380 | int status; | 379 | int status; |
381 | tid_t target; | 380 | tid_t target; |
382 | struct ocfs2_super *osb = OCFS2_SB(sb); | 381 | struct ocfs2_super *osb = OCFS2_SB(sb); |
383 | 382 | ||
384 | sb->s_dirt = 0; | ||
385 | |||
386 | if (ocfs2_is_hard_readonly(osb)) | 383 | if (ocfs2_is_hard_readonly(osb)) |
387 | return -EROFS; | 384 | return -EROFS; |
388 | 385 | ||
@@ -555,7 +552,7 @@ static unsigned long long ocfs2_max_file_offset(unsigned int bbits, | |||
555 | */ | 552 | */ |
556 | 553 | ||
557 | #if BITS_PER_LONG == 32 | 554 | #if BITS_PER_LONG == 32 |
558 | # if defined(CONFIG_LBD) | 555 | # if defined(CONFIG_LBDAF) |
559 | BUILD_BUG_ON(sizeof(sector_t) != 8); | 556 | BUILD_BUG_ON(sizeof(sector_t) != 8); |
560 | /* | 557 | /* |
561 | * We might be limited by page cache size. | 558 | * We might be limited by page cache size. |
@@ -595,6 +592,8 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) | |||
595 | struct mount_options parsed_options; | 592 | struct mount_options parsed_options; |
596 | struct ocfs2_super *osb = OCFS2_SB(sb); | 593 | struct ocfs2_super *osb = OCFS2_SB(sb); |
597 | 594 | ||
595 | lock_kernel(); | ||
596 | |||
598 | if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) { | 597 | if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) { |
599 | ret = -EINVAL; | 598 | ret = -EINVAL; |
600 | goto out; | 599 | goto out; |
@@ -698,12 +697,14 @@ unlock_osb: | |||
698 | ocfs2_set_journal_params(osb); | 697 | ocfs2_set_journal_params(osb); |
699 | } | 698 | } |
700 | out: | 699 | out: |
700 | unlock_kernel(); | ||
701 | return ret; | 701 | return ret; |
702 | } | 702 | } |
703 | 703 | ||
704 | static int ocfs2_sb_probe(struct super_block *sb, | 704 | static int ocfs2_sb_probe(struct super_block *sb, |
705 | struct buffer_head **bh, | 705 | struct buffer_head **bh, |
706 | int *sector_size) | 706 | int *sector_size, |
707 | struct ocfs2_blockcheck_stats *stats) | ||
707 | { | 708 | { |
708 | int status, tmpstat; | 709 | int status, tmpstat; |
709 | struct ocfs1_vol_disk_hdr *hdr; | 710 | struct ocfs1_vol_disk_hdr *hdr; |
@@ -713,7 +714,7 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
713 | *bh = NULL; | 714 | *bh = NULL; |
714 | 715 | ||
715 | /* may be > 512 */ | 716 | /* may be > 512 */ |
716 | *sector_size = bdev_hardsect_size(sb->s_bdev); | 717 | *sector_size = bdev_logical_block_size(sb->s_bdev); |
717 | if (*sector_size > OCFS2_MAX_BLOCKSIZE) { | 718 | if (*sector_size > OCFS2_MAX_BLOCKSIZE) { |
718 | mlog(ML_ERROR, "Hardware sector size too large: %d (max=%d)\n", | 719 | mlog(ML_ERROR, "Hardware sector size too large: %d (max=%d)\n", |
719 | *sector_size, OCFS2_MAX_BLOCKSIZE); | 720 | *sector_size, OCFS2_MAX_BLOCKSIZE); |
@@ -769,7 +770,8 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
769 | goto bail; | 770 | goto bail; |
770 | } | 771 | } |
771 | di = (struct ocfs2_dinode *) (*bh)->b_data; | 772 | di = (struct ocfs2_dinode *) (*bh)->b_data; |
772 | status = ocfs2_verify_volume(di, *bh, blksize); | 773 | memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); |
774 | status = ocfs2_verify_volume(di, *bh, blksize, stats); | ||
773 | if (status >= 0) | 775 | if (status >= 0) |
774 | goto bail; | 776 | goto bail; |
775 | brelse(*bh); | 777 | brelse(*bh); |
@@ -975,6 +977,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
975 | struct ocfs2_super *osb = NULL; | 977 | struct ocfs2_super *osb = NULL; |
976 | struct buffer_head *bh = NULL; | 978 | struct buffer_head *bh = NULL; |
977 | char nodestr[8]; | 979 | char nodestr[8]; |
980 | struct ocfs2_blockcheck_stats stats; | ||
978 | 981 | ||
979 | mlog_entry("%p, %p, %i", sb, data, silent); | 982 | mlog_entry("%p, %p, %i", sb, data, silent); |
980 | 983 | ||
@@ -984,13 +987,13 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
984 | } | 987 | } |
985 | 988 | ||
986 | /* probe for superblock */ | 989 | /* probe for superblock */ |
987 | status = ocfs2_sb_probe(sb, &bh, §or_size); | 990 | status = ocfs2_sb_probe(sb, &bh, §or_size, &stats); |
988 | if (status < 0) { | 991 | if (status < 0) { |
989 | mlog(ML_ERROR, "superblock probe failed!\n"); | 992 | mlog(ML_ERROR, "superblock probe failed!\n"); |
990 | goto read_super_error; | 993 | goto read_super_error; |
991 | } | 994 | } |
992 | 995 | ||
993 | status = ocfs2_initialize_super(sb, bh, sector_size); | 996 | status = ocfs2_initialize_super(sb, bh, sector_size, &stats); |
994 | osb = OCFS2_SB(sb); | 997 | osb = OCFS2_SB(sb); |
995 | if (status < 0) { | 998 | if (status < 0) { |
996 | mlog_errno(status); | 999 | mlog_errno(status); |
@@ -1100,6 +1103,18 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
1100 | goto read_super_error; | 1103 | goto read_super_error; |
1101 | } | 1104 | } |
1102 | 1105 | ||
1106 | if (ocfs2_meta_ecc(osb)) { | ||
1107 | status = ocfs2_blockcheck_stats_debugfs_install( | ||
1108 | &osb->osb_ecc_stats, | ||
1109 | osb->osb_debug_root); | ||
1110 | if (status) { | ||
1111 | mlog(ML_ERROR, | ||
1112 | "Unable to create blockcheck statistics " | ||
1113 | "files\n"); | ||
1114 | goto read_super_error; | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1103 | status = ocfs2_mount_volume(sb); | 1118 | status = ocfs2_mount_volume(sb); |
1104 | if (osb->root_inode) | 1119 | if (osb->root_inode) |
1105 | inode = igrab(osb->root_inode); | 1120 | inode = igrab(osb->root_inode); |
@@ -1550,9 +1565,13 @@ static void ocfs2_put_super(struct super_block *sb) | |||
1550 | { | 1565 | { |
1551 | mlog_entry("(0x%p)\n", sb); | 1566 | mlog_entry("(0x%p)\n", sb); |
1552 | 1567 | ||
1568 | lock_kernel(); | ||
1569 | |||
1553 | ocfs2_sync_blockdev(sb); | 1570 | ocfs2_sync_blockdev(sb); |
1554 | ocfs2_dismount_volume(sb, 0); | 1571 | ocfs2_dismount_volume(sb, 0); |
1555 | 1572 | ||
1573 | unlock_kernel(); | ||
1574 | |||
1556 | mlog_exit_void(); | 1575 | mlog_exit_void(); |
1557 | } | 1576 | } |
1558 | 1577 | ||
@@ -1766,13 +1785,8 @@ static int ocfs2_mount_volume(struct super_block *sb) | |||
1766 | } | 1785 | } |
1767 | 1786 | ||
1768 | status = ocfs2_truncate_log_init(osb); | 1787 | status = ocfs2_truncate_log_init(osb); |
1769 | if (status < 0) { | 1788 | if (status < 0) |
1770 | mlog_errno(status); | 1789 | mlog_errno(status); |
1771 | goto leave; | ||
1772 | } | ||
1773 | |||
1774 | if (ocfs2_mount_local(osb)) | ||
1775 | goto leave; | ||
1776 | 1790 | ||
1777 | leave: | 1791 | leave: |
1778 | if (unlock_super) | 1792 | if (unlock_super) |
@@ -1802,6 +1816,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1802 | 1816 | ||
1803 | ocfs2_truncate_log_shutdown(osb); | 1817 | ocfs2_truncate_log_shutdown(osb); |
1804 | 1818 | ||
1819 | ocfs2_orphan_scan_stop(osb); | ||
1820 | |||
1805 | /* This will disable recovery and flush any recovery work. */ | 1821 | /* This will disable recovery and flush any recovery work. */ |
1806 | ocfs2_recovery_exit(osb); | 1822 | ocfs2_recovery_exit(osb); |
1807 | 1823 | ||
@@ -1839,6 +1855,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1839 | if (osb->cconn) | 1855 | if (osb->cconn) |
1840 | ocfs2_dlm_shutdown(osb, hangup_needed); | 1856 | ocfs2_dlm_shutdown(osb, hangup_needed); |
1841 | 1857 | ||
1858 | ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats); | ||
1842 | debugfs_remove(osb->osb_debug_root); | 1859 | debugfs_remove(osb->osb_debug_root); |
1843 | 1860 | ||
1844 | if (hangup_needed) | 1861 | if (hangup_needed) |
@@ -1886,7 +1903,8 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu | |||
1886 | 1903 | ||
1887 | static int ocfs2_initialize_super(struct super_block *sb, | 1904 | static int ocfs2_initialize_super(struct super_block *sb, |
1888 | struct buffer_head *bh, | 1905 | struct buffer_head *bh, |
1889 | int sector_size) | 1906 | int sector_size, |
1907 | struct ocfs2_blockcheck_stats *stats) | ||
1890 | { | 1908 | { |
1891 | int status; | 1909 | int status; |
1892 | int i, cbits, bbits; | 1910 | int i, cbits, bbits; |
@@ -1945,6 +1963,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1945 | atomic_set(&osb->alloc_stats.bg_allocs, 0); | 1963 | atomic_set(&osb->alloc_stats.bg_allocs, 0); |
1946 | atomic_set(&osb->alloc_stats.bg_extends, 0); | 1964 | atomic_set(&osb->alloc_stats.bg_extends, 0); |
1947 | 1965 | ||
1966 | /* Copy the blockcheck stats from the superblock probe */ | ||
1967 | osb->osb_ecc_stats = *stats; | ||
1968 | |||
1948 | ocfs2_init_node_maps(osb); | 1969 | ocfs2_init_node_maps(osb); |
1949 | 1970 | ||
1950 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 1971 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
@@ -1957,6 +1978,13 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1957 | goto bail; | 1978 | goto bail; |
1958 | } | 1979 | } |
1959 | 1980 | ||
1981 | status = ocfs2_orphan_scan_init(osb); | ||
1982 | if (status) { | ||
1983 | mlog(ML_ERROR, "Unable to initialize delayed orphan scan\n"); | ||
1984 | mlog_errno(status); | ||
1985 | goto bail; | ||
1986 | } | ||
1987 | |||
1960 | init_waitqueue_head(&osb->checkpoint_event); | 1988 | init_waitqueue_head(&osb->checkpoint_event); |
1961 | atomic_set(&osb->needs_checkpoint, 0); | 1989 | atomic_set(&osb->needs_checkpoint, 0); |
1962 | 1990 | ||
@@ -2175,7 +2203,8 @@ bail: | |||
2175 | */ | 2203 | */ |
2176 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 2204 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
2177 | struct buffer_head *bh, | 2205 | struct buffer_head *bh, |
2178 | u32 blksz) | 2206 | u32 blksz, |
2207 | struct ocfs2_blockcheck_stats *stats) | ||
2179 | { | 2208 | { |
2180 | int status = -EAGAIN; | 2209 | int status = -EAGAIN; |
2181 | 2210 | ||
@@ -2188,7 +2217,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, | |||
2188 | OCFS2_FEATURE_INCOMPAT_META_ECC) { | 2217 | OCFS2_FEATURE_INCOMPAT_META_ECC) { |
2189 | status = ocfs2_block_check_validate(bh->b_data, | 2218 | status = ocfs2_block_check_validate(bh->b_data, |
2190 | bh->b_size, | 2219 | bh->b_size, |
2191 | &di->i_check); | 2220 | &di->i_check, |
2221 | stats); | ||
2192 | if (status) | 2222 | if (status) |
2193 | goto out; | 2223 | goto out; |
2194 | } | 2224 | } |