View | Details | Raw Unified | Return to bug 248528 | Differences between
and this patch

Collapse All | Expand All

(-)src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vnops.c (-129 / +1235 lines)
Lines 1-10 Link Here
1
/* $Id: vboxvfs_vnops.c $ */
2
/** @file
3
 * Description.
4
 */
5
6
/*
1
/*
7
 * Copyright (C) 2008-2017 Oracle Corporation
2
 * Copyright (C) 2008-2017 Oracle Corporation
3
 * Copyright (C) 2017 Mahdi Mokhtari
8
 *
4
 *
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
5
 * This file is part of VirtualBox Open Source Edition (OSE), as
10
 * available from http://www.virtualbox.org. This file is free software;
6
 * available from http://www.virtualbox.org. This file is free software;
Lines 14-241 Link Here
14
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16
 */
12
 */
17
18
#include "vboxvfs.h"
19
#include <sys/param.h>
13
#include <sys/param.h>
20
#include <sys/systm.h>
14
#include <sys/systm.h>
21
#include <sys/namei.h>
15
#include <sys/namei.h>
22
#include <sys/kernel.h>
16
#include <sys/kernel.h>
23
#include <sys/proc.h>
17
#include <sys/types.h>
18
#include <sys/malloc.h>
19
#include <sys/stat.h>
24
#include <sys/bio.h>
20
#include <sys/bio.h>
21
#include <sys/conf.h>
25
#include <sys/buf.h>
22
#include <sys/buf.h>
26
#include <sys/fcntl.h>
23
#include <sys/iconv.h>
27
#include <sys/mount.h>
24
#include <sys/mount.h>
28
#include <sys/unistd.h>
29
#include <sys/vnode.h>
25
#include <sys/vnode.h>
30
#include <sys/limits.h>
26
#include <sys/dirent.h>
31
#include <sys/lockf.h>
27
#include <sys/queue.h>
32
#include <sys/stat.h>
28
#include <sys/unistd.h>
29
#include <sys/endian.h>
33
30
34
#include <vm/vm.h>
31
#include <vm/uma.h>
35
#include <vm/vm_extern.h>
36
32
33
#include "vboxvfs.h"
34
35
#if __FreeBSD_version < 1300063
36
#define	VN_IS_DOOMED(vp)	 (((vp)->v_iflag & VI_DOOMED) != 0)
37
#endif
38
37
/*
39
/*
38
 * Prototypes for VBOXVFS vnode operations
40
 * Prototypes for VBOXVFS vnode operations
39
 */
41
 */
40
static vop_create_t     vboxvfs_create;
42
static vop_create_t	vboxfs_create;
41
static vop_mknod_t      vboxvfs_mknod;
43
static vop_open_t	vboxfs_open;
42
static vop_open_t       vboxvfs_open;
44
static vop_close_t	vboxfs_close;
43
static vop_close_t      vboxvfs_close;
45
static vop_access_t	vboxfs_access;
44
static vop_access_t     vboxvfs_access;
46
static vop_getattr_t	vboxfs_getattr;
45
static vop_getattr_t    vboxvfs_getattr;
47
static vop_setattr_t	vboxfs_setattr;
46
static vop_setattr_t    vboxvfs_setattr;
48
static vop_read_t	vboxfs_read;
47
static vop_read_t       vboxvfs_read;
49
static vop_readlink_t	vboxfs_readlink;
48
static vop_write_t      vboxvfs_write;
50
static vop_write_t	vboxfs_write;
49
static vop_fsync_t      vboxvfs_fsync;
51
static vop_fsync_t	vboxfs_fsync;
50
static vop_remove_t     vboxvfs_remove;
52
static vop_remove_t	vboxfs_remove;
51
static vop_link_t       vboxvfs_link;
53
static vop_link_t	vboxfs_link;
52
static vop_lookup_t     vboxvfs_lookup;
54
static vop_cachedlookup_t	vboxfs_lookup;
53
static vop_rename_t     vboxvfs_rename;
55
static vop_rename_t	vboxfs_rename;
54
static vop_mkdir_t      vboxvfs_mkdir;
56
static vop_mkdir_t	vboxfs_mkdir;
55
static vop_rmdir_t      vboxvfs_rmdir;
57
static vop_rmdir_t	vboxfs_rmdir;
56
static vop_symlink_t    vboxvfs_symlink;
58
static vop_symlink_t	vboxfs_symlink;
57
static vop_readdir_t    vboxvfs_readdir;
59
static vop_readdir_t	vboxfs_readdir;
58
static vop_strategy_t   vboxvfs_strategy;
60
static vop_print_t	vboxfs_print;
59
static vop_print_t      vboxvfs_print;
61
static vop_pathconf_t	vboxfs_pathconf;
60
static vop_pathconf_t   vboxvfs_pathconf;
62
static vop_advlock_t	vboxfs_advlock;
61
static vop_advlock_t    vboxvfs_advlock;
63
static vop_ioctl_t	vboxfs_ioctl;
62
static vop_getextattr_t vboxvfs_getextattr;
64
static vop_inactive_t	vboxfs_inactive;
63
static vop_ioctl_t      vboxvfs_ioctl;
65
static vop_reclaim_t	vboxfs_reclaim;
64
static vop_getpages_t   vboxvfs_getpages;
66
static vop_vptofh_t	vboxfs_vptofh;
65
static vop_inactive_t   vboxvfs_inactive;
66
static vop_putpages_t   vboxvfs_putpages;
67
static vop_reclaim_t    vboxvfs_reclaim;
68
67
69
struct vop_vector vboxvfs_vnodeops = {
68
struct vop_vector vboxfs_vnodeops = {
70
    .vop_default    =   &default_vnodeops,
69
	.vop_default	= &default_vnodeops,
71
70
72
    .vop_access     =   vboxvfs_access,
71
	.vop_access	= vboxfs_access,
73
    .vop_advlock    =   vboxvfs_advlock,
72
	.vop_advlock	= VOP_EOPNOTSUPP,
74
    .vop_close      =   vboxvfs_close,
73
	.vop_close	= vboxfs_close,
75
    .vop_create     =   vboxvfs_create,
74
	.vop_create	= vboxfs_create,
76
    .vop_fsync      =   vboxvfs_fsync,
75
	.vop_fsync	= vboxfs_fsync,
77
    .vop_getattr    =   vboxvfs_getattr,
76
	.vop_getattr	= vboxfs_getattr,
78
    .vop_getextattr =   vboxvfs_getextattr,
77
	.vop_getextattr = VOP_EOPNOTSUPP,
79
    .vop_getpages   =   vboxvfs_getpages,
78
	.vop_inactive	= vboxfs_inactive,
80
    .vop_inactive   =   vboxvfs_inactive,
79
	.vop_ioctl	= vboxfs_ioctl,
81
    .vop_ioctl      =   vboxvfs_ioctl,
80
	.vop_link	= vboxfs_link,
82
    .vop_link       =   vboxvfs_link,
81
	.vop_lookup	= vfs_cache_lookup,
83
    .vop_lookup     =   vboxvfs_lookup,
82
	.vop_cachedlookup	= vboxfs_lookup,
84
    .vop_mkdir      =   vboxvfs_mkdir,
83
	.vop_mkdir	= vboxfs_mkdir,
85
    .vop_mknod      =   vboxvfs_mknod,
84
	.vop_mknod	= VOP_EOPNOTSUPP,
86
    .vop_open       =   vboxvfs_open,
85
	.vop_open	= vboxfs_open,
87
    .vop_pathconf   =   vboxvfs_pathconf,
86
	.vop_pathconf	= vboxfs_pathconf,
88
    .vop_print      =   vboxvfs_print,
87
	.vop_print	= vboxfs_print,
89
    .vop_putpages   =   vboxvfs_putpages,
88
	.vop_read	= vboxfs_read,
90
    .vop_read       =   vboxvfs_read,
89
	.vop_readdir	= vboxfs_readdir,
91
    .vop_readdir    =   vboxvfs_readdir,
90
	.vop_readlink	= vboxfs_readlink,
92
    .vop_reclaim    =   vboxvfs_reclaim,
91
	.vop_reclaim	= vboxfs_reclaim,
93
    .vop_remove     =   vboxvfs_remove,
92
	.vop_remove	= vboxfs_remove,
94
    .vop_rename     =   vboxvfs_rename,
93
	.vop_rename	= vboxfs_rename,
95
    .vop_rmdir      =   vboxvfs_rmdir,
94
	.vop_rmdir	= vboxfs_rmdir,
96
    .vop_setattr    =   vboxvfs_setattr,
95
	.vop_setattr	= vboxfs_setattr,
97
    .vop_strategy   =   vboxvfs_strategy,
96
	.vop_vptofh 	= vboxfs_vptofh,
98
    .vop_symlink    =   vboxvfs_symlink,
97
	.vop_symlink	= vboxfs_symlink,
99
    .vop_write      =   vboxvfs_write,
98
	.vop_write	= vboxfs_write,
99
	.vop_bmap	= VOP_EOPNOTSUPP
100
};
100
};
101
101
102
static int vboxvfs_access(struct vop_access_args *ap)
102
static uint64_t
103
vsfnode_cur_time_usec(void)
103
{
104
{
104
    return 0;
105
	struct timeval now;
106
107
	getmicrotime(&now);
108
109
	return (now.tv_sec*1000 + now.tv_usec);
105
}
110
}
106
111
107
static int vboxvfs_open(struct vop_open_args *ap)
112
static int
113
vsfnode_stat_cached(struct vboxfs_node *np)
108
{
114
{
109
    return 0;
115
	return (vsfnode_cur_time_usec() - np->sf_stat_time) <
116
	    np->vboxfsmp->sf_stat_ttl * 1000UL;
110
}
117
}
111
118
112
static int vboxvfs_close(struct vop_close_args *ap)
119
static int
120
vsfnode_update_stat_cache(struct vboxfs_node *np)
113
{
121
{
114
    return 0;
122
	int error;
123
124
	error = sfprov_get_attr(np->vboxfsmp->sf_handle, np->sf_path,
125
	    &np->sf_stat);
126
#if 0
127
	if (error == ENOENT)
128
		sfnode_make_stale(node);
129
#endif
130
	if (error == 0)
131
		np->sf_stat_time = vsfnode_cur_time_usec();
132
133
	return (error);
115
}
134
}
116
135
117
static int vboxvfs_getattr(struct vop_getattr_args *ap)
136
/*
137
 * Need to clear v_object for insmntque failure.
138
 */
