/*
 * 9p backend
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

/*
 * Not so fast! You might want to read the 9p developer docs first:
 * https://wiki.qemu.org/Documentation/9p
 */

#include "qemu/osdep.h"
#include "fsdev/qemu-fsdev.h"
#include "qemu/thread.h"
#include "qemu/main-loop.h"
#include "qemu/error-report.h"
#include "coth.h"

int coroutine_fn v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
                                V9fsStatDotl *v9stat)
{
    int err = 0;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    if (s->ctx.exops.get_st_gen) {
        v9fs_path_read_lock(s);
        v9fs_co_run_in_worker(
            {
                err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
                                              &v9stat->st_gen);
                if (err < 0) {
                    err = -errno;
                }
            });
        v9fs_path_unlock(s);
    }
    return err;
}

int coroutine_fn v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_path_read_lock(s);
    v9fs_co_run_in_worker(
        {
            err = s->ops->lstat(&s->ctx, path, stbuf);
            if (err < 0) {
                err = -errno;
            }
        });
    v9fs_path_unlock(s);
    return err;
}

int coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp,
                               struct stat *stbuf)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_co_run_in_worker(
        {
            err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
            if (err < 0) {
                err = -errno;
            }
        });
    /*
     * Some FS driver (local:mapped-file) can't support fetching attributes
     * using file descriptor. Use Path name in that case.
     */
    if (err == -EOPNOTSUPP) {
        err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
        if (err == -ENOENT) {
            /*
             * fstat on an unlinked file. Work with partial results
             * returned from s->ops->fstat
             */
            err = 0;
        }
    }
    return err;
}

int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_path_read_lock(s);
    v9fs_co_run_in_worker(
        {
            err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
            if (err == -1) {
                err = -errno;
            } else {
                err = 0;
            }
        });
    v9fs_path_unlock(s);
    if (!err) {
        total_open_fd++;
        if (total_open_fd > open_fd_hw) {
            v9fs_reclaim_fd(pdu);
        }
    }
    return err;
}

int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
                               V9fsString *name, gid_t gid, int flags, int mode,
                               struct stat *stbuf)
{
    int err;
    FsCred cred;
    V9fsPath path;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    cred_init(&cred);
    cred.fc_mode = mode & 07777;
    cred.fc_uid = fidp->uid;
    cred.fc_gid = gid;
    /*
     * Hold the directory fid lock so that directory path name
     * don't change. Take the write lock to be sure this fid
     * cannot be used by another operation.
     */
    v9fs_path_write_lock(s);
    v9fs_co_run_in_worker(
        {
            err = s->ops->open2(&s->ctx, &fidp->path,
                                name->data, flags, &cred, &fidp->fs);
            if (err < 0) {
                err = -errno;
            } else {
                v9fs_path_init(&path);
                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
                if (!err) {
                    err = s->ops->lstat(&s->ctx, &path, stbuf);
                    if (err < 0) {
                        err = -errno;
                        s->ops->close(&s->ctx, &fidp->fs);
                    } else {
                        v9fs_path_copy(&fidp->path, &path);
                    }
                } else {
                    s->ops->close(&s->ctx, &fidp->fs);
                }
                v9fs_path_free(&path);
            }
        });
    v9fs_path_unlock(s);
    if (!err) {
        total_open_fd++;
        if (total_open_fd > open_fd_hw) {
            v9fs_reclaim_fd(pdu);
        }
    }
    return err;
}

int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_co_run_in_worker(
        {
            err = s->ops->close(&s->ctx, fs);
            if (err < 0) {
                err = -errno;
            }
        });
    /* 'man 2 close' suggests to ignore close() errors except of EBADF */
    if (unlikely(err && errno == EBADF)) {
        /* unexpected case as we should have checked for a valid file handle */
        error_report("9pfs: WARNING: v9fs_co_close() failed with EBADF");
    } else {
        total_open_fd--;
    }
    return err;
}

int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_co_run_in_worker(
        {
            err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
            if (err < 0) {
                err = -errno;
            }
        });
    return err;
}

int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
                              V9fsFidState *newdirfid, V9fsString *name)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    v9fs_path_read_lock(s);
    v9fs_co_run_in_worker(
        {
            err = s->ops->link(&s->ctx, &oldfid->path,
                               &newdirfid->path, name->data);
            if (err < 0) {
                err = -errno;
            }
        });
    v9fs_path_unlock(s);
    return err;
}

int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
                                 struct iovec *iov, int iovcnt, int64_t offset)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    fsdev_co_throttle_request(s->ctx.fst, THROTTLE_WRITE, iov, iovcnt);
    v9fs_co_run_in_worker(
        {
            err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
            if (err < 0) {
                err = -errno;
            }
        });
    return err;
}

int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
                                struct iovec *iov, int iovcnt, int64_t offset)
{
    int err;
    V9fsState *s = pdu->s;

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
    fsdev_co_throttle_request(s->ctx.fst, THROTTLE_READ, iov, iovcnt);
    v9fs_co_run_in_worker(
        {
            err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
            if (err < 0) {
                err = -errno;
            }
        });
    return err;
}
