Statistics
| Branch: | Revision:

root / hw / 9pfs / virtio-9p-handle.c @ 1f51470d

History | View | Annotate | Download (17.8 kB)

1 5f542225 Aneesh Kumar K.V
/*
2 5f542225 Aneesh Kumar K.V
 * Virtio 9p handle callback
3 5f542225 Aneesh Kumar K.V
 *
4 5f542225 Aneesh Kumar K.V
 * Copyright IBM, Corp. 2011
5 5f542225 Aneesh Kumar K.V
 *
6 5f542225 Aneesh Kumar K.V
 * Authors:
7 5f542225 Aneesh Kumar K.V
 *    Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8 5f542225 Aneesh Kumar K.V
 *
9 5f542225 Aneesh Kumar K.V
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 5f542225 Aneesh Kumar K.V
 * the COPYING file in the top-level directory.
11 5f542225 Aneesh Kumar K.V
 *
12 5f542225 Aneesh Kumar K.V
 */
13 5f542225 Aneesh Kumar K.V
14 5f542225 Aneesh Kumar K.V
#include "hw/virtio.h"
15 5f542225 Aneesh Kumar K.V
#include "virtio-9p.h"
16 5f542225 Aneesh Kumar K.V
#include "virtio-9p-xattr.h"
17 5f542225 Aneesh Kumar K.V
#include <arpa/inet.h>
18 5f542225 Aneesh Kumar K.V
#include <pwd.h>
19 5f542225 Aneesh Kumar K.V
#include <grp.h>
20 5f542225 Aneesh Kumar K.V
#include <sys/socket.h>
21 5f542225 Aneesh Kumar K.V
#include <sys/un.h>
22 4f26f2b6 Avi Kivity
#include "qemu-xattr.h"
23 5f542225 Aneesh Kumar K.V
#include <unistd.h>
24 edb9eb73 Harsh Prateek Bora
#include <linux/fs.h>
25 edb9eb73 Harsh Prateek Bora
#ifdef CONFIG_LINUX_MAGIC_H
26 edb9eb73 Harsh Prateek Bora
#include <linux/magic.h>
27 edb9eb73 Harsh Prateek Bora
#endif
28 edb9eb73 Harsh Prateek Bora
#include <sys/ioctl.h>
29 edb9eb73 Harsh Prateek Bora
30 edb9eb73 Harsh Prateek Bora
#ifndef XFS_SUPER_MAGIC
31 edb9eb73 Harsh Prateek Bora
#define XFS_SUPER_MAGIC  0x58465342
32 edb9eb73 Harsh Prateek Bora
#endif
33 edb9eb73 Harsh Prateek Bora
#ifndef EXT2_SUPER_MAGIC
34 edb9eb73 Harsh Prateek Bora
#define EXT2_SUPER_MAGIC 0xEF53
35 edb9eb73 Harsh Prateek Bora
#endif
36 edb9eb73 Harsh Prateek Bora
#ifndef REISERFS_SUPER_MAGIC
37 edb9eb73 Harsh Prateek Bora
#define REISERFS_SUPER_MAGIC 0x52654973
38 edb9eb73 Harsh Prateek Bora
#endif
39 edb9eb73 Harsh Prateek Bora
#ifndef BTRFS_SUPER_MAGIC
40 edb9eb73 Harsh Prateek Bora
#define BTRFS_SUPER_MAGIC 0x9123683E
41 edb9eb73 Harsh Prateek Bora
#endif
42 5f542225 Aneesh Kumar K.V
43 5f542225 Aneesh Kumar K.V
struct handle_data {
44 5f542225 Aneesh Kumar K.V
    int mountfd;
45 5f542225 Aneesh Kumar K.V
    int handle_bytes;
46 5f542225 Aneesh Kumar K.V
};
47 5f542225 Aneesh Kumar K.V
48 d2042378 Aneesh Kumar K.V
static inline int name_to_handle(int dirfd, const char *name,
49 d2042378 Aneesh Kumar K.V
                                 struct file_handle *fh, int *mnt_id, int flags)
50 d2042378 Aneesh Kumar K.V
{
51 d2042378 Aneesh Kumar K.V
    return name_to_handle_at(dirfd, name, fh, mnt_id, flags);
52 d2042378 Aneesh Kumar K.V
}
53 d2042378 Aneesh Kumar K.V
54 d2042378 Aneesh Kumar K.V
static inline int open_by_handle(int mountfd, const char *fh, int flags)
55 d2042378 Aneesh Kumar K.V
{
56 d2042378 Aneesh Kumar K.V
    return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
57 d2042378 Aneesh Kumar K.V
}
58 5f542225 Aneesh Kumar K.V
59 5f542225 Aneesh Kumar K.V
static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
60 5f542225 Aneesh Kumar K.V
{
61 5f542225 Aneesh Kumar K.V
    int fd, ret;
62 3a93113a Dong Xu Wang
    fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);
63 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
64 5f542225 Aneesh Kumar K.V
        return fd;
65 5f542225 Aneesh Kumar K.V
    }
66 2d40564a M. Mohan Kumar
    ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
67 5f542225 Aneesh Kumar K.V
    if (ret < 0) {
68 5f542225 Aneesh Kumar K.V
        goto err_out;
69 5f542225 Aneesh Kumar K.V
    }
70 2d40564a M. Mohan Kumar
    ret = fchmod(fd, credp->fc_mode & 07777);
71 5f542225 Aneesh Kumar K.V
err_out:
72 5f542225 Aneesh Kumar K.V
    close(fd);
73 5f542225 Aneesh Kumar K.V
    return ret;
74 5f542225 Aneesh Kumar K.V
}
75 5f542225 Aneesh Kumar K.V
76 5f542225 Aneesh Kumar K.V
77 5f542225 Aneesh Kumar K.V
static int handle_lstat(FsContext *fs_ctx, V9fsPath *fs_path,
78 5f542225 Aneesh Kumar K.V
                        struct stat *stbuf)