139
static void
140
vboxfs_insmntque_dtr(struct vnode *vp, void *dtr_arg)
118
{
141
{
119
    return 0;
142
143
	// XXX: vboxfs_destroy_vobject(vp, vp->v_object);
144
	vp->v_object = NULL;
145
	vp->v_data = NULL;
146
	vp->v_op = &dead_vnodeops;
147
	vgone(vp);
148
	vput(vp);
120
}
149
}
121
150
122
static int vboxvfs_setattr(struct vop_setattr_args *ap)
151
/*
152
 * Allocates a new vnode for the node node or returns a new reference to
153
 * an existing one if the node had already a vnode referencing it.  The
154
 * resulting locked vnode is returned in *vpp.
155
 *
156
 * Returns zero on success or an appropriate error code on failure.
157
 */
158
int
159
vboxfs_alloc_vp(struct mount *mp, struct vboxfs_node *node, int lkflag,
160
    struct vnode **vpp)
123
{
161
{
124
    return 0;
162
	struct vnode *vp;
163
	int error;
164
165
	error = 0;
166
loop:
167
	VBOXFS_NODE_LOCK(node);
168
loop1:
169
	if ((vp = node->sf_vnode) != NULL) {
170
		MPASS((node->sf_vpstate & VBOXFS_VNODE_DOOMED) == 0);
171
		VI_LOCK(vp);
172
		if ((node->sf_type == VDIR && node->sf_parent == NULL) ||
173
		    (VN_IS_DOOMED(vp) &&
174
		    (lkflag & LK_NOWAIT) != 0)) {
175
			VI_UNLOCK(vp);
176
			VBOXFS_NODE_UNLOCK(node);
177
			error = ENOENT;
178
			vp = NULL;
179
			goto out;
180
		}
181
		if (VN_IS_DOOMED(vp)) {
182
			VI_UNLOCK(vp);
183
			node->sf_vpstate |= VBOXFS_VNODE_WRECLAIM;
184
			while ((node->sf_vpstate & VBOXFS_VNODE_WRECLAIM) != 0) {
185
				msleep(&node->sf_vnode, VBOXFS_NODE_MTX(node),
186
				    0, "vsfE", 0);
187
			}
188
			goto loop1;
189
		}
190
		VBOXFS_NODE_UNLOCK(node);
191
		error = vget(vp, lkflag | LK_INTERLOCK, curthread);
192
		if (error == ENOENT)
193
			goto loop;
194
		if (error != 0) {
195
			vp = NULL;
196
			goto out;
197
		}
198
199
		/*
200
		 * Make sure the vnode is still there after
201
		 * getting the interlock to avoid racing a free.
202
		 */
203
		if (node->sf_vnode == NULL || node->sf_vnode != vp) {
204
			vput(vp);
205
			goto loop;
206
		}
207
208
		goto out;
209
	}
210
211
	if ((node->sf_vpstate & VBOXFS_VNODE_DOOMED) ||
212
	    (node->sf_type == VDIR && node->sf_parent == NULL)) {
213
		VBOXFS_NODE_UNLOCK(node);
214
		error = ENOENT;
215
		vp = NULL;
216
		goto out;
217
	}
218
219
	/*
220
	 * otherwise lock the vp list while we call getnewvnode
221
	 * since that can block.
222
	 */
223
	if (node->sf_vpstate & VBOXFS_VNODE_ALLOCATING) {
224
		node->sf_vpstate |= VBOXFS_VNODE_WANT;
225
		error = msleep((caddr_t) &node->sf_vpstate,
226
		    VBOXFS_NODE_MTX(node), PDROP | PCATCH,
227
		    "vboxfs_alloc_vp", 0);
228
		if (error)
229
			return error;
230
231
		goto loop;
232
	} else
233
		node->sf_vpstate |= VBOXFS_VNODE_ALLOCATING;
234
235
	VBOXFS_NODE_UNLOCK(node);
236
237
	/* Get a new vnode and associate it with our node. */
238
	error = getnewvnode("vboxfs", mp, &vboxfs_vnodeops, &vp);
239
	if (error != 0)
240
		goto unlock;
241
	MPASS(vp != NULL);
242
243
	/* lkflag is ignored, the lock is exclusive */
244
	(void) vn_lock(vp, lkflag | LK_RETRY);
245
246
	vp->v_data = node;
247
	vp->v_type = node->sf_type;
248
249
	/* Type-specific initialization. */
250
	switch (node->sf_type) {
251
	case VBLK:
252
		/* FALLTHROUGH */
253
	case VCHR:
254
		/* FALLTHROUGH */
255
	case VLNK:
256
		/* FALLTHROUGH */
257
	case VSOCK:
258
		/* FALLTHROUGH */
259
	case VFIFO:
260
		/* FALLTHROUGH */
261
	case VREG:
262
		break;
263
	case VDIR:
264
		MPASS(node->sf_parent != NULL);
265
		if (node->sf_parent == node)
266
			vp->v_vflag |= VV_ROOT;
267
		break;
268
269
	default:
270
		panic("vboxfs_alloc_vp: type %p %d", node, (int)node->sf_type);
271
	}
272
273
	if (vp->v_type != VFIFO)
274
		VN_LOCK_ASHARE(vp);
275
276
	error = insmntque1(vp, mp, vboxfs_insmntque_dtr, NULL);
277
	if (error)
278
		vp = NULL;
279
280
unlock:
281
	VBOXFS_NODE_LOCK(node);
282
283
	MPASS(node->sf_vpstate & VBOXFS_VNODE_ALLOCATING);
284
	node->sf_vpstate &= ~VBOXFS_VNODE_ALLOCATING;
285
	node->sf_vnode = vp;
286
287
	if (node->sf_vpstate & VBOXFS_VNODE_WANT) {
288
		node->sf_vpstate &= ~VBOXFS_VNODE_WANT;
289
		VBOXFS_NODE_UNLOCK(node);
290
		wakeup((caddr_t) &node->sf_vpstate);
291
	} else
292
		VBOXFS_NODE_UNLOCK(node);
293
294
out:
295
	*vpp = vp;
296
297
#ifdef INVARIANTS
298
	if (error == 0) {
299
		MPASS(*vpp != NULL && VOP_ISLOCKED(*vpp));
300
		VBOXFS_NODE_LOCK(node);
301
		MPASS(*vpp == node->sf_vnode);
302
		VBOXFS_NODE_UNLOCK(node);
303
	}
304
#endif
305
306
	return error;
125
}
307
}
126
308
127
static int vboxvfs_read(struct vop_read_args *ap)
309
/*
310
 * Destroys the association between the vnode vp and the node it
311
 * references.
312
 */
