hw/9pfs: Use read-write lock for protecting fid path.
On rename we take the write lock and this ensure path doesn't change as we operate on them. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
This commit is contained in:
		
							parent
							
								
									70c18fc08b
								
							
						
					
					
						commit
						02cb7f3a25
					
				@ -65,22 +65,34 @@ void v9fs_co_rewinddir(V9fsState *s, V9fsFidState *fidp)
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int v9fs_co_mkdir(V9fsState *s, char *name, mode_t mode, uid_t uid, gid_t gid)
 | 
			
		||||
int v9fs_co_mkdir(V9fsState *s, V9fsFidState *fidp, V9fsString *name,
 | 
			
		||||
                  mode_t mode, uid_t uid, gid_t gid, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    FsCred cred;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_mode = mode;
 | 
			
		||||
    cred.fc_uid = uid;
 | 
			
		||||
    cred.fc_gid = gid;
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->mkdir(&s->ctx, name, &cred);
 | 
			
		||||
            err = s->ops->mkdir(&s->ctx, fullname.data, &cred);
 | 
			
		||||
            if (err < 0) {
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            } else {
 | 
			
		||||
                err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
 | 
			
		||||
                if (err < 0) {
 | 
			
		||||
                    err = -errno;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -88,6 +100,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            fidp->fs.dir = s->ops->opendir(&s->ctx, fidp->path.data);
 | 
			
		||||
@ -97,6 +110,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
 | 
			
		||||
                err = 0;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (!err) {
 | 
			
		||||
        total_open_fd++;
 | 
			
		||||
        if (total_open_fd > open_fd_hw) {
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->lstat(&s->ctx, path->data, stbuf);
 | 
			
		||||
@ -28,6 +29,7 @@ int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,6 +51,7 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            fidp->fs.fd = s->ops->open(&s->ctx, fidp->path.data, flags);
 | 
			
		||||
@ -58,6 +61,7 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
 | 
			
		||||
                err = 0;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (!err) {
 | 
			
		||||
        total_open_fd++;
 | 
			
		||||
        if (total_open_fd > open_fd_hw) {
 | 
			
		||||
@ -67,30 +71,48 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid,
 | 
			
		||||
                  int flags, int mode)
 | 
			
		||||
int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, V9fsString *name, gid_t gid,
 | 
			
		||||
                  int flags, int mode, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    FsCred cred;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_mode = mode & 07777;
 | 
			
		||||
    cred.fc_uid = fidp->uid;
 | 
			
		||||
    cred.fc_gid = gid;
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    /*
 | 
			
		||||
     * Hold the directory fid lock so that directory path name
 | 
			
		||||
     * don't change. Read lock is fine because this fid cannot
 | 
			
		||||
     * be used by any other operation.
 | 
			
		||||
     */
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            fidp->fs.fd = s->ops->open2(&s->ctx, fullname, flags, &cred);
 | 
			
		||||
            err = 0;
 | 
			
		||||
            fidp->fs.fd = s->ops->open2(&s->ctx, fullname.data, flags, &cred);
 | 
			
		||||
            if (fidp->fs.fd == -1) {
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            } else {
 | 
			
		||||
                err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
 | 
			
		||||
                if (err < 0) {
 | 
			
		||||
                    err = -errno;
 | 
			
		||||
                    err = s->ops->close(&s->ctx, fidp->fs.fd);
 | 
			
		||||
                } else {
 | 
			
		||||
                    v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (!err) {
 | 
			
		||||
        total_open_fd++;
 | 
			
		||||
        if (total_open_fd > open_fd_hw) {
 | 
			
		||||
            v9fs_reclaim_fd(s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -131,6 +153,7 @@ int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->link(&s->ctx, oldpath->data, newpath->data);
 | 
			
		||||
@ -138,6 +161,7 @@ int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,8 @@ int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
 | 
			
		||||
    ssize_t len;
 | 
			
		||||
 | 
			
		||||
    buf->data = g_malloc(PATH_MAX);
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            len = s->ops->readlink(&s->ctx, path->data,
 | 
			
		||||
@ -35,6 +37,7 @@ int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        g_free(buf->data);
 | 
			
		||||
        buf->data = NULL;
 | 
			
		||||
@ -47,6 +50,7 @@ int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->statfs(&s->ctx, path->data, stbuf);
 | 
			
		||||
@ -54,6 +58,7 @@ int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -64,6 +69,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
 | 
			
		||||
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_mode = mode;
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->chmod(&s->ctx, path->data, &cred);
 | 
			
		||||
@ -71,6 +77,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -79,6 +86,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->utimensat(&s->ctx, path->data, times);
 | 
			
		||||
@ -86,6 +94,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -97,6 +106,7 @@ int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_uid = uid;
 | 
			
		||||
    cred.fc_gid = gid;
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->chown(&s->ctx, path->data, &cred);
 | 
			
		||||
@ -104,6 +114,7 @@ int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -111,6 +122,7 @@ int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->truncate(&s->ctx, path->data, size);
 | 
			
		||||
@ -118,27 +130,39 @@ int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int v9fs_co_mknod(V9fsState *s, V9fsString *path, uid_t uid,
 | 
			
		||||
                  gid_t gid, dev_t dev, mode_t mode)
 | 
			
		||||
int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid,
 | 
			
		||||
                  gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    FsCred cred;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_uid  = uid;
 | 
			
		||||
    cred.fc_gid  = gid;
 | 
			
		||||
    cred.fc_mode = mode;
 | 
			
		||||
    cred.fc_rdev = dev;
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->mknod(&s->ctx, path->data, &cred);
 | 
			
		||||
            err = s->ops->mknod(&s->ctx, fullname.data, &cred);
 | 
			
		||||
            if (err < 0) {
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            } else {
 | 
			
		||||
                err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
 | 
			
		||||
                if (err < 0) {
 | 
			
		||||
                    err = -errno;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -146,6 +170,7 @@ int v9fs_co_remove(V9fsState *s, V9fsString *path)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->remove(&s->ctx, path->data);
 | 
			
		||||
@ -153,6 +178,7 @@ int v9fs_co_remove(V9fsState *s, V9fsString *path)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -170,22 +196,34 @@ int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int v9fs_co_symlink(V9fsState *s, V9fsFidState *fidp,
 | 
			
		||||
                    const char *oldpath, const char *newpath, gid_t gid)
 | 
			
		||||
int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name,
 | 
			
		||||
                    const char *oldpath, gid_t gid, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    FsCred cred;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    cred_init(&cred);
 | 
			
		||||
    cred.fc_uid = fidp->uid;
 | 
			
		||||
    cred.fc_uid = dfidp->uid;
 | 
			
		||||
    cred.fc_gid = gid;
 | 
			
		||||
    cred.fc_mode = 0777;
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name->data);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->symlink(&s->ctx, oldpath, newpath, &cred);
 | 
			
		||||
            err = s->ops->symlink(&s->ctx, oldpath, fullname.data, &cred);
 | 
			
		||||
            if (err < 0) {
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            } else {
 | 
			
		||||
                err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
 | 
			
		||||
                if (err < 0) {
 | 
			
		||||
                    err = -errno;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ int v9fs_co_llistxattr(V9fsState *s, V9fsString *path, void *value, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->llistxattr(&s->ctx, path->data, value, size);
 | 
			
		||||
@ -28,6 +29,7 @@ int v9fs_co_llistxattr(V9fsState *s, V9fsString *path, void *value, size_t size)
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -37,6 +39,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->lgetxattr(&s->ctx, path->data,
 | 
			
		||||
@ -46,6 +49,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -55,6 +59,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->lsetxattr(&s->ctx, path->data,
 | 
			
		||||
@ -64,6 +69,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -72,6 +78,7 @@ int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_rdlock(&s->rename_lock);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            err = s->ops->lremovexattr(&s->ctx, path->data,
 | 
			
		||||
@ -80,5 +87,6 @@ int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path,
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -71,23 +71,25 @@ extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t);
 | 
			
		||||
extern int v9fs_co_llistxattr(V9fsState *, V9fsString *, void *, size_t);
 | 
			
		||||
extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *,
 | 
			
		||||
                             V9fsString *, void *, size_t);
 | 
			
		||||
extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t,
 | 
			
		||||
                         gid_t, dev_t, mode_t);
 | 
			
		||||
extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t);
 | 
			
		||||
extern int v9fs_co_mknod(V9fsState *, V9fsFidState *, V9fsString *, uid_t,
 | 
			
		||||
                         gid_t, dev_t, mode_t, struct stat *);
 | 
			
		||||
extern int v9fs_co_mkdir(V9fsState *, V9fsFidState *, V9fsString *,
 | 
			
		||||
                         mode_t, uid_t, gid_t, struct stat *);
 | 
			
		||||
extern int v9fs_co_remove(V9fsState *, V9fsString *);
 | 
			
		||||
extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *);
 | 
			
		||||
extern int v9fs_co_fstat(V9fsState *, int, struct stat *);
 | 
			
		||||
extern int v9fs_co_opendir(V9fsState *, V9fsFidState *);
 | 
			
		||||
extern int v9fs_co_open(V9fsState *, V9fsFidState *, int);
 | 
			
		||||
extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int);
 | 
			
		||||
extern int v9fs_co_open2(V9fsState *, V9fsFidState *, V9fsString *,
 | 
			
		||||
                         gid_t, int, int, struct stat *);
 | 
			
		||||
extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *,
 | 
			
		||||
                             void *, size_t, int);
 | 
			
		||||
extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *);
 | 
			
		||||
extern int v9fs_co_closedir(V9fsState *, DIR *);
 | 
			
		||||
extern int v9fs_co_close(V9fsState *, int);
 | 
			
		||||
extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
 | 
			
		||||
extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
 | 
			
		||||
                           const char *, gid_t);
 | 
			
		||||
extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, V9fsString *,
 | 
			
		||||
                           const char *, gid_t, struct stat *);
 | 
			
		||||
extern int v9fs_co_link(V9fsState *, V9fsString *, V9fsString *);
 | 
			
		||||
extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *,
 | 
			
		||||
                           struct iovec *, int, int64_t);
 | 
			
		||||
 | 
			
		||||
@ -131,6 +131,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
 | 
			
		||||
                        s->tag_len;
 | 
			
		||||
    s->vdev.get_config = virtio_9p_get_config;
 | 
			
		||||
    s->fid_list = NULL;
 | 
			
		||||
    qemu_co_rwlock_init(&s->rename_lock);
 | 
			
		||||
 | 
			
		||||
    if (v9fs_init_worker_threads() < 0) {
 | 
			
		||||
        fprintf(stderr, "worker thread initialization failed\n");
 | 
			
		||||
 | 
			
		||||
@ -1582,7 +1582,6 @@ static void v9fs_lcreate(void *opaque)
 | 
			
		||||
    gid_t gid;
 | 
			
		||||
    ssize_t err = 0;
 | 
			
		||||
    ssize_t offset = 7;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    V9fsString name;
 | 
			
		||||
    V9fsFidState *fidp;
 | 
			
		||||
    struct stat stbuf;
 | 
			
		||||
@ -1590,7 +1589,6 @@ static void v9fs_lcreate(void *opaque)
 | 
			
		||||
    int32_t iounit;
 | 
			
		||||
    V9fsPDU *pdu = opaque;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
 | 
			
		||||
                  &mode, &gid);
 | 
			
		||||
 | 
			
		||||
@ -1599,12 +1597,12 @@ static void v9fs_lcreate(void *opaque)
 | 
			
		||||
        err = -ENOENT;
 | 
			
		||||
        goto out_nofid;
 | 
			
		||||
    }
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
 | 
			
		||||
    /* Ignore direct disk access hint until the server supports it. */
 | 
			
		||||
    flags &= ~O_DIRECT;
 | 
			
		||||
 | 
			
		||||
    err = v9fs_co_open2(pdu->s, fidp, fullname.data, gid, flags, mode);
 | 
			
		||||
    err = v9fs_co_open2(pdu->s, fidp, &name, gid,
 | 
			
		||||
                        flags | O_CREAT, mode, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@ -1617,17 +1615,7 @@ static void v9fs_lcreate(void *opaque)
 | 
			
		||||
         */
 | 
			
		||||
        fidp->flags |= FID_NON_RECLAIMABLE;
 | 
			
		||||
    }
 | 
			
		||||
    iounit =  get_iounit(pdu->s, &fullname);
 | 
			
		||||
 | 
			
		||||
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        fidp->fid_type = P9_FID_NONE;
 | 
			
		||||
        if (fidp->fs.fd > 0) {
 | 
			
		||||
            v9fs_co_close(pdu->s, fidp->fs.fd);
 | 
			
		||||
        }
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    iounit =  get_iounit(pdu->s, &fidp->path);
 | 
			
		||||
    stat_to_qid(&stbuf, &qid);
 | 
			
		||||
    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
 | 
			
		||||
    err = offset;
 | 
			
		||||
@ -1636,7 +1624,6 @@ out:
 | 
			
		||||
out_nofid:
 | 
			
		||||
    complete_pdu(pdu->s, pdu, err);
 | 
			
		||||
    v9fs_string_free(&name);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void v9fs_fsync(void *opaque)
 | 
			
		||||
@ -2102,11 +2089,12 @@ static void v9fs_create(void *opaque)
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    if (perm & P9_STAT_MODE_DIR) {
 | 
			
		||||
        err = v9fs_co_mkdir(pdu->s, fullname.data, perm & 0777,
 | 
			
		||||
                            fidp->uid, -1);
 | 
			
		||||
        err = v9fs_co_mkdir(pdu->s, fidp, &name, perm & 0777,
 | 
			
		||||
                            fidp->uid, -1, &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
        err = v9fs_co_opendir(pdu->s, fidp);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
@ -2114,11 +2102,13 @@ static void v9fs_create(void *opaque)
 | 
			
		||||
        }
 | 
			
		||||
        fidp->fid_type = P9_FID_DIR;
 | 
			
		||||
    } else if (perm & P9_STAT_MODE_SYMLINK) {
 | 
			
		||||
        err = v9fs_co_symlink(pdu->s, fidp, extension.data,
 | 
			
		||||
                              fullname.data, -1);
 | 
			
		||||
        err = v9fs_co_symlink(pdu->s, fidp, &name,
 | 
			
		||||
                              extension.data, -1 , &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    } else if (perm & P9_STAT_MODE_LINK) {
 | 
			
		||||
        int32_t nfid = atoi(extension.data);
 | 
			
		||||
        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
 | 
			
		||||
@ -2126,12 +2116,19 @@ static void v9fs_create(void *opaque)
 | 
			
		||||
            err = -EINVAL;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
        put_fid(pdu->s, nfidp);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
        err = v9fs_co_lstat(pdu->s, &fidp->path, &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            fidp->fid_type = P9_FID_NONE;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        put_fid(pdu->s, nfidp);
 | 
			
		||||
    } else if (perm & P9_STAT_MODE_DEVICE) {
 | 
			
		||||
        char ctype;
 | 
			
		||||
        uint32_t major, minor;
 | 
			
		||||
@ -2155,26 +2152,32 @@ static void v9fs_create(void *opaque)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        nmode |= perm & 0777;
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
 | 
			
		||||
                            makedev(major, minor), nmode);
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1,
 | 
			
		||||
                            makedev(major, minor), nmode, &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
 | 
			
		||||
                            0, S_IFIFO | (perm & 0777));
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1,
 | 
			
		||||
                            0, S_IFIFO | (perm & 0777), &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    } else if (perm & P9_STAT_MODE_SOCKET) {
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
 | 
			
		||||
                            0, S_IFSOCK | (perm & 0777));
 | 
			
		||||
        err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1,
 | 
			
		||||
                            0, S_IFSOCK | (perm & 0777), &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
        v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    } else {
 | 
			
		||||
        err = v9fs_co_open2(pdu->s, fidp, fullname.data, -1,
 | 
			
		||||
                            omode_to_uflags(mode)|O_CREAT, perm);
 | 
			
		||||
        err = v9fs_co_open2(pdu->s, fidp, &name, -1,
 | 
			
		||||
                            omode_to_uflags(mode)|O_CREAT, perm, &stbuf);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
@ -2188,16 +2191,7 @@ static void v9fs_create(void *opaque)
 | 
			
		||||
            fidp->flags |= FID_NON_RECLAIMABLE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        fidp->fid_type = P9_FID_NONE;
 | 
			
		||||
        if (fidp->fs.fd) {
 | 
			
		||||
            v9fs_co_close(pdu->s, fidp->fs.fd);
 | 
			
		||||
        }
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    iounit = get_iounit(pdu->s, &fidp->path);
 | 
			
		||||
    v9fs_string_copy(&fidp->path, &fullname);
 | 
			
		||||
    stat_to_qid(&stbuf, &qid);
 | 
			
		||||
    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
 | 
			
		||||
    err = offset;
 | 
			
		||||
@ -2215,7 +2209,6 @@ static void v9fs_symlink(void *opaque)
 | 
			
		||||
    V9fsPDU *pdu = opaque;
 | 
			
		||||
    V9fsString name;
 | 
			
		||||
    V9fsString symname;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    V9fsFidState *dfidp;
 | 
			
		||||
    V9fsQID qid;
 | 
			
		||||
    struct stat stbuf;
 | 
			
		||||
@ -2224,7 +2217,6 @@ static void v9fs_symlink(void *opaque)
 | 
			
		||||
    gid_t gid;
 | 
			
		||||
    size_t offset = 7;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
 | 
			
		||||
 | 
			
		||||
    dfidp = get_fid(pdu->s, dfid);
 | 
			
		||||
@ -2232,13 +2224,7 @@ static void v9fs_symlink(void *opaque)
 | 
			
		||||
        err = -EINVAL;
 | 
			
		||||
        goto out_nofid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
 | 
			
		||||
    err = v9fs_co_symlink(pdu->s, dfidp, symname.data, fullname.data, gid);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
 | 
			
		||||
    err = v9fs_co_symlink(pdu->s, dfidp, &name, symname.data, gid, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@ -2251,7 +2237,6 @@ out_nofid:
 | 
			
		||||
    complete_pdu(pdu->s, pdu, err);
 | 
			
		||||
    v9fs_string_free(&name);
 | 
			
		||||
    v9fs_string_free(&symname);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void v9fs_flush(void *opaque)
 | 
			
		||||
@ -2469,7 +2454,9 @@ static void v9fs_rename(void *opaque)
 | 
			
		||||
    }
 | 
			
		||||
    BUG_ON(fidp->fid_type != P9_FID_NONE);
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_wrlock(&s->rename_lock);
 | 
			
		||||
    err = v9fs_complete_rename(s, fidp, newdirfid, &name);
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (!err) {
 | 
			
		||||
        err = offset;
 | 
			
		||||
    }
 | 
			
		||||
@ -2551,7 +2538,9 @@ static void v9fs_renameat(void *opaque)
 | 
			
		||||
    pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
 | 
			
		||||
                  &old_name, &newdirfid, &new_name);
 | 
			
		||||
 | 
			
		||||
    qemu_co_rwlock_wrlock(&s->rename_lock);
 | 
			
		||||
    err = v9fs_complete_renameat(s, olddirfid, &old_name, newdirfid, &new_name);
 | 
			
		||||
    qemu_co_rwlock_unlock(&s->rename_lock);
 | 
			
		||||
    if (!err) {
 | 
			
		||||
        err = offset;
 | 
			
		||||
    }
 | 
			
		||||
@ -2735,12 +2724,10 @@ static void v9fs_mknod(void *opaque)
 | 
			
		||||
    size_t offset = 7;
 | 
			
		||||
    V9fsString name;
 | 
			
		||||
    struct stat stbuf;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    V9fsFidState *fidp;
 | 
			
		||||
    V9fsPDU *pdu = opaque;
 | 
			
		||||
    V9fsState *s = pdu->s;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
 | 
			
		||||
                  &major, &minor, &gid);
 | 
			
		||||
 | 
			
		||||
@ -2749,13 +2736,8 @@ static void v9fs_mknod(void *opaque)
 | 
			
		||||
        err = -ENOENT;
 | 
			
		||||
        goto out_nofid;
 | 
			
		||||
    }
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
    err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
 | 
			
		||||
                        makedev(major, minor), mode);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    err = v9fs_co_lstat(s, &fullname, &stbuf);
 | 
			
		||||
    err = v9fs_co_mknod(s, fidp, &name, fidp->uid, gid,
 | 
			
		||||
                        makedev(major, minor), mode, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@ -2766,7 +2748,6 @@ out:
 | 
			
		||||
    put_fid(s, fidp);
 | 
			
		||||
out_nofid:
 | 
			
		||||
    complete_pdu(s, pdu, err);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    v9fs_string_free(&name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2867,14 +2848,13 @@ static void v9fs_mkdir(void *opaque)
 | 
			
		||||
    size_t offset = 7;
 | 
			
		||||
    int32_t fid;
 | 
			
		||||
    struct stat stbuf;
 | 
			
		||||
    V9fsString name, fullname;
 | 
			
		||||
    V9fsQID qid;
 | 
			
		||||
    V9fsString name;
 | 
			
		||||
    V9fsFidState *fidp;
 | 
			
		||||
    gid_t gid;
 | 
			
		||||
    int mode;
 | 
			
		||||
    int err = 0;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
 | 
			
		||||
 | 
			
		||||
    fidp = get_fid(pdu->s, fid);
 | 
			
		||||
@ -2882,12 +2862,7 @@ static void v9fs_mkdir(void *opaque)
 | 
			
		||||
        err = -ENOENT;
 | 
			
		||||
        goto out_nofid;
 | 
			
		||||
    }
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 | 
			
		||||
    err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
 | 
			
		||||
    err = v9fs_co_mkdir(pdu->s, fidp, &name, mode, fidp->uid, gid, &stbuf);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@ -2898,7 +2873,6 @@ out:
 | 
			
		||||
    put_fid(pdu->s, fidp);
 | 
			
		||||
out_nofid:
 | 
			
		||||
    complete_pdu(pdu->s, pdu, err);
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    v9fs_string_free(&name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,8 @@
 | 
			
		||||
#include <sys/resource.h>
 | 
			
		||||
#include "hw/virtio.h"
 | 
			
		||||
#include "fsdev/file-op-9p.h"
 | 
			
		||||
#include "qemu-thread.h"
 | 
			
		||||
#include "qemu-coroutine.h"
 | 
			
		||||
 | 
			
		||||
/* The feature bitmap for virtio 9P */
 | 
			
		||||
/* The mount point is specified in a config variable */
 | 
			
		||||
@ -237,6 +239,11 @@ typedef struct V9fsState
 | 
			
		||||
    size_t config_size;
 | 
			
		||||
    enum p9_proto_version proto_version;
 | 
			
		||||
    int32_t msize;
 | 
			
		||||
    /*
 | 
			
		||||
     * lock ensuring atomic path update
 | 
			
		||||
     * on rename.
 | 
			
		||||
     */
 | 
			
		||||
    CoRwlock rename_lock;
 | 
			
		||||
} V9fsState;
 | 
			
		||||
 | 
			
		||||
typedef struct V9fsStatState {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user