Statistics
| Branch: | Revision:

root / hw / 9pfs / virtio-9p.c @ 7834cf77

History | View | Annotate | Download (81.3 kB)

1 9f107513 Anthony Liguori
/*
2 9f107513 Anthony Liguori
 * Virtio 9p backend
3 9f107513 Anthony Liguori
 *
4 9f107513 Anthony Liguori
 * Copyright IBM, Corp. 2010
5 9f107513 Anthony Liguori
 *
6 9f107513 Anthony Liguori
 * Authors:
7 9f107513 Anthony Liguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 9f107513 Anthony Liguori
 *
9 9f107513 Anthony Liguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 9f107513 Anthony Liguori
 * the COPYING file in the top-level directory.
11 9f107513 Anthony Liguori
 *
12 9f107513 Anthony Liguori
 */
13 9f107513 Anthony Liguori
14 873c3213 Stefan Weil
#include "hw/virtio.h"
15 873c3213 Stefan Weil
#include "hw/pc.h"
16 9f107513 Anthony Liguori
#include "qemu_socket.h"
17 873c3213 Stefan Weil
#include "hw/virtio-pci.h"
18 9f107513 Anthony Liguori
#include "virtio-9p.h"
19 9f107513 Anthony Liguori
#include "fsdev/qemu-fsdev.h"
20 9f107513 Anthony Liguori
#include "virtio-9p-debug.h"
21 fc22118d Aneesh Kumar K.V
#include "virtio-9p-xattr.h"
22 ff06030f Venkateswararao Jujjuri (JV)
#include "virtio-9p-coth.h"
23 9f107513 Anthony Liguori
24 9f107513 Anthony Liguori
int debug_9p_pdu;
25 7a462745 Aneesh Kumar K.V
int open_fd_hw;
26 7a462745 Aneesh Kumar K.V
int total_open_fd;
27 7a462745 Aneesh Kumar K.V
static int open_fd_rc;
28 9f107513 Anthony Liguori
29 fac4f111 Venkateswararao Jujjuri (JV)
enum {
30 fac4f111 Venkateswararao Jujjuri (JV)
    Oread   = 0x00,
31 fac4f111 Venkateswararao Jujjuri (JV)
    Owrite  = 0x01,
32 fac4f111 Venkateswararao Jujjuri (JV)
    Ordwr   = 0x02,
33 fac4f111 Venkateswararao Jujjuri (JV)
    Oexec   = 0x03,
34 fac4f111 Venkateswararao Jujjuri (JV)
    Oexcl   = 0x04,
35 fac4f111 Venkateswararao Jujjuri (JV)
    Otrunc  = 0x10,
36 fac4f111 Venkateswararao Jujjuri (JV)
    Orexec  = 0x20,
37 fac4f111 Venkateswararao Jujjuri (JV)
    Orclose = 0x40,
38 fac4f111 Venkateswararao Jujjuri (JV)
    Oappend = 0x80,
39 fac4f111 Venkateswararao Jujjuri (JV)
};
40 fac4f111 Venkateswararao Jujjuri (JV)
41 fac4f111 Venkateswararao Jujjuri (JV)
static int omode_to_uflags(int8_t mode)
42 fac4f111 Venkateswararao Jujjuri (JV)
{
43 fac4f111 Venkateswararao Jujjuri (JV)
    int ret = 0;
44 fac4f111 Venkateswararao Jujjuri (JV)
45 fac4f111 Venkateswararao Jujjuri (JV)
    switch (mode & 3) {
46 fac4f111 Venkateswararao Jujjuri (JV)
    case Oread:
47 fac4f111 Venkateswararao Jujjuri (JV)
        ret = O_RDONLY;
48 fac4f111 Venkateswararao Jujjuri (JV)
        break;
49 fac4f111 Venkateswararao Jujjuri (JV)
    case Ordwr:
50 fac4f111 Venkateswararao Jujjuri (JV)
        ret = O_RDWR;
51 fac4f111 Venkateswararao Jujjuri (JV)
        break;
52 fac4f111 Venkateswararao Jujjuri (JV)
    case Owrite:
53 fac4f111 Venkateswararao Jujjuri (JV)
        ret = O_WRONLY;
54 fac4f111 Venkateswararao Jujjuri (JV)
        break;
55 fac4f111 Venkateswararao Jujjuri (JV)
    case Oexec:
56 fac4f111 Venkateswararao Jujjuri (JV)
        ret = O_RDONLY;
57 fac4f111 Venkateswararao Jujjuri (JV)
        break;
58 fac4f111 Venkateswararao Jujjuri (JV)
    }
59 fac4f111 Venkateswararao Jujjuri (JV)
60 fac4f111 Venkateswararao Jujjuri (JV)
    if (mode & Otrunc) {
61 fac4f111 Venkateswararao Jujjuri (JV)
        ret |= O_TRUNC;
62 fac4f111 Venkateswararao Jujjuri (JV)
    }
63 fac4f111 Venkateswararao Jujjuri (JV)
64 fac4f111 Venkateswararao Jujjuri (JV)
    if (mode & Oappend) {
65 fac4f111 Venkateswararao Jujjuri (JV)
        ret |= O_APPEND;
66 fac4f111 Venkateswararao Jujjuri (JV)
    }
67 fac4f111 Venkateswararao Jujjuri (JV)
68 fac4f111 Venkateswararao Jujjuri (JV)
    if (mode & Oexcl) {
69 fac4f111 Venkateswararao Jujjuri (JV)
        ret |= O_EXCL;
70 fac4f111 Venkateswararao Jujjuri (JV)
    }
71 fac4f111 Venkateswararao Jujjuri (JV)
72 fac4f111 Venkateswararao Jujjuri (JV)
    return ret;
73 fac4f111 Venkateswararao Jujjuri (JV)
}
74 fac4f111 Venkateswararao Jujjuri (JV)
75 758e8e38 Venkateswararao Jujjuri (JV)
void cred_init(FsCred *credp)
76 131dcb25 Anthony Liguori
{
77 758e8e38 Venkateswararao Jujjuri (JV)
    credp->fc_uid = -1;
78 758e8e38 Venkateswararao Jujjuri (JV)
    credp->fc_gid = -1;
79 758e8e38 Venkateswararao Jujjuri (JV)
    credp->fc_mode = -1;
80 758e8e38 Venkateswararao Jujjuri (JV)
    credp->fc_rdev = -1;
81 131dcb25 Anthony Liguori
}
82 131dcb25 Anthony Liguori
83 a03f7874 Anthony Liguori
static void v9fs_string_init(V9fsString *str)
84 a03f7874 Anthony Liguori
{
85 a03f7874 Anthony Liguori
    str->data = NULL;
86 a03f7874 Anthony Liguori
    str->size = 0;
87 a03f7874 Anthony Liguori
}
88 a03f7874 Anthony Liguori
89 a03f7874 Anthony Liguori
static void v9fs_string_free(V9fsString *str)
90 a03f7874 Anthony Liguori
{
91 7267c094 Anthony Liguori
    g_free(str->data);
92 a03f7874 Anthony Liguori
    str->data = NULL;
93 a03f7874 Anthony Liguori
    str->size = 0;
94 a03f7874 Anthony Liguori
}
95 a03f7874 Anthony Liguori
96 a03f7874 Anthony Liguori
static void v9fs_string_null(V9fsString *str)
97 a03f7874 Anthony Liguori
{
98 a03f7874 Anthony Liguori
    v9fs_string_free(str);
99 a03f7874 Anthony Liguori
}
100 a03f7874 Anthony Liguori
101 a03f7874 Anthony Liguori
static int number_to_string(void *arg, char type)
102 a03f7874 Anthony Liguori
{
103 a03f7874 Anthony Liguori
    unsigned int ret = 0;
104 a03f7874 Anthony Liguori
105 a03f7874 Anthony Liguori
    switch (type) {
106 a03f7874 Anthony Liguori
    case 'u': {
107 a03f7874 Anthony Liguori
        unsigned int num = *(unsigned int *)arg;
108 a03f7874 Anthony Liguori
109 a03f7874 Anthony Liguori
        do {
110 a03f7874 Anthony Liguori
            ret++;
111 a03f7874 Anthony Liguori
            num = num/10;
112 a03f7874 Anthony Liguori
        } while (num);
113 a03f7874 Anthony Liguori
        break;
114 a03f7874 Anthony Liguori
    }
115 45b23ff8 Venkateswararao Jujjuri (JV)
    case 'U': {
116 45b23ff8 Venkateswararao Jujjuri (JV)
        unsigned long num = *(unsigned long *)arg;
117 45b23ff8 Venkateswararao Jujjuri (JV)
        do {
118 45b23ff8 Venkateswararao Jujjuri (JV)
            ret++;
119 45b23ff8 Venkateswararao Jujjuri (JV)
            num = num/10;
120 45b23ff8 Venkateswararao Jujjuri (JV)
        } while (num);
121 45b23ff8 Venkateswararao Jujjuri (JV)
        break;
122 45b23ff8 Venkateswararao Jujjuri (JV)
    }
123 a03f7874 Anthony Liguori
    default:
124 a03f7874 Anthony Liguori
        printf("Number_to_string: Unknown number format\n");
125 a03f7874 Anthony Liguori
        return -1;
126 a03f7874 Anthony Liguori
    }
127 a03f7874 Anthony Liguori
128 a03f7874 Anthony Liguori
    return ret;
129 a03f7874 Anthony Liguori
}
130 a03f7874 Anthony Liguori
131 c9ba47dc Stefan Weil
static int GCC_FMT_ATTR(2, 0)
132 c9ba47dc Stefan Weil
v9fs_string_alloc_printf(char **strp, const char *fmt, va_list ap)
133 a03f7874 Anthony Liguori
{
134 a03f7874 Anthony Liguori
    va_list ap2;
135 a03f7874 Anthony Liguori
    char *iter = (char *)fmt;
136 a03f7874 Anthony Liguori
    int len = 0;
137 a03f7874 Anthony Liguori
    int nr_args = 0;
138 a03f7874 Anthony Liguori
    char *arg_char_ptr;
139 a03f7874 Anthony Liguori
    unsigned int arg_uint;
140 45b23ff8 Venkateswararao Jujjuri (JV)
    unsigned long arg_ulong;
141 a03f7874 Anthony Liguori
142 a03f7874 Anthony Liguori
    /* Find the number of %'s that denotes an argument */
143 a03f7874 Anthony Liguori
    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
144 a03f7874 Anthony Liguori
        nr_args++;
145 a03f7874 Anthony Liguori
        iter++;
146 a03f7874 Anthony Liguori
    }
147 a03f7874 Anthony Liguori
148 a03f7874 Anthony Liguori
    len = strlen(fmt) - 2*nr_args;
149 a03f7874 Anthony Liguori
150 a03f7874 Anthony Liguori
    if (!nr_args) {
151 a03f7874 Anthony Liguori
        goto alloc_print;
152 a03f7874 Anthony Liguori
    }
153 a03f7874 Anthony Liguori
154 a03f7874 Anthony Liguori
    va_copy(ap2, ap);
155 a03f7874 Anthony Liguori
156 a03f7874 Anthony Liguori
    iter = (char *)fmt;
157 a03f7874 Anthony Liguori
158 a03f7874 Anthony Liguori
    /* Now parse the format string */
159 a03f7874 Anthony Liguori
    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
160 a03f7874 Anthony Liguori
        iter++;
161 a03f7874 Anthony Liguori
        switch (*iter) {
162 a03f7874 Anthony Liguori
        case 'u':
163 a03f7874 Anthony Liguori
            arg_uint = va_arg(ap2, unsigned int);
164 a03f7874 Anthony Liguori
            len += number_to_string((void *)&arg_uint, 'u');
165 a03f7874 Anthony Liguori
            break;
166 45b23ff8 Venkateswararao Jujjuri (JV)
        case 'l':
167 45b23ff8 Venkateswararao Jujjuri (JV)
            if (*++iter == 'u') {
168 45b23ff8 Venkateswararao Jujjuri (JV)
                arg_ulong = va_arg(ap2, unsigned long);
169 45b23ff8 Venkateswararao Jujjuri (JV)
                len += number_to_string((void *)&arg_ulong, 'U');
170 45b23ff8 Venkateswararao Jujjuri (JV)
            } else {
171 45b23ff8 Venkateswararao Jujjuri (JV)
                return -1;
172 45b23ff8 Venkateswararao Jujjuri (JV)
            }
173 45b23ff8 Venkateswararao Jujjuri (JV)
            break;
174 a03f7874 Anthony Liguori
        case 's':
175 a03f7874 Anthony Liguori
            arg_char_ptr = va_arg(ap2, char *);
176 a03f7874 Anthony Liguori
            len += strlen(arg_char_ptr);
177 a03f7874 Anthony Liguori
            break;
178 a03f7874 Anthony Liguori
        case 'c':
179 a03f7874 Anthony Liguori
            len += 1;
180 a03f7874 Anthony Liguori
            break;
181 a03f7874 Anthony Liguori
        default:
182 a03f7874 Anthony Liguori
            fprintf(stderr,
183 a03f7874 Anthony Liguori
                    "v9fs_string_alloc_printf:Incorrect format %c", *iter);
184 a03f7874 Anthony Liguori
            return -1;
185 a03f7874 Anthony Liguori
        }
186 a03f7874 Anthony Liguori
        iter++;
187 a03f7874 Anthony Liguori
    }
188 a03f7874 Anthony Liguori
189 a03f7874 Anthony Liguori
alloc_print:
190 7267c094 Anthony Liguori
    *strp = g_malloc((len + 1) * sizeof(**strp));
191 a03f7874 Anthony Liguori
192 a03f7874 Anthony Liguori
    return vsprintf(*strp, fmt, ap);
193 a03f7874 Anthony Liguori
}
194 a03f7874 Anthony Liguori
195 c9ba47dc Stefan Weil
static void GCC_FMT_ATTR(2, 3)
196 c9ba47dc Stefan Weil
v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
197 a03f7874 Anthony Liguori
{
198 a03f7874 Anthony Liguori
    va_list ap;
199 a03f7874 Anthony Liguori
    int err;
200 a03f7874 Anthony Liguori
201 a03f7874 Anthony Liguori
    v9fs_string_free(str);
202 a03f7874 Anthony Liguori
203 a03f7874 Anthony Liguori
    va_start(ap, fmt);
204 a03f7874 Anthony Liguori
    err = v9fs_string_alloc_printf(&str->data, fmt, ap);
205 a03f7874 Anthony Liguori
    BUG_ON(err == -1);
206 a03f7874 Anthony Liguori
    va_end(ap);
207 a03f7874 Anthony Liguori
208 a03f7874 Anthony Liguori
    str->size = err;
209 a03f7874 Anthony Liguori
}
210 a03f7874 Anthony Liguori
211 a03f7874 Anthony Liguori
static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
212 a03f7874 Anthony Liguori
{
213 a03f7874 Anthony Liguori
    v9fs_string_free(lhs);
214 a03f7874 Anthony Liguori
    v9fs_string_sprintf(lhs, "%s", rhs->data);
215 a03f7874 Anthony Liguori
}
216 a03f7874 Anthony Liguori
217 936532a4 Malahal Naineni
/*
218 936532a4 Malahal Naineni
 * Return TRUE if s1 is an ancestor of s2.
219 936532a4 Malahal Naineni
 *
220 936532a4 Malahal Naineni
 * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
221 936532a4 Malahal Naineni
 * As a special case, We treat s1 as ancestor of s2 if they are same!
222 936532a4 Malahal Naineni
 */
223 936532a4 Malahal Naineni
static int v9fs_path_is_ancestor(V9fsString *s1, V9fsString *s2)
224 936532a4 Malahal Naineni
{
225 936532a4 Malahal Naineni
    if (!strncmp(s1->data, s2->data, s1->size)) {
226 936532a4 Malahal Naineni
        if (s2->data[s1->size] == '\0' || s2->data[s1->size] == '/') {
227 936532a4 Malahal Naineni
            return 1;
228 936532a4 Malahal Naineni
        }
229 936532a4 Malahal Naineni
    }
230 936532a4 Malahal Naineni
    return 0;
231 936532a4 Malahal Naineni
}
232 936532a4 Malahal Naineni
233 a03f7874 Anthony Liguori
static size_t v9fs_string_size(V9fsString *str)
234 a03f7874 Anthony Liguori
{
235 a03f7874 Anthony Liguori
    return str->size;
236 a03f7874 Anthony Liguori
}
237 a03f7874 Anthony Liguori
238 b9cb88b0 Aneesh Kumar K.V
/*
239 b9cb88b0 Aneesh Kumar K.V
 * returns 0 if fid got re-opened, 1 if not, < 0 on error */
240 b9cb88b0 Aneesh Kumar K.V
static int v9fs_reopen_fid(V9fsState *s, V9fsFidState *f)
241 b9cb88b0 Aneesh Kumar K.V
{
242 b9cb88b0 Aneesh Kumar K.V
    int err = 1;
243 b9cb88b0 Aneesh Kumar K.V
    if (f->fid_type == P9_FID_FILE) {
244 b9cb88b0 Aneesh Kumar K.V
        if (f->fs.fd == -1) {
245 b9cb88b0 Aneesh Kumar K.V
            do {
246 b9cb88b0 Aneesh Kumar K.V
                err = v9fs_co_open(s, f, f->open_flags);
247 b9cb88b0 Aneesh Kumar K.V
            } while (err == -EINTR);
248 b9cb88b0 Aneesh Kumar K.V
        }
249 b9cb88b0 Aneesh Kumar K.V
    } else if (f->fid_type == P9_FID_DIR) {
250 b9cb88b0 Aneesh Kumar K.V
        if (f->fs.dir == NULL) {
251 b9cb88b0 Aneesh Kumar K.V
            do {
252 b9cb88b0 Aneesh Kumar K.V
                err = v9fs_co_opendir(s, f);
253 b9cb88b0 Aneesh Kumar K.V
            } while (err == -EINTR);
254 b9cb88b0 Aneesh Kumar K.V
        }
255 b9cb88b0 Aneesh Kumar K.V
    }
256 b9cb88b0 Aneesh Kumar K.V
    return err;
257 b9cb88b0 Aneesh Kumar K.V
}
258 b9cb88b0 Aneesh Kumar K.V
259 84dfb926 Aneesh Kumar K.V
static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
260 286d5652 Anthony Liguori
{
261 7a462745 Aneesh Kumar K.V
    int err;
262 286d5652 Anthony Liguori
    V9fsFidState *f;
263 286d5652 Anthony Liguori
264 286d5652 Anthony Liguori
    for (f = s->fid_list; f; f = f->next) {
265 84dfb926 Aneesh Kumar K.V
        BUG_ON(f->clunked);
266 286d5652 Anthony Liguori
        if (f->fid == fid) {
267 7a462745 Aneesh Kumar K.V
            /*
268 7a462745 Aneesh Kumar K.V
             * Update the fid ref upfront so that
269 7a462745 Aneesh Kumar K.V
             * we don't get reclaimed when we yield
270 7a462745 Aneesh Kumar K.V
             * in open later.
271 7a462745 Aneesh Kumar K.V
             */
272 84dfb926 Aneesh Kumar K.V
            f->ref++;
273 7a462745 Aneesh Kumar K.V
            /*
274 7a462745 Aneesh Kumar K.V
             * check whether we need to reopen the
275 7a462745 Aneesh Kumar K.V
             * file. We might have closed the fd
276 7a462745 Aneesh Kumar K.V
             * while trying to free up some file
277 7a462745 Aneesh Kumar K.V
             * descriptors.
278 7a462745 Aneesh Kumar K.V
             */
279 b9cb88b0 Aneesh Kumar K.V
            err = v9fs_reopen_fid(s, f);
280 b9cb88b0 Aneesh Kumar K.V
            if (err < 0) {
281 b9cb88b0 Aneesh Kumar K.V
                f->ref--;
282 b9cb88b0 Aneesh Kumar K.V
                return NULL;
283 b9cb88b0 Aneesh Kumar K.V
            }
284 7a462745 Aneesh Kumar K.V
            /*
285 7a462745 Aneesh Kumar K.V
             * Mark the fid as referenced so that the LRU
286 7a462745 Aneesh Kumar K.V
             * reclaim won't close the file descriptor
287 7a462745 Aneesh Kumar K.V
             */
288 7a462745 Aneesh Kumar K.V
            f->flags |= FID_REFERENCED;
289 286d5652 Anthony Liguori
            return f;
290 286d5652 Anthony Liguori
        }
291 286d5652 Anthony Liguori
    }
292 286d5652 Anthony Liguori
    return NULL;
293 286d5652 Anthony Liguori
}
294 286d5652 Anthony Liguori
295 286d5652 Anthony Liguori
static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
296 286d5652 Anthony Liguori
{
297 286d5652 Anthony Liguori
    V9fsFidState *f;
298 286d5652 Anthony Liguori
299 84dfb926 Aneesh Kumar K.V
    for (f = s->fid_list; f; f = f->next) {
300 84dfb926 Aneesh Kumar K.V
        /* If fid is already there return NULL */
301 84dfb926 Aneesh Kumar K.V
        BUG_ON(f->clunked);
302 84dfb926 Aneesh Kumar K.V
        if (f->fid == fid) {
303 84dfb926 Aneesh Kumar K.V
            return NULL;
304 84dfb926 Aneesh Kumar K.V
        }
305 286d5652 Anthony Liguori
    }
306 7267c094 Anthony Liguori
    f = g_malloc0(sizeof(V9fsFidState));
307 286d5652 Anthony Liguori
    f->fid = fid;
308 d62dbb51 Aneesh Kumar K.V
    f->fid_type = P9_FID_NONE;
309 84dfb926 Aneesh Kumar K.V
    f->ref = 1;
310 7a462745 Aneesh Kumar K.V
    /*
311 7a462745 Aneesh Kumar K.V
     * Mark the fid as referenced so that the LRU
312 7a462745 Aneesh Kumar K.V
     * reclaim won't close the file descriptor
313 7a462745 Aneesh Kumar K.V
     */
314 7a462745 Aneesh Kumar K.V
    f->flags |= FID_REFERENCED;
315 286d5652 Anthony Liguori
    f->next = s->fid_list;
316 286d5652 Anthony Liguori
    s->fid_list = f;
317 286d5652 Anthony Liguori
318 286d5652 Anthony Liguori
    return f;
319 286d5652 Anthony Liguori
}
320 286d5652 Anthony Liguori
321 10b468bd Aneesh Kumar K.V
static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp)
322 10b468bd Aneesh Kumar K.V
{
323 10b468bd Aneesh Kumar K.V
    int retval = 0;
324 10b468bd Aneesh Kumar K.V
325 10b468bd Aneesh Kumar K.V
    if (fidp->fs.xattr.copied_len == -1) {
326 10b468bd Aneesh Kumar K.V
        /* getxattr/listxattr fid */
327 10b468bd Aneesh Kumar K.V
        goto free_value;
328 10b468bd Aneesh Kumar K.V
    }
329 10b468bd Aneesh Kumar K.V
    /*
330 10b468bd Aneesh Kumar K.V
     * if this is fid for setxattr. clunk should
331 10b468bd Aneesh Kumar K.V
     * result in setxattr localcall
332 10b468bd Aneesh Kumar K.V
     */
333 10b468bd Aneesh Kumar K.V
    if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
334 10b468bd Aneesh Kumar K.V
        /* clunk after partial write */
335 10b468bd Aneesh Kumar K.V
        retval = -EINVAL;
336 10b468bd Aneesh Kumar K.V
        goto free_out;
337 10b468bd Aneesh Kumar K.V
    }
338 9ed3ef26 Aneesh Kumar K.V
    if (fidp->fs.xattr.len) {
339 c540ee51 Aneesh Kumar K.V
        retval = v9fs_co_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
340 9ed3ef26 Aneesh Kumar K.V
                                   fidp->fs.xattr.value,
341 9ed3ef26 Aneesh Kumar K.V
                                   fidp->fs.xattr.len,
342 9ed3ef26 Aneesh Kumar K.V
                                   fidp->fs.xattr.flags);
343 9ed3ef26 Aneesh Kumar K.V
    } else {
344 c540ee51 Aneesh Kumar K.V
        retval = v9fs_co_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name);
345 9ed3ef26 Aneesh Kumar K.V
    }
346 10b468bd Aneesh Kumar K.V
free_out:
347 10b468bd Aneesh Kumar K.V
    v9fs_string_free(&fidp->fs.xattr.name);
348 10b468bd Aneesh Kumar K.V
free_value:
349 10b468bd Aneesh Kumar K.V
    if (fidp->fs.xattr.value) {
350 7267c094 Anthony Liguori
        g_free(fidp->fs.xattr.value);
351 10b468bd Aneesh Kumar K.V
    }
352 10b468bd Aneesh Kumar K.V
    return retval;
353 10b468bd Aneesh Kumar K.V
}
354 10b468bd Aneesh Kumar K.V
355 84dfb926 Aneesh Kumar K.V
static int free_fid(V9fsState *s, V9fsFidState *fidp)
356 286d5652 Anthony Liguori
{
357 10b468bd Aneesh Kumar K.V
    int retval = 0;
358 84dfb926 Aneesh Kumar K.V
359 84dfb926 Aneesh Kumar K.V
    if (fidp->fid_type == P9_FID_FILE) {
360 7a462745 Aneesh Kumar K.V
        /* If we reclaimed the fd no need to close */
361 7a462745 Aneesh Kumar K.V
        if (fidp->fs.fd != -1) {
362 7a462745 Aneesh Kumar K.V
            retval = v9fs_co_close(s, fidp->fs.fd);
363 7a462745 Aneesh Kumar K.V
        }
364 84dfb926 Aneesh Kumar K.V
    } else if (fidp->fid_type == P9_FID_DIR) {
365 95f65511 Aneesh Kumar K.V
        if (fidp->fs.dir != NULL) {
366 95f65511 Aneesh Kumar K.V
            retval = v9fs_co_closedir(s, fidp->fs.dir);
367 95f65511 Aneesh Kumar K.V
        }
368 84dfb926 Aneesh Kumar K.V
    } else if (fidp->fid_type == P9_FID_XATTR) {
369 84dfb926 Aneesh Kumar K.V
        retval = v9fs_xattr_fid_clunk(s, fidp);
370 84dfb926 Aneesh Kumar K.V
    }
371 84dfb926 Aneesh Kumar K.V
    v9fs_string_free(&fidp->path);
372 84dfb926 Aneesh Kumar K.V
    g_free(fidp);
373 84dfb926 Aneesh Kumar K.V
    return retval;
374 84dfb926 Aneesh Kumar K.V
}
375 84dfb926 Aneesh Kumar K.V
376 84dfb926 Aneesh Kumar K.V
static void put_fid(V9fsState *s, V9fsFidState *fidp)
377 84dfb926 Aneesh Kumar K.V
{
378 84dfb926 Aneesh Kumar K.V
    BUG_ON(!fidp->ref);
379 84dfb926 Aneesh Kumar K.V
    fidp->ref--;
380 7a462745 Aneesh Kumar K.V
    /*
381 7a462745 Aneesh Kumar K.V
     * Don't free the fid if it is in reclaim list
382 7a462745 Aneesh Kumar K.V
     */
383 84dfb926 Aneesh Kumar K.V
    if (!fidp->ref && fidp->clunked) {
384 84dfb926 Aneesh Kumar K.V
        free_fid(s, fidp);
385 84dfb926 Aneesh Kumar K.V
    }
386 84dfb926 Aneesh Kumar K.V
}
387 84dfb926 Aneesh Kumar K.V
388 84dfb926 Aneesh Kumar K.V
static int clunk_fid(V9fsState *s, int32_t fid)
389 84dfb926 Aneesh Kumar K.V
{
390 286d5652 Anthony Liguori
    V9fsFidState **fidpp, *fidp;
391 286d5652 Anthony Liguori
392 286d5652 Anthony Liguori
    for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
393 286d5652 Anthony Liguori
        if ((*fidpp)->fid == fid) {
394 286d5652 Anthony Liguori
            break;
395 286d5652 Anthony Liguori
        }
396 286d5652 Anthony Liguori
    }
397 286d5652 Anthony Liguori
398 286d5652 Anthony Liguori
    if (*fidpp == NULL) {
399 286d5652 Anthony Liguori
        return -ENOENT;
400 286d5652 Anthony Liguori
    }
401 286d5652 Anthony Liguori
    fidp = *fidpp;
402 286d5652 Anthony Liguori
    *fidpp = fidp->next;
403 84dfb926 Aneesh Kumar K.V
    fidp->clunked = 1;
404 84dfb926 Aneesh Kumar K.V
    return 0;