313
void
314
vboxfs_free_vp(struct vnode *vp)
128
{
315
{
129
    return 0;
316
	struct vboxfs_node *node;
317
318
	node = VP_TO_VBOXFS_NODE(vp);
319
320
	VBOXFS_NODE_ASSERT_LOCKED(node);
321
	node->sf_vnode = NULL;
322
	if ((node->sf_vpstate & VBOXFS_VNODE_WRECLAIM) != 0)
323
		wakeup(&node->sf_vnode);
324
	node->sf_vpstate &= ~VBOXFS_VNODE_WRECLAIM;
325
	vp->v_data = NULL;
130
}
326
}
131
327
132
static int vboxvfs_write(struct vop_write_args *ap)
328
/*
329
 * Allocate new vboxfs_node and vnode for given file
330
 */
331
static int
332
vboxfs_alloc_file(struct vboxfs_mnt *vboxfsmp, const char *fullpath,
333
    enum vtype type, mode_t mode, struct vboxfs_node *parent,
334
    int lkflag, struct vnode **vpp)
133
{
335
{
134
    return 0;
336
	int error;
337
	struct vboxfs_node *unode;
338
339
	error = vboxfs_alloc_node(vboxfsmp->sf_vfsp, vboxfsmp, fullpath, type,
340
	    vboxfsmp->sf_uid, vboxfsmp->sf_gid, mode, parent, &unode);
341
342
	if (error)
343
		goto out;
344
345
	error = vboxfs_alloc_vp(vboxfsmp->sf_vfsp, unode, lkflag, vpp);
346
	if (error)
347
		vboxfs_free_node(vboxfsmp, unode);
348
349
out:
350
	return (error);
135
}
351
}
136
352
137
static int vboxvfs_create(struct vop_create_args *ap)
353
static int
354
vboxfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
355
    struct vnode **rvp)
138
{
356
{
139
    return 0;
357
358
	return (vboxfs_alloc_vp(mp, arg, lkflags, rvp));
140
}
359
}
141
360
142
static int vboxvfs_remove(struct vop_remove_args *ap)
361
/*
362
 * Construct a new pathname given an sfnode plus an optional tail
363
 * component of length len
364
 * This handles ".." and "."
365
 */
366
static char *
367
sfnode_construct_path(struct vboxfs_node *node, char *tail, int len)
143
{
368
{
144
    return 0;
369
	char *p;
370
371
	if (len <= 2 && tail[0] == '.' && (len == 1 || tail[1] == '.'))
372
		panic("construct path for %s", tail);
373
	p = malloc(strlen(node->sf_path) + 1 + len + 1, M_VBOXVFS, M_WAITOK);
374
	strcpy(p, node->sf_path);
375
	strcat(p, "/");
376
	strcat(p, tail);
377
	return (p);
145
}
378
}
146
379
147
static int vboxvfs_rename(struct vop_rename_args *ap)
380
static int
381
vboxfs_access(struct vop_access_args *ap)
148
{
382
{
149
    return 0;
383
	struct vnode *vp = ap->a_vp;
384
	accmode_t accmode = ap->a_accmode;
385
	struct vboxfs_node *node;
386
	int error;
387
	mode_t m;
388
389
	MPASS(VOP_ISLOCKED(vp));
390
391
	node = VP_TO_VBOXFS_NODE(vp);
392
393
	if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
394
		switch (vp->v_type) {
395
		case VDIR:
396
		case VLNK:
397
		case VREG:
398
			return (EROFS);
399
			/* NOT REACHED */
400
		default:
401
			break;
402
		}
403
	}
404
405
	if (vsfnode_stat_cached(node))
406
		error = 0;
407
	else
408
		error = vsfnode_update_stat_cache(node);
409
	m = (error == 0) ? node->sf_stat.sf_mode : 0;
410
411
	return (vaccess(vp->v_type, m, node->vboxfsmp->sf_uid,
412
	    node->vboxfsmp->sf_gid, accmode, ap->a_cred));
150
}
413
}
151
414
152
static int vboxvfs_link(struct vop_link_args *ap)
415
/*
416
 * Clears the (cached) directory listing for the node.
417
 */