79 5f542225 Aneesh Kumar K.V
{
80 5f542225 Aneesh Kumar K.V
    int fd, ret;
81 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
82 5f542225 Aneesh Kumar K.V
83 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
84 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
85 5f542225 Aneesh Kumar K.V
        return fd;
86 5f542225 Aneesh Kumar K.V
    }
87 5f542225 Aneesh Kumar K.V
    ret = fstatat(fd, "", stbuf, AT_EMPTY_PATH);
88 5f542225 Aneesh Kumar K.V
    close(fd);
89 5f542225 Aneesh Kumar K.V
    return ret;
90 5f542225 Aneesh Kumar K.V
}
91 5f542225 Aneesh Kumar K.V
92 5f542225 Aneesh Kumar K.V
static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
93 5f542225 Aneesh Kumar K.V
                               char *buf, size_t bufsz)
94 5f542225 Aneesh Kumar K.V
{
95 5f542225 Aneesh Kumar K.V
    int fd, ret;
96 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
97 5f542225 Aneesh Kumar K.V
98 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
99 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
100 5f542225 Aneesh Kumar K.V
        return fd;
101 5f542225 Aneesh Kumar K.V
    }
102 5f542225 Aneesh Kumar K.V
    ret = readlinkat(fd, "", buf, bufsz);
103 5f542225 Aneesh Kumar K.V
    close(fd);
104 5f542225 Aneesh Kumar K.V
    return ret;
105 5f542225 Aneesh Kumar K.V
}
106 5f542225 Aneesh Kumar K.V
107 cc720ddb Aneesh Kumar K.V
static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
108 5f542225 Aneesh Kumar K.V
{
109 cc720ddb Aneesh Kumar K.V
    return close(fs->fd);
110 5f542225 Aneesh Kumar K.V
}
111 5f542225 Aneesh Kumar K.V
112 cc720ddb Aneesh Kumar K.V
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
113 5f542225 Aneesh Kumar K.V
{
114 cc720ddb Aneesh Kumar K.V
    return closedir(fs->dir);
115 5f542225 Aneesh Kumar K.V
}
116 5f542225 Aneesh Kumar K.V
117 cc720ddb Aneesh Kumar K.V
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
118 cc720ddb Aneesh Kumar K.V
                       int flags, V9fsFidOpenState *fs)
119 5f542225 Aneesh Kumar K.V
{
120 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
121 5f542225 Aneesh Kumar K.V
122 cc720ddb Aneesh Kumar K.V
    fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
123 cc720ddb Aneesh Kumar K.V
    return fs->fd;
124 5f542225 Aneesh Kumar K.V
}
125 5f542225 Aneesh Kumar K.V
126 cc720ddb Aneesh Kumar K.V
static int handle_opendir(FsContext *ctx,
127 cc720ddb Aneesh Kumar K.V
                          V9fsPath *fs_path, V9fsFidOpenState *fs)
128 5f542225 Aneesh Kumar K.V
{
129 cc720ddb Aneesh Kumar K.V
    int ret;
130 cc720ddb Aneesh Kumar K.V
    ret = handle_open(ctx, fs_path, O_DIRECTORY, fs);
131 cc720ddb Aneesh Kumar K.V
    if (ret < 0) {
132 cc720ddb Aneesh Kumar K.V
        return -1;
133 5f542225 Aneesh Kumar K.V
    }
134 cc720ddb Aneesh Kumar K.V
    fs->dir = fdopendir(ret);
135 cc720ddb Aneesh Kumar K.V
    if (!fs->dir) {
136 cc720ddb Aneesh Kumar K.V
        return -1;
137 cc720ddb Aneesh Kumar K.V
    }
138 cc720ddb Aneesh Kumar K.V
    return 0;
139 5f542225 Aneesh Kumar K.V
}
140 5f542225 Aneesh Kumar K.V
141 cc720ddb Aneesh Kumar K.V
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
142 5f542225 Aneesh Kumar K.V
{
143 cc720ddb Aneesh Kumar K.V
    return rewinddir(fs->dir);
144 5f542225 Aneesh Kumar K.V
}
145 5f542225 Aneesh Kumar K.V
146 cc720ddb Aneesh Kumar K.V
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
147 5f542225 Aneesh Kumar K.V
{
148 cc720ddb Aneesh Kumar K.V
    return telldir(fs->dir);
149 5f542225 Aneesh Kumar K.V
}
150 5f542225 Aneesh Kumar K.V
151 cc720ddb Aneesh Kumar K.V
static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
152 cc720ddb Aneesh Kumar K.V
                            struct dirent *entry,
153 5f542225 Aneesh Kumar K.V
                            struct dirent **result)
154 5f542225 Aneesh Kumar K.V
{
155 cc720ddb Aneesh Kumar K.V
    return readdir_r(fs->dir, entry, result);
156 5f542225 Aneesh Kumar K.V
}
157 5f542225 Aneesh Kumar K.V
158 cc720ddb Aneesh Kumar K.V
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
159 5f542225 Aneesh Kumar K.V
{
160 cc720ddb Aneesh Kumar K.V
    return seekdir(fs->dir, off);
161 5f542225 Aneesh Kumar K.V
}
162 5f542225 Aneesh Kumar K.V
163 cc720ddb Aneesh Kumar K.V
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
164 cc720ddb Aneesh Kumar K.V
                             const struct iovec *iov,
165 5f542225 Aneesh Kumar K.V
                             int iovcnt, off_t offset)
166 5f542225 Aneesh Kumar K.V
{
167 5f542225 Aneesh Kumar K.V
#ifdef CONFIG_PREADV
168 cc720ddb Aneesh Kumar K.V
    return preadv(fs->fd, iov, iovcnt, offset);
169 5f542225 Aneesh Kumar K.V
#else
170 cc720ddb Aneesh Kumar K.V
    int err = lseek(fs->fd, offset, SEEK_SET);
171 5f542225 Aneesh Kumar K.V
    if (err == -1) {
172 5f542225 Aneesh Kumar K.V
        return err;
173 5f542225 Aneesh Kumar K.V
    } else {
174 cc720ddb Aneesh Kumar K.V
        return readv(fs->fd, iov, iovcnt);
175 5f542225 Aneesh Kumar K.V
    }
176 5f542225 Aneesh Kumar K.V
#endif
177 5f542225 Aneesh Kumar K.V
}
178 5f542225 Aneesh Kumar K.V
179 cc720ddb Aneesh Kumar K.V
static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
180 cc720ddb Aneesh Kumar K.V
                              const struct iovec *iov,