405 286d5652 Anthony Liguori
}
406 286d5652 Anthony Liguori
407 7a462745 Aneesh Kumar K.V
void v9fs_reclaim_fd(V9fsState *s)
408 7a462745 Aneesh Kumar K.V
{
409 7a462745 Aneesh Kumar K.V
    int reclaim_count = 0;
410 7a462745 Aneesh Kumar K.V
    V9fsFidState *f, *reclaim_list = NULL;
411 7a462745 Aneesh Kumar K.V
412 7a462745 Aneesh Kumar K.V
    for (f = s->fid_list; f; f = f->next) {
413 7a462745 Aneesh Kumar K.V
        /*
414 7a462745 Aneesh Kumar K.V
         * Unlink fids cannot be reclaimed. Check
415 7a462745 Aneesh Kumar K.V
         * for them and skip them. Also skip fids
416 7a462745 Aneesh Kumar K.V
         * currently being operated on.
417 7a462745 Aneesh Kumar K.V
         */
418 7a462745 Aneesh Kumar K.V
        if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
419 7a462745 Aneesh Kumar K.V
            continue;
420 7a462745 Aneesh Kumar K.V
        }
421 7a462745 Aneesh Kumar K.V
        /*
422 7a462745 Aneesh Kumar K.V
         * if it is a recently referenced fid
423 7a462745 Aneesh Kumar K.V
         * we leave the fid untouched and clear the
424 7a462745 Aneesh Kumar K.V
         * reference bit. We come back to it later
425 7a462745 Aneesh Kumar K.V
         * in the next iteration. (a simple LRU without
426 7a462745 Aneesh Kumar K.V
         * moving list elements around)
427 7a462745 Aneesh Kumar K.V
         */
428 7a462745 Aneesh Kumar K.V
        if (f->flags & FID_REFERENCED) {
429 7a462745 Aneesh Kumar K.V
            f->flags &= ~FID_REFERENCED;
430 7a462745 Aneesh Kumar K.V
            continue;
431 7a462745 Aneesh Kumar K.V
        }
432 7a462745 Aneesh Kumar K.V
        /*
433 7a462745 Aneesh Kumar K.V
         * Add fids to reclaim list.
434 7a462745 Aneesh Kumar K.V
         */
435 7a462745 Aneesh Kumar K.V
        if (f->fid_type == P9_FID_FILE) {
436 7a462745 Aneesh Kumar K.V
            if (f->fs.fd != -1) {
437 7a462745 Aneesh Kumar K.V
                /*
438 7a462745 Aneesh Kumar K.V
                 * Up the reference count so that
439 7a462745 Aneesh Kumar K.V
                 * a clunk request won't free this fid
440 7a462745 Aneesh Kumar K.V
                 */
441 7a462745 Aneesh Kumar K.V
                f->ref++;
442 7a462745 Aneesh Kumar K.V
                f->rclm_lst = reclaim_list;
443 7a462745 Aneesh Kumar K.V
                reclaim_list = f;
444 7a462745 Aneesh Kumar K.V
                f->fs_reclaim.fd = f->fs.fd;
445 7a462745 Aneesh Kumar K.V
                f->fs.fd = -1;
446 7a462745 Aneesh Kumar K.V
                reclaim_count++;
447 7a462745 Aneesh Kumar K.V
            }
448 95f65511 Aneesh Kumar K.V
        } else if (f->fid_type == P9_FID_DIR) {
449 95f65511 Aneesh Kumar K.V
            if (f->fs.dir != NULL) {
450 95f65511 Aneesh Kumar K.V
                /*
451 95f65511 Aneesh Kumar K.V
                 * Up the reference count so that
452 95f65511 Aneesh Kumar K.V
                 * a clunk request won't free this fid
453 95f65511 Aneesh Kumar K.V
                 */
454 95f65511 Aneesh Kumar K.V
                f->ref++;
455 95f65511 Aneesh Kumar K.V
                f->rclm_lst = reclaim_list;
456 95f65511 Aneesh Kumar K.V
                reclaim_list = f;
457 95f65511 Aneesh Kumar K.V
                f->fs_reclaim.dir = f->fs.dir;
458 95f65511 Aneesh Kumar K.V
                f->fs.dir = NULL;
459 95f65511 Aneesh Kumar K.V
                reclaim_count++;
460 95f65511 Aneesh Kumar K.V
            }
461 7a462745 Aneesh Kumar K.V
        }
462 7a462745 Aneesh Kumar K.V
        if (reclaim_count >= open_fd_rc) {
463 7a462745 Aneesh Kumar K.V
            break;
464 7a462745 Aneesh Kumar K.V
        }
465 7a462745 Aneesh Kumar K.V
    }
466 7a462745 Aneesh Kumar K.V
    /*
467 7a462745 Aneesh Kumar K.V
     * Now close the fid in reclaim list. Free them if they
468 7a462745 Aneesh Kumar K.V
     * are already clunked.
469 7a462745 Aneesh Kumar K.V
     */
470 7a462745 Aneesh Kumar K.V
    while (reclaim_list) {
471 7a462745 Aneesh Kumar K.V
        f = reclaim_list;
472 7a462745 Aneesh Kumar K.V
        reclaim_list = f->rclm_lst;
473 7a462745 Aneesh Kumar K.V
        if (f->fid_type == P9_FID_FILE) {
474 7a462745 Aneesh Kumar K.V
            v9fs_co_close(s, f->fs_reclaim.fd);
475 95f65511 Aneesh Kumar K.V
        } else if (f->fid_type == P9_FID_DIR) {
476 95f65511 Aneesh Kumar K.V
            v9fs_co_closedir(s, f->fs_reclaim.dir);
477 7a462745 Aneesh Kumar K.V
        }
478 7a462745 Aneesh Kumar K.V
        f->rclm_lst = NULL;
479 7a462745 Aneesh Kumar K.V
        /*
480 7a462745 Aneesh Kumar K.V
         * Now drop the fid reference, free it
481 7a462745 Aneesh Kumar K.V
         * if clunked.
482 7a462745 Aneesh Kumar K.V
         */
483 7a462745 Aneesh Kumar K.V
        put_fid(s, f);
484 7a462745 Aneesh Kumar K.V
    }
485 7a462745 Aneesh Kumar K.V
}
486 7a462745 Aneesh Kumar K.V
487 7a462745 Aneesh Kumar K.V
static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
488 7a462745 Aneesh Kumar K.V
{
489 7a462745 Aneesh Kumar K.V
    int err;
490 7a462745 Aneesh Kumar K.V
    V9fsFidState *fidp, head_fid;
491 7a462745 Aneesh Kumar K.V
492 7a462745 Aneesh Kumar K.V
    head_fid.next = s->fid_list;
493 7a462745 Aneesh Kumar K.V
    for (fidp = s->fid_list; fidp; fidp = fidp->next) {
494 7a462745 Aneesh Kumar K.V
        if (!strcmp(fidp->path.data, str->data)) {
495 7a462745 Aneesh Kumar K.V
            /* Mark the fid non reclaimable. */
496 7a462745 Aneesh Kumar K.V
            fidp->flags |= FID_NON_RECLAIMABLE;
497 b9cb88b0 Aneesh Kumar K.V
498 b9cb88b0 Aneesh Kumar K.V
            /* reopen the file/dir if already closed */
499 b9cb88b0 Aneesh Kumar K.V
            err = v9fs_reopen_fid(s, fidp);
500 b9cb88b0 Aneesh Kumar K.V
            if (err < 0) {
501 b9cb88b0 Aneesh Kumar K.V
                return -1;
502 b9cb88b0 Aneesh Kumar K.V
            }
503 b9cb88b0 Aneesh Kumar K.V
            /*
504 b9cb88b0 Aneesh Kumar K.V
             * Go back to head of fid list because
505 b9cb88b0 Aneesh Kumar K.V
             * the list could have got updated when
506 b9cb88b0 Aneesh Kumar K.V
             * switched to the worker thread
507 b9cb88b0 Aneesh Kumar K.V
             */
508 b9cb88b0 Aneesh Kumar K.V
            if (err == 0) {
509 7a462745 Aneesh Kumar K.V
                fidp = &head_fid;
510 7a462745 Aneesh Kumar K.V
            }
511 7a462745 Aneesh Kumar K.V
        }
512 7a462745 Aneesh Kumar K.V
    }
513 7a462745 Aneesh Kumar K.V
    return 0;
514 7a462745 Aneesh Kumar K.V
}
515 7a462745 Aneesh Kumar K.V
516 286d5652 Anthony Liguori
#define P9_QID_TYPE_DIR         0x80
517 286d5652 Anthony Liguori
#define P9_QID_TYPE_SYMLINK     0x02
518 286d5652 Anthony Liguori
519 286d5652 Anthony Liguori
#define P9_STAT_MODE_DIR        0x80000000
520 286d5652 Anthony Liguori
#define P9_STAT_MODE_APPEND     0x40000000
521 286d5652 Anthony Liguori
#define P9_STAT_MODE_EXCL       0x20000000
522 286d5652 Anthony Liguori
#define P9_STAT_MODE_MOUNT      0x10000000
523 286d5652 Anthony Liguori
#define P9_STAT_MODE_AUTH       0x08000000
524 286d5652 Anthony Liguori
#define P9_STAT_MODE_TMP        0x04000000
525 286d5652 Anthony Liguori
#define P9_STAT_MODE_SYMLINK    0x02000000
526 286d5652 Anthony Liguori
#define P9_STAT_MODE_LINK       0x01000000
527 286d5652 Anthony Liguori
#define P9_STAT_MODE_DEVICE     0x00800000
528 286d5652 Anthony Liguori
#define P9_STAT_MODE_NAMED_PIPE 0x00200000
529 286d5652 Anthony Liguori
#define P9_STAT_MODE_SOCKET     0x00100000
530 286d5652 Anthony Liguori
#define P9_STAT_MODE_SETUID     0x00080000
531 286d5652 Anthony Liguori
#define P9_STAT_MODE_SETGID     0x00040000
532 286d5652 Anthony Liguori
#define P9_STAT_MODE_SETVTX     0x00010000
533 286d5652 Anthony Liguori
534 286d5652 Anthony Liguori
#define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |          \
535 286d5652 Anthony Liguori
                                P9_STAT_MODE_SYMLINK |      \
536 286d5652 Anthony Liguori
                                P9_STAT_MODE_LINK |         \
537 286d5652 Anthony Liguori
                                P9_STAT_MODE_DEVICE |       \
538 286d5652 Anthony Liguori
                                P9_STAT_MODE_NAMED_PIPE |   \
539 286d5652 Anthony Liguori
                                P9_STAT_MODE_SOCKET)
540 286d5652 Anthony Liguori
541 286d5652 Anthony Liguori
/* This is the algorithm from ufs in spfs */
542 286d5652 Anthony Liguori
static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
543 286d5652 Anthony Liguori
{
544 286d5652 Anthony Liguori
    size_t size;
545 286d5652 Anthony Liguori
546 25427ec1 Aneesh Kumar K.V
    memset(&qidp->path, 0, sizeof(qidp->path));
547 286d5652 Anthony Liguori
    size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path));
548 286d5652 Anthony Liguori
    memcpy(&qidp->path, &stbuf->st_ino, size);
549 286d5652 Anthony Liguori
    qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
550 286d5652 Anthony Liguori
    qidp->type = 0;
551 286d5652 Anthony Liguori
    if (S_ISDIR(stbuf->st_mode)) {
552 286d5652 Anthony Liguori
        qidp->type |= P9_QID_TYPE_DIR;
553 286d5652 Anthony Liguori
    }
554 286d5652 Anthony Liguori
    if (S_ISLNK(stbuf->st_mode)) {
555 286d5652 Anthony Liguori
        qidp->type |= P9_QID_TYPE_SYMLINK;
556 286d5652 Anthony Liguori
    }
557 286d5652 Anthony Liguori
}
558 286d5652 Anthony Liguori
559 286d5652 Anthony Liguori
static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
560 286d5652 Anthony Liguori
{
561 286d5652 Anthony Liguori
    struct stat stbuf;
562 286d5652 Anthony Liguori
    int err;
563 286d5652 Anthony Liguori
564 8c158561 Aneesh Kumar K.V
    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
565 8c158561 Aneesh Kumar K.V
    if (err < 0) {
566 286d5652 Anthony Liguori
        return err;
567 286d5652 Anthony Liguori
    }
568 286d5652 Anthony Liguori
    stat_to_qid(&stbuf, qidp);
569 286d5652 Anthony Liguori
    return 0;
570 286d5652 Anthony Liguori
}
571 286d5652 Anthony Liguori
572 9f107513 Anthony Liguori
static V9fsPDU *alloc_pdu(V9fsState *s)
573 9f107513 Anthony Liguori
{
574 9f107513 Anthony Liguori
    V9fsPDU *pdu = NULL;
575 9f107513 Anthony Liguori
576 9f107513 Anthony Liguori
    if (!QLIST_EMPTY(&s->free_list)) {
577 9f107513 Anthony Liguori
        pdu = QLIST_FIRST(&s->free_list);
578 9f107513 Anthony Liguori
        QLIST_REMOVE(pdu, next);
579 9f107513 Anthony Liguori
    }
580 9f107513 Anthony Liguori
    return pdu;
581 9f107513 Anthony Liguori
}
582 9f107513 Anthony Liguori
583 9f107513 Anthony Liguori
static void free_pdu(V9fsState *s, V9fsPDU *pdu)
584 9f107513 Anthony Liguori
{
585 9f107513 Anthony Liguori
    if (pdu) {
586 39792515 Aneesh Kumar K.V
        if (debug_9p_pdu) {
587 39792515 Aneesh Kumar K.V
            pprint_pdu(pdu);
588 39792515 Aneesh Kumar K.V
        }
589 39792515 Aneesh Kumar K.V
        QLIST_INSERT_HEAD(&s->free_list, pdu, next);
590 9f107513 Anthony Liguori
    }
591 9f107513 Anthony Liguori
}
592 9f107513 Anthony Liguori
593 9f107513 Anthony Liguori
size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
594 9f107513 Anthony Liguori
                        size_t offset, size_t size, int pack)
595 9f107513 Anthony Liguori
{
596 9f107513 Anthony Liguori
    int i = 0;
597 9f107513 Anthony Liguori
    size_t copied = 0;
598 9f107513 Anthony Liguori
599 9f107513 Anthony Liguori
    for (i = 0; size && i < sg_count; i++) {
600 9f107513 Anthony Liguori
        size_t len;
601 9f107513 Anthony Liguori
        if (offset >= sg[i].iov_len) {
602 9f107513 Anthony Liguori
            /* skip this sg */
603 9f107513 Anthony Liguori
            offset -= sg[i].iov_len;
604 9f107513 Anthony Liguori
            continue;
605 9f107513 Anthony Liguori
        } else {
606 9f107513 Anthony Liguori
            len = MIN(sg[i].iov_len - offset, size);
607 9f107513 Anthony Liguori
            if (pack) {
608 9f107513 Anthony Liguori
                memcpy(sg[i].iov_base + offset, addr, len);
609 9f107513 Anthony Liguori
            } else {
610 9f107513 Anthony Liguori
                memcpy(addr, sg[i].iov_base + offset, len);
611 9f107513 Anthony Liguori
            }
612 9f107513 Anthony Liguori
            size -= len;
613 9f107513 Anthony Liguori
            copied += len;
614 9f107513 Anthony Liguori
            addr += len;
615 9f107513 Anthony Liguori
            if (size) {
616 9f107513 Anthony Liguori
                offset = 0;
617 9f107513 Anthony Liguori
                continue;
618 9f107513 Anthony Liguori
            }
619 9f107513 Anthony Liguori
        }
620 9f107513 Anthony Liguori
    }
621 9f107513 Anthony Liguori
622 9f107513 Anthony Liguori
    return copied;
623 9f107513 Anthony Liguori
}
624 9f107513 Anthony Liguori
625 405a549a Anthony Liguori
static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
626 405a549a Anthony Liguori
{
627 405a549a Anthony Liguori
    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
628 405a549a Anthony Liguori
                         offset, size, 0);
629 405a549a Anthony Liguori
}
630 405a549a Anthony Liguori
631 405a549a Anthony Liguori
static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
632 405a549a Anthony Liguori
                        size_t size)
633 405a549a Anthony Liguori
{
634 405a549a Anthony Liguori
    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
635 405a549a Anthony Liguori
                             offset, size, 1);
636 405a549a Anthony Liguori
}
637 405a549a Anthony Liguori
638 405a549a Anthony Liguori
static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
639 405a549a Anthony Liguori
{
640 405a549a Anthony Liguori
    size_t pos = 0;
641 405a549a Anthony Liguori
    int i, j;
642 405a549a Anthony Liguori
    struct iovec *src_sg;
643 405a549a Anthony Liguori
    unsigned int num;
644 405a549a Anthony Liguori
645 405a549a Anthony Liguori
    if (rx) {
646 405a549a Anthony Liguori
        src_sg = pdu->elem.in_sg;
647 405a549a Anthony Liguori
        num = pdu->elem.in_num;
648 405a549a Anthony Liguori
    } else {
649 405a549a Anthony Liguori
        src_sg = pdu->elem.out_sg;
650 405a549a Anthony Liguori
        num = pdu->elem.out_num;
651 405a549a Anthony Liguori
    }
652 405a549a Anthony Liguori
653 405a549a Anthony Liguori
    j = 0;
654 405a549a Anthony Liguori
    for (i = 0; i < num; i++) {
655 405a549a Anthony Liguori
        if (offset <= pos) {
656 405a549a Anthony Liguori
            sg[j].iov_base = src_sg[i].iov_base;
657 405a549a Anthony Liguori
            sg[j].iov_len = src_sg[i].iov_len;
658 405a549a Anthony Liguori
            j++;
659 405a549a Anthony Liguori
        } else if (offset < (src_sg[i].iov_len + pos)) {
660 405a549a Anthony Liguori
            sg[j].iov_base = src_sg[i].iov_base;
661 405a549a Anthony Liguori
            sg[j].iov_len = src_sg[i].iov_len;
662 405a549a Anthony Liguori
            sg[j].iov_base += (offset - pos);
663 405a549a Anthony Liguori
            sg[j].iov_len -= (offset - pos);
664 405a549a Anthony Liguori
            j++;
665 405a549a Anthony Liguori
        }
666 405a549a Anthony Liguori
        pos += src_sg[i].iov_len;
667 405a549a Anthony Liguori
    }
668 405a549a Anthony Liguori
669 405a549a Anthony Liguori
    return j;
670 405a549a Anthony Liguori
}
671 405a549a Anthony Liguori
672 405a549a Anthony Liguori
static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
673 405a549a Anthony Liguori
{
674 405a549a Anthony Liguori
    size_t old_offset = offset;
675 405a549a Anthony Liguori
    va_list ap;
676 405a549a Anthony Liguori
    int i;
677 405a549a Anthony Liguori
678 405a549a Anthony Liguori
    va_start(ap, fmt);
679 405a549a Anthony Liguori
    for (i = 0; fmt[i]; i++) {
680 405a549a Anthony Liguori
        switch (fmt[i]) {
681 405a549a Anthony Liguori
        case 'b': {
682 405a549a Anthony Liguori
            uint8_t *valp = va_arg(ap, uint8_t *);
683 405a549a Anthony Liguori
            offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
684 405a549a Anthony Liguori
            break;
685 405a549a Anthony Liguori
        }
686 405a549a Anthony Liguori
        case 'w': {
687 405a549a Anthony Liguori
            uint16_t val, *valp;
688 405a549a Anthony Liguori
            valp = va_arg(ap, uint16_t *);
689 405a549a Anthony Liguori
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
690 4e37bfc1 Alexey Kardashevskiy
            *valp = le16_to_cpu(val);
691 405a549a Anthony Liguori
            break;
692 405a549a Anthony Liguori
        }
693 405a549a Anthony Liguori
        case 'd': {
694 405a549a Anthony Liguori
            uint32_t val, *valp;
695 405a549a Anthony Liguori
            valp = va_arg(ap, uint32_t *);
696 405a549a Anthony Liguori
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
697 4e37bfc1 Alexey Kardashevskiy
            *valp = le32_to_cpu(val);
698 405a549a Anthony Liguori
            break;
699 405a549a Anthony Liguori
        }
700 405a549a Anthony Liguori
        case 'q': {
701 405a549a Anthony Liguori
            uint64_t val, *valp;
702 405a549a Anthony Liguori
            valp = va_arg(ap, uint64_t *);
703 405a549a Anthony Liguori
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
704 4e37bfc1 Alexey Kardashevskiy
            *valp = le64_to_cpu(val);
705 405a549a Anthony Liguori
            break;
706 405a549a Anthony Liguori
        }
707 405a549a Anthony Liguori
        case 'v': {
708 405a549a Anthony Liguori
            struct iovec *iov = va_arg(ap, struct iovec *);
709 405a549a Anthony Liguori
            int *iovcnt = va_arg(ap, int *);
710 405a549a Anthony Liguori
            *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
711 405a549a Anthony Liguori
            break;
712 405a549a Anthony Liguori
        }
713 405a549a Anthony Liguori
        case 's': {
714 405a549a Anthony Liguori
            V9fsString *str = va_arg(ap, V9fsString *);
715 405a549a Anthony Liguori
            offset += pdu_unmarshal(pdu, offset, "w", &str->size);
716 405a549a Anthony Liguori
            /* FIXME: sanity check str->size */
717 7267c094 Anthony Liguori
            str->data = g_malloc(str->size + 1);
718 405a549a Anthony Liguori
            offset += pdu_unpack(str->data, pdu, offset, str->size);
719 405a549a Anthony Liguori
            str->data[str->size] = 0;
720 405a549a Anthony Liguori
            break;
721 405a549a Anthony Liguori
        }
722 405a549a Anthony Liguori
        case 'Q': {
723 405a549a Anthony Liguori
            V9fsQID *qidp = va_arg(ap, V9fsQID *);
724 405a549a Anthony Liguori
            offset += pdu_unmarshal(pdu, offset, "bdq",
725 405a549a Anthony Liguori
                        &qidp->type, &qidp->version, &qidp->path);
726 405a549a Anthony Liguori
            break;
727 405a549a Anthony Liguori
        }
728 405a549a Anthony Liguori
        case 'S': {
729 405a549a Anthony Liguori
            V9fsStat *statp = va_arg(ap, V9fsStat *);
730 405a549a Anthony Liguori
            offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
731 405a549a Anthony Liguori
                        &statp->size, &statp->type, &statp->dev,
732 405a549a Anthony Liguori
                        &statp->qid, &statp->mode, &statp->atime,
733 405a549a Anthony Liguori
                        &statp->mtime, &statp->length,
734 405a549a Anthony Liguori
                        &statp->name, &statp->uid, &statp->gid,
735 405a549a Anthony Liguori
                        &statp->muid, &statp->extension,
736 405a549a Anthony Liguori
                        &statp->n_uid, &statp->n_gid,
737 405a549a Anthony Liguori
                        &statp->n_muid);
738 405a549a Anthony Liguori
            break;
739 405a549a Anthony Liguori
        }
740 c79ce737 Sripathi Kodi
        case 'I': {
741 c79ce737 Sripathi Kodi
            V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
742 c79ce737 Sripathi Kodi
            offset += pdu_unmarshal(pdu, offset, "ddddqqqqq",
743 c79ce737 Sripathi Kodi
                        &iattr->valid, &iattr->mode,
744 c79ce737 Sripathi Kodi
                        &iattr->uid, &iattr->gid, &iattr->size,
745 c79ce737 Sripathi Kodi
                        &iattr->atime_sec, &iattr->atime_nsec,
746 c79ce737 Sripathi Kodi
                        &iattr->mtime_sec, &iattr->mtime_nsec);
747 c79ce737 Sripathi Kodi
            break;
748 c79ce737 Sripathi Kodi
        }
749 405a549a Anthony Liguori
        default:
750 405a549a Anthony Liguori
            break;
751 405a549a Anthony Liguori
        }
752 405a549a Anthony Liguori
    }
753 405a549a Anthony Liguori
754 405a549a Anthony Liguori
    va_end(ap);
755 405a549a Anthony Liguori
756 405a549a Anthony Liguori
    return offset - old_offset;
757 405a549a Anthony Liguori
}
758 405a549a Anthony Liguori
759 405a549a Anthony Liguori
static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
760 405a549a Anthony Liguori
{
761 405a549a Anthony Liguori
    size_t old_offset = offset;
762 405a549a Anthony Liguori
    va_list ap;
763 405a549a Anthony Liguori
    int i;
764 405a549a Anthony Liguori
765 405a549a Anthony Liguori
    va_start(ap, fmt);
766 405a549a Anthony Liguori
    for (i = 0; fmt[i]; i++) {
767 405a549a Anthony Liguori
        switch (fmt[i]) {
768 405a549a Anthony Liguori
        case 'b': {
769 405a549a Anthony Liguori
            uint8_t val = va_arg(ap, int);
770 405a549a Anthony Liguori
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
771 405a549a Anthony Liguori
            break;
772 405a549a Anthony Liguori
        }
773 405a549a Anthony Liguori
        case 'w': {
774 405a549a Anthony Liguori
            uint16_t val;
775 405a549a Anthony Liguori
            cpu_to_le16w(&val, va_arg(ap, int));
776 405a549a Anthony Liguori
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
777 405a549a Anthony Liguori
            break;
778 405a549a Anthony Liguori
        }
779 405a549a Anthony Liguori
        case 'd': {
780 405a549a Anthony Liguori
            uint32_t val;
781 405a549a Anthony Liguori
            cpu_to_le32w(&val, va_arg(ap, uint32_t));
782 405a549a Anthony Liguori
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
783 405a549a Anthony Liguori
            break;
784 405a549a Anthony Liguori
        }
785 405a549a Anthony Liguori
        case 'q': {
786 405a549a Anthony Liguori
            uint64_t val;
787 405a549a Anthony Liguori
            cpu_to_le64w(&val, va_arg(ap, uint64_t));
788 405a549a Anthony Liguori
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
789 405a549a Anthony Liguori
            break;
790 405a549a Anthony Liguori
        }
791 405a549a Anthony Liguori
        case 'v': {
792 405a549a Anthony Liguori
            struct iovec *iov = va_arg(ap, struct iovec *);
793 405a549a Anthony Liguori
            int *iovcnt = va_arg(ap, int *);
794 405a549a Anthony Liguori
            *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
795 405a549a Anthony Liguori
            break;
796 405a549a Anthony Liguori
        }
797 405a549a Anthony Liguori
        case 's': {
798 405a549a Anthony Liguori
            V9fsString *str = va_arg(ap, V9fsString *);
799 405a549a Anthony Liguori
            offset += pdu_marshal(pdu, offset, "w", str->size);
800 405a549a Anthony Liguori
            offset += pdu_pack(pdu, offset, str->data, str->size);
801 405a549a Anthony Liguori
            break;
802 405a549a Anthony Liguori
        }
803 405a549a Anthony Liguori
        case 'Q': {
804 405a549a Anthony Liguori
            V9fsQID *qidp = va_arg(ap, V9fsQID *);
805 405a549a Anthony Liguori
            offset += pdu_marshal(pdu, offset, "bdq",
806 405a549a Anthony Liguori
                        qidp->type, qidp->version, qidp->path);
807 405a549a Anthony Liguori
            break;
808 405a549a Anthony Liguori
        }
809 405a549a Anthony Liguori
        case 'S': {
810 405a549a Anthony Liguori
            V9fsStat *statp = va_arg(ap, V9fsStat *);
811 405a549a Anthony Liguori
            offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
812 405a549a Anthony Liguori
                        statp->size, statp->type, statp->dev,
813 405a549a Anthony Liguori
                        &statp->qid, statp->mode, statp->atime,
814 405a549a Anthony Liguori
                        statp->mtime, statp->length, &statp->name,
815 405a549a Anthony Liguori
                        &statp->uid, &statp->gid, &statp->muid,
816 405a549a Anthony Liguori
                        &statp->extension, statp->n_uid,
817 405a549a Anthony Liguori
                        statp->n_gid, statp->n_muid);
818 405a549a Anthony Liguori
            break;
819 405a549a Anthony Liguori
        }
820 00ede4c2 Sripathi Kodi
        case 'A': {
821 00ede4c2 Sripathi Kodi
            V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
822 00ede4c2 Sripathi Kodi
            offset += pdu_marshal(pdu, offset, "qQdddqqqqqqqqqqqqqqq",
823 00ede4c2 Sripathi Kodi
                        statp->st_result_mask,
824 00ede4c2 Sripathi Kodi
                        &statp->qid, statp->st_mode,
825 00ede4c2 Sripathi Kodi
                        statp->st_uid, statp->st_gid,
826 00ede4c2 Sripathi Kodi
                        statp->st_nlink, statp->st_rdev,
827 00ede4c2 Sripathi Kodi
                        statp->st_size, statp->st_blksize, statp->st_blocks,
828 00ede4c2 Sripathi Kodi
                        statp->st_atime_sec, statp->st_atime_nsec,
829 00ede4c2 Sripathi Kodi
                        statp->st_mtime_sec, statp->st_mtime_nsec,
830 00ede4c2 Sripathi Kodi
                        statp->st_ctime_sec, statp->st_ctime_nsec,
831 00ede4c2 Sripathi Kodi
                        statp->st_btime_sec, statp->st_btime_nsec,
832 00ede4c2 Sripathi Kodi
                        statp->st_gen, statp->st_data_version);
833 00ede4c2 Sripathi Kodi
            break;
834 00ede4c2 Sripathi Kodi
        }
835 405a549a Anthony Liguori
        default:
836 405a549a Anthony Liguori
            break;
837 405a549a Anthony Liguori
        }
838 405a549a Anthony Liguori
    }