418
static void
419
vfsnode_clear_dir_list(struct vboxfs_node *np)
153
{
420
{
154
    return EOPNOTSUPP;
421
	while (np->sf_dir_list != NULL) {
422
		sffs_dirents_t *next = np->sf_dir_list->sf_next;
423
		free(np->sf_dir_list, M_VBOXVFS);
424
		np->sf_dir_list = next;
425
	}
155
}
426
}
156
427
157
static int vboxvfs_symlink(struct vop_symlink_args *ap)
428
static int
429
vboxfs_open(struct vop_open_args *ap)
158
{
430
{
159
    return EOPNOTSUPP;
431
	struct vboxfs_node *np;
432
	sfp_file_t *fp;
433
	int error;
434
435
	MPASS(VOP_ISLOCKED(vp));
436
437
	np = VP_TO_VBOXFS_NODE(ap->a_vp);
438
	error = sfprov_open(np->vboxfsmp->sf_handle, np->sf_path, &fp);
439
	if (error != 0)
440
		goto out;
441
442
	np->sf_file = fp;
443
	vnode_create_vobject(ap->a_vp, 0, ap->a_td);
444
445
out:
446
	MPASS(VOP_ISLOCKED(vp));
447
448
	return (error);
160
}
449
}
161
450
162
static int vboxvfs_mknod(struct vop_mknod_args *ap)
451
static void
452
vfsnode_invalidate_stat_cache(struct vboxfs_node *np)
163
{
453
{
164
    return EOPNOTSUPP;
454
	np->sf_stat_time = 0;
165
}
455
}
166
456
167
static int vboxvfs_mkdir(struct vop_mkdir_args *ap)
457
static int
458
vboxfs_close(struct vop_close_args *ap)
168
{
459
{
169
    return 0;
460
	struct vnode *vp = ap->a_vp;
461
	struct vboxfs_node *np;
462
463
	np = VP_TO_VBOXFS_NODE(vp);
464
465
	/*
466
	 * Free the directory entries for the node. We do this on this call
467
	 * here because the directory node may not become inactive for a long
468
	 * time after the readdir is over. Case in point, if somebody cd's into
469
	 * the directory then it won't become inactive until they cd away again.
470
	 * In such a case we would end up with the directory listing not getting
471
	 * updated (i.e. the result of 'ls' always being the same) until they
472
	 * change the working directory.
473
	 */
474
	vfsnode_clear_dir_list(np);
475
476
	vfsnode_invalidate_stat_cache(np);
477
478
	if (np->sf_file != NULL && vp->v_usecount <= 1) {
479
		(void) sfprov_close(np->sf_file);
480
		np->sf_file = NULL;
481
	}
482
483
	return (0);
170
}
484
}
171
485
172
static int vboxvfs_rmdir(struct vop_rmdir_args *ap)
486
static int
487
vboxfs_getattr(struct vop_getattr_args *ap)
173
{
488
{
174
    return 0;
489
	struct vnode 		*vp = ap->a_vp;
490
	struct vattr 		*vap = ap->a_vap;
491
	struct vboxfs_node	*np = VP_TO_VBOXFS_NODE(vp);
492
	struct vboxfs_mnt  	*mp = np->vboxfsmp;
493
	mode_t			mode;
494
	int			error = 0;
495
496
	mode = 0;
497
	vap->va_type = vp->v_type;
498
499
	vap->va_nlink = 1;		/* number of references to file */
500
	vap->va_uid = mp->sf_uid;	/* owner user id */
501
	vap->va_gid = mp->sf_gid;	/* owner group id */
502
	vap->va_rdev = NODEV;		/* device the special file represents */
503
	vap->va_gen = VNOVAL;		/* generation number of file */
504
	vap->va_flags = 0;		/* flags defined for file */
505
	vap->va_filerev = 0;		/* file modification number */
506
	vap->va_vaflags = 0;		/* operations flags */
507
	vap->va_fileid = np->sf_ino;	/* file id */
508
	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
509
	if (vap->va_fileid == 0)
510
		vap->va_fileid = 2;
511
512
	vap->va_atime.tv_sec = VNOVAL;
513
	vap->va_atime.tv_nsec = VNOVAL;
514
	vap->va_mtime.tv_sec = VNOVAL;
515
	vap->va_mtime.tv_nsec = VNOVAL;
516
	vap->va_ctime.tv_sec = VNOVAL;
517
	vap->va_ctime.tv_nsec = VNOVAL;
518
519
	if (!vsfnode_stat_cached(np)) {
520
		error = vsfnode_update_stat_cache(np);
521
		if (error != 0)
522
			goto done;
523
	}
524
525
	vap->va_atime = np->sf_stat.sf_atime;
526
	vap->va_mtime = np->sf_stat.sf_mtime;
527
	vap->va_ctime = np->sf_stat.sf_ctime;
528
529
	mode = np->sf_stat.sf_mode;
530
531
	vap->va_mode = mode;
532
	if (S_ISDIR(mode)) {
533
		vap->va_type = VDIR;	/* vnode type (for create) */
534
		vap->va_mode = mp->sf_dmode != 0 ? (mp->sf_dmode & 0777) : vap->va_mode;
535
		vap->va_mode &= ~mp->sf_dmask;
536
		vap->va_mode |= S_IFDIR;
537
	} else if (S_ISREG(mode)) {
538
		vap->va_type = VREG;
539
		vap->va_mode = mp->sf_fmode != 0 ? (mp->sf_fmode & 0777) : vap->va_mode;
540
		vap->va_mode &= ~mp->sf_fmask;
541
		vap->va_mode |= S_IFREG;
542
	} else if (S_ISFIFO(mode))
543
		vap->va_type = VFIFO;
544
	else if (S_ISCHR(mode))
545
		vap->va_type = VCHR;
546
	else if (S_ISBLK(mode))
547
		vap->va_type = VBLK;
548
	else if (S_ISLNK(mode)) {
549
		vap->va_type = VLNK;
550
		vap->va_mode = mp->sf_fmode != 0 ? (mp->sf_fmode & 0777) : vap->va_mode;
551
		vap->va_mode &= ~mp->sf_fmask;
552
		vap->va_mode |= S_IFLNK;
553
	} else if (S_ISSOCK(mode))
554
		vap->va_type = VSOCK;
555
556
	vap->va_size = np->sf_stat.sf_size;
557
	vap->va_blocksize = 512;
558
	/* bytes of disk space held by file */
559
   	vap->va_bytes = (np->sf_stat.sf_alloc + 511) / 512;
560
561
done:
562
	return (error);
175
}
563
}
176
564
177
static int vboxvfs_readdir(struct vop_readdir_args *ap)
565
static int
566
vboxfs_setattr(struct vop_setattr_args *ap)
178
{
567
{
179
    return 0;
568
	struct vnode 		*vp = ap->a_vp;
569
	struct vattr 		*vap = ap->a_vap;
570
	struct vboxfs_node	*np = VP_TO_VBOXFS_NODE(vp);
571
	int			error;
572
	mode_t			mode;
573
574
	mode = vap->va_mode;
575
	if (vp->v_type == VREG)
576
		mode |= S_IFREG;
577
	else if (vp->v_type == VDIR)
578
		mode |= S_IFDIR;
579
	else if (vp->v_type == VBLK)
580
		mode |= S_IFBLK;
581
	else if (vp->v_type == VCHR)
582
		mode |= S_IFCHR;
583
	else if (vp->v_type == VLNK)
584
		mode |= S_IFLNK;
585
	else if (vp->v_type == VFIFO)
586
		mode |= S_IFIFO;
587
	else if (vp->v_type == VSOCK)
588
		mode |= S_IFSOCK;
589
590
	vfsnode_invalidate_stat_cache(np);
591
592
	error = sfprov_set_attr(np->vboxfsmp->sf_handle, np->sf_path,
593
	    mode, vap->va_atime, vap->va_mtime, vap->va_ctime);
594
#if 0
595
	if (error == ENOENT)
596
		sfnode_make_stale(np);
597
#endif
598
	if (vap->va_size != (u_quad_t)VNOVAL) {
599
		switch (vp->v_type) {
600
		case VDIR:
601
			return (EISDIR);
602
		case VLNK:
603
			/* FALLTHROUGH */
604
		case VREG:
605
			error = sfprov_set_size(np->vboxfsmp->sf_handle, np->sf_path, vap->va_size);
606
			break;
607
		case VCHR:
608
			/* FALLTHROUGH */
609
		case VBLK:
610
			/* FALLTHROUGH */
611
		case VSOCK:
612
			/* FALLTHROUGH */
613
		case VFIFO:
614
			/* FALLTHROUGH */
615
		case VNON:
616
			/* FALLTHROUGH */
617
		case VBAD:
618
			/* FALLTHROUGH */
619
		case VMARKER:
620
			return (0);
621
		}
622
	}
623
624
	return (error);
180
}
625
}
181
626
182
static int vboxvfs_fsync(struct vop_fsync_args *ap)
627
#define blkoff(vboxfsmp, loc)	((loc) & (vboxfsmp)->bmask)
628
629
static int
630
vboxfs_read(struct vop_read_args *ap)
183
{
631
{
184
    return 0;
632
	struct vnode		*vp = ap->a_vp;
633
	struct uio 		*uio = ap->a_uio;
634
	struct vboxfs_node	*np = VP_TO_VBOXFS_NODE(vp);
635
	int			error = 0;
636
	uint32_t		bytes;
637
	uint32_t		done;
638
	unsigned long		offset;
639
	ssize_t			total;
640
	void			*tmpbuf;
641
642
	if (vp->v_type == VDIR)
643
		return (EISDIR);
644
645
	if (vp->v_type != VREG)
646
		return (EINVAL);
647
648
	if (uio->uio_offset < 0)
649
		return (EINVAL);
650
651
	total = uio->uio_resid;
652
	if (total == 0)
653
		return (0);
654
655
	/*
656
	 * XXXGONZO: this is just to get things working
657
	 * should be optimized
658
	 */
659
	tmpbuf = contigmalloc(PAGE_SIZE, M_DEVBUF, M_WAITOK, 0, ~0, PAGE_SIZE, 0);
660
	if (tmpbuf == 0)
661
		return (ENOMEM);
662
663
	do {
664
		offset = uio->uio_offset;
665
		done = bytes = min(PAGE_SIZE, uio->uio_resid);
666
		error = sfprov_read(np->sf_file, tmpbuf,
667
		    offset, &done, 0);
668
		if (error == 0 && done > 0)
669
			error = uiomove(tmpbuf, done, uio);
670
	} while (error == 0 && uio->uio_resid > 0 && done > 0);
671
672
	contigfree(tmpbuf, PAGE_SIZE, M_DEVBUF);
673
674
	/* a partial read is never an error */
675
	if (total != uio->uio_resid)
676
		error = 0;
677
678
	return (error);
185
}
679
}
186
680
187
static int vboxvfs_print (struct vop_print_args *ap)
681
static int
682
vboxfs_write(struct vop_write_args *ap)
188
{
683
{
189
    return 0;
684
	struct vnode		*vp = ap->a_vp;
685
	struct uio 		*uio = ap->a_uio;
686
	struct vboxfs_node	*np = VP_TO_VBOXFS_NODE(vp);
687
	int			error = 0;
688
	uint32_t		bytes;
689
	uint32_t		done;
690
	unsigned long		offset;
691
	ssize_t			total;
692
	void			*tmpbuf;
693
694
	if (vp->v_type == VDIR)
695
		return (EISDIR);
696
697
	if (vp->v_type != VREG)
698
		return (EINVAL);
699
700
	if (uio->uio_offset < 0)
701
		return (EINVAL);
702
703
	total = uio->uio_resid;
704
	if (total == 0)
705
		return (0);
706
707
	/*
708
	 * XXXGONZO: this is just to get things working
709
	 * should be optimized
710
	 */
711
	tmpbuf = contigmalloc(PAGE_SIZE, M_DEVBUF, M_WAITOK, 0, ~0, PAGE_SIZE, 0);
712
	if (tmpbuf == 0)
713
		return (ENOMEM);
714
715
	do {
716
		offset = uio->uio_offset;
717
		bytes = min(PAGE_SIZE, uio->uio_resid);
718
		error = uiomove(tmpbuf, bytes, uio);
719
		if (error != 0)
720
			break;
721
		done = bytes;
722
		error = sfprov_write(np->sf_file, tmpbuf,
723
		    offset, &done, 0);
724
		if (error != 0)
725
			break;
726
		total -= done;
727
		if (done != bytes)
728
			uio->uio_resid += bytes - done;
729
	} while (error == 0 && uio->uio_resid > 0 && done > 0);
730
731
	contigfree(tmpbuf, PAGE_SIZE, M_DEVBUF);
732
733
	/* a partial write is never an error */
734
	if (total != uio->uio_resid)
735
		error = 0;
736
737
	return (error);
190
}
738
}
191
739
192
static int vboxvfs_pathconf (struct vop_pathconf_args *ap)
740
static int
741
vboxfs_create(struct vop_create_args *ap)
193
{
742
{
194
    return 0;
743
	struct vnode *dvp = ap->a_dvp;
744
	struct vnode **vpp = ap->a_vpp;
745
	struct componentname *cnp = ap->a_cnp;
746
	struct vattr *vap = ap->a_vap;
747
	sffs_stat_t	stat;
748
	char	*fullpath = NULL;
749
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
750
	sfp_file_t *fp;
751
	int error;
752
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
753
754
	MPASS(vap->va_type == VREG);
755
756
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
757
	error = sfprov_create(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
758
	    &fp, &stat);
759
760
	if (error)
761
		goto out;
762
763
	error = vboxfs_alloc_file(vboxfsmp, fullpath, VREG, vap->va_mode, dir, cnp->cn_lkflags, vpp);
764
765
out:
766
	if (fullpath)
767
		free(fullpath, M_VBOXVFS);
768
769
	if (error == 0) {
770
		vfsnode_clear_dir_list(dir);
771
		if ((cnp->cn_flags & MAKEENTRY) != 0)
772
			cache_enter(dvp, *vpp, cnp);
773
	}
774
775
	return (error);
195
}
776
}
196
777
197
static int vboxvfs_strategy (struct vop_strategy_args *ap)
778
static int
779
vboxfs_remove(struct vop_remove_args *ap)
198
{
780
{
199
    return 0;
781
	struct vnode *dvp = ap->a_dvp;
782
	struct vnode *vp = ap->a_vp;
783
	struct vboxfs_node *np, *dir;
784
785
	int error;
786
787
	MPASS(VOP_ISLOCKED(dvp));
788
	MPASS(VOP_ISLOCKED(vp));
789
790
	error = 0;
791
792
	np = VP_TO_VBOXFS_NODE(vp);
793
	dir = VP_TO_VBOXFS_NODE(vp);
794
795
	/*
796
	 * If anything else is using this vnode, then fail the remove.
797
	 * Why?  Windows hosts can't sfprov_remove() a file that is open,
798
	 * so we have to sfprov_close() it first.
799
	 * There is no errno for this - since it's not a problem on UNIX,
800
	 * but ETXTBSY is the closest.
801
	 */
802
	if (np->sf_file != NULL) {
803
		if (vp->v_usecount > 1) {
804
			error = ETXTBSY;
805
			goto out;
806
		}
807
		sfprov_close(np->sf_file);
808
		np->sf_file = NULL;
809
	}
810
811
	error = sfprov_remove(np->vboxfsmp->sf_handle, np->sf_path,
812
	    np->sf_type == VLNK);
813
814
#if 0
815
	if (error == ENOENT || error == 0)
816
		sfnode_make_stale(np);
817
#endif
818
819
	if (error == 0)
820
		vfsnode_clear_dir_list(dir);
821
822
out:
823
	return (error);
200
}
824
}
201
825
202
static int vboxvfs_ioctl(struct vop_ioctl_args *ap)
826
static int
827
vboxfs_rename(struct vop_rename_args *ap)
203
{
828
{
204
    return ENOTTY;
829
	struct vnode *fvp;
830
	struct vnode *fdvp;
831
	struct vnode *tvp;
832
	struct vnode *tdvp;
833
	struct componentname *fcnp;
834
	struct componentname *tcnp;
835
	struct vboxfs_node *np;
836
	int ret;
837
838
	fvp = ap->a_fvp;
839
	fdvp = ap->a_fdvp;
840
	tvp = ap->a_tvp;
841
	tdvp = ap->a_tdvp;
842
	fcnp = ap->a_fcnp;
843
	tcnp = ap->a_tcnp;
844
845
	/* Check for cross-device rename */
846
	if ((fvp->v_mount != tdvp->v_mount) ||
847
	    (tvp && (fvp->v_mount != tvp->v_mount))) {
848
		ret = EXDEV;
849
		goto out;
850
	}
851
	np = VP_TO_VBOXFS_NODE(fvp);
852
	if (np == NULL)
853
		return (0);
854
	ret = sfprov_rename(np->vboxfsmp->sf_handle,
855
	    fcnp->cn_nameptr, tcnp->cn_nameptr, fvp->v_type == VDIR);
856
out:
857
	if (tdvp == tvp)
858
		vrele(tdvp);
859
	else
860
		vput(tdvp);
861
	if (tvp)
862
		vput(tvp);
863
	vrele(fdvp);
864
	vrele(fvp);
865
	return (ret);
205
}
866
}
206
867
207
static int vboxvfs_getextattr(struct vop_getextattr_args *ap)
868
static int
869
vboxfs_link(struct vop_link_args *ap)
208
{
870
{
209
    return 0;
871
	return (EOPNOTSUPP);
210
}
872
}
211
873
212
static int vboxvfs_advlock(struct vop_advlock_args *ap)
874
static int
875
vboxfs_symlink(struct vop_symlink_args *ap)
213
{
876
{
214
    return 0;
877
	struct vnode *dvp = ap->a_dvp;
878
	struct vnode **vpp = ap->a_vpp;
879
	struct componentname *cnp = ap->a_cnp;
880
	struct vattr *vap = ap->a_vap;
881
	sffs_stat_t	stat;
882
	char	*fullpath = NULL;
883
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
884
	int error;
885
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
886
887
	MPASS(vap->va_type == VLNK);
888
889
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
890
	error = sfprov_symlink(dir->vboxfsmp->sf_handle, fullpath, ap->a_target, &stat);
891
892
	if (error)
893
		goto out;
894
895
	error = vboxfs_alloc_file(vboxfsmp, fullpath, VLNK, vap->va_mode, dir, cnp->cn_lkflags, vpp);
896
897
out:
898
	if (fullpath)
899
		free(fullpath, M_VBOXVFS);
900
901
	if (error == 0)
902
		vfsnode_clear_dir_list(dir);
903
904
	return (error);
215
}
905
}
216
906
217
static int vboxvfs_lookup(struct vop_lookup_args *ap)
907
static int
908
vboxfs_mkdir(struct vop_mkdir_args *ap)
218
{
909
{
219
    return 0;
910
	struct vnode *dvp = ap->a_dvp;
911
	struct vnode **vpp = ap->a_vpp;
912
	struct componentname *cnp = ap->a_cnp;
913
	struct vattr *vap = ap->a_vap;
914
	sffs_stat_t	stat;
915
	char	*fullpath = NULL;
916
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
917
	sfp_file_t *fp;
918
	int error;
919
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
920
921
	MPASS(vap->va_type == VDIR);
922
923
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
924
	error = sfprov_mkdir(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
925
	    &fp, &stat);
926
927
	if (error)
928
		goto out;
929
930
	error = vboxfs_alloc_file(vboxfsmp, fullpath, VDIR, vap->va_mode, dir, cnp->cn_lkflags, vpp);
931
932
out:
933
	if (fullpath)
934
		free(fullpath, M_VBOXVFS);
935
936
	if (error == 0)
937
		vfsnode_clear_dir_list(dir);
938
939
	return (error);
220
}
940
}
221
941
222
static int vboxvfs_inactive(struct vop_inactive_args *ap)
942
static int
943
vboxfs_rmdir(struct vop_rmdir_args *ap)
223
{
944
{
224
    return 0;
945
	struct vnode *dvp = ap->a_dvp;
946
	struct vnode *vp = ap->a_vp;
947
	struct vboxfs_node *np, *dir;
948
949
	int error;
950
951
	MPASS(VOP_ISLOCKED(dvp));
952
	MPASS(VOP_ISLOCKED(vp));
953
954
	error = 0;
955
956
	np = VP_TO_VBOXFS_NODE(vp);
957
	dir = VP_TO_VBOXFS_NODE(vp);
958
959
	/*
960
	 * If anything else is using this vnode, then fail the remove.
961
	 * Why?  Windows hosts can't sfprov_remove() a file that is open,
962
	 * so we have to sfprov_close() it first.
963
	 * There is no errno for this - since it's not a problem on UNIX,
964
	 * but ETXTBSY is the closest.
965
	 */
966
	if (np->sf_file != NULL) {
967
		if (vp->v_usecount > 1) {
968
			error = ETXTBSY;
969
			goto out;
970
		}
971
		sfprov_close(np->sf_file);
972
		np->sf_file = NULL;
973
	}
974
975
	error = sfprov_rmdir(np->vboxfsmp->sf_handle, np->sf_path);
976
977
#if 0
978
	if (error == ENOENT || error == 0)
979
		sfnode_make_stale(np);
980
#endif
981
982
	if (error == 0)
983
		vfsnode_clear_dir_list(dir);
984
985
out:
986
	return (error);
225
}
987
}
226
988
227
static int vboxvfs_reclaim(struct vop_reclaim_args *ap)
989
static int
990
vboxfs_readdir(struct vop_readdir_args *ap)
228
{
991
{
229
    return 0;
992
	int *eofp = ap->a_eofflag;
993
	struct vnode *vp = ap->a_vp;
994
	struct uio *uio = ap->a_uio;
995
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(vp);
996
	struct vboxfs_node *node;
997
	struct sffs_dirent *dirent = NULL;
998
	sffs_dirents_t *cur_buf;
999
	off_t offset = 0;
1000
	off_t orig_off = uio->uio_offset;
1001
	int error = 0;
1002
	int dummy_eof;
1003
1004
	if (vp->v_type != VDIR)
1005
		return (ENOTDIR);
1006
1007
	if (eofp == NULL)
1008
		eofp = &dummy_eof;
1009
	*eofp = 0;
1010
1011
	/*
1012
	 * Get the directory entry names from the host. This gets all
1013
	 * entries. These are stored in a linked list of sffs_dirents_t
1014
	 * buffers, each of which contains a list of dirent64_t's.
1015
	 */
1016
	if (dir->sf_dir_list == NULL) {
1017
		error = sfprov_readdir(dir->vboxfsmp->sf_handle, dir->sf_path,
1018
		    &dir->sf_dir_list);
1019
		if (error != 0)
1020
			goto done;
1021
	}
1022
1023
	/*
1024
	 * Validate and skip to the desired offset.
1025
	 */
1026
	cur_buf = dir->sf_dir_list;
1027
	offset = 0;
1028
1029
	while (cur_buf != NULL && offset + cur_buf->sf_len <= uio->uio_offset) {
1030
		offset += cur_buf->sf_len;
1031
		cur_buf = cur_buf->sf_next;
1032
	}
1033
1034
	if (cur_buf == NULL && offset != uio->uio_offset) {
1035
		error = EINVAL;
1036
		goto done;
1037
	}
1038
1039
	if (cur_buf != NULL && offset != uio->uio_offset) {
1040
		off_t off = offset;
1041
		int step;
1042
		dirent = &cur_buf->sf_entries[0];
1043
1044
		while (off < uio->uio_offset) {
1045
			if (dirent->sf_off == uio->uio_offset)
1046
				break;
1047
			step = sizeof(struct sffs_dirent) + dirent->sf_entry.d_reclen;
1048
			dirent = (struct sffs_dirent *) (((char *) dirent) + step);
1049
			off += step;
1050
		}
1051
1052
		if (off >= uio->uio_offset) {
1053
			error = EINVAL;
1054
			goto done;
1055
		}
1056
	}
1057
1058
	offset = uio->uio_offset - offset;
1059
1060
	/*
1061
	 * Lookup each of the names, so that we have ino's, and copy to
1062
	 * result buffer.
1063
	 */
1064
	while (cur_buf != NULL) {
1065
		if (offset >= cur_buf->sf_len) {
1066
			cur_buf = cur_buf->sf_next;
1067
			offset = 0;
1068
			continue;
1069
		}
1070
1071
		dirent = (struct sffs_dirent *)
1072
		    (((char *) &cur_buf->sf_entries[0]) + offset);
1073
		if (dirent->sf_entry.d_reclen > uio->uio_resid)
1074
			break;
1075
1076
		if (strcmp(dirent->sf_entry.d_name, ".") == 0) {
1077
			node = dir;
1078
		} else if (strcmp(dirent->sf_entry.d_name, "..") == 0) {
1079
			node = dir->sf_parent;
1080
			if (node == NULL)
1081
				node = dir;
1082
		} else {
1083
#if 0
1084
			node = vsfnode_lookup(dir, dirent->sf_entry.d_name, VNON,
1085
			    0, &dirent->sf_stat, vsfnode_cur_time_usec(), NULL);
1086
			if (node == NULL)
1087
				panic("sffs_readdir() lookup failed");
1088
#endif
1089
		}
1090
1091
		if (node)
1092
			dirent->sf_entry.d_fileno = node->sf_ino;
1093
		else
1094
			dirent->sf_entry.d_fileno = 0xdeadbeef;
1095
1096
		error = uiomove(&dirent->sf_entry, dirent->sf_entry.d_reclen, uio);
1097
		if (error != 0)
1098
			break;
1099
1100
		uio->uio_offset = dirent->sf_off;
1101
		offset += sizeof(struct sffs_dirent) + dirent->sf_entry.d_reclen;
1102
	}
1103
1104
	if (error == 0 && cur_buf == NULL)
1105
		*eofp = 1;
1106
done:
1107
	if (error != 0)
1108
		uio->uio_offset = orig_off;
1109
	return (error);
230
}
1110
}
231
1111
232
static int vboxvfs_getpages(struct vop_getpages_args *ap)
1112
static int
1113
vboxfs_readlink(struct vop_readlink_args *v)
233
{
1114
{
234
    return 0;
1115
	struct vnode *vp = v->a_vp;
1116
	struct uio *uio = v->a_uio;
1117
1118
	int error;
1119
	struct vboxfs_node *np;
1120
	void *tmpbuf;
1121
1122
	MPASS(uio->uio_offset == 0);
1123
	MPASS(vp->v_type == VLNK);
1124
1125
	np = VP_TO_VBOXFS_NODE(vp);
1126
1127
	tmpbuf = contigmalloc(MAXPATHLEN, M_DEVBUF, M_WAITOK, 0, ~0, 1, 0);
1128
	if (tmpbuf == NULL)
1129
		return (ENOMEM);
1130
1131
	error = sfprov_readlink(np->vboxfsmp->sf_handle, np->sf_path, tmpbuf,
1132
	    MAXPATHLEN);
1133
	if (error)
1134
		goto done;
1135
1136
	error = uiomove(tmpbuf, strlen(tmpbuf), uio);
1137
1138
done:
1139
	if (tmpbuf)
1140
		contigfree(tmpbuf, MAXPATHLEN, M_DEVBUF);
1141
	return (error);
235
}
1142
}
236
1143
237
static int vboxvfs_putpages(struct vop_putpages_args *ap)
1144
static int
1145
vboxfs_fsync(struct vop_fsync_args *ap)
238
{
1146
{
239
    return 0;
1147
	struct vnode *vp;
1148
	struct vboxfs_node *np;
1149
	int ret;
1150
1151
	vp = ap->a_vp;
1152
	np = VP_TO_VBOXFS_NODE(vp);
1153
	if (np == NULL)
1154
		return (0);
1155
	ret = sfprov_fsync(np->sf_file);
1156
	return (ret);
240
}
1157
}
241
1158
1159
static int
1160
vboxfs_print(struct vop_print_args *ap)
1161
{
1162
	struct vnode *vp = ap->a_vp;
1163
	struct vboxfs_node *np;
1164
1165
	np = VP_TO_VBOXFS_NODE(vp);
1166
1167
	if (np == NULL) {
1168
		printf("No vboxfs_node data\n");
1169
		return (0);
1170
	}
1171
1172
	printf("\tpath = %s, parent = %p", np->sf_path,
1173
	    np->sf_parent ? np->sf_parent : NULL);
1174
	printf("\n");
1175
	return (0);
1176
}
1177
1178
static int
1179
vboxfs_pathconf(struct vop_pathconf_args *ap)
1180
{
1181
	register_t *retval = ap->a_retval;
1182
	int error = 0;
1183
1184
	switch (ap->a_name) {
1185
	case _PC_LINK_MAX:
1186
		*retval = 65535;
1187
		break;
1188
	case _PC_NAME_MAX:
1189
		*retval = NAME_MAX;
1190
		break;
1191
	case _PC_PATH_MAX:
1192
		*retval = PATH_MAX;
1193
		break;
1194
	default:
1195
		error = EINVAL;
1196
		break;
1197
	}
1198
	return (error);
1199
}
1200
1201
/*
1202
 * File specific ioctls.
1203
 */
