Skip to content

Commit

Permalink
tools/xen-9pfsd: add 9pfs open request support
Browse files Browse the repository at this point in the history
Add the open request of the 9pfs protocol.

Signed-off-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
  • Loading branch information
jgross1 authored and andyhhp committed Feb 15, 2024
1 parent 9615e40 commit 7c0d5f3
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
137 changes: 137 additions & 0 deletions tools/9pfsd/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <xenctrl.h> /* For cpu barriers. */
#include <xen-tools/common-macros.h>

Expand All @@ -29,6 +31,15 @@
#define P9_CMD_ATTACH 104
#define P9_CMD_ERROR 107
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112

/* P9 protocol open flags. */
#define P9_OREAD 0 /* read */
#define P9_OWRITE 1 /* write */
#define P9_ORDWR 2 /* read and write */
#define P9_OMODEMASK 0x03
#define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
#define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */

#define P9_MIN_MSIZE 2048
#define P9_VERSION "9P2000.u"
Expand Down Expand Up @@ -827,6 +838,128 @@ static void p9_walk(struct ring *ring, struct p9_header *hdr)
free(names);
}

static int open_flags_from_mode(uint8_t mode)
{
int flags;

switch ( mode & P9_OMODEMASK )
{
case P9_OREAD:
flags = O_RDONLY;
break;

case P9_OWRITE:
flags = O_WRONLY;
break;

case P9_ORDWR:
flags = O_RDWR;
break;

default:
errno = EINVAL;
return -1;
}

if ( mode & P9_OTRUNC )
flags |= O_TRUNC;

return flags;
}

static unsigned int get_iounit(struct ring *ring, struct stat *st)
{
return (ring->max_size - st->st_blksize) & ~(st->st_blksize - 1);
}

static void p9_open(struct ring *ring, struct p9_header *hdr)
{
device *device = ring->device;
uint32_t fid;
uint8_t mode;
struct p9_fid *fidp;
struct stat st;
struct p9_qid qid;
uint32_t iounit;
int flags;
int ret;

ret = fill_data(ring, "Ub", &fid, &mode);
if ( ret != 2 )
{
p9_error(ring, hdr->tag, EINVAL);
return;
}
if ( mode & ~(P9_OMODEMASK | P9_OTRUNC | P9_OREMOVE) )
{
p9_error(ring, hdr->tag, EINVAL);
return;
}

fidp = get_fid_ref(device, fid);
if ( !fidp )
{
p9_error(ring, hdr->tag, ENOENT);
return;
}
if ( fidp->opened )
{
errno = EINVAL;
goto err;
}

if ( fstatat(device->root_fd, fidp->path, &st, 0) < 0 )
{
errno = ENOENT;
goto err;
}

if ( S_ISLNK(st.st_mode) )
{
errno = EMLINK;
goto err;
}

fidp->isdir = S_ISDIR(st.st_mode);
fidp->mode = mode;
if ( fidp->isdir )
{
if ( mode != P9_OREAD )
{
errno = EINVAL;
goto err;
}
fidp->fd = openat(device->root_fd, fidp->path, O_RDONLY);
if ( fidp->fd < 0 )
goto err;
fidp->data = fdopendir(fidp->fd);
if ( !fidp->data )
goto err;
}
else
{
flags = open_flags_from_mode(mode);
if ( flags < 0 )
goto err;

fidp->fd = openat(device->root_fd, fidp->path, flags);
if ( fidp->fd < 0 )
goto err;
}

fill_qid(device, fidp->path, &qid, &st);
iounit = get_iounit(ring, &st);
fidp->opened = true;

fill_buffer(ring, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);

return;

err:
free_fid(device, fidp);
p9_error(ring, hdr->tag, errno);
}

void *io_thread(void *arg)
{
struct ring *ring = arg;
Expand Down Expand Up @@ -894,6 +1027,10 @@ void *io_thread(void *arg)
p9_walk(ring, &hdr);
break;

case P9_CMD_OPEN:
p9_open(ring, &hdr);
break;

default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
ring->device->domid, ring->device->devid, hdr.cmd);
Expand Down
4 changes: 4 additions & 0 deletions tools/9pfsd/xen-9pfsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ struct p9_fid {
XEN_TAILQ_ENTRY(struct p9_fid) list;
unsigned int fid;
unsigned int ref;
int fd;
uint8_t mode;
bool opened;
bool isdir;
void *data; /* File type specific. */
char path[];
};

Expand Down

0 comments on commit 7c0d5f3

Please sign in to comment.