diff mbox

[11/13] 9p: xattr fid to reference file fid

Message ID 146702054693.5764.4075650484995253066.stgit@bahia.lan (mailing list archive)
State New, archived
Headers show

Commit Message

Greg Kurz June 27, 2016, 9:42 a.m. UTC
The flistxattr() and fgetxattr() syscalls in the guest are implementend
with XATTRWALK. In v9fs_xattrwalk(), we then create a xattr fid to
hold the the file path, and retrieve the xattr from the fs backend with
llistxattr() or lgetxattr().

This patch brings file descriptor support to fids with type P9_FID_XATTR,
so that the backend can use flistxattr() and fgetxattr(). This is done by
keeping a reference to the original fid until the xattr fid gets clunked.

Xattr fids created during XATTRCREATE (setxattr/removexattr in the guest),
are not affected: the guest does not provide the related open fid and we
have no reference to keep. In this case, the xattr operation will continue
to be based on the path.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c |   28 ++++++++++++++++++++++++----
 hw/9pfs/9p.h |    1 +
 2 files changed, 25 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 8824b71f364b..d02f95634b97 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -248,6 +248,12 @@  int v9fs_get_fd_fid(int fid_type, V9fsFidOpenState *fs)
         fd = dirfd(fs->dir.stream);
     } else if (fid_type == P9_FID_FILE) {
         fd = fs->fd;
+    } else if (fid_type == P9_FID_XATTR) {
+        V9fsFidState *fidp = fs->xattr.file;
+
+        if (fidp) {
+            return v9fs_get_fd_fid(fidp->fid_type, &fidp->fs);
+        }
     }
 
     return fd;
@@ -265,6 +271,12 @@  static bool fid_has_file(V9fsFidState *fidp)
         if (fidp->fs.fd > -1) {
             return true;
         }
+    } else if (fid_type == P9_FID_XATTR) {
+        V9fsFidState *file = fidp->fs.xattr.file;
+
+        if (file) {
+            return fid_has_file(file);
+        }
     }
 
     return false;
@@ -368,6 +380,8 @@  free_value:
     return retval;
 }
 
+static int put_fid(V9fsPDU *pdu, V9fsFidState *fidp);
+
 static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
 {
     int retval = 0;
@@ -382,7 +396,13 @@  static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
             retval = v9fs_co_closedir(pdu, &fidp->fs);
         }
     } else if (fidp->fid_type == P9_FID_XATTR) {
+        V9fsFidState *file_fidp = fidp->fs.xattr.file;
+
         retval = v9fs_xattr_fid_clunk(pdu, fidp);
+        if (file_fidp) {
+            fidp->fs.xattr.file = NULL;
+            put_fid(pdu, file_fidp);
+        }
     }
     v9fs_path_free(&fidp->path);
     g_free(fidp);
@@ -3125,6 +3145,10 @@  static void v9fs_xattrwalk(void *opaque)
         goto out;
     }
     v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
+    xattr_fidp->fid_type = P9_FID_XATTR;
+    xattr_fidp->fs.xattr.copied_len = -1;
+    xattr_fidp->fs.xattr.file = file_fidp;
+    file_fidp->ref++;
     if (name.data == NULL) {
         /*
          * listxattr request. Get the size first
@@ -3139,8 +3163,6 @@  static void v9fs_xattrwalk(void *opaque)
          * Read the xattr value
          */
         xattr_fidp->fs.xattr.len = size;
-        xattr_fidp->fid_type = P9_FID_XATTR;
-        xattr_fidp->fs.xattr.copied_len = -1;
         if (size) {
             xattr_fidp->fs.xattr.value = g_malloc(size);
             err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
@@ -3172,8 +3194,6 @@  static void v9fs_xattrwalk(void *opaque)
          * Read the xattr value
          */
         xattr_fidp->fs.xattr.len = size;
-        xattr_fidp->fid_type = P9_FID_XATTR;
-        xattr_fidp->fs.xattr.copied_len = -1;
         if (size) {
             xattr_fidp->fs.xattr.value = g_malloc(size);
             err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index d0ccc0089771..0b9db6bd8c38 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -164,6 +164,7 @@  typedef struct V9fsXattr
     void *value;
     V9fsString name;
     int flags;
+    V9fsFidState *file;
 } V9fsXattr;
 
 typedef struct V9fsDir {