1204
static int
1205
vboxfs_ioctl(struct vop_ioctl_args *ap)
1206
{
1207
	return (ENOTTY);
1208
}
1209
1210
/*
1211
 * Lookup an entry in a directory and create a new vnode if found.
1212
 */
1213
static int
1214
vboxfs_lookup(struct vop_cachedlookup_args /* {
1215
		struct vnodeop_desc *a_desc;
1216
		struct vnode *a_dvp;
1217
		struct vnode **a_vpp;
1218
		struct componentname *a_cnp;
1219
	} */ *ap)
1220
{
1221
	struct 	componentname *cnp = ap->a_cnp;
1222
	struct 	vnode *dvp = ap->a_dvp;		/* the directory vnode */
1223
	char	*nameptr = cnp->cn_nameptr;	/* the name of the file or directory */
1224
	struct	vnode **vpp = ap->a_vpp;	/* the vnode we found or NULL */
1225
	struct  vnode *tdp = NULL;
1226
	struct 	vboxfs_node *node = VP_TO_VBOXFS_NODE(dvp);
1227
	struct 	vboxfs_mnt *vboxfsmp = node->vboxfsmp;
1228
	u_long  nameiop = cnp->cn_nameiop;
1229
	u_long 	flags = cnp->cn_flags;
1230
	sffs_stat_t	stat;
1231
	//long 	namelen;
1232
	ino_t 	id = 0;
1233
	int 	ltype, type, error = 0;
1234
	int 	lkflags = cnp->cn_lkflags;
1235
	char	*fullpath = NULL;
1236
1237
	error = ENOENT;
1238
	if (cnp->cn_flags & ISDOTDOT) {
1239
		error = vn_vget_ino_gen(dvp, vboxfs_vn_get_ino_alloc,
1240
		    node->sf_parent, cnp->cn_lkflags, vpp);
1241
		error = ENOENT;
1242
		if (error != 0)
1243
			goto out;
1244
1245
	} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
1246
		VREF(dvp);
1247
		*vpp = dvp;
1248
		error = 0;
1249
	} else {
1250
		mode_t m;
1251
		type = VNON;
1252
		fullpath = sfnode_construct_path(node, cnp->cn_nameptr, cnp->cn_namelen);
1253
		error = sfprov_get_attr(node->vboxfsmp->sf_handle,
1254
		    fullpath, &stat);
1255
		// stat_time = vsfnode_cur_time_usec();
1256
1257
		m = stat.sf_mode;
1258
		if (error != 0) {
1259
			/* The entry was not found in the directory.
1260
			 * This is OK if we are creating or renaming an
1261
			 * entry and are working on the last component of
1262
			 * the path name. */
1263
			if ((cnp->cn_flags & ISLASTCN) &&
1264
			    (cnp->cn_nameiop == CREATE || \
1265
			    cnp->cn_nameiop == RENAME ||
1266
			    (cnp->cn_nameiop == DELETE &&
1267
			    cnp->cn_flags & DOWHITEOUT &&
1268
			    cnp->cn_flags & ISWHITEOUT))) {
1269
				error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
1270
				    cnp->cn_thread);
1271
				if (error != 0)
1272
					goto out;
1273
1274
				/* Keep the component name in the buffer for
1275
				 * future uses. */
1276
				cnp->cn_flags |= SAVENAME;
1277
1278
				error = EJUSTRETURN;
1279
			} else
1280
				error = ENOENT;
1281
		}
