diff options
Diffstat (limited to 'fs/ubifs/super.c')
-rw-r--r-- | fs/ubifs/super.c | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index e9f7a754c4f7..26d2e0d80465 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mount.h> | 36 | #include <linux/mount.h> |
37 | #include <linux/math64.h> | 37 | #include <linux/math64.h> |
38 | #include <linux/writeback.h> | 38 | #include <linux/writeback.h> |
39 | #include <linux/smp_lock.h> | ||
39 | #include "ubifs.h" | 40 | #include "ubifs.h" |
40 | 41 | ||
41 | /* | 42 | /* |
@@ -360,6 +361,11 @@ static void ubifs_delete_inode(struct inode *inode) | |||
360 | out: | 361 | out: |
361 | if (ui->dirty) | 362 | if (ui->dirty) |
362 | ubifs_release_dirty_inode_budget(c, ui); | 363 | ubifs_release_dirty_inode_budget(c, ui); |
364 | else { | ||
365 | /* We've deleted something - clean the "no space" flags */ | ||
366 | c->nospace = c->nospace_rp = 0; | ||
367 | smp_wmb(); | ||
368 | } | ||
363 | clear_inode(inode); | 369 | clear_inode(inode); |
364 | } | 370 | } |
365 | 371 | ||
@@ -447,9 +453,6 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) | |||
447 | if (!wait) | 453 | if (!wait) |
448 | return 0; | 454 | return 0; |
449 | 455 | ||
450 | if (sb->s_flags & MS_RDONLY) | ||
451 | return 0; | ||
452 | |||
453 | /* | 456 | /* |
454 | * VFS calls '->sync_fs()' before synchronizing all dirty inodes and | 457 | * VFS calls '->sync_fs()' before synchronizing all dirty inodes and |
455 | * pages, so synchronize them first, then commit the journal. Strictly | 458 | * pages, so synchronize them first, then commit the journal. Strictly |
@@ -794,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c) | |||
794 | * does not need to be synchronized by timer. | 797 | * does not need to be synchronized by timer. |
795 | */ | 798 | */ |
796 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; | 799 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; |
797 | c->jheads[GCHD].wbuf.timeout = 0; | 800 | c->jheads[GCHD].wbuf.no_timer = 1; |
798 | 801 | ||
799 | return 0; | 802 | return 0; |
800 | } | 803 | } |
@@ -935,6 +938,27 @@ static const match_table_t tokens = { | |||
935 | }; | 938 | }; |
936 | 939 | ||
937 | /** | 940 | /** |
941 | * parse_standard_option - parse a standard mount option. | ||
942 | * @option: the option to parse | ||
943 | * | ||
944 | * Normally, standard mount options like "sync" are passed to file-systems as | ||
945 | * flags. However, when a "rootflags=" kernel boot parameter is used, they may | ||
946 | * be present in the options string. This function tries to deal with this | ||
947 | * situation and parse standard options. Returns 0 if the option was not | ||
948 | * recognized, and the corresponding integer flag if it was. | ||
949 | * | ||
950 | * UBIFS is only interested in the "sync" option, so do not check for anything | ||
951 | * else. | ||
952 | */ | ||
953 | static int parse_standard_option(const char *option) | ||
954 | { | ||
955 | ubifs_msg("parse %s", option); | ||
956 | if (!strcmp(option, "sync")) | ||
957 | return MS_SYNCHRONOUS; | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /** | ||
938 | * ubifs_parse_options - parse mount parameters. | 962 | * ubifs_parse_options - parse mount parameters. |
939 | * @c: UBIFS file-system description object | 963 | * @c: UBIFS file-system description object |
940 | * @options: parameters to parse | 964 | * @options: parameters to parse |
@@ -962,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
962 | switch (token) { | 986 | switch (token) { |
963 | /* | 987 | /* |
964 | * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. | 988 | * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. |
965 | * We accepte them in order to be backware-compatible. But this | 989 | * We accept them in order to be backward-compatible. But this |
966 | * should be removed at some point. | 990 | * should be removed at some point. |
967 | */ | 991 | */ |
968 | case Opt_fast_unmount: | 992 | case Opt_fast_unmount: |
@@ -1010,9 +1034,19 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
1010 | break; | 1034 | break; |
1011 | } | 1035 | } |
1012 | default: | 1036 | default: |
1013 | ubifs_err("unrecognized mount option \"%s\" " | 1037 | { |
1014 | "or missing value", p); | 1038 | unsigned long flag; |
1015 | return -EINVAL; | 1039 | struct super_block *sb = c->vfs_sb; |
1040 | |||
1041 | flag = parse_standard_option(p); | ||
1042 | if (!flag) { | ||
1043 | ubifs_err("unrecognized mount option \"%s\" " | ||
1044 | "or missing value", p); | ||
1045 | return -EINVAL; | ||
1046 | } | ||
1047 | sb->s_flags |= flag; | ||
1048 | break; | ||
1049 | } | ||
1016 | } | 1050 | } |
1017 | } | 1051 | } |
1018 | 1052 | ||
@@ -1182,6 +1216,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1182 | if (!ubifs_compr_present(c->default_compr)) { | 1216 | if (!ubifs_compr_present(c->default_compr)) { |
1183 | ubifs_err("'compressor \"%s\" is not compiled in", | 1217 | ubifs_err("'compressor \"%s\" is not compiled in", |
1184 | ubifs_compr_name(c->default_compr)); | 1218 | ubifs_compr_name(c->default_compr)); |
1219 | err = -ENOTSUPP; | ||
1185 | goto out_free; | 1220 | goto out_free; |
1186 | } | 1221 | } |
1187 | 1222 | ||
@@ -1252,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1252 | if (err) | 1287 | if (err) |
1253 | goto out_journal; | 1288 | goto out_journal; |
1254 | 1289 | ||
1290 | /* Calculate 'min_idx_lebs' after journal replay */ | ||
1291 | c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); | ||
1292 | |||
1255 | err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); | 1293 | err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); |
1256 | if (err) | 1294 | if (err) |
1257 | goto out_orphans; | 1295 | goto out_orphans; |
@@ -1658,7 +1696,7 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
1658 | 1696 | ||
1659 | for (i = 0; i < c->jhead_cnt; i++) { | 1697 | for (i = 0; i < c->jhead_cnt; i++) { |
1660 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1698 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
1661 | del_timer_sync(&c->jheads[i].wbuf.timer); | 1699 | hrtimer_cancel(&c->jheads[i].wbuf.timer); |
1662 | } | 1700 | } |
1663 | 1701 | ||
1664 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); | 1702 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); |
@@ -1687,6 +1725,9 @@ static void ubifs_put_super(struct super_block *sb) | |||
1687 | 1725 | ||
1688 | ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num, | 1726 | ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num, |
1689 | c->vi.vol_id); | 1727 | c->vi.vol_id); |
1728 | |||
1729 | lock_kernel(); | ||
1730 | |||
1690 | /* | 1731 | /* |
1691 | * The following asserts are only valid if there has not been a failure | 1732 | * The following asserts are only valid if there has not been a failure |
1692 | * of the media. For example, there will be dirty inodes if we failed | 1733 | * of the media. For example, there will be dirty inodes if we failed |
@@ -1716,10 +1757,8 @@ static void ubifs_put_super(struct super_block *sb) | |||
1716 | 1757 | ||
1717 | /* Synchronize write-buffers */ | 1758 | /* Synchronize write-buffers */ |
1718 | if (c->jheads) | 1759 | if (c->jheads) |
1719 | for (i = 0; i < c->jhead_cnt; i++) { | 1760 | for (i = 0; i < c->jhead_cnt; i++) |
1720 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1761 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
1721 | del_timer_sync(&c->jheads[i].wbuf.timer); | ||
1722 | } | ||
1723 | 1762 | ||
1724 | /* | 1763 | /* |
1725 | * On fatal errors c->ro_media is set to 1, in which case we do | 1764 | * On fatal errors c->ro_media is set to 1, in which case we do |
@@ -1753,6 +1792,8 @@ static void ubifs_put_super(struct super_block *sb) | |||
1753 | ubi_close_volume(c->ubi); | 1792 | ubi_close_volume(c->ubi); |
1754 | mutex_unlock(&c->umount_mutex); | 1793 | mutex_unlock(&c->umount_mutex); |
1755 | kfree(c); | 1794 | kfree(c); |
1795 | |||
1796 | unlock_kernel(); | ||
1756 | } | 1797 | } |
1757 | 1798 | ||
1758 | static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | 1799 | static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) |
@@ -1768,17 +1809,22 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1768 | return err; | 1809 | return err; |
1769 | } | 1810 | } |
1770 | 1811 | ||
1812 | lock_kernel(); | ||
1771 | if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { | 1813 | if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { |
1772 | if (c->ro_media) { | 1814 | if (c->ro_media) { |
1773 | ubifs_msg("cannot re-mount due to prior errors"); | 1815 | ubifs_msg("cannot re-mount due to prior errors"); |
1816 | unlock_kernel(); | ||
1774 | return -EROFS; | 1817 | return -EROFS; |
1775 | } | 1818 | } |
1776 | err = ubifs_remount_rw(c); | 1819 | err = ubifs_remount_rw(c); |
1777 | if (err) | 1820 | if (err) { |
1821 | unlock_kernel(); | ||
1778 | return err; | 1822 | return err; |
1823 | } | ||
1779 | } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { | 1824 | } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { |
1780 | if (c->ro_media) { | 1825 | if (c->ro_media) { |
1781 | ubifs_msg("cannot re-mount due to prior errors"); | 1826 | ubifs_msg("cannot re-mount due to prior errors"); |
1827 | unlock_kernel(); | ||
1782 | return -EROFS; | 1828 | return -EROFS; |
1783 | } | 1829 | } |
1784 | ubifs_remount_ro(c); | 1830 | ubifs_remount_ro(c); |
@@ -1793,6 +1839,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1793 | } | 1839 | } |
1794 | 1840 | ||
1795 | ubifs_assert(c->lst.taken_empty_lebs > 0); | 1841 | ubifs_assert(c->lst.taken_empty_lebs > 0); |
1842 | unlock_kernel(); | ||
1796 | return 0; | 1843 | return 0; |
1797 | } | 1844 | } |
1798 | 1845 | ||
@@ -1902,6 +1949,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
1902 | INIT_LIST_HEAD(&c->orph_list); | 1949 | INIT_LIST_HEAD(&c->orph_list); |
1903 | INIT_LIST_HEAD(&c->orph_new); | 1950 | INIT_LIST_HEAD(&c->orph_new); |
1904 | 1951 | ||
1952 | c->vfs_sb = sb; | ||
1905 | c->highest_inum = UBIFS_FIRST_INO; | 1953 | c->highest_inum = UBIFS_FIRST_INO; |
1906 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; | 1954 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; |
1907 | 1955 | ||
@@ -1928,18 +1976,19 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
1928 | err = bdi_init(&c->bdi); | 1976 | err = bdi_init(&c->bdi); |
1929 | if (err) | 1977 | if (err) |
1930 | goto out_close; | 1978 | goto out_close; |
1979 | err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d", | ||
1980 | c->vi.ubi_num, c->vi.vol_id); | ||
1981 | if (err) | ||
1982 | goto out_bdi; | ||
1931 | 1983 | ||
1932 | err = ubifs_parse_options(c, data, 0); | 1984 | err = ubifs_parse_options(c, data, 0); |
1933 | if (err) | 1985 | if (err) |
1934 | goto out_bdi; | 1986 | goto out_bdi; |
1935 | 1987 | ||
1936 | c->vfs_sb = sb; | ||
1937 | |||
1938 | sb->s_fs_info = c; | 1988 | sb->s_fs_info = c; |
1939 | sb->s_magic = UBIFS_SUPER_MAGIC; | 1989 | sb->s_magic = UBIFS_SUPER_MAGIC; |
1940 | sb->s_blocksize = UBIFS_BLOCK_SIZE; | 1990 | sb->s_blocksize = UBIFS_BLOCK_SIZE; |
1941 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; | 1991 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; |
1942 | sb->s_dev = c->vi.cdev; | ||
1943 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); | 1992 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); |
1944 | if (c->max_inode_sz > MAX_LFS_FILESIZE) | 1993 | if (c->max_inode_sz > MAX_LFS_FILESIZE) |
1945 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; | 1994 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; |
@@ -1984,16 +2033,9 @@ out_free: | |||
1984 | static int sb_test(struct super_block *sb, void *data) | 2033 | static int sb_test(struct super_block *sb, void *data) |
1985 | { | 2034 | { |
1986 | dev_t *dev = data; | 2035 | dev_t *dev = data; |
2036 | struct ubifs_info *c = sb->s_fs_info; | ||
1987 | 2037 | ||
1988 | return sb->s_dev == *dev; | 2038 | return c->vi.cdev == *dev; |
1989 | } | ||
1990 | |||
1991 | static int sb_set(struct super_block *sb, void *data) | ||
1992 | { | ||
1993 | dev_t *dev = data; | ||
1994 | |||
1995 | sb->s_dev = *dev; | ||
1996 | return 0; | ||
1997 | } | 2039 | } |
1998 | 2040 | ||
1999 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | 2041 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, |
@@ -2021,7 +2063,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | |||
2021 | 2063 | ||
2022 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); | 2064 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); |
2023 | 2065 | ||
2024 | sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev); | 2066 | sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); |
2025 | if (IS_ERR(sb)) { | 2067 | if (IS_ERR(sb)) { |
2026 | err = PTR_ERR(sb); | 2068 | err = PTR_ERR(sb); |
2027 | goto out_close; | 2069 | goto out_close; |
@@ -2061,16 +2103,11 @@ out_close: | |||
2061 | return err; | 2103 | return err; |
2062 | } | 2104 | } |
2063 | 2105 | ||
2064 | static void ubifs_kill_sb(struct super_block *sb) | ||
2065 | { | ||
2066 | generic_shutdown_super(sb); | ||
2067 | } | ||
2068 | |||
2069 | static struct file_system_type ubifs_fs_type = { | 2106 | static struct file_system_type ubifs_fs_type = { |
2070 | .name = "ubifs", | 2107 | .name = "ubifs", |
2071 | .owner = THIS_MODULE, | 2108 | .owner = THIS_MODULE, |
2072 | .get_sb = ubifs_get_sb, | 2109 | .get_sb = ubifs_get_sb, |
2073 | .kill_sb = ubifs_kill_sb | 2110 | .kill_sb = kill_anon_super, |
2074 | }; | 2111 | }; |
2075 | 2112 | ||
2076 | /* | 2113 | /* |