181 5f542225 Aneesh Kumar K.V
                              int iovcnt, off_t offset)
182 5f542225 Aneesh Kumar K.V
{
183 d3ab98e6 Aneesh Kumar K.V
    ssize_t ret;
184 5f542225 Aneesh Kumar K.V
#ifdef CONFIG_PREADV
185 cc720ddb Aneesh Kumar K.V
    ret = pwritev(fs->fd, iov, iovcnt, offset);
186 5f542225 Aneesh Kumar K.V
#else
187 cc720ddb Aneesh Kumar K.V
    int err = lseek(fs->fd, offset, SEEK_SET);
188 5f542225 Aneesh Kumar K.V
    if (err == -1) {
189 5f542225 Aneesh Kumar K.V
        return err;
190 5f542225 Aneesh Kumar K.V
    } else {
191 cc720ddb Aneesh Kumar K.V
        ret = writev(fs->fd, iov, iovcnt);
192 5f542225 Aneesh Kumar K.V
    }
193 5f542225 Aneesh Kumar K.V
#endif
194 d3ab98e6 Aneesh Kumar K.V
#ifdef CONFIG_SYNC_FILE_RANGE
195 d3ab98e6 Aneesh Kumar K.V
    if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
196 d3ab98e6 Aneesh Kumar K.V
        /*
197 d3ab98e6 Aneesh Kumar K.V
         * Initiate a writeback. This is not a data integrity sync.
198 d3ab98e6 Aneesh Kumar K.V
         * We want to ensure that we don't leave dirty pages in the cache
199 d3ab98e6 Aneesh Kumar K.V
         * after write when writeout=immediate is sepcified.
200 d3ab98e6 Aneesh Kumar K.V
         */
201 cc720ddb Aneesh Kumar K.V
        sync_file_range(fs->fd, offset, ret,
202 d3ab98e6 Aneesh Kumar K.V
                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
203 d3ab98e6 Aneesh Kumar K.V
    }
204 d3ab98e6 Aneesh Kumar K.V
#endif
205 d3ab98e6 Aneesh Kumar K.V
    return ret;
206 5f542225 Aneesh Kumar K.V
}
207 5f542225 Aneesh Kumar K.V
208 5f542225 Aneesh Kumar K.V
static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
209 5f542225 Aneesh Kumar K.V
{
210 5f542225 Aneesh Kumar K.V
    int fd, ret;
211 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
212 5f542225 Aneesh Kumar K.V
213 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
214 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
215 5f542225 Aneesh Kumar K.V
        return fd;
216 5f542225 Aneesh Kumar K.V
    }
217 5f542225 Aneesh Kumar K.V
    ret = fchmod(fd, credp->fc_mode);
218 5f542225 Aneesh Kumar K.V
    close(fd);
219 5f542225 Aneesh Kumar K.V
    return ret;
220 5f542225 Aneesh Kumar K.V
}
221 5f542225 Aneesh Kumar K.V
222 5f542225 Aneesh Kumar K.V
static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
223 5f542225 Aneesh Kumar K.V
                       const char *name, FsCred *credp)
224 5f542225 Aneesh Kumar K.V
{
225 5f542225 Aneesh Kumar K.V
    int dirfd, ret;
226 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
227 5f542225 Aneesh Kumar K.V
228 5f542225 Aneesh Kumar K.V
    dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
229 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
230 5f542225 Aneesh Kumar K.V
        return dirfd;
231 5f542225 Aneesh Kumar K.V
    }
232 5f542225 Aneesh Kumar K.V
    ret = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
233 5f542225 Aneesh Kumar K.V
    if (!ret) {
234 5f542225 Aneesh Kumar K.V
        ret = handle_update_file_cred(dirfd, name, credp);
235 5f542225 Aneesh Kumar K.V
    }
236 5f542225 Aneesh Kumar K.V
    close(dirfd);
237 5f542225 Aneesh Kumar K.V
    return ret;
238 5f542225 Aneesh Kumar K.V
}
239 5f542225 Aneesh Kumar K.V
240 5f542225 Aneesh Kumar K.V
static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
241 5f542225 Aneesh Kumar K.V
                       const char *name, FsCred *credp)
242 5f542225 Aneesh Kumar K.V
{
243 5f542225 Aneesh Kumar K.V
    int dirfd, ret;
244 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
245 5f542225 Aneesh Kumar K.V
246 5f542225 Aneesh Kumar K.V
    dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
247 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
248 5f542225 Aneesh Kumar K.V
        return dirfd;
249 5f542225 Aneesh Kumar K.V
    }
250 5f542225 Aneesh Kumar K.V
    ret = mkdirat(dirfd, name, credp->fc_mode);
251 5f542225 Aneesh Kumar K.V
    if (!ret) {
252 5f542225 Aneesh Kumar K.V
        ret = handle_update_file_cred(dirfd, name, credp);
253 5f542225 Aneesh Kumar K.V
    }
254 5f542225 Aneesh Kumar K.V
    close(dirfd);
255 5f542225 Aneesh Kumar K.V
    return ret;
256 5f542225 Aneesh Kumar K.V
}
257 5f542225 Aneesh Kumar K.V
258 8b888272 Aneesh Kumar K.V
static int handle_fstat(FsContext *fs_ctx, int fid_type,
259 8b888272 Aneesh Kumar K.V
                        V9fsFidOpenState *fs, struct stat *stbuf)
