Revision cc720ddb

b/fsdev/file-op-9p.h
78 78
    char *data;
79 79
} V9fsPath;
80 80

  
81
typedef union V9fsFidOpenState V9fsFidOpenState;
82

  
81 83
void cred_init(FsCred *);
82 84

  
83 85
typedef struct FileOperations
......
94 96
                   const char *, FsCred *);
95 97
    int (*link)(FsContext *, V9fsPath *, V9fsPath *, const char *);
96 98
    int (*setuid)(FsContext *, uid_t);
97
    int (*close)(FsContext *, int);
98
    int (*closedir)(FsContext *, DIR *);
99
    DIR *(*opendir)(FsContext *, V9fsPath *);
100
    int (*open)(FsContext *, V9fsPath *, int);
101
    int (*open2)(FsContext *, V9fsPath *, const char *, int, FsCred *);
102
    void (*rewinddir)(FsContext *, DIR *);
103
    off_t (*telldir)(FsContext *, DIR *);
104
    int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **);
105
    void (*seekdir)(FsContext *, DIR *, off_t);
106
    ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
107
    ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
99
    int (*close)(FsContext *, V9fsFidOpenState *);
100
    int (*closedir)(FsContext *, V9fsFidOpenState *);
101
    int (*opendir)(FsContext *, V9fsPath *, V9fsFidOpenState *);
102
    int (*open)(FsContext *, V9fsPath *, int, V9fsFidOpenState *);
103
    int (*open2)(FsContext *, V9fsPath *, const char *,
104
                 int, FsCred *, V9fsFidOpenState *);
105
    void (*rewinddir)(FsContext *, V9fsFidOpenState *);
106
    off_t (*telldir)(FsContext *, V9fsFidOpenState *);
107
    int (*readdir_r)(FsContext *, V9fsFidOpenState *,
108
                     struct dirent *, struct dirent **);
109
    void (*seekdir)(FsContext *, V9fsFidOpenState *, off_t);
110
    ssize_t (*preadv)(FsContext *, V9fsFidOpenState *,
111
                      const struct iovec *, int, off_t);
112
    ssize_t (*pwritev)(FsContext *, V9fsFidOpenState *,
113
                       const struct iovec *, int, off_t);
108 114
    int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *);
109
    int (*fstat)(FsContext *, int, struct stat *);
115
    int (*fstat)(FsContext *, V9fsFidOpenState *, struct stat *);
110 116
    int (*rename)(FsContext *, const char *, const char *);
111 117
    int (*truncate)(FsContext *, V9fsPath *, off_t);
112
    int (*fsync)(FsContext *, int, int);
118
    int (*fsync)(FsContext *, V9fsFidOpenState *, int);
113 119
    int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf);
114 120
    ssize_t (*lgetxattr)(FsContext *, V9fsPath *,
115 121
                         const char *, void *, size_t);
b/hw/9pfs/codir.c
29 29
    v9fs_co_run_in_worker(
30 30
        {
31 31
            errno = 0;
32
            err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result);
32
            err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
33 33
            if (!*result && errno) {
34 34
                err = -errno;
35 35
            } else {
......
49 49
    }
50 50
    v9fs_co_run_in_worker(
51 51
        {
52
            err = s->ops->telldir(&s->ctx, fidp->fs.dir);
52
            err = s->ops->telldir(&s->ctx, &fidp->fs);
53 53
            if (err < 0) {
54 54
                err = -errno;
55 55
            }
......
65 65
    }
66 66
    v9fs_co_run_in_worker(
67 67
        {
68
            s->ops->seekdir(&s->ctx, fidp->fs.dir, offset);
68
            s->ops->seekdir(&s->ctx, &fidp->fs, offset);
69 69
        });
70 70
}
71 71

  
......
77 77
    }
78 78
    v9fs_co_run_in_worker(
79 79
        {
80
            s->ops->rewinddir(&s->ctx, fidp->fs.dir);
80
            s->ops->rewinddir(&s->ctx, &fidp->fs);
81 81
        });
