view docs/fs-protocol.md @ 878:fe84110a0b10

common: extend LINK to include more args and a return value These should have been part of the RPC from the beginning. Since nothing implements LINK yet, we can modify it without dealing with protocol version issues. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sat, 17 Dec 2022 16:32:57 -0500
parents 7f967ffda1ac
children
line wrap: on
line source

This document describes the RPC protocol between the client daemon and the
fs component.  It is still a work-in-progress.

Currently, we use `rpcgen(1)` created XDR encoding.

Before RPC requests are accepted the initiator sends a handshake request using
`struct rpc_handshake_req`. The response uses `struct rpc_header_res` with
success (status code 0) if the version is supported, at which point the
initiator may send RPC requests. On error the initiator must close the
connection without sending more data.

```C
struct rpc_handshake_req {
	uint32_t version;
};
```

Each RPC request begins with a `struct rpc_header_req`.  It is then followed
by a variable number of bytes representing the rest of the request.  The
exact layout of this additional payload depends on the `opcode` in the
request header.

```C
struct rpc_header_req {
	uint16_t opcode;
};
```

Each RPC reply starts with a `struct rpc_header_res` which contains a status
code.  In the case of success (status code is 0), more data may follow
depending on the `opcode` in the request header.

```C
struct rpc_header_res {
	uint32_t err;
};
```

The following list of RPC commands does not explicitly list the request and
response headers since they are always present.  It only lists the
additional fields that follow.


NOP (0x0000)
============

This is a simple no-operation.

Inputs
------
None.

Output
------
None.

Limitations
-----------
None.


LOGIN (0x0001)
==============

The first command sent to the client daemon by the fs component.  It informs
the daemon of a mount request.  Eventually, this will also contain
credentials checking, etc. (hence the name).

Inputs
------
* conn name
* volume id (uuid)

Outputs
-------
* oid of root

Limitations
-----------
At most one successful LOGIN is allowed per connection.  All LOGIN attempts
after a successful LOGIN will fail with `EALREADY`.


GETATTR (0x0002)
================

Get attributes (`struct nattr`) for of an object identified an open file
handle.

Inputs
------
* open file handle

Outputs
-------
* attributes

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


LOOKUP (0x0003)
===============

Given a directory open file handle and a path component (string), do a
lookup of the path component in the directory.

Inputs
------
* directory open file handle
* path component name

Outputs
-------
* child oid

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


CREATE (0x0004)
===============

Given a directory open file handle, a path component (string), and mode
(both type and access bits) create the new path component returning the oid
of the newly created file.  Creating an already existing path component
fails with `EEXIST`.

Inputs
------
* directory open file handle
* path component name
* owner id (uid)
* group id (gid)
* mode (see `NATTR_*`)

Outputs
-------
* new file/dir/etc.'s oid

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


LINK (0x0005)
=============

Given a directory open file handle, a path component (string), a target path
(string), and a symlink bool add a link to the directory making the path
component refer to the file at the target path as either a hardlink or a
symlink.  Hard-linking to a non-existent path fails with `ENOENT`.

If a non-null desired oid is specified, only the dirent matching the oid is
considered as a target.  If a null oid is specificied and there is only one
dirent under that name (in other words, there is no conflict), the dirent is
use as the target.  If a null oid is specified and there are multiple
dirents with the same name, the operation fails with `ENOTUNIQ`.

Symlinks have their own owner, group, and mode.  The returned oid is used
only for symlinks.

Inputs
------
* directory open file handle
* path component name
* target path
* desired target oid
* symlink
* symlink owner
* symlink group
* symlink mode

Outputs
-------
* new symlink oid

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


UNLINK (0x0006)
===============

Given a directory open file handle, a path component (string), and an
optional desired target oid, remove the corresponding path component from
the directory.  Removing a non-existent path component fails with `ENOENT`.

If a non-null desired oid is specified, only the dirent matching the oid is
considered for removal.  If a null oid is specificied and there is only one
dirent under that name (in other words, there is no conflict), the dirent is
removed.  If a null oid is specified and there are multiple dirents with the
same name, the operation fails with `ENOTUNIQ`.