1282
		else {
1283
			if (S_ISDIR(m))
1284
				type = VDIR;
1285
			else if (S_ISREG(m))
1286
				type = VREG;
1287
			else if (S_ISLNK(m))
1288
				type = VLNK;
1289
			error = vboxfs_alloc_file(vboxfsmp, fullpath, type, 0755, node, cnp->cn_lkflags, vpp);
1290
		}
1291
	}
1292
1293
	if ((cnp->cn_flags & MAKEENTRY) != 0)
1294
		cache_enter(dvp, *vpp, cnp);
1295
out:
1296
	if (fullpath)
1297
		free(fullpath, M_VBOXVFS);
1298
1299
	return (error);
1300
}
1301
1302
static int
1303
vboxfs_inactive(struct vop_inactive_args *ap)
1304
{
1305
   	return (0);
1306
}
1307
1308
static int
1309
vboxfs_reclaim(struct vop_reclaim_args *ap)
1310
{
1311
	struct vnode *vp;
1312
	struct vboxfs_node *node;
1313
	struct 	vboxfs_mnt *vboxfsmp;
1314
1315
	vp = ap->a_vp;
1316
	node = VP_TO_VBOXFS_NODE(vp);
1317
	vboxfsmp = node->vboxfsmp;
1318
1319
	vnode_destroy_vobject(vp);
1320
	vp->v_object = NULL;
1321
	cache_purge(vp);
1322
1323
	VBOXFS_NODE_LOCK(node);
1324
	VBOXFS_ASSERT_ELOCKED(node);
1325
	vboxfs_free_vp(vp);
1326
1327
	/* If the node referenced by this vnode was deleted by the user,
1328
	 * we must free its associated data structures (now that the vnode
1329
	 * is being reclaimed). */
1330
	if ((node->sf_vpstate & VBOXFS_VNODE_ALLOCATING) == 0) {
1331
		node->sf_vpstate = VBOXFS_VNODE_DOOMED;
1332
		VBOXFS_NODE_UNLOCK(node);
1333
		vboxfs_free_node(vboxfsmp, node);
1334
	} else
1335
		VBOXFS_NODE_UNLOCK(node);
1336
1337
	MPASS(vp->v_data == NULL);
1338
1339
	return (0);
1340
}
1341
1342
static int
1343
vboxfs_vptofh(struct vop_vptofh_args *ap)
1344
{
1345
1346
	return (EOPNOTSUPP);
1347
}

Return to bug 248528