260 5f542225 Aneesh Kumar K.V
{
261 8b888272 Aneesh Kumar K.V
    int fd;
262 8b888272 Aneesh Kumar K.V
263 8b888272 Aneesh Kumar K.V
    if (fid_type == P9_FID_DIR) {
264 8b888272 Aneesh Kumar K.V
        fd = dirfd(fs->dir);
265 8b888272 Aneesh Kumar K.V
    } else {
266 8b888272 Aneesh Kumar K.V
        fd = fs->fd;
267 8b888272 Aneesh Kumar K.V
    }
268 8b888272 Aneesh Kumar K.V
    return fstat(fd, stbuf);
269 5f542225 Aneesh Kumar K.V
}
270 5f542225 Aneesh Kumar K.V
271 5f542225 Aneesh Kumar K.V
static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
272 cc720ddb Aneesh Kumar K.V
                        int flags, FsCred *credp, V9fsFidOpenState *fs)
273 5f542225 Aneesh Kumar K.V
{
274 5f542225 Aneesh Kumar K.V
    int ret;
275 5f542225 Aneesh Kumar K.V
    int dirfd, fd;
276 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
277 5f542225 Aneesh Kumar K.V
278 5f542225 Aneesh Kumar K.V
    dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
279 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
280 5f542225 Aneesh Kumar K.V
        return dirfd;
281 5f542225 Aneesh Kumar K.V
    }
282 5f542225 Aneesh Kumar K.V
    fd = openat(dirfd, name, flags | O_NOFOLLOW, credp->fc_mode);
283 5f542225 Aneesh Kumar K.V
    if (fd >= 0) {
284 5f542225 Aneesh Kumar K.V
        ret = handle_update_file_cred(dirfd, name, credp);
285 5f542225 Aneesh Kumar K.V
        if (ret < 0) {
286 5f542225 Aneesh Kumar K.V
            close(fd);
287 5f542225 Aneesh Kumar K.V
            fd = ret;
288 cc720ddb Aneesh Kumar K.V
        } else {
289 cc720ddb Aneesh Kumar K.V
            fs->fd = fd;
290 5f542225 Aneesh Kumar K.V
        }
291 5f542225 Aneesh Kumar K.V
    }
292 5f542225 Aneesh Kumar K.V
    close(dirfd);
293 5f542225 Aneesh Kumar K.V
    return fd;
294 5f542225 Aneesh Kumar K.V
}
295 5f542225 Aneesh Kumar K.V
296 5f542225 Aneesh Kumar K.V
297 5f542225 Aneesh Kumar K.V
static int handle_symlink(FsContext *fs_ctx, const char *oldpath,
298 5f542225 Aneesh Kumar K.V
                          V9fsPath *dir_path, const char *name, FsCred *credp)
299 5f542225 Aneesh Kumar K.V
{
300 5f542225 Aneesh Kumar K.V
    int fd, dirfd, ret;
301 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
302 5f542225 Aneesh Kumar K.V
303 5f542225 Aneesh Kumar K.V
    dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
304 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
305 5f542225 Aneesh Kumar K.V
        return dirfd;
306 5f542225 Aneesh Kumar K.V
    }
307 5f542225 Aneesh Kumar K.V
    ret = symlinkat(oldpath, dirfd, name);
308 5f542225 Aneesh Kumar K.V
    if (!ret) {
309 5f542225 Aneesh Kumar K.V
        fd = openat(dirfd, name, O_PATH | O_NOFOLLOW);
310 5f542225 Aneesh Kumar K.V
        if (fd < 0) {
311 5f542225 Aneesh Kumar K.V
            ret = fd;
312 5f542225 Aneesh Kumar K.V
            goto err_out;
313 5f542225 Aneesh Kumar K.V
        }
314 5f542225 Aneesh Kumar K.V
        ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
315 5f542225 Aneesh Kumar K.V
        close(fd);
316 5f542225 Aneesh Kumar K.V
    }
317 5f542225 Aneesh Kumar K.V
err_out:
318 5f542225 Aneesh Kumar K.V
    close(dirfd);
319 5f542225 Aneesh Kumar K.V
    return ret;
320 5f542225 Aneesh Kumar K.V
}
321 5f542225 Aneesh Kumar K.V
322 5f542225 Aneesh Kumar K.V
static int handle_link(FsContext *ctx, V9fsPath *oldpath,
323 5f542225 Aneesh Kumar K.V
                       V9fsPath *dirpath, const char *name)
324 5f542225 Aneesh Kumar K.V
{
325 5f542225 Aneesh Kumar K.V
    int oldfd, newdirfd, ret;
326 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
327 5f542225 Aneesh Kumar K.V
328 5f542225 Aneesh Kumar K.V
    oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH);
329 5f542225 Aneesh Kumar K.V
    if (oldfd < 0) {
330 5f542225 Aneesh Kumar K.V
        return oldfd;
331 5f542225 Aneesh Kumar K.V
    }
332 5f542225 Aneesh Kumar K.V
    newdirfd = open_by_handle(data->mountfd, dirpath->data, O_PATH);
333 5f542225 Aneesh Kumar K.V
    if (newdirfd < 0) {
334 5f542225 Aneesh Kumar K.V
        close(oldfd);
335 5f542225 Aneesh Kumar K.V
        return newdirfd;
336 5f542225 Aneesh Kumar K.V
    }
337 5f542225 Aneesh Kumar K.V
    ret = linkat(oldfd, "", newdirfd, name, AT_EMPTY_PATH);
338 5f542225 Aneesh Kumar K.V
    close(newdirfd);
339 5f542225 Aneesh Kumar K.V
    close(oldfd);
340 5f542225 Aneesh Kumar K.V
    return ret;
341 5f542225 Aneesh Kumar K.V
}
342 5f542225 Aneesh Kumar K.V
343 5f542225 Aneesh Kumar K.V
static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
344 5f542225 Aneesh Kumar K.V
{
345 5f542225 Aneesh Kumar K.V
    int fd, ret;
346 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
347 5f542225 Aneesh Kumar K.V
348 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY);
349 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
350 5f542225 Aneesh Kumar K.V
        return fd;
351 5f542225 Aneesh Kumar K.V
    }
352 5f542225 Aneesh Kumar K.V
    ret = ftruncate(fd, size);
