qemu/hw/virtio-9p.h
Sripathi Kodi c79ce73747 virtio-9p: Implement server side of setattr for 9P2000.L protocol.
SYNOPSIS

      size[4] Tsetattr tag[2] attr[n]

      size[4] Rsetattr tag[2]

   DESCRIPTION

      The setattr command changes some of the file status information.
      attr resembles the iattr structure used in Linux kernel. It
      specifies which status parameter is to be changed and to what
      value. It is laid out as follows:

         valid[4]
            specifies which status information is to be changed. Possible
            values are:
            ATTR_MODE       (1 << 0)
            ATTR_UID        (1 << 1)
            ATTR_GID        (1 << 2)
            ATTR_SIZE       (1 << 3)
            ATTR_ATIME      (1 << 4)
            ATTR_MTIME      (1 << 5)
            ATTR_CTIME      (1 << 5)
            ATTR_ATIME_SET  (1 << 7)
            ATTR_MTIME_SET  (1 << 8)

            The last two bits represent whether the time information
            is being sent by the client's user space. In the absense
            of these bits the server always uses server's time.

         mode[4]
            File permission bits

         uid[4]
            Owner id of file

         gid[4]
            Group id of the file

         size[8]
            File size

         atime_sec[8]
            Time of last file access, seconds

         atime_nsec[8]
            Time of last file access, nanoseconds

         mtime_sec[8]
            Time of last file modification, seconds

         mtime_nsec[8]
            Time of last file modification, nanoseconds

Explanation of the patches:
--------------------------

*) The kernel just copies relevent contents of iattr structure to p9_iattr_dotl
   structure and passes it down to the client. The only check it has is calling
   inode_change_ok()
*) The p9_iattr_dotl structure does not have ctime and ia_file parameters because
   I don't think these are needed in our case. The client user space can request
   updating just ctime by calling chown(fd, -1, -1). This is handled on server
   side without a need for putting ctime on the wire.
*) The server currently supports changing mode, time, ownership and size of the
   file.
*) 9P RFC says "Either all the changes in wstat request happen, or none of them
   does: if the request succeeds, all changes were made; if it fails, none were."
   I have not done anything to implement this specifically because I don't see
   a reason.

