mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
tools/xen-9pfsd: add 9pfs open request support
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>
This commit is contained in:
1 parent
9615e40f47
commit
7c0d5f3cac
2 files changed
+141
No files matched your search
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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[];
|
||||
};
|
||||
|
||||
|
||||