353 5f542225 Aneesh Kumar K.V
    close(fd);
354 5f542225 Aneesh Kumar K.V
    return ret;
355 5f542225 Aneesh Kumar K.V
}
356 5f542225 Aneesh Kumar K.V
357 5f542225 Aneesh Kumar K.V
static int handle_rename(FsContext *ctx, const char *oldpath,
358 5f542225 Aneesh Kumar K.V
                         const char *newpath)
359 5f542225 Aneesh Kumar K.V
{
360 5f542225 Aneesh Kumar K.V
    errno = EOPNOTSUPP;
361 5f542225 Aneesh Kumar K.V
    return -1;
362 5f542225 Aneesh Kumar K.V
}
363 5f542225 Aneesh Kumar K.V
364 5f542225 Aneesh Kumar K.V
static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
365 5f542225 Aneesh Kumar K.V
{
366 5f542225 Aneesh Kumar K.V
    int fd, ret;
367 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)fs_ctx->private;
368 5f542225 Aneesh Kumar K.V
369 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
370 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
371 5f542225 Aneesh Kumar K.V
        return fd;
372 5f542225 Aneesh Kumar K.V
    }
373 5f542225 Aneesh Kumar K.V
    ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
374 5f542225 Aneesh Kumar K.V
    close(fd);
375 5f542225 Aneesh Kumar K.V
    return ret;
376 5f542225 Aneesh Kumar K.V
}
377 5f542225 Aneesh Kumar K.V
378 5f542225 Aneesh Kumar K.V
static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
379 5f542225 Aneesh Kumar K.V
                            const struct timespec *buf)
380 5f542225 Aneesh Kumar K.V
{
381 d2042378 Aneesh Kumar K.V
    int ret;
382 d2042378 Aneesh Kumar K.V
#ifdef CONFIG_UTIMENSAT
383 d2042378 Aneesh Kumar K.V
    int fd;
384 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
385 5f542225 Aneesh Kumar K.V
386 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
387 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
388 5f542225 Aneesh Kumar K.V
        return fd;
389 5f542225 Aneesh Kumar K.V
    }
390 5f542225 Aneesh Kumar K.V
    ret = futimens(fd, buf);
391 5f542225 Aneesh Kumar K.V
    close(fd);
392 d2042378 Aneesh Kumar K.V
#else
393 d2042378 Aneesh Kumar K.V
    ret = -1;
394 d2042378 Aneesh Kumar K.V
    errno = ENOSYS;
395 d2042378 Aneesh Kumar K.V
#endif
396 5f542225 Aneesh Kumar K.V
    return ret;
397 5f542225 Aneesh Kumar K.V
}
398 5f542225 Aneesh Kumar K.V
399 5f542225 Aneesh Kumar K.V
static int handle_remove(FsContext *ctx, const char *path)
400 5f542225 Aneesh Kumar K.V
{
401 5f542225 Aneesh Kumar K.V
    errno = EOPNOTSUPP;
402 5f542225 Aneesh Kumar K.V
    return -1;
403 5f542225 Aneesh Kumar K.V
}
404 5f542225 Aneesh Kumar K.V
405 8b888272 Aneesh Kumar K.V
static int handle_fsync(FsContext *ctx, int fid_type,
406 8b888272 Aneesh Kumar K.V
                        V9fsFidOpenState *fs, int datasync)
407 5f542225 Aneesh Kumar K.V
{
408 8b888272 Aneesh Kumar K.V
    int fd;
409 8b888272 Aneesh Kumar K.V
410 8b888272 Aneesh Kumar K.V
    if (fid_type == P9_FID_DIR) {
411 8b888272 Aneesh Kumar K.V
        fd = dirfd(fs->dir);
412 8b888272 Aneesh Kumar K.V
    } else {
413 8b888272 Aneesh Kumar K.V
        fd = fs->fd;
414 8b888272 Aneesh Kumar K.V
    }
415 8b888272 Aneesh Kumar K.V
416 5f542225 Aneesh Kumar K.V
    if (datasync) {
417 8b888272 Aneesh Kumar K.V
        return qemu_fdatasync(fd);
418 5f542225 Aneesh Kumar K.V
    } else {
419 8b888272 Aneesh Kumar K.V
        return fsync(fd);
420 5f542225 Aneesh Kumar K.V
    }
421 5f542225 Aneesh Kumar K.V
}
422 5f542225 Aneesh Kumar K.V
423 5f542225 Aneesh Kumar K.V
static int handle_statfs(FsContext *ctx, V9fsPath *fs_path,
424 5f542225 Aneesh Kumar K.V
                         struct statfs *stbuf)
425 5f542225 Aneesh Kumar K.V
{
426 5f542225 Aneesh Kumar K.V
    int fd, ret;
427 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
428 5f542225 Aneesh Kumar K.V
429 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
430 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
431 5f542225 Aneesh Kumar K.V
        return fd;
432 5f542225 Aneesh Kumar K.V
    }
433 5f542225 Aneesh Kumar K.V
    ret = fstatfs(fd, stbuf);
434 5f542225 Aneesh Kumar K.V
    close(fd);
435 5f542225 Aneesh Kumar K.V
    return ret;
436 5f542225 Aneesh Kumar K.V
}
437 5f542225 Aneesh Kumar K.V
438 5f542225 Aneesh Kumar K.V
static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
439 5f542225 Aneesh Kumar K.V
                                const char *name, void *value, size_t size)
440 5f542225 Aneesh Kumar K.V
{
441 5f542225 Aneesh Kumar K.V
    int fd, ret;
442 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
443 5f542225 Aneesh Kumar K.V
444 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
445 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
446 5f542225 Aneesh Kumar K.V
        return fd;
447 5f542225 Aneesh Kumar K.V
    }
448 5f542225 Aneesh Kumar K.V
    ret = fgetxattr(fd, name, value, size);
449 5f542225 Aneesh Kumar K.V
    close(fd);
450 5f542225 Aneesh Kumar K.V
    return ret;