839 405a549a Anthony Liguori
    va_end(ap);
840 405a549a Anthony Liguori
841 405a549a Anthony Liguori
    return offset - old_offset;
842 405a549a Anthony Liguori
}
843 405a549a Anthony Liguori
844 405a549a Anthony Liguori
static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
845 405a549a Anthony Liguori
{
846 405a549a Anthony Liguori
    int8_t id = pdu->id + 1; /* Response */
847 405a549a Anthony Liguori
848 405a549a Anthony Liguori
    if (len < 0) {
849 405a549a Anthony Liguori
        int err = -len;
850 8f4d1ca5 Arun R Bharadwaj
        len = 7;
851 405a549a Anthony Liguori
852 8f4d1ca5 Arun R Bharadwaj
        if (s->proto_version != V9FS_PROTO_2000L) {
853 8f4d1ca5 Arun R Bharadwaj
            V9fsString str;
854 8f4d1ca5 Arun R Bharadwaj
855 8f4d1ca5 Arun R Bharadwaj
            str.data = strerror(err);
856 8f4d1ca5 Arun R Bharadwaj
            str.size = strlen(str.data);
857 8f4d1ca5 Arun R Bharadwaj
858 8f4d1ca5 Arun R Bharadwaj
            len += pdu_marshal(pdu, len, "s", &str);
859 8f4d1ca5 Arun R Bharadwaj
            id = P9_RERROR;
860 8f4d1ca5 Arun R Bharadwaj
        }
861 405a549a Anthony Liguori
862 cf03eb2c Arun R Bharadwaj
        len += pdu_marshal(pdu, len, "d", err);
863 405a549a Anthony Liguori
864 8f4d1ca5 Arun R Bharadwaj
        if (s->proto_version == V9FS_PROTO_2000L) {
865 8f4d1ca5 Arun R Bharadwaj
            id = P9_RLERROR;
866 8f4d1ca5 Arun R Bharadwaj
        }
867 405a549a Anthony Liguori
    }
868 405a549a Anthony Liguori
869 405a549a Anthony Liguori
    /* fill out the header */
870 405a549a Anthony Liguori
    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
871 405a549a Anthony Liguori
872 405a549a Anthony Liguori
    /* keep these in sync */
873 405a549a Anthony Liguori
    pdu->size = len;
874 405a549a Anthony Liguori
    pdu->id = id;
875 405a549a Anthony Liguori
876 405a549a Anthony Liguori
    /* push onto queue and notify */
877 405a549a Anthony Liguori
    virtqueue_push(s->vq, &pdu->elem, len);
878 405a549a Anthony Liguori
879 405a549a Anthony Liguori
    /* FIXME: we should batch these completions */
880 405a549a Anthony Liguori
    virtio_notify(&s->vdev, s->vq);
881 405a549a Anthony Liguori
882 405a549a Anthony Liguori
    free_pdu(s, pdu);
883 405a549a Anthony Liguori
}
884 405a549a Anthony Liguori
885 bb9e3216 Anthony Liguori
static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
886 bb9e3216 Anthony Liguori
{
887 bb9e3216 Anthony Liguori
    mode_t ret;
888 bb9e3216 Anthony Liguori
889 bb9e3216 Anthony Liguori
    ret = mode & 0777;
890 bb9e3216 Anthony Liguori
    if (mode & P9_STAT_MODE_DIR) {
891 bb9e3216 Anthony Liguori
        ret |= S_IFDIR;
892 bb9e3216 Anthony Liguori
    }
893 bb9e3216 Anthony Liguori
894 cf03eb2c Arun R Bharadwaj
    if (mode & P9_STAT_MODE_SYMLINK) {
895 cf03eb2c Arun R Bharadwaj
        ret |= S_IFLNK;
896 cf03eb2c Arun R Bharadwaj
    }
897 cf03eb2c Arun R Bharadwaj
    if (mode & P9_STAT_MODE_SOCKET) {
898 cf03eb2c Arun R Bharadwaj
        ret |= S_IFSOCK;
899 cf03eb2c Arun R Bharadwaj
    }
900 cf03eb2c Arun R Bharadwaj
    if (mode & P9_STAT_MODE_NAMED_PIPE) {
901 cf03eb2c Arun R Bharadwaj
        ret |= S_IFIFO;
902 cf03eb2c Arun R Bharadwaj
    }
903 cf03eb2c Arun R Bharadwaj
    if (mode & P9_STAT_MODE_DEVICE) {
904 cf03eb2c Arun R Bharadwaj
        if (extension && extension->data[0] == 'c') {
905 cf03eb2c Arun R Bharadwaj
            ret |= S_IFCHR;
906 cf03eb2c Arun R Bharadwaj
        } else {
907 cf03eb2c Arun R Bharadwaj
            ret |= S_IFBLK;
908 bb9e3216 Anthony Liguori
        }
909 bb9e3216 Anthony Liguori
    }
910 bb9e3216 Anthony Liguori
911 bb9e3216 Anthony Liguori
    if (!(ret&~0777)) {
912 bb9e3216 Anthony Liguori
        ret |= S_IFREG;
913 bb9e3216 Anthony Liguori
    }
914 bb9e3216 Anthony Liguori
915 bb9e3216 Anthony Liguori
    if (mode & P9_STAT_MODE_SETUID) {
916 bb9e3216 Anthony Liguori
        ret |= S_ISUID;
917 bb9e3216 Anthony Liguori
    }
918 bb9e3216 Anthony Liguori
    if (mode & P9_STAT_MODE_SETGID) {
919 bb9e3216 Anthony Liguori
        ret |= S_ISGID;
920 bb9e3216 Anthony Liguori
    }
921 bb9e3216 Anthony Liguori
    if (mode & P9_STAT_MODE_SETVTX) {
922 bb9e3216 Anthony Liguori
        ret |= S_ISVTX;
923 bb9e3216 Anthony Liguori
    }
924 bb9e3216 Anthony Liguori
925 bb9e3216 Anthony Liguori
    return ret;
926 bb9e3216 Anthony Liguori
}
927 bb9e3216 Anthony Liguori
928 bb9e3216 Anthony Liguori
static int donttouch_stat(V9fsStat *stat)
929 bb9e3216 Anthony Liguori
{
930 bb9e3216 Anthony Liguori
    if (stat->type == -1 &&
931 bb9e3216 Anthony Liguori
        stat->dev == -1 &&
932 bb9e3216 Anthony Liguori
        stat->qid.type == -1 &&
933 bb9e3216 Anthony Liguori
        stat->qid.version == -1 &&
934 bb9e3216 Anthony Liguori
        stat->qid.path == -1 &&
935 bb9e3216 Anthony Liguori
        stat->mode == -1 &&
936 bb9e3216 Anthony Liguori
        stat->atime == -1 &&
937 bb9e3216 Anthony Liguori
        stat->mtime == -1 &&
938 bb9e3216 Anthony Liguori
        stat->length == -1 &&
939 bb9e3216 Anthony Liguori
        !stat->name.size &&
940 bb9e3216 Anthony Liguori
        !stat->uid.size &&
941 bb9e3216 Anthony Liguori
        !stat->gid.size &&
942 bb9e3216 Anthony Liguori
        !stat->muid.size &&
943 bb9e3216 Anthony Liguori
        stat->n_uid == -1 &&
944 bb9e3216 Anthony Liguori
        stat->n_gid == -1 &&
945 bb9e3216 Anthony Liguori
        stat->n_muid == -1) {
946 bb9e3216 Anthony Liguori
        return 1;
947 bb9e3216 Anthony Liguori
    }
948 bb9e3216 Anthony Liguori
949 bb9e3216 Anthony Liguori
    return 0;
950 bb9e3216 Anthony Liguori
}
951 bb9e3216 Anthony Liguori
952 bb9e3216 Anthony Liguori
static void v9fs_stat_free(V9fsStat *stat)
953 bb9e3216 Anthony Liguori
{
954 bb9e3216 Anthony Liguori
    v9fs_string_free(&stat->name);
955 bb9e3216 Anthony Liguori
    v9fs_string_free(&stat->uid);
956 bb9e3216 Anthony Liguori
    v9fs_string_free(&stat->gid);
957 bb9e3216 Anthony Liguori
    v9fs_string_free(&stat->muid);
958 bb9e3216 Anthony Liguori
    v9fs_string_free(&stat->extension);
959 bb9e3216 Anthony Liguori
}
960 bb9e3216 Anthony Liguori
961 bb9e3216 Anthony Liguori
static uint32_t stat_to_v9mode(const struct stat *stbuf)
962 bb9e3216 Anthony Liguori
{
963 bb9e3216 Anthony Liguori
    uint32_t mode;
964 bb9e3216 Anthony Liguori
965 bb9e3216 Anthony Liguori
    mode = stbuf->st_mode & 0777;
966 bb9e3216 Anthony Liguori
    if (S_ISDIR(stbuf->st_mode)) {
967 bb9e3216 Anthony Liguori
        mode |= P9_STAT_MODE_DIR;
968 bb9e3216 Anthony Liguori
    }
969 bb9e3216 Anthony Liguori
970 cf03eb2c Arun R Bharadwaj
    if (S_ISLNK(stbuf->st_mode)) {
971 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_SYMLINK;
972 cf03eb2c Arun R Bharadwaj
    }
973 bb9e3216 Anthony Liguori
974 cf03eb2c Arun R Bharadwaj
    if (S_ISSOCK(stbuf->st_mode)) {
975 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_SOCKET;
976 cf03eb2c Arun R Bharadwaj
    }
977 bb9e3216 Anthony Liguori
978 cf03eb2c Arun R Bharadwaj
    if (S_ISFIFO(stbuf->st_mode)) {
979 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_NAMED_PIPE;
980 cf03eb2c Arun R Bharadwaj
    }
981 bb9e3216 Anthony Liguori
982 cf03eb2c Arun R Bharadwaj
    if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode)) {
983 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_DEVICE;
984 cf03eb2c Arun R Bharadwaj
    }
985 bb9e3216 Anthony Liguori
986 cf03eb2c Arun R Bharadwaj
    if (stbuf->st_mode & S_ISUID) {
987 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_SETUID;
988 cf03eb2c Arun R Bharadwaj
    }
989 bb9e3216 Anthony Liguori
990 cf03eb2c Arun R Bharadwaj
    if (stbuf->st_mode & S_ISGID) {
991 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_SETGID;
992 cf03eb2c Arun R Bharadwaj
    }
993 bb9e3216 Anthony Liguori
994 cf03eb2c Arun R Bharadwaj
    if (stbuf->st_mode & S_ISVTX) {
995 cf03eb2c Arun R Bharadwaj
        mode |= P9_STAT_MODE_SETVTX;
996 bb9e3216 Anthony Liguori
    }
997 bb9e3216 Anthony Liguori
998 bb9e3216 Anthony Liguori
    return mode;
999 bb9e3216 Anthony Liguori
}
1000 bb9e3216 Anthony Liguori
1001 bb9e3216 Anthony Liguori
static int stat_to_v9stat(V9fsState *s, V9fsString *name,
1002 bb9e3216 Anthony Liguori
                            const struct stat *stbuf,
1003 bb9e3216 Anthony Liguori
                            V9fsStat *v9stat)
1004 bb9e3216 Anthony Liguori
{
1005 bb9e3216 Anthony Liguori
    int err;
1006 bb9e3216 Anthony Liguori
    const char *str;
1007 bb9e3216 Anthony Liguori
1008 bb9e3216 Anthony Liguori
    memset(v9stat, 0, sizeof(*v9stat));
1009 bb9e3216 Anthony Liguori
1010 bb9e3216 Anthony Liguori
    stat_to_qid(stbuf, &v9stat->qid);
1011 bb9e3216 Anthony Liguori
    v9stat->mode = stat_to_v9mode(stbuf);
1012 bb9e3216 Anthony Liguori
    v9stat->atime = stbuf->st_atime;
1013 bb9e3216 Anthony Liguori
    v9stat->mtime = stbuf->st_mtime;
1014 bb9e3216 Anthony Liguori
    v9stat->length = stbuf->st_size;
1015 bb9e3216 Anthony Liguori
1016 bb9e3216 Anthony Liguori
    v9fs_string_null(&v9stat->uid);
1017 bb9e3216 Anthony Liguori
    v9fs_string_null(&v9stat->gid);
1018 bb9e3216 Anthony Liguori
    v9fs_string_null(&v9stat->muid);
1019 bb9e3216 Anthony Liguori
1020 cf03eb2c Arun R Bharadwaj
    v9stat->n_uid = stbuf->st_uid;
1021 cf03eb2c Arun R Bharadwaj
    v9stat->n_gid = stbuf->st_gid;
1022 cf03eb2c Arun R Bharadwaj
    v9stat->n_muid = 0;
1023 bb9e3216 Anthony Liguori
1024 cf03eb2c Arun R Bharadwaj
    v9fs_string_null(&v9stat->extension);
1025 bb9e3216 Anthony Liguori
1026 cf03eb2c Arun R Bharadwaj
    if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
1027 7a5ca31e Venkateswararao Jujjuri
        err = v9fs_co_readlink(s, name, &v9stat->extension);
1028 7a5ca31e Venkateswararao Jujjuri
        if (err < 0) {
1029 cf03eb2c Arun R Bharadwaj
            return err;
1030 bb9e3216 Anthony Liguori
        }
1031 cf03eb2c Arun R Bharadwaj
    } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
1032 cf03eb2c Arun R Bharadwaj
        v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
1033 cf03eb2c Arun R Bharadwaj
                S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
1034 cf03eb2c Arun R Bharadwaj
                major(stbuf->st_rdev), minor(stbuf->st_rdev));
1035 cf03eb2c Arun R Bharadwaj
    } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
1036 c9ba47dc Stefan Weil
        v9fs_string_sprintf(&v9stat->extension, "%s %lu",
1037 c9ba47dc Stefan Weil
                "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
1038 bb9e3216 Anthony Liguori
    }
1039 bb9e3216 Anthony Liguori
1040 bb9e3216 Anthony Liguori
    str = strrchr(name->data, '/');
1041 bb9e3216 Anthony Liguori
    if (str) {
1042 bb9e3216 Anthony Liguori
        str += 1;
1043 bb9e3216 Anthony Liguori
    } else {
1044 bb9e3216 Anthony Liguori
        str = name->data;
1045 bb9e3216 Anthony Liguori
    }
1046 bb9e3216 Anthony Liguori
1047 bb9e3216 Anthony Liguori
    v9fs_string_sprintf(&v9stat->name, "%s", str);
1048 bb9e3216 Anthony Liguori
1049 bb9e3216 Anthony Liguori
    v9stat->size = 61 +
1050 bb9e3216 Anthony Liguori
        v9fs_string_size(&v9stat->name) +
1051 bb9e3216 Anthony Liguori
        v9fs_string_size(&v9stat->uid) +
1052 bb9e3216 Anthony Liguori
        v9fs_string_size(&v9stat->gid) +
1053 bb9e3216 Anthony Liguori
        v9fs_string_size(&v9stat->muid) +
1054 bb9e3216 Anthony Liguori
        v9fs_string_size(&v9stat->extension);
1055 bb9e3216 Anthony Liguori
    return 0;
1056 bb9e3216 Anthony Liguori
}
1057 bb9e3216 Anthony Liguori
1058 00ede4c2 Sripathi Kodi
#define P9_STATS_MODE          0x00000001ULL
1059 00ede4c2 Sripathi Kodi
#define P9_STATS_NLINK         0x00000002ULL
1060 00ede4c2 Sripathi Kodi
#define P9_STATS_UID           0x00000004ULL
1061 00ede4c2 Sripathi Kodi
#define P9_STATS_GID           0x00000008ULL
1062 00ede4c2 Sripathi Kodi
#define P9_STATS_RDEV          0x00000010ULL
1063 00ede4c2 Sripathi Kodi
#define P9_STATS_ATIME         0x00000020ULL
1064 00ede4c2 Sripathi Kodi
#define P9_STATS_MTIME         0x00000040ULL
1065 00ede4c2 Sripathi Kodi
#define P9_STATS_CTIME         0x00000080ULL
1066 00ede4c2 Sripathi Kodi
#define P9_STATS_INO           0x00000100ULL
1067 00ede4c2 Sripathi Kodi
#define P9_STATS_SIZE          0x00000200ULL
1068 00ede4c2 Sripathi Kodi
#define P9_STATS_BLOCKS        0x00000400ULL
1069 00ede4c2 Sripathi Kodi
1070 00ede4c2 Sripathi Kodi
#define P9_STATS_BTIME         0x00000800ULL
1071 00ede4c2 Sripathi Kodi
#define P9_STATS_GEN           0x00001000ULL
1072 00ede4c2 Sripathi Kodi
#define P9_STATS_DATA_VERSION  0x00002000ULL
1073 00ede4c2 Sripathi Kodi
1074 00ede4c2 Sripathi Kodi
#define P9_STATS_BASIC         0x000007ffULL /* Mask for fields up to BLOCKS */
1075 00ede4c2 Sripathi Kodi
#define P9_STATS_ALL           0x00003fffULL /* Mask for All fields above */
1076 00ede4c2 Sripathi Kodi
1077 00ede4c2 Sripathi Kodi
1078 00ede4c2 Sripathi Kodi
static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
1079 8db21ce7 Aneesh Kumar K.V
                                V9fsStatDotl *v9lstat)
1080 00ede4c2 Sripathi Kodi
{
1081 00ede4c2 Sripathi Kodi
    memset(v9lstat, 0, sizeof(*v9lstat));
1082 00ede4c2 Sripathi Kodi
1083 00ede4c2 Sripathi Kodi
    v9lstat->st_mode = stbuf->st_mode;
1084 00ede4c2 Sripathi Kodi
    v9lstat->st_nlink = stbuf->st_nlink;
1085 00ede4c2 Sripathi Kodi
    v9lstat->st_uid = stbuf->st_uid;
1086 00ede4c2 Sripathi Kodi
    v9lstat->st_gid = stbuf->st_gid;
1087 00ede4c2 Sripathi Kodi
    v9lstat->st_rdev = stbuf->st_rdev;
1088 00ede4c2 Sripathi Kodi
    v9lstat->st_size = stbuf->st_size;
1089 00ede4c2 Sripathi Kodi
    v9lstat->st_blksize = stbuf->st_blksize;
1090 00ede4c2 Sripathi Kodi
    v9lstat->st_blocks = stbuf->st_blocks;
1091 00ede4c2 Sripathi Kodi
    v9lstat->st_atime_sec = stbuf->st_atime;
1092 00ede4c2 Sripathi Kodi
    v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
1093 00ede4c2 Sripathi Kodi
    v9lstat->st_mtime_sec = stbuf->st_mtime;
1094 00ede4c2 Sripathi Kodi
    v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
1095 00ede4c2 Sripathi Kodi
    v9lstat->st_ctime_sec = stbuf->st_ctime;
1096 00ede4c2 Sripathi Kodi
    v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
1097 00ede4c2 Sripathi Kodi
    /* Currently we only support BASIC fields in stat */
1098 00ede4c2 Sripathi Kodi
    v9lstat->st_result_mask = P9_STATS_BASIC;
1099 00ede4c2 Sripathi Kodi
1100 00ede4c2 Sripathi Kodi
    stat_to_qid(stbuf, &v9lstat->qid);
1101 00ede4c2 Sripathi Kodi
}
1102 00ede4c2 Sripathi Kodi
1103 1f5a89bf Anthony Liguori
static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt)
1104 1f5a89bf Anthony Liguori
{
1105 1f5a89bf Anthony Liguori
    while (len && *iovcnt) {
1106 1f5a89bf Anthony Liguori
        if (len < sg->iov_len) {
1107 1f5a89bf Anthony Liguori
            sg->iov_len -= len;
1108 1f5a89bf Anthony Liguori
            sg->iov_base += len;
1109 1f5a89bf Anthony Liguori
            len = 0;
1110 1f5a89bf Anthony Liguori
        } else {
1111 1f5a89bf Anthony Liguori
            len -= sg->iov_len;
1112 1f5a89bf Anthony Liguori
            sg++;
1113 1f5a89bf Anthony Liguori
            *iovcnt -= 1;
1114 1f5a89bf Anthony Liguori
        }
1115 1f5a89bf Anthony Liguori
    }
1116 1f5a89bf Anthony Liguori
1117 1f5a89bf Anthony Liguori
    return sg;
1118 1f5a89bf Anthony Liguori
}
1119 1f5a89bf Anthony Liguori
1120 1f5a89bf Anthony Liguori
static struct iovec *cap_sg(struct iovec *sg, int cap, int *cnt)
1121 1f5a89bf Anthony Liguori
{
1122 1f5a89bf Anthony Liguori
    int i;
1123 1f5a89bf Anthony Liguori
    int total = 0;
1124 1f5a89bf Anthony Liguori
1125 1f5a89bf Anthony Liguori
    for (i = 0; i < *cnt; i++) {
1126 1f5a89bf Anthony Liguori
        if ((total + sg[i].iov_len) > cap) {
1127 1f5a89bf Anthony Liguori
            sg[i].iov_len -= ((total + sg[i].iov_len) - cap);
1128 1f5a89bf Anthony Liguori
            i++;
1129 1f5a89bf Anthony Liguori
            break;
1130 1f5a89bf Anthony Liguori
        }
1131 1f5a89bf Anthony Liguori
        total += sg[i].iov_len;
1132 1f5a89bf Anthony Liguori
    }
1133 1f5a89bf Anthony Liguori
1134 1f5a89bf Anthony Liguori
    *cnt = i;
1135 1f5a89bf Anthony Liguori
1136 1f5a89bf Anthony Liguori
    return sg;
1137 1f5a89bf Anthony Liguori
}
1138 1f5a89bf Anthony Liguori
1139 1f5a89bf Anthony Liguori
static void print_sg(struct iovec *sg, int cnt)
1140 1f5a89bf Anthony Liguori
{
1141 1f5a89bf Anthony Liguori
    int i;
1142 1f5a89bf Anthony Liguori
1143 1f5a89bf Anthony Liguori
    printf("sg[%d]: {", cnt);
1144 1f5a89bf Anthony Liguori
    for (i = 0; i < cnt; i++) {
1145 1f5a89bf Anthony Liguori
        if (i) {
1146 1f5a89bf Anthony Liguori
            printf(", ");
1147 1f5a89bf Anthony Liguori
        }
1148 1f5a89bf Anthony Liguori
        printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len);
1149 1f5a89bf Anthony Liguori
    }
1150 1f5a89bf Anthony Liguori
    printf("}\n");
1151 1f5a89bf Anthony Liguori
}
1152 1f5a89bf Anthony Liguori
1153 8cf89e00 Anthony Liguori
static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
1154 8cf89e00 Anthony Liguori
{
1155 8cf89e00 Anthony Liguori
    V9fsString str;
1156 8cf89e00 Anthony Liguori
    v9fs_string_init(&str);
1157 8cf89e00 Anthony Liguori
    v9fs_string_copy(&str, dst);
1158 8cf89e00 Anthony Liguori
    v9fs_string_sprintf(dst, "%s%s", src->data, str.data+len);
1159 8cf89e00 Anthony Liguori
    v9fs_string_free(&str);
1160 8cf89e00 Anthony Liguori
}
1161 8cf89e00 Anthony Liguori
1162 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_version(void *opaque)
1163 9f107513 Anthony Liguori
{
1164 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
1165 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
1166 92c1ad03 Anthony Liguori
    V9fsString version;
1167 92c1ad03 Anthony Liguori
    size_t offset = 7;
1168 92c1ad03 Anthony Liguori
1169 5e94c103 M. Mohan Kumar
    pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
1170 92c1ad03 Anthony Liguori
1171 84151514 M. Mohan Kumar
    if (!strcmp(version.data, "9P2000.u")) {
1172 84151514 M. Mohan Kumar
        s->proto_version = V9FS_PROTO_2000U;
1173 84151514 M. Mohan Kumar
    } else if (!strcmp(version.data, "9P2000.L")) {
1174 84151514 M. Mohan Kumar
        s->proto_version = V9FS_PROTO_2000L;
1175 84151514 M. Mohan Kumar
    } else {
1176 92c1ad03 Anthony Liguori
        v9fs_string_sprintf(&version, "unknown");
1177 9f107513 Anthony Liguori
    }
1178 92c1ad03 Anthony Liguori
1179 5e94c103 M. Mohan Kumar
    offset += pdu_marshal(pdu, offset, "ds", s->msize, &version);
1180 92c1ad03 Anthony Liguori
    complete_pdu(s, pdu, offset);
1181 92c1ad03 Anthony Liguori
1182 92c1ad03 Anthony Liguori
    v9fs_string_free(&version);
1183 ff06030f Venkateswararao Jujjuri (JV)
    return;
1184 9f107513 Anthony Liguori
}
1185 9f107513 Anthony Liguori
1186 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_attach(void *opaque)
1187 9f107513 Anthony Liguori
{
1188 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
1189 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
1190 955efc47 Anthony Liguori
    int32_t fid, afid, n_uname;
1191 955efc47 Anthony Liguori
    V9fsString uname, aname;
1192 955efc47 Anthony Liguori
    V9fsFidState *fidp;
1193 955efc47 Anthony Liguori
    size_t offset = 7;
1194 8c158561 Aneesh Kumar K.V
    V9fsQID qid;
1195 955efc47 Anthony Liguori
    ssize_t err;
1196 955efc47 Anthony Liguori
1197 955efc47 Anthony Liguori
    pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
1198 955efc47 Anthony Liguori
1199 955efc47 Anthony Liguori
    fidp = alloc_fid(s, fid);
1200 955efc47 Anthony Liguori
    if (fidp == NULL) {
1201 955efc47 Anthony Liguori
        err = -EINVAL;
1202 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1203 9f107513 Anthony Liguori
    }
1204 955efc47 Anthony Liguori
    fidp->uid = n_uname;
1205 955efc47 Anthony Liguori
    v9fs_string_sprintf(&fidp->path, "%s", "/");
1206 955efc47 Anthony Liguori
    err = fid_to_qid(s, fidp, &qid);
1207 8c158561 Aneesh Kumar K.V
    if (err < 0) {
1208 955efc47 Anthony Liguori
        err = -EINVAL;
1209 84dfb926 Aneesh Kumar K.V
        clunk_fid(s, fid);
1210 955efc47 Anthony Liguori
        goto out;
1211 955efc47 Anthony Liguori
    }
1212 955efc47 Anthony Liguori
    offset += pdu_marshal(pdu, offset, "Q", &qid);
1213 955efc47 Anthony Liguori
    err = offset;
1214 955efc47 Anthony Liguori
out:
1215 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1216 84dfb926 Aneesh Kumar K.V
out_nofid:
1217 955efc47 Anthony Liguori
    complete_pdu(s, pdu, err);
1218 955efc47 Anthony Liguori
    v9fs_string_free(&uname);
1219 955efc47 Anthony Liguori
    v9fs_string_free(&aname);
1220 9f107513 Anthony Liguori
}
1221 9f107513 Anthony Liguori
1222 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_stat(void *opaque)
1223 9f107513 Anthony Liguori
{
1224 4da7d3fa Anthony Liguori
    int32_t fid;
1225 d8e0c29e Aneesh Kumar K.V
    V9fsStat v9stat;
1226 4da7d3fa Anthony Liguori
    ssize_t err = 0;
1227 d8e0c29e Aneesh Kumar K.V
    size_t offset = 7;
1228 d8e0c29e Aneesh Kumar K.V
    struct stat stbuf;
1229 d8e0c29e Aneesh Kumar K.V
    V9fsFidState *fidp;
1230 d8e0c29e Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1231 d8e0c29e Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1232 4da7d3fa Anthony Liguori
1233 d8e0c29e Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "d", &fid);
1234 84dfb926 Aneesh Kumar K.V
1235 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1236 d8e0c29e Aneesh Kumar K.V
    if (fidp == NULL) {
1237 4da7d3fa Anthony Liguori
        err = -ENOENT;
1238 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1239 9f107513 Anthony Liguori
    }
