diff options
Diffstat (limited to 'fs/hugetlbfs')
-rw-r--r-- | fs/hugetlbfs/inode.c | 63 |
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 | ||
926 | static struct vfsmount *hugetlbfs_vfsmount; | 926 | static struct vfsmount *hugetlbfs_vfsmount[HUGE_MAX_HSTATE]; |
927 | 927 | ||
928 | static int can_do_hugetlb_shm(void) | 928 | static 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 | ||
935 | static 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 | |||
935 | struct file *hugetlb_file_setup(const char *name, unsigned long addr, | 947 | struct 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 | ||
1012 | static int __init init_hugetlbfs_fs(void) | 1030 | static 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 | ||
1048 | static void __exit exit_hugetlbfs_fs(void) | 1079 | static 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 | } |