@@ -104,6 +104,7 @@ typedef struct FileOperations
int (*name_to_path)(FsContext *, V9fsPath *, const char *, V9fsPath *);
int (*renameat)(FsContext *ctx, V9fsPath *olddir, const char *old_name,
V9fsPath *newdir, const char *new_name);
+ int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
void *opaque;
} FileOperations;
@@ -184,6 +184,22 @@ int v9fs_co_remove(V9fsState *s, V9fsPath *path)
return err;
}
+int v9fs_co_unlinkat(V9fsState *s, V9fsPath *path, V9fsString *name, int flags)
+{
+ int err;
+
+ qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ qemu_co_rwlock_unlock(&s->rename_lock);
+ return err;
+}
+
/* Only work with path name based fid */
int v9fs_co_rename(V9fsState *s, V9fsPath *oldpath, V9fsPath *newpath)
{
@@ -77,6 +77,7 @@ extern int v9fs_co_mkdir(V9fsState *, V9fsFidState *, V9fsString *,
mode_t, uid_t, gid_t, struct stat *);
extern int v9fs_co_remove(V9fsState *, V9fsPath *);
extern int v9fs_co_rename(V9fsState *, V9fsPath *, V9fsPath *);
+extern int v9fs_co_unlinkat(V9fsState *, V9fsPath *, V9fsString *, int flags);
extern int v9fs_co_renameat(V9fsState *, V9fsPath *, V9fsString *,
V9fsPath *, V9fsString *);
extern int v9fs_co_fstat(V9fsState *, int, struct stat *);
@@ -631,6 +631,21 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir,
return ret;
}
+static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
+ const char *name, int flags)
+{
+ int ret;
+ V9fsString fullname;
+ char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+
+ v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+ ret = remove(rpath(ctx, fullname.data, buffer));
+ v9fs_string_free(&fullname);
+
+ return ret;
+}
+
FileOperations local_ops = {
.lstat = local_lstat,
.readlink = local_readlink,
@@ -664,4 +679,5 @@ FileOperations local_ops = {
.lremovexattr = local_lremovexattr,
.name_to_path = local_name_to_path,
.renameat = local_renameat,
+ .unlinkat = local_unlinkat,
};
@@ -2378,6 +2378,49 @@ out_nofid:
complete_pdu(pdu->s, pdu, err);
}
+static void v9fs_unlinkat(void *opaque)
+{
+ int err = 0;
+ V9fsString name;
+ int32_t dfid, flags;
+ size_t offset = 7;
+ V9fsPath path;
+ V9fsFidState *dfidp;
+ V9fsPDU *pdu = opaque;
+
+ pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
+
+ dfidp = get_fid(pdu->s, dfid);
+ if (dfidp == NULL) {
+ err = -EINVAL;
+ goto out_nofid;
+ }
+ /*
+ * IF the file is unlinked, we cannot reopen
+ * the file later. So don't reclaim fd
+ */
+ v9fs_path_init(&path);
+ err = v9fs_co_name_to_path(pdu->s, &dfidp->path, name.data, &path);
+ if (err < 0) {
+ goto out_err;
+ }
+ err = v9fs_mark_fids_unreclaim(pdu->s, &path);
+ if (err < 0) {
+ goto out_err;
+ }
+ err = v9fs_co_unlinkat(pdu->s, &dfidp->path, &name, flags);
+ if (!err) {
+ err = offset;
+ }
+out_err:
+ put_fid(pdu->s, dfidp);
+ v9fs_path_free(&path);
+ v9fs_string_free(&name);
+out_nofid:
+ complete_pdu(pdu->s, pdu, err);
+}
+
+
/* Only works with path name based fid */
static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
int32_t newdirfid, V9fsString *name)
@@ -3058,6 +3101,7 @@ static CoroutineEntry *pdu_co_handlers[] = {
[P9_TGETLOCK] = v9fs_getlock,
[P9_TRENAMEAT] = v9fs_renameat,
[P9_TREADLINK] = v9fs_readlink,
+ [P9_TUNLINKAT] = v9fs_unlinkat,
[P9_TMKDIR] = v9fs_mkdir,
[P9_TVERSION] = v9fs_version,
[P9_TLOPEN] = v9fs_open,
@@ -54,6 +54,8 @@ enum {
P9_RMKDIR,
P9_TRENAMEAT = 74,
P9_RRENAMEAT,
+ P9_TUNLINKAT = 76,
+ P9_RUNLINKAT,
P9_TVERSION = 100,
P9_RVERSION,
P9_TAUTH = 102,
unlinkat - Remove a directory entry size[4] Tunlinkat tag[2] dirfid[4] name[s] flag[4] size[4] Runlinkat tag[2] older Tremove have the below request format size[4] Tremove tag[2] fid[4] The remove message is used to remove a directory entry either file or directory The remove opreation is actually a directory opertation and should ideally have dirfid, if not we cannot represent the fid on server with anything other than name. We will have to derive the directory name from fid in the Tremove request. NOTE: The operation doesn't clunk the unlink fid. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> --- fsdev/file-op-9p.h | 1 + hw/9pfs/cofs.c | 16 ++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + hw/9pfs/virtio-9p-local.c | 16 ++++++++++++++++ hw/9pfs/virtio-9p.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p.h | 2 ++ 6 files changed, 80 insertions(+), 0 deletions(-)