1240 d8e0c29e Aneesh Kumar K.V
    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
1241 d8e0c29e Aneesh Kumar K.V
    if (err < 0) {
1242 d8e0c29e Aneesh Kumar K.V
        goto out;
1243 d8e0c29e Aneesh Kumar K.V
    }
1244 d8e0c29e Aneesh Kumar K.V
    err = stat_to_v9stat(s, &fidp->path, &stbuf, &v9stat);
1245 d8e0c29e Aneesh Kumar K.V
    if (err < 0) {
1246 d8e0c29e Aneesh Kumar K.V
        goto out;
1247 d8e0c29e Aneesh Kumar K.V
    }
1248 d8e0c29e Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat);
1249 d8e0c29e Aneesh Kumar K.V
    err = offset;
1250 d8e0c29e Aneesh Kumar K.V
    v9fs_stat_free(&v9stat);
1251 4da7d3fa Anthony Liguori
out:
1252 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1253 84dfb926 Aneesh Kumar K.V
out_nofid:
1254 d8e0c29e Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
1255 9f107513 Anthony Liguori
}
1256 9f107513 Anthony Liguori
1257 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_getattr(void *opaque)
1258 00ede4c2 Sripathi Kodi
{
1259 00ede4c2 Sripathi Kodi
    int32_t fid;
1260 8db21ce7 Aneesh Kumar K.V
    size_t offset = 7;
1261 8db21ce7 Aneesh Kumar K.V
    ssize_t retval = 0;
1262 8db21ce7 Aneesh Kumar K.V
    struct stat stbuf;
1263 00ede4c2 Sripathi Kodi
    V9fsFidState *fidp;
1264 00ede4c2 Sripathi Kodi
    uint64_t request_mask;
1265 8db21ce7 Aneesh Kumar K.V
    V9fsStatDotl v9stat_dotl;
1266 8db21ce7 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1267 8db21ce7 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1268 00ede4c2 Sripathi Kodi
1269 8db21ce7 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
1270 00ede4c2 Sripathi Kodi
1271 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1272 00ede4c2 Sripathi Kodi
    if (fidp == NULL) {
1273 8db21ce7 Aneesh Kumar K.V
        retval = -ENOENT;
1274 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1275 00ede4c2 Sripathi Kodi
    }
1276 8db21ce7 Aneesh Kumar K.V
    /*
1277 8db21ce7 Aneesh Kumar K.V
     * Currently we only support BASIC fields in stat, so there is no
1278 00ede4c2 Sripathi Kodi
     * need to look at request_mask.
1279 00ede4c2 Sripathi Kodi
     */
1280 8db21ce7 Aneesh Kumar K.V
    retval = v9fs_co_lstat(s, &fidp->path, &stbuf);
1281 8db21ce7 Aneesh Kumar K.V
    if (retval < 0) {
1282 8db21ce7 Aneesh Kumar K.V
        goto out;
1283 8db21ce7 Aneesh Kumar K.V
    }
1284 8db21ce7 Aneesh Kumar K.V
    stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl);
1285 8db21ce7 Aneesh Kumar K.V
    retval = offset;
1286 8db21ce7 Aneesh Kumar K.V
    retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
1287 00ede4c2 Sripathi Kodi
out:
1288 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1289 84dfb926 Aneesh Kumar K.V
out_nofid:
1290 8db21ce7 Aneesh Kumar K.V
    complete_pdu(s, pdu, retval);
1291 00ede4c2 Sripathi Kodi
}
1292 00ede4c2 Sripathi Kodi
1293 c79ce737 Sripathi Kodi
/* From Linux kernel code */
1294 c79ce737 Sripathi Kodi
#define ATTR_MODE    (1 << 0)
1295 c79ce737 Sripathi Kodi
#define ATTR_UID     (1 << 1)
1296 c79ce737 Sripathi Kodi
#define ATTR_GID     (1 << 2)
1297 c79ce737 Sripathi Kodi
#define ATTR_SIZE    (1 << 3)
1298 c79ce737 Sripathi Kodi
#define ATTR_ATIME   (1 << 4)
1299 c79ce737 Sripathi Kodi
#define ATTR_MTIME   (1 << 5)
1300 c79ce737 Sripathi Kodi
#define ATTR_CTIME   (1 << 6)
1301 c79ce737 Sripathi Kodi
#define ATTR_MASK    127
1302 c79ce737 Sripathi Kodi
#define ATTR_ATIME_SET  (1 << 7)
1303 c79ce737 Sripathi Kodi
#define ATTR_MTIME_SET  (1 << 8)
1304 c79ce737 Sripathi Kodi
1305 65c05f9a Aneesh Kumar K.V
static void v9fs_setattr(void *opaque)
1306 c79ce737 Sripathi Kodi
{
1307 65c05f9a Aneesh Kumar K.V
    int err = 0;
1308 65c05f9a Aneesh Kumar K.V
    int32_t fid;
1309 65c05f9a Aneesh Kumar K.V
    V9fsFidState *fidp;
1310 65c05f9a Aneesh Kumar K.V
    size_t offset = 7;
1311 65c05f9a Aneesh Kumar K.V
    V9fsIattr v9iattr;
1312 65c05f9a Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1313 65c05f9a Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1314 c79ce737 Sripathi Kodi
1315 65c05f9a Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
1316 c79ce737 Sripathi Kodi
1317 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1318 65c05f9a Aneesh Kumar K.V
    if (fidp == NULL) {
1319 65c05f9a Aneesh Kumar K.V
        err = -EINVAL;
1320 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1321 c79ce737 Sripathi Kodi
    }
1322 65c05f9a Aneesh Kumar K.V
    if (v9iattr.valid & ATTR_MODE) {
1323 65c05f9a Aneesh Kumar K.V
        err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode);
1324 65c05f9a Aneesh Kumar K.V
        if (err < 0) {
1325 65c05f9a Aneesh Kumar K.V
            goto out;
1326 c79ce737 Sripathi Kodi
        }
1327 c79ce737 Sripathi Kodi
    }
1328 65c05f9a Aneesh Kumar K.V
    if (v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) {
1329 c79ce737 Sripathi Kodi
        struct timespec times[2];
1330 65c05f9a Aneesh Kumar K.V
        if (v9iattr.valid & ATTR_ATIME) {
1331 65c05f9a Aneesh Kumar K.V
            if (v9iattr.valid & ATTR_ATIME_SET) {
1332 65c05f9a Aneesh Kumar K.V
                times[0].tv_sec = v9iattr.atime_sec;
1333 65c05f9a Aneesh Kumar K.V
                times[0].tv_nsec = v9iattr.atime_nsec;
1334 c79ce737 Sripathi Kodi
            } else {
1335 c79ce737 Sripathi Kodi
                times[0].tv_nsec = UTIME_NOW;
1336 c79ce737 Sripathi Kodi
            }
1337 c79ce737 Sripathi Kodi
        } else {
1338 c79ce737 Sripathi Kodi
            times[0].tv_nsec = UTIME_OMIT;
1339 c79ce737 Sripathi Kodi
        }
1340 65c05f9a Aneesh Kumar K.V
        if (v9iattr.valid & ATTR_MTIME) {
1341 65c05f9a Aneesh Kumar K.V
            if (v9iattr.valid & ATTR_MTIME_SET) {
1342 65c05f9a Aneesh Kumar K.V
                times[1].tv_sec = v9iattr.mtime_sec;
1343 65c05f9a Aneesh Kumar K.V
                times[1].tv_nsec = v9iattr.mtime_nsec;
1344 c79ce737 Sripathi Kodi
            } else {
1345 c79ce737 Sripathi Kodi
                times[1].tv_nsec = UTIME_NOW;
1346 c79ce737 Sripathi Kodi
            }
1347 c79ce737 Sripathi Kodi
        } else {
1348 c79ce737 Sripathi Kodi
            times[1].tv_nsec = UTIME_OMIT;
1349 c79ce737 Sripathi Kodi
        }
1350 65c05f9a Aneesh Kumar K.V
        err = v9fs_co_utimensat(s, &fidp->path, times);
1351 65c05f9a Aneesh Kumar K.V
        if (err < 0) {
1352 65c05f9a Aneesh Kumar K.V
            goto out;
1353 65c05f9a Aneesh Kumar K.V
        }
1354 c79ce737 Sripathi Kodi
    }
1355 65c05f9a Aneesh Kumar K.V
    /*
1356 65c05f9a Aneesh Kumar K.V
     * If the only valid entry in iattr is ctime we can call
1357 65c05f9a Aneesh Kumar K.V
     * chown(-1,-1) to update the ctime of the file
1358 65c05f9a Aneesh Kumar K.V
     */
1359 65c05f9a Aneesh Kumar K.V
    if ((v9iattr.valid & (ATTR_UID | ATTR_GID)) ||
1360 65c05f9a Aneesh Kumar K.V
        ((v9iattr.valid & ATTR_CTIME)
1361 65c05f9a Aneesh Kumar K.V
         && !((v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
1362 65c05f9a Aneesh Kumar K.V
        if (!(v9iattr.valid & ATTR_UID)) {
1363 65c05f9a Aneesh Kumar K.V
            v9iattr.uid = -1;
1364 65c05f9a Aneesh Kumar K.V
        }
1365 65c05f9a Aneesh Kumar K.V
        if (!(v9iattr.valid & ATTR_GID)) {
1366 65c05f9a Aneesh Kumar K.V
            v9iattr.gid = -1;
1367 65c05f9a Aneesh Kumar K.V
        }
1368 65c05f9a Aneesh Kumar K.V
        err = v9fs_co_chown(s, &fidp->path, v9iattr.uid,
1369 65c05f9a Aneesh Kumar K.V
                            v9iattr.gid);
1370 65c05f9a Aneesh Kumar K.V
        if (err < 0) {
1371 65c05f9a Aneesh Kumar K.V
            goto out;
1372 65c05f9a Aneesh Kumar K.V
        }
1373 c79ce737 Sripathi Kodi
    }
1374 65c05f9a Aneesh Kumar K.V
    if (v9iattr.valid & (ATTR_SIZE)) {
1375 65c05f9a Aneesh Kumar K.V
        err = v9fs_co_truncate(s, &fidp->path, v9iattr.size);
1376 65c05f9a Aneesh Kumar K.V
        if (err < 0) {
1377 65c05f9a Aneesh Kumar K.V
            goto out;
1378 65c05f9a Aneesh Kumar K.V
        }
1379 c79ce737 Sripathi Kodi
    }
1380 65c05f9a Aneesh Kumar K.V
    err = offset;
1381 c79ce737 Sripathi Kodi
out:
1382 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1383 84dfb926 Aneesh Kumar K.V
out_nofid:
1384 65c05f9a Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
1385 c79ce737 Sripathi Kodi
}
1386 c79ce737 Sripathi Kodi
1387 3cc19c0c Aneesh Kumar K.V
static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
1388 ff5e54c9 Anthony Liguori
{
1389 ff5e54c9 Anthony Liguori
    int i;
1390 3cc19c0c Aneesh Kumar K.V
    size_t offset = 7;
1391 3cc19c0c Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "w", nwnames);
1392 3cc19c0c Aneesh Kumar K.V
    for (i = 0; i < nwnames; i++) {
1393 3cc19c0c Aneesh Kumar K.V
        offset += pdu_marshal(pdu, offset, "Q", &qids[i]);
1394 ff5e54c9 Anthony Liguori
    }
1395 3cc19c0c Aneesh Kumar K.V
    return offset;
1396 ff5e54c9 Anthony Liguori
}
1397 ff5e54c9 Anthony Liguori
1398 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_walk(void *opaque)
1399 9f107513 Anthony Liguori
{
1400 3cc19c0c Aneesh Kumar K.V
    int name_idx;
1401 3cc19c0c Aneesh Kumar K.V
    V9fsQID *qids = NULL;
1402 3cc19c0c Aneesh Kumar K.V
    int i, err = 0;
1403 3cc19c0c Aneesh Kumar K.V
    V9fsString path;
1404 3cc19c0c Aneesh Kumar K.V
    uint16_t nwnames;
1405 3cc19c0c Aneesh Kumar K.V
    struct stat stbuf;
1406 3cc19c0c Aneesh Kumar K.V
    size_t offset = 7;
1407 3cc19c0c Aneesh Kumar K.V
    int32_t fid, newfid;
1408 3cc19c0c Aneesh Kumar K.V
    V9fsString *wnames = NULL;
1409 3cc19c0c Aneesh Kumar K.V
    V9fsFidState *fidp;
1410 84dfb926 Aneesh Kumar K.V
    V9fsFidState *newfidp = NULL;;
1411 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
1412 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
1413 ff5e54c9 Anthony Liguori
1414 3cc19c0c Aneesh Kumar K.V
    offset += pdu_unmarshal(pdu, offset, "ddw", &fid,
1415 3cc19c0c Aneesh Kumar K.V
                            &newfid, &nwnames);
1416 ff5e54c9 Anthony Liguori
1417 3cc19c0c Aneesh Kumar K.V
    if (nwnames && nwnames <= P9_MAXWELEM) {
1418 3cc19c0c Aneesh Kumar K.V
        wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
1419 3cc19c0c Aneesh Kumar K.V
        qids   = g_malloc0(sizeof(qids[0]) * nwnames);
1420 3cc19c0c Aneesh Kumar K.V
        for (i = 0; i < nwnames; i++) {
1421 3cc19c0c Aneesh Kumar K.V
            offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]);
1422 ff5e54c9 Anthony Liguori
        }
1423 3cc19c0c Aneesh Kumar K.V
1424 3cc19c0c Aneesh Kumar K.V
    } else if (nwnames > P9_MAXWELEM) {
1425 4f8dee2d Harsh Prateek Bora
        err = -EINVAL;
1426 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1427 ff5e54c9 Anthony Liguori
    }
1428 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1429 3cc19c0c Aneesh Kumar K.V
    if (fidp == NULL) {
1430 ff5e54c9 Anthony Liguori
        err = -ENOENT;
1431 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1432 ff5e54c9 Anthony Liguori
    }
1433 ff5e54c9 Anthony Liguori
    if (fid == newfid) {
1434 3cc19c0c Aneesh Kumar K.V
        BUG_ON(fidp->fid_type != P9_FID_NONE);
1435 3cc19c0c Aneesh Kumar K.V
        v9fs_string_init(&path);
1436 3cc19c0c Aneesh Kumar K.V
        for (name_idx = 0; name_idx < nwnames; name_idx++) {
1437 3cc19c0c Aneesh Kumar K.V
            v9fs_string_sprintf(&path, "%s/%s",
1438 3cc19c0c Aneesh Kumar K.V
                                fidp->path.data, wnames[name_idx].data);
1439 3cc19c0c Aneesh Kumar K.V
            v9fs_string_copy(&fidp->path, &path);
1440 3cc19c0c Aneesh Kumar K.V
1441 3cc19c0c Aneesh Kumar K.V
            err = v9fs_co_lstat(s, &fidp->path, &stbuf);
1442 3cc19c0c Aneesh Kumar K.V
            if (err < 0) {
1443 3cc19c0c Aneesh Kumar K.V
                v9fs_string_free(&path);
1444 3cc19c0c Aneesh Kumar K.V
                goto out;
1445 3cc19c0c Aneesh Kumar K.V
            }
1446 3cc19c0c Aneesh Kumar K.V
            stat_to_qid(&stbuf, &qids[name_idx]);
1447 ff5e54c9 Anthony Liguori
        }
1448 3cc19c0c Aneesh Kumar K.V
        v9fs_string_free(&path);
1449 ff5e54c9 Anthony Liguori
    } else {
1450 3cc19c0c Aneesh Kumar K.V
        newfidp = alloc_fid(s, newfid);
1451 3cc19c0c Aneesh Kumar K.V
        if (newfidp == NULL) {
1452 ff5e54c9 Anthony Liguori
            err = -EINVAL;
1453 ff5e54c9 Anthony Liguori
            goto out;
1454 ff5e54c9 Anthony Liguori
        }
1455 3cc19c0c Aneesh Kumar K.V
        newfidp->uid = fidp->uid;
1456 3cc19c0c Aneesh Kumar K.V
        v9fs_string_init(&path);
1457 3cc19c0c Aneesh Kumar K.V
        v9fs_string_copy(&newfidp->path, &fidp->path);
1458 3cc19c0c Aneesh Kumar K.V
        for (name_idx = 0; name_idx < nwnames; name_idx++) {
1459 3cc19c0c Aneesh Kumar K.V
            v9fs_string_sprintf(&path, "%s/%s", newfidp->path.data,
1460 3cc19c0c Aneesh Kumar K.V
                                wnames[name_idx].data);
1461 3cc19c0c Aneesh Kumar K.V
            v9fs_string_copy(&newfidp->path, &path);
1462 3cc19c0c Aneesh Kumar K.V
            err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
1463 3cc19c0c Aneesh Kumar K.V
            if (err < 0) {
1464 84dfb926 Aneesh Kumar K.V
                clunk_fid(s, newfidp->fid);
1465 3cc19c0c Aneesh Kumar K.V
                v9fs_string_free(&path);
1466 3cc19c0c Aneesh Kumar K.V
                goto out;
1467 3cc19c0c Aneesh Kumar K.V
            }
1468 3cc19c0c Aneesh Kumar K.V
            stat_to_qid(&stbuf, &qids[name_idx]);
1469 ff5e54c9 Anthony Liguori
        }
1470 3cc19c0c Aneesh Kumar K.V
        v9fs_string_free(&path);
1471 9f107513 Anthony Liguori
    }
1472 3cc19c0c Aneesh Kumar K.V
    err = v9fs_walk_marshal(pdu, nwnames, qids);
1473 ff5e54c9 Anthony Liguori
out:
1474 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1475 84dfb926 Aneesh Kumar K.V
    if (newfidp) {
1476 84dfb926 Aneesh Kumar K.V
        put_fid(s, newfidp);
1477 84dfb926 Aneesh Kumar K.V
    }
1478 84dfb926 Aneesh Kumar K.V
out_nofid:
1479 3cc19c0c Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
1480 3cc19c0c Aneesh Kumar K.V
    if (nwnames && nwnames <= P9_MAXWELEM) {
1481 3cc19c0c Aneesh Kumar K.V
        for (name_idx = 0; name_idx < nwnames; name_idx++) {
1482 3cc19c0c Aneesh Kumar K.V
            v9fs_string_free(&wnames[name_idx]);
1483 3cc19c0c Aneesh Kumar K.V
        }
1484 3cc19c0c Aneesh Kumar K.V
        g_free(wnames);
1485 3cc19c0c Aneesh Kumar K.V
        g_free(qids);
1486 3cc19c0c Aneesh Kumar K.V
    }
1487 9f107513 Anthony Liguori
}
1488 9f107513 Anthony Liguori
1489 5e94c103 M. Mohan Kumar
static int32_t get_iounit(V9fsState *s, V9fsString *name)
1490 5e94c103 M. Mohan Kumar
{
1491 5e94c103 M. Mohan Kumar
    struct statfs stbuf;
1492 5e94c103 M. Mohan Kumar
    int32_t iounit = 0;
1493 5e94c103 M. Mohan Kumar
1494 5e94c103 M. Mohan Kumar
    /*
1495 5e94c103 M. Mohan Kumar
     * iounit should be multiples of f_bsize (host filesystem block size
1496 5e94c103 M. Mohan Kumar
     * and as well as less than (client msize - P9_IOHDRSZ))
1497 5e94c103 M. Mohan Kumar
     */
1498 857bc158 Aneesh Kumar K.V
    if (!v9fs_co_statfs(s, name, &stbuf)) {
1499 5e94c103 M. Mohan Kumar
        iounit = stbuf.f_bsize;
1500 5e94c103 M. Mohan Kumar
        iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
1501 5e94c103 M. Mohan Kumar
    }
1502 5e94c103 M. Mohan Kumar
    if (!iounit) {
1503 5e94c103 M. Mohan Kumar
        iounit = s->msize - P9_IOHDRSZ;
1504 5e94c103 M. Mohan Kumar
    }
1505 5e94c103 M. Mohan Kumar
    return iounit;
1506 5e94c103 M. Mohan Kumar
}
1507 5e94c103 M. Mohan Kumar
1508 857bc158 Aneesh Kumar K.V
static void v9fs_open(void *opaque)
1509 5e94c103 M. Mohan Kumar
{
1510 857bc158 Aneesh Kumar K.V
    int flags;
1511 857bc158 Aneesh Kumar K.V
    int iounit;
1512 857bc158 Aneesh Kumar K.V
    int32_t fid;
1513 857bc158 Aneesh Kumar K.V
    int32_t mode;
1514 857bc158 Aneesh Kumar K.V
    V9fsQID qid;
1515 857bc158 Aneesh Kumar K.V
    ssize_t err = 0;
1516 857bc158 Aneesh Kumar K.V
    size_t offset = 7;
1517 857bc158 Aneesh Kumar K.V
    struct stat stbuf;
1518 857bc158 Aneesh Kumar K.V
    V9fsFidState *fidp;
1519 857bc158 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1520 857bc158 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1521 5e94c103 M. Mohan Kumar
1522 857bc158 Aneesh Kumar K.V
    if (s->proto_version == V9FS_PROTO_2000L) {
1523 857bc158 Aneesh Kumar K.V
        pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
1524 857bc158 Aneesh Kumar K.V
    } else {
1525 857bc158 Aneesh Kumar K.V
        pdu_unmarshal(pdu, offset, "db", &fid, &mode);
1526 857bc158 Aneesh Kumar K.V
    }
1527 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1528 857bc158 Aneesh Kumar K.V
    if (fidp == NULL) {
1529 857bc158 Aneesh Kumar K.V
        err = -ENOENT;
1530 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1531 a6568fe2 Anthony Liguori
    }
1532 857bc158 Aneesh Kumar K.V
    BUG_ON(fidp->fid_type != P9_FID_NONE);
1533 a6568fe2 Anthony Liguori
1534 857bc158 Aneesh Kumar K.V
    err = v9fs_co_lstat(s, &fidp->path, &stbuf);
1535 857bc158 Aneesh Kumar K.V
    if (err < 0) {
1536 a6568fe2 Anthony Liguori
        goto out;
1537 a6568fe2 Anthony Liguori
    }
1538 857bc158 Aneesh Kumar K.V
    stat_to_qid(&stbuf, &qid);
1539 857bc158 Aneesh Kumar K.V
    if (S_ISDIR(stbuf.st_mode)) {
1540 857bc158 Aneesh Kumar K.V
        err = v9fs_co_opendir(s, fidp);
1541 857bc158 Aneesh Kumar K.V
        if (err < 0) {
1542 857bc158 Aneesh Kumar K.V
            goto out;
1543 857bc158 Aneesh Kumar K.V
        }
1544 857bc158 Aneesh Kumar K.V
        fidp->fid_type = P9_FID_DIR;
1545 857bc158 Aneesh Kumar K.V
        offset += pdu_marshal(pdu, offset, "Qd", &qid, 0);
1546 857bc158 Aneesh Kumar K.V
        err = offset;
1547 a6568fe2 Anthony Liguori
    } else {
1548 771e9d4c M. Mohan Kumar
        if (s->proto_version == V9FS_PROTO_2000L) {
1549 857bc158 Aneesh Kumar K.V
            flags = mode;
1550 630c2689 Sripathi Kodi
            flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
1551 0f8151cb Venkateswararao Jujjuri (JV)
            /* Ignore direct disk access hint until the server supports it. */
1552 0f8151cb Venkateswararao Jujjuri (JV)
            flags &= ~O_DIRECT;
1553 771e9d4c M. Mohan Kumar
        } else {
1554 857bc158 Aneesh Kumar K.V
            flags = omode_to_uflags(mode);
1555 771e9d4c M. Mohan Kumar
        }
1556 857bc158 Aneesh Kumar K.V
        err = v9fs_co_open(s, fidp, flags);
1557 857bc158 Aneesh Kumar K.V
        if (err < 0) {
1558 857bc158 Aneesh Kumar K.V
            goto out;
1559 857bc158 Aneesh Kumar K.V
        }
1560 857bc158 Aneesh Kumar K.V
        fidp->fid_type = P9_FID_FILE;
1561 7a462745 Aneesh Kumar K.V
        fidp->open_flags = flags;
1562 7a462745 Aneesh Kumar K.V
        if (flags & O_EXCL) {
1563 7a462745 Aneesh Kumar K.V
            /*
1564 7a462745 Aneesh Kumar K.V
             * We let the host file system do O_EXCL check
1565 7a462745 Aneesh Kumar K.V
             * We should not reclaim such fd
1566 7a462745 Aneesh Kumar K.V
             */
1567 7a462745 Aneesh Kumar K.V
            fidp->flags |= FID_NON_RECLAIMABLE;
1568 7a462745 Aneesh Kumar K.V
        }
1569 857bc158 Aneesh Kumar K.V
        iounit = get_iounit(s, &fidp->path);
1570 857bc158 Aneesh Kumar K.V
        offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1571 857bc158 Aneesh Kumar K.V
        err = offset;
1572 a6568fe2 Anthony Liguori
    }
1573 a6568fe2 Anthony Liguori
out:
1574 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1575 84dfb926 Aneesh Kumar K.V
out_nofid:
1576 a6568fe2 Anthony Liguori
    complete_pdu(s, pdu, err);
1577 a6568fe2 Anthony Liguori
}
1578 a6568fe2 Anthony Liguori
1579 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_lcreate(void *opaque)
1580 c1568af5 Venkateswararao Jujjuri (JV)
{
1581 c1568af5 Venkateswararao Jujjuri (JV)
    int32_t dfid, flags, mode;
1582 c1568af5 Venkateswararao Jujjuri (JV)
    gid_t gid;
1583 c1568af5 Venkateswararao Jujjuri (JV)
    ssize_t err = 0;
1584 36f8981f Venkateswararao Jujjuri
    ssize_t offset = 7;
1585 36f8981f Venkateswararao Jujjuri
    V9fsString fullname;
1586 36f8981f Venkateswararao Jujjuri
    V9fsString name;
1587 36f8981f Venkateswararao Jujjuri
    V9fsFidState *fidp;
1588 36f8981f Venkateswararao Jujjuri
    struct stat stbuf;
1589 36f8981f Venkateswararao Jujjuri
    V9fsQID qid;
1590 36f8981f Venkateswararao Jujjuri
    int32_t iounit;
1591 36f8981f Venkateswararao Jujjuri
    V9fsPDU *pdu = opaque;
1592 c1568af5 Venkateswararao Jujjuri (JV)
1593 36f8981f Venkateswararao Jujjuri
    v9fs_string_init(&fullname);
1594 36f8981f Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
1595 36f8981f Venkateswararao Jujjuri
                  &mode, &gid);
1596 c1568af5 Venkateswararao Jujjuri (JV)
1597 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(pdu->s, dfid);
1598 36f8981f Venkateswararao Jujjuri
    if (fidp == NULL) {
1599 c1568af5 Venkateswararao Jujjuri (JV)
        err = -ENOENT;
1600 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1601 c1568af5 Venkateswararao Jujjuri (JV)
    }
1602 36f8981f Venkateswararao Jujjuri
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
1603 c1568af5 Venkateswararao Jujjuri (JV)
1604 0f8151cb Venkateswararao Jujjuri (JV)
    /* Ignore direct disk access hint until the server supports it. */
1605 0f8151cb Venkateswararao Jujjuri (JV)
    flags &= ~O_DIRECT;
1606 0f8151cb Venkateswararao Jujjuri (JV)
1607 36f8981f Venkateswararao Jujjuri
    err = v9fs_co_open2(pdu->s, fidp, fullname.data, gid, flags, mode);
1608 36f8981f Venkateswararao Jujjuri
    if (err < 0) {
1609 36f8981f Venkateswararao Jujjuri
        goto out;
1610 36f8981f Venkateswararao Jujjuri
    }
1611 36f8981f Venkateswararao Jujjuri
    fidp->fid_type = P9_FID_FILE;
1612 7a462745 Aneesh Kumar K.V
    fidp->open_flags = flags;
1613 7a462745 Aneesh Kumar K.V
    if (flags & O_EXCL) {
1614 7a462745 Aneesh Kumar K.V
        /*
1615 7a462745 Aneesh Kumar K.V
         * We let the host file system do O_EXCL check
1616 7a462745 Aneesh Kumar K.V
         * We should not reclaim such fd
1617 7a462745 Aneesh Kumar K.V
         */
1618 7a462745 Aneesh Kumar K.V
        fidp->flags |= FID_NON_RECLAIMABLE;
1619 7a462745 Aneesh Kumar K.V
    }