82 82
}
83 83

  
......
129 129
    v9fs_path_read_lock(s);
130 130
    v9fs_co_run_in_worker(
131 131
        {
132
            fidp->fs.dir = s->ops->opendir(&s->ctx, &fidp->path);
133
            if (!fidp->fs.dir) {
132
            err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs);
133
            if (err < 0) {
134 134
                err = -errno;
135 135
            } else {
136 136
                err = 0;
......
146 146
    return err;
147 147
}
148 148

  
149
int v9fs_co_closedir(V9fsPDU *pdu, DIR *dir)
149
int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs)
150 150
{
151 151
    int err;
152 152
    V9fsState *s = pdu->s;
......
156 156
    }
157 157
    v9fs_co_run_in_worker(
158 158
        {
159
            err = s->ops->closedir(&s->ctx, dir);
159
            err = s->ops->closedir(&s->ctx, fs);
160 160
            if (err < 0) {
161 161
                err = -errno;
162 162
            }
b/hw/9pfs/cofile.c
61 61
    return err;
62 62
}
63 63

  
64
int v9fs_co_fstat(V9fsPDU *pdu, int fd, struct stat *stbuf)
64
int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
65 65
{
66 66
    int err;
67 67
    V9fsState *s = pdu->s;
......
71 71
    }
72 72
    v9fs_co_run_in_worker(
73 73
        {
74
            err = s->ops->fstat(&s->ctx, fd, stbuf);
74
            err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf);
75 75
            if (err < 0) {
76 76
                err = -errno;
77 77
            }
......
90 90
    v9fs_path_read_lock(s);
91 91
    v9fs_co_run_in_worker(
92 92
        {
93
            fidp->fs.fd = s->ops->open(&s->ctx, &fidp->path, flags);
94
            if (fidp->fs.fd == -1) {
93
            err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
94
            if (err == -1) {
95 95
                err = -errno;
96 96
            } else {
97 97
                err = 0;
......
130 130
    v9fs_path_read_lock(s);
131 131
    v9fs_co_run_in_worker(
132 132
        {
133
            fidp->fs.fd = s->ops->open2(&s->ctx, &fidp->path,
134
                                        name->data, flags, &cred);
135
            if (fidp->fs.fd == -1) {
133
            err = s->ops->open2(&s->ctx, &fidp->path,
134
                                name->data, flags, &cred, &fidp->fs);
135
            if (err < 0) {
136 136
                err = -errno;
137 137
            } else {
138 138
                v9fs_path_init(&path);
......
141 141
                    err = s->ops->lstat(&s->ctx, &path, stbuf);
142 142
                    if (err < 0) {
143 143
                        err = -errno;
144
                        s->ops->close(&s->ctx, fidp->fs.fd);
144
                        s->ops->close(&s->ctx, &fidp->fs);
145 145
                    } else {
146 146
                        v9fs_path_copy(&fidp->path, &path);
147 147
                    }
148 148
                } else {
149
                    s->ops->close(&s->ctx, fidp->fs.fd);
149
                    s->ops->close(&s->ctx, &fidp->fs);
150 150
                }
151 151
                v9fs_path_free(&path);
152 152
            }
......
161 161
    return err;
162 162
}
163 163

  
164
int v9fs_co_close(V9fsPDU *pdu, int fd)
164
int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
165 165
{
166 166
    int err;
167 167
    V9fsState *s = pdu->s;
......
171 171
    }
172 172
    v9fs_co_run_in_worker(
173 173
        {
174
            err = s->ops->close(&s->ctx, fd);
174
            err = s->ops->close(&s->ctx, fs);
175 175
            if (err < 0) {
176 176
                err = -errno;
177 177
            }
......
184 184

  
185 185
int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
186 186
{
187
    int fd, err;
187
    int err;
188 188
    V9fsState *s = pdu->s;
189 189

  
190 190
    if (v9fs_request_cancelled(pdu)) {
191 191
        return -EINTR;
192 192
    }
193
    fd = fidp->fs.fd;
194 193
    v9fs_co_run_in_worker(
195 194
        {
196
            err = s->ops->fsync(&s->ctx, fd, datasync);
195
            err = s->ops->fsync(&s->ctx, &fidp->fs, datasync);
197 196
            if (err < 0) {
198 197
                err = -errno;
199 198
            }
......
226 225
int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
227 226
                    struct iovec *iov, int iovcnt, int64_t offset)
228 227
{
229
    int fd, err;
228
    int err;
230 229
    V9fsState *s = pdu->s;
231 230

  
232 231
    if (v9fs_request_cancelled(pdu)) {
233 232
        return -EINTR;
234 233
    }
235
    fd = fidp->fs.fd;
236 234
    v9fs_co_run_in_worker(
237 235
        {
238
            err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset);
236
            err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
239 237
            if (err < 0) {
240 238
                err = -errno;
241 239
            }
......
246 244
int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
247 245
                   struct iovec *iov, int iovcnt, int64_t offset)
248 246
{
249
    int fd, err;
247
    int err;
250 248
    V9fsState *s = pdu->s;
251 249

  
252 250
    if (v9fs_request_cancelled(pdu)) {
253 251
        return -EINTR;
254 252
    }
255
    fd = fidp->fs.fd;
256 253
    v9fs_co_run_in_worker(
257 254
        {
258
            err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset);
255
            err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
259 256
            if (err < 0) {
260 257
                err = -errno;
261 258
            }
b/hw/9pfs/virtio-9p-coth.h
80 80
extern int v9fs_co_unlinkat(V9fsPDU *, V9fsPath *, V9fsString *, int flags);
81 81
extern int v9fs_co_renameat(V9fsPDU *, V9fsPath *, V9fsString *,
82 82
                            V9fsPath *, V9fsString *);
83
extern int v9fs_co_fstat(V9fsPDU *, int, struct stat *);
83
extern int v9fs_co_fstat(V9fsPDU *, V9fsFidState *, struct stat *);
84 84
extern int v9fs_co_opendir(V9fsPDU *, V9fsFidState *);
85 85
extern int v9fs_co_open(V9fsPDU *, V9fsFidState *, int);
86 86
extern int v9fs_co_open2(V9fsPDU *, V9fsFidState *, V9fsString *,
......
88 88
extern int v9fs_co_lsetxattr(V9fsPDU *, V9fsPath *, V9fsString *,
89 89
                             void *, size_t, int);
90 90
extern int v9fs_co_lremovexattr(V9fsPDU *, V9fsPath *, V9fsString *);
91
extern int v9fs_co_closedir(V9fsPDU *, DIR *);
92
extern int v9fs_co_close(V9fsPDU *, int);
91
extern int v9fs_co_closedir(V9fsPDU *, V9fsFidOpenState *);
92
extern int v9fs_co_close(V9fsPDU *, V9fsFidOpenState *);
93 93
extern int v9fs_co_fsync(V9fsPDU *, V9fsFidState *, int);
94 94
extern int v9fs_co_symlink(V9fsPDU *, V9fsFidState *, V9fsString *,
95 95
                           const char *, gid_t, struct stat *);
b/hw/9pfs/virtio-9p-handle.c
133 133
    return ret;
134 134
}
135 135

  
136
static int handle_close(FsContext *ctx, int fd)
136
static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
137 137
{
138
    return close(fd);
138
    return close(fs->fd);
139 139
}
140 140

  
141
static int handle_closedir(FsContext *ctx, DIR *dir)
141
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
142 142
{
143
    return closedir(dir);
143
    return closedir(fs->dir);
144 144
}
145 145

  
146
static int handle_open(FsContext *ctx, V9fsPath *fs_path, int flags)
146
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
147
                       int flags, V9fsFidOpenState *fs)
147 148
{
148 149
    struct handle_data *data = (struct handle_data *)ctx->private;
149 150

  
150
    return open_by_handle(data->mountfd, fs_path->data, flags);
151
    fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
152
    return fs->fd;
151 153
}
152 154

  
153
static DIR *handle_opendir(FsContext *ctx, V9fsPath *fs_path)
155
static int handle_opendir(FsContext *ctx,
156
                          V9fsPath *fs_path, V9fsFidOpenState *fs)
154 157
{
155
    int fd;
156
    fd = handle_open(ctx, fs_path, O_DIRECTORY);
157
    if (fd < 0) {
158
        return NULL;
158
    int ret;
159
    ret = handle_open(ctx, fs_path, O_DIRECTORY, fs);
160
    if (ret < 0) {
161
        return -1;
159 162
    }
160
    return fdopendir(fd);
163
    fs->dir = fdopendir(ret);
164
    if (!fs->dir) {
165
        return -1;
166
    }
167
    return 0;
161 168
}
162 169

  
163
static void handle_rewinddir(FsContext *ctx, DIR *dir)
170
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
164 171
{
165
    return rewinddir(dir);
172
    return rewinddir(fs->dir);
166 173
}
167 174

  
168
static off_t handle_telldir(FsContext *ctx, DIR *dir)
175
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
169 176
{
170
    return telldir(dir);
177
    return telldir(fs->dir);
171 178
}
172 179

  
173
static int handle_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
180
static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
181
                            struct dirent *entry,
174 182
                            struct dirent **result)
175 183
{
176
    return readdir_r(dir, entry, result);
184
    return readdir_r(fs->dir, entry, result);
177 185
}
178 186

  
179
static void handle_seekdir(FsContext *ctx, DIR *dir, off_t off)
187
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
180 188
{
181
    return seekdir(dir, off);
189
    return seekdir(fs->dir, off);
182 190
}
183 191

  
184
static ssize_t handle_preadv(FsContext *ctx, int fd, const struct iovec *iov,
192
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
193
                             const struct iovec *iov,
185 194
                             int iovcnt, off_t offset)
186 195
{
187 196
#ifdef CONFIG_PREADV
188
    return preadv(fd, iov, iovcnt, offset);
197
    return preadv(fs->fd, iov, iovcnt, offset);
189 198
#else
190
    int err = lseek(fd, offset, SEEK_SET);
199
    int err = lseek(fs->fd, offset, SEEK_SET);
191 200
    if (err == -1) {
192 201
        return err;
193 202
    } else {
194
        return readv(fd, iov, iovcnt);
203
        return readv(fs->fd, iov, iovcnt);
195 204
    }
196 205
#endif
197 206
}
198 207

  
199
static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
208
static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
209
                              const struct iovec *iov,
200 210
                              int iovcnt, off_t offset)
201 211
{
202 212
    ssize_t ret;
203 213
#ifdef CONFIG_PREADV
204
    ret = pwritev(fd, iov, iovcnt, offset);
214
    ret = pwritev(fs->fd, iov, iovcnt, offset);
205 215
#else
206
    int err = lseek(fd, offset, SEEK_SET);
216
    int err = lseek(fs->fd, offset, SEEK_SET);
207 217
    if (err == -1) {
208 218
        return err;
209 219
    } else {
210
        ret = writev(fd, iov, iovcnt);
220
        ret = writev(fs->fd, iov, iovcnt);
211 221
    }
212 222
#endif
213 223
#ifdef CONFIG_SYNC_FILE_RANGE
......
217 227
         * We want to ensure that we don't leave dirty pages in the cache
218 228
         * after write when writeout=immediate is sepcified.
219 229
         */
220
        sync_file_range(fd, offset, ret,
230
        sync_file_range(fs->fd, offset, ret,
221 231
                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
222 232
    }
223 233
#endif
......
274 284
    return ret;
275 285
}
276 286

  
277
static int handle_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
287
static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs,
288
                        struct stat *stbuf)
278 289
{
279
    return fstat(fd, stbuf);
290
    return fstat(fs->fd, stbuf);
280 291
}
281 292

  
282 293
static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
283
                       int flags, FsCred *credp)
294
                        int flags, FsCred *credp, V9fsFidOpenState *fs)
284 295
{
285 296
    int ret;
286 297
    int dirfd, fd;
......
296 307
        if (ret < 0) {
297 308
            close(fd);
298 309
            fd = ret;
310
        } else {
311
            fs->fd = fd;
299 312
        }
300 313
    }
301 314
    close(dirfd);
......
411 424
    return -1;
412 425
}
413 426

  
414
static int handle_fsync(FsContext *ctx, int fd, int datasync)
427
static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
415 428
{
416 429
    if (datasync) {
417
        return qemu_fdatasync(fd);
430
        return qemu_fdatasync(fs->fd);
418 431
    } else {
419
        return fsync(fd);
432
        return fsync(fs->fd);
420 433
    }
421 434
}
422 435

  
......
575 588
static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
576 589
                                 mode_t st_mode, uint64_t *st_gen)
577 590
{
578
    int err, fd;
591
    int err;
592
    V9fsFidOpenState fid_open;
579 593

  
580 594
    /*
581 595
     * Do not try to open special files like device nodes, fifos etc
......
584 598
    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
585 599
            return 0;
586 600
    }
587
    fd = handle_open(ctx, path, O_RDONLY);
588
    if (fd < 0) {
589
        return fd;
601
    err = handle_open(ctx, path, O_RDONLY, &fid_open);
602
    if (err < 0) {
603
        return err;
590 604
    }
591
    err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
592
    handle_close(ctx, fd);
605
    err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
606
    handle_close(ctx, &fid_open);
593 607
    return err;
594 608
}
595 609

  
b/hw/9pfs/virtio-9p-local.c
156 156
    return tsize;
157 157
}
158 158

  
159
static int local_close(FsContext *ctx, int fd)
159
static int local_close(FsContext *ctx, V9fsFidOpenState *fs)
160 160
{
161
    return close(fd);
161
    return close(fs->fd);
162 162
}
163 163

  
164
static int local_closedir(FsContext *ctx, DIR *dir)
164
static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
165 165
{
166
    return closedir(dir);
166
    return closedir(fs->dir);
167 167
}
168 168

  
169
static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags)
169
static int local_open(FsContext *ctx, V9fsPath *fs_path,
170
                      int flags, V9fsFidOpenState *fs)
170 171
{
171 172
    char buffer[PATH_MAX];
172 173
    char *path = fs_path->data;
173 174

  
174
    return open(rpath(ctx, path, buffer), flags);
175
    fs->fd = open(rpath(ctx, path, buffer), flags);
176
    return fs->fd;
175 177
}
176 178

  
177
static DIR *local_opendir(FsContext *ctx, V9fsPath *fs_path)
179
static int local_opendir(FsContext *ctx,
180
                         V9fsPath *fs_path, V9fsFidOpenState *fs)
178 181
{
179 182
    char buffer[PATH_MAX];
180 183
    char *path = fs_path->data;
181 184

  
182
    return opendir(rpath(ctx, path, buffer));
185
    fs->dir = opendir(rpath(ctx, path, buffer));
186
    if (!fs->dir) {
187
        return -1;
188
    }
189
    return 0;
183 190
}
184 191

  
185
static void local_rewinddir(FsContext *ctx, DIR *dir)
192
static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
186 193
{
187
    return rewinddir(dir);
194
    return rewinddir(fs->dir);
188 195
}
189 196

  
190
static off_t local_telldir(FsContext *ctx, DIR *dir)
197
static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
191 198
{
192
    return telldir(dir);
199
    return telldir(fs->dir);
193 200
}
194 201

  
195
static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
202
static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
203
                           struct dirent *entry,
196 204
                           struct dirent **result)
197 205
{
198
    return readdir_r(dir, entry, result);
206
    return readdir_r(fs->dir, entry, result);
199 207
}
200 208

  
201
static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
209
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
202 210
{
203
    return seekdir(dir, off);
211
    return seekdir(fs->dir, off);
204 212
}
205 213

  
206
static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
214
static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
215
                            const struct iovec *iov,
207 216
                            int iovcnt, off_t offset)
208 217
{
209 218
#ifdef CONFIG_PREADV
210
    return preadv(fd, iov, iovcnt, offset);
219
    return preadv(fs->fd, iov, iovcnt, offset);
211 220
#else
212
    int err = lseek(fd, offset, SEEK_SET);
221
    int err = lseek(fs->fd, offset, SEEK_SET);
213 222
    if (err == -1) {
214 223
        return err;
215 224
    } else {
216
        return readv(fd, iov, iovcnt);
225
        return readv(fs->fd, iov, iovcnt);
217 226
    }
218 227
#endif
219 228
}
220 229

  
221
static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
230
static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
231
                             const struct iovec *iov,
222 232
                             int iovcnt, off_t offset)
223 233
{
224 234
    ssize_t ret
225 235
;
226 236
#ifdef CONFIG_PREADV
227
    ret = pwritev(fd, iov, iovcnt, offset);
237
    ret = pwritev(fs->fd, iov, iovcnt, offset);
228 238
#else
229
    int err = lseek(fd, offset, SEEK_SET);
239
    int err = lseek(fs->fd, offset, SEEK_SET);
230 240
    if (err == -1) {
231 241
        return err;
232 242
    } else {
233
        ret = writev(fd, iov, iovcnt);
243
        ret = writev(fs->fd, iov, iovcnt);
234 244
    }
235 245
#endif
236 246
#ifdef CONFIG_SYNC_FILE_RANGE
......
240 250
         * We want to ensure that we don't leave dirty pages in the cache
241 251
         * after write when writeout=immediate is sepcified.
242 252
         */
243
        sync_file_range(fd, offset, ret,
253
        sync_file_range(fs->fd, offset, ret,
244 254
                        SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
245 255
    }
246 256
#endif
......
356 366
    return err;
357 367
}
358 368

  
359
static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
369
static int local_fstat(FsContext *fs_ctx,
370
                       V9fsFidOpenState *fs, struct stat *stbuf)
360 371
{
361 372
    int err;
362
    err = fstat(fd, stbuf);
373
    err = fstat(fs->fd, stbuf);
363 374
    if (err) {
364 375
        return err;
365 376
    }
......
370 381
        mode_t tmp_mode;
371 382
        dev_t tmp_dev;
372 383

  
373
        if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
384
        if (fgetxattr(fs->fd, "user.virtfs.uid",
385
                      &tmp_uid, sizeof(uid_t)) > 0) {
374 386
            stbuf->st_uid = tmp_uid;
375 387
        }
376
        if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
388
        if (fgetxattr(fs->fd, "user.virtfs.gid",
389
                      &tmp_gid, sizeof(gid_t)) > 0) {
377 390
            stbuf->st_gid = tmp_gid;
378 391
        }
379
        if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
392
        if (fgetxattr(fs->fd, "user.virtfs.mode",
393
                      &tmp_mode, sizeof(mode_t)) > 0) {
380 394
            stbuf->st_mode = tmp_mode;
381 395
        }
382
        if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
396
        if (fgetxattr(fs->fd, "user.virtfs.rdev",
397
                      &tmp_dev, sizeof(dev_t)) > 0) {
383 398
                stbuf->st_rdev = tmp_dev;
384 399
        }
385 400
    }
......
387 402
}
388 403

  
389 404
static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
390
                       int flags, FsCred *credp)
405
                       int flags, FsCred *credp, V9fsFidOpenState *fs)
391 406
{
392 407
    char *path;
393 408
    int fd = -1;
......
428 443
        }
429 444
    }
430 445
    err = fd;
446
    fs->fd = fd;
431 447
    goto out;
432 448

  
433 449
err_end:
......
577 593
    return remove(rpath(ctx, path, buffer));
578 594
}
579 595

  
580
static int local_fsync(FsContext *ctx, int fd, int datasync)
596
static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
581 597
{
582 598
    if (datasync) {
583
        return qemu_fdatasync(fd);
599
        return qemu_fdatasync(fs->fd);
584 600
    } else {
585
        return fsync(fd);
601
        return fsync(fs->fd);
586 602
    }
587 603
}
588 604

  
......
677 693
static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
678 694
                                mode_t st_mode, uint64_t *st_gen)
679 695
{
680
    int err, fd;
696
    int err;
697
    V9fsFidOpenState fid_open;
698

  
681 699
    /*
682 700
     * Do not try to open special files like device nodes, fifos etc
683 701
     * We can get fd for regular files and directories only
......
685 703
    if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
686 704
            return 0;
687 705
    }
688
    fd = local_open(ctx, path, O_RDONLY);
689
    if (fd < 0) {
690
        return fd;
706
    err = local_open(ctx, path, O_RDONLY, &fid_open);
707
    if (err < 0) {
708
        return err;
691 709
    }
692
    err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
693
    local_close(ctx, fd);
710
    err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
711
    local_close(ctx, &fid_open);
694 712
    return err;
695 713
}
696 714

  
b/hw/9pfs/virtio-9p.c
455 455
    if (fidp->fid_type == P9_FID_FILE) {
456 456
        /* If we reclaimed the fd no need to close */
457 457
        if (fidp->fs.fd != -1) {
458
            retval = v9fs_co_close(pdu, fidp->fs.fd);
458
            retval = v9fs_co_close(pdu, &fidp->fs);
459 459
        }
460 460
    } else if (fidp->fid_type == P9_FID_DIR) {
461 461
        if (fidp->fs.dir != NULL) {
462
            retval = v9fs_co_closedir(pdu, fidp->fs.dir);
462
            retval = v9fs_co_closedir(pdu, &fidp->fs);
463 463
        }
464 464
    } else if (fidp->fid_type == P9_FID_XATTR) {
465 465
        retval = v9fs_xattr_fid_clunk(pdu, fidp);
......
567 567
        f = reclaim_list;
568 568
        reclaim_list = f->rclm_lst;
569 569
        if (f->fid_type == P9_FID_FILE) {
570
            v9fs_co_close(pdu, f->fs_reclaim.fd);
570
            v9fs_co_close(pdu, &f->fs_reclaim);
571 571
        } else if (f->fid_type == P9_FID_DIR) {
572
            v9fs_co_closedir(pdu, f->fs_reclaim.dir);
572
            v9fs_co_closedir(pdu, &f->fs_reclaim);
573 573
        }
574 574
        f->rclm_lst = NULL;
575 575
        /*
......
3009 3009
        err = -ENOENT;
3010 3010
        goto out_nofid;
3011 3011
    }
3012
    err = v9fs_co_fstat(pdu, fidp->fs.fd, &stbuf);
3012
    err = v9fs_co_fstat(pdu, fidp, &stbuf);
3013 3013
    if (err < 0) {
3014 3014
        goto out;
3015 3015
    }
......
3052 3052
        err = -ENOENT;
3053 3053
        goto out_nofid;
3054 3054
    }
3055
    err = v9fs_co_fstat(pdu, fidp->fs.fd, &stbuf);
3055
    err = v9fs_co_fstat(pdu, fidp, &stbuf);
3056 3056
    if (err < 0) {
3057 3057
        goto out;
3058 3058
    }
b/hw/9pfs/virtio-9p.h
204 204
    int flags;
205 205
} V9fsXattr;
206 206

  
207
/*
208
 * Filled by fs driver on open and other
209
 * calls.
210
 */
211
union V9fsFidOpenState {
212
    int fd;
213
    DIR *dir;
214
    V9fsXattr xattr;
215
};
216

  
207 217
struct V9fsFidState
208 218
{
209 219
    int fid_type;
210 220
    int32_t fid;
211 221
    V9fsPath path;
212
    union {
213
        int fd;
214
        DIR *dir;
215
        V9fsXattr xattr;
216
    } fs;
217
    union {
218
        int fd;
219
        DIR *dir;
220
    } fs_reclaim;
222
    V9fsFidOpenState fs;
223
    V9fsFidOpenState fs_reclaim;
221 224
    int flags;
222 225
    int open_flags;
223 226
    uid_t uid;

Also available in: Unified diff