The rmdir bool specifies whether the operation is a rmdir (true) or unlink
(false).

Inputs
------
* directory open file handle
* path component name
* desired target oid
* rmdir semantics

Outputs
-------
None.

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


OPEN (0x0008)
=============

Given a version of an object (oid and vector clock, or inode number and
vector clock), open the specified object and return an open file handle.

If a non-null vector clock is specified, only that version of the object is
considered.  If a null vector clock is specificied and there is only one
version of the object, the attributes of that version are returned.  If a
null vector clock is specified and there are multiple version of the object,
the operation fails with `ENOTUNIQ`.

Inputs
------
* oid
* inode number
* vector clock

Outputs
-------
* open file handle

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


CLOSE (0x0009)
==============

Close an open file handle.  If the handle supplied has not be open via the
OPEN RPC, this operation fails with `EINVAL`.

Inputs
------
* open file handle

Outputs
-------
None.

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


READ (0x000A)
=============

Read a portion of an open object.  Trying to read from a directory fails with
`EISDIR`.  If the requested number of bytes would read beyond the end of the
object, only the data between the requested offset and the end of the object
is returned.  (Therefore, reading with an offset that is greater than or
equal to the object size will yield zero bytes.)

Inputs
------
* open file handle
* offset into the object version's data
* length (in bytes) to read

Outputs
-------
* length of data
* data

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


WRITE (0x000B)
==============

Write a portion of an open object.  Trying to write to a directory fails with
`EISDIR`.  Writing past the end of the object succeeds and the object length is
updated automatically.

The whole write is guaranteed to succeed.

Inputs
------
* open file handle
* offset into the object version's data
* length (in bytes) to write
* data

Outputs
-------
None.

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


SETATTR (0x000C)
================

Set selected attributes on an open object.  Even though the entire attribute
structure is sent, only the attributes marked as valid are set.

Setting the file size either truncates the object to the specified size or
extends it padding it with zero bytes.

Inputs
------
* open file handle
* new attributes (`struct nattr`)
* mode is valid
* size is valid
* atime is valid
* btime is valid
* ctime is valid
* mtime is valid
* owner is valid
* group is valid

Outputs
-------
* full set of attributes

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


GETDENT (0x000D)
================

Get the directory entry at a specific offset in a directory.  Additionally,
it returns the size of the current entry.  Adding this size to the current
offset will yield the offset of the next entry.

Inputs
------
* directory open file handle
* directory offset

Outputs
-------
* child oid
* child name
* entry size

Limitations
-----------
Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.


OBJ_INFO (0x000E)
=================

Get information about an object.

Inputs
------
* oid

Outputs
-------
For each version of the object:

* vector clock


VDEV_IMPORT (0x0100)
====================

Import or create a vdev.

Inputs
------
* type of vdev (e.g., posix or mem)
* path
* create volume bool (true = create, false = import)

Outputs
-------
* vdev uuid


VDEV_LIST (0x0101)
==================

List currently imported vdevs.

Inputs
------
None.

Outputs
-------
For each imported vdev:

* uuid
* type
* path
* size (bytes)
* used (bytes)
* number of volumes


VOL_CREATE (0x0200)
===================

Create or clone a volume.

If the supplied volume uuid is null, a new volume is created on the
specified vdev.  The new volume's uuid is returned.

If the supplied volume uuid is not nul, a clone of the volume onto the
specified vdev is performed.  The returned volume uuid will match the input.

Inputs
------
* vdev uuid
* volume uuid

Outputs
-------
* volume uuid


VOL_LIST (0x0201)
=================

List volumes managed by the server - all or on a specific vdev.

Inputs
------
* vdev uuid (clear to indicate all vdevs)

Outputs
-------
For each loaded volume matching the uuid criteria:

* uuid


Other RPCs that may end up useful
=================================

* RENAME - rename a "file"