1620 36f8981f Venkateswararao Jujjuri
    iounit =  get_iounit(pdu->s, &fullname);
1621 c1568af5 Venkateswararao Jujjuri (JV)
1622 36f8981f Venkateswararao Jujjuri
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
1623 36f8981f Venkateswararao Jujjuri
    if (err < 0) {
1624 36f8981f Venkateswararao Jujjuri
        fidp->fid_type = P9_FID_NONE;
1625 36f8981f Venkateswararao Jujjuri
        if (fidp->fs.fd > 0) {
1626 9b54ffaa Aneesh Kumar K.V
            v9fs_co_close(pdu->s, fidp->fs.fd);
1627 36f8981f Venkateswararao Jujjuri
        }
1628 36f8981f Venkateswararao Jujjuri
        goto out;
1629 36f8981f Venkateswararao Jujjuri
    }
1630 36f8981f Venkateswararao Jujjuri
    v9fs_string_copy(&fidp->path, &fullname);
1631 36f8981f Venkateswararao Jujjuri
    stat_to_qid(&stbuf, &qid);
1632 36f8981f Venkateswararao Jujjuri
    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1633 36f8981f Venkateswararao Jujjuri
    err = offset;
1634 c1568af5 Venkateswararao Jujjuri (JV)
out:
1635 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, fidp);
1636 84dfb926 Aneesh Kumar K.V
out_nofid:
1637 36f8981f Venkateswararao Jujjuri
    complete_pdu(pdu->s, pdu, err);
1638 36f8981f Venkateswararao Jujjuri
    v9fs_string_free(&name);
1639 36f8981f Venkateswararao Jujjuri
    v9fs_string_free(&fullname);
1640 c1568af5 Venkateswararao Jujjuri (JV)
}
1641 c1568af5 Venkateswararao Jujjuri (JV)
1642 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_fsync(void *opaque)
1643 b41e95d3 Venkateswararao Jujjuri (JV)
{
1644 4e9ad444 Aneesh Kumar K.V
    int err;
1645 b41e95d3 Venkateswararao Jujjuri (JV)
    int32_t fid;
1646 4e9ad444 Aneesh Kumar K.V
    int datasync;
1647 b41e95d3 Venkateswararao Jujjuri (JV)
    size_t offset = 7;
1648 b41e95d3 Venkateswararao Jujjuri (JV)
    V9fsFidState *fidp;
1649 4e9ad444 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1650 4e9ad444 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1651 b41e95d3 Venkateswararao Jujjuri (JV)
1652 49594973 Venkateswararao Jujjuri (JV)
    pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
1653 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1654 b41e95d3 Venkateswararao Jujjuri (JV)
    if (fidp == NULL) {
1655 b41e95d3 Venkateswararao Jujjuri (JV)
        err = -ENOENT;
1656 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1657 b41e95d3 Venkateswararao Jujjuri (JV)
    }
1658 4e9ad444 Aneesh Kumar K.V
    err = v9fs_co_fsync(s, fidp, datasync);
1659 4e9ad444 Aneesh Kumar K.V
    if (!err) {
1660 4e9ad444 Aneesh Kumar K.V
        err = offset;
1661 4e9ad444 Aneesh Kumar K.V
    }
1662 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1663 84dfb926 Aneesh Kumar K.V
out_nofid:
1664 4e9ad444 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
1665 b41e95d3 Venkateswararao Jujjuri (JV)
}
1666 b41e95d3 Venkateswararao Jujjuri (JV)
1667 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_clunk(void *opaque)
1668 a6568fe2 Anthony Liguori
{
1669 c540ee51 Aneesh Kumar K.V
    int err;
1670 bbd5697b Anthony Liguori
    int32_t fid;
1671 bbd5697b Anthony Liguori
    size_t offset = 7;
1672 84dfb926 Aneesh Kumar K.V
    V9fsFidState *fidp;
1673 c540ee51 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1674 c540ee51 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1675 bbd5697b Anthony Liguori
1676 bbd5697b Anthony Liguori
    pdu_unmarshal(pdu, offset, "d", &fid);
1677 84dfb926 Aneesh Kumar K.V
1678 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1679 84dfb926 Aneesh Kumar K.V
    if (fidp == NULL) {
1680 84dfb926 Aneesh Kumar K.V
        err = -ENOENT;
1681 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1682 84dfb926 Aneesh Kumar K.V
    }
1683 84dfb926 Aneesh Kumar K.V
    err = clunk_fid(s, fidp->fid);
1684 bbd5697b Anthony Liguori
    if (err < 0) {
1685 bbd5697b Anthony Liguori
        goto out;
1686 a6568fe2 Anthony Liguori
    }
1687 bbd5697b Anthony Liguori
    err = offset;
1688 bbd5697b Anthony Liguori
out:
1689 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1690 84dfb926 Aneesh Kumar K.V
out_nofid:
1691 bbd5697b Anthony Liguori
    complete_pdu(s, pdu, err);
1692 9f107513 Anthony Liguori
}
1693 9f107513 Anthony Liguori
1694 d208a0e0 Aneesh Kumar K.V
static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
1695 d208a0e0 Aneesh Kumar K.V
                           V9fsFidState *fidp, int64_t off, int32_t max_count)
1696 a9231555 Anthony Liguori
{
1697 d208a0e0 Aneesh Kumar K.V
    size_t offset = 7;
1698 d208a0e0 Aneesh Kumar K.V
    int read_count;
1699 d208a0e0 Aneesh Kumar K.V
    int64_t xattr_len;
1700 a9231555 Anthony Liguori
1701 d208a0e0 Aneesh Kumar K.V
    xattr_len = fidp->fs.xattr.len;
1702 d208a0e0 Aneesh Kumar K.V
    read_count = xattr_len - off;
1703 d208a0e0 Aneesh Kumar K.V
    if (read_count > max_count) {
1704 d208a0e0 Aneesh Kumar K.V
        read_count = max_count;
1705 d208a0e0 Aneesh Kumar K.V
    } else if (read_count < 0) {
1706 d208a0e0 Aneesh Kumar K.V
        /*
1707 d208a0e0 Aneesh Kumar K.V
         * read beyond XATTR value
1708 d208a0e0 Aneesh Kumar K.V
         */
1709 d208a0e0 Aneesh Kumar K.V
        read_count = 0;
1710 a9231555 Anthony Liguori
    }
1711 d208a0e0 Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "d", read_count);
1712 d208a0e0 Aneesh Kumar K.V
    offset += pdu_pack(pdu, offset,
1713 d208a0e0 Aneesh Kumar K.V
                       ((char *)fidp->fs.xattr.value) + off,
1714 d208a0e0 Aneesh Kumar K.V
                       read_count);
1715 d208a0e0 Aneesh Kumar K.V
    return offset;
1716 a9231555 Anthony Liguori
}
1717 a9231555 Anthony Liguori
1718 d208a0e0 Aneesh Kumar K.V
static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu,
1719 d208a0e0 Aneesh Kumar K.V
                                     V9fsFidState *fidp, int32_t max_count)
1720 a9231555 Anthony Liguori
{
1721 d208a0e0 Aneesh Kumar K.V
    V9fsString name;
1722 d208a0e0 Aneesh Kumar K.V
    V9fsStat v9stat;
1723 d208a0e0 Aneesh Kumar K.V
    int len, err = 0;
1724 d208a0e0 Aneesh Kumar K.V
    int32_t count = 0;
1725 d208a0e0 Aneesh Kumar K.V
    struct stat stbuf;
1726 d208a0e0 Aneesh Kumar K.V
    off_t saved_dir_pos;
1727 5f524c1e Harsh Prateek Bora
    struct dirent *dent, *result;
1728 a9231555 Anthony Liguori
1729 d208a0e0 Aneesh Kumar K.V
    /* save the directory position */
1730 d208a0e0 Aneesh Kumar K.V
    saved_dir_pos = v9fs_co_telldir(s, fidp);
1731 d208a0e0 Aneesh Kumar K.V
    if (saved_dir_pos < 0) {
1732 d208a0e0 Aneesh Kumar K.V
        return saved_dir_pos;
1733 a9231555 Anthony Liguori
    }
1734 5f524c1e Harsh Prateek Bora
1735 5f524c1e Harsh Prateek Bora
    dent = g_malloc(sizeof(struct dirent));
1736 5f524c1e Harsh Prateek Bora
1737 d208a0e0 Aneesh Kumar K.V
    while (1) {
1738 d208a0e0 Aneesh Kumar K.V
        v9fs_string_init(&name);
1739 5f524c1e Harsh Prateek Bora
        err = v9fs_co_readdir_r(s, fidp, dent, &result);
1740 5f524c1e Harsh Prateek Bora
        if (err || !result) {
1741 d208a0e0 Aneesh Kumar K.V
            break;
1742 d208a0e0 Aneesh Kumar K.V
        }
1743 d208a0e0 Aneesh Kumar K.V
        v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name);
1744 d208a0e0 Aneesh Kumar K.V
        err = v9fs_co_lstat(s, &name, &stbuf);
1745 d208a0e0 Aneesh Kumar K.V
        if (err < 0) {
1746 d208a0e0 Aneesh Kumar K.V
            goto out;
1747 d208a0e0 Aneesh Kumar K.V
        }
1748 d208a0e0 Aneesh Kumar K.V
        err = stat_to_v9stat(s, &name, &stbuf, &v9stat);
1749 d208a0e0 Aneesh Kumar K.V
        if (err < 0) {
1750 d208a0e0 Aneesh Kumar K.V
            goto out;
1751 a9231555 Anthony Liguori
        }
1752 d208a0e0 Aneesh Kumar K.V
        /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1753 d208a0e0 Aneesh Kumar K.V
        len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
1754 d208a0e0 Aneesh Kumar K.V
        if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
1755 d208a0e0 Aneesh Kumar K.V
            /* Ran out of buffer. Set dir back to old position and return */
1756 d208a0e0 Aneesh Kumar K.V
            v9fs_co_seekdir(s, fidp, saved_dir_pos);
1757 d208a0e0 Aneesh Kumar K.V
            v9fs_stat_free(&v9stat);
1758 d208a0e0 Aneesh Kumar K.V
            v9fs_string_free(&name);
1759 5f524c1e Harsh Prateek Bora
            g_free(dent);
1760 d208a0e0 Aneesh Kumar K.V
            return count;
1761 d208a0e0 Aneesh Kumar K.V
        }
1762 d208a0e0 Aneesh Kumar K.V
        count += len;
1763 d208a0e0 Aneesh Kumar K.V
        v9fs_stat_free(&v9stat);
1764 d208a0e0 Aneesh Kumar K.V
        v9fs_string_free(&name);
1765 d208a0e0 Aneesh Kumar K.V
        saved_dir_pos = dent->d_off;
1766 a9231555 Anthony Liguori
    }
1767 a9231555 Anthony Liguori
out:
1768 5f524c1e Harsh Prateek Bora
    g_free(dent);
1769 d208a0e0 Aneesh Kumar K.V
    v9fs_string_free(&name);
1770 d208a0e0 Aneesh Kumar K.V
    if (err < 0) {
1771 d208a0e0 Aneesh Kumar K.V
        return err;
1772 fa32ef88 Aneesh Kumar K.V
    }
1773 d208a0e0 Aneesh Kumar K.V
    return count;
1774 fa32ef88 Aneesh Kumar K.V
}
1775 fa32ef88 Aneesh Kumar K.V
1776 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_read(void *opaque)
1777 9f107513 Anthony Liguori
{
1778 a9231555 Anthony Liguori
    int32_t fid;
1779 d208a0e0 Aneesh Kumar K.V
    int64_t off;
1780 a9231555 Anthony Liguori
    ssize_t err = 0;
1781 d208a0e0 Aneesh Kumar K.V
    int32_t count = 0;
1782 d208a0e0 Aneesh Kumar K.V
    size_t offset = 7;
1783 d208a0e0 Aneesh Kumar K.V
    int32_t max_count;
1784 d208a0e0 Aneesh Kumar K.V
    V9fsFidState *fidp;
1785 d208a0e0 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1786 d208a0e0 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1787 a9231555 Anthony Liguori
1788 d208a0e0 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
1789 84dfb926 Aneesh Kumar K.V
1790 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1791 d208a0e0 Aneesh Kumar K.V
    if (fidp == NULL) {
1792 a9231555 Anthony Liguori
        err = -EINVAL;
1793 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1794 a9231555 Anthony Liguori
    }
1795 d208a0e0 Aneesh Kumar K.V
    if (fidp->fid_type == P9_FID_DIR) {
1796 a9231555 Anthony Liguori
1797 d208a0e0 Aneesh Kumar K.V
        if (off == 0) {
1798 d208a0e0 Aneesh Kumar K.V
            v9fs_co_rewinddir(s, fidp);
1799 a9231555 Anthony Liguori
        }
1800 d208a0e0 Aneesh Kumar K.V
        count = v9fs_do_readdir_with_stat(s, pdu, fidp, max_count);
1801 d208a0e0 Aneesh Kumar K.V
        if (count < 0) {
1802 d208a0e0 Aneesh Kumar K.V
            err = count;
1803 d208a0e0 Aneesh Kumar K.V
            goto out;
1804 56d15a53 Sanchit Garg
        }
1805 d208a0e0 Aneesh Kumar K.V
        err = offset;
1806 d208a0e0 Aneesh Kumar K.V
        err += pdu_marshal(pdu, offset, "d", count);
1807 d208a0e0 Aneesh Kumar K.V
        err += count;
1808 d208a0e0 Aneesh Kumar K.V
    } else if (fidp->fid_type == P9_FID_FILE) {
1809 d208a0e0 Aneesh Kumar K.V
        int32_t cnt;
1810 d208a0e0 Aneesh Kumar K.V
        int32_t len;
1811 d208a0e0 Aneesh Kumar K.V
        struct iovec *sg;
1812 d208a0e0 Aneesh Kumar K.V
        struct iovec iov[128]; /* FIXME: bad, bad, bad */
1813 d208a0e0 Aneesh Kumar K.V
1814 d208a0e0 Aneesh Kumar K.V
        sg = iov;
1815 d208a0e0 Aneesh Kumar K.V
        pdu_marshal(pdu, offset + 4, "v", sg, &cnt);
1816 d208a0e0 Aneesh Kumar K.V
        sg = cap_sg(sg, max_count, &cnt);
1817 d208a0e0 Aneesh Kumar K.V
        do {
1818 d208a0e0 Aneesh Kumar K.V
            if (0) {
1819 d208a0e0 Aneesh Kumar K.V
                print_sg(sg, cnt);
1820 d208a0e0 Aneesh Kumar K.V
            }
1821 d208a0e0 Aneesh Kumar K.V
            /* Loop in case of EINTR */
1822 d208a0e0 Aneesh Kumar K.V
            do {
1823 d208a0e0 Aneesh Kumar K.V
                len = v9fs_co_preadv(s, fidp, sg, cnt, off);
1824 d208a0e0 Aneesh Kumar K.V
                if (len >= 0) {
1825 d208a0e0 Aneesh Kumar K.V
                    off   += len;
1826 d208a0e0 Aneesh Kumar K.V
                    count += len;
1827 d208a0e0 Aneesh Kumar K.V
                }
1828 d208a0e0 Aneesh Kumar K.V
            } while (len == -EINTR);
1829 d208a0e0 Aneesh Kumar K.V
            if (len < 0) {
1830 d208a0e0 Aneesh Kumar K.V
                /* IO error return the error */
1831 d208a0e0 Aneesh Kumar K.V
                err = len;
1832 d208a0e0 Aneesh Kumar K.V
                goto out;
1833 d208a0e0 Aneesh Kumar K.V
            }
1834 d208a0e0 Aneesh Kumar K.V
            sg = adjust_sg(sg, len, &cnt);
1835 d208a0e0 Aneesh Kumar K.V
        } while (count < max_count && len > 0);
1836 d208a0e0 Aneesh Kumar K.V
        err = offset;
1837 d208a0e0 Aneesh Kumar K.V
        err += pdu_marshal(pdu, offset, "d", count);
1838 d208a0e0 Aneesh Kumar K.V
        err += count;
1839 d208a0e0 Aneesh Kumar K.V
    } else if (fidp->fid_type == P9_FID_XATTR) {
1840 d208a0e0 Aneesh Kumar K.V
        err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
1841 a9231555 Anthony Liguori
    } else {
1842 a9231555 Anthony Liguori
        err = -EINVAL;
1843 9f107513 Anthony Liguori
    }
1844 a9231555 Anthony Liguori
out:
1845 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1846 84dfb926 Aneesh Kumar K.V
out_nofid:
1847 a9231555 Anthony Liguori
    complete_pdu(s, pdu, err);
1848 9f107513 Anthony Liguori
}
1849 9f107513 Anthony Liguori
1850 5e4eaa79 Aneesh Kumar K.V
static size_t v9fs_readdir_data_size(V9fsString *name)
1851 c18e2f94 Sripathi Kodi
{
1852 5e4eaa79 Aneesh Kumar K.V
    /*
1853 5e4eaa79 Aneesh Kumar K.V
     * Size of each dirent on the wire: size of qid (13) + size of offset (8)
1854 5e4eaa79 Aneesh Kumar K.V
     * size of type (1) + size of name.size (2) + strlen(name.data)
1855 5e4eaa79 Aneesh Kumar K.V
     */
1856 5e4eaa79 Aneesh Kumar K.V
    return 24 + v9fs_string_size(name);
1857 c18e2f94 Sripathi Kodi
}
1858 c18e2f94 Sripathi Kodi
1859 5e4eaa79 Aneesh Kumar K.V
static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu,
1860 5e4eaa79 Aneesh Kumar K.V
                           V9fsFidState *fidp, int32_t max_count)
1861 c18e2f94 Sripathi Kodi
{
1862 c18e2f94 Sripathi Kodi
    size_t size;
1863 5e4eaa79 Aneesh Kumar K.V
    V9fsQID qid;
1864 5e4eaa79 Aneesh Kumar K.V
    V9fsString name;
1865 5e4eaa79 Aneesh Kumar K.V
    int len, err = 0;
1866 5e4eaa79 Aneesh Kumar K.V
    int32_t count = 0;
1867 5e4eaa79 Aneesh Kumar K.V
    off_t saved_dir_pos;
1868 5f524c1e Harsh Prateek Bora
    struct dirent *dent, *result;
1869 c18e2f94 Sripathi Kodi
1870 5e4eaa79 Aneesh Kumar K.V
    /* save the directory position */
1871 5e4eaa79 Aneesh Kumar K.V
    saved_dir_pos = v9fs_co_telldir(s, fidp);
1872 5e4eaa79 Aneesh Kumar K.V
    if (saved_dir_pos < 0) {
1873 5e4eaa79 Aneesh Kumar K.V
        return saved_dir_pos;
1874 5e4eaa79 Aneesh Kumar K.V
    }
1875 5f524c1e Harsh Prateek Bora
1876 5f524c1e Harsh Prateek Bora
    dent = g_malloc(sizeof(struct dirent));
1877 5f524c1e Harsh Prateek Bora
1878 5e4eaa79 Aneesh Kumar K.V
    while (1) {
1879 5f524c1e Harsh Prateek Bora
        err = v9fs_co_readdir_r(s, fidp, dent, &result);
1880 5f524c1e Harsh Prateek Bora
        if (err || !result) {
1881 5e4eaa79 Aneesh Kumar K.V
            break;
1882 5e4eaa79 Aneesh Kumar K.V
        }
1883 5e4eaa79 Aneesh Kumar K.V
        v9fs_string_init(&name);
1884 5e4eaa79 Aneesh Kumar K.V
        v9fs_string_sprintf(&name, "%s", dent->d_name);
1885 5e4eaa79 Aneesh Kumar K.V
        if ((count + v9fs_readdir_data_size(&name)) > max_count) {
1886 c18e2f94 Sripathi Kodi
            /* Ran out of buffer. Set dir back to old position and return */
1887 5e4eaa79 Aneesh Kumar K.V
            v9fs_co_seekdir(s, fidp, saved_dir_pos);
1888 5e4eaa79 Aneesh Kumar K.V
            v9fs_string_free(&name);
1889 5f524c1e Harsh Prateek Bora
            g_free(dent);
1890 5e4eaa79 Aneesh Kumar K.V
            return count;
1891 c18e2f94 Sripathi Kodi
        }
1892 5e4eaa79 Aneesh Kumar K.V
        /*
1893 5e4eaa79 Aneesh Kumar K.V
         * Fill up just the path field of qid because the client uses
1894 c18e2f94 Sripathi Kodi
         * only that. To fill the entire qid structure we will have
1895 c18e2f94 Sripathi Kodi
         * to stat each dirent found, which is expensive
1896 c18e2f94 Sripathi Kodi
         */
1897 5e4eaa79 Aneesh Kumar K.V
        size = MIN(sizeof(dent->d_ino), sizeof(qid.path));
1898 5e4eaa79 Aneesh Kumar K.V
        memcpy(&qid.path, &dent->d_ino, size);
1899 c18e2f94 Sripathi Kodi
        /* Fill the other fields with dummy values */
1900 5e4eaa79 Aneesh Kumar K.V
        qid.type = 0;
1901 5e4eaa79 Aneesh Kumar K.V
        qid.version = 0;
1902 c18e2f94 Sripathi Kodi
1903 5e4eaa79 Aneesh Kumar K.V
        /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1904 5e4eaa79 Aneesh Kumar K.V
        len = pdu_marshal(pdu, 11 + count, "Qqbs",
1905 5e4eaa79 Aneesh Kumar K.V
                          &qid, dent->d_off,
1906 5e4eaa79 Aneesh Kumar K.V
                          dent->d_type, &name);
1907 5e4eaa79 Aneesh Kumar K.V
        count += len;
1908 5e4eaa79 Aneesh Kumar K.V
        v9fs_string_free(&name);
1909 5e4eaa79 Aneesh Kumar K.V
        saved_dir_pos = dent->d_off;
1910 5e4eaa79 Aneesh Kumar K.V
    }
1911 5f524c1e Harsh Prateek Bora
    g_free(dent);
1912 5e4eaa79 Aneesh Kumar K.V
    if (err < 0) {
1913 5e4eaa79 Aneesh Kumar K.V
        return err;
1914 5e4eaa79 Aneesh Kumar K.V
    }
1915 5e4eaa79 Aneesh Kumar K.V
    return count;
1916 c18e2f94 Sripathi Kodi
}
1917 c18e2f94 Sripathi Kodi
1918 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_readdir(void *opaque)
1919 c18e2f94 Sripathi Kodi
{
1920 c18e2f94 Sripathi Kodi
    int32_t fid;
1921 5e4eaa79 Aneesh Kumar K.V
    V9fsFidState *fidp;
1922 5e4eaa79 Aneesh Kumar K.V
    ssize_t retval = 0;
1923 c18e2f94 Sripathi Kodi
    size_t offset = 7;
1924 5e4eaa79 Aneesh Kumar K.V
    int64_t initial_offset;
1925 5e4eaa79 Aneesh Kumar K.V
    int32_t count, max_count;
1926 5e4eaa79 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
1927 5e4eaa79 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
1928 c18e2f94 Sripathi Kodi
1929 5e4eaa79 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
1930 c18e2f94 Sripathi Kodi
1931 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
1932 84dfb926 Aneesh Kumar K.V
    if (fidp == NULL) {
1933 84dfb926 Aneesh Kumar K.V
        retval = -EINVAL;
1934 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
1935 84dfb926 Aneesh Kumar K.V
    }
1936 84dfb926 Aneesh Kumar K.V
    if (!fidp->fs.dir) {
1937 5e4eaa79 Aneesh Kumar K.V
        retval = -EINVAL;
1938 c18e2f94 Sripathi Kodi
        goto out;
1939 c18e2f94 Sripathi Kodi
    }
1940 5e4eaa79 Aneesh Kumar K.V
    if (initial_offset == 0) {
1941 5e4eaa79 Aneesh Kumar K.V
        v9fs_co_rewinddir(s, fidp);
1942 c18e2f94 Sripathi Kodi
    } else {
1943 5e4eaa79 Aneesh Kumar K.V
        v9fs_co_seekdir(s, fidp, initial_offset);
1944 c18e2f94 Sripathi Kodi
    }
1945 5e4eaa79 Aneesh Kumar K.V
    count = v9fs_do_readdir(s, pdu, fidp, max_count);
1946 5e4eaa79 Aneesh Kumar K.V
    if (count < 0) {
1947 5e4eaa79 Aneesh Kumar K.V
        retval = count;
1948 5e4eaa79 Aneesh Kumar K.V
        goto out;
1949 5e4eaa79 Aneesh Kumar K.V
    }
1950 5e4eaa79 Aneesh Kumar K.V
    retval = offset;
1951 5e4eaa79 Aneesh Kumar K.V
    retval += pdu_marshal(pdu, offset, "d", count);
1952 5e4eaa79 Aneesh Kumar K.V
    retval += count;
1953 c18e2f94 Sripathi Kodi
out:
1954 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
1955 84dfb926 Aneesh Kumar K.V
out_nofid:
1956 5e4eaa79 Aneesh Kumar K.V
    complete_pdu(s, pdu, retval);
1957 c18e2f94 Sripathi Kodi
}
1958 c18e2f94 Sripathi Kodi
1959 d7a90491 Aneesh Kumar K.V
static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
1960 d7a90491 Aneesh Kumar K.V
                            int64_t off, int32_t count,
1961 d7a90491 Aneesh Kumar K.V
                            struct iovec *sg, int cnt)
1962 10b468bd Aneesh Kumar K.V
{
1963 10b468bd Aneesh Kumar K.V
    int i, to_copy;
1964 10b468bd Aneesh Kumar K.V
    ssize_t err = 0;
1965 10b468bd Aneesh Kumar K.V
    int write_count;
1966 10b468bd Aneesh Kumar K.V
    int64_t xattr_len;
1967 d7a90491 Aneesh Kumar K.V
    size_t offset = 7;
1968 10b468bd Aneesh Kumar K.V
1969 d7a90491 Aneesh Kumar K.V
1970 d7a90491 Aneesh Kumar K.V
    xattr_len = fidp->fs.xattr.len;
1971 d7a90491 Aneesh Kumar K.V
    write_count = xattr_len - off;
1972 d7a90491 Aneesh Kumar K.V
    if (write_count > count) {
1973 d7a90491 Aneesh Kumar K.V
        write_count = count;
1974 10b468bd Aneesh Kumar K.V
    } else if (write_count < 0) {
1975 10b468bd Aneesh Kumar K.V
        /*
1976 10b468bd Aneesh Kumar K.V
         * write beyond XATTR value len specified in
1977 10b468bd Aneesh Kumar K.V
         * xattrcreate
1978 10b468bd Aneesh Kumar K.V
         */
1979 10b468bd Aneesh Kumar K.V
        err = -ENOSPC;
1980 10b468bd Aneesh Kumar K.V
        goto out;
1981 10b468bd Aneesh Kumar K.V
    }
1982 d7a90491 Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "d", write_count);
1983 d7a90491 Aneesh Kumar K.V
    err = offset;
1984 d7a90491 Aneesh Kumar K.V
    fidp->fs.xattr.copied_len += write_count;
1985 10b468bd Aneesh Kumar K.V
    /*
1986 10b468bd Aneesh Kumar K.V
     * Now copy the content from sg list
1987 10b468bd Aneesh Kumar K.V
     */
1988 d7a90491 Aneesh Kumar K.V
    for (i = 0; i < cnt; i++) {
1989 d7a90491 Aneesh Kumar K.V
        if (write_count > sg[i].iov_len) {
1990 d7a90491 Aneesh Kumar K.V
            to_copy = sg[i].iov_len;
1991 10b468bd Aneesh Kumar K.V
        } else {
1992 10b468bd Aneesh Kumar K.V
            to_copy = write_count;
1993 10b468bd Aneesh Kumar K.V
        }
1994 d7a90491 Aneesh Kumar K.V
        memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy);
1995 10b468bd Aneesh Kumar K.V
        /* updating vs->off since we are not using below */
1996 d7a90491 Aneesh Kumar K.V
        off += to_copy;
1997 10b468bd Aneesh Kumar K.V
        write_count -= to_copy;
1998 10b468bd Aneesh Kumar K.V
    }
1999 10b468bd Aneesh Kumar K.V
out:
2000 d7a90491 Aneesh Kumar K.V
    return err;