451 5f542225 Aneesh Kumar K.V
}
452 5f542225 Aneesh Kumar K.V
453 5f542225 Aneesh Kumar K.V
static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
454 5f542225 Aneesh Kumar K.V
                                 void *value, size_t size)
455 5f542225 Aneesh Kumar K.V
{
456 5f542225 Aneesh Kumar K.V
    int fd, ret;
457 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
458 5f542225 Aneesh Kumar K.V
459 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
460 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
461 5f542225 Aneesh Kumar K.V
        return fd;
462 5f542225 Aneesh Kumar K.V
    }
463 5f542225 Aneesh Kumar K.V
    ret = flistxattr(fd, value, size);
464 5f542225 Aneesh Kumar K.V
    close(fd);
465 5f542225 Aneesh Kumar K.V
    return ret;
466 5f542225 Aneesh Kumar K.V
}
467 5f542225 Aneesh Kumar K.V
468 5f542225 Aneesh Kumar K.V
static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
469 5f542225 Aneesh Kumar K.V
                            void *value, size_t size, int flags)
470 5f542225 Aneesh Kumar K.V
{
471 5f542225 Aneesh Kumar K.V
    int fd, ret;
472 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
473 5f542225 Aneesh Kumar K.V
474 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
475 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
476 5f542225 Aneesh Kumar K.V
        return fd;
477 5f542225 Aneesh Kumar K.V
    }
478 5f542225 Aneesh Kumar K.V
    ret = fsetxattr(fd, name, value, size, flags);
479 5f542225 Aneesh Kumar K.V
    close(fd);
480 5f542225 Aneesh Kumar K.V
    return ret;
481 5f542225 Aneesh Kumar K.V
}
482 5f542225 Aneesh Kumar K.V
483 5f542225 Aneesh Kumar K.V
static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
484 5f542225 Aneesh Kumar K.V
                               const char *name)
485 5f542225 Aneesh Kumar K.V
{
486 5f542225 Aneesh Kumar K.V
    int fd, ret;
487 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
488 5f542225 Aneesh Kumar K.V
489 5f542225 Aneesh Kumar K.V
    fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
490 5f542225 Aneesh Kumar K.V
    if (fd < 0) {
491 5f542225 Aneesh Kumar K.V
        return fd;
492 5f542225 Aneesh Kumar K.V
    }
493 5f542225 Aneesh Kumar K.V
    ret = fremovexattr(fd, name);
494 5f542225 Aneesh Kumar K.V
    close(fd);
495 5f542225 Aneesh Kumar K.V
    return ret;
496 5f542225 Aneesh Kumar K.V
}
497 5f542225 Aneesh Kumar K.V
498 5f542225 Aneesh Kumar K.V
static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
499 5f542225 Aneesh Kumar K.V
                              const char *name, V9fsPath *target)
500 5f542225 Aneesh Kumar K.V
{
501 5f542225 Aneesh Kumar K.V
    char buffer[PATH_MAX];
502 5f542225 Aneesh Kumar K.V
    struct file_handle *fh;
503 5f542225 Aneesh Kumar K.V
    int dirfd, ret, mnt_id;
504 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
505 5f542225 Aneesh Kumar K.V
506 5f542225 Aneesh Kumar K.V
    /* "." and ".." are not allowed */
507 5f542225 Aneesh Kumar K.V
    if (!strcmp(name, ".") || !strcmp(name, "..")) {
508 5f542225 Aneesh Kumar K.V
        errno = EINVAL;
509 5f542225 Aneesh Kumar K.V
        return -1;
510 5f542225 Aneesh Kumar K.V
511 5f542225 Aneesh Kumar K.V
    }
512 5f542225 Aneesh Kumar K.V
    if (dir_path) {
513 5f542225 Aneesh Kumar K.V
        dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
514 5f542225 Aneesh Kumar K.V
    } else {
515 5f542225 Aneesh Kumar K.V
        /* relative to export root */
516 5f542225 Aneesh Kumar K.V
        dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
517 5f542225 Aneesh Kumar K.V
    }
518 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
519 5f542225 Aneesh Kumar K.V
        return dirfd;
520 5f542225 Aneesh Kumar K.V
    }
521 5f542225 Aneesh Kumar K.V
    fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
522 5f542225 Aneesh Kumar K.V
    fh->handle_bytes = data->handle_bytes;
523 66a0a2cb Dong Xu Wang
    /* add a "./" at the beginning of the path */
524 5f542225 Aneesh Kumar K.V
    snprintf(buffer, PATH_MAX, "./%s", name);
525 5f542225 Aneesh Kumar K.V
    /* flag = 0 imply don't follow symlink */
526 5f542225 Aneesh Kumar K.V
    ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
527 5f542225 Aneesh Kumar K.V
    if (!ret) {
528 5f542225 Aneesh Kumar K.V
        target->data = (char *)fh;
529 5f542225 Aneesh Kumar K.V
        target->size = sizeof(struct file_handle) + data->handle_bytes;
530 5f542225 Aneesh Kumar K.V
    } else {
531 5f542225 Aneesh Kumar K.V
        g_free(fh);
532 5f542225 Aneesh Kumar K.V
    }
533 5f542225 Aneesh Kumar K.V
    close(dirfd);
534 5f542225 Aneesh Kumar K.V
    return ret;
535 5f542225 Aneesh Kumar K.V
}
536 5f542225 Aneesh Kumar K.V
537 5f542225 Aneesh Kumar K.V
static int handle_renameat(FsContext *ctx, V9fsPath *olddir,
538 5f542225 Aneesh Kumar K.V
                           const char *old_name, V9fsPath *newdir,
539 5f542225 Aneesh Kumar K.V
                           const char *new_name)
540 5f542225 Aneesh Kumar K.V
{
541 5f542225 Aneesh Kumar K.V
    int olddirfd, newdirfd, ret;
542 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
543 5f542225 Aneesh Kumar K.V
544 5f542225 Aneesh Kumar K.V
    olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH);
