aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hugetlbfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hugetlbfs')
-rw-r--r--fs/hugetlbfs/inode.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index c5bc355d8243..21b8a4875237 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -923,7 +923,7 @@ static struct file_system_type hugetlbfs_fs_type = {
923 .kill_sb = kill_litter_super, 923 .kill_sb = kill_litter_super,
924}; 924};
925 925
926static struct vfsmount *hugetlbfs_vfsmount; 926static struct vfsmount *hugetlbfs_vfsmount[HUGE_MAX_HSTATE];
927 927
928static int can_do_hugetlb_shm(void) 928static int can_do_hugetlb_shm(void)
929{ 929{
@@ -932,9 +932,22 @@ static int can_do_hugetlb_shm(void)
932 return capable(CAP_IPC_LOCK) || in_group_p(shm_group); 932 return capable(CAP_IPC_LOCK) || in_group_p(shm_group);
933} 933}
934 934
935static int get_hstate_idx(int page_size_log)
936{
937 struct hstate *h;
938
939 if (!page_size_log)
940 return default_hstate_idx;
941 h = size_to_hstate(1 << page_size_log);
942 if (!h)
943 return -1;
944 return h - hstates;
945}
946
935struct file *hugetlb_file_setup(const char *name, unsigned long addr, 947struct file *hugetlb_file_setup(const char *name, unsigned long addr,
936 size_t size, vm_flags_t acctflag, 948 size_t size, vm_flags_t acctflag,
937 struct user_struct **user, int creat_flags) 949 struct user_struct **user,
950 int creat_flags, int page_size_log)
938{ 951{
939 int error = -ENOMEM; 952 int error = -ENOMEM;
940 struct file *file; 953 struct file *file;
@@ -944,9 +957,14 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
944 struct qstr quick_string; 957 struct qstr quick_string;
945 struct hstate *hstate; 958 struct hstate *hstate;
946 unsigned long num_pages; 959 unsigned long num_pages;
960 int hstate_idx;
961
962 hstate_idx = get_hstate_idx(page_size_log);
963 if (hstate_idx < 0)
964 return ERR_PTR(-ENODEV);
947 965
948 *user = NULL; 966 *user = NULL;
949 if (!hugetlbfs_vfsmount) 967 if (!hugetlbfs_vfsmount[hstate_idx])
950 return ERR_PTR(-ENOENT); 968 return ERR_PTR(-ENOENT);
951 969
952 if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) { 970 if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
@@ -963,7 +981,7 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
963 } 981 }
964 } 982 }
965 983
966 root = hugetlbfs_vfsmount->mnt_root; 984 root = hugetlbfs_vfsmount[hstate_idx]->mnt_root;
967 quick_string.name = name; 985 quick_string.name = name;
968 quick_string.len = strlen(quick_string.name); 986 quick_string.len = strlen(quick_string.name);
969 quick_string.hash = 0; 987 quick_string.hash = 0;
@@ -971,7 +989,7 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
971 if (!path.dentry) 989 if (!path.dentry)
972 goto out_shm_unlock; 990 goto out_shm_unlock;
973 991
974 path.mnt = mntget(hugetlbfs_vfsmount); 992 path.mnt = mntget(hugetlbfs_vfsmount[hstate_idx]);
975 error = -ENOSPC; 993 error = -ENOSPC;
976 inode = hugetlbfs_get_inode(root->d_sb, NULL, S_IFREG | S_IRWXUGO, 0); 994 inode = hugetlbfs_get_inode(root->d_sb, NULL, S_IFREG | S_IRWXUGO, 0);
977 if (!inode) 995 if (!inode)
@@ -1011,8 +1029,9 @@ out_shm_unlock:
1011 1029
1012static int __init init_hugetlbfs_fs(void) 1030static int __init init_hugetlbfs_fs(void)
1013{ 1031{
1032 struct hstate *h;
1014 int error; 1033 int error;
1015 struct vfsmount *vfsmount; 1034 int i;
1016 1035
1017 error = bdi_init(&hugetlbfs_backing_dev_info); 1036 error = bdi_init(&hugetlbfs_backing_dev_info);
1018 if (error) 1037 if (error)
@@ -1029,14 +1048,26 @@ static int __init init_hugetlbfs_fs(void)
1029 if (error) 1048 if (error)
1030 goto out; 1049 goto out;
1031 1050
1032 vfsmount = kern_mount(&hugetlbfs_fs_type); 1051 i = 0;
1052 for_each_hstate(h) {
1053 char buf[50];
1054 unsigned ps_kb = 1U << (h->order + PAGE_SHIFT - 10);
1033 1055
1034 if (!IS_ERR(vfsmount)) { 1056 snprintf(buf, sizeof(buf), "pagesize=%uK", ps_kb);
1035 hugetlbfs_vfsmount = vfsmount; 1057 hugetlbfs_vfsmount[i] = kern_mount_data(&hugetlbfs_fs_type,
1036 return 0; 1058 buf);
1037 }
1038 1059
1039 error = PTR_ERR(vfsmount); 1060 if (IS_ERR(hugetlbfs_vfsmount[i])) {
1061 pr_err("hugetlb: Cannot mount internal hugetlbfs for "
1062 "page size %uK", ps_kb);
1063 error = PTR_ERR(hugetlbfs_vfsmount[i]);
1064 hugetlbfs_vfsmount[i] = NULL;
1065 }
1066 i++;
1067 }
1068 /* Non default hstates are optional */
1069 if (!IS_ERR_OR_NULL(hugetlbfs_vfsmount[default_hstate_idx]))
1070 return 0;
1040 1071
1041 out: 1072 out:
1042 kmem_cache_destroy(hugetlbfs_inode_cachep); 1073 kmem_cache_destroy(hugetlbfs_inode_cachep);
@@ -1047,13 +1078,19 @@ static int __init init_hugetlbfs_fs(void)
1047 1078
1048static void __exit exit_hugetlbfs_fs(void) 1079static void __exit exit_hugetlbfs_fs(void)
1049{ 1080{
1081 struct hstate *h;
1082 int i;
1083
1084
1050 /* 1085 /*
1051 * Make sure all delayed rcu free inodes are flushed before we 1086 * Make sure all delayed rcu free inodes are flushed before we
1052 * destroy cache. 1087 * destroy cache.
1053 */ 1088 */
1054 rcu_barrier(); 1089 rcu_barrier();
1055 kmem_cache_destroy(hugetlbfs_inode_cachep); 1090 kmem_cache_destroy(hugetlbfs_inode_cachep);
1056 kern_unmount(hugetlbfs_vfsmount); 1091 i = 0;
1092 for_each_hstate(h)
1093 kern_unmount(hugetlbfs_vfsmount[i++]);
1057 unregister_filesystem(&hugetlbfs_fs_type); 1094 unregister_filesystem(&hugetlbfs_fs_type);
1058 bdi_destroy(&hugetlbfs_backing_dev_info); 1095 bdi_destroy(&hugetlbfs_backing_dev_info);
1059} 1096}