2001 10b468bd Aneesh Kumar K.V
}
2002 10b468bd Aneesh Kumar K.V
2003 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_write(void *opaque)
2004 9f107513 Anthony Liguori
{
2005 d7a90491 Aneesh Kumar K.V
    int cnt;
2006 d7a90491 Aneesh Kumar K.V
    ssize_t err;
2007 d7a90491 Aneesh Kumar K.V
    int32_t fid;
2008 d7a90491 Aneesh Kumar K.V
    int64_t off;
2009 d7a90491 Aneesh Kumar K.V
    int32_t count;
2010 d7a90491 Aneesh Kumar K.V
    int32_t len = 0;
2011 d7a90491 Aneesh Kumar K.V
    int32_t total = 0;
2012 d7a90491 Aneesh Kumar K.V
    size_t offset = 7;
2013 d7a90491 Aneesh Kumar K.V
    V9fsFidState *fidp;
2014 d7a90491 Aneesh Kumar K.V
    struct iovec iov[128]; /* FIXME: bad, bad, bad */
2015 d7a90491 Aneesh Kumar K.V
    struct iovec *sg = iov;
2016 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2017 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2018 8449360c Anthony Liguori
2019 d7a90491 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
2020 84dfb926 Aneesh Kumar K.V
2021 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2022 d7a90491 Aneesh Kumar K.V
    if (fidp == NULL) {
2023 8449360c Anthony Liguori
        err = -EINVAL;
2024 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2025 9f107513 Anthony Liguori
    }
2026 d7a90491 Aneesh Kumar K.V
    if (fidp->fid_type == P9_FID_FILE) {
2027 d7a90491 Aneesh Kumar K.V
        if (fidp->fs.fd == -1) {
2028 10b468bd Aneesh Kumar K.V
            err = -EINVAL;
2029 10b468bd Aneesh Kumar K.V
            goto out;
2030 10b468bd Aneesh Kumar K.V
        }
2031 d7a90491 Aneesh Kumar K.V
    } else if (fidp->fid_type == P9_FID_XATTR) {
2032 10b468bd Aneesh Kumar K.V
        /*
2033 10b468bd Aneesh Kumar K.V
         * setxattr operation
2034 10b468bd Aneesh Kumar K.V
         */
2035 d7a90491 Aneesh Kumar K.V
        err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt);
2036 d7a90491 Aneesh Kumar K.V
        goto out;
2037 10b468bd Aneesh Kumar K.V
    } else {
2038 8449360c Anthony Liguori
        err = -EINVAL;
2039 8449360c Anthony Liguori
        goto out;
2040 8449360c Anthony Liguori
    }
2041 d7a90491 Aneesh Kumar K.V
    sg = cap_sg(sg, count, &cnt);
2042 d7a90491 Aneesh Kumar K.V
    do {
2043 d7a90491 Aneesh Kumar K.V
        if (0) {
2044 d7a90491 Aneesh Kumar K.V
            print_sg(sg, cnt);
2045 56d15a53 Sanchit Garg
        }
2046 d7a90491 Aneesh Kumar K.V
        /* Loop in case of EINTR */
2047 d7a90491 Aneesh Kumar K.V
        do {
2048 d7a90491 Aneesh Kumar K.V
            len = v9fs_co_pwritev(s, fidp, sg, cnt, off);
2049 d7a90491 Aneesh Kumar K.V
            if (len >= 0) {
2050 d7a90491 Aneesh Kumar K.V
                off   += len;
2051 d7a90491 Aneesh Kumar K.V
                total += len;
2052 d7a90491 Aneesh Kumar K.V
            }
2053 d7a90491 Aneesh Kumar K.V
        } while (len == -EINTR);
2054 d7a90491 Aneesh Kumar K.V
        if (len < 0) {
2055 d7a90491 Aneesh Kumar K.V
            /* IO error return the error */
2056 d7a90491 Aneesh Kumar K.V
            err = len;
2057 d7a90491 Aneesh Kumar K.V
            goto out;
2058 d7a90491 Aneesh Kumar K.V
        }
2059 d7a90491 Aneesh Kumar K.V
        sg = adjust_sg(sg, len, &cnt);
2060 d7a90491 Aneesh Kumar K.V
    } while (total < count && len > 0);
2061 d7a90491 Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "d", total);
2062 d7a90491 Aneesh Kumar K.V
    err = offset;
2063 8449360c Anthony Liguori
out:
2064 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2065 84dfb926 Aneesh Kumar K.V
out_nofid:
2066 d7a90491 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2067 9f107513 Anthony Liguori
}
2068 9f107513 Anthony Liguori
2069 baaa86d9 Venkateswararao Jujjuri
static void v9fs_create(void *opaque)
2070 5e94c103 M. Mohan Kumar
{
2071 baaa86d9 Venkateswararao Jujjuri
    int32_t fid;
2072 baaa86d9 Venkateswararao Jujjuri
    int err = 0;
2073 baaa86d9 Venkateswararao Jujjuri
    size_t offset = 7;
2074 baaa86d9 Venkateswararao Jujjuri
    V9fsFidState *fidp;
2075 baaa86d9 Venkateswararao Jujjuri
    V9fsQID qid;
2076 baaa86d9 Venkateswararao Jujjuri
    int32_t perm;
2077 baaa86d9 Venkateswararao Jujjuri
    int8_t mode;
2078 baaa86d9 Venkateswararao Jujjuri
    struct stat stbuf;
2079 baaa86d9 Venkateswararao Jujjuri
    V9fsString name;
2080 baaa86d9 Venkateswararao Jujjuri
    V9fsString extension;
2081 baaa86d9 Venkateswararao Jujjuri
    V9fsString fullname;
2082 baaa86d9 Venkateswararao Jujjuri
    int iounit;
2083 baaa86d9 Venkateswararao Jujjuri
    V9fsPDU *pdu = opaque;
2084 c494dd6f Anthony Liguori
2085 baaa86d9 Venkateswararao Jujjuri
    v9fs_string_init(&fullname);
2086 c494dd6f Anthony Liguori
2087 baaa86d9 Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
2088 baaa86d9 Venkateswararao Jujjuri
                  &perm, &mode, &extension);
2089 c494dd6f Anthony Liguori
2090 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(pdu->s, fid);
2091 baaa86d9 Venkateswararao Jujjuri
    if (fidp == NULL) {
2092 baaa86d9 Venkateswararao Jujjuri
        err = -EINVAL;
2093 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2094 c494dd6f Anthony Liguori
    }
2095 c494dd6f Anthony Liguori
2096 baaa86d9 Venkateswararao Jujjuri
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
2097 baaa86d9 Venkateswararao Jujjuri
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
2098 baaa86d9 Venkateswararao Jujjuri
    if (!err) {
2099 baaa86d9 Venkateswararao Jujjuri
        err = -EEXIST;
2100 c494dd6f Anthony Liguori
        goto out;
2101 baaa86d9 Venkateswararao Jujjuri
    } else if (err != -ENOENT) {
2102 c494dd6f Anthony Liguori
        goto out;
2103 c494dd6f Anthony Liguori
    }
2104 baaa86d9 Venkateswararao Jujjuri
    if (perm & P9_STAT_MODE_DIR) {
2105 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_mkdir(pdu->s, fullname.data, perm & 0777,
2106 baaa86d9 Venkateswararao Jujjuri
                            fidp->uid, -1);
2107 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2108 baaa86d9 Venkateswararao Jujjuri
            goto out;
2109 baaa86d9 Venkateswararao Jujjuri
        }
2110 407fee0f Aneesh Kumar K.V
        v9fs_string_copy(&fidp->path, &fullname);
2111 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_opendir(pdu->s, fidp);
2112 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2113 baaa86d9 Venkateswararao Jujjuri
            goto out;
2114 baaa86d9 Venkateswararao Jujjuri
        }
2115 baaa86d9 Venkateswararao Jujjuri
        fidp->fid_type = P9_FID_DIR;
2116 baaa86d9 Venkateswararao Jujjuri
    } else if (perm & P9_STAT_MODE_SYMLINK) {
2117 3fa2a8d1 Venkateswararao Jujjuri
        err = v9fs_co_symlink(pdu->s, fidp, extension.data,
2118 baaa86d9 Venkateswararao Jujjuri
                              fullname.data, -1);
2119 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2120 baaa86d9 Venkateswararao Jujjuri
            goto out;
2121 baaa86d9 Venkateswararao Jujjuri
        }
2122 baaa86d9 Venkateswararao Jujjuri
    } else if (perm & P9_STAT_MODE_LINK) {
2123 baaa86d9 Venkateswararao Jujjuri
        int32_t nfid = atoi(extension.data);
2124 84dfb926 Aneesh Kumar K.V
        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
2125 c494dd6f Anthony Liguori
        if (nfidp == NULL) {
2126 baaa86d9 Venkateswararao Jujjuri
            err = -EINVAL;
2127 baaa86d9 Venkateswararao Jujjuri
            goto out;
2128 baaa86d9 Venkateswararao Jujjuri
        }
2129 ffd66876 Venkateswararao Jujjuri (JV)
        err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
2130 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2131 84dfb926 Aneesh Kumar K.V
            put_fid(pdu->s, nfidp);
2132 baaa86d9 Venkateswararao Jujjuri
            goto out;
2133 c494dd6f Anthony Liguori
        }
2134 84dfb926 Aneesh Kumar K.V
        put_fid(pdu->s, nfidp);
2135 baaa86d9 Venkateswararao Jujjuri
    } else if (perm & P9_STAT_MODE_DEVICE) {
2136 c494dd6f Anthony Liguori
        char ctype;
2137 c494dd6f Anthony Liguori
        uint32_t major, minor;
2138 c494dd6f Anthony Liguori
        mode_t nmode = 0;
2139 c494dd6f Anthony Liguori
2140 baaa86d9 Venkateswararao Jujjuri
        if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
2141 c494dd6f Anthony Liguori
            err = -errno;
2142 baaa86d9 Venkateswararao Jujjuri
            goto out;
2143 c494dd6f Anthony Liguori
        }
2144 c494dd6f Anthony Liguori
2145 c494dd6f Anthony Liguori
        switch (ctype) {
2146 c494dd6f Anthony Liguori
        case 'c':
2147 c494dd6f Anthony Liguori
            nmode = S_IFCHR;
2148 c494dd6f Anthony Liguori
            break;
2149 c494dd6f Anthony Liguori
        case 'b':
2150 c494dd6f Anthony Liguori
            nmode = S_IFBLK;
2151 c494dd6f Anthony Liguori
            break;
2152 c494dd6f Anthony Liguori
        default:
2153 c494dd6f Anthony Liguori
            err = -EIO;
2154 baaa86d9 Venkateswararao Jujjuri
            goto out;
2155 baaa86d9 Venkateswararao Jujjuri
        }
2156 c1568af5 Venkateswararao Jujjuri (JV)
2157 baaa86d9 Venkateswararao Jujjuri
        nmode |= perm & 0777;
2158 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
2159 baaa86d9 Venkateswararao Jujjuri
                            makedev(major, minor), nmode);
2160 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2161 baaa86d9 Venkateswararao Jujjuri
            goto out;
2162 baaa86d9 Venkateswararao Jujjuri
        }
2163 baaa86d9 Venkateswararao Jujjuri
    } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
2164 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
2165 baaa86d9 Venkateswararao Jujjuri
                            0, S_IFIFO | (perm & 0777));
2166 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2167 baaa86d9 Venkateswararao Jujjuri
            goto out;
2168 baaa86d9 Venkateswararao Jujjuri
        }
2169 baaa86d9 Venkateswararao Jujjuri
    } else if (perm & P9_STAT_MODE_SOCKET) {
2170 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1,
2171 baaa86d9 Venkateswararao Jujjuri
                            0, S_IFSOCK | (perm & 0777));
2172 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2173 baaa86d9 Venkateswararao Jujjuri
            goto out;
2174 baaa86d9 Venkateswararao Jujjuri
        }
2175 baaa86d9 Venkateswararao Jujjuri
    } else {
2176 baaa86d9 Venkateswararao Jujjuri
        err = v9fs_co_open2(pdu->s, fidp, fullname.data, -1,
2177 baaa86d9 Venkateswararao Jujjuri
                            omode_to_uflags(mode)|O_CREAT, perm);
2178 baaa86d9 Venkateswararao Jujjuri
        if (err < 0) {
2179 baaa86d9 Venkateswararao Jujjuri
            goto out;
2180 baaa86d9 Venkateswararao Jujjuri
        }
2181 baaa86d9 Venkateswararao Jujjuri
        fidp->fid_type = P9_FID_FILE;
2182 7a462745 Aneesh Kumar K.V
        fidp->open_flags = omode_to_uflags(mode);
2183 7a462745 Aneesh Kumar K.V
        if (fidp->open_flags & O_EXCL) {
2184 7a462745 Aneesh Kumar K.V
            /*
2185 7a462745 Aneesh Kumar K.V
             * We let the host file system do O_EXCL check
2186 7a462745 Aneesh Kumar K.V
             * We should not reclaim such fd
2187 7a462745 Aneesh Kumar K.V
             */
2188 7a462745 Aneesh Kumar K.V
            fidp->flags |= FID_NON_RECLAIMABLE;
2189 7a462745 Aneesh Kumar K.V
        }
2190 c494dd6f Anthony Liguori
    }
2191 baaa86d9 Venkateswararao Jujjuri
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
2192 baaa86d9 Venkateswararao Jujjuri
    if (err < 0) {
2193 baaa86d9 Venkateswararao Jujjuri
        fidp->fid_type = P9_FID_NONE;
2194 baaa86d9 Venkateswararao Jujjuri
        if (fidp->fs.fd) {
2195 9b54ffaa Aneesh Kumar K.V
            v9fs_co_close(pdu->s, fidp->fs.fd);
2196 baaa86d9 Venkateswararao Jujjuri
        }
2197 c494dd6f Anthony Liguori
        goto out;
2198 9f107513 Anthony Liguori
    }
2199 baaa86d9 Venkateswararao Jujjuri
    iounit = get_iounit(pdu->s, &fidp->path);
2200 baaa86d9 Venkateswararao Jujjuri
    v9fs_string_copy(&fidp->path, &fullname);
2201 baaa86d9 Venkateswararao Jujjuri
    stat_to_qid(&stbuf, &qid);
2202 baaa86d9 Venkateswararao Jujjuri
    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
2203 baaa86d9 Venkateswararao Jujjuri
    err = offset;
2204 c494dd6f Anthony Liguori
out:
2205 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, fidp);
2206 84dfb926 Aneesh Kumar K.V
out_nofid:
2207 baaa86d9 Venkateswararao Jujjuri
   complete_pdu(pdu->s, pdu, err);
2208 baaa86d9 Venkateswararao Jujjuri
   v9fs_string_free(&name);
2209 baaa86d9 Venkateswararao Jujjuri
   v9fs_string_free(&extension);
2210 baaa86d9 Venkateswararao Jujjuri
   v9fs_string_free(&fullname);
2211 9f107513 Anthony Liguori
}
2212 9f107513 Anthony Liguori
2213 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_symlink(void *opaque)
2214 08c60fc9 Venkateswararao Jujjuri (JV)
{
2215 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2216 3fa2a8d1 Venkateswararao Jujjuri
    V9fsString name;
2217 3fa2a8d1 Venkateswararao Jujjuri
    V9fsString symname;
2218 3fa2a8d1 Venkateswararao Jujjuri
    V9fsString fullname;
2219 3fa2a8d1 Venkateswararao Jujjuri
    V9fsFidState *dfidp;
2220 3fa2a8d1 Venkateswararao Jujjuri
    V9fsQID qid;
2221 3fa2a8d1 Venkateswararao Jujjuri
    struct stat stbuf;
2222 08c60fc9 Venkateswararao Jujjuri (JV)
    int32_t dfid;
2223 08c60fc9 Venkateswararao Jujjuri (JV)
    int err = 0;
2224 08c60fc9 Venkateswararao Jujjuri (JV)
    gid_t gid;
2225 3fa2a8d1 Venkateswararao Jujjuri
    size_t offset = 7;
2226 08c60fc9 Venkateswararao Jujjuri (JV)
2227 3fa2a8d1 Venkateswararao Jujjuri
    v9fs_string_init(&fullname);
2228 3fa2a8d1 Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
2229 08c60fc9 Venkateswararao Jujjuri (JV)
2230 84dfb926 Aneesh Kumar K.V
    dfidp = get_fid(pdu->s, dfid);
2231 3fa2a8d1 Venkateswararao Jujjuri
    if (dfidp == NULL) {
2232 08c60fc9 Venkateswararao Jujjuri (JV)
        err = -EINVAL;
2233 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2234 08c60fc9 Venkateswararao Jujjuri (JV)
    }
2235 08c60fc9 Venkateswararao Jujjuri (JV)
2236 3fa2a8d1 Venkateswararao Jujjuri
    v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
2237 3fa2a8d1 Venkateswararao Jujjuri
    err = v9fs_co_symlink(pdu->s, dfidp, symname.data, fullname.data, gid);
2238 3fa2a8d1 Venkateswararao Jujjuri
    if (err < 0) {
2239 3fa2a8d1 Venkateswararao Jujjuri
        goto out;
2240 3fa2a8d1 Venkateswararao Jujjuri
    }
2241 3fa2a8d1 Venkateswararao Jujjuri
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
2242 3fa2a8d1 Venkateswararao Jujjuri
    if (err < 0) {
2243 3fa2a8d1 Venkateswararao Jujjuri
        goto out;
2244 3fa2a8d1 Venkateswararao Jujjuri
    }
2245 3fa2a8d1 Venkateswararao Jujjuri
    stat_to_qid(&stbuf, &qid);
2246 3fa2a8d1 Venkateswararao Jujjuri
    offset += pdu_marshal(pdu, offset, "Q", &qid);
2247 3fa2a8d1 Venkateswararao Jujjuri
    err = offset;
2248 08c60fc9 Venkateswararao Jujjuri (JV)
out:
2249 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, dfidp);
2250 84dfb926 Aneesh Kumar K.V
out_nofid:
2251 3fa2a8d1 Venkateswararao Jujjuri
    complete_pdu(pdu->s, pdu, err);
2252 3fa2a8d1 Venkateswararao Jujjuri
    v9fs_string_free(&name);
2253 3fa2a8d1 Venkateswararao Jujjuri
    v9fs_string_free(&symname);
2254 3fa2a8d1 Venkateswararao Jujjuri
    v9fs_string_free(&fullname);
2255 08c60fc9 Venkateswararao Jujjuri (JV)
}
2256 08c60fc9 Venkateswararao Jujjuri (JV)
2257 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_flush(void *opaque)
2258 9f107513 Anthony Liguori
{
2259 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2260 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2261 9c5e9d89 Anthony Liguori
    /* A nop call with no return */
2262 9c5e9d89 Anthony Liguori
    complete_pdu(s, pdu, 7);
2263 ff06030f Venkateswararao Jujjuri (JV)
    return;
2264 9f107513 Anthony Liguori
}
2265 9f107513 Anthony Liguori
2266 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_link(void *opaque)
2267 b2c224be Venkateswararao Jujjuri (JV)
{
2268 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2269 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2270 b2c224be Venkateswararao Jujjuri (JV)
    int32_t dfid, oldfid;
2271 b2c224be Venkateswararao Jujjuri (JV)
    V9fsFidState *dfidp, *oldfidp;
2272 b2c224be Venkateswararao Jujjuri (JV)
    V9fsString name, fullname;
2273 b2c224be Venkateswararao Jujjuri (JV)
    size_t offset = 7;
2274 b2c224be Venkateswararao Jujjuri (JV)
    int err = 0;
2275 b2c224be Venkateswararao Jujjuri (JV)
2276 b2c224be Venkateswararao Jujjuri (JV)
    v9fs_string_init(&fullname);
2277 b2c224be Venkateswararao Jujjuri (JV)
2278 b2c224be Venkateswararao Jujjuri (JV)
    pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
2279 b2c224be Venkateswararao Jujjuri (JV)
2280 84dfb926 Aneesh Kumar K.V
    dfidp = get_fid(s, dfid);
2281 b2c224be Venkateswararao Jujjuri (JV)
    if (dfidp == NULL) {
2282 ffd66876 Venkateswararao Jujjuri (JV)
        err = -ENOENT;
2283 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2284 b2c224be Venkateswararao Jujjuri (JV)
    }
2285 b2c224be Venkateswararao Jujjuri (JV)
2286 84dfb926 Aneesh Kumar K.V
    oldfidp = get_fid(s, oldfid);
2287 b2c224be Venkateswararao Jujjuri (JV)
    if (oldfidp == NULL) {
2288 ffd66876 Venkateswararao Jujjuri (JV)
        err = -ENOENT;
2289 b2c224be Venkateswararao Jujjuri (JV)
        goto out;
2290 b2c224be Venkateswararao Jujjuri (JV)
    }
2291 b2c224be Venkateswararao Jujjuri (JV)
2292 b2c224be Venkateswararao Jujjuri (JV)
    v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
2293 ffd66876 Venkateswararao Jujjuri (JV)
    err = v9fs_co_link(s, &oldfidp->path, &fullname);
2294 ffd66876 Venkateswararao Jujjuri (JV)
    if (!err) {
2295 ffd66876 Venkateswararao Jujjuri (JV)
        err = offset;
2296 b2c224be Venkateswararao Jujjuri (JV)
    }
2297 b2c224be Venkateswararao Jujjuri (JV)
    v9fs_string_free(&fullname);
2298 b2c224be Venkateswararao Jujjuri (JV)
2299 b2c224be Venkateswararao Jujjuri (JV)
out:
2300 84dfb926 Aneesh Kumar K.V
    put_fid(s, dfidp);
2301 84dfb926 Aneesh Kumar K.V
out_nofid:
2302 b2c224be Venkateswararao Jujjuri (JV)
    v9fs_string_free(&name);
2303 b2c224be Venkateswararao Jujjuri (JV)
    complete_pdu(s, pdu, err);
2304 b2c224be Venkateswararao Jujjuri (JV)
}
2305 b2c224be Venkateswararao Jujjuri (JV)
2306 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_remove(void *opaque)
2307 9f107513 Anthony Liguori
{
2308 5bae1900 Anthony Liguori
    int32_t fid;
2309 5bae1900 Anthony Liguori
    int err = 0;
2310 ae1ef571 Venkateswararao Jujjuri
    size_t offset = 7;
2311 ae1ef571 Venkateswararao Jujjuri
    V9fsFidState *fidp;
2312 ae1ef571 Venkateswararao Jujjuri
    V9fsPDU *pdu = opaque;
2313 5bae1900 Anthony Liguori
2314 ae1ef571 Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "d", &fid);
2315 5bae1900 Anthony Liguori
2316 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(pdu->s, fid);
2317 ae1ef571 Venkateswararao Jujjuri
    if (fidp == NULL) {
2318 5bae1900 Anthony Liguori
        err = -EINVAL;
2319 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2320 9f107513 Anthony Liguori
    }
2321 7a462745 Aneesh Kumar K.V
    /*
2322 7a462745 Aneesh Kumar K.V
     * IF the file is unlinked, we cannot reopen
2323 7a462745 Aneesh Kumar K.V
     * the file later. So don't reclaim fd
2324 7a462745 Aneesh Kumar K.V
     */
2325 7a462745 Aneesh Kumar K.V
    err = v9fs_mark_fids_unreclaim(pdu->s, &fidp->path);
2326 7a462745 Aneesh Kumar K.V
    if (err < 0) {
2327 7a462745 Aneesh Kumar K.V
        goto out_err;
2328 7a462745 Aneesh Kumar K.V
    }
2329 ae1ef571 Venkateswararao Jujjuri
    err = v9fs_co_remove(pdu->s, &fidp->path);
2330 ae1ef571 Venkateswararao Jujjuri
    if (!err) {
2331 ae1ef571 Venkateswararao Jujjuri
        err = offset;
2332 ae1ef571 Venkateswararao Jujjuri
    }
2333 7a462745 Aneesh Kumar K.V
out_err:
2334 ae1ef571 Venkateswararao Jujjuri
    /* For TREMOVE we need to clunk the fid even on failed remove */
2335 84dfb926 Aneesh Kumar K.V
    clunk_fid(pdu->s, fidp->fid);
2336 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, fidp);
2337 84dfb926 Aneesh Kumar K.V
out_nofid:
2338 ae1ef571 Venkateswararao Jujjuri
    complete_pdu(pdu->s, pdu, err);
2339 9f107513 Anthony Liguori
}
2340 9f107513 Anthony Liguori
2341 7834cf77 Aneesh Kumar K.V
static void v9fs_unlinkat(void *opaque)
2342 7834cf77 Aneesh Kumar K.V
{
2343 7834cf77 Aneesh Kumar K.V
    int err = 0;
2344 7834cf77 Aneesh Kumar K.V
    V9fsString name;
2345 7834cf77 Aneesh Kumar K.V
    int32_t dfid, flags;
2346 7834cf77 Aneesh Kumar K.V
    size_t offset = 7;
2347 7834cf77 Aneesh Kumar K.V
    V9fsFidState *dfidp;
2348 7834cf77 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2349 7834cf77 Aneesh Kumar K.V
    V9fsString full_name;
2350 7834cf77 Aneesh Kumar K.V
2351 7834cf77 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
2352 7834cf77 Aneesh Kumar K.V
2353 7834cf77 Aneesh Kumar K.V
    dfidp = get_fid(pdu->s, dfid);
2354 7834cf77 Aneesh Kumar K.V
    if (dfidp == NULL) {
2355 7834cf77 Aneesh Kumar K.V
        err = -EINVAL;
2356 7834cf77 Aneesh Kumar K.V
        goto out_nofid;
2357 7834cf77 Aneesh Kumar K.V
    }
2358 7834cf77 Aneesh Kumar K.V
    v9fs_string_init(&full_name);
2359 7834cf77 Aneesh Kumar K.V
    v9fs_string_sprintf(&full_name, "%s/%s", dfidp->path.data, name.data);
2360 7834cf77 Aneesh Kumar K.V
    /*
2361 7834cf77 Aneesh Kumar K.V
     * IF the file is unlinked, we cannot reopen
2362 7834cf77 Aneesh Kumar K.V
     * the file later. So don't reclaim fd
2363 7834cf77 Aneesh Kumar K.V
     */
2364 7834cf77 Aneesh Kumar K.V
    err = v9fs_mark_fids_unreclaim(pdu->s, &full_name);
2365 7834cf77 Aneesh Kumar K.V
    if (err < 0) {
2366 7834cf77 Aneesh Kumar K.V
        goto out_err;
2367 7834cf77 Aneesh Kumar K.V
    }
2368 7834cf77 Aneesh Kumar K.V
    err = v9fs_co_remove(pdu->s, &full_name);
2369 7834cf77 Aneesh Kumar K.V
    if (!err) {
2370 7834cf77 Aneesh Kumar K.V
        err = offset;
2371 7834cf77 Aneesh Kumar K.V
    }
2372 7834cf77 Aneesh Kumar K.V
out_err:
2373 7834cf77 Aneesh Kumar K.V
    put_fid(pdu->s, dfidp);
2374 7834cf77 Aneesh Kumar K.V
    v9fs_string_free(&full_name);
2375 7834cf77 Aneesh Kumar K.V
out_nofid:
2376 7834cf77 Aneesh Kumar K.V
    complete_pdu(pdu->s, pdu, err);
2377 7834cf77 Aneesh Kumar K.V
    v9fs_string_free(&name);
2378 7834cf77 Aneesh Kumar K.V
}
2379 7834cf77 Aneesh Kumar K.V
2380 930b1e17 Aneesh Kumar K.V
static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
2381 930b1e17 Aneesh Kumar K.V
                                int32_t newdirfid, V9fsString *name)
