tools/xen-9pfsd: add 9pfs stat request support

Add the stat 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:
Juergen Gross authored and Andrew Cooper committed 2024-02-15 16:24:39 +00:00
1 parent 34449f8cf0
commit 01c569f3fc
1 file changed
+102
+102
View File
@@ -34,6 +34,7 @@
#define P9_CMD_OPEN 112
#define P9_CMD_CREATE 114
#define P9_CMD_CLUNK 120
#define P9_CMD_STAT 124
/* P9 protocol open flags. */
#define P9_OREAD 0 /* read */
@@ -60,6 +61,25 @@ struct p9_qid {
uint64_t path;
};
struct p9_stat {
uint16_t size;
uint16_t type;
uint32_t dev;
struct p9_qid qid;
uint32_t mode;
uint32_t atime;
uint32_t mtime;
uint64_t length;
const char *name;
const char *uid;
const char *gid;
const char *muid;
const char *extension;
uint32_t n_uid;
uint32_t n_gid;
uint32_t n_muid;
};
/*
* Note that the ring names "in" and "out" are from the frontend's
* perspective, so the "in" ring will be used for responses to the frontend,
@@ -166,6 +186,7 @@ static void fmt_err(const char *fmt)
* S: String (2 byte length + <length> characters)
* The length is obtained via strlen() of the parameter, being a pointer
* to the first character of the string
* s: stat (struct p9_stat)
* U: 4 byte unsigned integer
* The parameter is a pointer to a uint32_t value
*/
@@ -176,6 +197,8 @@ static void vfill_buffer_at(void **data, const char *fmt, va_list ap)
const void *par;
const char *str_val;
const struct p9_qid *qid;
const struct p9_stat *stat;
uint16_t tlen;
unsigned int len;
unsigned int array_sz = 0;
unsigned int elem_sz = 0;
@@ -259,6 +282,18 @@ static void vfill_buffer_at(void **data, const char *fmt, va_list ap)
*data += len;
break;
case 's':
stat = par;
elem_sz = sizeof(*stat);
tlen = stat->size + sizeof(stat->size);
fill_buffer_at(data, "uuuUQUUULSSSSSUUU", &tlen, &stat->size,
&stat->type, &stat->dev, &stat->qid, &stat->mode,
&stat->atime, &stat->mtime, &stat->length,
stat->name, stat->uid, stat->gid, stat->muid,
stat->extension, &stat->n_uid, &stat->n_gid,
&stat->n_muid);
break;
case 'U':
put_unaligned(*(const uint32_t *)par, (uint32_t *)*data);
elem_sz = sizeof(uint32_t);
@@ -1146,6 +1181,69 @@ static void p9_clunk(struct ring *ring, struct p9_header *hdr)
fill_buffer(ring, hdr->cmd + 1, hdr->tag, "");
}
static void fill_p9_stat(device *device, struct p9_stat *p9s, struct stat *st,
const char *name)
{
memset(p9s, 0, sizeof(*p9s));
fill_qid(device, NULL, &p9s->qid, st);
p9s->mode = st->st_mode & 0777;
if ( S_ISDIR(st->st_mode) )
p9s->mode |= P9_CREATE_PERM_DIR;
p9s->atime = st->st_atime;
p9s->mtime = st->st_mtime;
p9s->length = st->st_size;
p9s->name = name;
p9s->uid = "";
p9s->gid = "";
p9s->muid = "";
p9s->extension = "";
p9s->n_uid = 0;
p9s->n_gid = 0;
p9s->n_muid = 0;
/*
* Size of individual fields without the size field, including 5 2-byte
* string length fields.
*/
p9s->size = 71 + strlen(p9s->name);
}
static void p9_stat(struct ring *ring, struct p9_header *hdr)
{
device *device = ring->device;
uint32_t fid;
struct p9_fid *fidp;
struct p9_stat p9s;
struct stat st;
int ret;
ret = fill_data(ring, "U", &fid);
if ( ret != 1 )
{
p9_error(ring, hdr->tag, EINVAL);
return;
}
fidp = get_fid_ref(device, fid);
if ( !fidp )
{
p9_error(ring, hdr->tag, ENOENT);
return;
}
if ( fstatat(device->root_fd, fidp->path, &st, 0) < 0 )
{
p9_error(ring, hdr->tag, errno);
goto out;
}
fill_p9_stat(device, &p9s, &st, strrchr(fidp->path, '/') + 1);
fill_buffer(ring, hdr->cmd + 1, hdr->tag, "s", &p9s);
out:
free_fid(device, fidp);
}
void *io_thread(void *arg)
{
struct ring *ring = arg;
@@ -1225,6 +1323,10 @@ void *io_thread(void *arg)
p9_clunk(ring, &hdr);
break;
case P9_CMD_STAT:
p9_stat(ring, &hdr);
break;
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
ring->device->domid, ring->device->devid, hdr.cmd);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.