[jvrao@linux.vnet.ibm.com: Parts of code for handling chown(-1,-1)

Signed-off-by: Sripathi Kodi <sripathik@in.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
2010-09-08 22:56:40 +05:30

356 lines
6.7 KiB
C

#ifndef _QEMU_VIRTIO_9P_H
#define _QEMU_VIRTIO_9P_H
#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
#include <utime.h>
#include "file-op-9p.h"
/* The feature bitmap for virtio 9P */
/* The mount point is specified in a config variable */
#define VIRTIO_9P_MOUNT_TAG 0
enum {
P9_TSTATFS = 8,
P9_RSTATFS,
P9_TGETATTR = 24,
P9_RGETATTR,
P9_TSETATTR = 26,
P9_RSETATTR,
P9_TREADDIR = 40,
P9_RREADDIR,
P9_TVERSION = 100,
P9_RVERSION,
P9_TAUTH = 102,
P9_RAUTH,
P9_TATTACH = 104,
P9_RATTACH,
P9_TERROR = 106,
P9_RERROR,
P9_TFLUSH = 108,
P9_RFLUSH,
P9_TWALK = 110,
P9_RWALK,
P9_TOPEN = 112,
P9_ROPEN,
P9_TCREATE = 114,
P9_RCREATE,
P9_TREAD = 116,
P9_RREAD,
P9_TWRITE = 118,
P9_RWRITE,
P9_TCLUNK = 120,
P9_RCLUNK,
P9_TREMOVE = 122,
P9_RREMOVE,
P9_TSTAT = 124,
P9_RSTAT,
P9_TWSTAT = 126,
P9_RWSTAT,
};
/* qid.types */
enum {
P9_QTDIR = 0x80,
P9_QTAPPEND = 0x40,
P9_QTEXCL = 0x20,
P9_QTMOUNT = 0x10,
P9_QTAUTH = 0x08,
P9_QTTMP = 0x04,
P9_QTSYMLINK = 0x02,
P9_QTLINK = 0x01,
P9_QTFILE = 0x00,
};
enum p9_proto_version {
V9FS_PROTO_2000U = 0x01,
V9FS_PROTO_2000L = 0x02,
};
#define P9_NOTAG (u16)(~0)
#define P9_NOFID (u32)(~0)
#define P9_MAXWELEM 16
/*
* ample room for Twrite/Rread header
* size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4]
*/
#define P9_IOHDRSZ 24
typedef struct V9fsPDU V9fsPDU;
struct V9fsPDU
{
uint32_t size;
uint16_t tag;
uint8_t id;
VirtQueueElement elem;
QLIST_ENTRY(V9fsPDU) next;
};
/* FIXME
* 1) change user needs to set groups and stuff
*/
/* from Linux's linux/virtio_9p.h */
/* The ID for virtio console */
#define VIRTIO_ID_9P 9
#define MAX_REQ 128
#define MAX_TAG_LEN 32
#define BUG_ON(cond) assert(!(cond))
typedef struct V9fsFidState V9fsFidState;
typedef struct V9fsString
{
int16_t size;
char *data;
} V9fsString;
typedef struct V9fsQID
{
int8_t type;
int32_t version;
int64_t path;
} V9fsQID;
typedef struct V9fsStat
{
int16_t size;
int16_t type;
int32_t dev;
V9fsQID qid;
int32_t mode;
int32_t atime;
int32_t mtime;
int64_t length;
V9fsString name;
V9fsString uid;
V9fsString gid;
V9fsString muid;
/* 9p2000.u */
V9fsString extension;
int32_t n_uid;
int32_t n_gid;
int32_t n_muid;
} V9fsStat;
struct V9fsFidState
{
int32_t fid;
V9fsString path;
int fd;
DIR *dir;
uid_t uid;
V9fsFidState *next;
};
typedef struct V9fsState
{
VirtIODevice vdev;
VirtQueue *vq;
V9fsPDU pdus[MAX_REQ];
QLIST_HEAD(, V9fsPDU) free_list;
V9fsFidState *fid_list;
FileOperations *ops;
FsContext ctx;
uint16_t tag_len;
uint8_t *tag;
size_t config_size;
enum p9_proto_version proto_version;
int32_t msize;
} V9fsState;
typedef struct V9fsCreateState {
V9fsPDU *pdu;
size_t offset;
V9fsFidState *fidp;
V9fsQID qid;
int32_t perm;
int8_t mode;
struct stat stbuf;
V9fsString name;
V9fsString extension;
V9fsString fullname;
int iounit;
} V9fsCreateState;
typedef struct V9fsStatState {
V9fsPDU *pdu;
size_t offset;
V9fsStat v9stat;
V9fsFidState *fidp;
struct stat stbuf;
} V9fsStatState;
typedef struct V9fsStatDotl {
uint64_t st_result_mask;
V9fsQID qid;
uint32_t st_mode;
uint32_t st_uid;
uint32_t st_gid;
uint64_t st_nlink;
uint64_t st_rdev;
uint64_t st_size;
uint64_t st_blksize;
uint64_t st_blocks;
uint64_t st_atime_sec;
uint64_t st_atime_nsec;
uint64_t st_mtime_sec;
uint64_t st_mtime_nsec;
uint64_t st_ctime_sec;
uint64_t st_ctime_nsec;
uint64_t st_btime_sec;
uint64_t st_btime_nsec;
uint64_t st_gen;
uint64_t st_data_version;
} V9fsStatDotl;
typedef struct V9fsStatStateDotl {
V9fsPDU *pdu;
size_t offset;
V9fsStatDotl v9stat_dotl;
struct stat stbuf;
} V9fsStatStateDotl;
typedef struct V9fsWalkState {
V9fsPDU *pdu;
size_t offset;
int16_t nwnames;
int name_idx;
V9fsQID *qids;
V9fsFidState *fidp;
V9fsFidState *newfidp;
V9fsString path;
V9fsString *wnames;
struct stat stbuf;
} V9fsWalkState;
typedef struct V9fsOpenState {
V9fsPDU *pdu;
size_t offset;
int8_t mode;
V9fsFidState *fidp;
V9fsQID qid;
struct stat stbuf;
int iounit;
} V9fsOpenState;
typedef struct V9fsReadState {
V9fsPDU *pdu;
size_t offset;
int32_t count;
int32_t total;
int64_t off;
V9fsFidState *fidp;
struct iovec iov[128]; /* FIXME: bad, bad, bad */
struct iovec *sg;
off_t dir_pos;
struct dirent *dent;
struct stat stbuf;
V9fsString name;
V9fsStat v9stat;
int32_t len;
int32_t cnt;
int32_t max_count;
} V9fsReadState;
typedef struct V9fsWriteState {
V9fsPDU *pdu;
size_t offset;
int32_t len;
int32_t count;
int32_t total;
int64_t off;
V9fsFidState *fidp;
struct iovec iov[128]; /* FIXME: bad, bad, bad */
struct iovec *sg;
int cnt;
} V9fsWriteState;
typedef struct V9fsRemoveState {
V9fsPDU *pdu;
size_t offset;
V9fsFidState *fidp;
} V9fsRemoveState;
typedef struct V9fsWstatState
{
V9fsPDU *pdu;
size_t offset;
int16_t unused;
V9fsStat v9stat;
V9fsFidState *fidp;
struct stat stbuf;
V9fsString nname;
} V9fsWstatState;
typedef struct V9fsIattr
{
int32_t valid;
int32_t mode;
int32_t uid;
int32_t gid;
int64_t size;
int64_t atime_sec;
int64_t atime_nsec;
int64_t mtime_sec;
int64_t mtime_nsec;
} V9fsIattr;
typedef struct V9fsSetattrState
{
V9fsPDU *pdu;
size_t offset;
V9fsIattr v9iattr;
V9fsFidState *fidp;
} V9fsSetattrState;
struct virtio_9p_config
{
/* number of characters in tag */
uint16_t tag_len;
/* Variable size tag name */
uint8_t tag[0];
} __attribute__((packed));
typedef struct V9fsStatfs
{
uint32_t f_type;
uint32_t f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
uint64_t fsid_val;
uint32_t f_namelen;
} V9fsStatfs;
typedef struct V9fsStatfsState {
V9fsPDU *pdu;
size_t offset;
int32_t fid;
V9fsStatfs v9statfs;
V9fsFidState *fidp;
struct statfs stbuf;
} V9fsStatfsState;
extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
size_t offset, size_t size, int pack);
static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
size_t offset, size_t size)
{
return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
}
#endif