2382 8cf89e00 Anthony Liguori
{
2383 930b1e17 Aneesh Kumar K.V
    char *end;
2384 c7b4b0b3 M. Mohan Kumar
    int err = 0;
2385 84dfb926 Aneesh Kumar K.V
    V9fsFidState *dirfidp = NULL;
2386 c7b4b0b3 M. Mohan Kumar
    char *old_name, *new_name;
2387 8cf89e00 Anthony Liguori
2388 930b1e17 Aneesh Kumar K.V
    if (newdirfid != -1) {
2389 84dfb926 Aneesh Kumar K.V
        dirfidp = get_fid(s, newdirfid);
2390 c7b4b0b3 M. Mohan Kumar
        if (dirfidp == NULL) {
2391 c7b4b0b3 M. Mohan Kumar
            err = -ENOENT;
2392 84dfb926 Aneesh Kumar K.V
            goto out_nofid;
2393 c7b4b0b3 M. Mohan Kumar
        }
2394 d62dbb51 Aneesh Kumar K.V
        BUG_ON(dirfidp->fid_type != P9_FID_NONE);
2395 8cf89e00 Anthony Liguori
2396 7267c094 Anthony Liguori
        new_name = g_malloc0(dirfidp->path.size + name->size + 2);
2397 c7b4b0b3 M. Mohan Kumar
2398 c7b4b0b3 M. Mohan Kumar
        strcpy(new_name, dirfidp->path.data);
2399 c7b4b0b3 M. Mohan Kumar
        strcat(new_name, "/");
2400 930b1e17 Aneesh Kumar K.V
        strcat(new_name + dirfidp->path.size, name->data);
2401 c7b4b0b3 M. Mohan Kumar
    } else {
2402 930b1e17 Aneesh Kumar K.V
        old_name = fidp->path.data;
2403 8cf89e00 Anthony Liguori
        end = strrchr(old_name, '/');
2404 8cf89e00 Anthony Liguori
        if (end) {
2405 8cf89e00 Anthony Liguori
            end++;
2406 8cf89e00 Anthony Liguori
        } else {
2407 8cf89e00 Anthony Liguori
            end = old_name;
2408 8cf89e00 Anthony Liguori
        }
2409 7267c094 Anthony Liguori
        new_name = g_malloc0(end - old_name + name->size + 1);
2410 8cf89e00 Anthony Liguori
2411 c7b4b0b3 M. Mohan Kumar
        strncat(new_name, old_name, end - old_name);
2412 930b1e17 Aneesh Kumar K.V
        strncat(new_name + (end - old_name), name->data, name->size);
2413 c7b4b0b3 M. Mohan Kumar
    }
2414 8cf89e00 Anthony Liguori
2415 930b1e17 Aneesh Kumar K.V
    v9fs_string_free(name);
2416 930b1e17 Aneesh Kumar K.V
    name->data = new_name;
2417 930b1e17 Aneesh Kumar K.V
    name->size = strlen(new_name);
2418 8cf89e00 Anthony Liguori
2419 930b1e17 Aneesh Kumar K.V
    if (strcmp(new_name, fidp->path.data) != 0) {
2420 930b1e17 Aneesh Kumar K.V
        err = v9fs_co_rename(s, &fidp->path, name);
2421 930b1e17 Aneesh Kumar K.V
        if (err < 0) {
2422 930b1e17 Aneesh Kumar K.V
            goto out;
2423 930b1e17 Aneesh Kumar K.V
        }
2424 930b1e17 Aneesh Kumar K.V
        V9fsFidState *tfidp;
2425 930b1e17 Aneesh Kumar K.V
        /*
2426 930b1e17 Aneesh Kumar K.V
         * Fixup fid's pointing to the old name to
2427 930b1e17 Aneesh Kumar K.V
         * start pointing to the new name
2428 930b1e17 Aneesh Kumar K.V
         */
2429 930b1e17 Aneesh Kumar K.V
        for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2430 930b1e17 Aneesh Kumar K.V
            if (fidp == tfidp) {
2431 930b1e17 Aneesh Kumar K.V
                /*
2432 930b1e17 Aneesh Kumar K.V
                 * we replace name of this fid towards the end
2433 930b1e17 Aneesh Kumar K.V
                 * so that our below strcmp will work
2434 930b1e17 Aneesh Kumar K.V
                 */
2435 930b1e17 Aneesh Kumar K.V
                continue;
2436 930b1e17 Aneesh Kumar K.V
            }
2437 930b1e17 Aneesh Kumar K.V
            if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) {
2438 930b1e17 Aneesh Kumar K.V
                /* replace the name */
2439 930b1e17 Aneesh Kumar K.V
                v9fs_fix_path(&tfidp->path, name, strlen(fidp->path.data));
2440 8cf89e00 Anthony Liguori
            }
2441 8cf89e00 Anthony Liguori
        }
2442 930b1e17 Aneesh Kumar K.V
        v9fs_string_copy(&fidp->path, name);
2443 8cf89e00 Anthony Liguori
    }
2444 c7b4b0b3 M. Mohan Kumar
out:
2445 84dfb926 Aneesh Kumar K.V
    if (dirfidp) {
2446 84dfb926 Aneesh Kumar K.V
        put_fid(s, dirfidp);
2447 84dfb926 Aneesh Kumar K.V
    }
2448 84dfb926 Aneesh Kumar K.V
out_nofid:
2449 c7b4b0b3 M. Mohan Kumar
    return err;
2450 c7b4b0b3 M. Mohan Kumar
}
2451 c7b4b0b3 M. Mohan Kumar
2452 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_rename(void *opaque)
2453 c7b4b0b3 M. Mohan Kumar
{
2454 c7b4b0b3 M. Mohan Kumar
    int32_t fid;
2455 c7b4b0b3 M. Mohan Kumar
    ssize_t err = 0;
2456 930b1e17 Aneesh Kumar K.V
    size_t offset = 7;
2457 930b1e17 Aneesh Kumar K.V
    V9fsString name;
2458 930b1e17 Aneesh Kumar K.V
    int32_t newdirfid;
2459 930b1e17 Aneesh Kumar K.V
    V9fsFidState *fidp;
2460 930b1e17 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2461 930b1e17 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
2462 c7b4b0b3 M. Mohan Kumar
2463 930b1e17 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
2464 c7b4b0b3 M. Mohan Kumar
2465 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2466 930b1e17 Aneesh Kumar K.V
    if (fidp == NULL) {
2467 c7b4b0b3 M. Mohan Kumar
        err = -ENOENT;
2468 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2469 c7b4b0b3 M. Mohan Kumar
    }
2470 930b1e17 Aneesh Kumar K.V
    BUG_ON(fidp->fid_type != P9_FID_NONE);
2471 c7b4b0b3 M. Mohan Kumar
2472 930b1e17 Aneesh Kumar K.V
    err = v9fs_complete_rename(s, fidp, newdirfid, &name);
2473 930b1e17 Aneesh Kumar K.V
    if (!err) {
2474 930b1e17 Aneesh Kumar K.V
        err = offset;
2475 930b1e17 Aneesh Kumar K.V
    }
2476 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2477 84dfb926 Aneesh Kumar K.V
out_nofid:
2478 930b1e17 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2479 930b1e17 Aneesh Kumar K.V
    v9fs_string_free(&name);
2480 c7b4b0b3 M. Mohan Kumar
}
2481 c7b4b0b3 M. Mohan Kumar
2482 89bf6593 Aneesh Kumar K.V
static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid,
2483 89bf6593 Aneesh Kumar K.V
                                  V9fsString *old_name, int32_t newdirfid,
2484 89bf6593 Aneesh Kumar K.V
                                  V9fsString *new_name)
2485 89bf6593 Aneesh Kumar K.V
{
2486 89bf6593 Aneesh Kumar K.V
    int err = 0;
2487 89bf6593 Aneesh Kumar K.V
    V9fsString old_full_name, new_full_name;
2488 89bf6593 Aneesh Kumar K.V
    V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL;
2489 89bf6593 Aneesh Kumar K.V
2490 89bf6593 Aneesh Kumar K.V
    olddirfidp = get_fid(s, olddirfid);
2491 89bf6593 Aneesh Kumar K.V
    if (olddirfidp == NULL) {
2492 89bf6593 Aneesh Kumar K.V
        err = -ENOENT;
2493 89bf6593 Aneesh Kumar K.V
        goto out;
2494 89bf6593 Aneesh Kumar K.V
    }
2495 89bf6593 Aneesh Kumar K.V
    v9fs_string_init(&old_full_name);
2496 89bf6593 Aneesh Kumar K.V
    v9fs_string_init(&new_full_name);
2497 89bf6593 Aneesh Kumar K.V
2498 89bf6593 Aneesh Kumar K.V
    v9fs_string_sprintf(&old_full_name, "%s/%s",
2499 89bf6593 Aneesh Kumar K.V
                        olddirfidp->path.data, old_name->data);
2500 89bf6593 Aneesh Kumar K.V
    if (newdirfid != -1) {
2501 89bf6593 Aneesh Kumar K.V
        newdirfidp = get_fid(s, newdirfid);
2502 89bf6593 Aneesh Kumar K.V
        if (newdirfidp == NULL) {
2503 89bf6593 Aneesh Kumar K.V
            err = -ENOENT;
2504 89bf6593 Aneesh Kumar K.V
            goto out;
2505 89bf6593 Aneesh Kumar K.V
        }
2506 89bf6593 Aneesh Kumar K.V
        v9fs_string_sprintf(&new_full_name, "%s/%s",
2507 89bf6593 Aneesh Kumar K.V
                            newdirfidp->path.data, new_name->data);
2508 89bf6593 Aneesh Kumar K.V
    } else {
2509 89bf6593 Aneesh Kumar K.V
        v9fs_string_sprintf(&new_full_name, "%s/%s",
2510 89bf6593 Aneesh Kumar K.V
                            olddirfidp->path.data, new_name->data);
2511 89bf6593 Aneesh Kumar K.V
    }
2512 89bf6593 Aneesh Kumar K.V
2513 89bf6593 Aneesh Kumar K.V
    if (strcmp(old_full_name.data, new_full_name.data) != 0) {
2514 89bf6593 Aneesh Kumar K.V
        V9fsFidState *tfidp;
2515 89bf6593 Aneesh Kumar K.V
        err = v9fs_co_rename(s, &old_full_name, &new_full_name);
2516 89bf6593 Aneesh Kumar K.V
        if (err < 0) {
2517 89bf6593 Aneesh Kumar K.V
            goto out;
2518 89bf6593 Aneesh Kumar K.V
        }
2519 89bf6593 Aneesh Kumar K.V
        /*
2520 89bf6593 Aneesh Kumar K.V
         * Fixup fid's pointing to the old name to
2521 89bf6593 Aneesh Kumar K.V
         * start pointing to the new name
2522 89bf6593 Aneesh Kumar K.V
         */
2523 89bf6593 Aneesh Kumar K.V
        for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2524 89bf6593 Aneesh Kumar K.V
            if (v9fs_path_is_ancestor(&old_full_name, &tfidp->path)) {
2525 89bf6593 Aneesh Kumar K.V
                /* replace the name */
2526 89bf6593 Aneesh Kumar K.V
                v9fs_fix_path(&tfidp->path, &new_full_name, old_full_name.size);
2527 89bf6593 Aneesh Kumar K.V
            }
2528 89bf6593 Aneesh Kumar K.V
        }
2529 89bf6593 Aneesh Kumar K.V
    }
2530 89bf6593 Aneesh Kumar K.V
out:
2531 89bf6593 Aneesh Kumar K.V
    if (olddirfidp) {
2532 89bf6593 Aneesh Kumar K.V
        put_fid(s, olddirfidp);
2533 89bf6593 Aneesh Kumar K.V
    }
2534 89bf6593 Aneesh Kumar K.V
    if (newdirfidp) {
2535 89bf6593 Aneesh Kumar K.V
        put_fid(s, newdirfidp);
2536 89bf6593 Aneesh Kumar K.V
    }
2537 89bf6593 Aneesh Kumar K.V
    v9fs_string_free(&old_full_name);
2538 89bf6593 Aneesh Kumar K.V
    v9fs_string_free(&new_full_name);
2539 89bf6593 Aneesh Kumar K.V
    return err;
2540 89bf6593 Aneesh Kumar K.V
}
2541 89bf6593 Aneesh Kumar K.V
2542 89bf6593 Aneesh Kumar K.V
static void v9fs_renameat(void *opaque)
2543 89bf6593 Aneesh Kumar K.V
{
2544 89bf6593 Aneesh Kumar K.V
    ssize_t err = 0;
2545 89bf6593 Aneesh Kumar K.V
    size_t offset = 7;
2546 89bf6593 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2547 89bf6593 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
2548 89bf6593 Aneesh Kumar K.V
    int32_t olddirfid, newdirfid;
2549 89bf6593 Aneesh Kumar K.V
    V9fsString old_name, new_name;
2550 89bf6593 Aneesh Kumar K.V
2551 89bf6593 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
2552 89bf6593 Aneesh Kumar K.V
                  &old_name, &newdirfid, &new_name);
2553 89bf6593 Aneesh Kumar K.V
2554 89bf6593 Aneesh Kumar K.V
    err = v9fs_complete_renameat(s, olddirfid, &old_name, newdirfid, &new_name);
2555 89bf6593 Aneesh Kumar K.V
    if (!err) {
2556 89bf6593 Aneesh Kumar K.V
        err = offset;
2557 89bf6593 Aneesh Kumar K.V
    }
2558 89bf6593 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2559 89bf6593 Aneesh Kumar K.V
    v9fs_string_free(&old_name);
2560 89bf6593 Aneesh Kumar K.V
    v9fs_string_free(&new_name);
2561 89bf6593 Aneesh Kumar K.V
}
2562 89bf6593 Aneesh Kumar K.V
2563 b81d685e Aneesh Kumar K.V
static void v9fs_wstat(void *opaque)
2564 8cf89e00 Anthony Liguori
{
2565 b81d685e Aneesh Kumar K.V
    int32_t fid;
2566 b81d685e Aneesh Kumar K.V
    int err = 0;
2567 b81d685e Aneesh Kumar K.V
    int16_t unused;
2568 b81d685e Aneesh Kumar K.V
    V9fsStat v9stat;
2569 b81d685e Aneesh Kumar K.V
    size_t offset = 7;
2570 b81d685e Aneesh Kumar K.V
    struct stat stbuf;
2571 b81d685e Aneesh Kumar K.V
    V9fsFidState *fidp;
2572 b81d685e Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2573 b81d685e Aneesh Kumar K.V
    V9fsState *s = pdu->s;
2574 8cf89e00 Anthony Liguori
2575 b81d685e Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
2576 84dfb926 Aneesh Kumar K.V
2577 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2578 b81d685e Aneesh Kumar K.V
    if (fidp == NULL) {
2579 b81d685e Aneesh Kumar K.V
        err = -EINVAL;
2580 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2581 8cf89e00 Anthony Liguori
    }
2582 b81d685e Aneesh Kumar K.V
    /* do we need to sync the file? */
2583 b81d685e Aneesh Kumar K.V
    if (donttouch_stat(&v9stat)) {
2584 b81d685e Aneesh Kumar K.V
        err = v9fs_co_fsync(s, fidp, 0);
2585 8cf89e00 Anthony Liguori
        goto out;
2586 8cf89e00 Anthony Liguori
    }
2587 b81d685e Aneesh Kumar K.V
    if (v9stat.mode != -1) {
2588 b81d685e Aneesh Kumar K.V
        uint32_t v9_mode;
2589 b81d685e Aneesh Kumar K.V
        err = v9fs_co_lstat(s, &fidp->path, &stbuf);
2590 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2591 b81d685e Aneesh Kumar K.V
            goto out;
2592 b81d685e Aneesh Kumar K.V
        }
2593 b81d685e Aneesh Kumar K.V
        v9_mode = stat_to_v9mode(&stbuf);
2594 b81d685e Aneesh Kumar K.V
        if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
2595 b81d685e Aneesh Kumar K.V
            (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
2596 b81d685e Aneesh Kumar K.V
            /* Attempting to change the type */
2597 b81d685e Aneesh Kumar K.V
            err = -EIO;
2598 b81d685e Aneesh Kumar K.V
            goto out;
2599 b81d685e Aneesh Kumar K.V
        }
2600 b81d685e Aneesh Kumar K.V
        err = v9fs_co_chmod(s, &fidp->path,
2601 b81d685e Aneesh Kumar K.V
                            v9mode_to_mode(v9stat.mode,
2602 b81d685e Aneesh Kumar K.V
                                           &v9stat.extension));
2603 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2604 b81d685e Aneesh Kumar K.V
            goto out;
2605 b81d685e Aneesh Kumar K.V
        }
2606 b81d685e Aneesh Kumar K.V
    }
2607 b81d685e Aneesh Kumar K.V
    if (v9stat.mtime != -1 || v9stat.atime != -1) {
2608 8fc39ae4 Sripathi Kodi
        struct timespec times[2];
2609 b81d685e Aneesh Kumar K.V
        if (v9stat.atime != -1) {
2610 b81d685e Aneesh Kumar K.V
            times[0].tv_sec = v9stat.atime;
2611 8fc39ae4 Sripathi Kodi
            times[0].tv_nsec = 0;
2612 8fc39ae4 Sripathi Kodi
        } else {
2613 8fc39ae4 Sripathi Kodi
            times[0].tv_nsec = UTIME_OMIT;
2614 8fc39ae4 Sripathi Kodi
        }
2615 b81d685e Aneesh Kumar K.V
        if (v9stat.mtime != -1) {
2616 b81d685e Aneesh Kumar K.V
            times[1].tv_sec = v9stat.mtime;
2617 8fc39ae4 Sripathi Kodi
            times[1].tv_nsec = 0;
2618 8fc39ae4 Sripathi Kodi
        } else {
2619 8fc39ae4 Sripathi Kodi
            times[1].tv_nsec = UTIME_OMIT;
2620 8fc39ae4 Sripathi Kodi
        }
2621 b81d685e Aneesh Kumar K.V
        err = v9fs_co_utimensat(s, &fidp->path, times);
2622 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2623 b81d685e Aneesh Kumar K.V
            goto out;
2624 8cf89e00 Anthony Liguori
        }
2625 8cf89e00 Anthony Liguori
    }
2626 b81d685e Aneesh Kumar K.V
    if (v9stat.n_gid != -1 || v9stat.n_uid != -1) {
2627 b81d685e Aneesh Kumar K.V
        err = v9fs_co_chown(s, &fidp->path, v9stat.n_uid, v9stat.n_gid);
2628 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2629 8cf89e00 Anthony Liguori
            goto out;
2630 b81d685e Aneesh Kumar K.V
        }
2631 8cf89e00 Anthony Liguori
    }
2632 b81d685e Aneesh Kumar K.V
    if (v9stat.name.size != 0) {
2633 b81d685e Aneesh Kumar K.V
        err = v9fs_complete_rename(s, fidp, -1, &v9stat.name);
2634 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2635 b81d685e Aneesh Kumar K.V
            goto out;
2636 b81d685e Aneesh Kumar K.V
        }
2637 8cf89e00 Anthony Liguori
    }
2638 b81d685e Aneesh Kumar K.V
    if (v9stat.length != -1) {
2639 b81d685e Aneesh Kumar K.V
        err = v9fs_co_truncate(s, &fidp->path, v9stat.length);
2640 b81d685e Aneesh Kumar K.V
        if (err < 0) {
2641 b81d685e Aneesh Kumar K.V
            goto out;
2642 b81d685e Aneesh Kumar K.V
        }
2643 8cf89e00 Anthony Liguori
    }
2644 b81d685e Aneesh Kumar K.V
    err = offset;
2645 8cf89e00 Anthony Liguori
out:
2646 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2647 84dfb926 Aneesh Kumar K.V
out_nofid:
2648 b81d685e Aneesh Kumar K.V
    v9fs_stat_free(&v9stat);
2649 b81d685e Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2650 9f107513 Anthony Liguori
}
2651 9f107513 Anthony Liguori
2652 88a4763e Aneesh Kumar K.V
static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
2653 88a4763e Aneesh Kumar K.V
{
2654 88a4763e Aneesh Kumar K.V
    uint32_t f_type;
2655 88a4763e Aneesh Kumar K.V
    uint32_t f_bsize;
2656 88a4763e Aneesh Kumar K.V
    uint64_t f_blocks;
2657 88a4763e Aneesh Kumar K.V
    uint64_t f_bfree;
2658 88a4763e Aneesh Kumar K.V
    uint64_t f_bavail;
2659 88a4763e Aneesh Kumar K.V
    uint64_t f_files;
2660 88a4763e Aneesh Kumar K.V
    uint64_t f_ffree;
2661 88a4763e Aneesh Kumar K.V
    uint64_t fsid_val;
2662 88a4763e Aneesh Kumar K.V
    uint32_t f_namelen;
2663 88a4763e Aneesh Kumar K.V
    size_t offset = 7;
2664 5e94c103 M. Mohan Kumar
    int32_t bsize_factor;
2665 5e94c103 M. Mohan Kumar
2666 5e94c103 M. Mohan Kumar
    /*
2667 5e94c103 M. Mohan Kumar
     * compute bsize factor based on host file system block size
2668 5e94c103 M. Mohan Kumar
     * and client msize
2669 5e94c103 M. Mohan Kumar
     */
2670 88a4763e Aneesh Kumar K.V
    bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize;
2671 5e94c103 M. Mohan Kumar
    if (!bsize_factor) {
2672 5e94c103 M. Mohan Kumar
        bsize_factor = 1;
2673 5e94c103 M. Mohan Kumar
    }
2674 88a4763e Aneesh Kumar K.V
    f_type  = stbuf->f_type;
2675 88a4763e Aneesh Kumar K.V
    f_bsize = stbuf->f_bsize;
2676 88a4763e Aneesh Kumar K.V
    f_bsize *= bsize_factor;
2677 5e94c103 M. Mohan Kumar
    /*
2678 5e94c103 M. Mohan Kumar
     * f_bsize is adjusted(multiplied) by bsize factor, so we need to
2679 5e94c103 M. Mohan Kumar
     * adjust(divide) the number of blocks, free blocks and available
2680 5e94c103 M. Mohan Kumar
     * blocks by bsize factor
2681 5e94c103 M. Mohan Kumar
     */
2682 88a4763e Aneesh Kumar K.V
    f_blocks = stbuf->f_blocks/bsize_factor;
2683 88a4763e Aneesh Kumar K.V
    f_bfree  = stbuf->f_bfree/bsize_factor;
2684 88a4763e Aneesh Kumar K.V
    f_bavail = stbuf->f_bavail/bsize_factor;
2685 88a4763e Aneesh Kumar K.V
    f_files  = stbuf->f_files;
2686 88a4763e Aneesh Kumar K.V
    f_ffree  = stbuf->f_ffree;
2687 88a4763e Aneesh Kumar K.V
    fsid_val = (unsigned int) stbuf->f_fsid.__val[0] |
2688 88a4763e Aneesh Kumar K.V
               (unsigned long long)stbuf->f_fsid.__val[1] << 32;
2689 88a4763e Aneesh Kumar K.V
    f_namelen = stbuf->f_namelen;
2690 be940c87 M. Mohan Kumar
2691 88a4763e Aneesh Kumar K.V
    return pdu_marshal(pdu, offset, "ddqqqqqqd",
2692 88a4763e Aneesh Kumar K.V
                       f_type, f_bsize, f_blocks, f_bfree,
2693 88a4763e Aneesh Kumar K.V
                       f_bavail, f_files, f_ffree,
2694 88a4763e Aneesh Kumar K.V
                       fsid_val, f_namelen);
2695 be940c87 M. Mohan Kumar
}
2696 be940c87 M. Mohan Kumar
2697 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_statfs(void *opaque)
2698 be940c87 M. Mohan Kumar
{
2699 88a4763e Aneesh Kumar K.V
    int32_t fid;
2700 88a4763e Aneesh Kumar K.V
    ssize_t retval = 0;
2701 88a4763e Aneesh Kumar K.V
    size_t offset = 7;
2702 88a4763e Aneesh Kumar K.V
    V9fsFidState *fidp;
2703 88a4763e Aneesh Kumar K.V
    struct statfs stbuf;
2704 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2705 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2706 be940c87 M. Mohan Kumar
2707 88a4763e Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "d", &fid);
2708 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2709 88a4763e Aneesh Kumar K.V
    if (fidp == NULL) {
2710 88a4763e Aneesh Kumar K.V
        retval = -ENOENT;
2711 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2712 be940c87 M. Mohan Kumar
    }
2713 88a4763e Aneesh Kumar K.V
    retval = v9fs_co_statfs(s, &fidp->path, &stbuf);
2714 88a4763e Aneesh Kumar K.V
    if (retval < 0) {
2715 88a4763e Aneesh Kumar K.V
        goto out;
2716 88a4763e Aneesh Kumar K.V
    }
2717 88a4763e Aneesh Kumar K.V
    retval = offset;
2718 88a4763e Aneesh Kumar K.V
    retval += v9fs_fill_statfs(s, pdu, &stbuf);
2719 be940c87 M. Mohan Kumar
out:
2720 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2721 84dfb926 Aneesh Kumar K.V
out_nofid:
2722 88a4763e Aneesh Kumar K.V
    complete_pdu(s, pdu, retval);
2723 ff06030f Venkateswararao Jujjuri (JV)
    return;
2724 be940c87 M. Mohan Kumar
}
2725 be940c87 M. Mohan Kumar
2726 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_mknod(void *opaque)
2727 5268cecc M. Mohan Kumar
{
2728 1b733fed Aneesh Kumar K.V
2729 1b733fed Aneesh Kumar K.V
    int mode;
2730 1b733fed Aneesh Kumar K.V
    gid_t gid;
2731 5268cecc M. Mohan Kumar
    int32_t fid;
2732 1b733fed Aneesh Kumar K.V
    V9fsQID qid;
2733 5268cecc M. Mohan Kumar
    int err = 0;
2734 5268cecc M. Mohan Kumar
    int major, minor;
2735 1b733fed Aneesh Kumar K.V
    size_t offset = 7;
2736 1b733fed Aneesh Kumar K.V
    V9fsString name;
2737 1b733fed Aneesh Kumar K.V
    struct stat stbuf;
2738 1b733fed Aneesh Kumar K.V
    V9fsString fullname;
2739 1b733fed Aneesh Kumar K.V
    V9fsFidState *fidp;
2740 1b733fed Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2741 1b733fed Aneesh Kumar K.V
    V9fsState *s = pdu->s;
2742 5268cecc M. Mohan Kumar
2743 1b733fed Aneesh Kumar K.V
    v9fs_string_init(&fullname);
2744 1b733fed Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
2745 1b733fed Aneesh Kumar K.V
                  &major, &minor, &gid);
2746 5268cecc M. Mohan Kumar
2747 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2748 5268cecc M. Mohan Kumar
    if (fidp == NULL) {
2749 5268cecc M. Mohan Kumar
        err = -ENOENT;
2750 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2751 5268cecc M. Mohan Kumar
    }
2752 1b733fed Aneesh Kumar K.V
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
2753 1b733fed Aneesh Kumar K.V
    err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
2754 1b733fed Aneesh Kumar K.V
                        makedev(major, minor), mode);
2755 1b733fed Aneesh Kumar K.V
    if (err < 0) {
2756 1b733fed Aneesh Kumar K.V
        goto out;
2757 1b733fed Aneesh Kumar K.V
    }
2758 1b733fed Aneesh Kumar K.V
    err = v9fs_co_lstat(s, &fullname, &stbuf);
2759 1b733fed Aneesh Kumar K.V
    if (err < 0) {
2760 1b733fed Aneesh Kumar K.V
        goto out;
2761 1b733fed Aneesh Kumar K.V
    }
2762 1b733fed Aneesh Kumar K.V
    stat_to_qid(&stbuf, &qid);
2763 1b733fed Aneesh Kumar K.V
    err = offset;
2764 1b733fed Aneesh Kumar K.V
    err += pdu_marshal(pdu, offset, "Q", &qid);
2765 5268cecc M. Mohan Kumar
out:
2766 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2767 84dfb926 Aneesh Kumar K.V
out_nofid:
2768 1b733fed Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2769 1b733fed Aneesh Kumar K.V
    v9fs_string_free(&fullname);
2770 1b733fed Aneesh Kumar K.V
    v9fs_string_free(&name);
2771 5268cecc M. Mohan Kumar
}
2772 5268cecc M. Mohan Kumar
2773 82cc3ee8 M. Mohan Kumar
/*
2774 82cc3ee8 M. Mohan Kumar
 * Implement posix byte range locking code
2775 82cc3ee8 M. Mohan Kumar
 * Server side handling of locking code is very simple, because 9p server in
2776 82cc3ee8 M. Mohan Kumar
 * QEMU can handle only one client. And most of the lock handling
2777 82cc3ee8 M. Mohan Kumar
 * (like conflict, merging) etc is done by the VFS layer itself, so no need to
2778 82cc3ee8 M. Mohan Kumar
 * do any thing in * qemu 9p server side lock code path.
2779 82cc3ee8 M. Mohan Kumar
 * So when a TLOCK request comes, always return success
2780 82cc3ee8 M. Mohan Kumar
 */
2781 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_lock(void *opaque)
2782 82cc3ee8 M. Mohan Kumar
{
2783 0c27bf2a Aneesh Kumar K.V
    int8_t status;
2784 0c27bf2a Aneesh Kumar K.V
    V9fsFlock *flock;
2785 0c27bf2a Aneesh Kumar K.V
    size_t offset = 7;
2786 0c27bf2a Aneesh Kumar K.V
    struct stat stbuf;
2787 0c27bf2a Aneesh Kumar K.V
    V9fsFidState *fidp;
2788 0c27bf2a Aneesh Kumar K.V
    int32_t fid, err = 0;
2789 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2790 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2791 82cc3ee8 M. Mohan Kumar
2792 0c27bf2a Aneesh Kumar K.V
    flock = g_malloc(sizeof(*flock));
2793 0c27bf2a Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type,
2794 0c27bf2a Aneesh Kumar K.V
                  &flock->flags, &flock->start, &flock->length,
2795 0c27bf2a Aneesh Kumar K.V
                  &flock->proc_id, &flock->client_id);
