| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: tmpfs_vfsops.c,v 1.68 2016/08/26 21:44:24 dholland Exp $ */ | | 1 | /* $NetBSD: tmpfs_vfsops.c,v 1.69 2017/01/27 10:47:54 hannken Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | | 8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code |
9 | * 2005 program. | | 9 | * 2005 program. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -32,27 +32,27 @@ | | | @@ -32,27 +32,27 @@ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Efficient memory file system. | | 34 | * Efficient memory file system. |
35 | * | | 35 | * |
36 | * tmpfs is a file system that uses NetBSD's virtual memory sub-system | | 36 | * tmpfs is a file system that uses NetBSD's virtual memory sub-system |
37 | * (the well-known UVM) to store file data and metadata in an efficient | | 37 | * (the well-known UVM) to store file data and metadata in an efficient |
38 | * way. This means that it does not follow the structure of an on-disk | | 38 | * way. This means that it does not follow the structure of an on-disk |
39 | * file system because it simply does not need to. Instead, it uses | | 39 | * file system because it simply does not need to. Instead, it uses |
40 | * memory-specific data structures and algorithms to automatically | | 40 | * memory-specific data structures and algorithms to automatically |
41 | * allocate and release resources. | | 41 | * allocate and release resources. |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
45 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.68 2016/08/26 21:44:24 dholland Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.69 2017/01/27 10:47:54 hannken Exp $"); |
46 | | | 46 | |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <sys/atomic.h> | | 48 | #include <sys/atomic.h> |
49 | #include <sys/types.h> | | 49 | #include <sys/types.h> |
50 | #include <sys/kmem.h> | | 50 | #include <sys/kmem.h> |
51 | #include <sys/mount.h> | | 51 | #include <sys/mount.h> |
52 | #include <sys/stat.h> | | 52 | #include <sys/stat.h> |
53 | #include <sys/systm.h> | | 53 | #include <sys/systm.h> |
54 | #include <sys/vnode.h> | | 54 | #include <sys/vnode.h> |
55 | #include <sys/kauth.h> | | 55 | #include <sys/kauth.h> |
56 | #include <sys/module.h> | | 56 | #include <sys/module.h> |
57 | | | 57 | |
58 | #include <miscfs/genfs/genfs.h> | | 58 | #include <miscfs/genfs/genfs.h> |
| @@ -82,27 +82,27 @@ tmpfs_done(void) | | | @@ -82,27 +82,27 @@ tmpfs_done(void) |
82 | pool_destroy(&tmpfs_node_pool); | | 82 | pool_destroy(&tmpfs_node_pool); |
83 | } | | 83 | } |
84 | | | 84 | |
85 | int | | 85 | int |
86 | tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) | | 86 | tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) |
87 | { | | 87 | { |
88 | struct tmpfs_args *args = data; | | 88 | struct tmpfs_args *args = data; |
89 | tmpfs_mount_t *tmp; | | 89 | tmpfs_mount_t *tmp; |
90 | tmpfs_node_t *root; | | 90 | tmpfs_node_t *root; |
91 | struct vattr va; | | 91 | struct vattr va; |
92 | struct vnode *vp; | | 92 | struct vnode *vp; |
93 | uint64_t memlimit; | | 93 | uint64_t memlimit; |
94 | ino_t nodes; | | 94 | ino_t nodes; |
95 | int error; | | 95 | int error, flags; |
96 | bool set_memlimit; | | 96 | bool set_memlimit; |
97 | bool set_nodes; | | 97 | bool set_nodes; |
98 | | | 98 | |
99 | if (args == NULL) | | 99 | if (args == NULL) |
100 | return EINVAL; | | 100 | return EINVAL; |
101 | | | 101 | |
102 | /* Validate the version. */ | | 102 | /* Validate the version. */ |
103 | if (*data_len < sizeof(*args) || | | 103 | if (*data_len < sizeof(*args) || |
104 | args->ta_version != TMPFS_ARGS_VERSION) | | 104 | args->ta_version != TMPFS_ARGS_VERSION) |
105 | return EINVAL; | | 105 | return EINVAL; |
106 | | | 106 | |
107 | /* Handle retrieval of mount point arguments. */ | | 107 | /* Handle retrieval of mount point arguments. */ |
108 | if (mp->mnt_flag & MNT_GETARGS) { | | 108 | if (mp->mnt_flag & MNT_GETARGS) { |
| @@ -150,44 +150,60 @@ tmpfs_mount(struct mount *mp, const char | | | @@ -150,44 +150,60 @@ tmpfs_mount(struct mount *mp, const char |
150 | nodes = 3 + (memlimit / 1024); | | 150 | nodes = 3 + (memlimit / 1024); |
151 | set_nodes = false; | | 151 | set_nodes = false; |
152 | } else { | | 152 | } else { |
153 | nodes = args->ta_nodes_max; | | 153 | nodes = args->ta_nodes_max; |
154 | set_nodes = true; | | 154 | set_nodes = true; |
155 | } | | 155 | } |
156 | nodes = MIN(nodes, INT_MAX); | | 156 | nodes = MIN(nodes, INT_MAX); |
157 | KASSERT(nodes >= 3); | | 157 | KASSERT(nodes >= 3); |
158 | | | 158 | |
159 | if (mp->mnt_flag & MNT_UPDATE) { | | 159 | if (mp->mnt_flag & MNT_UPDATE) { |
160 | tmp = VFS_TO_TMPFS(mp); | | 160 | tmp = VFS_TO_TMPFS(mp); |
161 | if (set_nodes && nodes < tmp->tm_nodes_cnt) | | 161 | if (set_nodes && nodes < tmp->tm_nodes_cnt) |
162 | return EBUSY; | | 162 | return EBUSY; |
| | | 163 | if (!tmp->tm_rdonly && (mp->mnt_flag & MNT_RDONLY)) { |
| | | 164 | /* Changing from read/write to read-only. */ |
| | | 165 | flags = WRITECLOSE; |
| | | 166 | if ((mp->mnt_flag & MNT_FORCE)) |
| | | 167 | flags |= FORCECLOSE; |
| | | 168 | error = vflush(mp, NULL, flags); |
| | | 169 | if (error) |
| | | 170 | return error; |
| | | 171 | tmp->tm_rdonly = true; |
| | | 172 | } |
| | | 173 | if (tmp->tm_rdonly && (mp->mnt_flag & IMNT_WANTRDWR)) { |
| | | 174 | /* Changing from read-only to read/write. */ |
| | | 175 | tmp->tm_rdonly = false; |
| | | 176 | } |
163 | if (set_memlimit) { | | 177 | if (set_memlimit) { |
164 | if ((error = tmpfs_mntmem_set(tmp, memlimit)) != 0) | | 178 | if ((error = tmpfs_mntmem_set(tmp, memlimit)) != 0) |
165 | return error; | | 179 | return error; |
166 | } | | 180 | } |
167 | if (set_nodes) | | 181 | if (set_nodes) |
168 | tmp->tm_nodes_max = nodes; | | 182 | tmp->tm_nodes_max = nodes; |
169 | root = tmp->tm_root; | | 183 | root = tmp->tm_root; |
170 | root->tn_uid = args->ta_root_uid; | | 184 | root->tn_uid = args->ta_root_uid; |
171 | root->tn_gid = args->ta_root_gid; | | 185 | root->tn_gid = args->ta_root_gid; |
172 | root->tn_mode = args->ta_root_mode; | | 186 | root->tn_mode = args->ta_root_mode; |
173 | return 0; | | 187 | return 0; |
174 | } | | 188 | } |
175 | | | 189 | |
176 | /* Allocate the tmpfs mount structure and fill it. */ | | 190 | /* Allocate the tmpfs mount structure and fill it. */ |
177 | tmp = kmem_zalloc(sizeof(tmpfs_mount_t), KM_SLEEP); | | 191 | tmp = kmem_zalloc(sizeof(tmpfs_mount_t), KM_SLEEP); |
178 | if (tmp == NULL) | | 192 | if (tmp == NULL) |
179 | return ENOMEM; | | 193 | return ENOMEM; |
180 | | | 194 | |
| | | 195 | if ((mp->mnt_flag & MNT_RDONLY)) |
| | | 196 | tmp->tm_rdonly = true; |
181 | tmp->tm_nodes_max = nodes; | | 197 | tmp->tm_nodes_max = nodes; |
182 | tmp->tm_nodes_cnt = 0; | | 198 | tmp->tm_nodes_cnt = 0; |
183 | LIST_INIT(&tmp->tm_nodes); | | 199 | LIST_INIT(&tmp->tm_nodes); |
184 | | | 200 | |
185 | mutex_init(&tmp->tm_lock, MUTEX_DEFAULT, IPL_NONE); | | 201 | mutex_init(&tmp->tm_lock, MUTEX_DEFAULT, IPL_NONE); |
186 | tmpfs_mntmem_init(tmp, memlimit); | | 202 | tmpfs_mntmem_init(tmp, memlimit); |
187 | mp->mnt_data = tmp; | | 203 | mp->mnt_data = tmp; |
188 | | | 204 | |
189 | /* Allocate the root node. */ | | 205 | /* Allocate the root node. */ |
190 | vattr_null(&va); | | 206 | vattr_null(&va); |
191 | va.va_type = VDIR; | | 207 | va.va_type = VDIR; |
192 | va.va_mode = args->ta_root_mode & ALLPERMS; | | 208 | va.va_mode = args->ta_root_mode & ALLPERMS; |
193 | va.va_uid = args->ta_root_uid; | | 209 | va.va_uid = args->ta_root_uid; |