diff options
Diffstat (limited to 'fs/namespace.c')
| -rw-r--r-- | fs/namespace.c | 177 |
1 files changed, 115 insertions, 62 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 22e536705c45..2ffc5a2905d4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -23,11 +23,34 @@ | |||
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <linux/proc_ns.h> | 24 | #include <linux/proc_ns.h> |
| 25 | #include <linux/magic.h> | 25 | #include <linux/magic.h> |
| 26 | #include <linux/bootmem.h> | ||
| 26 | #include "pnode.h" | 27 | #include "pnode.h" |
| 27 | #include "internal.h" | 28 | #include "internal.h" |
| 28 | 29 | ||
| 29 | #define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head)) | 30 | static unsigned int m_hash_mask __read_mostly; |
| 30 | #define HASH_SIZE (1UL << HASH_SHIFT) | 31 | static unsigned int m_hash_shift __read_mostly; |
| 32 | static unsigned int mp_hash_mask __read_mostly; | ||
| 33 | static unsigned int mp_hash_shift __read_mostly; | ||
| 34 | |||
| 35 | static __initdata unsigned long mhash_entries; | ||
| 36 | static int __init set_mhash_entries(char *str) | ||
| 37 | { | ||
| 38 | if (!str) | ||
| 39 | return 0; | ||
| 40 | mhash_entries = simple_strtoul(str, &str, 0); | ||
| 41 | return 1; | ||
| 42 | } | ||
| 43 | __setup("mhash_entries=", set_mhash_entries); | ||
| 44 | |||
| 45 | static __initdata unsigned long mphash_entries; | ||
| 46 | static int __init set_mphash_entries(char *str) | ||
| 47 | { | ||
| 48 | if (!str) | ||
| 49 | return 0; | ||
| 50 | mphash_entries = simple_strtoul(str, &str, 0); | ||
| 51 | return 1; | ||
| 52 | } | ||
| 53 | __setup("mphash_entries=", set_mphash_entries); | ||
| 31 | 54 | ||
| 32 | static int event; | 55 | static int event; |
| 33 | static DEFINE_IDA(mnt_id_ida); | 56 | static DEFINE_IDA(mnt_id_ida); |
| @@ -36,8 +59,8 @@ static DEFINE_SPINLOCK(mnt_id_lock); | |||
| 36 | static int mnt_id_start = 0; | 59 | static int mnt_id_start = 0; |
| 37 | static int mnt_group_start = 1; | 60 | static int mnt_group_start = 1; |
| 38 | 61 | ||
| 39 | static struct list_head *mount_hashtable __read_mostly; | 62 | static struct hlist_head *mount_hashtable __read_mostly; |
| 40 | static struct list_head *mountpoint_hashtable __read_mostly; | 63 | static struct hlist_head *mountpoint_hashtable __read_mostly; |
| 41 | static struct kmem_cache *mnt_cache __read_mostly; | 64 | static struct kmem_cache *mnt_cache __read_mostly; |
| 42 | static DECLARE_RWSEM(namespace_sem); | 65 | static DECLARE_RWSEM(namespace_sem); |
| 43 | 66 | ||
| @@ -55,12 +78,19 @@ EXPORT_SYMBOL_GPL(fs_kobj); | |||
| 55 | */ | 78 | */ |
| 56 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock); | 79 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock); |
| 57 | 80 | ||
| 58 | static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | 81 | static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry *dentry) |
| 59 | { | 82 | { |
| 60 | unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); | 83 | unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); |
| 61 | tmp += ((unsigned long)dentry / L1_CACHE_BYTES); | 84 | tmp += ((unsigned long)dentry / L1_CACHE_BYTES); |
| 62 | tmp = tmp + (tmp >> HASH_SHIFT); | 85 | tmp = tmp + (tmp >> m_hash_shift); |
| 63 | return tmp & (HASH_SIZE - 1); | 86 | return &mount_hashtable[tmp & m_hash_mask]; |
| 87 | } | ||
| 88 | |||
| 89 | static inline struct hlist_head *mp_hash(struct dentry *dentry) | ||
| 90 | { | ||
| 91 | unsigned long tmp = ((unsigned long)dentry / L1_CACHE_BYTES); | ||
| 92 | tmp = tmp + (tmp >> mp_hash_shift); | ||
| 93 | return &mountpoint_hashtable[tmp & mp_hash_mask]; | ||
| 64 | } | 94 | } |
| 65 | 95 | ||
| 66 | /* | 96 | /* |
| @@ -187,7 +217,7 @@ static struct mount *alloc_vfsmnt(const char *name) | |||
| 187 | mnt->mnt_writers = 0; | 217 | mnt->mnt_writers = 0; |
| 188 | #endif | 218 | #endif |
| 189 | 219 | ||
| 190 | INIT_LIST_HEAD(&mnt->mnt_hash); | 220 | INIT_HLIST_NODE(&mnt->mnt_hash); |
| 191 | INIT_LIST_HEAD(&mnt->mnt_child); | 221 | INIT_LIST_HEAD(&mnt->mnt_child); |
| 192 | INIT_LIST_HEAD(&mnt->mnt_mounts); | 222 | INIT_LIST_HEAD(&mnt->mnt_mounts); |
| 193 | INIT_LIST_HEAD(&mnt->mnt_list); | 223 | INIT_LIST_HEAD(&mnt->mnt_list); |
| @@ -575,10 +605,10 @@ bool legitimize_mnt(struct vfsmount *bastard, unsigned seq) | |||
| 575 | */ | 605 | */ |
| 576 | struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | 606 | struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) |
| 577 | { | 607 | { |
| 578 | struct list_head *head = mount_hashtable + hash(mnt, dentry); | 608 | struct hlist_head *head = m_hash(mnt, dentry); |
| 579 | struct mount *p; | 609 | struct mount *p; |
| 580 | 610 | ||
| 581 | list_for_each_entry_rcu(p, head, mnt_hash) | 611 | hlist_for_each_entry_rcu(p, head, mnt_hash) |
| 582 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) | 612 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) |
| 583 | return p; | 613 | return p; |
| 584 | return NULL; | 614 | return NULL; |
| @@ -590,13 +620,17 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | |||
| 590 | */ | 620 | */ |
| 591 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) | 621 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) |
| 592 | { | 622 | { |
| 593 | struct list_head *head = mount_hashtable + hash(mnt, dentry); | 623 | struct mount *p, *res; |
| 594 | struct mount *p; | 624 | res = p = __lookup_mnt(mnt, dentry); |
| 595 | 625 | if (!p) | |
| 596 | list_for_each_entry_reverse(p, head, mnt_hash) | 626 | goto out; |
| 597 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) | 627 | hlist_for_each_entry_continue(p, mnt_hash) { |
| 598 | return p; | 628 | if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry) |
| 599 | return NULL; | 629 | break; |
| 630 | res = p; | ||
| 631 | } | ||
| 632 | out: | ||
| 633 | return res; | ||
| 600 | } | 634 | } |
| 601 | 635 | ||
| 602 | /* | 636 | /* |
| @@ -633,11 +667,11 @@ struct vfsmount *lookup_mnt(struct path *path) | |||
| 633 | 667 | ||
| 634 | static struct mountpoint *new_mountpoint(struct dentry *dentry) | 668 | static struct mountpoint *new_mountpoint(struct dentry *dentry) |
| 635 | { | 669 | { |
| 636 | struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry); | 670 | struct hlist_head *chain = mp_hash(dentry); |
| 637 | struct mountpoint *mp; | 671 | struct mountpoint *mp; |
| 638 | int ret; | 672 | int ret; |
| 639 | 673 | ||
| 640 | list_for_each_entry(mp, chain, m_hash) { | 674 | hlist_for_each_entry(mp, chain, m_hash) { |
| 641 | if (mp->m_dentry == dentry) { | 675 | if (mp->m_dentry == dentry) { |
| 642 | /* might be worth a WARN_ON() */ | 676 | /* might be worth a WARN_ON() */ |
| 643 | if (d_unlinked(dentry)) | 677 | if (d_unlinked(dentry)) |
| @@ -659,7 +693,7 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry) | |||
| 659 | 693 | ||
| 660 | mp->m_dentry = dentry; | 694 | mp->m_dentry = dentry; |
| 661 | mp->m_count = 1; | 695 | mp->m_count = 1; |
| 662 | list_add(&mp->m_hash, chain); | 696 | hlist_add_head(&mp->m_hash, chain); |
| 663 | return mp; | 697 | return mp; |
| 664 | } | 698 | } |
| 665 | 699 | ||
| @@ -670,7 +704,7 @@ static void put_mountpoint(struct mountpoint *mp) | |||
| 670 | spin_lock(&dentry->d_lock); | 704 | spin_lock(&dentry->d_lock); |
| 671 | dentry->d_flags &= ~DCACHE_MOUNTED; | 705 | dentry->d_flags &= ~DCACHE_MOUNTED; |
| 672 | spin_unlock(&dentry->d_lock); | 706 | spin_unlock(&dentry->d_lock); |
| 673 | list_del(&mp->m_hash); | 707 | hlist_del(&mp->m_hash); |
| 674 | kfree(mp); | 708 | kfree(mp); |
| 675 | } | 709 | } |
| 676 | } | 710 | } |
| @@ -712,7 +746,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) | |||
| 712 | mnt->mnt_parent = mnt; | 746 | mnt->mnt_parent = mnt; |
| 713 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 747 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 714 | list_del_init(&mnt->mnt_child); | 748 | list_del_init(&mnt->mnt_child); |
| 715 | list_del_init(&mnt->mnt_hash); | 749 | hlist_del_init_rcu(&mnt->mnt_hash); |
| 716 | put_mountpoint(mnt->mnt_mp); | 750 | put_mountpoint(mnt->mnt_mp); |
| 717 | mnt->mnt_mp = NULL; | 751 | mnt->mnt_mp = NULL; |
| 718 | } | 752 | } |
| @@ -739,15 +773,14 @@ static void attach_mnt(struct mount *mnt, | |||
| 739 | struct mountpoint *mp) | 773 | struct mountpoint *mp) |
| 740 | { | 774 | { |
| 741 | mnt_set_mountpoint(parent, mp, mnt); | 775 | mnt_set_mountpoint(parent, mp, mnt); |
| 742 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 776 | hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry)); |
| 743 | hash(&parent->mnt, mp->m_dentry)); | ||
| 744 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 777 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 745 | } | 778 | } |
| 746 | 779 | ||
| 747 | /* | 780 | /* |
| 748 | * vfsmount lock must be held for write | 781 | * vfsmount lock must be held for write |
| 749 | */ | 782 | */ |
| 750 | static void commit_tree(struct mount *mnt) | 783 | static void commit_tree(struct mount *mnt, struct mount *shadows) |
| 751 | { | 784 | { |
| 752 | struct mount *parent = mnt->mnt_parent; | 785 | struct mount *parent = mnt->mnt_parent; |
| 753 | struct mount *m; | 786 | struct mount *m; |
| @@ -762,8 +795,11 @@ static void commit_tree(struct mount *mnt) | |||
| 762 | 795 | ||
| 763 | list_splice(&head, n->list.prev); | 796 | list_splice(&head, n->list.prev); |
| 764 | 797 | ||
| 765 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 798 | if (shadows) |
| 766 | hash(&parent->mnt, mnt->mnt_mountpoint)); | 799 | hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); |
| 800 | else | ||
| 801 | hlist_add_head_rcu(&mnt->mnt_hash, | ||
| 802 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); | ||
| 767 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 803 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 768 | touch_mnt_namespace(n); | 804 | touch_mnt_namespace(n); |
| 769 | } | 805 | } |
| @@ -1153,26 +1189,28 @@ int may_umount(struct vfsmount *mnt) | |||
| 1153 | 1189 | ||
| 1154 | EXPORT_SYMBOL(may_umount); | 1190 | EXPORT_SYMBOL(may_umount); |
| 1155 | 1191 | ||
| 1156 | static LIST_HEAD(unmounted); /* protected by namespace_sem */ | 1192 | static HLIST_HEAD(unmounted); /* protected by namespace_sem */ |
| 1157 | 1193 | ||
| 1158 | static void namespace_unlock(void) | 1194 | static void namespace_unlock(void) |
| 1159 | { | 1195 | { |
| 1160 | struct mount *mnt; | 1196 | struct mount *mnt; |
| 1161 | LIST_HEAD(head); | 1197 | struct hlist_head head = unmounted; |
| 1162 | 1198 | ||
| 1163 | if (likely(list_empty(&unmounted))) { | 1199 | if (likely(hlist_empty(&head))) { |
| 1164 | up_write(&namespace_sem); | 1200 | up_write(&namespace_sem); |
| 1165 | return; | 1201 | return; |
| 1166 | } | 1202 | } |
| 1167 | 1203 | ||
| 1168 | list_splice_init(&unmounted, &head); | 1204 | head.first->pprev = &head.first; |
| 1205 | INIT_HLIST_HEAD(&unmounted); | ||
| 1206 | |||
| 1169 | up_write(&namespace_sem); | 1207 | up_write(&namespace_sem); |
| 1170 | 1208 | ||
| 1171 | synchronize_rcu(); | 1209 | synchronize_rcu(); |
| 1172 | 1210 | ||
| 1173 | while (!list_empty(&head)) { | 1211 | while (!hlist_empty(&head)) { |
| 1174 | mnt = list_first_entry(&head, struct mount, mnt_hash); | 1212 | mnt = hlist_entry(head.first, struct mount, mnt_hash); |
| 1175 | list_del_init(&mnt->mnt_hash); | 1213 | hlist_del_init(&mnt->mnt_hash); |
| 1176 | if (mnt->mnt_ex_mountpoint.mnt) | 1214 | if (mnt->mnt_ex_mountpoint.mnt) |
| 1177 | path_put(&mnt->mnt_ex_mountpoint); | 1215 | path_put(&mnt->mnt_ex_mountpoint); |
| 1178 | mntput(&mnt->mnt); | 1216 | mntput(&mnt->mnt); |
| @@ -1193,16 +1231,19 @@ static inline void namespace_lock(void) | |||
| 1193 | */ | 1231 | */ |
| 1194 | void umount_tree(struct mount *mnt, int how) | 1232 | void umount_tree(struct mount *mnt, int how) |
| 1195 | { | 1233 | { |
| 1196 | LIST_HEAD(tmp_list); | 1234 | HLIST_HEAD(tmp_list); |
| 1197 | struct mount *p; | 1235 | struct mount *p; |
| 1236 | struct mount *last = NULL; | ||
| 1198 | 1237 | ||
| 1199 | for (p = mnt; p; p = next_mnt(p, mnt)) | 1238 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
| 1200 | list_move(&p->mnt_hash, &tmp_list); | 1239 | hlist_del_init_rcu(&p->mnt_hash); |
| 1240 | hlist_add_head(&p->mnt_hash, &tmp_list); | ||
| 1241 | } | ||
| 1201 | 1242 | ||
| 1202 | if (how) | 1243 | if (how) |
| 1203 | propagate_umount(&tmp_list); | 1244 | propagate_umount(&tmp_list); |
| 1204 | 1245 | ||
| 1205 | list_for_each_entry(p, &tmp_list, mnt_hash) { | 1246 | hlist_for_each_entry(p, &tmp_list, mnt_hash) { |
| 1206 | list_del_init(&p->mnt_expire); | 1247 | list_del_init(&p->mnt_expire); |
| 1207 | list_del_init(&p->mnt_list); | 1248 | list_del_init(&p->mnt_list); |
| 1208 | __touch_mnt_namespace(p->mnt_ns); | 1249 | __touch_mnt_namespace(p->mnt_ns); |
| @@ -1220,8 +1261,13 @@ void umount_tree(struct mount *mnt, int how) | |||
| 1220 | p->mnt_mp = NULL; | 1261 | p->mnt_mp = NULL; |
| 1221 | } | 1262 | } |
| 1222 | change_mnt_propagation(p, MS_PRIVATE); | 1263 | change_mnt_propagation(p, MS_PRIVATE); |
| 1264 | last = p; | ||
| 1265 | } | ||
| 1266 | if (last) { | ||
| 1267 | last->mnt_hash.next = unmounted.first; | ||
| 1268 | unmounted.first = tmp_list.first; | ||
| 1269 | unmounted.first->pprev = &unmounted.first; | ||
| 1223 | } | 1270 | } |
| 1224 | list_splice(&tmp_list, &unmounted); | ||
| 1225 | } | 1271 | } |
| 1226 | 1272 | ||
| 1227 | static void shrink_submounts(struct mount *mnt); | 1273 | static void shrink_submounts(struct mount *mnt); |
| @@ -1605,24 +1651,23 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1605 | struct mountpoint *dest_mp, | 1651 | struct mountpoint *dest_mp, |
| 1606 | struct path *parent_path) | 1652 | struct path *parent_path) |
| 1607 | { | 1653 | { |
| 1608 | LIST_HEAD(tree_list); | 1654 | HLIST_HEAD(tree_list); |
| 1609 | struct mount *child, *p; | 1655 | struct mount *child, *p; |
| 1656 | struct hlist_node *n; | ||
| 1610 | int err; | 1657 | int err; |
| 1611 | 1658 | ||
| 1612 | if (IS_MNT_SHARED(dest_mnt)) { | 1659 | if (IS_MNT_SHARED(dest_mnt)) { |
| 1613 | err = invent_group_ids(source_mnt, true); | 1660 | err = invent_group_ids(source_mnt, true); |
| 1614 | if (err) | 1661 | if (err) |
| 1615 | goto out; | 1662 | goto out; |
| 1616 | } | 1663 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); |
| 1617 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); | 1664 | if (err) |
| 1618 | if (err) | 1665 | goto out_cleanup_ids; |
| 1619 | goto out_cleanup_ids; | 1666 | lock_mount_hash(); |
| 1620 | |||
| 1621 | lock_mount_hash(); | ||
| 1622 | |||
| 1623 | if (IS_MNT_SHARED(dest_mnt)) { | ||
| 1624 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) | 1667 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) |
| 1625 | set_mnt_shared(p); | 1668 | set_mnt_shared(p); |
| 1669 | } else { | ||
| 1670 | lock_mount_hash(); | ||
| 1626 | } | 1671 | } |
| 1627 | if (parent_path) { | 1672 | if (parent_path) { |
| 1628 | detach_mnt(source_mnt, parent_path); | 1673 | detach_mnt(source_mnt, parent_path); |
| @@ -1630,20 +1675,22 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1630 | touch_mnt_namespace(source_mnt->mnt_ns); | 1675 | touch_mnt_namespace(source_mnt->mnt_ns); |
| 1631 | } else { | 1676 | } else { |
| 1632 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); | 1677 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); |
| 1633 | commit_tree(source_mnt); | 1678 | commit_tree(source_mnt, NULL); |
| 1634 | } | 1679 | } |
| 1635 | 1680 | ||
| 1636 | list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { | 1681 | hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) { |
| 1637 | list_del_init(&child->mnt_hash); | 1682 | struct mount *q; |
| 1638 | commit_tree(child); | 1683 | hlist_del_init(&child->mnt_hash); |
| 1684 | q = __lookup_mnt_last(&child->mnt_parent->mnt, | ||
| 1685 | child->mnt_mountpoint); | ||
| 1686 | commit_tree(child, q); | ||
| 1639 | } | 1687 | } |
| 1640 | unlock_mount_hash(); | 1688 | unlock_mount_hash(); |
| 1641 | 1689 | ||
| 1642 | return 0; | 1690 | return 0; |
| 1643 | 1691 | ||
| 1644 | out_cleanup_ids: | 1692 | out_cleanup_ids: |
| 1645 | if (IS_MNT_SHARED(dest_mnt)) | 1693 | cleanup_group_ids(source_mnt, NULL); |
| 1646 | cleanup_group_ids(source_mnt, NULL); | ||
| 1647 | out: | 1694 | out: |
| 1648 | return err; | 1695 | return err; |
| 1649 | } | 1696 | } |
| @@ -2777,18 +2824,24 @@ void __init mnt_init(void) | |||
| 2777 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount), | 2824 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount), |
| 2778 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | 2825 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); |
| 2779 | 2826 | ||
| 2780 | mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); | 2827 | mount_hashtable = alloc_large_system_hash("Mount-cache", |
| 2781 | mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); | 2828 | sizeof(struct hlist_head), |
| 2829 | mhash_entries, 19, | ||
| 2830 | 0, | ||
| 2831 | &m_hash_shift, &m_hash_mask, 0, 0); | ||
| 2832 | mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache", | ||
| 2833 | sizeof(struct hlist_head), | ||
| 2834 | mphash_entries, 19, | ||
| 2835 | 0, | ||
| 2836 | &mp_hash_shift, &mp_hash_mask, 0, 0); | ||
| 2782 | 2837 | ||
| 2783 | if (!mount_hashtable || !mountpoint_hashtable) | 2838 | if (!mount_hashtable || !mountpoint_hashtable) |
| 2784 | panic("Failed to allocate mount hash table\n"); | 2839 | panic("Failed to allocate mount hash table\n"); |
| 2785 | 2840 | ||
| 2786 | printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE); | 2841 | for (u = 0; u <= m_hash_mask; u++) |
| 2787 | 2842 | INIT_HLIST_HEAD(&mount_hashtable[u]); | |
| 2788 | for (u = 0; u < HASH_SIZE; u++) | 2843 | for (u = 0; u <= mp_hash_mask; u++) |
| 2789 | INIT_LIST_HEAD(&mount_hashtable[u]); | 2844 | INIT_HLIST_HEAD(&mountpoint_hashtable[u]); |
| 2790 | for (u = 0; u < HASH_SIZE; u++) | ||
| 2791 | INIT_LIST_HEAD(&mountpoint_hashtable[u]); | ||
| 2792 | 2845 | ||
| 2793 | kernfs_init(); | 2846 | kernfs_init(); |
| 2794 | 2847 | ||