2796 0c27bf2a Aneesh Kumar K.V
    status = P9_LOCK_ERROR;
2797 82cc3ee8 M. Mohan Kumar
2798 82cc3ee8 M. Mohan Kumar
    /* We support only block flag now (that too ignored currently) */
2799 0c27bf2a Aneesh Kumar K.V
    if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
2800 82cc3ee8 M. Mohan Kumar
        err = -EINVAL;
2801 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2802 82cc3ee8 M. Mohan Kumar
    }
2803 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2804 0c27bf2a Aneesh Kumar K.V
    if (fidp == NULL) {
2805 82cc3ee8 M. Mohan Kumar
        err = -ENOENT;
2806 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2807 82cc3ee8 M. Mohan Kumar
    }
2808 0c27bf2a Aneesh Kumar K.V
    err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
2809 82cc3ee8 M. Mohan Kumar
    if (err < 0) {
2810 82cc3ee8 M. Mohan Kumar
        goto out;
2811 82cc3ee8 M. Mohan Kumar
    }
2812 0c27bf2a Aneesh Kumar K.V
    status = P9_LOCK_SUCCESS;
2813 82cc3ee8 M. Mohan Kumar
out:
2814 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2815 84dfb926 Aneesh Kumar K.V
out_nofid:
2816 0c27bf2a Aneesh Kumar K.V
    err = offset;
2817 0c27bf2a Aneesh Kumar K.V
    err += pdu_marshal(pdu, offset, "b", status);
2818 0c27bf2a Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2819 10e72295 Aneesh Kumar K.V
    v9fs_string_free(&flock->client_id);
2820 0c27bf2a Aneesh Kumar K.V
    g_free(flock);
2821 82cc3ee8 M. Mohan Kumar
}
2822 82cc3ee8 M. Mohan Kumar
2823 8f354003 M. Mohan Kumar
/*
2824 8f354003 M. Mohan Kumar
 * When a TGETLOCK request comes, always return success because all lock
2825 8f354003 M. Mohan Kumar
 * handling is done by client's VFS layer.
2826 8f354003 M. Mohan Kumar
 */
2827 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_getlock(void *opaque)
2828 8f354003 M. Mohan Kumar
{
2829 e4e414a4 Aneesh Kumar K.V
    size_t offset = 7;
2830 e4e414a4 Aneesh Kumar K.V
    struct stat stbuf;
2831 e4e414a4 Aneesh Kumar K.V
    V9fsFidState *fidp;
2832 e4e414a4 Aneesh Kumar K.V
    V9fsGetlock *glock;
2833 e4e414a4 Aneesh Kumar K.V
    int32_t fid, err = 0;
2834 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2835 ff06030f Venkateswararao Jujjuri (JV)
    V9fsState *s = pdu->s;
2836 8f354003 M. Mohan Kumar
2837 e4e414a4 Aneesh Kumar K.V
    glock = g_malloc(sizeof(*glock));
2838 e4e414a4 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock->type,
2839 e4e414a4 Aneesh Kumar K.V
                  &glock->start, &glock->length, &glock->proc_id,
2840 e4e414a4 Aneesh Kumar K.V
                  &glock->client_id);
2841 8f354003 M. Mohan Kumar
2842 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(s, fid);
2843 e4e414a4 Aneesh Kumar K.V
    if (fidp == NULL) {
2844 8f354003 M. Mohan Kumar
        err = -ENOENT;
2845 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2846 8f354003 M. Mohan Kumar
    }
2847 e4e414a4 Aneesh Kumar K.V
    err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
2848 8f354003 M. Mohan Kumar
    if (err < 0) {
2849 8f354003 M. Mohan Kumar
        goto out;
2850 8f354003 M. Mohan Kumar
    }
2851 e4e414a4 Aneesh Kumar K.V
    glock->type = F_UNLCK;
2852 e4e414a4 Aneesh Kumar K.V
    offset += pdu_marshal(pdu, offset, "bqqds", glock->type,
2853 e4e414a4 Aneesh Kumar K.V
                          glock->start, glock->length, glock->proc_id,
2854 e4e414a4 Aneesh Kumar K.V
                          &glock->client_id);
2855 e4e414a4 Aneesh Kumar K.V
    err = offset;
2856 8f354003 M. Mohan Kumar
out:
2857 84dfb926 Aneesh Kumar K.V
    put_fid(s, fidp);
2858 84dfb926 Aneesh Kumar K.V
out_nofid:
2859 e4e414a4 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2860 10e72295 Aneesh Kumar K.V
    v9fs_string_free(&glock->client_id);
2861 e4e414a4 Aneesh Kumar K.V
    g_free(glock);
2862 8f354003 M. Mohan Kumar
}
2863 8f354003 M. Mohan Kumar
2864 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_mkdir(void *opaque)
2865 b67592ea M. Mohan Kumar
{
2866 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
2867 e84861f7 Venkateswararao Jujjuri
    size_t offset = 7;
2868 b67592ea M. Mohan Kumar
    int32_t fid;
2869 e84861f7 Venkateswararao Jujjuri
    struct stat stbuf;
2870 e84861f7 Venkateswararao Jujjuri
    V9fsString name, fullname;
2871 e84861f7 Venkateswararao Jujjuri
    V9fsQID qid;
2872 b67592ea M. Mohan Kumar
    V9fsFidState *fidp;
2873 b67592ea M. Mohan Kumar
    gid_t gid;
2874 b67592ea M. Mohan Kumar
    int mode;
2875 e84861f7 Venkateswararao Jujjuri
    int err = 0;
2876 b67592ea M. Mohan Kumar
2877 e84861f7 Venkateswararao Jujjuri
    v9fs_string_init(&fullname);
2878 e84861f7 Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
2879 b67592ea M. Mohan Kumar
2880 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(pdu->s, fid);
2881 b67592ea M. Mohan Kumar
    if (fidp == NULL) {
2882 b67592ea M. Mohan Kumar
        err = -ENOENT;
2883 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2884 b67592ea M. Mohan Kumar
    }
2885 e84861f7 Venkateswararao Jujjuri
    v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
2886 e84861f7 Venkateswararao Jujjuri
    err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
2887 e84861f7 Venkateswararao Jujjuri
    if (err < 0) {
2888 e84861f7 Venkateswararao Jujjuri
        goto out;
2889 e84861f7 Venkateswararao Jujjuri
    }
2890 e84861f7 Venkateswararao Jujjuri
    err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
2891 e84861f7 Venkateswararao Jujjuri
    if (err < 0) {
2892 e84861f7 Venkateswararao Jujjuri
        goto out;
2893 e84861f7 Venkateswararao Jujjuri
    }
2894 e84861f7 Venkateswararao Jujjuri
    stat_to_qid(&stbuf, &qid);
2895 e84861f7 Venkateswararao Jujjuri
    offset += pdu_marshal(pdu, offset, "Q", &qid);
2896 e84861f7 Venkateswararao Jujjuri
    err = offset;
2897 b67592ea M. Mohan Kumar
out:
2898 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, fidp);
2899 84dfb926 Aneesh Kumar K.V
out_nofid:
2900 e84861f7 Venkateswararao Jujjuri
    complete_pdu(pdu->s, pdu, err);
2901 e84861f7 Venkateswararao Jujjuri
    v9fs_string_free(&fullname);
2902 e84861f7 Venkateswararao Jujjuri
    v9fs_string_free(&name);
2903 b67592ea M. Mohan Kumar
}
2904 b67592ea M. Mohan Kumar
2905 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_xattrwalk(void *opaque)
2906 fa32ef88 Aneesh Kumar K.V
{
2907 670185a6 Aneesh Kumar K.V
    int64_t size;
2908 670185a6 Aneesh Kumar K.V
    V9fsString name;
2909 fa32ef88 Aneesh Kumar K.V
    ssize_t err = 0;
2910 670185a6 Aneesh Kumar K.V
    size_t offset = 7;
2911 fa32ef88 Aneesh Kumar K.V
    int32_t fid, newfid;
2912 670185a6 Aneesh Kumar K.V
    V9fsFidState *file_fidp;
2913 84dfb926 Aneesh Kumar K.V
    V9fsFidState *xattr_fidp = NULL;
2914 670185a6 Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
2915 670185a6 Aneesh Kumar K.V
    V9fsState *s = pdu->s;
2916 fa32ef88 Aneesh Kumar K.V
2917 670185a6 Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
2918 84dfb926 Aneesh Kumar K.V
    file_fidp = get_fid(s, fid);
2919 670185a6 Aneesh Kumar K.V
    if (file_fidp == NULL) {
2920 fa32ef88 Aneesh Kumar K.V
        err = -ENOENT;
2921 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
2922 fa32ef88 Aneesh Kumar K.V
    }
2923 670185a6 Aneesh Kumar K.V
    xattr_fidp = alloc_fid(s, newfid);
2924 670185a6 Aneesh Kumar K.V
    if (xattr_fidp == NULL) {
2925 fa32ef88 Aneesh Kumar K.V
        err = -EINVAL;
2926 fa32ef88 Aneesh Kumar K.V
        goto out;
2927 fa32ef88 Aneesh Kumar K.V
    }
2928 670185a6 Aneesh Kumar K.V
    v9fs_string_copy(&xattr_fidp->path, &file_fidp->path);
2929 670185a6 Aneesh Kumar K.V
    if (name.data[0] == 0) {
2930 fa32ef88 Aneesh Kumar K.V
        /*
2931 fa32ef88 Aneesh Kumar K.V
         * listxattr request. Get the size first
2932 fa32ef88 Aneesh Kumar K.V
         */
2933 670185a6 Aneesh Kumar K.V
        size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
2934 670185a6 Aneesh Kumar K.V
        if (size < 0) {
2935 670185a6 Aneesh Kumar K.V
            err = size;
2936 84dfb926 Aneesh Kumar K.V
            clunk_fid(s, xattr_fidp->fid);
2937 670185a6 Aneesh Kumar K.V
            goto out;
2938 fa32ef88 Aneesh Kumar K.V
        }
2939 670185a6 Aneesh Kumar K.V
        /*
2940 670185a6 Aneesh Kumar K.V
         * Read the xattr value
2941 670185a6 Aneesh Kumar K.V
         */
2942 670185a6 Aneesh Kumar K.V
        xattr_fidp->fs.xattr.len = size;
2943 670185a6 Aneesh Kumar K.V
        xattr_fidp->fid_type = P9_FID_XATTR;
2944 670185a6 Aneesh Kumar K.V
        xattr_fidp->fs.xattr.copied_len = -1;
2945 670185a6 Aneesh Kumar K.V
        if (size) {
2946 7267c094 Anthony Liguori
            xattr_fidp->fs.xattr.value = g_malloc(size);
2947 670185a6 Aneesh Kumar K.V
            err = v9fs_co_llistxattr(s, &xattr_fidp->path,
2948 670185a6 Aneesh Kumar K.V
                                     xattr_fidp->fs.xattr.value,
2949 670185a6 Aneesh Kumar K.V
                                     xattr_fidp->fs.xattr.len);
2950 670185a6 Aneesh Kumar K.V
            if (err < 0) {
2951 84dfb926 Aneesh Kumar K.V
                clunk_fid(s, xattr_fidp->fid);
2952 670185a6 Aneesh Kumar K.V
                goto out;
2953 670185a6 Aneesh Kumar K.V
            }
2954 670185a6 Aneesh Kumar K.V
        }
2955 670185a6 Aneesh Kumar K.V
        offset += pdu_marshal(pdu, offset, "q", size);
2956 670185a6 Aneesh Kumar K.V
        err = offset;
2957 fa32ef88 Aneesh Kumar K.V
    } else {
2958 fa32ef88 Aneesh Kumar K.V
        /*
2959 fa32ef88 Aneesh Kumar K.V
         * specific xattr fid. We check for xattr
2960 fa32ef88 Aneesh Kumar K.V
         * presence also collect the xattr size
2961 fa32ef88 Aneesh Kumar K.V
         */
2962 670185a6 Aneesh Kumar K.V
        size = v9fs_co_lgetxattr(s, &xattr_fidp->path,
2963 670185a6 Aneesh Kumar K.V
                                 &name, NULL, 0);
2964 670185a6 Aneesh Kumar K.V
        if (size < 0) {
2965 670185a6 Aneesh Kumar K.V
            err = size;
2966 84dfb926 Aneesh Kumar K.V
            clunk_fid(s, xattr_fidp->fid);
2967 670185a6 Aneesh Kumar K.V
            goto out;
2968 fa32ef88 Aneesh Kumar K.V
        }
2969 670185a6 Aneesh Kumar K.V
        /*
2970 670185a6 Aneesh Kumar K.V
         * Read the xattr value
2971 670185a6 Aneesh Kumar K.V
         */
2972 670185a6 Aneesh Kumar K.V
        xattr_fidp->fs.xattr.len = size;
2973 670185a6 Aneesh Kumar K.V
        xattr_fidp->fid_type = P9_FID_XATTR;
2974 670185a6 Aneesh Kumar K.V
        xattr_fidp->fs.xattr.copied_len = -1;
2975 670185a6 Aneesh Kumar K.V
        if (size) {
2976 7267c094 Anthony Liguori
            xattr_fidp->fs.xattr.value = g_malloc(size);
2977 670185a6 Aneesh Kumar K.V
            err = v9fs_co_lgetxattr(s, &xattr_fidp->path,
2978 670185a6 Aneesh Kumar K.V
                                    &name, xattr_fidp->fs.xattr.value,
2979 670185a6 Aneesh Kumar K.V
                                    xattr_fidp->fs.xattr.len);
2980 670185a6 Aneesh Kumar K.V
            if (err < 0) {
2981 84dfb926 Aneesh Kumar K.V
                clunk_fid(s, xattr_fidp->fid);
2982 670185a6 Aneesh Kumar K.V
                goto out;
2983 670185a6 Aneesh Kumar K.V
            }
2984 670185a6 Aneesh Kumar K.V
        }
2985 670185a6 Aneesh Kumar K.V
        offset += pdu_marshal(pdu, offset, "q", size);
2986 670185a6 Aneesh Kumar K.V
        err = offset;
2987 fa32ef88 Aneesh Kumar K.V
    }
2988 fa32ef88 Aneesh Kumar K.V
out:
2989 84dfb926 Aneesh Kumar K.V
    put_fid(s, file_fidp);
2990 84dfb926 Aneesh Kumar K.V
    if (xattr_fidp) {
2991 84dfb926 Aneesh Kumar K.V
        put_fid(s, xattr_fidp);
2992 84dfb926 Aneesh Kumar K.V
    }
2993 84dfb926 Aneesh Kumar K.V
out_nofid:
2994 670185a6 Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
2995 670185a6 Aneesh Kumar K.V
    v9fs_string_free(&name);
2996 fa32ef88 Aneesh Kumar K.V
}
2997 fa32ef88 Aneesh Kumar K.V
2998 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_xattrcreate(void *opaque)
2999 10b468bd Aneesh Kumar K.V
{
3000 10b468bd Aneesh Kumar K.V
    int flags;
3001 10b468bd Aneesh Kumar K.V
    int32_t fid;
3002 f10ff58d Aneesh Kumar K.V
    int64_t size;
3003 10b468bd Aneesh Kumar K.V
    ssize_t err = 0;
3004 f10ff58d Aneesh Kumar K.V
    V9fsString name;
3005 f10ff58d Aneesh Kumar K.V
    size_t offset = 7;
3006 f10ff58d Aneesh Kumar K.V
    V9fsFidState *file_fidp;
3007 f10ff58d Aneesh Kumar K.V
    V9fsFidState *xattr_fidp;
3008 f10ff58d Aneesh Kumar K.V
    V9fsPDU *pdu = opaque;
3009 f10ff58d Aneesh Kumar K.V
    V9fsState *s = pdu->s;
3010 10b468bd Aneesh Kumar K.V
3011 f10ff58d Aneesh Kumar K.V
    pdu_unmarshal(pdu, offset, "dsqd",
3012 f10ff58d Aneesh Kumar K.V
                  &fid, &name, &size, &flags);
3013 10b468bd Aneesh Kumar K.V
3014 84dfb926 Aneesh Kumar K.V
    file_fidp = get_fid(s, fid);
3015 f10ff58d Aneesh Kumar K.V
    if (file_fidp == NULL) {
3016 10b468bd Aneesh Kumar K.V
        err = -EINVAL;
3017 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
3018 10b468bd Aneesh Kumar K.V
    }
3019 10b468bd Aneesh Kumar K.V
    /* Make the file fid point to xattr */
3020 f10ff58d Aneesh Kumar K.V
    xattr_fidp = file_fidp;
3021 f10ff58d Aneesh Kumar K.V
    xattr_fidp->fid_type = P9_FID_XATTR;
3022 f10ff58d Aneesh Kumar K.V
    xattr_fidp->fs.xattr.copied_len = 0;
3023 f10ff58d Aneesh Kumar K.V
    xattr_fidp->fs.xattr.len = size;
3024 f10ff58d Aneesh Kumar K.V
    xattr_fidp->fs.xattr.flags = flags;
3025 f10ff58d Aneesh Kumar K.V
    v9fs_string_init(&xattr_fidp->fs.xattr.name);
3026 f10ff58d Aneesh Kumar K.V
    v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
3027 f10ff58d Aneesh Kumar K.V
    if (size) {
3028 7267c094 Anthony Liguori
        xattr_fidp->fs.xattr.value = g_malloc(size);
3029 f10ff58d Aneesh Kumar K.V
    } else {
3030 f10ff58d Aneesh Kumar K.V
        xattr_fidp->fs.xattr.value = NULL;
3031 f10ff58d Aneesh Kumar K.V
    }
3032 f10ff58d Aneesh Kumar K.V
    err = offset;
3033 84dfb926 Aneesh Kumar K.V
    put_fid(s, file_fidp);
3034 84dfb926 Aneesh Kumar K.V
out_nofid:
3035 f10ff58d Aneesh Kumar K.V
    complete_pdu(s, pdu, err);
3036 f10ff58d Aneesh Kumar K.V
    v9fs_string_free(&name);
3037 10b468bd Aneesh Kumar K.V
}
3038 fa32ef88 Aneesh Kumar K.V
3039 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_readlink(void *opaque)
3040 df0973a4 M. Mohan Kumar
{
3041 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
3042 7a5ca31e Venkateswararao Jujjuri
    size_t offset = 7;
3043 7a5ca31e Venkateswararao Jujjuri
    V9fsString target;
3044 df0973a4 M. Mohan Kumar
    int32_t fid;
3045 df0973a4 M. Mohan Kumar
    int err = 0;
3046 df0973a4 M. Mohan Kumar
    V9fsFidState *fidp;
3047 df0973a4 M. Mohan Kumar
3048 7a5ca31e Venkateswararao Jujjuri
    pdu_unmarshal(pdu, offset, "d", &fid);
3049 84dfb926 Aneesh Kumar K.V
    fidp = get_fid(pdu->s, fid);
3050 df0973a4 M. Mohan Kumar
    if (fidp == NULL) {
3051 df0973a4 M. Mohan Kumar
        err = -ENOENT;
3052 84dfb926 Aneesh Kumar K.V
        goto out_nofid;
3053 df0973a4 M. Mohan Kumar
    }
3054 df0973a4 M. Mohan Kumar
3055 7a5ca31e Venkateswararao Jujjuri
    v9fs_string_init(&target);
3056 7a5ca31e Venkateswararao Jujjuri
    err = v9fs_co_readlink(pdu->s, &fidp->path, &target);
3057 7a5ca31e Venkateswararao Jujjuri
    if (err < 0) {
3058 7a5ca31e Venkateswararao Jujjuri
        goto out;
3059 7a5ca31e Venkateswararao Jujjuri
    }
3060 7a5ca31e Venkateswararao Jujjuri
    offset += pdu_marshal(pdu, offset, "s", &target);
3061 7a5ca31e Venkateswararao Jujjuri
    err = offset;
3062 7a5ca31e Venkateswararao Jujjuri
    v9fs_string_free(&target);
3063 df0973a4 M. Mohan Kumar
out:
3064 84dfb926 Aneesh Kumar K.V
    put_fid(pdu->s, fidp);
3065 84dfb926 Aneesh Kumar K.V
out_nofid:
3066 7a5ca31e Venkateswararao Jujjuri
    complete_pdu(pdu->s, pdu, err);
3067 df0973a4 M. Mohan Kumar
}
3068 df0973a4 M. Mohan Kumar
3069 ff06030f Venkateswararao Jujjuri (JV)
static CoroutineEntry *pdu_co_handlers[] = {
3070 c18e2f94 Sripathi Kodi
    [P9_TREADDIR] = v9fs_readdir,
3071 be940c87 M. Mohan Kumar
    [P9_TSTATFS] = v9fs_statfs,
3072 00ede4c2 Sripathi Kodi
    [P9_TGETATTR] = v9fs_getattr,
3073 c79ce737 Sripathi Kodi
    [P9_TSETATTR] = v9fs_setattr,
3074 fa32ef88 Aneesh Kumar K.V
    [P9_TXATTRWALK] = v9fs_xattrwalk,
3075 10b468bd Aneesh Kumar K.V
    [P9_TXATTRCREATE] = v9fs_xattrcreate,
3076 5268cecc M. Mohan Kumar
    [P9_TMKNOD] = v9fs_mknod,
3077 c7b4b0b3 M. Mohan Kumar
    [P9_TRENAME] = v9fs_rename,
3078 82cc3ee8 M. Mohan Kumar
    [P9_TLOCK] = v9fs_lock,
3079 8f354003 M. Mohan Kumar
    [P9_TGETLOCK] = v9fs_getlock,
3080 89bf6593 Aneesh Kumar K.V
    [P9_TRENAMEAT] = v9fs_renameat,
3081 df0973a4 M. Mohan Kumar
    [P9_TREADLINK] = v9fs_readlink,
3082 7834cf77 Aneesh Kumar K.V
    [P9_TUNLINKAT] = v9fs_unlinkat,
3083 b67592ea M. Mohan Kumar
    [P9_TMKDIR] = v9fs_mkdir,
3084 9f107513 Anthony Liguori
    [P9_TVERSION] = v9fs_version,
3085 771e9d4c M. Mohan Kumar
    [P9_TLOPEN] = v9fs_open,
3086 9f107513 Anthony Liguori
    [P9_TATTACH] = v9fs_attach,
3087 9f107513 Anthony Liguori
    [P9_TSTAT] = v9fs_stat,
3088 9f107513 Anthony Liguori
    [P9_TWALK] = v9fs_walk,
3089 9f107513 Anthony Liguori
    [P9_TCLUNK] = v9fs_clunk,
3090 b41e95d3 Venkateswararao Jujjuri (JV)
    [P9_TFSYNC] = v9fs_fsync,
3091 9f107513 Anthony Liguori
    [P9_TOPEN] = v9fs_open,
3092 9f107513 Anthony Liguori
    [P9_TREAD] = v9fs_read,
3093 9f107513 Anthony Liguori
#if 0
3094 9f107513 Anthony Liguori
    [P9_TAUTH] = v9fs_auth,
3095 9f107513 Anthony Liguori
#endif
3096 9f107513 Anthony Liguori
    [P9_TFLUSH] = v9fs_flush,
3097 b2c224be Venkateswararao Jujjuri (JV)
    [P9_TLINK] = v9fs_link,
3098 08c60fc9 Venkateswararao Jujjuri (JV)
    [P9_TSYMLINK] = v9fs_symlink,
3099 9f107513 Anthony Liguori
    [P9_TCREATE] = v9fs_create,
3100 c1568af5 Venkateswararao Jujjuri (JV)
    [P9_TLCREATE] = v9fs_lcreate,
3101 9f107513 Anthony Liguori
    [P9_TWRITE] = v9fs_write,
3102 9f107513 Anthony Liguori
    [P9_TWSTAT] = v9fs_wstat,
3103 9f107513 Anthony Liguori
    [P9_TREMOVE] = v9fs_remove,
3104 9f107513 Anthony Liguori
};
3105 9f107513 Anthony Liguori
3106 ff06030f Venkateswararao Jujjuri (JV)
static void v9fs_op_not_supp(void *opaque)
3107 5c3234c6 Aneesh Kumar K.V
{
3108 ff06030f Venkateswararao Jujjuri (JV)
    V9fsPDU *pdu = opaque;
3109 ff06030f Venkateswararao Jujjuri (JV)
    complete_pdu(pdu->s, pdu, -EOPNOTSUPP);
3110 5c3234c6 Aneesh Kumar K.V
}
3111 5c3234c6 Aneesh Kumar K.V
3112 9f107513 Anthony Liguori
static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
3113 9f107513 Anthony Liguori
{
3114 ff06030f Venkateswararao Jujjuri (JV)
    Coroutine *co;
3115 ff06030f Venkateswararao Jujjuri (JV)
    CoroutineEntry *handler;
3116 9f107513 Anthony Liguori
3117 9f107513 Anthony Liguori
    if (debug_9p_pdu) {
3118 9f107513 Anthony Liguori
        pprint_pdu(pdu);
3119 9f107513 Anthony Liguori
    }
3120 ff06030f Venkateswararao Jujjuri (JV)
    if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
3121 ff06030f Venkateswararao Jujjuri (JV)
        (pdu_co_handlers[pdu->id] == NULL)) {
3122 5c3234c6 Aneesh Kumar K.V
        handler = v9fs_op_not_supp;
3123 5c3234c6 Aneesh Kumar K.V
    } else {
3124 ff06030f Venkateswararao Jujjuri (JV)
        handler = pdu_co_handlers[pdu->id];
3125 5c3234c6 Aneesh Kumar K.V
    }
3126 ff06030f Venkateswararao Jujjuri (JV)
    co = qemu_coroutine_create(handler);
3127 ff06030f Venkateswararao Jujjuri (JV)
    qemu_coroutine_enter(co, pdu);
3128 9f107513 Anthony Liguori
}
3129 9f107513 Anthony Liguori
3130 f4f61d27 Aneesh Kumar K.V
void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
3131 9f107513 Anthony Liguori
{
3132 9f107513 Anthony Liguori
    V9fsState *s = (V9fsState *)vdev;
3133 9f107513 Anthony Liguori
    V9fsPDU *pdu;
3134 9f107513 Anthony Liguori
    ssize_t len;
3135 9f107513 Anthony Liguori
3136 9f107513 Anthony Liguori
    while ((pdu = alloc_pdu(s)) &&
3137 9f107513 Anthony Liguori
            (len = virtqueue_pop(vq, &pdu->elem)) != 0) {
3138 9f107513 Anthony Liguori
        uint8_t *ptr;
3139 ff06030f Venkateswararao Jujjuri (JV)
        pdu->s = s;
3140 9f107513 Anthony Liguori
        BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
3141 9f107513 Anthony Liguori
        BUG_ON(pdu->elem.out_sg[0].iov_len < 7);
3142 9f107513 Anthony Liguori
3143 9f107513 Anthony Liguori
        ptr = pdu->elem.out_sg[0].iov_base;
3144 9f107513 Anthony Liguori
3145 9f107513 Anthony Liguori
        memcpy(&pdu->size, ptr, 4);
3146 9f107513 Anthony Liguori
        pdu->id = ptr[4];
3147 9f107513 Anthony Liguori
        memcpy(&pdu->tag, ptr + 5, 2);
3148 9f107513 Anthony Liguori
        submit_pdu(s, pdu);
3149 9f107513 Anthony Liguori
    }
3150 9f107513 Anthony Liguori
    free_pdu(s, pdu);
3151 9f107513 Anthony Liguori
}
3152 7a462745 Aneesh Kumar K.V
3153 7a462745 Aneesh Kumar K.V
void virtio_9p_set_fd_limit(void)
3154 7a462745 Aneesh Kumar K.V
{
3155 7a462745 Aneesh Kumar K.V
    struct rlimit rlim;
3156 7a462745 Aneesh Kumar K.V
    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
3157 7a462745 Aneesh Kumar K.V
        fprintf(stderr, "Failed to get the resource limit\n");
3158 7a462745 Aneesh Kumar K.V
        exit(1);
3159 7a462745 Aneesh Kumar K.V
    }
3160 7a462745 Aneesh Kumar K.V
    open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
3161 7a462745 Aneesh Kumar K.V
    open_fd_rc = rlim.rlim_cur/2;
3162 7a462745 Aneesh Kumar K.V
}