545 5f542225 Aneesh Kumar K.V
    if (olddirfd < 0) {
546 5f542225 Aneesh Kumar K.V
        return olddirfd;
547 5f542225 Aneesh Kumar K.V
    }
548 5f542225 Aneesh Kumar K.V
    newdirfd = open_by_handle(data->mountfd, newdir->data, O_PATH);
549 5f542225 Aneesh Kumar K.V
    if (newdirfd < 0) {
550 5f542225 Aneesh Kumar K.V
        close(olddirfd);
551 5f542225 Aneesh Kumar K.V
        return newdirfd;
552 5f542225 Aneesh Kumar K.V
    }
553 5f542225 Aneesh Kumar K.V
    ret = renameat(olddirfd, old_name, newdirfd, new_name);
554 5f542225 Aneesh Kumar K.V
    close(newdirfd);
555 5f542225 Aneesh Kumar K.V
    close(olddirfd);
556 5f542225 Aneesh Kumar K.V
    return ret;
557 5f542225 Aneesh Kumar K.V
}
558 5f542225 Aneesh Kumar K.V
559 5f542225 Aneesh Kumar K.V
static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
560 5f542225 Aneesh Kumar K.V
                           const char *name, int flags)
561 5f542225 Aneesh Kumar K.V
{
562 5f542225 Aneesh Kumar K.V
    int dirfd, ret;
563 5f542225 Aneesh Kumar K.V
    struct handle_data *data = (struct handle_data *)ctx->private;
564 930b5883 Paolo Bonzini
    int rflags;
565 5f542225 Aneesh Kumar K.V
566 5f542225 Aneesh Kumar K.V
    dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
567 5f542225 Aneesh Kumar K.V
    if (dirfd < 0) {
568 5f542225 Aneesh Kumar K.V
        return dirfd;
569 5f542225 Aneesh Kumar K.V
    }
570 5f542225 Aneesh Kumar K.V
571 930b5883 Paolo Bonzini
    rflags = 0;
572 930b5883 Paolo Bonzini
    if (flags & P9_DOTL_AT_REMOVEDIR) {
573 930b5883 Paolo Bonzini
        rflags |= AT_REMOVEDIR;
574 930b5883 Paolo Bonzini
    }
575 930b5883 Paolo Bonzini
576 930b5883 Paolo Bonzini
    ret = unlinkat(dirfd, name, rflags);
577 930b5883 Paolo Bonzini
578 5f542225 Aneesh Kumar K.V
    close(dirfd);
579 5f542225 Aneesh Kumar K.V
    return ret;
580 5f542225 Aneesh Kumar K.V
}
581 5f542225 Aneesh Kumar K.V
582 edb9eb73 Harsh Prateek Bora
static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
583 edb9eb73 Harsh Prateek Bora
                                 mode_t st_mode, uint64_t *st_gen)
584 edb9eb73 Harsh Prateek Bora
{
585 cc720ddb Aneesh Kumar K.V
    int err;
586 cc720ddb Aneesh Kumar K.V
    V9fsFidOpenState fid_open;
587 edb9eb73 Harsh Prateek Bora
588 edb9eb73 Harsh Prateek Bora
    /*
589 edb9eb73 Harsh Prateek Bora
     * Do not try to open special files like device nodes, fifos etc
590 edb9eb73 Harsh Prateek Bora
     * We can get fd for regular files and directories only
591 edb9eb73 Harsh Prateek Bora
     */
592 edb9eb73 Harsh Prateek Bora
    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
593 edb9eb73 Harsh Prateek Bora
            return 0;
594 edb9eb73 Harsh Prateek Bora
    }
595 cc720ddb Aneesh Kumar K.V
    err = handle_open(ctx, path, O_RDONLY, &fid_open);
596 cc720ddb Aneesh Kumar K.V
    if (err < 0) {
597 cc720ddb Aneesh Kumar K.V
        return err;
598 edb9eb73 Harsh Prateek Bora
    }
599 cc720ddb Aneesh Kumar K.V
    err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
600 cc720ddb Aneesh Kumar K.V
    handle_close(ctx, &fid_open);
601 edb9eb73 Harsh Prateek Bora
    return err;
