xref: /minix3/minix/lib/libfsdriver/call.c (revision 0a2a08739e5ee13a20ba5d874beca4958a42cb49)
189c9de7dSDavid van Moolenbroek 
289c9de7dSDavid van Moolenbroek #include "fsdriver.h"
389c9de7dSDavid van Moolenbroek #include <minix/ds.h>
4e321f655SDavid van Moolenbroek #include <sys/mman.h>
589c9de7dSDavid van Moolenbroek 
6*0a2a0873SDavid van Moolenbroek static int fsdriver_vmcache;	/* have we used the VM cache? */
7*0a2a0873SDavid van Moolenbroek 
889c9de7dSDavid van Moolenbroek /*
989c9de7dSDavid van Moolenbroek  * Process a READSUPER request from VFS.
1089c9de7dSDavid van Moolenbroek  */
1189c9de7dSDavid van Moolenbroek int
fsdriver_readsuper(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)1289c9de7dSDavid van Moolenbroek fsdriver_readsuper(const struct fsdriver * __restrict fdp,
1389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
1489c9de7dSDavid van Moolenbroek {
1589c9de7dSDavid van Moolenbroek 	struct fsdriver_node root_node;
1689c9de7dSDavid van Moolenbroek 	char label[DS_MAX_KEYLEN];
1789c9de7dSDavid van Moolenbroek 	cp_grant_id_t label_grant;
1889c9de7dSDavid van Moolenbroek 	size_t label_len;
1989c9de7dSDavid van Moolenbroek 	unsigned int flags, res_flags;
2089c9de7dSDavid van Moolenbroek 	dev_t dev;
2189c9de7dSDavid van Moolenbroek 	int r;
2289c9de7dSDavid van Moolenbroek 
2389c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_readsuper.device;
2489c9de7dSDavid van Moolenbroek 	label_grant = m_in->m_vfs_fs_readsuper.grant;
2589c9de7dSDavid van Moolenbroek 	label_len = m_in->m_vfs_fs_readsuper.path_len;
2689c9de7dSDavid van Moolenbroek 	flags = m_in->m_vfs_fs_readsuper.flags;
2789c9de7dSDavid van Moolenbroek 
2889c9de7dSDavid van Moolenbroek 	if (fdp->fdr_mount == NULL)
2989c9de7dSDavid van Moolenbroek 		return ENOSYS;
3089c9de7dSDavid van Moolenbroek 
3189c9de7dSDavid van Moolenbroek 	if (fsdriver_mounted) {
3289c9de7dSDavid van Moolenbroek 		printf("fsdriver: attempt to mount multiple times\n");
3389c9de7dSDavid van Moolenbroek 		return EBUSY;
3489c9de7dSDavid van Moolenbroek 	}
3589c9de7dSDavid van Moolenbroek 
3689c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, label_grant, label_len,
3789c9de7dSDavid van Moolenbroek 	    label, sizeof(label), FALSE /*not_empty*/)) != OK)
3889c9de7dSDavid van Moolenbroek 		return r;
3989c9de7dSDavid van Moolenbroek 
4089c9de7dSDavid van Moolenbroek 	if (fdp->fdr_driver != NULL)
4189c9de7dSDavid van Moolenbroek 		fdp->fdr_driver(dev, label);
4289c9de7dSDavid van Moolenbroek 
4389c9de7dSDavid van Moolenbroek 	res_flags = RES_NOFLAGS;
4489c9de7dSDavid van Moolenbroek 
4589c9de7dSDavid van Moolenbroek 	r = fdp->fdr_mount(dev, flags, &root_node, &res_flags);
4689c9de7dSDavid van Moolenbroek 
4789c9de7dSDavid van Moolenbroek 	if (r == OK) {
4889c9de7dSDavid van Moolenbroek 		/* This one we can set on the file system's behalf. */
49e321f655SDavid van Moolenbroek 		if ((fdp->fdr_peek != NULL && fdp->fdr_bpeek != NULL) ||
50e321f655SDavid van Moolenbroek 		    major(dev) == NONE_MAJOR)
5189c9de7dSDavid van Moolenbroek 			res_flags |= RES_HASPEEK;
5289c9de7dSDavid van Moolenbroek 
5389c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.inode = root_node.fn_ino_nr;
5489c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.mode = root_node.fn_mode;
5589c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.file_size = root_node.fn_size;
5689c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.uid = root_node.fn_uid;
5789c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.gid = root_node.fn_gid;
5889c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readsuper.flags = res_flags;
5989c9de7dSDavid van Moolenbroek 
6089c9de7dSDavid van Moolenbroek 		/* Update library-local state. */
6189c9de7dSDavid van Moolenbroek 		fsdriver_mounted = TRUE;
62289b0467SDavid van Moolenbroek 		fsdriver_device = dev;
6389c9de7dSDavid van Moolenbroek 		fsdriver_root = root_node.fn_ino_nr;
64*0a2a0873SDavid van Moolenbroek 		fsdriver_vmcache = FALSE;
6589c9de7dSDavid van Moolenbroek 	}
6689c9de7dSDavid van Moolenbroek 
6789c9de7dSDavid van Moolenbroek 	return r;
6889c9de7dSDavid van Moolenbroek }
6989c9de7dSDavid van Moolenbroek 
7089c9de7dSDavid van Moolenbroek /*
7189c9de7dSDavid van Moolenbroek  * Process an UNMOUNT request from VFS.
7289c9de7dSDavid van Moolenbroek  */
7389c9de7dSDavid van Moolenbroek int
fsdriver_unmount(const struct fsdriver * __restrict fdp,const message * __restrict __unused m_in,message * __restrict __unused m_out)7489c9de7dSDavid van Moolenbroek fsdriver_unmount(const struct fsdriver * __restrict fdp,
7589c9de7dSDavid van Moolenbroek 	const message * __restrict __unused m_in,
7689c9de7dSDavid van Moolenbroek 	message * __restrict __unused m_out)
7789c9de7dSDavid van Moolenbroek {
7889c9de7dSDavid van Moolenbroek 
7989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_unmount != NULL)
8089c9de7dSDavid van Moolenbroek 		fdp->fdr_unmount();
8189c9de7dSDavid van Moolenbroek 
82e321f655SDavid van Moolenbroek 	/* If we used mmap emulation, clear any cached blocks from VM. */
83*0a2a0873SDavid van Moolenbroek 	if (fsdriver_vmcache)
84e321f655SDavid van Moolenbroek 		vm_clear_cache(fsdriver_device);
85e321f655SDavid van Moolenbroek 
8689c9de7dSDavid van Moolenbroek 	/* Update library-local state. */
8789c9de7dSDavid van Moolenbroek 	fsdriver_mounted = FALSE;
8889c9de7dSDavid van Moolenbroek 
8989c9de7dSDavid van Moolenbroek 	return OK;
9089c9de7dSDavid van Moolenbroek }
9189c9de7dSDavid van Moolenbroek 
9289c9de7dSDavid van Moolenbroek /*
9389c9de7dSDavid van Moolenbroek  * Process a PUTNODE request from VFS.
9489c9de7dSDavid van Moolenbroek  */
9589c9de7dSDavid van Moolenbroek int
fsdriver_putnode(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)9689c9de7dSDavid van Moolenbroek fsdriver_putnode(const struct fsdriver * __restrict fdp,
9789c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
9889c9de7dSDavid van Moolenbroek {
9989c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
10089c9de7dSDavid van Moolenbroek 	unsigned int count;
10189c9de7dSDavid van Moolenbroek 
10289c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_putnode.inode;
10389c9de7dSDavid van Moolenbroek 	count = m_in->m_vfs_fs_putnode.count;
10489c9de7dSDavid van Moolenbroek 
10589c9de7dSDavid van Moolenbroek 	if (count == 0 || count > INT_MAX) {
10689c9de7dSDavid van Moolenbroek 		printf("fsdriver: invalid reference count\n");
10789c9de7dSDavid van Moolenbroek 		return EINVAL;
10889c9de7dSDavid van Moolenbroek 	}
10989c9de7dSDavid van Moolenbroek 
1103f30eb69SDavid van Moolenbroek 	if (fdp->fdr_putnode != NULL)
11189c9de7dSDavid van Moolenbroek 		return fdp->fdr_putnode(ino_nr, count);
1123f30eb69SDavid van Moolenbroek 	else
1133f30eb69SDavid van Moolenbroek 		return OK;
11489c9de7dSDavid van Moolenbroek }
11589c9de7dSDavid van Moolenbroek 
11689c9de7dSDavid van Moolenbroek /*
11789c9de7dSDavid van Moolenbroek  * Process a NEWNODE request from VFS.
11889c9de7dSDavid van Moolenbroek  */
11989c9de7dSDavid van Moolenbroek int
fsdriver_newnode(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)12089c9de7dSDavid van Moolenbroek fsdriver_newnode(const struct fsdriver * __restrict fdp,
12189c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
12289c9de7dSDavid van Moolenbroek {
12389c9de7dSDavid van Moolenbroek 	struct fsdriver_node node;
12489c9de7dSDavid van Moolenbroek 	mode_t mode;
12589c9de7dSDavid van Moolenbroek 	uid_t uid;
12689c9de7dSDavid van Moolenbroek 	gid_t gid;
12789c9de7dSDavid van Moolenbroek 	dev_t dev;
12889c9de7dSDavid van Moolenbroek 	int r;
12989c9de7dSDavid van Moolenbroek 
13089c9de7dSDavid van Moolenbroek 	mode = m_in->m_vfs_fs_newnode.mode;
13189c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_newnode.uid;
13289c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_newnode.gid;
13389c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_newnode.device;
13489c9de7dSDavid van Moolenbroek 
13589c9de7dSDavid van Moolenbroek 	if (fdp->fdr_newnode == NULL)
13689c9de7dSDavid van Moolenbroek 		return ENOSYS;
13789c9de7dSDavid van Moolenbroek 
13889c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_newnode(mode, uid, gid, dev, &node)) == OK) {
13989c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.inode = node.fn_ino_nr;
14089c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.mode = node.fn_mode;
14189c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.file_size = node.fn_size;
14289c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.uid = node.fn_uid;
14389c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.gid = node.fn_gid;
14489c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_newnode.device = node.fn_dev;
14589c9de7dSDavid van Moolenbroek 	}
14689c9de7dSDavid van Moolenbroek 
14789c9de7dSDavid van Moolenbroek 	return r;
14889c9de7dSDavid van Moolenbroek }
14989c9de7dSDavid van Moolenbroek 
15089c9de7dSDavid van Moolenbroek /*
15189c9de7dSDavid van Moolenbroek  * Process a read or write request from VFS.
15289c9de7dSDavid van Moolenbroek  */
15389c9de7dSDavid van Moolenbroek static int
read_write(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out,int call)15489c9de7dSDavid van Moolenbroek read_write(const struct fsdriver * __restrict fdp,
15589c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out, int call)
15689c9de7dSDavid van Moolenbroek {
15789c9de7dSDavid van Moolenbroek 	struct fsdriver_data data;
15889c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
15989c9de7dSDavid van Moolenbroek 	off_t pos;
16089c9de7dSDavid van Moolenbroek 	size_t nbytes;
16189c9de7dSDavid van Moolenbroek 	ssize_t r;
16289c9de7dSDavid van Moolenbroek 
16389c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_readwrite.inode;
16489c9de7dSDavid van Moolenbroek 	pos = m_in->m_vfs_fs_readwrite.seek_pos;
16589c9de7dSDavid van Moolenbroek 	nbytes = m_in->m_vfs_fs_readwrite.nbytes;
16689c9de7dSDavid van Moolenbroek 
16789c9de7dSDavid van Moolenbroek 	if (pos < 0 || nbytes > SSIZE_MAX)
16889c9de7dSDavid van Moolenbroek 		return EINVAL;
16989c9de7dSDavid van Moolenbroek 
17089c9de7dSDavid van Moolenbroek 	data.endpt = m_in->m_source;
17189c9de7dSDavid van Moolenbroek 	data.grant = m_in->m_vfs_fs_readwrite.grant;
17289c9de7dSDavid van Moolenbroek 	data.size = nbytes;
17389c9de7dSDavid van Moolenbroek 
17489c9de7dSDavid van Moolenbroek 	if (call == FSC_WRITE)
17589c9de7dSDavid van Moolenbroek 		r = fdp->fdr_write(ino_nr, &data, nbytes, pos, call);
17689c9de7dSDavid van Moolenbroek 	else
17789c9de7dSDavid van Moolenbroek 		r = fdp->fdr_read(ino_nr, &data, nbytes, pos, call);
17889c9de7dSDavid van Moolenbroek 
17989c9de7dSDavid van Moolenbroek 	if (r >= 0) {
18089c9de7dSDavid van Moolenbroek 		pos += r;
18189c9de7dSDavid van Moolenbroek 
18289c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readwrite.seek_pos = pos;
18389c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readwrite.nbytes = r;
18489c9de7dSDavid van Moolenbroek 		r = OK;
18589c9de7dSDavid van Moolenbroek 	}
18689c9de7dSDavid van Moolenbroek 
18789c9de7dSDavid van Moolenbroek 	return r;
18889c9de7dSDavid van Moolenbroek }
18989c9de7dSDavid van Moolenbroek 
19089c9de7dSDavid van Moolenbroek /*
19189c9de7dSDavid van Moolenbroek  * Process a READ request from VFS.
19289c9de7dSDavid van Moolenbroek  */
19389c9de7dSDavid van Moolenbroek int
fsdriver_read(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)19489c9de7dSDavid van Moolenbroek fsdriver_read(const struct fsdriver * __restrict fdp,
19589c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
19689c9de7dSDavid van Moolenbroek {
19789c9de7dSDavid van Moolenbroek 
19889c9de7dSDavid van Moolenbroek 	if (fdp->fdr_read == NULL)
19989c9de7dSDavid van Moolenbroek 		return ENOSYS;
20089c9de7dSDavid van Moolenbroek 
20189c9de7dSDavid van Moolenbroek 	return read_write(fdp, m_in, m_out, FSC_READ);
20289c9de7dSDavid van Moolenbroek }
20389c9de7dSDavid van Moolenbroek 
20489c9de7dSDavid van Moolenbroek /*
20589c9de7dSDavid van Moolenbroek  * Process a WRITE request from VFS.
20689c9de7dSDavid van Moolenbroek  */
20789c9de7dSDavid van Moolenbroek int
fsdriver_write(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)20889c9de7dSDavid van Moolenbroek fsdriver_write(const struct fsdriver * __restrict fdp,
20989c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
21089c9de7dSDavid van Moolenbroek {
21189c9de7dSDavid van Moolenbroek 
21289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_write == NULL)
21389c9de7dSDavid van Moolenbroek 		return ENOSYS;
21489c9de7dSDavid van Moolenbroek 
21589c9de7dSDavid van Moolenbroek 	return read_write(fdp, m_in, m_out, FSC_WRITE);
21689c9de7dSDavid van Moolenbroek }
21789c9de7dSDavid van Moolenbroek 
21889c9de7dSDavid van Moolenbroek /*
219e321f655SDavid van Moolenbroek  * A read-based peek implementation.  This allows file systems that do not have
220e321f655SDavid van Moolenbroek  * a buffer cache and do not implement peek, to support a limited form of mmap.
221e321f655SDavid van Moolenbroek  * We map in a block, fill it by calling the file system's read function, tell
222e321f655SDavid van Moolenbroek  * VM about the page, and then unmap the block again.  We tell VM not to cache
223e321f655SDavid van Moolenbroek  * the block beyond its immediate use for the mmap request, so as to prevent
224e321f655SDavid van Moolenbroek  * potentially stale data from being cached--at the cost of performance.
225e321f655SDavid van Moolenbroek  */
226e321f655SDavid van Moolenbroek static ssize_t
builtin_peek(const struct fsdriver * __restrict fdp,ino_t ino_nr,size_t nbytes,off_t pos)227e321f655SDavid van Moolenbroek builtin_peek(const struct fsdriver * __restrict fdp, ino_t ino_nr,
228e321f655SDavid van Moolenbroek 	size_t nbytes, off_t pos)
229e321f655SDavid van Moolenbroek {
230e321f655SDavid van Moolenbroek 	static u32_t flags = 0;	/* storage for the VMMC_ flags of all blocks */
231e321f655SDavid van Moolenbroek 	static off_t dev_off = 0; /* fake device offset, see below */
232e321f655SDavid van Moolenbroek 	struct fsdriver_data data;
233e321f655SDavid van Moolenbroek 	char *buf;
234e321f655SDavid van Moolenbroek 	ssize_t r;
235e321f655SDavid van Moolenbroek 
236e321f655SDavid van Moolenbroek 	if ((buf = mmap(NULL, nbytes, PROT_READ | PROT_WRITE,
237e321f655SDavid van Moolenbroek 	    MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
238e321f655SDavid van Moolenbroek 		return ENOMEM;
239e321f655SDavid van Moolenbroek 
240e321f655SDavid van Moolenbroek 	data.endpt = SELF;
241e321f655SDavid van Moolenbroek 	data.grant = (cp_grant_id_t)buf;
242e321f655SDavid van Moolenbroek 	data.size = nbytes;
243e321f655SDavid van Moolenbroek 
244e321f655SDavid van Moolenbroek 	r = fdp->fdr_read(ino_nr, &data, nbytes, pos, FSC_READ);
245e321f655SDavid van Moolenbroek 
246e321f655SDavid van Moolenbroek 	if (r >= 0) {
247e321f655SDavid van Moolenbroek 		if ((size_t)r < nbytes)
248e321f655SDavid van Moolenbroek 			memset(&buf[r], 0, nbytes - r);
249e321f655SDavid van Moolenbroek 
250e321f655SDavid van Moolenbroek 		/*
251e321f655SDavid van Moolenbroek 		 * VM uses serialized communication to VFS.  Since the page is
252e321f655SDavid van Moolenbroek 		 * to be used only once, VM will use and then discard it before
253e321f655SDavid van Moolenbroek 		 * sending a new peek request.  Thus, it should be safe to
254e321f655SDavid van Moolenbroek 		 * reuse the same device offset all the time.  However, relying
255e321f655SDavid van Moolenbroek 		 * on assumptions in protocols elsewhere a bit dangerous, so we
256e321f655SDavid van Moolenbroek 		 * use an ever-increasing device offset just to be safe.
257e321f655SDavid van Moolenbroek 		 */
258e321f655SDavid van Moolenbroek 		r = vm_set_cacheblock(buf, fsdriver_device, dev_off, ino_nr,
259e321f655SDavid van Moolenbroek 		    pos, &flags, nbytes, VMSF_ONCE);
260e321f655SDavid van Moolenbroek 
261e321f655SDavid van Moolenbroek 		if (r == OK) {
262*0a2a0873SDavid van Moolenbroek 			fsdriver_vmcache = TRUE;
263*0a2a0873SDavid van Moolenbroek 
264e321f655SDavid van Moolenbroek 			dev_off += nbytes;
265e321f655SDavid van Moolenbroek 
266e321f655SDavid van Moolenbroek 			r = nbytes;
267e321f655SDavid van Moolenbroek 		}
268e321f655SDavid van Moolenbroek 	}
269e321f655SDavid van Moolenbroek 
270e321f655SDavid van Moolenbroek 	munmap(buf, nbytes);
271e321f655SDavid van Moolenbroek 
272e321f655SDavid van Moolenbroek 	return r;
273e321f655SDavid van Moolenbroek }
274e321f655SDavid van Moolenbroek 
275e321f655SDavid van Moolenbroek /*
27689c9de7dSDavid van Moolenbroek  * Process a PEEK request from VFS.
27789c9de7dSDavid van Moolenbroek  */
27889c9de7dSDavid van Moolenbroek int
fsdriver_peek(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)27989c9de7dSDavid van Moolenbroek fsdriver_peek(const struct fsdriver * __restrict fdp,
28089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
28189c9de7dSDavid van Moolenbroek {
28289c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
28389c9de7dSDavid van Moolenbroek 	off_t pos;
28489c9de7dSDavid van Moolenbroek 	size_t nbytes;
28589c9de7dSDavid van Moolenbroek 	ssize_t r;
28689c9de7dSDavid van Moolenbroek 
28789c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_readwrite.inode;
28889c9de7dSDavid van Moolenbroek 	pos = m_in->m_vfs_fs_readwrite.seek_pos;
28989c9de7dSDavid van Moolenbroek 	nbytes = m_in->m_vfs_fs_readwrite.nbytes;
29089c9de7dSDavid van Moolenbroek 
29189c9de7dSDavid van Moolenbroek 	if (pos < 0 || nbytes > SSIZE_MAX)
29289c9de7dSDavid van Moolenbroek 		return EINVAL;
29389c9de7dSDavid van Moolenbroek 
294e321f655SDavid van Moolenbroek 	if (fdp->fdr_peek == NULL) {
295e321f655SDavid van Moolenbroek 		if (major(fsdriver_device) != NONE_MAJOR)
296e321f655SDavid van Moolenbroek 			return ENOSYS;
297e321f655SDavid van Moolenbroek 
298e321f655SDavid van Moolenbroek 		/*
299e321f655SDavid van Moolenbroek 		 * For file systems that have no backing device, emulate peek
300e321f655SDavid van Moolenbroek 		 * support by reading into temporary buffers and passing these
301e321f655SDavid van Moolenbroek 		 * to VM.
302e321f655SDavid van Moolenbroek 		 */
303e321f655SDavid van Moolenbroek 		r = builtin_peek(fdp, ino_nr, nbytes, pos);
304e321f655SDavid van Moolenbroek 	} else
305e321f655SDavid van Moolenbroek 		r = fdp->fdr_peek(ino_nr, NULL /*data*/, nbytes, pos,
306e321f655SDavid van Moolenbroek 		    FSC_PEEK);
30789c9de7dSDavid van Moolenbroek 
30889c9de7dSDavid van Moolenbroek 	/* Do not return a new position. */
30989c9de7dSDavid van Moolenbroek 	if (r >= 0) {
31089c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_readwrite.nbytes = r;
31189c9de7dSDavid van Moolenbroek 		r = OK;
31289c9de7dSDavid van Moolenbroek 	}
31389c9de7dSDavid van Moolenbroek 
31489c9de7dSDavid van Moolenbroek 	return r;
31589c9de7dSDavid van Moolenbroek }
31689c9de7dSDavid van Moolenbroek 
31789c9de7dSDavid van Moolenbroek /*
31889c9de7dSDavid van Moolenbroek  * Process a GETDENTS request from VFS.
31989c9de7dSDavid van Moolenbroek  */
32089c9de7dSDavid van Moolenbroek int
fsdriver_getdents(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)32189c9de7dSDavid van Moolenbroek fsdriver_getdents(const struct fsdriver * __restrict fdp,
32289c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
32389c9de7dSDavid van Moolenbroek {
32489c9de7dSDavid van Moolenbroek 	struct fsdriver_data data;
32589c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
32689c9de7dSDavid van Moolenbroek 	off_t pos;
32789c9de7dSDavid van Moolenbroek 	size_t nbytes;
32889c9de7dSDavid van Moolenbroek 	ssize_t r;
32989c9de7dSDavid van Moolenbroek 
33089c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_getdents.inode;
33189c9de7dSDavid van Moolenbroek 	pos = m_in->m_vfs_fs_getdents.seek_pos;
33289c9de7dSDavid van Moolenbroek 	nbytes = m_in->m_vfs_fs_getdents.mem_size;
33389c9de7dSDavid van Moolenbroek 
33489c9de7dSDavid van Moolenbroek 	if (fdp->fdr_getdents == NULL)
33589c9de7dSDavid van Moolenbroek 		return ENOSYS;
33689c9de7dSDavid van Moolenbroek 
33789c9de7dSDavid van Moolenbroek 	if (pos < 0 || nbytes > SSIZE_MAX)
33889c9de7dSDavid van Moolenbroek 		return EINVAL;
33989c9de7dSDavid van Moolenbroek 
34089c9de7dSDavid van Moolenbroek 	data.endpt = m_in->m_source;
34189c9de7dSDavid van Moolenbroek 	data.grant = m_in->m_vfs_fs_getdents.grant;
34289c9de7dSDavid van Moolenbroek 	data.size = nbytes;
34389c9de7dSDavid van Moolenbroek 
34489c9de7dSDavid van Moolenbroek 	r = fdp->fdr_getdents(ino_nr, &data, nbytes, &pos);
34589c9de7dSDavid van Moolenbroek 
34689c9de7dSDavid van Moolenbroek 	if (r >= 0) {
34789c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_getdents.seek_pos = pos;
34889c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_getdents.nbytes = r;
34989c9de7dSDavid van Moolenbroek 		r = OK;
35089c9de7dSDavid van Moolenbroek 	}
35189c9de7dSDavid van Moolenbroek 
35289c9de7dSDavid van Moolenbroek 	return r;
35389c9de7dSDavid van Moolenbroek }
35489c9de7dSDavid van Moolenbroek 
35589c9de7dSDavid van Moolenbroek /*
35689c9de7dSDavid van Moolenbroek  * Process a FTRUNC request from VFS.
35789c9de7dSDavid van Moolenbroek  */
35889c9de7dSDavid van Moolenbroek int
fsdriver_trunc(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)35989c9de7dSDavid van Moolenbroek fsdriver_trunc(const struct fsdriver * __restrict fdp,
36089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
36189c9de7dSDavid van Moolenbroek {
36289c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
36389c9de7dSDavid van Moolenbroek 	off_t start_pos, end_pos;
36489c9de7dSDavid van Moolenbroek 
36589c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_ftrunc.inode;
36689c9de7dSDavid van Moolenbroek 	start_pos = m_in->m_vfs_fs_ftrunc.trc_start;
36789c9de7dSDavid van Moolenbroek 	end_pos = m_in->m_vfs_fs_ftrunc.trc_end;
36889c9de7dSDavid van Moolenbroek 
36989c9de7dSDavid van Moolenbroek 	if (start_pos < 0 || end_pos < 0)
37089c9de7dSDavid van Moolenbroek 		return EINVAL;
37189c9de7dSDavid van Moolenbroek 
37289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_trunc == NULL)
37389c9de7dSDavid van Moolenbroek 		return ENOSYS;
37489c9de7dSDavid van Moolenbroek 
37589c9de7dSDavid van Moolenbroek 	return fdp->fdr_trunc(ino_nr, start_pos, end_pos);
37689c9de7dSDavid van Moolenbroek }
37789c9de7dSDavid van Moolenbroek 
37889c9de7dSDavid van Moolenbroek /*
37989c9de7dSDavid van Moolenbroek  * Process a INHIBREAD request from VFS.
38089c9de7dSDavid van Moolenbroek  */
38189c9de7dSDavid van Moolenbroek int
fsdriver_inhibread(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)38289c9de7dSDavid van Moolenbroek fsdriver_inhibread(const struct fsdriver * __restrict fdp,
38389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
38489c9de7dSDavid van Moolenbroek {
38589c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
38689c9de7dSDavid van Moolenbroek 
38789c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_inhibread.inode;
38889c9de7dSDavid van Moolenbroek 
38989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_seek != NULL)
39089c9de7dSDavid van Moolenbroek 		fdp->fdr_seek(ino_nr);
39189c9de7dSDavid van Moolenbroek 
39289c9de7dSDavid van Moolenbroek 	return OK;
39389c9de7dSDavid van Moolenbroek }
39489c9de7dSDavid van Moolenbroek 
39589c9de7dSDavid van Moolenbroek /*
39689c9de7dSDavid van Moolenbroek  * Process a CREATE request from VFS.
39789c9de7dSDavid van Moolenbroek  */
39889c9de7dSDavid van Moolenbroek int
fsdriver_create(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)39989c9de7dSDavid van Moolenbroek fsdriver_create(const struct fsdriver * __restrict fdp,
40089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
40189c9de7dSDavid van Moolenbroek {
40289c9de7dSDavid van Moolenbroek 	struct fsdriver_node node;
40389c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
40489c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
40589c9de7dSDavid van Moolenbroek 	size_t len;
40689c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
40789c9de7dSDavid van Moolenbroek 	mode_t mode;
40889c9de7dSDavid van Moolenbroek 	uid_t uid;
40989c9de7dSDavid van Moolenbroek 	gid_t gid;
41089c9de7dSDavid van Moolenbroek 	int r;
41189c9de7dSDavid van Moolenbroek 
41289c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_create.grant;
41389c9de7dSDavid van Moolenbroek 	len = m_in->m_vfs_fs_create.path_len;
41489c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_create.inode;
41589c9de7dSDavid van Moolenbroek 	mode = m_in->m_vfs_fs_create.mode;
41689c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_create.uid;
41789c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_create.gid;
41889c9de7dSDavid van Moolenbroek 
41989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_create == NULL)
42089c9de7dSDavid van Moolenbroek 		return ENOSYS;
42189c9de7dSDavid van Moolenbroek 
42289c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, len, name,
42389c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
42489c9de7dSDavid van Moolenbroek 		return r;
42589c9de7dSDavid van Moolenbroek 
42689c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
42789c9de7dSDavid van Moolenbroek 		return EEXIST;
42889c9de7dSDavid van Moolenbroek 
42989c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_create(dir_nr, name, mode, uid, gid, &node)) == OK) {
43089c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_create.inode = node.fn_ino_nr;
43189c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_create.mode = node.fn_mode;
43289c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_create.file_size = node.fn_size;
43389c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_create.uid = node.fn_uid;
43489c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_create.gid = node.fn_gid;
43589c9de7dSDavid van Moolenbroek 	}
43689c9de7dSDavid van Moolenbroek 
43789c9de7dSDavid van Moolenbroek 	return r;
43889c9de7dSDavid van Moolenbroek }
43989c9de7dSDavid van Moolenbroek 
44089c9de7dSDavid van Moolenbroek /*
44189c9de7dSDavid van Moolenbroek  * Process a MKDIR request from VFS.
44289c9de7dSDavid van Moolenbroek  */
44389c9de7dSDavid van Moolenbroek int
fsdriver_mkdir(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)44489c9de7dSDavid van Moolenbroek fsdriver_mkdir(const struct fsdriver * __restrict fdp,
44589c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
44689c9de7dSDavid van Moolenbroek {
44789c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
44889c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
44989c9de7dSDavid van Moolenbroek 	size_t path_len;
45089c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
45189c9de7dSDavid van Moolenbroek 	mode_t mode;
45289c9de7dSDavid van Moolenbroek 	uid_t uid;
45389c9de7dSDavid van Moolenbroek 	gid_t gid;
45489c9de7dSDavid van Moolenbroek 	int r;
45589c9de7dSDavid van Moolenbroek 
45689c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_mkdir.grant;
45789c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_mkdir.path_len;
45889c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_mkdir.inode;
45989c9de7dSDavid van Moolenbroek 	mode = m_in->m_vfs_fs_mkdir.mode;
46089c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_mkdir.uid;
46189c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_mkdir.gid;
46289c9de7dSDavid van Moolenbroek 
46389c9de7dSDavid van Moolenbroek 	if (fdp->fdr_mkdir == NULL)
46489c9de7dSDavid van Moolenbroek 		return ENOSYS;
46589c9de7dSDavid van Moolenbroek 
46689c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
46789c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
46889c9de7dSDavid van Moolenbroek 		return r;
46989c9de7dSDavid van Moolenbroek 
47089c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
47189c9de7dSDavid van Moolenbroek 		return EEXIST;
47289c9de7dSDavid van Moolenbroek 
47389c9de7dSDavid van Moolenbroek 	return fdp->fdr_mkdir(dir_nr, name, mode, uid, gid);
47489c9de7dSDavid van Moolenbroek }
47589c9de7dSDavid van Moolenbroek 
47689c9de7dSDavid van Moolenbroek /*
47789c9de7dSDavid van Moolenbroek  * Process a MKNOD request from VFS.
47889c9de7dSDavid van Moolenbroek  */
47989c9de7dSDavid van Moolenbroek int
fsdriver_mknod(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)48089c9de7dSDavid van Moolenbroek fsdriver_mknod(const struct fsdriver * __restrict fdp,
48189c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
48289c9de7dSDavid van Moolenbroek {
48389c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
48489c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
48589c9de7dSDavid van Moolenbroek 	size_t path_len;
48689c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
48789c9de7dSDavid van Moolenbroek 	mode_t mode;
48889c9de7dSDavid van Moolenbroek 	uid_t uid;
48989c9de7dSDavid van Moolenbroek 	gid_t gid;
49089c9de7dSDavid van Moolenbroek 	dev_t dev;
49189c9de7dSDavid van Moolenbroek 	int r;
49289c9de7dSDavid van Moolenbroek 
49389c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_mknod.grant;
49489c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_mknod.path_len;
49589c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_mknod.inode;
49689c9de7dSDavid van Moolenbroek 	mode = m_in->m_vfs_fs_mknod.mode;
49789c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_mknod.uid;
49889c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_mknod.gid;
49989c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_mknod.device;
50089c9de7dSDavid van Moolenbroek 
50189c9de7dSDavid van Moolenbroek 	if (fdp->fdr_mknod == NULL)
50289c9de7dSDavid van Moolenbroek 		return ENOSYS;
50389c9de7dSDavid van Moolenbroek 
50489c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
50589c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
50689c9de7dSDavid van Moolenbroek 		return r;
50789c9de7dSDavid van Moolenbroek 
50889c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
50989c9de7dSDavid van Moolenbroek 		return EEXIST;
51089c9de7dSDavid van Moolenbroek 
51189c9de7dSDavid van Moolenbroek 	return fdp->fdr_mknod(dir_nr, name, mode, uid, gid, dev);
51289c9de7dSDavid van Moolenbroek }
51389c9de7dSDavid van Moolenbroek 
51489c9de7dSDavid van Moolenbroek /*
51589c9de7dSDavid van Moolenbroek  * Process a LINK request from VFS.
51689c9de7dSDavid van Moolenbroek  */
51789c9de7dSDavid van Moolenbroek int
fsdriver_link(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)51889c9de7dSDavid van Moolenbroek fsdriver_link(const struct fsdriver * __restrict fdp,
51989c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
52089c9de7dSDavid van Moolenbroek {
52189c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
52289c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
52389c9de7dSDavid van Moolenbroek 	size_t path_len;
52489c9de7dSDavid van Moolenbroek 	ino_t dir_nr, ino_nr;
52589c9de7dSDavid van Moolenbroek 	int r;
52689c9de7dSDavid van Moolenbroek 
52789c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_link.grant;
52889c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_link.path_len;
52989c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_link.dir_ino;
53089c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_link.inode;
53189c9de7dSDavid van Moolenbroek 
53289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_link == NULL)
53389c9de7dSDavid van Moolenbroek 		return ENOSYS;
53489c9de7dSDavid van Moolenbroek 
53589c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
53689c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
53789c9de7dSDavid van Moolenbroek 		return r;
53889c9de7dSDavid van Moolenbroek 
53989c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
54089c9de7dSDavid van Moolenbroek 		return EEXIST;
54189c9de7dSDavid van Moolenbroek 
54289c9de7dSDavid van Moolenbroek 	return fdp->fdr_link(dir_nr, name, ino_nr);
54389c9de7dSDavid van Moolenbroek }
54489c9de7dSDavid van Moolenbroek 
54589c9de7dSDavid van Moolenbroek /*
54689c9de7dSDavid van Moolenbroek  * Process an UNLINK request from VFS.
54789c9de7dSDavid van Moolenbroek  */
54889c9de7dSDavid van Moolenbroek int
fsdriver_unlink(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)54989c9de7dSDavid van Moolenbroek fsdriver_unlink(const struct fsdriver * __restrict fdp,
55089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
55189c9de7dSDavid van Moolenbroek {
55289c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
55389c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
55489c9de7dSDavid van Moolenbroek 	size_t path_len;
55589c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
55689c9de7dSDavid van Moolenbroek 	int r;
55789c9de7dSDavid van Moolenbroek 
55889c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_unlink.grant;
55989c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_unlink.path_len;
56089c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_unlink.inode;
56189c9de7dSDavid van Moolenbroek 
56289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_unlink == NULL)
56389c9de7dSDavid van Moolenbroek 		return ENOSYS;
56489c9de7dSDavid van Moolenbroek 
56589c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
56689c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
56789c9de7dSDavid van Moolenbroek 		return r;
56889c9de7dSDavid van Moolenbroek 
56989c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
57089c9de7dSDavid van Moolenbroek 		return EPERM;
57189c9de7dSDavid van Moolenbroek 
57289c9de7dSDavid van Moolenbroek 	return fdp->fdr_unlink(dir_nr, name, FSC_UNLINK);
57389c9de7dSDavid van Moolenbroek }
57489c9de7dSDavid van Moolenbroek 
57589c9de7dSDavid van Moolenbroek /*
57689c9de7dSDavid van Moolenbroek  * Process a RMDIR request from VFS.
57789c9de7dSDavid van Moolenbroek  */
57889c9de7dSDavid van Moolenbroek int
fsdriver_rmdir(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)57989c9de7dSDavid van Moolenbroek fsdriver_rmdir(const struct fsdriver * __restrict fdp,
58089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
58189c9de7dSDavid van Moolenbroek {
58289c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
58389c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
58489c9de7dSDavid van Moolenbroek 	size_t path_len;
58589c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
58689c9de7dSDavid van Moolenbroek 	int r;
58789c9de7dSDavid van Moolenbroek 
58889c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_unlink.grant;
58989c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_unlink.path_len;
59089c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_unlink.inode;
59189c9de7dSDavid van Moolenbroek 
59289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_rmdir == NULL)
59389c9de7dSDavid van Moolenbroek 		return ENOSYS;
59489c9de7dSDavid van Moolenbroek 
59589c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
59689c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
59789c9de7dSDavid van Moolenbroek 		return r;
59889c9de7dSDavid van Moolenbroek 
59989c9de7dSDavid van Moolenbroek 	if (!strcmp(name, "."))
60089c9de7dSDavid van Moolenbroek 		return EINVAL;
60189c9de7dSDavid van Moolenbroek 
60289c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".."))
60389c9de7dSDavid van Moolenbroek 		return ENOTEMPTY;
60489c9de7dSDavid van Moolenbroek 
60589c9de7dSDavid van Moolenbroek 	return fdp->fdr_rmdir(dir_nr, name, FSC_RMDIR);
60689c9de7dSDavid van Moolenbroek }
60789c9de7dSDavid van Moolenbroek 
60889c9de7dSDavid van Moolenbroek /*
60989c9de7dSDavid van Moolenbroek  * Process a RENAME request from VFS.
61089c9de7dSDavid van Moolenbroek  */
61189c9de7dSDavid van Moolenbroek int
fsdriver_rename(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)61289c9de7dSDavid van Moolenbroek fsdriver_rename(const struct fsdriver * __restrict fdp,
61389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
61489c9de7dSDavid van Moolenbroek {
61589c9de7dSDavid van Moolenbroek 	char old_name[NAME_MAX+1], new_name[NAME_MAX+1];
61689c9de7dSDavid van Moolenbroek 	cp_grant_id_t old_grant, new_grant;
61789c9de7dSDavid van Moolenbroek 	size_t old_len, new_len;
61889c9de7dSDavid van Moolenbroek 	ino_t old_dir_nr, new_dir_nr;
61989c9de7dSDavid van Moolenbroek 	int r;
62089c9de7dSDavid van Moolenbroek 
62189c9de7dSDavid van Moolenbroek 	old_grant = m_in->m_vfs_fs_rename.grant_old;
62289c9de7dSDavid van Moolenbroek 	old_len = m_in->m_vfs_fs_rename.len_old;
62389c9de7dSDavid van Moolenbroek 	old_dir_nr = m_in->m_vfs_fs_rename.dir_old;
62489c9de7dSDavid van Moolenbroek 	new_grant = m_in->m_vfs_fs_rename.grant_new;
62589c9de7dSDavid van Moolenbroek 	new_len = m_in->m_vfs_fs_rename.len_new;
62689c9de7dSDavid van Moolenbroek 	new_dir_nr = m_in->m_vfs_fs_rename.dir_new;
62789c9de7dSDavid van Moolenbroek 
62889c9de7dSDavid van Moolenbroek 	if (fdp->fdr_rename == NULL)
62989c9de7dSDavid van Moolenbroek 		return ENOSYS;
63089c9de7dSDavid van Moolenbroek 
63189c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, old_grant, old_len, old_name,
63289c9de7dSDavid van Moolenbroek 	    sizeof(old_name), TRUE /*not_empty*/)) != OK)
63389c9de7dSDavid van Moolenbroek 		return r;
63489c9de7dSDavid van Moolenbroek 
63589c9de7dSDavid van Moolenbroek 	if (!strcmp(old_name, ".") || !strcmp(old_name, ".."))
63689c9de7dSDavid van Moolenbroek 		return EINVAL;
63789c9de7dSDavid van Moolenbroek 
63889c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, new_grant, new_len, new_name,
63989c9de7dSDavid van Moolenbroek 	    sizeof(new_name), TRUE /*not_empty*/)) != OK)
64089c9de7dSDavid van Moolenbroek 		return r;
64189c9de7dSDavid van Moolenbroek 
64289c9de7dSDavid van Moolenbroek 	if (!strcmp(new_name, ".") || !strcmp(new_name, ".."))
64389c9de7dSDavid van Moolenbroek 		return EINVAL;
64489c9de7dSDavid van Moolenbroek 
64589c9de7dSDavid van Moolenbroek 	return fdp->fdr_rename(old_dir_nr, old_name, new_dir_nr, new_name);
64689c9de7dSDavid van Moolenbroek }
64789c9de7dSDavid van Moolenbroek 
64889c9de7dSDavid van Moolenbroek /*
64989c9de7dSDavid van Moolenbroek  * Process a SLINK request from VFS.
65089c9de7dSDavid van Moolenbroek  */
65189c9de7dSDavid van Moolenbroek int
fsdriver_slink(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)65289c9de7dSDavid van Moolenbroek fsdriver_slink(const struct fsdriver * __restrict fdp,
65389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
65489c9de7dSDavid van Moolenbroek {
65589c9de7dSDavid van Moolenbroek 	struct fsdriver_data data;
65689c9de7dSDavid van Moolenbroek 	char name[NAME_MAX+1];
65789c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
65889c9de7dSDavid van Moolenbroek 	size_t path_len;
65989c9de7dSDavid van Moolenbroek 	ino_t dir_nr;
66089c9de7dSDavid van Moolenbroek 	uid_t uid;
66189c9de7dSDavid van Moolenbroek 	gid_t gid;
66289c9de7dSDavid van Moolenbroek 	int r;
66389c9de7dSDavid van Moolenbroek 
66489c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_slink.grant_path;
66589c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_slink.path_len;
66689c9de7dSDavid van Moolenbroek 	dir_nr = m_in->m_vfs_fs_slink.inode;
66789c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_slink.uid;
66889c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_slink.gid;
66989c9de7dSDavid van Moolenbroek 
67089c9de7dSDavid van Moolenbroek 	if (fdp->fdr_slink == NULL)
67189c9de7dSDavid van Moolenbroek 		return ENOSYS;
67289c9de7dSDavid van Moolenbroek 
67389c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
67489c9de7dSDavid van Moolenbroek 	    sizeof(name), TRUE /*not_empty*/)) != OK)
67589c9de7dSDavid van Moolenbroek 		return r;
67689c9de7dSDavid van Moolenbroek 
67789c9de7dSDavid van Moolenbroek 	if (!strcmp(name, ".") || !strcmp(name, ".."))
67889c9de7dSDavid van Moolenbroek 		return EEXIST;
67989c9de7dSDavid van Moolenbroek 
68089c9de7dSDavid van Moolenbroek 	data.endpt = m_in->m_source;
68189c9de7dSDavid van Moolenbroek 	data.grant = m_in->m_vfs_fs_slink.grant_target;
68289c9de7dSDavid van Moolenbroek 	data.size = m_in->m_vfs_fs_slink.mem_size;
68389c9de7dSDavid van Moolenbroek 
68489c9de7dSDavid van Moolenbroek 	return fdp->fdr_slink(dir_nr, name, uid, gid, &data, data.size);
68589c9de7dSDavid van Moolenbroek }
68689c9de7dSDavid van Moolenbroek 
68789c9de7dSDavid van Moolenbroek /*
68889c9de7dSDavid van Moolenbroek  * Process a RDLINK request from VFS.
68989c9de7dSDavid van Moolenbroek  */
69089c9de7dSDavid van Moolenbroek int
fsdriver_rdlink(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)69189c9de7dSDavid van Moolenbroek fsdriver_rdlink(const struct fsdriver * __restrict fdp,
69289c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
69389c9de7dSDavid van Moolenbroek {
69489c9de7dSDavid van Moolenbroek 	struct fsdriver_data data;
69589c9de7dSDavid van Moolenbroek 	ssize_t r;
69689c9de7dSDavid van Moolenbroek 
69789c9de7dSDavid van Moolenbroek 	if (fdp->fdr_rdlink == NULL)
69889c9de7dSDavid van Moolenbroek 		return ENOSYS;
69989c9de7dSDavid van Moolenbroek 
70089c9de7dSDavid van Moolenbroek 	data.endpt = m_in->m_source;
70189c9de7dSDavid van Moolenbroek 	data.grant = m_in->m_vfs_fs_rdlink.grant;
70289c9de7dSDavid van Moolenbroek 	data.size = m_in->m_vfs_fs_rdlink.mem_size;
70389c9de7dSDavid van Moolenbroek 
70489c9de7dSDavid van Moolenbroek 	r = fdp->fdr_rdlink(m_in->m_vfs_fs_rdlink.inode, &data, data.size);
70589c9de7dSDavid van Moolenbroek 
70689c9de7dSDavid van Moolenbroek 	if (r >= 0) {
70789c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_rdlink.nbytes = r;
70889c9de7dSDavid van Moolenbroek 		r = OK;
70989c9de7dSDavid van Moolenbroek 	}
71089c9de7dSDavid van Moolenbroek 
71189c9de7dSDavid van Moolenbroek 	return r;
71289c9de7dSDavid van Moolenbroek }
71389c9de7dSDavid van Moolenbroek 
71489c9de7dSDavid van Moolenbroek /*
71589c9de7dSDavid van Moolenbroek  * Process a STAT request from VFS.
71689c9de7dSDavid van Moolenbroek  */
71789c9de7dSDavid van Moolenbroek int
fsdriver_stat(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)71889c9de7dSDavid van Moolenbroek fsdriver_stat(const struct fsdriver * __restrict fdp,
71989c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
72089c9de7dSDavid van Moolenbroek {
72189c9de7dSDavid van Moolenbroek 	struct stat buf;
72289c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
72389c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
72489c9de7dSDavid van Moolenbroek 	int r;
72589c9de7dSDavid van Moolenbroek 
72689c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_stat.inode;
72789c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_stat.grant;
72889c9de7dSDavid van Moolenbroek 
72989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_stat == NULL)
73089c9de7dSDavid van Moolenbroek 		return ENOSYS;
73189c9de7dSDavid van Moolenbroek 
73289c9de7dSDavid van Moolenbroek 	memset(&buf, 0, sizeof(buf));
733289b0467SDavid van Moolenbroek 	buf.st_dev = fsdriver_device;
73422840deaSDavid van Moolenbroek 	buf.st_ino = ino_nr;
73589c9de7dSDavid van Moolenbroek 
73689c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_stat(ino_nr, &buf)) == OK)
73789c9de7dSDavid van Moolenbroek 		r = sys_safecopyto(m_in->m_source, grant, 0, (vir_bytes)&buf,
73889c9de7dSDavid van Moolenbroek 		    (phys_bytes)sizeof(buf));
73989c9de7dSDavid van Moolenbroek 
74089c9de7dSDavid van Moolenbroek 	return r;
74189c9de7dSDavid van Moolenbroek }
74289c9de7dSDavid van Moolenbroek 
74389c9de7dSDavid van Moolenbroek /*
74489c9de7dSDavid van Moolenbroek  * Process a CHOWN request from VFS.
74589c9de7dSDavid van Moolenbroek  */
74689c9de7dSDavid van Moolenbroek int
fsdriver_chown(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)74789c9de7dSDavid van Moolenbroek fsdriver_chown(const struct fsdriver * __restrict fdp,
74889c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
74989c9de7dSDavid van Moolenbroek {
75089c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
75189c9de7dSDavid van Moolenbroek 	uid_t uid;
75289c9de7dSDavid van Moolenbroek 	gid_t gid;
75389c9de7dSDavid van Moolenbroek 	mode_t mode;
75489c9de7dSDavid van Moolenbroek 	int r;
75589c9de7dSDavid van Moolenbroek 
75689c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_chown.inode;
75789c9de7dSDavid van Moolenbroek 	uid = m_in->m_vfs_fs_chown.uid;
75889c9de7dSDavid van Moolenbroek 	gid = m_in->m_vfs_fs_chown.gid;
75989c9de7dSDavid van Moolenbroek 
76089c9de7dSDavid van Moolenbroek 	if (fdp->fdr_chown == NULL)
76189c9de7dSDavid van Moolenbroek 		return ENOSYS;
76289c9de7dSDavid van Moolenbroek 
76389c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_chown(ino_nr, uid, gid, &mode)) == OK)
76489c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_chown.mode = mode;
76589c9de7dSDavid van Moolenbroek 
76689c9de7dSDavid van Moolenbroek 	return r;
76789c9de7dSDavid van Moolenbroek }
76889c9de7dSDavid van Moolenbroek 
76989c9de7dSDavid van Moolenbroek /*
77089c9de7dSDavid van Moolenbroek  * Process a CHMOD request from VFS.
77189c9de7dSDavid van Moolenbroek  */
77289c9de7dSDavid van Moolenbroek int
fsdriver_chmod(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)77389c9de7dSDavid van Moolenbroek fsdriver_chmod(const struct fsdriver * __restrict fdp,
77489c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
77589c9de7dSDavid van Moolenbroek {
77689c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
77789c9de7dSDavid van Moolenbroek 	mode_t mode;
77889c9de7dSDavid van Moolenbroek 	int r;
77989c9de7dSDavid van Moolenbroek 
78089c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_chmod.inode;
78189c9de7dSDavid van Moolenbroek 	mode = m_in->m_vfs_fs_chmod.mode;
78289c9de7dSDavid van Moolenbroek 
78389c9de7dSDavid van Moolenbroek 	if (fdp->fdr_chmod == NULL)
78489c9de7dSDavid van Moolenbroek 		return ENOSYS;
78589c9de7dSDavid van Moolenbroek 
78689c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_chmod(ino_nr, &mode)) == OK)
78789c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_chmod.mode = mode;
78889c9de7dSDavid van Moolenbroek 
78989c9de7dSDavid van Moolenbroek 	return r;
79089c9de7dSDavid van Moolenbroek }
79189c9de7dSDavid van Moolenbroek 
79289c9de7dSDavid van Moolenbroek /*
79389c9de7dSDavid van Moolenbroek  * Process a UTIME request from VFS.
79489c9de7dSDavid van Moolenbroek  */
79589c9de7dSDavid van Moolenbroek int
fsdriver_utime(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)79689c9de7dSDavid van Moolenbroek fsdriver_utime(const struct fsdriver * __restrict fdp,
79789c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
79889c9de7dSDavid van Moolenbroek {
79989c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
80089c9de7dSDavid van Moolenbroek 	struct timespec atime, mtime;
80189c9de7dSDavid van Moolenbroek 
80289c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_utime.inode;
80389c9de7dSDavid van Moolenbroek 	atime.tv_sec = m_in->m_vfs_fs_utime.actime;
80489c9de7dSDavid van Moolenbroek 	atime.tv_nsec = m_in->m_vfs_fs_utime.acnsec;
80589c9de7dSDavid van Moolenbroek 	mtime.tv_sec = m_in->m_vfs_fs_utime.modtime;
80689c9de7dSDavid van Moolenbroek 	mtime.tv_nsec = m_in->m_vfs_fs_utime.modnsec;
80789c9de7dSDavid van Moolenbroek 
80889c9de7dSDavid van Moolenbroek 	if (fdp->fdr_utime == NULL)
80989c9de7dSDavid van Moolenbroek 		return ENOSYS;
81089c9de7dSDavid van Moolenbroek 
81189c9de7dSDavid van Moolenbroek 	return fdp->fdr_utime(ino_nr, &atime, &mtime);
81289c9de7dSDavid van Moolenbroek }
81389c9de7dSDavid van Moolenbroek 
81489c9de7dSDavid van Moolenbroek /*
81589c9de7dSDavid van Moolenbroek  * Process a MOUNTPOINT request from VFS.
81689c9de7dSDavid van Moolenbroek  */
81789c9de7dSDavid van Moolenbroek int
fsdriver_mountpoint(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)81889c9de7dSDavid van Moolenbroek fsdriver_mountpoint(const struct fsdriver * __restrict fdp,
81989c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
82089c9de7dSDavid van Moolenbroek {
82189c9de7dSDavid van Moolenbroek 	ino_t ino_nr;
82289c9de7dSDavid van Moolenbroek 
82389c9de7dSDavid van Moolenbroek 	ino_nr = m_in->m_vfs_fs_mountpoint.inode;
82489c9de7dSDavid van Moolenbroek 
82589c9de7dSDavid van Moolenbroek 	if (fdp->fdr_mountpt == NULL)
82689c9de7dSDavid van Moolenbroek 		return ENOSYS;
82789c9de7dSDavid van Moolenbroek 
82889c9de7dSDavid van Moolenbroek 	return fdp->fdr_mountpt(ino_nr);
82989c9de7dSDavid van Moolenbroek }
83089c9de7dSDavid van Moolenbroek 
83189c9de7dSDavid van Moolenbroek /*
83289c9de7dSDavid van Moolenbroek  * Process a STATVFS request from VFS.
83389c9de7dSDavid van Moolenbroek  */
83489c9de7dSDavid van Moolenbroek int
fsdriver_statvfs(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)83589c9de7dSDavid van Moolenbroek fsdriver_statvfs(const struct fsdriver * __restrict fdp,
83689c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
83789c9de7dSDavid van Moolenbroek {
83889c9de7dSDavid van Moolenbroek 	struct statvfs buf;
83989c9de7dSDavid van Moolenbroek 	int r;
84089c9de7dSDavid van Moolenbroek 
84189c9de7dSDavid van Moolenbroek 	if (fdp->fdr_statvfs == NULL)
84289c9de7dSDavid van Moolenbroek 		return ENOSYS;
84389c9de7dSDavid van Moolenbroek 
84489c9de7dSDavid van Moolenbroek 	memset(&buf, 0, sizeof(buf));
84589c9de7dSDavid van Moolenbroek 
84689c9de7dSDavid van Moolenbroek 	if ((r = fdp->fdr_statvfs(&buf)) != OK)
84789c9de7dSDavid van Moolenbroek 		return r;
84889c9de7dSDavid van Moolenbroek 
84989c9de7dSDavid van Moolenbroek 	return sys_safecopyto(m_in->m_source, m_in->m_vfs_fs_statvfs.grant, 0,
85089c9de7dSDavid van Moolenbroek 	    (vir_bytes)&buf, (phys_bytes)sizeof(buf));
85189c9de7dSDavid van Moolenbroek }
85289c9de7dSDavid van Moolenbroek 
85389c9de7dSDavid van Moolenbroek /*
85489c9de7dSDavid van Moolenbroek  * Process a SYNC request from VFS.
85589c9de7dSDavid van Moolenbroek  */
85689c9de7dSDavid van Moolenbroek int
fsdriver_sync(const struct fsdriver * __restrict fdp,const message * __restrict __unused m_in,message * __restrict __unused m_out)85789c9de7dSDavid van Moolenbroek fsdriver_sync(const struct fsdriver * __restrict fdp,
85889c9de7dSDavid van Moolenbroek 	const message * __restrict __unused m_in,
85989c9de7dSDavid van Moolenbroek 	message * __restrict __unused m_out)
86089c9de7dSDavid van Moolenbroek {
86189c9de7dSDavid van Moolenbroek 
86289c9de7dSDavid van Moolenbroek 	if (fdp->fdr_sync != NULL)
86389c9de7dSDavid van Moolenbroek 		fdp->fdr_sync();
86489c9de7dSDavid van Moolenbroek 
86589c9de7dSDavid van Moolenbroek 	return OK;
86689c9de7dSDavid van Moolenbroek }
86789c9de7dSDavid van Moolenbroek 
86889c9de7dSDavid van Moolenbroek /*
86989c9de7dSDavid van Moolenbroek  * Process a NEW_DRIVER request from VFS.
87089c9de7dSDavid van Moolenbroek  */
87189c9de7dSDavid van Moolenbroek int
fsdriver_newdriver(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)87289c9de7dSDavid van Moolenbroek fsdriver_newdriver(const struct fsdriver * __restrict fdp,
87389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
87489c9de7dSDavid van Moolenbroek {
87589c9de7dSDavid van Moolenbroek 	char label[DS_MAX_KEYLEN];
87689c9de7dSDavid van Moolenbroek 	cp_grant_id_t grant;
87789c9de7dSDavid van Moolenbroek 	size_t path_len;
87889c9de7dSDavid van Moolenbroek 	dev_t dev;
87989c9de7dSDavid van Moolenbroek 	int r;
88089c9de7dSDavid van Moolenbroek 
88189c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_new_driver.device;
88289c9de7dSDavid van Moolenbroek 	grant = m_in->m_vfs_fs_new_driver.grant;
88389c9de7dSDavid van Moolenbroek 	path_len = m_in->m_vfs_fs_new_driver.path_len;
88489c9de7dSDavid van Moolenbroek 
88589c9de7dSDavid van Moolenbroek 	if (fdp->fdr_driver == NULL)
88689c9de7dSDavid van Moolenbroek 		return OK;
88789c9de7dSDavid van Moolenbroek 
88889c9de7dSDavid van Moolenbroek 	if ((r = fsdriver_getname(m_in->m_source, grant, path_len, label,
88989c9de7dSDavid van Moolenbroek 	    sizeof(label), FALSE /*not_empty*/)) != OK)
89089c9de7dSDavid van Moolenbroek 		return r;
89189c9de7dSDavid van Moolenbroek 
89289c9de7dSDavid van Moolenbroek 	fdp->fdr_driver(dev, label);
89389c9de7dSDavid van Moolenbroek 
89489c9de7dSDavid van Moolenbroek 	return OK;
89589c9de7dSDavid van Moolenbroek }
89689c9de7dSDavid van Moolenbroek 
89789c9de7dSDavid van Moolenbroek /*
89889c9de7dSDavid van Moolenbroek  * Process a block read or write request from VFS.
89989c9de7dSDavid van Moolenbroek  */
90089c9de7dSDavid van Moolenbroek static ssize_t
bread_bwrite(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out,int call)90189c9de7dSDavid van Moolenbroek bread_bwrite(const struct fsdriver * __restrict fdp,
90289c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out, int call)
90389c9de7dSDavid van Moolenbroek {
90489c9de7dSDavid van Moolenbroek 	struct fsdriver_data data;
90589c9de7dSDavid van Moolenbroek 	dev_t dev;
90689c9de7dSDavid van Moolenbroek 	off_t pos;
90789c9de7dSDavid van Moolenbroek 	size_t nbytes;
90889c9de7dSDavid van Moolenbroek 	ssize_t r;
90989c9de7dSDavid van Moolenbroek 
91089c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_breadwrite.device;
91189c9de7dSDavid van Moolenbroek 	pos = m_in->m_vfs_fs_breadwrite.seek_pos;
91289c9de7dSDavid van Moolenbroek 	nbytes = m_in->m_vfs_fs_breadwrite.nbytes;
91389c9de7dSDavid van Moolenbroek 
91489c9de7dSDavid van Moolenbroek 	if (pos < 0 || nbytes > SSIZE_MAX)
91589c9de7dSDavid van Moolenbroek 		return EINVAL;
91689c9de7dSDavid van Moolenbroek 
91789c9de7dSDavid van Moolenbroek 	data.endpt = m_in->m_source;
91889c9de7dSDavid van Moolenbroek 	data.grant = m_in->m_vfs_fs_breadwrite.grant;
91989c9de7dSDavid van Moolenbroek 	data.size = nbytes;
92089c9de7dSDavid van Moolenbroek 
92189c9de7dSDavid van Moolenbroek 	if (call == FSC_WRITE)
92289c9de7dSDavid van Moolenbroek 		r = fdp->fdr_bwrite(dev, &data, nbytes, pos, call);
92389c9de7dSDavid van Moolenbroek 	else
92489c9de7dSDavid van Moolenbroek 		r = fdp->fdr_bread(dev, &data, nbytes, pos, call);
92589c9de7dSDavid van Moolenbroek 
92689c9de7dSDavid van Moolenbroek 	if (r >= 0) {
92789c9de7dSDavid van Moolenbroek 		pos += r;
92889c9de7dSDavid van Moolenbroek 
92989c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_breadwrite.seek_pos = pos;
93089c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_breadwrite.nbytes = r;
93189c9de7dSDavid van Moolenbroek 		r = OK;
93289c9de7dSDavid van Moolenbroek 	}
93389c9de7dSDavid van Moolenbroek 
93489c9de7dSDavid van Moolenbroek 	return r;
93589c9de7dSDavid van Moolenbroek }
93689c9de7dSDavid van Moolenbroek 
93789c9de7dSDavid van Moolenbroek /*
93889c9de7dSDavid van Moolenbroek  * Process a BREAD request from VFS.
93989c9de7dSDavid van Moolenbroek  */
94089c9de7dSDavid van Moolenbroek ssize_t
fsdriver_bread(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)94189c9de7dSDavid van Moolenbroek fsdriver_bread(const struct fsdriver * __restrict fdp,
94289c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
94389c9de7dSDavid van Moolenbroek {
94489c9de7dSDavid van Moolenbroek 
94589c9de7dSDavid van Moolenbroek 	if (fdp->fdr_bread == NULL)
94689c9de7dSDavid van Moolenbroek 		return ENOSYS;
94789c9de7dSDavid van Moolenbroek 
94889c9de7dSDavid van Moolenbroek 	return bread_bwrite(fdp, m_in, m_out, FSC_READ);
94989c9de7dSDavid van Moolenbroek }
95089c9de7dSDavid van Moolenbroek 
95189c9de7dSDavid van Moolenbroek /*
95289c9de7dSDavid van Moolenbroek  * Process a BWRITE request from VFS.
95389c9de7dSDavid van Moolenbroek  */
95489c9de7dSDavid van Moolenbroek ssize_t
fsdriver_bwrite(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict m_out)95589c9de7dSDavid van Moolenbroek fsdriver_bwrite(const struct fsdriver * __restrict fdp,
95689c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict m_out)
95789c9de7dSDavid van Moolenbroek {
95889c9de7dSDavid van Moolenbroek 
95989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_bwrite == NULL)
96089c9de7dSDavid van Moolenbroek 		return ENOSYS;
96189c9de7dSDavid van Moolenbroek 
96289c9de7dSDavid van Moolenbroek 	return bread_bwrite(fdp, m_in, m_out, FSC_WRITE);
96389c9de7dSDavid van Moolenbroek }
96489c9de7dSDavid van Moolenbroek 
96589c9de7dSDavid van Moolenbroek /*
96689c9de7dSDavid van Moolenbroek  * Process a BPEEK request from VFS.
96789c9de7dSDavid van Moolenbroek  */
96889c9de7dSDavid van Moolenbroek int
fsdriver_bpeek(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)96989c9de7dSDavid van Moolenbroek fsdriver_bpeek(const struct fsdriver * __restrict fdp,
97089c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
97189c9de7dSDavid van Moolenbroek {
97289c9de7dSDavid van Moolenbroek 	dev_t dev;
97389c9de7dSDavid van Moolenbroek 	off_t pos;
97489c9de7dSDavid van Moolenbroek 	size_t nbytes;
97589c9de7dSDavid van Moolenbroek 	ssize_t r;
97689c9de7dSDavid van Moolenbroek 
97789c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_breadwrite.device;
97889c9de7dSDavid van Moolenbroek 	pos = m_in->m_vfs_fs_breadwrite.seek_pos;
97989c9de7dSDavid van Moolenbroek 	nbytes = m_in->m_vfs_fs_breadwrite.nbytes;
98089c9de7dSDavid van Moolenbroek 
98189c9de7dSDavid van Moolenbroek 	if (fdp->fdr_bpeek == NULL)
98289c9de7dSDavid van Moolenbroek 		return ENOSYS;
98389c9de7dSDavid van Moolenbroek 
98489c9de7dSDavid van Moolenbroek 	if (pos < 0 || nbytes > SSIZE_MAX)
98589c9de7dSDavid van Moolenbroek 		return EINVAL;
98689c9de7dSDavid van Moolenbroek 
98789c9de7dSDavid van Moolenbroek 	r = fdp->fdr_bpeek(dev, NULL /*data*/, nbytes, pos, FSC_PEEK);
98889c9de7dSDavid van Moolenbroek 
98989c9de7dSDavid van Moolenbroek 	/* Do not return a new position. */
99089c9de7dSDavid van Moolenbroek 	if (r >= 0) {
99189c9de7dSDavid van Moolenbroek 		m_out->m_fs_vfs_breadwrite.nbytes = r;
99289c9de7dSDavid van Moolenbroek 		r = OK;
99389c9de7dSDavid van Moolenbroek 	}
99489c9de7dSDavid van Moolenbroek 
99589c9de7dSDavid van Moolenbroek 	return r;
99689c9de7dSDavid van Moolenbroek }
99789c9de7dSDavid van Moolenbroek 
99889c9de7dSDavid van Moolenbroek /*
99989c9de7dSDavid van Moolenbroek  * Process a FLUSH request from VFS.
100089c9de7dSDavid van Moolenbroek  */
100189c9de7dSDavid van Moolenbroek int
fsdriver_flush(const struct fsdriver * __restrict fdp,const message * __restrict m_in,message * __restrict __unused m_out)100289c9de7dSDavid van Moolenbroek fsdriver_flush(const struct fsdriver * __restrict fdp,
100389c9de7dSDavid van Moolenbroek 	const message * __restrict m_in, message * __restrict __unused m_out)
100489c9de7dSDavid van Moolenbroek {
100589c9de7dSDavid van Moolenbroek 	dev_t dev;
100689c9de7dSDavid van Moolenbroek 
100789c9de7dSDavid van Moolenbroek 	dev = m_in->m_vfs_fs_flush.device;
100889c9de7dSDavid van Moolenbroek 
100989c9de7dSDavid van Moolenbroek 	if (fdp->fdr_bflush != NULL)
101089c9de7dSDavid van Moolenbroek 		fdp->fdr_bflush(dev);
101189c9de7dSDavid van Moolenbroek 
101289c9de7dSDavid van Moolenbroek 	return OK;
101389c9de7dSDavid van Moolenbroek }
1014