Wed Sep 24 09:37:13 2008 UTC ()
Don't assign vnode::v_mount. getnewvnode() does it.


(ad)
diff -r1.15 -r1.16 src/sys/fs/efs/efs_vfsops.c

cvs diff -r1.15 -r1.16 src/sys/fs/efs/efs_vfsops.c (switch to unified diff)

--- src/sys/fs/efs/efs_vfsops.c 2008/05/10 02:26:09 1.15
+++ src/sys/fs/efs/efs_vfsops.c 2008/09/24 09:37:13 1.16
@@ -1,602 +1,601 @@ @@ -1,602 +1,601 @@
1/* $NetBSD: efs_vfsops.c,v 1.15 2008/05/10 02:26:09 rumble Exp $ */ 1/* $NetBSD: efs_vfsops.c,v 1.16 2008/09/24 09:37:13 ad Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Stephen M. Rumble <rumble@ephemeral.org> 4 * Copyright (c) 2006 Stephen M. Rumble <rumble@ephemeral.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies. 8 * copyright notice and this permission notice appear in all copies.
9 * 9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19#include <sys/cdefs.h> 19#include <sys/cdefs.h>
20__KERNEL_RCSID(0, "$NetBSD: efs_vfsops.c,v 1.15 2008/05/10 02:26:09 rumble Exp $"); 20__KERNEL_RCSID(0, "$NetBSD: efs_vfsops.c,v 1.16 2008/09/24 09:37:13 ad Exp $");
21 21
22#include <sys/param.h> 22#include <sys/param.h>
23#include <sys/systm.h> 23#include <sys/systm.h>
24#include <sys/malloc.h> 24#include <sys/malloc.h>
25#include <sys/mount.h> 25#include <sys/mount.h>
26#include <sys/fstypes.h> 26#include <sys/fstypes.h>
27#include <sys/vnode.h> 27#include <sys/vnode.h>
28#include <sys/buf.h> 28#include <sys/buf.h>
29#include <sys/namei.h> 29#include <sys/namei.h>
30#include <sys/fcntl.h> 30#include <sys/fcntl.h>
31#include <sys/stat.h> 31#include <sys/stat.h>
32#include <sys/kauth.h> 32#include <sys/kauth.h>
33#include <sys/proc.h> 33#include <sys/proc.h>
34#include <sys/module.h> 34#include <sys/module.h>
35 35
36#include <miscfs/genfs/genfs_node.h> 36#include <miscfs/genfs/genfs_node.h>
37 37
38#include <miscfs/specfs/specdev.h> 38#include <miscfs/specfs/specdev.h>
39 39
40#include <fs/efs/efs.h> 40#include <fs/efs/efs.h>
41#include <fs/efs/efs_sb.h> 41#include <fs/efs/efs_sb.h>
42#include <fs/efs/efs_dir.h> 42#include <fs/efs/efs_dir.h>
43#include <fs/efs/efs_genfs.h> 43#include <fs/efs/efs_genfs.h>
44#include <fs/efs/efs_mount.h> 44#include <fs/efs/efs_mount.h>
45#include <fs/efs/efs_extent.h> 45#include <fs/efs/efs_extent.h>
46#include <fs/efs/efs_dinode.h> 46#include <fs/efs/efs_dinode.h>
47#include <fs/efs/efs_inode.h> 47#include <fs/efs/efs_inode.h>
48#include <fs/efs/efs_subr.h> 48#include <fs/efs/efs_subr.h>
49#include <fs/efs/efs_ihash.h> 49#include <fs/efs/efs_ihash.h>
50 50
51MODULE(MODULE_CLASS_VFS, efs, NULL); 51MODULE(MODULE_CLASS_VFS, efs, NULL);
52 52
53MALLOC_JUSTDEFINE(M_EFSMNT, "efsmnt", "efs mount structure"); 53MALLOC_JUSTDEFINE(M_EFSMNT, "efsmnt", "efs mount structure");
54MALLOC_JUSTDEFINE(M_EFSINO, "efsino", "efs in-core inode structure"); 54MALLOC_JUSTDEFINE(M_EFSINO, "efsino", "efs in-core inode structure");
55MALLOC_JUSTDEFINE(M_EFSTMP, "efstmp", "efs temporary allocations"); 55MALLOC_JUSTDEFINE(M_EFSTMP, "efstmp", "efs temporary allocations");
56 56
57extern int (**efs_vnodeop_p)(void *); /* for getnewvnode() */ 57extern int (**efs_vnodeop_p)(void *); /* for getnewvnode() */
58static int efs_statvfs(struct mount *, struct statvfs *); 58static int efs_statvfs(struct mount *, struct statvfs *);
59 59
60/* 60/*
61 * efs_mount and efs_mountroot common functions. 61 * efs_mount and efs_mountroot common functions.
62 */ 62 */
63static int 63static int
64efs_mount_common(struct mount *mp, const char *path, struct vnode *devvp, 64efs_mount_common(struct mount *mp, const char *path, struct vnode *devvp,
65 struct efs_args *args) 65 struct efs_args *args)
66{ 66{
67 int err; 67 int err;
68 struct buf *bp; 68 struct buf *bp;
69 const char *why; 69 const char *why;
70 struct efs_mount *emp; 70 struct efs_mount *emp;
71 struct lwp *l = curlwp; 71 struct lwp *l = curlwp;
72 72
73 emp = malloc(sizeof(*emp), M_EFSMNT, M_WAITOK); 73 emp = malloc(sizeof(*emp), M_EFSMNT, M_WAITOK);
74 emp->em_dev = devvp->v_rdev; 74 emp->em_dev = devvp->v_rdev;
75 emp->em_devvp = devvp; 75 emp->em_devvp = devvp;
76 emp->em_mnt = mp; 76 emp->em_mnt = mp;
77 77
78 /* read in the superblock */ 78 /* read in the superblock */
79 err = efs_bread(emp, EFS_BB_SB, l, &bp); 79 err = efs_bread(emp, EFS_BB_SB, l, &bp);
80 if (err) { 80 if (err) {
81 EFS_DPRINTF(("superblock read failed\n")); 81 EFS_DPRINTF(("superblock read failed\n"));
82 free(emp, M_EFSMNT); 82 free(emp, M_EFSMNT);
83 brelse(bp, 0); 83 brelse(bp, 0);
84 return (err); 84 return (err);
85 } 85 }
86 memcpy(&emp->em_sb, bp->b_data, sizeof(emp->em_sb)); 86 memcpy(&emp->em_sb, bp->b_data, sizeof(emp->em_sb));
87 brelse(bp, 0); 87 brelse(bp, 0);
88 88
89 /* validate the superblock */ 89 /* validate the superblock */
90 if (efs_sb_validate(&emp->em_sb, &why)) { 90 if (efs_sb_validate(&emp->em_sb, &why)) {
91 printf("efs: invalid superblock: %s\n", why); 91 printf("efs: invalid superblock: %s\n", why);
92 if (!(mp->mnt_flag & MNT_FORCE)) { 92 if (!(mp->mnt_flag & MNT_FORCE)) {
93 free(emp, M_EFSMNT); 93 free(emp, M_EFSMNT);
94 return (EIO); 94 return (EIO);
95 } 95 }
96 } 96 }
97 97
98 /* check that it's clean */ 98 /* check that it's clean */
99 if (be16toh(emp->em_sb.sb_dirty) != EFS_SB_CLEAN) { 99 if (be16toh(emp->em_sb.sb_dirty) != EFS_SB_CLEAN) {
100 printf("efs: filesystem is dirty (sb_dirty = 0x%x); please " 100 printf("efs: filesystem is dirty (sb_dirty = 0x%x); please "
101 "run fsck_efs(8)\n", be16toh(emp->em_sb.sb_dirty)); 101 "run fsck_efs(8)\n", be16toh(emp->em_sb.sb_dirty));
102 /* XXX - default to readonly unless forced?? */ 102 /* XXX - default to readonly unless forced?? */
103 } 103 }
104 104
105 /* if the superblock was replicated, verify that it is the same */ 105 /* if the superblock was replicated, verify that it is the same */
106 if (be32toh(emp->em_sb.sb_replsb) != 0) { 106 if (be32toh(emp->em_sb.sb_replsb) != 0) {
107 struct buf *rbp; 107 struct buf *rbp;
108 bool skip = false; 108 bool skip = false;
109 109
110 err = efs_bread(emp, be32toh(emp->em_sb.sb_replsb), l, &rbp); 110 err = efs_bread(emp, be32toh(emp->em_sb.sb_replsb), l, &rbp);
111 if (err) { 111 if (err) {
112 printf("efs: read of superblock replicant failed; " 112 printf("efs: read of superblock replicant failed; "
113 "please run fsck_efs(8)\n"); 113 "please run fsck_efs(8)\n");
114 if (mp->mnt_flag & MNT_FORCE) { 114 if (mp->mnt_flag & MNT_FORCE) {
115 skip = true; 115 skip = true;
116 } else { 116 } else {
117 free(emp, M_EFSMNT); 117 free(emp, M_EFSMNT);
118 brelse(rbp, 0); 118 brelse(rbp, 0);
119 return (err); 119 return (err);
120 } 120 }
121 } 121 }
122 122
123 if (!skip) { 123 if (!skip) {
124 if (memcmp(rbp->b_data, &emp->em_sb, 124 if (memcmp(rbp->b_data, &emp->em_sb,
125 sizeof(emp->em_sb))) { 125 sizeof(emp->em_sb))) {
126 printf("efs: superblock differs from " 126 printf("efs: superblock differs from "
127 "replicant; please run fsck_efs(8)\n"); 127 "replicant; please run fsck_efs(8)\n");
128 if (!(mp->mnt_flag & MNT_FORCE)) { 128 if (!(mp->mnt_flag & MNT_FORCE)) {
129 brelse(rbp, 0); 129 brelse(rbp, 0);
130 free(emp, M_EFSMNT); 130 free(emp, M_EFSMNT);
131 return (EIO); 131 return (EIO);
132 } 132 }
133 } 133 }
134 } 134 }
135 brelse(rbp, 0); 135 brelse(rbp, 0);
136 } 136 }
137 137
138 /* ensure we can read last block */ 138 /* ensure we can read last block */
139 err = efs_bread(emp, be32toh(emp->em_sb.sb_size) - 1, l, &bp); 139 err = efs_bread(emp, be32toh(emp->em_sb.sb_size) - 1, l, &bp);
140 if (err) { 140 if (err) {
141 printf("efs: cannot access all filesystem blocks; please run " 141 printf("efs: cannot access all filesystem blocks; please run "
142 "fsck_efs(8)\n"); 142 "fsck_efs(8)\n");
143 if (!(mp->mnt_flag & MNT_FORCE)) { 143 if (!(mp->mnt_flag & MNT_FORCE)) {
144 free(emp, M_EFSMNT); 144 free(emp, M_EFSMNT);
145 brelse(bp, 0); 145 brelse(bp, 0);
146 return (err); 146 return (err);
147 } 147 }
148 } 148 }
149 brelse(bp, 0); 149 brelse(bp, 0);
150 150
151 mp->mnt_data = emp; 151 mp->mnt_data = emp;
152 mp->mnt_flag |= MNT_LOCAL; 152 mp->mnt_flag |= MNT_LOCAL;
153 mp->mnt_fs_bshift = EFS_BB_SHFT; 153 mp->mnt_fs_bshift = EFS_BB_SHFT;
154 mp->mnt_dev_bshift = DEV_BSHIFT; 154 mp->mnt_dev_bshift = DEV_BSHIFT;
155 vfs_getnewfsid(mp); 155 vfs_getnewfsid(mp);
156 efs_statvfs(mp, &mp->mnt_stat); 156 efs_statvfs(mp, &mp->mnt_stat);
157 157
158 err = set_statvfs_info(path, UIO_USERSPACE, args->fspec, 158 err = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
159 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); 159 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
160 if (err) 160 if (err)
161 free(emp, M_EFSMNT); 161 free(emp, M_EFSMNT);
162 162
163 return (err); 163 return (err);
164} 164}
165 165
166/* 166/*
167 * mount syscall vfsop. 167 * mount syscall vfsop.
168 * 168 *
169 * Returns 0 on success. 169 * Returns 0 on success.
170 */ 170 */
171static int 171static int
172efs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 172efs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
173{ 173{
174 struct lwp *l = curlwp; 174 struct lwp *l = curlwp;
175 struct efs_args *args = data; 175 struct efs_args *args = data;
176 struct nameidata devndp; 176 struct nameidata devndp;
177 struct efs_mount *emp;  177 struct efs_mount *emp;
178 struct vnode *devvp; 178 struct vnode *devvp;
179 int err, mode; 179 int err, mode;
180 180
181 if (*data_len < sizeof *args) 181 if (*data_len < sizeof *args)
182 return EINVAL; 182 return EINVAL;
183 183
184 if (mp->mnt_flag & MNT_GETARGS) { 184 if (mp->mnt_flag & MNT_GETARGS) {
185 if ((emp = VFSTOEFS(mp)) == NULL) 185 if ((emp = VFSTOEFS(mp)) == NULL)
186 return (EIO); 186 return (EIO);
187 args->fspec = NULL; 187 args->fspec = NULL;
188 args->version = EFS_MNT_VERSION; 188 args->version = EFS_MNT_VERSION;
189 *data_len = sizeof *args; 189 *data_len = sizeof *args;
190 return 0; 190 return 0;
191 } 191 }
192 192
193 if (mp->mnt_flag & MNT_UPDATE) 193 if (mp->mnt_flag & MNT_UPDATE)
194 return (EOPNOTSUPP); /* XXX read-only */ 194 return (EOPNOTSUPP); /* XXX read-only */
195 195
196 /* look up our device's vnode. it is returned locked */ 196 /* look up our device's vnode. it is returned locked */
197 NDINIT(&devndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, args->fspec); 197 NDINIT(&devndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, args->fspec);
198 if ((err = namei(&devndp))) 198 if ((err = namei(&devndp)))
199 return (err); 199 return (err);
200 200
201 devvp = devndp.ni_vp; 201 devvp = devndp.ni_vp;
202 if (devvp->v_type != VBLK) { 202 if (devvp->v_type != VBLK) {
203 vput(devvp); 203 vput(devvp);
204 return (ENOTBLK); 204 return (ENOTBLK);
205 } 205 }
206 206
207 /* XXX - rdonly */ 207 /* XXX - rdonly */
208 mode = FREAD; 208 mode = FREAD;
209 209
210 /* 210 /*
211 * If mount by non-root, then verify that user has necessary 211 * If mount by non-root, then verify that user has necessary
212 * permissions on the device. 212 * permissions on the device.
213 */ 213 */
214 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) { 214 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
215 err = VOP_ACCESS(devvp, mode, l->l_cred); 215 err = VOP_ACCESS(devvp, mode, l->l_cred);
216 if (err) { 216 if (err) {
217 vput(devvp); 217 vput(devvp);
218 return (err); 218 return (err);
219 } 219 }
220 } 220 }
221 221
222 if ((err = VOP_OPEN(devvp, mode, l->l_cred))) { 222 if ((err = VOP_OPEN(devvp, mode, l->l_cred))) {
223 vput(devvp); 223 vput(devvp);
224 return (err); 224 return (err);
225 } 225 }
226 226
227 err = efs_mount_common(mp, path, devvp, args); 227 err = efs_mount_common(mp, path, devvp, args);
228 if (err) { 228 if (err) {
229 VOP_CLOSE(devvp, mode, l->l_cred); 229 VOP_CLOSE(devvp, mode, l->l_cred);
230 vput(devvp); 230 vput(devvp);
231 return (err); 231 return (err);
232 } 232 }
233 233
234 VOP_UNLOCK(devvp, 0); 234 VOP_UNLOCK(devvp, 0);
235 235
236 return (0); 236 return (0);
237} 237}
238 238
239/* 239/*
240 * Initialisation routine. 240 * Initialisation routine.
241 * 241 *
242 * Returns 0 on success. 242 * Returns 0 on success.
243 */ 243 */
244static int 244static int
245efs_start(struct mount *mp, int flags) 245efs_start(struct mount *mp, int flags)
246{ 246{
247 247
248 return (0); 248 return (0);
249} 249}
250 250
251/* 251/*
252 * unmount syscall vfsop.  252 * unmount syscall vfsop.
253 * 253 *
254 * Returns 0 on success. 254 * Returns 0 on success.
255 */ 255 */
256static int 256static int
257efs_unmount(struct mount *mp, int mntflags) 257efs_unmount(struct mount *mp, int mntflags)
258{ 258{
259 struct efs_mount *emp; 259 struct efs_mount *emp;
260 struct lwp *l = curlwp; 260 struct lwp *l = curlwp;
261 int err; 261 int err;
262 262
263 emp = VFSTOEFS(mp); 263 emp = VFSTOEFS(mp);
264 264
265 err = vflush(mp, NULL, (mntflags & MNT_FORCE) ? FORCECLOSE : 0); 265 err = vflush(mp, NULL, (mntflags & MNT_FORCE) ? FORCECLOSE : 0);
266 if (err) 266 if (err)
267 return (err); 267 return (err);
268 268
269 cache_purgevfs(mp); 269 cache_purgevfs(mp);
270 270
271 vn_lock(emp->em_devvp, LK_EXCLUSIVE | LK_RETRY); 271 vn_lock(emp->em_devvp, LK_EXCLUSIVE | LK_RETRY);
272 err = VOP_CLOSE(emp->em_devvp, FREAD, l->l_cred); 272 err = VOP_CLOSE(emp->em_devvp, FREAD, l->l_cred);
273 vput(emp->em_devvp); 273 vput(emp->em_devvp);
274 274
275 free(mp->mnt_data, M_EFSMNT); 275 free(mp->mnt_data, M_EFSMNT);
276 mp->mnt_data = NULL; 276 mp->mnt_data = NULL;
277 mp->mnt_flag &= ~MNT_LOCAL; 277 mp->mnt_flag &= ~MNT_LOCAL;
278 278
279 return (err); 279 return (err);
280} 280}
281 281
282/* 282/*
283 * Return the root vnode. 283 * Return the root vnode.
284 * 284 *
285 * Returns 0 on success. 285 * Returns 0 on success.
286 */ 286 */
287static int 287static int
288efs_root(struct mount *mp, struct vnode **vpp) 288efs_root(struct mount *mp, struct vnode **vpp)
289{ 289{
290 int err; 290 int err;
291 struct vnode *vp; 291 struct vnode *vp;
292  292
293 if ((err = VFS_VGET(mp, EFS_ROOTINO, &vp))) 293 if ((err = VFS_VGET(mp, EFS_ROOTINO, &vp)))
294 return (err); 294 return (err);
295 295
296 *vpp = vp; 296 *vpp = vp;
297 return (0); 297 return (0);
298} 298}
299 299
300/* 300/*
301 * statvfs syscall vfsop. 301 * statvfs syscall vfsop.
302 * 302 *
303 * Returns 0 on success. 303 * Returns 0 on success.
304 */ 304 */
305static int 305static int
306efs_statvfs(struct mount *mp, struct statvfs *sbp) 306efs_statvfs(struct mount *mp, struct statvfs *sbp)
307{ 307{
308 struct efs_mount *emp; 308 struct efs_mount *emp;
309  309
310 emp = VFSTOEFS(mp); 310 emp = VFSTOEFS(mp);
311 sbp->f_bsize = EFS_BB_SIZE; 311 sbp->f_bsize = EFS_BB_SIZE;
312 sbp->f_frsize = EFS_BB_SIZE; 312 sbp->f_frsize = EFS_BB_SIZE;
313 sbp->f_iosize = EFS_BB_SIZE; 313 sbp->f_iosize = EFS_BB_SIZE;
314 sbp->f_blocks = be32toh(emp->em_sb.sb_size); 314 sbp->f_blocks = be32toh(emp->em_sb.sb_size);
315 sbp->f_bfree = be32toh(emp->em_sb.sb_tfree); 315 sbp->f_bfree = be32toh(emp->em_sb.sb_tfree);
316 sbp->f_bavail = sbp->f_bfree; // XXX same??  316 sbp->f_bavail = sbp->f_bfree; // XXX same??
317 sbp->f_bresvd = 0; 317 sbp->f_bresvd = 0;
318 sbp->f_files = be32toh(emp->em_sb.sb_tinode); 318 sbp->f_files = be32toh(emp->em_sb.sb_tinode);
319 sbp->f_ffree = be16toh(emp->em_sb.sb_cgisize) * 319 sbp->f_ffree = be16toh(emp->em_sb.sb_cgisize) *
320 be16toh(emp->em_sb.sb_ncg) * 320 be16toh(emp->em_sb.sb_ncg) *
321 EFS_DINODES_PER_BB; 321 EFS_DINODES_PER_BB;
322 sbp->f_favail = sbp->f_ffree; // XXX same?? 322 sbp->f_favail = sbp->f_ffree; // XXX same??
323 sbp->f_fresvd = 0; 323 sbp->f_fresvd = 0;
324 sbp->f_namemax = EFS_DIRENT_NAMELEN_MAX; 324 sbp->f_namemax = EFS_DIRENT_NAMELEN_MAX;
325 copy_statvfs_info(sbp, mp); 325 copy_statvfs_info(sbp, mp);
326 326
327 return (0); 327 return (0);
328} 328}
329 329
330/* 330/*
331 * Obtain a locked vnode for the given on-disk inode number. 331 * Obtain a locked vnode for the given on-disk inode number.
332 * 332 *
333 * We currently allocate a new vnode from getnewnode(), tack it with 333 * We currently allocate a new vnode from getnewnode(), tack it with
334 * our in-core inode structure (efs_inode), and read in the inode from 334 * our in-core inode structure (efs_inode), and read in the inode from
335 * disk. The returned inode must be locked. 335 * disk. The returned inode must be locked.
336 * 336 *
337 * Returns 0 on success. 337 * Returns 0 on success.
338 */ 338 */
339static int 339static int
340efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 340efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
341{ 341{
342 int err; 342 int err;
343 struct vnode *vp; 343 struct vnode *vp;
344 struct efs_inode *eip; 344 struct efs_inode *eip;
345 struct efs_mount *emp; 345 struct efs_mount *emp;
346 346
347 emp = VFSTOEFS(mp); 347 emp = VFSTOEFS(mp);
348 348
349 while (true) { 349 while (true) {
350 *vpp = efs_ihashget(emp->em_dev, ino, LK_EXCLUSIVE); 350 *vpp = efs_ihashget(emp->em_dev, ino, LK_EXCLUSIVE);
351 if (*vpp != NULL) 351 if (*vpp != NULL)
352 return (0); 352 return (0);
353 353
354 err = getnewvnode(VT_EFS, mp, efs_vnodeop_p, &vp); 354 err = getnewvnode(VT_EFS, mp, efs_vnodeop_p, &vp);
355 if (err) 355 if (err)
356 return (err); 356 return (err);
357  357
358 eip = pool_get(&efs_inode_pool, PR_WAITOK); 358 eip = pool_get(&efs_inode_pool, PR_WAITOK);
359 359
360 /* 360 /*
361 * See if anybody has raced us here. If not, continue 361 * See if anybody has raced us here. If not, continue
362 * setting up the new inode, otherwise start over. 362 * setting up the new inode, otherwise start over.
363 */ 363 */
364 efs_ihashlock(); 364 efs_ihashlock();
365 365
366 if (efs_ihashget(emp->em_dev, ino, 0) == NULL) 366 if (efs_ihashget(emp->em_dev, ino, 0) == NULL)
367 break; 367 break;
368 368
369 efs_ihashunlock(); 369 efs_ihashunlock();
370 ungetnewvnode(vp); 370 ungetnewvnode(vp);
371 pool_put(&efs_inode_pool, eip); 371 pool_put(&efs_inode_pool, eip);
372 } 372 }
373 373
374 vp->v_vflag |= VV_LOCKSWORK; 374 vp->v_vflag |= VV_LOCKSWORK;
375 eip->ei_mode = 0; 375 eip->ei_mode = 0;
376 eip->ei_lockf = NULL; 376 eip->ei_lockf = NULL;
377 eip->ei_number = ino; 377 eip->ei_number = ino;
378 eip->ei_dev = emp->em_dev; 378 eip->ei_dev = emp->em_dev;
379 eip->ei_vp = vp; 379 eip->ei_vp = vp;
380 vp->v_data = eip; 380 vp->v_data = eip;
381 vp->v_mount = mp; 
382 381
383 /* 382 /*
384 * Place the vnode on the hash chain. Doing so will lock the 383 * Place the vnode on the hash chain. Doing so will lock the
385 * vnode, so it's okay to drop the global lock and read in 384 * vnode, so it's okay to drop the global lock and read in
386 * the inode from disk. 385 * the inode from disk.
387 */ 386 */
388 efs_ihashins(eip); 387 efs_ihashins(eip);
389 efs_ihashunlock(); 388 efs_ihashunlock();
390 389
391 /* 390 /*
392 * Init genfs early, otherwise we'll trip up on genfs_node_destroy 391 * Init genfs early, otherwise we'll trip up on genfs_node_destroy
393 * in efs_reclaim when vput()ing in an error branch here. 392 * in efs_reclaim when vput()ing in an error branch here.
394 */ 393 */
395 genfs_node_init(vp, &efs_genfsops); 394 genfs_node_init(vp, &efs_genfsops);
396 395
397 err = efs_read_inode(emp, ino, NULL, &eip->ei_di); 396 err = efs_read_inode(emp, ino, NULL, &eip->ei_di);
398 if (err) { 397 if (err) {
399 vput(vp); 398 vput(vp);
400 *vpp = NULL; 399 *vpp = NULL;
401 return (err); 400 return (err);
402 } 401 }
403 402
404 efs_sync_dinode_to_inode(eip); 403 efs_sync_dinode_to_inode(eip);
405 404
406 if (ino == EFS_ROOTINO && !S_ISDIR(eip->ei_mode)) { 405 if (ino == EFS_ROOTINO && !S_ISDIR(eip->ei_mode)) {
407 printf("efs: root inode (%lu) is not a directory!\n", 406 printf("efs: root inode (%lu) is not a directory!\n",
408 (ulong)EFS_ROOTINO); 407 (ulong)EFS_ROOTINO);
409 vput(vp); 408 vput(vp);
410 *vpp = NULL; 409 *vpp = NULL;
411 return (EIO); 410 return (EIO);
412 } 411 }
413 412
414 switch (eip->ei_mode & S_IFMT) { 413 switch (eip->ei_mode & S_IFMT) {
415 case S_IFIFO: 414 case S_IFIFO:
416 vp->v_type = VFIFO; 415 vp->v_type = VFIFO;
417 break; 416 break;
418 case S_IFCHR: 417 case S_IFCHR:
419 vp->v_type = VCHR; 418 vp->v_type = VCHR;
420 break; 419 break;
421 case S_IFDIR: 420 case S_IFDIR:
422 vp->v_type = VDIR; 421 vp->v_type = VDIR;
423 if (ino == EFS_ROOTINO) 422 if (ino == EFS_ROOTINO)
424 vp->v_vflag |= VV_ROOT; 423 vp->v_vflag |= VV_ROOT;
425 break; 424 break;
426 case S_IFBLK: 425 case S_IFBLK:
427 vp->v_type = VBLK; 426 vp->v_type = VBLK;
428 break; 427 break;
429 case S_IFREG: 428 case S_IFREG:
430 vp->v_type = VREG; 429 vp->v_type = VREG;
431 break; 430 break;
432 case S_IFLNK: 431 case S_IFLNK:
433 vp->v_type = VLNK; 432 vp->v_type = VLNK;
434 break; 433 break;
435 case S_IFSOCK: 434 case S_IFSOCK:
436 vp->v_type = VSOCK; 435 vp->v_type = VSOCK;
437 break; 436 break;
438 default: 437 default:
439 printf("efs: invalid mode 0x%x in inode %lu on mount %s\n", 438 printf("efs: invalid mode 0x%x in inode %lu on mount %s\n",
440 eip->ei_mode, (ulong)ino, mp->mnt_stat.f_mntonname); 439 eip->ei_mode, (ulong)ino, mp->mnt_stat.f_mntonname);
441 vput(vp); 440 vput(vp);
442 *vpp = NULL; 441 *vpp = NULL;
443 return (EIO); 442 return (EIO);
444 } 443 }
445 444
446 uvm_vnp_setsize(vp, eip->ei_size); 445 uvm_vnp_setsize(vp, eip->ei_size);
447 *vpp = vp; 446 *vpp = vp;
448 447
449 KASSERT(VOP_ISLOCKED(vp)); 448 KASSERT(VOP_ISLOCKED(vp));
450 449
451 return (0); 450 return (0);
452} 451}
453 452
454/* 453/*
455 * Convert the provided opaque, unique file handle into a vnode. 454 * Convert the provided opaque, unique file handle into a vnode.
456 * 455 *
457 * Returns 0 on success. 456 * Returns 0 on success.
458 */ 457 */
459static int 458static int
460efs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 459efs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
461{ 460{
462 int err; 461 int err;
463 struct vnode *vp; 462 struct vnode *vp;
464 struct efs_fid *efp; 463 struct efs_fid *efp;
465 struct efs_inode *eip; 464 struct efs_inode *eip;
466 465
467 if (fhp->fid_len != sizeof(struct efs_fid))  466 if (fhp->fid_len != sizeof(struct efs_fid))
468 return (EINVAL); 467 return (EINVAL);
469 468
470 efp = (struct efs_fid *)fhp; 469 efp = (struct efs_fid *)fhp;
471 470
472 if ((err = VFS_VGET(mp, efp->ef_ino, &vp))) { 471 if ((err = VFS_VGET(mp, efp->ef_ino, &vp))) {
473 *vpp = NULL; 472 *vpp = NULL;
474 return (err); 473 return (err);
475 } 474 }
476 475
477 eip = EFS_VTOI(vp); 476 eip = EFS_VTOI(vp);
478 if (eip->ei_mode == 0 || eip->ei_gen != efp->ef_gen) { 477 if (eip->ei_mode == 0 || eip->ei_gen != efp->ef_gen) {
479 vput(vp); 478 vput(vp);
480 *vpp = NULL; 479 *vpp = NULL;
481 return (ESTALE); 480 return (ESTALE);
482 } 481 }
483 482
484 *vpp = vp; 483 *vpp = vp;
485 return (0); 484 return (0);
486} 485}
487 486
488/* 487/*
489 * Convert the provided vnode into an opaque, unique file handle. 488 * Convert the provided vnode into an opaque, unique file handle.
490 * 489 *
491 * Returns 0 on success. 490 * Returns 0 on success.
492 */ 491 */
493static int 492static int
494efs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) 493efs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
495{ 494{
496 struct efs_fid *efp; 495 struct efs_fid *efp;
497 struct efs_inode *eip; 496 struct efs_inode *eip;
498 497
499 if (*fh_size < sizeof(struct efs_fid)) { 498 if (*fh_size < sizeof(struct efs_fid)) {
500 *fh_size = sizeof(struct efs_fid); 499 *fh_size = sizeof(struct efs_fid);
501 return (E2BIG); 500 return (E2BIG);
502 } 501 }
503 *fh_size = sizeof(struct efs_fid); 502 *fh_size = sizeof(struct efs_fid);
504 503
505 eip = EFS_VTOI(vp);  504 eip = EFS_VTOI(vp);
506 efp = (struct efs_fid *)fhp; 505 efp = (struct efs_fid *)fhp;
507 506
508 fhp->fid_len = sizeof(struct efs_fid); 507 fhp->fid_len = sizeof(struct efs_fid);
509 efp->ef_ino = eip->ei_number; 508 efp->ef_ino = eip->ei_number;
510 efp->ef_gen = eip->ei_gen; 509 efp->ef_gen = eip->ei_gen;
511 510
512 return (0); 511 return (0);
513} 512}
514 513
515/* 514/*
516 * Globally initialise the filesystem. 515 * Globally initialise the filesystem.
517 */ 516 */
518static void  517static void
519efs_init(void) 518efs_init(void)
520{ 519{
521 520
522 malloc_type_attach(M_EFSMNT); 521 malloc_type_attach(M_EFSMNT);
523 malloc_type_attach(M_EFSINO); 522 malloc_type_attach(M_EFSINO);
524 malloc_type_attach(M_EFSTMP); 523 malloc_type_attach(M_EFSTMP);
525 efs_ihashinit(); 524 efs_ihashinit();
526 pool_init(&efs_inode_pool, sizeof(struct efs_inode), 0, 0, 0, 525 pool_init(&efs_inode_pool, sizeof(struct efs_inode), 0, 0, 0,
527 "efsinopl", &pool_allocator_nointr, IPL_NONE); 526 "efsinopl", &pool_allocator_nointr, IPL_NONE);
528} 527}
529 528
530/* 529/*
531 * Globally reinitialise the filesystem. 530 * Globally reinitialise the filesystem.
532 */ 531 */
533static void  532static void
534efs_reinit(void) 533efs_reinit(void)
535{ 534{
536  535
537 efs_ihashreinit(); 536 efs_ihashreinit();
538} 537}
539 538
540/* 539/*
541 * Globally clean up the filesystem. 540 * Globally clean up the filesystem.
542 */ 541 */
543static void  542static void
544efs_done(void) 543efs_done(void)
545{ 544{
546  545
547 pool_destroy(&efs_inode_pool); 546 pool_destroy(&efs_inode_pool);
548 efs_ihashdone(); 547 efs_ihashdone();
549 malloc_type_detach(M_EFSMNT); 548 malloc_type_detach(M_EFSMNT);
550 malloc_type_detach(M_EFSINO); 549 malloc_type_detach(M_EFSINO);
551 malloc_type_detach(M_EFSTMP); 550 malloc_type_detach(M_EFSTMP);
552} 551}
553 552
554extern const struct vnodeopv_desc efs_vnodeop_opv_desc; 553extern const struct vnodeopv_desc efs_vnodeop_opv_desc;
555//extern const struct vnodeopv_desc efs_specop_opv_desc; 554//extern const struct vnodeopv_desc efs_specop_opv_desc;
556//extern const struct vnodeopv_desc efs_fifoop_opv_desc; 555//extern const struct vnodeopv_desc efs_fifoop_opv_desc;
557 556
558const struct vnodeopv_desc * const efs_vnodeopv_descs[] = { 557const struct vnodeopv_desc * const efs_vnodeopv_descs[] = {
559 &efs_vnodeop_opv_desc, 558 &efs_vnodeop_opv_desc,
560// &efs_specop_opv_desc, 559// &efs_specop_opv_desc,
561// &efs_fifoop_opv_desc, 560// &efs_fifoop_opv_desc,
562 NULL 561 NULL
563}; 562};
564 563
565struct vfsops efs_vfsops = { 564struct vfsops efs_vfsops = {
566 .vfs_name = MOUNT_EFS, 565 .vfs_name = MOUNT_EFS,
567 .vfs_min_mount_data = sizeof (struct efs_args), 566 .vfs_min_mount_data = sizeof (struct efs_args),
568 .vfs_mount = efs_mount, 567 .vfs_mount = efs_mount,
569 .vfs_start = efs_start, 568 .vfs_start = efs_start,
570 .vfs_unmount = efs_unmount, 569 .vfs_unmount = efs_unmount,
571 .vfs_root = efs_root, 570 .vfs_root = efs_root,
572 .vfs_quotactl = (void *)eopnotsupp, 571 .vfs_quotactl = (void *)eopnotsupp,
573 .vfs_statvfs = efs_statvfs, 572 .vfs_statvfs = efs_statvfs,
574 .vfs_sync = (void *)nullop, 573 .vfs_sync = (void *)nullop,
575 .vfs_vget = efs_vget, 574 .vfs_vget = efs_vget,
576 .vfs_fhtovp = efs_fhtovp, 575 .vfs_fhtovp = efs_fhtovp,
577 .vfs_vptofh = efs_vptofh, 576 .vfs_vptofh = efs_vptofh,
578 .vfs_init = efs_init, 577 .vfs_init = efs_init,
579 .vfs_reinit = efs_reinit, 578 .vfs_reinit = efs_reinit,
580 .vfs_done = efs_done, 579 .vfs_done = efs_done,
581 .vfs_mountroot = (void *)eopnotsupp, 580 .vfs_mountroot = (void *)eopnotsupp,
582 .vfs_snapshot = (void *)eopnotsupp, 581 .vfs_snapshot = (void *)eopnotsupp,
583 .vfs_extattrctl = vfs_stdextattrctl, 582 .vfs_extattrctl = vfs_stdextattrctl,
584 .vfs_suspendctl = (void *)eopnotsupp, 583 .vfs_suspendctl = (void *)eopnotsupp,
585 .vfs_opv_descs = efs_vnodeopv_descs 584 .vfs_opv_descs = efs_vnodeopv_descs
586/* .vfs_refcount */ 585/* .vfs_refcount */
587/* .vfs_list */ 586/* .vfs_list */
588}; 587};
589 588
590static int 589static int
591efs_modcmd(modcmd_t cmd, void *arg) 590efs_modcmd(modcmd_t cmd, void *arg)
592{ 591{
593 592
594 switch (cmd) { 593 switch (cmd) {
595 case MODULE_CMD_INIT: 594 case MODULE_CMD_INIT:
596 return vfs_attach(&efs_vfsops); 595 return vfs_attach(&efs_vfsops);
597 case MODULE_CMD_FINI: 596 case MODULE_CMD_FINI:
598 return vfs_detach(&efs_vfsops); 597 return vfs_detach(&efs_vfsops);
599 default: 598 default:
600 return ENOTTY; 599 return ENOTTY;
601 } 600 }
602} 601}