602 edb9eb73 Harsh Prateek Bora
}
603 edb9eb73 Harsh Prateek Bora
604 5f542225 Aneesh Kumar K.V
static int handle_init(FsContext *ctx)
605 5f542225 Aneesh Kumar K.V
{
606 5f542225 Aneesh Kumar K.V
    int ret, mnt_id;
607 edb9eb73 Harsh Prateek Bora
    struct statfs stbuf;
608 5f542225 Aneesh Kumar K.V
    struct file_handle fh;
609 5f542225 Aneesh Kumar K.V
    struct handle_data *data = g_malloc(sizeof(struct handle_data));
610 d2042378 Aneesh Kumar K.V
611 5f542225 Aneesh Kumar K.V
    data->mountfd = open(ctx->fs_root, O_DIRECTORY);
612 5f542225 Aneesh Kumar K.V
    if (data->mountfd < 0) {
613 5f542225 Aneesh Kumar K.V
        ret = data->mountfd;
614 5f542225 Aneesh Kumar K.V
        goto err_out;
615 5f542225 Aneesh Kumar K.V
    }
616 edb9eb73 Harsh Prateek Bora
    ret = statfs(ctx->fs_root, &stbuf);
617 edb9eb73 Harsh Prateek Bora
    if (!ret) {
618 edb9eb73 Harsh Prateek Bora
        switch (stbuf.f_type) {
619 edb9eb73 Harsh Prateek Bora
        case EXT2_SUPER_MAGIC:
620 edb9eb73 Harsh Prateek Bora
        case BTRFS_SUPER_MAGIC:
621 edb9eb73 Harsh Prateek Bora
        case REISERFS_SUPER_MAGIC:
622 edb9eb73 Harsh Prateek Bora
        case XFS_SUPER_MAGIC:
623 edb9eb73 Harsh Prateek Bora
            ctx->exops.get_st_gen = handle_ioc_getversion;
624 edb9eb73 Harsh Prateek Bora
            break;
625 edb9eb73 Harsh Prateek Bora
        }
626 edb9eb73 Harsh Prateek Bora
    }
627 5f542225 Aneesh Kumar K.V
    memset(&fh, 0, sizeof(struct file_handle));
628 5f542225 Aneesh Kumar K.V
    ret = name_to_handle(data->mountfd, ".", &fh, &mnt_id, 0);
629 5f542225 Aneesh Kumar K.V
    if (ret && errno == EOVERFLOW) {
630 5f542225 Aneesh Kumar K.V
        data->handle_bytes = fh.handle_bytes;
631 5f542225 Aneesh Kumar K.V
        ctx->private = data;
632 5f542225 Aneesh Kumar K.V
        ret = 0;
633 5f542225 Aneesh Kumar K.V
        goto out;
634 5f542225 Aneesh Kumar K.V
    }
635 5f542225 Aneesh Kumar K.V
    /* we got 0 byte handle ? */
636 5f542225 Aneesh Kumar K.V
    ret = -1;
637 5f542225 Aneesh Kumar K.V
    close(data->mountfd);
638 5f542225 Aneesh Kumar K.V
err_out:
639 5f542225 Aneesh Kumar K.V
    g_free(data);
640 5f542225 Aneesh Kumar K.V
out:
641 5f542225 Aneesh Kumar K.V
    return ret;
642 5f542225 Aneesh Kumar K.V
}
643 5f542225 Aneesh Kumar K.V
644 99519f0a Aneesh Kumar K.V
static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
645 99519f0a Aneesh Kumar K.V
{
646 99519f0a Aneesh Kumar K.V
    const char *sec_model = qemu_opt_get(opts, "security_model");
647 99519f0a Aneesh Kumar K.V
    const char *path = qemu_opt_get(opts, "path");
648 99519f0a Aneesh Kumar K.V
649 99519f0a Aneesh Kumar K.V
    if (sec_model) {
650 99519f0a Aneesh Kumar K.V
        fprintf(stderr, "Invalid argument security_model specified with handle fsdriver\n");
651 99519f0a Aneesh Kumar K.V
        return -1;
652 99519f0a Aneesh Kumar K.V
    }
653 99519f0a Aneesh Kumar K.V
654 99519f0a Aneesh Kumar K.V
    if (!path) {
655 99519f0a Aneesh Kumar K.V
        fprintf(stderr, "fsdev: No path specified.\n");
656 99519f0a Aneesh Kumar K.V
        return -1;
657 99519f0a Aneesh Kumar K.V
    }
658 99519f0a Aneesh Kumar K.V
    fse->path = g_strdup(path);
659 99519f0a Aneesh Kumar K.V
    return 0;
660 99519f0a Aneesh Kumar K.V
661 99519f0a Aneesh Kumar K.V
}
662 99519f0a Aneesh Kumar K.V
663 5f542225 Aneesh Kumar K.V
FileOperations handle_ops = {
664 99519f0a Aneesh Kumar K.V
    .parse_opts   = handle_parse_opts,
665 5f542225 Aneesh Kumar K.V
    .init         = handle_init,
666 5f542225 Aneesh Kumar K.V
    .lstat        = handle_lstat,
667 5f542225 Aneesh Kumar K.V
    .readlink     = handle_readlink,
668 5f542225 Aneesh Kumar K.V
    .close        = handle_close,
669 5f542225 Aneesh Kumar K.V
    .closedir     = handle_closedir,
670 5f542225 Aneesh Kumar K.V
    .open         = handle_open,
671 5f542225 Aneesh Kumar K.V
    .opendir      = handle_opendir,
672 5f542225 Aneesh Kumar K.V
    .rewinddir    = handle_rewinddir,
673 5f542225 Aneesh Kumar K.V
    .telldir      = handle_telldir,
674 5f542225 Aneesh Kumar K.V
    .readdir_r    = handle_readdir_r,
675 5f542225 Aneesh Kumar K.V
    .seekdir      = handle_seekdir,
676 5f542225 Aneesh Kumar K.V
    .preadv       = handle_preadv,
677 5f542225 Aneesh Kumar K.V
    .pwritev      = handle_pwritev,
678 5f542225 Aneesh Kumar K.V
    .chmod        = handle_chmod,
679 5f542225 Aneesh Kumar K.V
    .mknod        = handle_mknod,
680 5f542225 Aneesh Kumar K.V
    .mkdir        = handle_mkdir,
681 5f542225 Aneesh Kumar K.V
    .fstat        = handle_fstat,
682 5f542225 Aneesh Kumar K.V
    .open2        = handle_open2,
683 5f542225 Aneesh Kumar K.V
    .symlink      = handle_symlink,
684 5f542225 Aneesh Kumar K.V
    .link         = handle_link,
685 5f542225 Aneesh Kumar K.V
    .truncate     = handle_truncate,
686 5f542225 Aneesh Kumar K.V
    .rename       = handle_rename,
687 5f542225 Aneesh Kumar K.V
    .chown        = handle_chown,
688 5f542225 Aneesh Kumar K.V
    .utimensat    = handle_utimensat,
689 5f542225 Aneesh Kumar K.V
    .remove       = handle_remove,
690 5f542225 Aneesh Kumar K.V
    .fsync        = handle_fsync,
691 5f542225 Aneesh Kumar K.V
    .statfs       = handle_statfs,
692 5f542225 Aneesh Kumar K.V
    .lgetxattr    = handle_lgetxattr,
693 5f542225 Aneesh Kumar K.V
    .llistxattr   = handle_llistxattr,
694 5f542225 Aneesh Kumar K.V
    .lsetxattr    = handle_lsetxattr,
695 5f542225 Aneesh Kumar K.V
    .lremovexattr = handle_lremovexattr,
696 5f542225 Aneesh Kumar K.V
    .name_to_path = handle_name_to_path,
697 5f542225 Aneesh Kumar K.V
    .renameat     = handle_renameat,
698 5f542225 Aneesh Kumar K.V
    .unlinkat     = handle_unlinkat,
699 5f542225 Aneesh Kumar K.V
};