~ubuntu-branches/ubuntu/trusty/glusterfs/trusty

« back to all changes in this revision

Viewing changes to xlators/mount/fuse/src/fuse-bridge.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Matthäi
  • Date: 2010-02-09 18:53:10 UTC
  • mfrom: (1.2.4 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100209185310-ww8p82lsbosorg2u
* New upstream release.
* Uploading to unstable.
* Bump Standards-Version to 3.8.4 (no changes needed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <stdint.h>
29
29
#include <signal.h>
30
30
#include <pthread.h>
 
31
#include <stddef.h>
 
32
#include <dirent.h>
 
33
#include <sys/mount.h>
 
34
#include <sys/time.h>
31
35
 
32
36
#ifndef _CONFIG_H
33
37
#define _CONFIG_H
37
41
#include "glusterfs.h"
38
42
#include "logging.h"
39
43
#include "xlator.h"
40
 
#include "glusterfs.h"
41
44
#include "defaults.h"
42
45
#include "common-utils.h"
43
 
 
44
 
#include <fuse/fuse_lowlevel.h>
45
 
 
46
 
#include "fuse-extra.h"
 
46
#include "statedump.h"
 
47
 
 
48
#include "fuse_kernel.h"
 
49
#include "fuse-misc.h"
 
50
#include "fuse-mount.h"
 
51
 
47
52
#include "list.h"
48
53
#include "dict.h"
49
54
 
50
55
#include "compat.h"
51
56
#include "compat-errno.h"
52
57
 
53
 
#include <sys/time.h>
54
 
 
55
58
/* TODO: when supporting posix acl, remove this definition */
56
59
#define DISABLE_POSIX_ACL
57
60
 
58
61
#define ZR_MOUNTPOINT_OPT       "mountpoint"
59
62
#define ZR_DIRECT_IO_OPT        "direct-io-mode"
60
63
#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check"
 
64
 
 
65
#define FUSE_713_OP_HIGH (FUSE_POLL + 1)
 
66
#define GLUSTERFS_XATTR_LEN_MAX  65536
 
67
 
61
68
#define MAX_FUSE_PROC_DELAY 1
62
69
 
 
70
typedef struct fuse_in_header fuse_in_header_t;
 
71
typedef void (fuse_handler_t) (xlator_t *this, fuse_in_header_t *finh,
 
72
                               void *msg);
 
73
 
63
74
struct fuse_private {
64
75
        int                  fd;
65
 
        struct fuse         *fuse;
66
 
        struct fuse_session *se;
67
 
        struct fuse_chan    *ch;
 
76
        uint32_t             proto_minor;
68
77
        char                *volfile;
69
78
        size_t               volfile_size;
70
79
        char                *mount_point;
72
81
        pthread_t            fuse_thread;
73
82
        char                 fuse_thread_started;
74
83
        uint32_t             direct_io_mode;
 
84
        size_t              *msg0_len_p;
75
85
        double               entry_timeout;
76
86
        double               attribute_timeout;
77
87
        pthread_cond_t       first_call_cond;
81
91
        pthread_cond_t       child_up_cond;
82
92
        pthread_mutex_t      child_up_mutex;
83
93
        char                 child_up_value;
 
94
 
84
95
};
85
96
typedef struct fuse_private fuse_private_t;
86
97
 
87
 
#define _FI_TO_FD(fi) ((fd_t *)((long)fi->fh))
 
98
#define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh))
88
99
 
89
 
#define FI_TO_FD(fi) ((_FI_TO_FD (fi))?(fd_ref (_FI_TO_FD(fi))):((fd_t *) 0))
 
100
#define FH_TO_FD(fh) ((_FH_TO_FD (fh))?(fd_ref (_FH_TO_FD (fh))):((fd_t *) 0))
90
101
 
91
102
#define FUSE_FOP(state, ret, op_num, fop, args ...)                     \
92
103
        do {                                                            \
93
 
                call_frame_t *frame = get_call_frame_for_req (state, 1); \
94
 
                xlator_t *xl = frame->this->children ?                  \
 
104
                call_frame_t *frame = NULL;                             \
 
105
                xlator_t *xl = NULL;                                    \
 
106
                                                                        \
 
107
                frame = get_call_frame_for_req (state);                 \
 
108
                if (!frame) {                                           \
 
109
                         /* This is not completely clean, as some       \
 
110
                          * earlier allocations might remain unfreed    \
 
111
                          * if we return at this point, but still       \
 
112
                          * better than trying to go on with a NULL     \
 
113
                          * frame ...                                   \
 
114
                          */                                            \
 
115
                        gf_log ("glusterfs-fuse",                       \
 
116
                                GF_LOG_ERROR,                           \
 
117
                                "FUSE message"                          \
 
118
                                " unique %"PRIu64" opcode %d:"          \
 
119
                                " frame allocation failed",             \
 
120
                                state->finh->unique,                    \
 
121
                                state->finh->opcode);                   \
 
122
                        free_state (state);                             \
 
123
                        return;                                         \
 
124
                }                                                       \
 
125
                xl = frame->this->children ?                            \
95
126
                        frame->this->children->xlator : NULL;           \
96
127
                frame->root->state = state;                             \
97
 
                frame->root->op   = op_num;                                \
 
128
                frame->root->op    = op_num;                            \
98
129
                STACK_WIND (frame, ret, xl, xl->fops->fop, args);       \
99
130
        } while (0)
100
131
 
102
133
        (((_errno == ENOENT) || (_errno == ESTALE))?    \
103
134
         GF_LOG_DEBUG)
104
135
 
 
136
#define GET_STATE(this, finh, state)                                       \
 
137
        do {                                                               \
 
138
                state = get_state (this, finh);                            \
 
139
                if (!state) {                                              \
 
140
                        gf_log ("glusterfs-fuse",                          \
 
141
                                GF_LOG_ERROR,                              \
 
142
                                "FUSE message unique %"PRIu64" opcode %d:" \
 
143
                                " state allocation failed",                \
 
144
                                finh->unique, finh->opcode);               \
 
145
                                                                           \
 
146
                        send_fuse_err (this, finh, ENOMEM);                \
 
147
                        FREE (finh);                                       \
 
148
                                                                           \
 
149
                        return;                                            \
 
150
                }                                                          \
 
151
        } while (0)
 
152
 
 
153
 
105
154
typedef struct {
106
155
        void          *pool;
107
156
        xlator_t      *this;
108
157
        inode_table_t *itable;
109
158
        loc_t          loc;
110
159
        loc_t          loc2;
111
 
        fuse_req_t     req;
 
160
        fuse_in_header_t *finh;
112
161
        int32_t        flags;
113
162
        off_t          off;
114
163
        size_t         size;
117
166
        dict_t        *dict;
118
167
        char          *name;
119
168
        char           is_revalidate;
 
169
        gf_boolean_t   truncate_needed;
 
170
        gf_lock_t      lock;
 
171
        uint64_t       lk_owner;
120
172
} fuse_state_t;
121
173
 
122
 
int fuse_chan_receive (struct fuse_chan *ch, char *buf, int32_t size);
123
 
 
124
174
 
125
175
static void
126
176
free_state (fuse_state_t *state)
141
191
                fd_unref (state->fd);
142
192
                state->fd = (void *)0xfdfdfdfd;
143
193
        }
 
194
        if (state->finh) {
 
195
                FREE (state->finh);
 
196
                state->finh = NULL;
 
197
        }
144
198
#ifdef DEBUG
145
199
        memset (state, 0x90, sizeof (*state));
146
200
#endif
150
204
 
151
205
 
152
206
fuse_state_t *
153
 
state_from_req (fuse_req_t req)
 
207
get_state (xlator_t *this, fuse_in_header_t *finh)
154
208
{
155
209
        fuse_state_t *state = NULL;
156
 
        xlator_t     *this = NULL;
157
 
 
158
 
        this = fuse_req_userdata (req);
159
210
 
160
211
        state = (void *)calloc (1, sizeof (*state));
161
212
        if (!state)
162
213
                return NULL;
163
214
        state->pool = this->ctx->pool;
164
215
        state->itable = this->itable;
165
 
        state->req = req;
 
216
        state->finh = finh;
166
217
        state->this = this;
167
218
 
 
219
        LOCK_INIT (&state->lock);
 
220
 
168
221
        return state;
169
222
}
170
223
 
171
224
 
172
 
static pid_t
173
 
get_pid_from_req (fuse_req_t req)
174
 
{
175
 
        const struct fuse_ctx *ctx = NULL;
176
 
 
177
 
        ctx = fuse_req_ctx (req);
178
 
        return ctx->pid;
179
 
}
180
 
 
181
 
 
182
225
static call_frame_t *
183
 
get_call_frame_for_req (fuse_state_t *state, char d)
 
226
get_call_frame_for_req (fuse_state_t *state)
184
227
{
185
228
        call_pool_t           *pool = NULL;
186
 
        fuse_req_t             req = NULL;
187
 
        const struct fuse_ctx *ctx = NULL;
 
229
        fuse_in_header_t      *finh = NULL;
188
230
        call_frame_t          *frame = NULL;
189
231
        xlator_t              *this = NULL;
190
232
        fuse_private_t        *priv = NULL;
191
233
 
192
234
        pool = state->pool;
193
 
        req  = state->req;
194
 
 
195
 
        if (req) {
196
 
                this = fuse_req_userdata (req);
197
 
        } else {
198
 
                this = state->this;
199
 
        }
 
235
        finh = state->finh;
 
236
        this = state->this;
200
237
        priv = this->private;
201
238
 
202
239
        frame = create_frame (this, pool);
203
 
 
204
 
        if (req) {
205
 
                ctx = fuse_req_ctx (req);
206
 
 
207
 
                frame->root->uid    = ctx->uid;
208
 
                frame->root->gid    = ctx->gid;
209
 
                frame->root->pid    = ctx->pid;
210
 
                frame->root->unique = req_callid (req);
 
240
        if (!frame)
 
241
                return NULL;
 
242
 
 
243
        if (finh) {
 
244
                frame->root->uid      = finh->uid;
 
245
                frame->root->gid      = finh->gid;
 
246
                frame->root->pid      = finh->pid;
 
247
                frame->root->lk_owner = state->lk_owner;
 
248
                frame->root->unique   = finh->unique;
211
249
        }
212
250
 
213
251
        frame->root->type = GF_OP_TYPE_FOP_REQUEST;
216
254
}
217
255
 
218
256
 
 
257
/*
 
258
 * iov_out should contain a fuse_out_header at zeroth position.
 
259
 * The error value of this header is sent to kernel.
 
260
 */
 
261
static int
 
262
send_fuse_iov (xlator_t *this, fuse_in_header_t *finh, struct iovec *iov_out,
 
263
               int count)
 
264
{
 
265
        fuse_private_t *priv = NULL;
 
266
        struct fuse_out_header *fouh = NULL;
 
267
        int res, i;
 
268
 
 
269
        priv = this->private;
 
270
 
 
271
        fouh = iov_out[0].iov_base;
 
272
        iov_out[0].iov_len = sizeof (*fouh);
 
273
        fouh->len = 0;
 
274
        for (i = 0; i < count; i++)
 
275
                fouh->len += iov_out[i].iov_len;
 
276
        fouh->unique = finh->unique;
 
277
 
 
278
        res = writev (priv->fd, iov_out, count);
 
279
 
 
280
        if (res == -1)
 
281
                return errno;
 
282
        if (res != fouh->len)
 
283
                return EINVAL;
 
284
        return 0;
 
285
}
 
286
 
 
287
static int
 
288
send_fuse_data (xlator_t *this, fuse_in_header_t *finh, void *data, size_t size)
 
289
{
 
290
        struct fuse_out_header fouh = {0, };
 
291
        struct iovec iov_out[2];
 
292
 
 
293
        fouh.error = 0;
 
294
        iov_out[0].iov_base = &fouh;
 
295
        iov_out[1].iov_base = data;
 
296
        iov_out[1].iov_len = size;
 
297
 
 
298
        return send_fuse_iov (this, finh, iov_out, 2);
 
299
}
 
300
 
 
301
#define send_fuse_obj(this, finh, obj) \
 
302
        send_fuse_data (this, finh, obj, sizeof (*(obj)))
 
303
 
 
304
static int
 
305
send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error)
 
306
{
 
307
        struct fuse_out_header fouh = {0, };
 
308
        struct iovec iov_out;
 
309
 
 
310
        fouh.error = -error;
 
311
        iov_out.iov_base = &fouh;
 
312
 
 
313
        return send_fuse_iov (this, finh, &iov_out, 1);
 
314
}
 
315
 
 
316
static inode_t *
 
317
fuse_ino_to_inode (uint64_t ino, inode_table_t *table)
 
318
{
 
319
        inode_t *inode = NULL;
 
320
 
 
321
        if (ino == 1) {
 
322
                inode = table->root;
 
323
        } else {
 
324
                inode = (inode_t *) (unsigned long) ino;
 
325
                inode_ref (inode);
 
326
        }
 
327
 
 
328
        return inode;
 
329
}
 
330
 
 
331
static uint64_t
 
332
inode_to_nodeid (inode_t *inode)
 
333
{
 
334
        if (!inode || inode->ino == 1)
 
335
                return 1;
 
336
 
 
337
        return (unsigned long) inode;
 
338
}
 
339
 
 
340
 
219
341
GF_MUST_CHECK static int32_t
220
342
fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino,
221
343
               ino_t par, const char *name)
230
352
 
231
353
        inode = loc->inode;
232
354
 
233
 
        if (!inode) {
234
 
                if (ino)
235
 
                        inode = inode_search (state->itable, ino, NULL);
236
 
                if (par && name)
237
 
                        inode = inode_search (state->itable, par, name);
238
 
 
239
 
                loc->inode = inode;
240
 
                if (inode)
241
 
                        loc->ino = inode->ino;
242
 
        }
243
 
 
244
 
        parent = loc->parent;
245
 
        if (!parent) {
246
 
                if (inode)
247
 
                        parent = inode_parent (inode, par, name);
248
 
                else
249
 
                        parent = inode_search (state->itable, par, NULL);
250
 
                loc->parent = parent;
251
 
        }
252
 
 
253
 
        if (name && parent) {
 
355
        if (name) {
 
356
                parent = loc->parent;
 
357
                if (!parent) {
 
358
                        parent = fuse_ino_to_inode (par, state->itable);
 
359
                        loc->parent = parent;
 
360
                }
 
361
 
 
362
                inode = loc->inode;
 
363
                if (!inode) {
 
364
                        inode = inode_grep (state->itable, parent, name);
 
365
                        loc->inode = inode;
 
366
                }
 
367
 
254
368
                ret = inode_path (parent, name, &path);
255
369
                if (ret <= 0) {
256
370
                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
257
371
                                "inode_path failed for %"PRId64"/%s",
258
372
                                parent->ino, name);
259
373
                        goto fail;
260
 
                } else {
261
 
                        loc->path = path;
262
 
                }
263
 
        } else         if (inode) {
 
374
                }
 
375
                loc->path = path;
 
376
        } else {
 
377
                inode = loc->inode;
 
378
                if (!inode) {
 
379
                        inode = fuse_ino_to_inode (ino, state->itable);
 
380
                        loc->inode = inode;
 
381
                }
 
382
 
 
383
                parent = loc->parent;
 
384
                if (!parent) {
 
385
                        parent = inode_parent (inode, par, name);
 
386
                        loc->parent = parent;
 
387
                }
 
388
 
264
389
                ret = inode_path (inode, NULL, &path);
265
390
                if (ret <= 0) {
266
391
                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
267
392
                                "inode_path failed for %"PRId64,
268
393
                                inode->ino);
269
394
                        goto fail;
270
 
                } else {
271
 
                        loc->path = path;
272
395
                }
 
396
                loc->path = path;
273
397
        }
 
398
 
 
399
        if (inode)
 
400
                loc->ino = inode->ino;
 
401
 
274
402
        if (loc->path) {
275
403
                loc->name = strrchr (loc->path, '/');
276
404
                if (loc->name)
277
405
                        loc->name++;
278
 
                else loc->name = "";
 
406
                else
 
407
                        loc->name = "";
279
408
        }
280
409
 
281
 
        if ((ino != 1) &&
282
 
            (parent == NULL)) {
 
410
        if ((ino != 1) && (parent == NULL)) {
283
411
                gf_log ("fuse-bridge", GF_LOG_DEBUG,
284
412
                        "failed to search parent for %"PRId64"/%s (%"PRId64")",
285
413
                        (ino_t)par, name, (ino_t)ino);
292
420
}
293
421
 
294
422
 
295
 
static int
296
 
need_fresh_lookup (int32_t op_ret, int32_t op_errno,
297
 
                   loc_t *loc, struct stat *buf)
 
423
/* courtesy of folly */
 
424
static void
 
425
stat2attr (struct stat *st, struct fuse_attr *fa)
298
426
{
299
 
        if (op_ret == -1) {
300
 
                gf_log ("fuse-bridge", GF_LOG_DEBUG,
301
 
                        "revalidate of %s failed (%s)",
302
 
                        loc->path, strerror (op_errno));
303
 
                return 1;
304
 
        }
305
 
 
306
 
        if (loc->inode->ino != buf->st_ino) {
307
 
                gf_log ("fuse-bridge", GF_LOG_DEBUG,
308
 
                        "inode num of %s changed %"PRId64" -> %"PRId64,
309
 
                        loc->path, loc->inode->ino, buf->st_ino);
310
 
                return 1;
311
 
        }
312
 
 
313
 
        if ((loc->inode->st_mode & S_IFMT) ^ (buf->st_mode & S_IFMT)) {
314
 
                gf_log ("fuse-bridge", GF_LOG_DEBUG,
315
 
                        "inode mode of %s changed 0%o -> 0%o",
316
 
                        loc->path, loc->inode->st_mode, buf->st_mode);
317
 
                return 1;
318
 
        }
319
 
 
320
 
        return 0;
 
427
        fa->ino        = st->st_ino;
 
428
        fa->size       = st->st_size;
 
429
        fa->blocks     = st->st_blocks;
 
430
        fa->atime      = st->st_atime;
 
431
        fa->mtime      = st->st_mtime;
 
432
        fa->ctime      = st->st_ctime;
 
433
        fa->atimensec = ST_ATIM_NSEC (st);
 
434
        fa->mtimensec = ST_MTIM_NSEC (st);
 
435
        fa->ctimensec = ST_CTIM_NSEC (st);
 
436
        fa->mode       = st->st_mode;
 
437
        fa->nlink      = st->st_nlink;
 
438
        fa->uid        = st->st_uid;
 
439
        fa->gid        = st->st_gid;
 
440
        fa->rdev       = st->st_rdev;
 
441
        fa->blksize    = st->st_blksize;
321
442
}
322
443
 
323
444
 
324
445
static int
325
 
fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
326
 
                 int32_t op_ret, int32_t op_errno,
327
 
                 inode_t *inode, struct stat *stat, dict_t *dict);
328
 
 
329
 
static int
330
446
fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
331
447
                int32_t op_ret, int32_t op_errno,
332
448
                inode_t *inode, struct stat *buf)
333
449
{
334
450
        fuse_state_t            *state = NULL;
335
 
        fuse_req_t               req = NULL;
336
 
        struct fuse_entry_param  e = {0, };
 
451
        fuse_in_header_t        *finh = NULL;
 
452
        struct fuse_entry_out    feo = {0, };
337
453
        fuse_private_t          *priv = NULL;
 
454
        inode_t                 *linked_inode = NULL;
338
455
 
339
456
        priv = this->private;
340
457
        state = frame->root->state;
341
 
        req = state->req;
 
458
        finh = state->finh;
342
459
 
343
460
        if (!op_ret && state->loc.ino == 1) {
344
461
                buf->st_ino = 1;
345
462
        }
346
463
 
347
 
        if (state->is_revalidate == 1
348
 
            && need_fresh_lookup (op_ret, op_errno, &state->loc, buf)) {
 
464
        if (op_ret == 0) {
 
465
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
 
466
                        "%"PRIu64": %s() %s => %"PRId64" (%"PRId64")",
 
467
                        frame->root->unique, gf_fop_list[frame->root->op],
 
468
                        state->loc.path, buf->st_ino, state->loc.ino);
 
469
 
 
470
                buf->st_blksize = this->ctx->page_size;
 
471
                stat2attr (buf, &feo.attr);
 
472
 
 
473
                if (!buf->st_ino) {
 
474
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
475
                                "%"PRIu64": %s() %s returning inode 0",
 
476
                                frame->root->unique,
 
477
                                gf_fop_list[frame->root->op], state->loc.path);
 
478
                }
 
479
 
 
480
                linked_inode = inode_link (inode, state->loc.parent,
 
481
                                           state->loc.name, buf);
 
482
 
 
483
                if (linked_inode != inode) {
 
484
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
485
                                "%s(%s) inode (ptr=%p, ino=%"PRId64", "
 
486
                                "gen=%"PRId64") found conflict (ptr=%p, "
 
487
                                "ino=%"PRId64", gen=%"PRId64")",
 
488
                                gf_fop_list[frame->root->op],
 
489
                                state->loc.path, inode, inode->ino,
 
490
                                inode->generation, linked_inode,
 
491
                                linked_inode->ino, linked_inode->generation);
 
492
                }
 
493
 
 
494
                inode_lookup (linked_inode);
 
495
 
 
496
                /* TODO: make these timeouts configurable (via meta?) */
 
497
                feo.nodeid = inode_to_nodeid (linked_inode);
 
498
 
 
499
                feo.generation = linked_inode->generation;
 
500
 
 
501
                inode_unref (linked_inode);
 
502
 
 
503
                feo.entry_valid =
 
504
                        calc_timeout_sec (priv->entry_timeout);
 
505
                feo.entry_valid_nsec =
 
506
                        calc_timeout_nsec (priv->entry_timeout);
 
507
                feo.attr_valid =
 
508
                        calc_timeout_sec (priv->attribute_timeout);
 
509
                feo.attr_valid_nsec =
 
510
                        calc_timeout_nsec (priv->attribute_timeout);
 
511
 
 
512
                priv->proto_minor >= 9 ?
 
513
                        send_fuse_obj (this, finh, &feo) :
 
514
                        send_fuse_data (this, finh, &feo,
 
515
                                        FUSE_COMPAT_ENTRY_OUT_SIZE);
 
516
        } else {
 
517
                gf_log ("glusterfs-fuse",
 
518
                        (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_WARNING),
 
519
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
 
520
                        gf_fop_list[frame->root->op], state->loc.path,
 
521
                        strerror (op_errno));
 
522
                send_fuse_err (this, state->finh, op_errno);
 
523
        }
 
524
 
 
525
        free_state (state);
 
526
        STACK_DESTROY (frame->root);
 
527
        return 0;
 
528
}
 
529
 
 
530
 
 
531
static int
 
532
fuse_newentry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
533
                   int32_t op_ret, int32_t op_errno,
 
534
                   inode_t *inode, struct stat *buf, struct stat *preparent,
 
535
                   struct stat *postparent)
 
536
{
 
537
        fuse_entry_cbk (frame, cookie, this, op_ret, op_errno, inode, buf);
 
538
        return 0;
 
539
}
 
540
 
 
541
 
 
542
static int
 
543
fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
544
                 int32_t op_ret, int32_t op_errno,
 
545
                 inode_t *inode, struct stat *stat, dict_t *dict,
 
546
                 struct stat *postparent)
 
547
{
 
548
        fuse_state_t            *state = NULL;
 
549
        call_frame_t            *prev = NULL;
 
550
 
 
551
        state = frame->root->state;
 
552
        prev  = cookie;
 
553
 
 
554
        if (op_ret == -1 && state->is_revalidate == 1) {
349
555
                inode_unref (state->loc.inode);
350
556
                state->loc.inode = inode_new (state->itable);
351
557
                state->is_revalidate = 2;
352
558
 
353
559
                STACK_WIND (frame, fuse_lookup_cbk,
354
 
                            FIRST_CHILD (this),
355
 
                            FIRST_CHILD (this)->fops->lookup,
 
560
                            prev->this, prev->this->fops->lookup,
356
561
                            &state->loc, state->dict);
357
 
 
358
562
                return 0;
359
563
        }
360
564
 
361
 
        if (op_ret == 0) {
362
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
363
 
                        "%"PRId64": %s() %s => %"PRId64" (%"PRId64")",
364
 
                        frame->root->unique, gf_fop_list[frame->root->op],
365
 
                        state->loc.path, buf->st_ino, state->loc.ino);
366
 
 
367
 
                inode_link (inode, state->loc.parent, state->loc.name, buf);
368
 
 
369
 
                inode_lookup (inode);
370
 
 
371
 
                /* TODO: make these timeouts configurable (via meta?) */
372
 
                e.ino = inode->ino;
373
 
 
374
 
#ifdef GF_DARWIN_HOST_OS
375
 
                e.generation = 0;
376
 
#else
377
 
                e.generation = buf->st_ctime;
378
 
#endif
379
 
 
380
 
                buf->st_blksize = this->ctx->page_size;
381
 
                e.entry_timeout = priv->entry_timeout;
382
 
                e.attr_timeout  = priv->attribute_timeout;
383
 
                e.attr = *buf;
384
 
 
385
 
                if (!e.ino || !buf->st_ino) {
386
 
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
387
 
                                "%"PRId64": %s() %s returning inode 0",
388
 
                                frame->root->unique,
389
 
                                gf_fop_list[frame->root->op], state->loc.path);
390
 
                }
391
 
 
392
 
                if (state->loc.parent)
393
 
                        fuse_reply_entry (req, &e);
394
 
                else
395
 
                        fuse_reply_attr (req, buf, priv->attribute_timeout);
396
 
        } else {
397
 
                gf_log ("glusterfs-fuse",
398
 
                        (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_WARNING),
399
 
                        "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
400
 
                        gf_fop_list[frame->root->op], state->loc.path,
401
 
                        strerror (op_errno));
402
 
                fuse_reply_err (req, op_errno);
403
 
        }
404
 
 
405
 
        free_state (state);
406
 
        STACK_DESTROY (frame->root);
407
 
        return 0;
408
 
}
409
 
 
410
 
 
411
 
static int
412
 
fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
413
 
                 int32_t op_ret, int32_t op_errno,
414
 
                 inode_t *inode, struct stat *stat, dict_t *dict)
415
 
{
416
565
        fuse_entry_cbk (frame, cookie, this, op_ret, op_errno, inode, stat);
417
566
        return 0;
418
567
}
419
568
 
420
569
 
421
570
static void
422
 
fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name)
 
571
fuse_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg)
423
572
{
 
573
        char *name = msg;
 
574
 
424
575
        fuse_state_t *state = NULL;
425
576
        int32_t       ret = -1;
426
577
 
427
 
        state = state_from_req (req);
 
578
        GET_STATE (this, finh, state);
428
579
 
429
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
580
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
430
581
 
431
582
        if (ret < 0) {
432
583
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
433
 
                        "%"PRId64": LOOKUP %"PRId64"/%s (fuse_loc_fill() failed)",
434
 
                        req_callid (req), (ino_t)par, name);
 
584
                        "%"PRIu64": LOOKUP %"PRIu64"/%s (fuse_loc_fill() failed)",
 
585
                        finh->unique, finh->nodeid, name);
435
586
                free_state (state);
436
 
                fuse_reply_err (req, ENOENT);
 
587
                send_fuse_err (this, finh, ENOENT);
437
588
                return;
438
589
        }
439
590
 
440
591
        if (!state->loc.inode) {
441
592
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
442
 
                        "%"PRId64": LOOKUP %s", req_callid (req),
 
593
                        "%"PRIu64": LOOKUP %s", finh->unique,
443
594
                        state->loc.path);
444
595
 
445
596
                state->loc.inode = inode_new (state->itable);
446
 
                /* to differntiate in entry_cbk what kind of call it is */
447
 
                state->is_revalidate = -1;
448
597
        } else {
449
598
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
450
 
                        "%"PRId64": LOOKUP %s(%"PRId64")", req_callid (req),
 
599
                        "%"PRIu64": LOOKUP %s(%"PRId64")", finh->unique,
451
600
                        state->loc.path, state->loc.inode->ino);
452
601
                state->is_revalidate = 1;
453
602
        }
460
609
 
461
610
 
462
611
static void
463
 
fuse_forget (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
 
612
fuse_forget (xlator_t *this, fuse_in_header_t *finh, void *msg)
 
613
 
464
614
{
 
615
        struct fuse_forget_in *ffi = msg;
 
616
 
465
617
        inode_t      *fuse_inode;
466
 
        fuse_state_t *state;
467
618
 
468
 
        if (ino == 1) {
469
 
                fuse_reply_none (req);
 
619
        if (finh->nodeid == 1) {
 
620
                FREE (finh);
470
621
                return;
471
622
        }
472
623
 
473
 
        state = state_from_req (req);
474
 
        fuse_inode = inode_search (state->itable, ino, NULL);
475
 
        if (fuse_inode) {
 
624
        fuse_inode = fuse_ino_to_inode (finh->nodeid, this->itable);
 
625
 
 
626
        inode_forget (fuse_inode, ffi->nlookup);
 
627
        inode_unref (fuse_inode);
 
628
 
 
629
        FREE (finh);
 
630
}
 
631
 
 
632
 
 
633
static int
 
634
fuse_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
635
                   int32_t op_ret, int32_t op_errno, struct stat *prebuf,
 
636
                   struct stat *postbuf)
 
637
{
 
638
        fuse_state_t     *state;
 
639
        fuse_in_header_t *finh;
 
640
        fuse_private_t   *priv = NULL;
 
641
        struct fuse_attr_out fao;
 
642
 
 
643
        priv  = this->private;
 
644
        state = frame->root->state;
 
645
        finh  = state->finh;
 
646
 
 
647
        if (op_ret == 0) {
476
648
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
477
 
                        "got forget on inode (%lu)", ino);
478
 
                inode_forget (fuse_inode, nlookup);
479
 
                inode_unref (fuse_inode);
 
649
                        "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
 
650
                        gf_fop_list[frame->root->op],
 
651
                        state->loc.path ? state->loc.path : "ERR",
 
652
                        prebuf->st_ino);
 
653
 
 
654
                /* TODO: make these timeouts configurable via meta */
 
655
                /* TODO: what if the inode number has changed by now */
 
656
                postbuf->st_blksize = this->ctx->page_size;
 
657
                stat2attr (postbuf, &fao.attr);
 
658
 
 
659
                fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
 
660
                fao.attr_valid_nsec =
 
661
                  calc_timeout_nsec (priv->attribute_timeout);
 
662
 
 
663
                priv->proto_minor >= 9 ?
 
664
                send_fuse_obj (this, finh, &fao) :
 
665
                send_fuse_data (this, finh, &fao,
 
666
                                FUSE_COMPAT_ATTR_OUT_SIZE);
480
667
        } else {
481
 
                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
482
 
                        "got forget, but inode (%lu) not found", ino);
 
668
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
669
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
 
670
                        gf_fop_list[frame->root->op],
 
671
                        state->loc.path ? state->loc.path : "ERR",
 
672
                        strerror (op_errno));
 
673
 
 
674
                send_fuse_err (this, finh, op_errno);
483
675
        }
484
676
 
485
677
        free_state (state);
486
 
        fuse_reply_none (req);
 
678
        STACK_DESTROY (frame->root);
 
679
 
 
680
        return 0;
487
681
}
488
682
 
489
683
 
491
685
fuse_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
492
686
               int32_t op_ret, int32_t op_errno, struct stat *buf)
493
687
{
494
 
        fuse_state_t   *state;
495
 
        fuse_req_t      req;
496
 
        fuse_private_t *priv = NULL;
 
688
        fuse_state_t     *state;
 
689
        fuse_in_header_t *finh;
 
690
        fuse_private_t   *priv = NULL;
 
691
        struct fuse_attr_out fao;
497
692
 
498
693
        priv  = this->private;
499
694
        state = frame->root->state;
500
 
        req   = state->req;
 
695
        finh  = state->finh;
501
696
 
502
697
        if (op_ret == 0) {
503
698
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
504
 
                        "%"PRId64": %s() %s => %"PRId64, frame->root->unique,
 
699
                        "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
505
700
                        gf_fop_list[frame->root->op],
506
701
                        state->loc.path ? state->loc.path : "ERR",
507
702
                        buf->st_ino);
509
704
                /* TODO: make these timeouts configurable via meta */
510
705
                /* TODO: what if the inode number has changed by now */
511
706
                buf->st_blksize = this->ctx->page_size;
512
 
 
513
 
                fuse_reply_attr (req, buf, priv->attribute_timeout);
 
707
                stat2attr (buf, &fao.attr);
 
708
 
 
709
                fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
 
710
                fao.attr_valid_nsec =
 
711
                  calc_timeout_nsec (priv->attribute_timeout);
 
712
 
 
713
                priv->proto_minor >= 9 ?
 
714
                send_fuse_obj (this, finh, &fao) :
 
715
                send_fuse_data (this, finh, &fao,
 
716
                                FUSE_COMPAT_ATTR_OUT_SIZE);
514
717
        } else {
515
718
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
516
 
                        "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
 
719
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
517
720
                        gf_fop_list[frame->root->op],
518
721
                        state->loc.path ? state->loc.path : "ERR",
519
722
                        strerror (op_errno));
520
723
 
521
 
                fuse_reply_err (req, op_errno);
 
724
                send_fuse_err (this, finh, op_errno);
522
725
        }
523
726
 
524
727
        free_state (state);
525
728
        STACK_DESTROY (frame->root);
 
729
 
 
730
        return 0;
 
731
}
 
732
 
 
733
 
 
734
static int
 
735
fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
736
                      int32_t op_ret, int32_t op_errno,
 
737
                      inode_t *inode, struct stat *stat, dict_t *dict,
 
738
                      struct stat *postparent)
 
739
{
 
740
        fuse_attr_cbk (frame, cookie, this, op_ret, op_errno, stat);
 
741
 
526
742
        return 0;
527
743
}
528
744
 
529
745
 
530
746
static void
531
 
fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
747
fuse_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
532
748
{
533
749
        fuse_state_t *state;
534
750
        fd_t         *fd = NULL;
535
751
        int32_t       ret = -1;
536
752
 
537
 
        state = state_from_req (req);
 
753
        GET_STATE (this, finh, state);
538
754
 
539
 
        if (ino == 1) {
540
 
                ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
755
        if (finh->nodeid == 1) {
 
756
                ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
541
757
                if (ret < 0) {
542
758
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
543
 
                                "%"PRId64": GETATTR %"PRId64" (fuse_loc_fill() failed)",
544
 
                                req_callid (req), (ino_t)ino);
545
 
                        fuse_reply_err (req, ENOENT);
 
759
                                "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)",
 
760
                                finh->unique, finh->nodeid);
 
761
                        send_fuse_err (this, finh, ENOENT);
546
762
                        free_state (state);
547
763
                        return;
548
764
                }
549
765
 
550
 
                if (state->loc.inode)
551
 
                        state->is_revalidate = 1;
552
 
                else
553
 
                        state->is_revalidate = -1;
554
 
 
555
766
                state->dict = dict_new ();
556
767
 
557
 
                FUSE_FOP (state, fuse_lookup_cbk, GF_FOP_LOOKUP,
 
768
                FUSE_FOP (state, fuse_root_lookup_cbk, GF_FOP_LOOKUP,
558
769
                          lookup, &state->loc, state->dict);
559
770
                return;
560
771
        }
561
772
 
562
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
773
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
563
774
 
564
775
        if (!state->loc.inode) {
565
776
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
566
 
                        "%"PRId64": GETATTR %"PRId64" (%s) (fuse_loc_fill() returned NULL inode)",
567
 
                        req_callid (req), (int64_t)ino, state->loc.path);
568
 
                fuse_reply_err (req, ENOENT);
 
777
                        "%"PRIu64": GETATTR %"PRIu64" (%s) (fuse_loc_fill() returned NULL inode)",
 
778
                        finh->unique, finh->nodeid, state->loc.path);
 
779
                send_fuse_err (this, finh, ENOENT);
 
780
                free_state (state);
569
781
                return;
570
782
        }
571
783
 
572
 
        fd = fd_lookup (state->loc.inode, get_pid_from_req (req));
 
784
        fd = fd_lookup (state->loc.inode, finh->pid);
573
785
        state->fd = fd;
574
786
        if (!fd || S_ISDIR (state->loc.inode->st_mode)) {
575
787
                /* this is the @ret of fuse_loc_fill, checked here
577
789
                */
578
790
                if (ret < 0) {
579
791
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
580
 
                                "%"PRId64": GETATTR %"PRId64" (fuse_loc_fill() failed)",
581
 
                                req_callid (req), (ino_t)ino);
582
 
                        fuse_reply_err (req, ENOENT);
 
792
                                "%"PRIu64": GETATTR %"PRIu64" (fuse_loc_fill() failed)",
 
793
                                finh->unique, finh->nodeid);
 
794
                        send_fuse_err (this, finh, ENOENT);
583
795
                        free_state (state);
584
796
                        return;
585
797
                }
586
798
 
587
799
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
588
 
                        "%"PRId64": GETATTR %"PRId64" (%s)",
589
 
                        req_callid (req), (int64_t)ino, state->loc.path);
 
800
                        "%"PRIu64": GETATTR %"PRIu64" (%s)",
 
801
                        finh->unique, finh->nodeid, state->loc.path);
590
802
 
591
803
 
592
804
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_STAT,
594
806
        } else {
595
807
 
596
808
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
597
 
                        "%"PRId64": FGETATTR %"PRId64" (%s/%p)",
598
 
                        req_callid (req), (int64_t)ino, state->loc.path, fd);
 
809
                        "%"PRIu64": FGETATTR %"PRIu64" (%s/%p)",
 
810
                        finh->unique, finh->nodeid, state->loc.path, fd);
599
811
 
600
812
                FUSE_FOP (state,fuse_attr_cbk, GF_FOP_FSTAT,
601
813
                          fstat, fd);
608
820
             int32_t op_ret, int32_t op_errno, fd_t *fd)
609
821
{
610
822
        fuse_state_t          *state;
611
 
        fuse_req_t             req;
 
823
        fuse_in_header_t      *finh;
612
824
        fuse_private_t        *priv = NULL;
613
 
        struct fuse_file_info  fi = {0, };
 
825
        struct fuse_open_out   foo = {0, };
614
826
 
615
827
        priv = this->private;
616
828
        state = frame->root->state;
617
 
        req = state->req;
 
829
        finh = state->finh;
618
830
 
619
831
        if (op_ret >= 0) {
620
 
                fi.fh = (unsigned long) fd;
621
 
                fi.flags = state->flags;
 
832
                foo.fh = (uintptr_t) fd;
 
833
                foo.open_flags = 0;
622
834
 
623
835
                if (!S_ISDIR (fd->inode->st_mode)) {
624
 
                        if ((fi.flags & 3) && priv->direct_io_mode)
625
 
                                fi.direct_io = 1;
 
836
                        if (((state->flags & O_ACCMODE) != O_RDONLY) &&
 
837
                            priv->direct_io_mode)
 
838
                                foo.open_flags |= FOPEN_DIRECT_IO;
626
839
                }
627
840
 
628
841
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
629
 
                        "%"PRId64": %s() %s => %p", frame->root->unique,
 
842
                        "%"PRIu64": %s() %s => %p", frame->root->unique,
630
843
                        gf_fop_list[frame->root->op], state->loc.path, fd);
631
844
 
632
845
                fd_ref (fd);
633
 
                if (fuse_reply_open (req, &fi) == -ENOENT) {
 
846
                if (send_fuse_obj (this, finh, &foo) == ENOENT) {
634
847
                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
635
848
                                "open(%s) got EINTR", state->loc.path);
636
849
                        fd_unref (fd);
640
853
                fd_bind (fd);
641
854
        } else {
642
855
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
643
 
                        "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
 
856
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
644
857
                        gf_fop_list[frame->root->op], state->loc.path,
645
858
                        strerror (op_errno));
646
859
 
647
 
                fuse_reply_err (req, op_errno);
 
860
                send_fuse_err (this, finh, op_errno);
648
861
        }
649
862
out:
650
863
        free_state (state);
654
867
 
655
868
 
656
869
static void
657
 
do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
658
 
          struct fuse_file_info *fi)
659
 
{
660
 
        fuse_state_t *state = NULL;
661
 
        fd_t         *fd = NULL;
662
 
        int32_t       ret = -1;
663
 
 
664
 
        state = state_from_req (req);
665
 
        if (fi) {
666
 
                fd = FI_TO_FD (fi);
667
 
                state->fd = fd;
668
 
        }
669
 
 
670
 
        if (fd) {
671
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
672
 
                        "%"PRId64": FCHMOD %p", req_callid (req), fd);
673
 
 
674
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHMOD,
675
 
                          fchmod, fd, attr->st_mode);
676
 
        } else {
677
 
                ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
678
 
 
679
 
                if ((state->loc.inode == NULL) ||
680
 
                    (ret < 0)) {
681
 
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
682
 
                                "%"PRId64": CHMOD %"PRId64" (%s) (fuse_loc_fill() failed)",
683
 
                                req_callid (req), (int64_t)ino,
684
 
                                state->loc.path);
685
 
                        fuse_reply_err (req, ENOENT);
686
 
                        free_state (state);
687
 
                        return;
688
 
                }
689
 
 
690
 
 
691
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
692
 
                        "%"PRId64": CHMOD %s", req_callid (req),
693
 
                        state->loc.path);
694
 
 
695
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHMOD,
696
 
                          chmod, &state->loc, attr->st_mode);
697
 
        }
698
 
}
699
 
 
700
 
 
701
 
static void
702
 
do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
703
 
          int valid, struct fuse_file_info *fi)
704
 
{
705
 
        fuse_state_t *state = NULL;
706
 
        fd_t         *fd = NULL;
707
 
        int32_t       ret = -1;
708
 
        uid_t         uid = 0;
709
 
        gid_t         gid = 0;
710
 
 
711
 
        uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
712
 
        gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
713
 
        state = state_from_req (req);
714
 
 
715
 
        if (fi) {
716
 
                fd = FI_TO_FD (fi);
717
 
                state->fd = fd;
718
 
        }
719
 
 
720
 
        if (fd) {
721
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
722
 
                        "%"PRId64": FCHOWN %p", req_callid (req), fd);
723
 
 
724
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHOWN,
725
 
                          fchown, fd, uid, gid);
726
 
        } else {
727
 
                ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
728
 
                if ((state->loc.inode == NULL) ||
729
 
                    (ret < 0)) {
730
 
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
731
 
                                "%"PRId64": CHOWN %"PRId64" (%s) (fuse_loc_fill() failed)",
732
 
                                req_callid (req), (int64_t)ino,
733
 
                                state->loc.path);
734
 
                        fuse_reply_err (req, ENOENT);
735
 
                        free_state (state);
736
 
                        return;
737
 
                }
738
 
 
739
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
740
 
                        "%"PRId64": CHOWN %s", req_callid (req),
741
 
                        state->loc.path);
742
 
 
743
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHOWN,
744
 
                          chown, &state->loc, uid, gid);
745
 
        }
746
 
}
747
 
 
748
 
 
749
 
static void
750
 
do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
751
 
             struct fuse_file_info *fi)
752
 
{
753
 
        fuse_state_t *state = NULL;
754
 
        fd_t         *fd = NULL;
755
 
        int32_t       ret = -1;
756
 
 
757
 
        state = state_from_req (req);
758
 
 
759
 
        if (fi) {
760
 
                fd = FI_TO_FD (fi);
761
 
                state->fd = fd;
762
 
        }
763
 
 
764
 
        if (fd) {
765
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
766
 
                        "%"PRId64": FTRUNCATE %p/%"PRId64, req_callid (req),
767
 
                        fd, attr->st_size);
768
 
 
769
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FTRUNCATE,
770
 
                          ftruncate, fd, attr->st_size);
771
 
        } else {
772
 
                ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
773
 
                if ((state->loc.inode == NULL) ||
774
 
                    (ret < 0)) {
775
 
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
776
 
                                "%"PRId64": TRUNCATE %s/%"PRId64" (fuse_loc_fill() failed)",
777
 
                                req_callid (req), state->loc.path,
778
 
                                attr->st_size);
779
 
                        fuse_reply_err (req, ENOENT);
780
 
                        free_state (state);
781
 
                        return;
782
 
                }
783
 
 
784
 
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
785
 
                        "%"PRId64": TRUNCATE %s/%"PRId64"(%lu)",
786
 
                        req_callid (req),
787
 
                        state->loc.path, attr->st_size, ino);
788
 
 
789
 
                FUSE_FOP (state, fuse_attr_cbk, GF_FOP_TRUNCATE,
790
 
                          truncate, &state->loc, attr->st_size);
 
870
fuse_do_truncate (fuse_state_t *state, size_t size)
 
871
{
 
872
        if (state->fd) {
 
873
                FUSE_FOP (state, fuse_truncate_cbk, GF_FOP_FTRUNCATE,
 
874
                          ftruncate, state->fd, size);
 
875
        } else {
 
876
                FUSE_FOP (state, fuse_truncate_cbk, GF_FOP_TRUNCATE,
 
877
                          truncate, &state->loc, size);
791
878
        }
792
879
 
793
880
        return;
794
881
}
795
882
 
796
883
 
797
 
static void
798
 
do_utimes (fuse_req_t req, fuse_ino_t ino, struct stat *attr)
 
884
static int
 
885
fuse_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
886
                  int32_t op_ret, int32_t op_errno,
 
887
                  struct stat *statpre, struct stat *statpost)
799
888
{
800
 
        fuse_state_t    *state = NULL;
801
 
        struct timespec  tv[2];
802
 
        int32_t          ret = -1;
803
 
 
804
 
        tv[0].tv_sec  = attr->st_atime;
805
 
        tv[0].tv_nsec = ST_ATIM_NSEC (attr);
806
 
        tv[1].tv_sec  = attr->st_mtime;
807
 
        tv[1].tv_nsec = ST_ATIM_NSEC (attr);
808
 
 
809
 
        state = state_from_req (req);
810
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
811
 
        if ((state->loc.inode == NULL) ||
812
 
            (ret < 0)) {
 
889
        fuse_state_t     *state;
 
890
        fuse_in_header_t *finh;
 
891
        fuse_private_t   *priv = NULL;
 
892
        struct fuse_attr_out fao;
 
893
 
 
894
        int op_done = 0;
 
895
 
 
896
        priv  = this->private;
 
897
        state = frame->root->state;
 
898
        finh  = state->finh;
 
899
 
 
900
        if (op_ret == 0) {
 
901
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
 
902
                        "%"PRIu64": %s() %s => %"PRId64, frame->root->unique,
 
903
                        gf_fop_list[frame->root->op],
 
904
                        state->loc.path ? state->loc.path : "ERR",
 
905
                        statpost->st_ino);
 
906
 
 
907
                /* TODO: make these timeouts configurable via meta */
 
908
                /* TODO: what if the inode number has changed by now */
 
909
 
 
910
                statpost->st_blksize = this->ctx->page_size;
 
911
 
 
912
                stat2attr (statpost, &fao.attr);
 
913
 
 
914
                fao.attr_valid = calc_timeout_sec (priv->attribute_timeout);
 
915
                fao.attr_valid_nsec =
 
916
                        calc_timeout_nsec (priv->attribute_timeout);
 
917
 
 
918
                if (state->truncate_needed) {
 
919
                        fuse_do_truncate (state, state->size);
 
920
                } else {
 
921
                        priv->proto_minor >= 9 ?
 
922
                                send_fuse_obj (this, finh, &fao) :
 
923
                                send_fuse_data (this, finh, &fao,
 
924
                                                FUSE_COMPAT_ATTR_OUT_SIZE);
 
925
                        op_done = 1;
 
926
                }
 
927
        } else {
813
928
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
814
 
                        "%"PRId64": UTIMENS %s (fuse_loc_fill() failed)",
815
 
                        req_callid (req), state->loc.path);
816
 
                fuse_reply_err (req, ENOENT);
 
929
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
 
930
                        gf_fop_list[frame->root->op],
 
931
                        state->loc.path ? state->loc.path : "ERR",
 
932
                        strerror (op_errno));
 
933
 
 
934
                send_fuse_err (this, finh, op_errno);
 
935
                op_done = 1;
 
936
        }
 
937
 
 
938
        if (op_done) {
817
939
                free_state (state);
818
 
                return;
 
940
                STACK_DESTROY (frame->root);
819
941
        }
820
942
 
821
 
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
822
 
                "%"PRId64": UTIMENS (%lu)%s", req_callid (req),
823
 
                ino, state->loc.path);
824
 
 
825
 
        FUSE_FOP (state, fuse_attr_cbk, GF_FOP_UTIMENS,
826
 
                  utimens, &state->loc, tv);
827
 
}
 
943
        return 0;
 
944
}
 
945
 
 
946
 
 
947
static int32_t
 
948
fattr_to_gf_set_attr (int32_t valid)
 
949
{
 
950
        int32_t gf_valid = 0;
 
951
 
 
952
        if (valid & FATTR_MODE)
 
953
                gf_valid |= GF_SET_ATTR_MODE;
 
954
 
 
955
        if (valid & FATTR_UID)
 
956
                gf_valid |= GF_SET_ATTR_UID;
 
957
 
 
958
        if (valid & FATTR_GID)
 
959
                gf_valid |= GF_SET_ATTR_GID;
 
960
 
 
961
        if (valid & FATTR_ATIME)
 
962
                gf_valid |= GF_SET_ATTR_ATIME;
 
963
 
 
964
        if (valid & FATTR_MTIME)
 
965
                gf_valid |= GF_SET_ATTR_MTIME;
 
966
 
 
967
        if (valid & FATTR_SIZE)
 
968
                gf_valid |= GF_SET_ATTR_SIZE;
 
969
 
 
970
        return gf_valid;
 
971
}
 
972
 
 
973
 
 
974
#define FATTR_MASK   (FATTR_SIZE                        \
 
975
                      | FATTR_UID | FATTR_GID           \
 
976
                      | FATTR_ATIME | FATTR_MTIME       \
 
977
                      | FATTR_MODE)
828
978
 
829
979
 
830
980
static void
831
 
fuse_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
832
 
              int valid, struct fuse_file_info *fi)
 
981
fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
833
982
{
834
 
 
835
 
        if (valid & FUSE_SET_ATTR_MODE)
836
 
                do_chmod (req, ino, attr, fi);
837
 
        else if (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))
838
 
                do_chown (req, ino, attr, valid, fi);
839
 
        else if (valid & FUSE_SET_ATTR_SIZE)
840
 
                do_truncate (req, ino, attr, fi);
841
 
        else if (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))
842
 
                do_utimes (req, ino, attr);
 
983
        struct fuse_setattr_in *fsi = msg;
 
984
 
 
985
        struct stat attr = {0, };
 
986
 
 
987
        fuse_private_t  *priv = NULL;
 
988
        fuse_state_t *state = NULL;
 
989
        int32_t       ret   = -1;
 
990
        int32_t       valid = 0;
 
991
 
 
992
        GET_STATE (this, finh, state);
 
993
 
 
994
        if (fsi->valid & FATTR_FH &&
 
995
            !(fsi->valid & (FATTR_ATIME|FATTR_MTIME)))
 
996
                /* We need no loc if kernel sent us an fd and
 
997
                 * we are not fiddling with times */
 
998
                ret = 1;
843
999
        else
844
 
                fuse_getattr (req, ino, fi);
 
1000
                ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0,
 
1001
                                     NULL);
 
1002
 
 
1003
        /*
 
1004
         * This is just stub code demonstrating how to retrieve
 
1005
         * lock_owner in setattr, according to the FUSE proto.
 
1006
         * We do not make use of ATM. Its purpose is supporting
 
1007
         * mandatory locking, but getting that right is further
 
1008
         * down the road. Cf.
 
1009
         *
 
1010
         * http://thread.gmane.org/gmane.comp.file-systems.fuse.devel/
 
1011
         * 4962/focus=4982
 
1012
         *
 
1013
         * http://git.kernel.org/?p=linux/kernel/git/torvalds/
 
1014
         * linux-2.6.git;a=commit;h=v2.6.23-5896-gf333211
 
1015
         */
 
1016
        priv = this->private;
 
1017
        if (priv->proto_minor >= 9 && fsi->valid & FATTR_LOCKOWNER)
 
1018
                state->lk_owner = fsi->lock_owner;
 
1019
 
 
1020
        if ((state->loc.inode == NULL && ret == 0) ||
 
1021
            (ret < 0)) {
 
1022
 
 
1023
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
1024
                        "%"PRIu64": SETATTR %s (fuse_loc_fill() failed)",
 
1025
                        finh->unique, state->loc.path);
 
1026
 
 
1027
                send_fuse_err (this, finh, ENOENT);
 
1028
                free_state (state);
 
1029
 
 
1030
                return;
 
1031
        }
 
1032
 
 
1033
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
 
1034
                "%"PRIu64": SETATTR (%"PRIu64")%s", finh->unique,
 
1035
                finh->nodeid, state->loc.path);
 
1036
 
 
1037
        valid = fsi->valid;
 
1038
 
 
1039
        if (fsi->valid & FATTR_FH) {
 
1040
                state->fd = FH_TO_FD (fsi->fh);
 
1041
        }
 
1042
 
 
1043
        if ((valid & (FATTR_MASK)) != FATTR_SIZE) {
 
1044
                if (valid & FATTR_SIZE) {
 
1045
                        state->size            = fsi->size;
 
1046
                        state->truncate_needed = _gf_true;
 
1047
                }
 
1048
 
 
1049
                attr.st_size  = fsi->size;
 
1050
                attr.st_atime = fsi->atime;
 
1051
                attr.st_mtime = fsi->mtime;
 
1052
                ST_ATIM_NSEC_SET (&attr, fsi->atimensec);
 
1053
                ST_MTIM_NSEC_SET (&attr, fsi->mtimensec);
 
1054
 
 
1055
                attr.st_mode = fsi->mode;
 
1056
                attr.st_uid  = fsi->uid;
 
1057
                attr.st_gid  = fsi->gid;
 
1058
 
 
1059
                if (state->fd &&
 
1060
                    !((fsi->valid & FATTR_ATIME) || (fsi->valid & FATTR_MTIME))) {
 
1061
 
 
1062
                         /*
 
1063
                            there is no "futimes" call, so don't send
 
1064
                            fsetattr if ATIME or MTIME is set
 
1065
                         */
 
1066
 
 
1067
                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_FSETATTR,
 
1068
                                  fsetattr, state->fd, &attr,
 
1069
                                  fattr_to_gf_set_attr (fsi->valid));
 
1070
                } else {
 
1071
                        FUSE_FOP (state, fuse_setattr_cbk, GF_FOP_SETATTR,
 
1072
                                  setattr, &state->loc, &attr,
 
1073
                                  fattr_to_gf_set_attr (fsi->valid));
 
1074
                }
 
1075
        } else {
 
1076
                fuse_do_truncate (state, fsi->size);
 
1077
        }
 
1078
 
845
1079
}
846
1080
 
847
1081
 
848
1082
static int gf_fuse_xattr_enotsup_log;
 
1083
static int
 
1084
fuse_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
1085
                int32_t op_ret, int32_t op_errno, struct stat *prebuf,
 
1086
                struct stat *postbuf)
 
1087
{
 
1088
        fuse_state_t *state = frame->root->state;
 
1089
        fuse_in_header_t *finh = state->finh;
 
1090
 
 
1091
        if (op_ret == 0) {
 
1092
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
 
1093
                        "%"PRIu64": %s() %s => 0", frame->root->unique,
 
1094
                        gf_fop_list[frame->root->op],
 
1095
                        state->loc.path ? state->loc.path : "ERR");
 
1096
 
 
1097
                send_fuse_err (this, finh, 0);
 
1098
        } else {
 
1099
                if (frame->root->op == GF_FOP_SETXATTR) {
 
1100
                        op_ret = gf_compat_setxattr (state->dict);
 
1101
                        if (op_ret == 0)
 
1102
                                op_errno = 0;
 
1103
                        if (op_errno == ENOTSUP) {
 
1104
                                gf_fuse_xattr_enotsup_log++;
 
1105
                                if (!(gf_fuse_xattr_enotsup_log % GF_UNIVERSAL_ANSWER))
 
1106
                                        gf_log ("glusterfs-fuse",
 
1107
                                                GF_LOG_CRITICAL,
 
1108
                                                "extended attribute not "
 
1109
                                                "supported by the backend "
 
1110
                                                "storage");
 
1111
                        }
 
1112
                } else {
 
1113
                        if ((frame->root->op == GF_FOP_REMOVEXATTR)
 
1114
                            && (op_errno == ENOATTR)) {
 
1115
                                goto nolog;
 
1116
                        }
 
1117
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
1118
                                "%"PRIu64": %s() %s => -1 (%s)",
 
1119
                                frame->root->unique,
 
1120
                                gf_fop_list[frame->root->op],
 
1121
                                state->loc.path ? state->loc.path : "ERR",
 
1122
                                strerror (op_errno));
 
1123
                }
 
1124
        nolog:
 
1125
 
 
1126
                send_fuse_err (this, finh, op_errno);
 
1127
        }
 
1128
 
 
1129
        free_state (state);
 
1130
        STACK_DESTROY (frame->root);
 
1131
 
 
1132
        return 0;
 
1133
}
 
1134
 
849
1135
 
850
1136
static int
851
1137
fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
852
1138
              int32_t op_ret, int32_t op_errno)
853
1139
{
854
1140
        fuse_state_t *state = frame->root->state;
855
 
        fuse_req_t req = state->req;
 
1141
        fuse_in_header_t *finh = state->finh;
856
1142
 
857
1143
        if (op_ret == 0) {
858
1144
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
859
 
                        "%"PRId64": %s() %s => 0", frame->root->unique,
 
1145
                        "%"PRIu64": %s() %s => 0", frame->root->unique,
860
1146
                        gf_fop_list[frame->root->op],
861
1147
                        state->loc.path ? state->loc.path : "ERR");
862
1148
 
863
 
                fuse_reply_err (req, 0);
 
1149
                send_fuse_err (this, finh, 0);
864
1150
        } else {
865
1151
                if (frame->root->op == GF_FOP_SETXATTR) {
866
1152
                        op_ret = gf_compat_setxattr (state->dict);
881
1167
                                goto nolog;
882
1168
                        }
883
1169
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
884
 
                                "%"PRId64": %s() %s => -1 (%s)",
 
1170
                                "%"PRIu64": %s() %s => -1 (%s)",
885
1171
                                frame->root->unique,
886
1172
                                gf_fop_list[frame->root->op],
887
1173
                                state->loc.path ? state->loc.path : "ERR",
889
1175
                }
890
1176
        nolog:
891
1177
 
892
 
                fuse_reply_err (req, op_errno);
 
1178
                send_fuse_err (this, finh, op_errno);
893
1179
        }
894
1180
 
895
1181
        free_state (state);
901
1187
 
902
1188
static int
903
1189
fuse_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
904
 
                 int32_t op_ret, int32_t op_errno)
 
1190
                 int32_t op_ret, int32_t op_errno, struct stat *preparent,
 
1191
                 struct stat *postparent)
905
1192
{
906
 
        fuse_state_t *state = NULL;
907
 
        fuse_req_t    req = NULL;
 
1193
        fuse_state_t     *state = NULL;
 
1194
        fuse_in_header_t *finh = NULL;
908
1195
 
909
1196
        state = frame->root->state;
910
 
        req = state->req;
 
1197
        finh = state->finh;
911
1198
 
912
1199
        if (op_ret == 0)
913
1200
                inode_unlink (state->loc.inode, state->loc.parent,
915
1202
 
916
1203
        if (op_ret == 0) {
917
1204
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
918
 
                        "%"PRId64": %s() %s => 0", frame->root->unique,
 
1205
                        "%"PRIu64": %s() %s => 0", frame->root->unique,
919
1206
                        gf_fop_list[frame->root->op], state->loc.path);
920
1207
 
921
 
                fuse_reply_err (req, 0);
 
1208
                send_fuse_err (this, finh, 0);
922
1209
        } else {
923
1210
                gf_log ("glusterfs-fuse",
924
1211
                        op_errno == ENOTEMPTY ? GF_LOG_DEBUG : GF_LOG_WARNING,
925
 
                        "%"PRId64": %s() %s => -1 (%s)", frame->root->unique,
 
1212
                        "%"PRIu64": %s() %s => -1 (%s)", frame->root->unique,
926
1213
                        gf_fop_list[frame->root->op], state->loc.path,
927
1214
                        strerror (op_errno));
928
1215
 
929
 
                fuse_reply_err (req, op_errno);
 
1216
                send_fuse_err (this, finh, op_errno);
930
1217
        }
931
1218
 
932
1219
        free_state (state);
937
1224
 
938
1225
 
939
1226
static void
940
 
fuse_access (fuse_req_t req, fuse_ino_t ino, int mask)
 
1227
fuse_access (xlator_t *this, fuse_in_header_t *finh, void *msg)
941
1228
{
 
1229
        struct fuse_access_in *fai = msg;
 
1230
 
942
1231
        fuse_state_t *state = NULL;
943
1232
        int32_t       ret = -1;
944
1233
 
945
 
        state = state_from_req (req);
 
1234
        GET_STATE (this, finh, state);
946
1235
 
947
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
1236
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
948
1237
        if ((state->loc.inode == NULL) ||
949
1238
            (ret < 0)) {
950
1239
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
951
 
                        "%"PRId64": ACCESS %"PRId64" (%s) (fuse_loc_fill() failed)",
952
 
                        req_callid (req), (int64_t)ino, state->loc.path);
953
 
                fuse_reply_err (req, ENOENT);
 
1240
                        "%"PRIu64": ACCESS %"PRIu64" (%s) (fuse_loc_fill() failed)",
 
1241
                        finh->unique, finh->nodeid, state->loc.path);
 
1242
                send_fuse_err (this, finh, ENOENT);
954
1243
                free_state (state);
955
1244
                return;
956
1245
        }
957
1246
 
958
1247
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
959
 
                "%"PRId64" ACCESS %s/%lu mask=%d", req_callid (req),
960
 
                state->loc.path, ino, mask);
 
1248
                "%"PRIu64" ACCESS %s/%"PRIu64" mask=%d", finh->unique,
 
1249
                state->loc.path, finh->nodeid, fai->mask);
961
1250
 
962
1251
        FUSE_FOP (state, fuse_err_cbk,
963
1252
                  GF_FOP_ACCESS, access,
964
 
                  &state->loc, mask);
 
1253
                  &state->loc, fai->mask);
965
1254
 
966
1255
        return;
967
1256
}
969
1258
 
970
1259
static int
971
1260
fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
972
 
                   int32_t op_ret, int32_t op_errno, const char *linkname)
 
1261
                   int32_t op_ret, int32_t op_errno, const char *linkname,
 
1262
                   struct stat *buf)
973
1263
{
974
 
        fuse_state_t *state = NULL;
975
 
        fuse_req_t    req = NULL;
 
1264
        fuse_state_t     *state = NULL;
 
1265
        fuse_in_header_t *finh = NULL;
976
1266
 
977
1267
        state = frame->root->state;
978
 
        req = state->req;
 
1268
        finh = state->finh;
979
1269
 
980
1270
        if (op_ret > 0) {
981
1271
                ((char *)linkname)[op_ret] = '\0';
982
1272
 
983
1273
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
984
 
                        "%"PRId64": %s => %s", frame->root->unique,
 
1274
                        "%"PRIu64": %s => %s", frame->root->unique,
985
1275
                        state->loc.path, linkname);
986
1276
 
987
 
                fuse_reply_readlink (req, linkname);
 
1277
                send_fuse_data (this, finh, (void *)linkname, op_ret + 1);
988
1278
        } else {
989
1279
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
990
 
                        "%"PRId64": %s => -1 (%s)", frame->root->unique,
 
1280
                        "%"PRIu64": %s => -1 (%s)", frame->root->unique,
991
1281
                        state->loc.path, strerror (op_errno));
992
1282
 
993
 
                fuse_reply_err (req, op_errno);
 
1283
                send_fuse_err (this, finh, op_errno);
994
1284
        }
995
1285
 
996
1286
        free_state (state);
1001
1291
 
1002
1292
 
1003
1293
static void
1004
 
fuse_readlink (fuse_req_t req, fuse_ino_t ino)
 
1294
fuse_readlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
1005
1295
{
1006
1296
        fuse_state_t *state = NULL;
1007
1297
        int32_t       ret = -1;
1008
1298
 
1009
 
        state = state_from_req (req);
1010
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
1299
        GET_STATE (this, finh, state);
 
1300
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
1011
1301
        if ((state->loc.inode == NULL) ||
1012
1302
            (ret < 0)) {
1013
1303
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1014
 
                        "%"PRId64" READLINK %s/%"PRId64" (fuse_loc_fill() returned NULL inode)",
1015
 
                        req_callid (req), state->loc.path,
 
1304
                        "%"PRIu64" READLINK %s/%"PRId64" (fuse_loc_fill() returned NULL inode)",
 
1305
                        finh->unique, state->loc.path,
1016
1306
                        state->loc.inode->ino);
1017
 
                fuse_reply_err (req, ENOENT);
 
1307
                send_fuse_err (this, finh, ENOENT);
1018
1308
                free_state (state);
1019
1309
                return;
1020
1310
        }
1021
1311
 
1022
1312
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1023
 
                "%"PRId64" READLINK %s/%"PRId64, req_callid (req),
 
1313
                "%"PRIu64" READLINK %s/%"PRId64, finh->unique,
1024
1314
                state->loc.path, state->loc.inode->ino);
1025
1315
 
1026
1316
        FUSE_FOP (state, fuse_readlink_cbk, GF_FOP_READLINK,
1031
1321
 
1032
1322
 
1033
1323
static void
1034
 
fuse_mknod (fuse_req_t req, fuse_ino_t par, const char *name,
1035
 
            mode_t mode, dev_t rdev)
 
1324
fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg)
1036
1325
{
1037
 
        fuse_state_t *state = NULL;
1038
 
        int32_t       ret = -1;
1039
 
 
1040
 
        state = state_from_req (req);
1041
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1326
        struct fuse_mknod_in *fmi = msg;
 
1327
        char         *name = (char *)(fmi + 1);
 
1328
 
 
1329
        fuse_state_t   *state = NULL;
 
1330
        fuse_private_t *priv = NULL;
 
1331
        int32_t         ret = -1;
 
1332
 
 
1333
        priv = this->private;
 
1334
        if (priv->proto_minor < 12)
 
1335
                name = (char *)msg + FUSE_COMPAT_MKNOD_IN_SIZE;
 
1336
 
 
1337
        GET_STATE (this, finh, state);
 
1338
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1042
1339
        if (ret < 0) {
1043
1340
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1044
 
                        "%"PRId64" MKNOD %s (fuse_loc_fill() failed)",
1045
 
                        req_callid (req), state->loc.path);
1046
 
                fuse_reply_err (req, ENOENT);
 
1341
                        "%"PRIu64" MKNOD %s (fuse_loc_fill() failed)",
 
1342
                        finh->unique, state->loc.path);
 
1343
                send_fuse_err (this, finh, ENOENT);
1047
1344
                free_state (state);
1048
1345
                return;
1049
1346
        }
1051
1348
        state->loc.inode = inode_new (state->itable);
1052
1349
 
1053
1350
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1054
 
                "%"PRId64": MKNOD %s", req_callid (req),
 
1351
                "%"PRIu64": MKNOD %s", finh->unique,
1055
1352
                state->loc.path);
1056
1353
 
1057
 
        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKNOD,
1058
 
                  mknod, &state->loc, mode, rdev);
 
1354
        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKNOD,
 
1355
                  mknod, &state->loc, fmi->mode, fmi->rdev);
1059
1356
 
1060
1357
        return;
1061
1358
}
1062
1359
 
1063
1360
 
1064
1361
static void
1065
 
fuse_mkdir (fuse_req_t req, fuse_ino_t par, const char *name, mode_t mode)
 
1362
fuse_mkdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1066
1363
{
 
1364
        struct fuse_mkdir_in *fmi = msg;
 
1365
        char *name = (char *)(fmi + 1);
 
1366
 
1067
1367
        fuse_state_t *state;
1068
1368
        int32_t ret = -1;
1069
1369
 
1070
 
        state = state_from_req (req);
1071
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1370
        GET_STATE (this, finh, state);
 
1371
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1072
1372
        if (ret < 0) {
1073
1373
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1074
 
                        "%"PRId64" MKDIR %s (fuse_loc_fill() failed)",
1075
 
                        req_callid (req), state->loc.path);
1076
 
                fuse_reply_err (req, ENOENT);
 
1374
                        "%"PRIu64" MKDIR %s (fuse_loc_fill() failed)",
 
1375
                        finh->unique, state->loc.path);
 
1376
                send_fuse_err (this, finh, ENOENT);
1077
1377
                free_state (state);
1078
1378
                return;
1079
1379
        }
1081
1381
        state->loc.inode = inode_new (state->itable);
1082
1382
 
1083
1383
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1084
 
                "%"PRId64": MKDIR %s", req_callid (req),
 
1384
                "%"PRIu64": MKDIR %s", finh->unique,
1085
1385
                state->loc.path);
1086
1386
 
1087
 
        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKDIR,
1088
 
                  mkdir, &state->loc, mode);
 
1387
        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_MKDIR,
 
1388
                  mkdir, &state->loc, fmi->mode);
1089
1389
 
1090
1390
        return;
1091
1391
}
1092
1392
 
1093
1393
 
1094
1394
static void
1095
 
fuse_unlink (fuse_req_t req, fuse_ino_t par, const char *name)
 
1395
fuse_unlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
1096
1396
{
 
1397
        char         *name = msg;
 
1398
 
1097
1399
        fuse_state_t *state = NULL;
1098
1400
        int32_t       ret = -1;
1099
1401
 
1100
 
        state = state_from_req (req);
 
1402
        GET_STATE (this, finh, state);
1101
1403
 
1102
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1404
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1103
1405
 
1104
1406
        if ((state->loc.inode == NULL) ||
1105
1407
            (ret < 0)) {
1106
1408
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1107
 
                        "%"PRId64": UNLINK %s (fuse_loc_fill() returned NULL inode)",
1108
 
                        req_callid (req), state->loc.path);
1109
 
                fuse_reply_err (req, ENOENT);
 
1409
                        "%"PRIu64": UNLINK %s (fuse_loc_fill() returned NULL inode)",
 
1410
                        finh->unique, state->loc.path);
 
1411
                send_fuse_err (this, finh, ENOENT);
1110
1412
                free_state (state);
1111
1413
                return;
1112
1414
        }
1113
1415
 
1114
1416
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1115
 
                "%"PRId64": UNLINK %s", req_callid (req),
 
1417
                "%"PRIu64": UNLINK %s", finh->unique,
1116
1418
                state->loc.path);
1117
1419
 
1118
1420
        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_UNLINK,
1123
1425
 
1124
1426
 
1125
1427
static void
1126
 
fuse_rmdir (fuse_req_t req, fuse_ino_t par, const char *name)
 
1428
fuse_rmdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1127
1429
{
 
1430
        char         *name = msg;
 
1431
 
1128
1432
        fuse_state_t *state = NULL;
1129
1433
        int32_t       ret = -1;
1130
1434
 
1131
 
        state = state_from_req (req);
1132
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1435
        GET_STATE (this, finh, state);
 
1436
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1133
1437
        if ((state->loc.inode == NULL) ||
1134
1438
            (ret < 0)) {
1135
1439
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1136
 
                        "%"PRId64": RMDIR %s (fuse_loc_fill() failed)",
1137
 
                        req_callid (req), state->loc.path);
1138
 
                fuse_reply_err (req, ENOENT);
 
1440
                        "%"PRIu64": RMDIR %s (fuse_loc_fill() failed)",
 
1441
                        finh->unique, state->loc.path);
 
1442
                send_fuse_err (this, finh, ENOENT);
1139
1443
                free_state (state);
1140
1444
                return;
1141
1445
        }
1142
1446
 
1143
1447
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1144
 
                "%"PRId64": RMDIR %s", req_callid (req),
 
1448
                "%"PRIu64": RMDIR %s", finh->unique,
1145
1449
                state->loc.path);
1146
1450
 
1147
1451
        FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_RMDIR,
1152
1456
 
1153
1457
 
1154
1458
static void
1155
 
fuse_symlink (fuse_req_t req, const char *linkname, fuse_ino_t par,
1156
 
              const char *name)
 
1459
fuse_symlink (xlator_t *this, fuse_in_header_t *finh, void *msg)
1157
1460
{
 
1461
        char *name = msg;
 
1462
        char *linkname = name + strlen (name) + 1;
 
1463
 
1158
1464
        fuse_state_t *state = NULL;
1159
1465
        int32_t       ret = -1;
1160
1466
 
1161
 
        state = state_from_req (req);
1162
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1467
        GET_STATE (this, finh, state);
 
1468
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1163
1469
        if (ret < 0) {
1164
1470
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1165
 
                        "%"PRId64" SYMLINK %s -> %s (fuse_loc_fill() failed)",
1166
 
                        req_callid (req), state->loc.path, linkname);
1167
 
                fuse_reply_err (req, ENOENT);
 
1471
                        "%"PRIu64" SYMLINK %s -> %s (fuse_loc_fill() failed)",
 
1472
                        finh->unique, state->loc.path, linkname);
 
1473
                send_fuse_err (this, finh, ENOENT);
1168
1474
                free_state (state);
1169
1475
                return;
1170
1476
        }
1172
1478
        state->loc.inode = inode_new (state->itable);
1173
1479
 
1174
1480
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1175
 
                "%"PRId64": SYMLINK %s -> %s", req_callid (req),
 
1481
                "%"PRIu64": SYMLINK %s -> %s", finh->unique,
1176
1482
                state->loc.path, linkname);
1177
1483
 
1178
 
        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_SYMLINK,
 
1484
        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_SYMLINK,
1179
1485
                  symlink, linkname, &state->loc);
1180
1486
 
1181
1487
        return;
1184
1490
 
1185
1491
int
1186
1492
fuse_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
1187
 
                 int32_t op_ret, int32_t op_errno, struct stat *buf)
 
1493
                 int32_t op_ret, int32_t op_errno, struct stat *buf,
 
1494
                 struct stat *preoldparent, struct stat *postoldparent,
 
1495
                 struct stat *prenewparent, struct stat *postnewparent)
1188
1496
{
1189
 
        fuse_state_t *state = NULL;
1190
 
        fuse_req_t    req = NULL;
 
1497
        fuse_state_t     *state = NULL;
 
1498
        fuse_in_header_t *finh = NULL;
1191
1499
 
1192
1500
        state = frame->root->state;
1193
 
        req   = state->req;
 
1501
        finh  = state->finh;
1194
1502
 
1195
1503
        if (op_ret == 0) {
1196
1504
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1197
 
                        "%"PRId64": %s -> %s => 0 (buf->st_ino=%"PRId64" , loc->ino=%"PRId64")",
 
1505
                        "%"PRIu64": %s -> %s => 0 (buf->st_ino=%"PRId64" , loc->ino=%"PRId64")",
1198
1506
                        frame->root->unique, state->loc.path, state->loc2.path,
1199
1507
                        buf->st_ino, state->loc.ino);
1200
1508
 
1212
1520
                              state->loc2.parent, state->loc2.name,
1213
1521
                              state->loc.inode, buf);
1214
1522
 
1215
 
                fuse_reply_err (req, 0);
 
1523
                send_fuse_err (this, finh, 0);
1216
1524
        } else {
1217
1525
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1218
 
                        "%"PRId64": %s -> %s => -1 (%s)", frame->root->unique,
 
1526
                        "%"PRIu64": %s -> %s => -1 (%s)", frame->root->unique,
1219
1527
                        state->loc.path, state->loc2.path,
1220
1528
                        strerror (op_errno));
1221
 
                fuse_reply_err (req, op_errno);
 
1529
                send_fuse_err (this, finh, op_errno);
1222
1530
        }
1223
1531
 
1224
1532
        free_state (state);
1228
1536
 
1229
1537
 
1230
1538
static void
1231
 
fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname,
1232
 
             fuse_ino_t newpar, const char *newname)
 
1539
fuse_rename (xlator_t *this, fuse_in_header_t *finh, void *msg)
1233
1540
{
 
1541
        struct fuse_rename_in  *fri = msg;
 
1542
        char *oldname = (char *)(fri + 1);
 
1543
        char *newname = oldname + strlen (oldname) + 1;
 
1544
 
1234
1545
        fuse_state_t *state = NULL;
1235
1546
        int32_t       ret = -1;
1236
1547
 
1237
 
        state = state_from_req (req);
 
1548
        GET_STATE (this, finh, state);
1238
1549
 
1239
 
        ret = fuse_loc_fill (&state->loc, state, 0, oldpar, oldname);
 
1550
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, oldname);
1240
1551
        if ((state->loc.inode == NULL) ||
1241
1552
            (ret < 0)) {
1242
1553
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1243
 
                        "for %s %"PRId64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
1244
 
                        state->loc.path, req_callid (req), state->loc.path,
 
1554
                        "for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
 
1555
                        state->loc.path, finh->unique, state->loc.path,
1245
1556
                        state->loc2.path);
1246
1557
 
1247
 
                fuse_reply_err (req, ENOENT);
 
1558
                send_fuse_err (this, finh, ENOENT);
1248
1559
                free_state (state);
1249
1560
                return;
1250
1561
        }
1251
1562
 
1252
 
        ret = fuse_loc_fill (&state->loc2, state, 0, newpar, newname);
 
1563
        ret = fuse_loc_fill (&state->loc2, state, 0, fri->newdir, newname);
1253
1564
        if (ret < 0) {
1254
1565
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1255
 
                        "for %s %"PRId64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
1256
 
                        state->loc.path, req_callid (req), state->loc.path,
 
1566
                        "for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)",
 
1567
                        state->loc.path, finh->unique, state->loc.path,
1257
1568
                        state->loc2.path);
1258
1569
 
1259
 
                fuse_reply_err (req, ENOENT);
 
1570
                send_fuse_err (this, finh, ENOENT);
1260
1571
                free_state (state);
1261
1572
                return;
1262
1573
               }
1263
1574
 
1264
1575
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1265
 
                "%"PRId64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'",
1266
 
                req_callid (req), state->loc.path, state->loc.ino,
 
1576
                "%"PRIu64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'",
 
1577
                finh->unique, state->loc.path, state->loc.ino,
1267
1578
                state->loc2.path, state->loc2.ino);
1268
1579
 
1269
1580
        FUSE_FOP (state, fuse_rename_cbk, GF_FOP_RENAME,
1274
1585
 
1275
1586
 
1276
1587
static void
1277
 
fuse_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t par, const char *name)
 
1588
fuse_link (xlator_t *this, fuse_in_header_t *finh, void *msg)
1278
1589
{
 
1590
        struct fuse_link_in *fli = msg;
 
1591
        char         *name = (char *)(fli + 1);
 
1592
 
1279
1593
        fuse_state_t *state = NULL;
1280
1594
        int32_t       ret = -1;
1281
1595
 
1282
 
        state = state_from_req (req);
 
1596
        GET_STATE (this, finh, state);
1283
1597
 
1284
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
1285
 
        ret = fuse_loc_fill (&state->loc2, state, ino, 0, NULL);
 
1598
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
 
1599
        if (ret == 0)
 
1600
                ret = fuse_loc_fill (&state->loc2, state, fli->oldnodeid, 0,
 
1601
                                     NULL);
1286
1602
 
1287
1603
        if ((state->loc2.inode == NULL) ||
1288
1604
            (ret < 0)) {
1289
1605
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1290
 
                        "fuse_loc_fill() failed for %s %"PRId64": LINK %s %s",
1291
 
                        state->loc2.path, req_callid (req),
 
1606
                        "fuse_loc_fill() failed for %s %"PRIu64": LINK %s %s",
 
1607
                        state->loc2.path, finh->unique,
1292
1608
                        state->loc2.path, state->loc.path);
1293
 
                fuse_reply_err (req, ENOENT);
 
1609
                send_fuse_err (this, finh, ENOENT);
1294
1610
                free_state (state);
1295
1611
                return;
1296
1612
        }
1297
1613
 
1298
1614
        state->loc.inode = inode_ref (state->loc2.inode);
1299
1615
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1300
 
                "%"PRId64": LINK() %s (%"PRId64") -> %s (%"PRId64")",
1301
 
                req_callid (req), state->loc2.path, state->loc2.ino,
 
1616
                "%"PRIu64": LINK() %s (%"PRId64") -> %s (%"PRId64")",
 
1617
                finh->unique, state->loc2.path, state->loc2.ino,
1302
1618
                state->loc.path, state->loc.ino);
1303
1619
 
1304
 
        FUSE_FOP (state, fuse_entry_cbk, GF_FOP_LINK,
 
1620
        FUSE_FOP (state, fuse_newentry_cbk, GF_FOP_LINK,
1305
1621
                  link, &state->loc2, &state->loc);
1306
1622
 
1307
1623
        return;
1311
1627
static int
1312
1628
fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
1313
1629
                 int32_t op_ret, int32_t op_errno,
1314
 
                 fd_t *fd, inode_t *inode, struct stat *buf)
 
1630
                 fd_t *fd, inode_t *inode, struct stat *buf,
 
1631
                 struct stat *preparent, struct stat *postparent)
1315
1632
{
1316
1633
        fuse_state_t            *state = NULL;
1317
 
        fuse_req_t               req = NULL;
 
1634
        fuse_in_header_t        *finh = NULL;
1318
1635
        fuse_private_t          *priv = NULL;
1319
 
        struct fuse_file_info    fi = {0, };
1320
 
        struct fuse_entry_param  e = {0, };
 
1636
        struct fuse_out_header   fouh = {0, };
 
1637
        struct fuse_entry_out    feo = {0, };
 
1638
        struct fuse_open_out     foo = {0, };
 
1639
        struct iovec             iov_out[3];
 
1640
        inode_t                 *linked_inode = NULL;
 
1641
 
1321
1642
 
1322
1643
        state    = frame->root->state;
1323
1644
        priv     = this->private;
1324
 
        req      = state->req;
1325
 
        fi.flags = state->flags;
 
1645
        finh     = state->finh;
 
1646
        foo.open_flags = 0;
1326
1647
 
1327
1648
        if (op_ret >= 0) {
1328
 
                fi.fh = (unsigned long) fd;
 
1649
                foo.fh = (uintptr_t) fd;
1329
1650
 
1330
 
                if ((fi.flags & 3) && priv->direct_io_mode)
1331
 
                        fi.direct_io = 1;
 
1651
                if (((state->flags & O_ACCMODE) != O_RDONLY) &&
 
1652
                    priv->direct_io_mode)
 
1653
                        foo.open_flags |= FOPEN_DIRECT_IO;
1332
1654
 
1333
1655
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1334
 
                        "%"PRId64": %s() %s => %p (ino=%"PRId64")",
 
1656
                        "%"PRIu64": %s() %s => %p (ino=%"PRId64")",
1335
1657
                        frame->root->unique, gf_fop_list[frame->root->op],
1336
1658
                        state->loc.path, fd, buf->st_ino);
1337
1659
 
1338
 
                e.ino = buf->st_ino;
1339
 
 
1340
 
#ifdef GF_DARWIN_HOST_OS
1341
 
                e.generation = 0;
1342
 
#else
1343
 
                e.generation = buf->st_ctime;
1344
 
#endif
1345
 
 
1346
1660
                buf->st_blksize = this->ctx->page_size;
1347
 
                e.entry_timeout = priv->entry_timeout;
1348
 
                e.attr_timeout = priv->attribute_timeout;
1349
 
                e.attr = *buf;
1350
 
 
1351
 
                fi.keep_cache = 0;
1352
 
 
1353
 
                inode_link (inode, state->loc.parent,
1354
 
                            state->loc.name, buf);
1355
 
 
1356
 
                inode_lookup (inode);
 
1661
                stat2attr (buf, &feo.attr);
 
1662
 
 
1663
                linked_inode = inode_link (inode, state->loc.parent,
 
1664
                                           state->loc.name, buf);
 
1665
 
 
1666
                if (linked_inode != inode) {
 
1667
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
1668
                                "create(%s) inode (ptr=%p, ino=%"PRId64", "
 
1669
                                "gen=%"PRId64") found conflict (ptr=%p, "
 
1670
                                "ino=%"PRId64", gen=%"PRId64")",
 
1671
                                state->loc.path, inode, inode->ino,
 
1672
                                inode->generation, linked_inode,
 
1673
                                linked_inode->ino, linked_inode->generation);
 
1674
 
 
1675
                        /*
 
1676
                           VERY racy code (if used anywhere else)
 
1677
                           -- don't do this without understanding
 
1678
                        */
 
1679
                        inode_unref (fd->inode);
 
1680
                        fd->inode = inode_ref (linked_inode);
 
1681
                }
 
1682
 
 
1683
                inode_lookup (linked_inode);
 
1684
 
 
1685
                inode_unref (linked_inode);
1357
1686
 
1358
1687
                fd_ref (fd);
1359
 
                if (fuse_reply_create (req, &e, &fi) == -ENOENT) {
 
1688
 
 
1689
                feo.nodeid = inode_to_nodeid (linked_inode);
 
1690
 
 
1691
                feo.generation = linked_inode->generation;
 
1692
 
 
1693
                feo.entry_valid = calc_timeout_sec (priv->entry_timeout);
 
1694
                feo.entry_valid_nsec = calc_timeout_nsec (priv->entry_timeout);
 
1695
                feo.attr_valid = calc_timeout_sec (priv->attribute_timeout);
 
1696
                feo.attr_valid_nsec =
 
1697
                  calc_timeout_nsec (priv->attribute_timeout);
 
1698
 
 
1699
                fouh.error = 0;
 
1700
                iov_out[0].iov_base = &fouh;
 
1701
                iov_out[1].iov_base = &feo;
 
1702
                iov_out[1].iov_len = priv->proto_minor >= 9 ?
 
1703
                                     sizeof (feo) :
 
1704
                                     FUSE_COMPAT_ENTRY_OUT_SIZE;
 
1705
                iov_out[2].iov_base = &foo;
 
1706
                iov_out[2].iov_len = sizeof (foo);
 
1707
                if (send_fuse_iov (this, finh, iov_out, 3) == ENOENT) {
1360
1708
                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
1361
1709
                                "create(%s) got EINTR", state->loc.path);
1362
1710
                        inode_forget (inode, 1);
1367
1715
                fd_bind (fd);
1368
1716
        } else {
1369
1717
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1370
 
                        "%"PRId64": %s => -1 (%s)", req_callid (req),
 
1718
                        "%"PRIu64": %s => -1 (%s)", finh->unique,
1371
1719
                        state->loc.path, strerror (op_errno));
1372
 
                fuse_reply_err (req, op_errno);
 
1720
                send_fuse_err (this, finh, op_errno);
1373
1721
        }
1374
1722
out:
1375
1723
        free_state (state);
1380
1728
 
1381
1729
 
1382
1730
static void
1383
 
fuse_create (fuse_req_t req, fuse_ino_t par, const char *name,
1384
 
             mode_t mode, struct fuse_file_info *fi)
 
1731
fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg)
1385
1732
{
 
1733
        struct fuse_create_in *fci = msg;
 
1734
        char         *name = (char *)(fci + 1);
 
1735
 
 
1736
        fuse_private_t        *priv = NULL;
1386
1737
        fuse_state_t *state = NULL;
1387
1738
        fd_t         *fd = NULL;
1388
1739
        int32_t       ret = -1;
1389
1740
 
1390
 
        state = state_from_req (req);
1391
 
        state->flags = fi->flags;
1392
 
 
1393
 
        ret = fuse_loc_fill (&state->loc, state, 0, par, name);
 
1741
        priv = this->private;
 
1742
        if (priv->proto_minor < 12)
 
1743
                name = (char *)((struct fuse_open_in *)msg + 1);
 
1744
 
 
1745
        GET_STATE (this, finh, state);
 
1746
        state->flags = fci->flags;
 
1747
 
 
1748
        ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name);
1394
1749
        if (ret < 0) {
1395
1750
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1396
 
                        "%"PRId64" CREATE %s (fuse_loc_fill() failed)",
1397
 
                        req_callid (req), state->loc.path);
1398
 
                fuse_reply_err (req, ENOENT);
 
1751
                        "%"PRIu64" CREATE %s (fuse_loc_fill() failed)",
 
1752
                        finh->unique, state->loc.path);
 
1753
                send_fuse_err (this, finh, ENOENT);
1399
1754
                free_state (state);
1400
1755
                return;
1401
1756
        }
1402
1757
 
1403
1758
        state->loc.inode = inode_new (state->itable);
1404
1759
 
1405
 
        fd = fd_create (state->loc.inode, get_pid_from_req (req));
 
1760
        fd = fd_create (state->loc.inode, finh->pid);
1406
1761
        state->fd = fd;
1407
1762
        fd->flags = state->flags;
1408
1763
 
1409
1764
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1410
 
                "%"PRId64": CREATE %s", req_callid (req),
 
1765
                "%"PRIu64": CREATE %s", finh->unique,
1411
1766
                state->loc.path);
1412
1767
 
1413
1768
        FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE,
1414
 
                  create, &state->loc, state->flags, mode, fd);
 
1769
                  create, &state->loc, state->flags, fci->mode, fd);
1415
1770
 
1416
1771
        return;
1417
1772
}
1418
1773
 
1419
1774
 
1420
1775
static void
1421
 
fuse_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
1776
fuse_open (xlator_t *this, fuse_in_header_t *finh, void *msg)
1422
1777
{
 
1778
        struct fuse_open_in *foi = msg;
 
1779
 
1423
1780
        fuse_state_t *state = NULL;
1424
1781
        fd_t         *fd = NULL;
1425
1782
        int32_t       ret = -1;
1426
1783
 
1427
 
        state = state_from_req (req);
1428
 
        state->flags = fi->flags;
 
1784
        GET_STATE (this, finh, state);
 
1785
        state->flags = foi->flags;
1429
1786
 
1430
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
1787
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
1431
1788
        if ((state->loc.inode == NULL) ||
1432
1789
            (ret < 0)) {
1433
1790
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1434
 
                        "%"PRId64": OPEN %s (fuse_loc_fill() failed)",
1435
 
                        req_callid (req), state->loc.path);
 
1791
                        "%"PRIu64": OPEN %s (fuse_loc_fill() failed)",
 
1792
                        finh->unique, state->loc.path);
1436
1793
 
1437
 
                fuse_reply_err (req, ENOENT);
 
1794
                send_fuse_err (this, finh, ENOENT);
1438
1795
                free_state (state);
1439
1796
                return;
1440
1797
        }
1441
1798
 
1442
 
        fd = fd_create (state->loc.inode, get_pid_from_req (req));
 
1799
        fd = fd_create (state->loc.inode, finh->pid);
1443
1800
        state->fd = fd;
1444
 
        fd->flags = fi->flags;
 
1801
        fd->flags = foi->flags;
1445
1802
 
1446
1803
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1447
 
                "%"PRId64": OPEN %s", req_callid (req),
 
1804
                "%"PRIu64": OPEN %s", finh->unique,
1448
1805
                state->loc.path);
1449
1806
 
1450
1807
        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN,
1451
 
                  open, &state->loc, fi->flags, fd);
 
1808
                  open, &state->loc, foi->flags, fd, 0);
1452
1809
 
1453
1810
        return;
1454
1811
}
1461
1818
                struct stat *stbuf, struct iobref *iobref)
1462
1819
{
1463
1820
        fuse_state_t *state = NULL;
1464
 
        fuse_req_t    req = NULL;
 
1821
        fuse_in_header_t *finh = NULL;
 
1822
        struct fuse_out_header fouh = {0, };
 
1823
        struct iovec *iov_out = NULL;
1465
1824
 
1466
1825
        state = frame->root->state;
1467
 
        req = state->req;
 
1826
        finh = state->finh;
1468
1827
 
1469
1828
        if (op_ret >= 0) {
1470
1829
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1471
 
                        "%"PRId64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
 
1830
                        "%"PRIu64": READ => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
1472
1831
                        frame->root->unique,
1473
1832
                        op_ret, state->size, state->off, stbuf->st_size);
1474
1833
 
1475
 
#ifdef HAVE_FUSE_REPLY_IOV
1476
 
                fuse_reply_iov (req, vector, count);
1477
 
#else
1478
 
                fuse_reply_vec (req, vector, count);
1479
 
#endif
 
1834
                iov_out = CALLOC (count + 1, sizeof (*iov_out));
 
1835
                if (iov_out) {
 
1836
                        fouh.error = 0;
 
1837
                        iov_out[0].iov_base = &fouh;
 
1838
                        memcpy (iov_out + 1, vector, count * sizeof (*iov_out));
 
1839
                        send_fuse_iov (this, finh, iov_out, count + 1);
 
1840
                        FREE (iov_out);
 
1841
                } else
 
1842
                        send_fuse_err (this, finh, ENOMEM);
1480
1843
        } else {
1481
1844
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1482
 
                        "%"PRId64": READ => %d (%s)", frame->root->unique,
 
1845
                        "%"PRIu64": READ => %d (%s)", frame->root->unique,
1483
1846
                        op_ret, strerror (op_errno));
1484
1847
 
1485
 
                fuse_reply_err (req, op_errno);
 
1848
                send_fuse_err (this, finh, op_errno);
1486
1849
        }
1487
1850
 
1488
1851
        free_state (state);
1493
1856
 
1494
1857
 
1495
1858
static void
1496
 
fuse_readv (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
1497
 
            struct fuse_file_info *fi)
 
1859
fuse_readv (xlator_t *this, fuse_in_header_t *finh, void *msg)
1498
1860
{
 
1861
        struct fuse_read_in *fri = msg;
 
1862
 
 
1863
        fuse_private_t  *priv = NULL;
1499
1864
        fuse_state_t *state = NULL;
1500
1865
        fd_t         *fd = NULL;
1501
1866
 
1502
 
        state = state_from_req (req);
1503
 
        state->size = size;
1504
 
        state->off = off;
1505
 
 
1506
 
        fd = FI_TO_FD (fi);
 
1867
        GET_STATE (this, finh, state);
 
1868
 
 
1869
        state->size = fri->size;
 
1870
        state->off = fri->offset;
 
1871
 
 
1872
        fd = FH_TO_FD (fri->fh);
1507
1873
        state->fd = fd;
1508
1874
 
 
1875
        /* See comment by similar code in fuse_settatr */
 
1876
        priv = this->private;
 
1877
        if (priv->proto_minor >= 9 && fri->read_flags & FUSE_READ_LOCKOWNER)
 
1878
                state->lk_owner = fri->lock_owner;
 
1879
 
1509
1880
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1510
 
                "%"PRId64": READ (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
1511
 
                req_callid (req), fd, size, off);
 
1881
                "%"PRIu64": READ (%p, size=%"PRIu32", offset=%"PRIu64")",
 
1882
                finh->unique, fd, fri->size, fri->offset);
1512
1883
 
1513
1884
        FUSE_FOP (state, fuse_readv_cbk, GF_FOP_READ,
1514
 
                  readv, fd, size, off);
 
1885
                  readv, fd, fri->size, fri->offset);
1515
1886
 
1516
1887
}
1517
1888
 
1519
1890
static int
1520
1891
fuse_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
1521
1892
                 int32_t op_ret, int32_t op_errno,
1522
 
                 struct stat *stbuf)
 
1893
                 struct stat *stbuf, struct stat *postbuf)
1523
1894
{
1524
1895
        fuse_state_t *state = NULL;
1525
 
        fuse_req_t    req = NULL;
 
1896
        fuse_in_header_t *finh = NULL;
 
1897
        struct fuse_write_out fwo = {0, };
1526
1898
 
1527
1899
        state = frame->root->state;
1528
 
        req = state->req;
 
1900
        finh = state->finh;
1529
1901
 
1530
1902
        if (op_ret >= 0) {
1531
1903
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1532
 
                        "%"PRId64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
 
1904
                        "%"PRIu64": WRITE => %d/%"GF_PRI_SIZET",%"PRId64"/%"PRId64,
1533
1905
                        frame->root->unique,
1534
1906
                        op_ret, state->size, state->off, stbuf->st_size);
1535
1907
 
1536
 
                fuse_reply_write (req, op_ret);
 
1908
                fwo.size = op_ret;
 
1909
                send_fuse_obj (this, finh, &fwo);
1537
1910
        } else {
1538
1911
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1539
 
                        "%"PRId64": WRITE => -1 (%s)", frame->root->unique,
 
1912
                        "%"PRIu64": WRITE => -1 (%s)", frame->root->unique,
1540
1913
                        strerror (op_errno));
1541
1914
 
1542
 
                fuse_reply_err (req, op_errno);
 
1915
                send_fuse_err (this, finh, op_errno);
1543
1916
        }
1544
1917
 
1545
1918
        free_state (state);
1550
1923
 
1551
1924
 
1552
1925
static void
1553
 
fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf,
1554
 
            size_t size, off_t off,
1555
 
            struct fuse_file_info *fi)
 
1926
fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg)
1556
1927
{
 
1928
        /* WRITE is special, metadata is attached to in_header,
 
1929
         * and msg is the payload as-is.
 
1930
         */
 
1931
        struct fuse_write_in *fwi = (struct fuse_write_in *)
 
1932
                                      (finh + 1);
 
1933
 
 
1934
        fuse_private_t  *priv = NULL;
1557
1935
        fuse_state_t    *state = NULL;
1558
1936
        struct iovec     vector;
1559
1937
        fd_t            *fd = NULL;
1560
1938
        struct iobref   *iobref = NULL;
1561
1939
        struct iobuf    *iobuf = NULL;
1562
1940
 
1563
 
        state       = state_from_req (req);
1564
 
        state->size = size;
1565
 
        state->off  = off;
1566
 
        fd          = FI_TO_FD (fi);
 
1941
        priv = this->private;
 
1942
 
 
1943
        GET_STATE (this, finh, state);
 
1944
        state->size = fwi->size;
 
1945
        state->off  = fwi->offset;
 
1946
        fd          = FH_TO_FD (fwi->fh);
1567
1947
        state->fd   = fd;
1568
 
        vector.iov_base = (void *)buf;
1569
 
        vector.iov_len  = size;
 
1948
        vector.iov_base = msg;
 
1949
        vector.iov_len  = fwi->size;
 
1950
 
 
1951
        /* See comment by similar code in fuse_settatr */
 
1952
        priv = this->private;
 
1953
        if (priv->proto_minor >= 9 && fwi->write_flags & FUSE_WRITE_LOCKOWNER)
 
1954
                state->lk_owner = fwi->lock_owner;
1570
1955
 
1571
1956
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1572
 
                "%"PRId64": WRITE (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
1573
 
                req_callid (req), fd, size, off);
 
1957
                "%"PRIu64": WRITE (%p, size=%"PRIu32", offset=%"PRId64")",
 
1958
                finh->unique, fd, fwi->size, fwi->offset);
1574
1959
 
1575
1960
        iobref = iobref_new ();
 
1961
        if (!iobref) {
 
1962
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
1963
                        "%"PRIu64": WRITE iobref allocation failed",
 
1964
                        finh->unique);
 
1965
 
 
1966
                free_state (state);
 
1967
                return;
 
1968
        }
1576
1969
        iobuf = ((fuse_private_t *) (state->this->private))->iobuf;
1577
1970
        iobref_add (iobref, iobuf);
1578
1971
 
1579
1972
        FUSE_FOP (state, fuse_writev_cbk, GF_FOP_WRITE,
1580
 
                  writev, fd, &vector, 1, off, iobref);
 
1973
                  writev, fd, &vector, 1, fwi->offset, iobref);
1581
1974
 
1582
1975
        iobref_unref (iobref);
1583
1976
        return;
1585
1978
 
1586
1979
 
1587
1980
static void
1588
 
fuse_flush (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
1981
fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg)
1589
1982
{
 
1983
        struct fuse_flush_in *ffi = msg;
 
1984
 
1590
1985
        fuse_state_t *state = NULL;
1591
1986
        fd_t         *fd = NULL;
1592
1987
 
1593
 
        state = state_from_req (req);
1594
 
        fd = FI_TO_FD (fi);
 
1988
        GET_STATE (this, finh, state);
 
1989
        fd = FH_TO_FD (ffi->fh);
1595
1990
        state->fd = fd;
1596
1991
        if (fd)
1597
 
                fd->flush_unique = req_callid (req);
 
1992
                fd->flush_unique = finh->unique;
 
1993
 
 
1994
        state->lk_owner = ffi->lock_owner;
1598
1995
 
1599
1996
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1600
 
                "%"PRId64": FLUSH %p", req_callid (req), fd);
 
1997
                "%"PRIu64": FLUSH %p", finh->unique, fd);
1601
1998
 
1602
1999
        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH,
1603
2000
                  flush, fd);
1607
2004
 
1608
2005
 
1609
2006
static void
1610
 
fuse_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
2007
fuse_release (xlator_t *this, fuse_in_header_t *finh, void *msg)
1611
2008
{
 
2009
        struct fuse_release_in *fri = msg;
 
2010
 
 
2011
        fd_t     *fd = NULL;
 
2012
        int do_flush = 0;
 
2013
 
1612
2014
        fuse_state_t *state = NULL;
1613
 
        fd_t            *fd = NULL;
1614
 
        int        do_flush = 0;
1615
2015
 
1616
 
        state = state_from_req (req);
1617
 
        fd = FI_TO_FD (fi);
 
2016
        GET_STATE (this, finh, state);
 
2017
        fd = FH_TO_FD (fri->fh);
1618
2018
        state->fd = fd;
 
2019
 
1619
2020
#ifdef  GF_LINUX_HOST_OS
1620
2021
        /* This is an ugly Linux specific hack, relying on subtle
1621
2022
         * implementation details.
1646
2047
         * Note #3: cf. Bug #223.
1647
2048
         */
1648
2049
 
1649
 
        if (fd && fd->flush_unique + 1 != req_callid (req))
 
2050
        if (fd && fd->flush_unique + 1 != finh->unique)
1650
2051
                do_flush = 1;
1651
2052
#endif
1652
2053
 
1653
2054
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1654
 
                "%"PRId64": RELEASE %p%s", req_callid (req), fd,
 
2055
                "%"PRIu64": RELEASE %p%s", finh->unique, fd,
1655
2056
                do_flush ? " (FLUSH implied)" : "");
1656
2057
 
1657
2058
        if (do_flush) {
 
2059
                state->lk_owner = (uint64_t)-1;
1658
2060
                FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, flush, fd);
1659
2061
                fd_unref (fd);
1660
2062
        } else {
1661
2063
                fd_unref (fd);
1662
2064
 
1663
 
                fuse_reply_err (req, 0);
 
2065
                send_fuse_err (this, finh, 0);
1664
2066
 
1665
2067
                free_state (state);
1666
2068
        }
1670
2072
 
1671
2073
 
1672
2074
static void
1673
 
fuse_fsync (fuse_req_t req, fuse_ino_t ino, int datasync,
1674
 
            struct fuse_file_info *fi)
 
2075
fuse_fsync (xlator_t *this, fuse_in_header_t *finh, void *msg)
1675
2076
{
 
2077
        struct fuse_fsync_in *fsi = msg;
 
2078
 
1676
2079
        fuse_state_t *state = NULL;
1677
2080
        fd_t         *fd = NULL;
1678
2081
 
1679
 
        state = state_from_req (req);
1680
 
        fd = FI_TO_FD (fi);
 
2082
        GET_STATE (this, finh, state);
 
2083
        fd = FH_TO_FD (fsi->fh);
1681
2084
        state->fd = fd;
1682
2085
 
1683
2086
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1684
 
                "%"PRId64": FSYNC %p", req_callid (req), fd);
 
2087
                "%"PRIu64": FSYNC %p", finh->unique, fd);
1685
2088
 
1686
 
        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNC,
1687
 
                  fsync, fd, datasync);
 
2089
        /* fsync_flags: 1 means "datasync" (no defines for this) */
 
2090
        FUSE_FOP (state, fuse_fsync_cbk, GF_FOP_FSYNC,
 
2091
                  fsync, fd, fsi->fsync_flags & 1);
1688
2092
 
1689
2093
        return;
1690
2094
}
1691
2095
 
1692
2096
 
1693
2097
static void
1694
 
fuse_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
2098
fuse_opendir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1695
2099
{
 
2100
        /*
 
2101
        struct fuse_open_in *foi = msg;
 
2102
         */
 
2103
 
1696
2104
        fuse_state_t *state = NULL;
1697
2105
        fd_t         *fd = NULL;
1698
2106
        int32_t       ret = -1;
1699
2107
 
1700
 
        state = state_from_req (req);
1701
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
2108
        GET_STATE (this, finh, state);
 
2109
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
1702
2110
        if ((state->loc.inode == NULL) ||
1703
2111
            (ret < 0)) {
1704
2112
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1705
 
                        "%"PRId64": OPENDIR %s (fuse_loc_fill() failed)",
1706
 
                        req_callid (req), state->loc.path);
 
2113
                        "%"PRIu64": OPENDIR %s (fuse_loc_fill() failed)",
 
2114
                        finh->unique, state->loc.path);
1707
2115
 
1708
 
                fuse_reply_err (req, ENOENT);
 
2116
                send_fuse_err (this, finh, ENOENT);
1709
2117
                free_state (state);
1710
2118
                return;
1711
2119
        }
1712
2120
 
1713
 
        fd = fd_create (state->loc.inode, get_pid_from_req (req));
 
2121
        fd = fd_create (state->loc.inode, finh->pid);
1714
2122
        state->fd = fd;
1715
2123
 
1716
2124
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1717
 
                "%"PRId64": OPENDIR %s", req_callid (req),
 
2125
                "%"PRIu64": OPENDIR %s", finh->unique,
1718
2126
                state->loc.path);
1719
2127
 
1720
2128
        FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPENDIR,
1722
2130
}
1723
2131
 
1724
2132
 
 
2133
unsigned char
 
2134
d_type_from_stat (struct stat *buf)
 
2135
{
 
2136
        unsigned char d_type;
 
2137
 
 
2138
        if (S_ISLNK (buf->st_mode)) {
 
2139
                d_type = DT_LNK;
 
2140
 
 
2141
        } else if (S_ISDIR (buf->st_mode)) {
 
2142
                d_type = DT_DIR;
 
2143
 
 
2144
        } else if (S_ISFIFO (buf->st_mode)) {
 
2145
                d_type = DT_FIFO;
 
2146
 
 
2147
        } else if (S_ISSOCK (buf->st_mode)) {
 
2148
                d_type = DT_SOCK;
 
2149
 
 
2150
        } else if (S_ISCHR (buf->st_mode)) {
 
2151
                d_type = DT_CHR;
 
2152
 
 
2153
        } else if (S_ISBLK (buf->st_mode)) {
 
2154
                d_type = DT_BLK;
 
2155
 
 
2156
        } else if (S_ISREG (buf->st_mode)) {
 
2157
                d_type = DT_REG;
 
2158
 
 
2159
        } else {
 
2160
                d_type = DT_UNKNOWN;
 
2161
        }
 
2162
 
 
2163
        return d_type;
 
2164
}
 
2165
 
 
2166
 
1725
2167
static int
1726
2168
fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
1727
2169
                  int32_t op_ret, int32_t op_errno, gf_dirent_t *entries)
1728
2170
{
1729
2171
        fuse_state_t *state = NULL;
1730
 
        fuse_req_t    req = NULL;
 
2172
        fuse_in_header_t *finh = NULL;
1731
2173
        int           size = 0;
1732
 
        int           entry_size = 0;
1733
2174
        char         *buf = NULL;
1734
2175
        gf_dirent_t  *entry = NULL;
1735
 
        struct stat   stbuf = {0, };
 
2176
        struct fuse_dirent *fde = NULL;
1736
2177
 
1737
2178
        state = frame->root->state;
1738
 
        req   = state->req;
 
2179
        finh  = state->finh;
1739
2180
 
1740
2181
        if (op_ret < 0) {
1741
2182
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1742
 
                        "%"PRId64": READDIR => -1 (%s)", frame->root->unique,
 
2183
                        "%"PRIu64": READDIR => -1 (%s)", frame->root->unique,
1743
2184
                        strerror (op_errno));
1744
2185
 
1745
 
                fuse_reply_err (req, op_errno);
 
2186
                send_fuse_err (this, finh, op_errno);
1746
2187
                goto out;
1747
2188
        }
1748
2189
 
1749
2190
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1750
 
                "%"PRId64": READDIR => %d/%"GF_PRI_SIZET",%"PRId64,
 
2191
                "%"PRIu64": READDIR => %d/%"GF_PRI_SIZET",%"PRId64,
1751
2192
                frame->root->unique, op_ret, state->size, state->off);
1752
2193
 
1753
2194
        list_for_each_entry (entry, &entries->list, list) {
1754
 
                size += fuse_dirent_size (strlen (entry->d_name));
 
2195
                size += FUSE_DIRENT_ALIGN (FUSE_NAME_OFFSET +
 
2196
                                           strlen (entry->d_name));
1755
2197
        }
1756
2198
 
1757
2199
        buf = CALLOC (1, size);
1758
2200
        if (!buf) {
1759
2201
                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
1760
 
                        "%"PRId64": READDIR => -1 (%s)", frame->root->unique,
 
2202
                        "%"PRIu64": READDIR => -1 (%s)", frame->root->unique,
1761
2203
                        strerror (ENOMEM));
1762
 
                fuse_reply_err (req, -ENOMEM);
 
2204
                send_fuse_err (this, finh, ENOMEM);
1763
2205
                goto out;
1764
2206
        }
1765
2207
 
1766
2208
        size = 0;
1767
2209
        list_for_each_entry (entry, &entries->list, list) {
1768
 
                stbuf.st_ino = entry->d_ino;
1769
 
                entry_size = fuse_dirent_size (strlen (entry->d_name));
1770
 
                fuse_add_direntry (req, buf + size, entry_size,
1771
 
                                   entry->d_name, &stbuf,
1772
 
                                   entry->d_off);
1773
 
                size += entry_size;
 
2210
                fde = (struct fuse_dirent *)(buf + size);
 
2211
                fde->ino = entry->d_ino;
 
2212
                fde->off = entry->d_off;
 
2213
                fde->type = d_type_from_stat (&entry->d_stat);
 
2214
                fde->namelen = strlen (entry->d_name);
 
2215
                strncpy (fde->name, entry->d_name, fde->namelen);
 
2216
                size += FUSE_DIRENT_SIZE (fde);
1774
2217
        }
1775
2218
 
1776
 
        fuse_reply_buf (req, (void *)buf, size);
 
2219
        send_fuse_data (this, finh, buf, size);
1777
2220
 
1778
2221
out:
1779
2222
        free_state (state);
1786
2229
 
1787
2230
 
1788
2231
static void
1789
 
fuse_readdir (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
1790
 
              struct fuse_file_info *fi)
 
2232
fuse_readdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1791
2233
{
 
2234
        struct fuse_read_in *fri = msg;
 
2235
 
1792
2236
        fuse_state_t *state = NULL;
1793
2237
        fd_t         *fd = NULL;
1794
2238
 
1795
 
        state = state_from_req (req);
1796
 
        state->size = size;
1797
 
        state->off = off;
1798
 
        fd = FI_TO_FD (fi);
 
2239
        GET_STATE (this, finh, state);
 
2240
        state->size = fri->size;
 
2241
        state->off = fri->offset;
 
2242
        fd = FH_TO_FD (fri->fh);
1799
2243
        state->fd = fd;
1800
2244
 
1801
2245
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1802
 
                "%"PRId64": READDIR (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")",
1803
 
                req_callid (req), fd, size, off);
 
2246
                "%"PRIu64": READDIR (%p, size=%"PRIu32", offset=%"PRId64")",
 
2247
                finh->unique, fd, fri->size, fri->offset);
1804
2248
 
1805
 
        FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIR,
1806
 
                  readdir, fd, size, off);
 
2249
        FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIRP,
 
2250
                  readdirp, fd, fri->size, fri->offset);
1807
2251
}
1808
2252
 
1809
2253
 
1810
2254
static void
1811
 
fuse_releasedir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 
2255
fuse_releasedir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1812
2256
{
 
2257
        struct fuse_release_in *fri = msg;
 
2258
 
1813
2259
        fuse_state_t *state = NULL;
1814
2260
 
1815
 
        state = state_from_req (req);
1816
 
        state->fd = FI_TO_FD (fi);
 
2261
        GET_STATE (this, finh, state);
 
2262
        state->fd = FH_TO_FD (fri->fh);
1817
2263
 
1818
2264
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1819
 
                "%"PRId64": RELEASEDIR %p", req_callid (req), state->fd);
 
2265
                "%"PRIu64": RELEASEDIR %p", finh->unique, state->fd);
1820
2266
 
1821
2267
        fd_unref (state->fd);
1822
2268
 
1823
 
        fuse_reply_err (req, 0);
 
2269
        send_fuse_err (this, finh, 0);
1824
2270
 
1825
2271
        free_state (state);
1826
2272
 
1829
2275
 
1830
2276
 
1831
2277
static void
1832
 
fuse_fsyncdir (fuse_req_t req, fuse_ino_t ino, int datasync,
1833
 
               struct fuse_file_info *fi)
 
2278
fuse_fsyncdir (xlator_t *this, fuse_in_header_t *finh, void *msg)
1834
2279
{
 
2280
        struct fuse_fsync_in *fsi = msg;
 
2281
 
1835
2282
        fuse_state_t *state = NULL;
1836
2283
        fd_t         *fd = NULL;
1837
2284
 
1838
 
        fd = FI_TO_FD (fi);
 
2285
        fd = FH_TO_FD (fsi->fh);
1839
2286
 
1840
 
        state = state_from_req (req);
 
2287
        GET_STATE (this, finh, state);
1841
2288
        state->fd = fd;
1842
2289
 
1843
2290
        FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNCDIR,
1844
 
                  fsyncdir, fd, datasync);
 
2291
                  fsyncdir, fd, fsi->fsync_flags & 1);
1845
2292
 
1846
2293
        return;
1847
2294
}
1852
2299
                 int32_t op_ret, int32_t op_errno, struct statvfs *buf)
1853
2300
{
1854
2301
        fuse_state_t *state = NULL;
1855
 
        fuse_req_t    req = NULL;
 
2302
        fuse_in_header_t *finh = NULL;
 
2303
        fuse_private_t   *priv = NULL;
 
2304
        struct fuse_statfs_out fso = {{0, }, };
1856
2305
 
1857
2306
        state = frame->root->state;
1858
 
        req   = state->req;
 
2307
        priv  = this->private;
 
2308
        finh  = state->finh;
1859
2309
        /*
1860
2310
          Filesystems (like ZFS on solaris) reports
1861
2311
          different ->f_frsize and ->f_bsize. Old coreutils
1884
2334
 
1885
2335
                buf->f_frsize = buf->f_bsize =this->ctx->page_size;
1886
2336
#endif /* GF_DARWIN_HOST_OS */
1887
 
                fuse_reply_statfs (req, buf);
 
2337
                fso.st.bsize   = buf->f_bsize;
 
2338
                fso.st.frsize  = buf->f_frsize;
 
2339
                fso.st.blocks  = buf->f_blocks;
 
2340
                fso.st.bfree   = buf->f_bfree;
 
2341
                fso.st.bavail  = buf->f_bavail;
 
2342
                fso.st.files   = buf->f_files;
 
2343
                fso.st.ffree   = buf->f_ffree;
 
2344
                fso.st.namelen = buf->f_namemax;
1888
2345
 
 
2346
                priv->proto_minor >= 4 ?
 
2347
                send_fuse_obj (this, finh, &fso) :
 
2348
                send_fuse_data (this, finh, &fso, FUSE_COMPAT_STATFS_SIZE);
1889
2349
        } else {
1890
2350
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1891
 
                        "%"PRId64": ERR => -1 (%s)", frame->root->unique,
 
2351
                        "%"PRIu64": ERR => -1 (%s)", frame->root->unique,
1892
2352
                        strerror (op_errno));
1893
 
                fuse_reply_err (req, op_errno);
 
2353
                send_fuse_err (this, finh, op_errno);
1894
2354
        }
1895
2355
 
1896
2356
        free_state (state);
1901
2361
 
1902
2362
 
1903
2363
static void
1904
 
fuse_statfs (fuse_req_t req, fuse_ino_t ino)
 
2364
fuse_statfs (xlator_t *this, fuse_in_header_t *finh, void *msg)
1905
2365
{
1906
2366
        fuse_state_t *state = NULL;
1907
2367
        int32_t       ret = -1;
1908
2368
 
1909
 
        state = state_from_req (req);
 
2369
        GET_STATE (this, finh, state);
1910
2370
        ret = fuse_loc_fill (&state->loc, state, 1, 0, NULL);
1911
2371
        if ((state->loc.inode == NULL) ||
1912
2372
            (ret < 0)) {
1913
2373
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1914
 
                        "%"PRId64": STATFS (fuse_loc_fill() fail)",
1915
 
                        req_callid (req));
 
2374
                        "%"PRIu64": STATFS (fuse_loc_fill() fail)",
 
2375
                        finh->unique);
1916
2376
 
1917
 
                fuse_reply_err (req, ENOENT);
 
2377
                send_fuse_err (this, finh, ENOENT);
1918
2378
                free_state (state);
1919
2379
                return;
1920
2380
        }
1921
2381
 
1922
2382
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1923
 
                "%"PRId64": STATFS", req_callid (req));
 
2383
                "%"PRIu64": STATFS", finh->unique);
1924
2384
 
1925
2385
        FUSE_FOP (state, fuse_statfs_cbk, GF_FOP_STATFS,
1926
2386
                  statfs, &state->loc);
1928
2388
 
1929
2389
 
1930
2390
static void
1931
 
fuse_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name,
1932
 
               const char *value, size_t size, int flags)
 
2391
fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
1933
2392
{
 
2393
        struct fuse_setxattr_in *fsi = msg;
 
2394
        char         *name = (char *)(fsi + 1);
 
2395
        char         *value = name + strlen (name) + 1;
 
2396
 
1934
2397
        fuse_state_t *state = NULL;
1935
2398
        char         *dict_value = NULL;
1936
2399
        int32_t       ret = -1;
1937
2400
 
1938
2401
#ifdef DISABLE_POSIX_ACL
1939
2402
        if (!strncmp (name, "system.", 7)) {
1940
 
                fuse_reply_err (req, EOPNOTSUPP);
 
2403
                send_fuse_err (this, finh, EOPNOTSUPP);
 
2404
                FREE (finh);
1941
2405
                return;
1942
2406
        }
1943
2407
#endif
1944
2408
 
1945
 
        state = state_from_req (req);
1946
 
        state->size = size;
1947
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
2409
        GET_STATE (this, finh, state);
 
2410
        state->size = fsi->size;
 
2411
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
1948
2412
        if ((state->loc.inode == NULL) ||
1949
2413
            (ret < 0)) {
1950
2414
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
1951
 
                        "%"PRId64": SETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
1952
 
                        req_callid (req),
1953
 
                        state->loc.path, (int64_t)ino, name);
 
2415
                        "%"PRIu64": SETXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
 
2416
                        finh->unique,
 
2417
                        state->loc.path, finh->nodeid, name);
1954
2418
 
1955
 
                fuse_reply_err (req, ENOENT);
 
2419
                send_fuse_err (this, finh, ENOENT);
1956
2420
                free_state (state);
1957
2421
                return;
1958
2422
        }
1959
2423
 
1960
2424
        state->dict = get_new_dict ();
1961
 
 
1962
 
        dict_value = memdup (value, size);
 
2425
        if (!state->dict) {
 
2426
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
2427
                        "%"PRIu64": SETXATTR dict allocation failed",
 
2428
                        finh->unique);
 
2429
 
 
2430
                free_state (state);
 
2431
                return;
 
2432
        }
 
2433
 
 
2434
        dict_value = memdup (value, fsi->size);
1963
2435
        dict_set (state->dict, (char *)name,
1964
 
                  data_from_dynptr ((void *)dict_value, size));
 
2436
                  data_from_dynptr ((void *)dict_value, fsi->size));
1965
2437
        dict_ref (state->dict);
1966
2438
 
1967
2439
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
1968
 
                "%"PRId64": SETXATTR %s/%"PRId64" (%s)", req_callid (req),
1969
 
                state->loc.path, (int64_t)ino, name);
 
2440
                "%"PRIu64": SETXATTR %s/%"PRIu64" (%s)", finh->unique,
 
2441
                state->loc.path, finh->nodeid, name);
1970
2442
 
1971
2443
        FUSE_FOP (state, fuse_err_cbk, GF_FOP_SETXATTR,
1972
 
                  setxattr, &state->loc, state->dict, flags);
 
2444
                  setxattr, &state->loc, state->dict, fsi->flags);
1973
2445
 
1974
2446
        return;
1975
2447
}
1976
2448
 
1977
2449
static void
1978
 
fuse_reply_xattr_buf (fuse_state_t *state, fuse_req_t req, const char *value,
1979
 
                     size_t ret)
 
2450
send_fuse_xattr (xlator_t *this, fuse_in_header_t *finh, const char *value,
 
2451
                 size_t size, size_t expected)
1980
2452
{
 
2453
        struct fuse_getxattr_out fgxo;
 
2454
 
1981
2455
        /* linux kernel limits the size of xattr value to 64k */
1982
 
        if (ret > GLUSTERFS_XATTR_LEN_MAX)
1983
 
                fuse_reply_err (req, E2BIG);
1984
 
        else if (state->size) {
 
2456
        if (size > GLUSTERFS_XATTR_LEN_MAX)
 
2457
                send_fuse_err (this, finh, E2BIG);
 
2458
        else if (expected) {
1985
2459
                /* if callback for getxattr and asks for value */
1986
 
                if (ret > state->size)
 
2460
                if (size > expected)
1987
2461
                        /* reply would be bigger than
1988
2462
                         * what was asked by kernel */
1989
 
                        fuse_reply_err (req, ERANGE);
 
2463
                        send_fuse_err (this, finh, ERANGE);
1990
2464
                else
1991
 
                        fuse_reply_buf (req, value, ret);
1992
 
        } else
1993
 
                fuse_reply_xattr (req, ret);
 
2465
                        send_fuse_data (this, finh, (void *)value, size);
 
2466
        } else {
 
2467
                fgxo.size = size;
 
2468
                send_fuse_obj (this, finh, &fgxo);
 
2469
        }
1994
2470
}
1995
2471
 
1996
2472
static int
2000
2476
        int             need_to_free_dict = 0;
2001
2477
        char           *value = "";
2002
2478
        fuse_state_t   *state = NULL;
2003
 
        fuse_req_t      req = NULL;
 
2479
        fuse_in_header_t *finh = NULL;
2004
2480
        int32_t         dummy_ret = 0;
2005
2481
        data_t         *value_data = NULL;
2006
2482
        fuse_private_t *priv = NULL;
2014
2490
        priv  = this->private;
2015
2491
        ret   = op_ret;
2016
2492
        state = frame->root->state;
2017
 
        req   = state->req;
 
2493
        finh  = state->finh;
2018
2494
        dummy_ret = 0;
2019
2495
 
2020
2496
#ifdef GF_DARWIN_HOST_OS
2043
2519
 
2044
2520
        if (ret >= 0) {
2045
2521
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2046
 
                        "%"PRId64": %s() %s => %d", frame->root->unique,
 
2522
                        "%"PRIu64": %s() %s => %d", frame->root->unique,
2047
2523
                        gf_fop_list[frame->root->op], state->loc.path, op_ret);
2048
2524
 
2049
2525
                /* if successful */
2054
2530
                                ret = value_data->len; /* Don't return the value for '\0' */
2055
2531
                                value = value_data->data;
2056
2532
 
2057
 
                                fuse_reply_xattr_buf (state, req, value, ret);
 
2533
                                send_fuse_xattr (this, finh, value, ret, state->size);
2058
2534
                                /* if(ret >...)...else if...else */
2059
2535
                        }  else if (!strcmp (state->name, "user.glusterfs-booster-volfile")) {
2060
2536
                                if (!priv->volfile) {
2065
2541
                                                gf_log (this->name,
2066
2542
                                                        GF_LOG_ERROR,
2067
2543
                                                        "fstat on fd (%d) failed (%s)", fd, strerror (errno));
2068
 
                                                fuse_reply_err (req, ENODATA);
 
2544
                                                send_fuse_err (this, finh, ENODATA);
2069
2545
                                        }
2070
2546
 
2071
2547
                                        priv->volfile_size = st.st_size;
2076
2552
                                        }
2077
2553
                                }
2078
2554
 
2079
 
                                fuse_reply_xattr_buf (state, req, priv->volfile, priv->volfile_size);
 
2555
                                send_fuse_xattr (this, finh, priv->volfile,
 
2556
                                                 priv->volfile_size, state->size);
2080
2557
                                /* if(ret >...)...else if...else */
2081
2558
                        } else if (!strcmp (state->name, "user.glusterfs-booster-path")) {
2082
 
                                fuse_reply_xattr_buf (state, req, state->loc.path,
2083
 
                                                      strlen (state->loc.path) + 1);
 
2559
                                send_fuse_xattr (this, finh, state->loc.path,
 
2560
                                                 strlen (state->loc.path) + 1, state->size);
2084
2561
                        } else if (!strcmp (state->name, "user.glusterfs-booster-mount")) {
2085
 
                                fuse_reply_xattr_buf (state, req, priv->mount_point,
2086
 
                                                      strlen(priv->mount_point) + 1);
 
2562
                                send_fuse_xattr (this, finh, priv->mount_point,
 
2563
                                                 strlen (priv->mount_point) + 1, state->size);
2087
2564
                        } else {
2088
 
                                fuse_reply_err (req, ENODATA);
 
2565
                                send_fuse_err (this, finh, ENODATA);
2089
2566
                        } /* if(value_data)...else */
2090
2567
                } else {
2091
2568
                        /* if callback for listxattr */
2104
2581
                                len += strlen (trav->key) + 1;
2105
2582
                                trav = trav->next;
2106
2583
                        } /* while(trav) */
2107
 
                        fuse_reply_xattr_buf (state, req, value, len);
 
2584
                        send_fuse_xattr (this, finh, value, len, state->size);
2108
2585
                } /* if(state->name)...else */
2109
2586
        } else {
2110
2587
                /* if failure - no need to check if listxattr or getxattr */
2121
2598
                        else
2122
2599
                        {
2123
2600
                                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2124
 
                                        "%"PRId64": %s() %s => -1 (%s)",
 
2601
                                        "%"PRIu64": %s() %s => -1 (%s)",
2125
2602
                                        frame->root->unique,
2126
2603
                                        gf_fop_list[frame->root->op],
2127
2604
                                        state->loc.path, strerror (op_errno));
2128
2605
                        }
2129
2606
                } else {
2130
2607
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2131
 
                                "%"PRId64": %s() %s => -1 (%s)",
 
2608
                                "%"PRIu64": %s() %s => -1 (%s)",
2132
2609
                                frame->root->unique,
2133
2610
                                gf_fop_list[frame->root->op], state->loc.path,
2134
2611
                                strerror (op_errno));
2135
2612
                } /* if(op_errno!= ENODATA)...else */
2136
2613
 
2137
 
                fuse_reply_err (req, op_errno);
 
2614
                send_fuse_err (this, finh, op_errno);
2138
2615
        } /* if(op_ret>=0)...else */
2139
2616
 
2140
2617
        if (need_to_free_dict)
2148
2625
 
2149
2626
 
2150
2627
static void
2151
 
fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
 
2628
fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
2152
2629
{
 
2630
        struct fuse_getxattr_in *fgxi = msg;
 
2631
        char         *name = (char *)(fgxi + 1);
 
2632
 
2153
2633
        fuse_state_t *state = NULL;
2154
2634
        int32_t       ret = -1;
2155
2635
 
2156
2636
#ifdef DISABLE_POSIX_ACL
2157
2637
        if (!strncmp (name, "system.", 7)) {
2158
 
                fuse_reply_err (req, ENODATA);
 
2638
                send_fuse_err (this, finh, ENODATA);
 
2639
                FREE (finh);
2159
2640
                return;
2160
2641
        }
2161
2642
#endif
2162
2643
 
2163
 
        state = state_from_req (req);
2164
 
        state->size = size;
 
2644
        GET_STATE (this, finh, state);
 
2645
        state->size = fgxi->size;
2165
2646
        state->name = strdup (name);
2166
2647
 
2167
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
2648
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
2168
2649
        if ((state->loc.inode == NULL) ||
2169
2650
            (ret < 0)) {
2170
2651
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2171
 
                        "%"PRId64": GETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
2172
 
                        req_callid (req), state->loc.path, (int64_t)ino, name);
 
2652
                        "%"PRIu64": GETXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
 
2653
                        finh->unique, state->loc.path, finh->nodeid, name);
2173
2654
 
2174
 
                fuse_reply_err (req, ENOENT);
 
2655
                send_fuse_err (this, finh, ENOENT);
2175
2656
                free_state (state);
2176
2657
                return;
2177
2658
        }
2178
2659
 
2179
2660
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2180
 
                "%"PRId64": GETXATTR %s/%"PRId64" (%s)", req_callid (req),
2181
 
                state->loc.path, (int64_t)ino, name);
 
2661
                "%"PRIu64": GETXATTR %s/%"PRIu64" (%s)", finh->unique,
 
2662
                state->loc.path, finh->nodeid, name);
2182
2663
 
2183
2664
        FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR,
2184
2665
                  getxattr, &state->loc, name);
2188
2669
 
2189
2670
 
2190
2671
static void
2191
 
fuse_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size)
 
2672
fuse_listxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
2192
2673
{
 
2674
        struct fuse_getxattr_in *fgxi = msg;
 
2675
 
2193
2676
        fuse_state_t *state = NULL;
2194
2677
        int32_t       ret = -1;
2195
2678
 
2196
 
        state = state_from_req (req);
2197
 
        state->size = size;
2198
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
2679
        GET_STATE (this, finh, state);
 
2680
        state->size = fgxi->size;
 
2681
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
2199
2682
        if ((state->loc.inode == NULL) ||
2200
2683
            (ret < 0)) {
2201
2684
                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2202
 
                        "%"PRId64": LISTXATTR %s/%"PRId64" (fuse_loc_fill() failed)",
2203
 
                        req_callid (req), state->loc.path, (int64_t)ino);
 
2685
                        "%"PRIu64": LISTXATTR %s/%"PRIu64" (fuse_loc_fill() failed)",
 
2686
                        finh->unique, state->loc.path, finh->nodeid);
2204
2687
 
2205
 
                fuse_reply_err (req, ENOENT);
 
2688
                send_fuse_err (this, finh, ENOENT);
2206
2689
                free_state (state);
2207
2690
                return;
2208
2691
        }
2209
2692
 
2210
2693
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2211
 
                "%"PRId64": LISTXATTR %s/%"PRId64, req_callid (req),
2212
 
                state->loc.path, (int64_t)ino);
 
2694
                "%"PRIu64": LISTXATTR %s/%"PRIu64, finh->unique,
 
2695
                state->loc.path, finh->nodeid);
2213
2696
 
2214
2697
        FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR,
2215
2698
                  getxattr, &state->loc, NULL);
2219
2702
 
2220
2703
 
2221
2704
static void
2222
 
fuse_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name)
 
2705
fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg)
2223
2706
 
2224
2707
{
 
2708
        char *name = msg;
 
2709
 
2225
2710
        fuse_state_t *state = NULL;
2226
2711
        int32_t       ret = -1;
2227
2712
 
2228
 
        state = state_from_req (req);
2229
 
        ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL);
 
2713
        GET_STATE (this, finh, state);
 
2714
        ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);
2230
2715
        if ((state->loc.inode == NULL) ||
2231
2716
            (ret < 0)) {
2232
2717
                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
2233
 
                        "%"PRId64": REMOVEXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)",
2234
 
                        req_callid (req), state->loc.path, (int64_t)ino, name);
 
2718
                        "%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s) (fuse_loc_fill() failed)",
 
2719
                        finh->unique, state->loc.path, finh->nodeid, name);
2235
2720
 
2236
 
                fuse_reply_err (req, ENOENT);
 
2721
                send_fuse_err (this, finh, ENOENT);
2237
2722
                free_state (state);
2238
2723
                return;
2239
2724
        }
2240
2725
 
2241
2726
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2242
 
                "%"PRId64": REMOVEXATTR %s/%"PRId64" (%s)", req_callid (req),
2243
 
                state->loc.path, (int64_t)ino, name);
 
2727
                "%"PRIu64": REMOVEXATTR %s/%"PRIu64" (%s)", finh->unique,
 
2728
                state->loc.path, finh->nodeid, name);
2244
2729
 
2245
2730
        FUSE_FOP (state, fuse_err_cbk, GF_FOP_REMOVEXATTR,
2246
2731
                  removexattr, &state->loc, name);
2258
2743
        fuse_state_t *state = NULL;
2259
2744
 
2260
2745
        state = frame->root->state;
 
2746
        struct fuse_lk_out flo = {{0, }, };
2261
2747
 
2262
2748
        if (op_ret == 0) {
2263
2749
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2264
 
                        "%"PRId64": ERR => 0", frame->root->unique);
2265
 
                fuse_reply_lock (state->req, lock);
 
2750
                        "%"PRIu64": ERR => 0", frame->root->unique);
 
2751
                flo.lk.type = lock->l_type;
 
2752
                flo.lk.pid  = lock->l_pid;
 
2753
                if (lock->l_type == F_UNLCK)
 
2754
                        flo.lk.start = flo.lk.end = 0;
 
2755
                else {
 
2756
                        flo.lk.start = lock->l_start;
 
2757
                        flo.lk.end = lock->l_len ?
 
2758
                                     (lock->l_start + lock->l_len - 1) :
 
2759
                                     OFFSET_MAX;
 
2760
                }
 
2761
                send_fuse_obj (this, state->finh, &flo);
2266
2762
        } else {
2267
2763
                if (op_errno == ENOSYS) {
2268
2764
                        gf_fuse_lk_enosys_log++;
2274
2770
                        }
2275
2771
                } else {
2276
2772
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2277
 
                                "%"PRId64": ERR => -1 (%s)",
 
2773
                                "%"PRIu64": ERR => -1 (%s)",
2278
2774
                                frame->root->unique, strerror (op_errno));
2279
2775
                }
2280
 
                fuse_reply_err (state->req, op_errno);
 
2776
                send_fuse_err (this, state->finh, op_errno);
2281
2777
        }
2282
2778
 
2283
2779
        free_state (state);
2288
2784
 
2289
2785
 
2290
2786
static void
2291
 
fuse_getlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
2292
 
            struct flock *lock)
 
2787
fuse_getlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
2293
2788
{
 
2789
        struct fuse_lk_in *fli = msg;
 
2790
 
2294
2791
        fuse_state_t *state = NULL;
2295
2792
        fd_t         *fd = NULL;
 
2793
        struct flock  lock = {0, };
2296
2794
 
2297
 
        fd = FI_TO_FD (fi);
2298
 
        state = state_from_req (req);
2299
 
        state->req = req;
 
2795
        fd = FH_TO_FD (fli->fh);
 
2796
        GET_STATE (this, finh, state);
2300
2797
        state->fd = fd;
 
2798
        convert_fuse_file_lock (&fli->lk, &lock);
 
2799
 
 
2800
        state->lk_owner = fli->owner;
2301
2801
 
2302
2802
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2303
 
                "%"PRId64": GETLK %p", req_callid (req), fd);
 
2803
                "%"PRIu64": GETLK %p", finh->unique, fd);
2304
2804
 
2305
2805
        FUSE_FOP (state, fuse_getlk_cbk, GF_FOP_LK,
2306
 
                  lk, fd, F_GETLK, lock);
 
2806
                  lk, fd, F_GETLK, &lock);
2307
2807
 
2308
2808
        return;
2309
2809
}
2319
2819
 
2320
2820
        if (op_ret == 0) {
2321
2821
                gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2322
 
                        "%"PRId64": ERR => 0", frame->root->unique);
2323
 
                fuse_reply_err (state->req, 0);
 
2822
                        "%"PRIu64": ERR => 0", frame->root->unique);
 
2823
                send_fuse_err (this, state->finh, 0);
2324
2824
        } else {
2325
2825
                if (op_errno == ENOSYS) {
2326
2826
                        gf_fuse_lk_enosys_log++;
2330
2830
                                        "'features/posix-locks' on server side "
2331
2831
                                        "will add SETLK support.");
2332
2832
                        }
2333
 
                } else  if (op_errno != EAGAIN) {
2334
 
                        gf_log ("glusterfs-fuse", GF_LOG_ERROR,
2335
 
                                "%"PRId64": ERR => -1 (%s)",
 
2833
                } else if (op_errno == EAGAIN) {
 
2834
                        gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
 
2835
                                "Returning EAGAIN Flock: "
 
2836
                                "start=%llu, len=%llu, pid=%llu, lk-owner=%llu",
 
2837
                                (unsigned long long) lock->l_start,
 
2838
                                (unsigned long long) lock->l_len,
 
2839
                                (unsigned long long) lock->l_pid,
 
2840
                                (unsigned long long) frame->root->lk_owner);
 
2841
 
 
2842
                } else  {
 
2843
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING,
 
2844
                                "%"PRIu64": ERR => -1 (%s)",
2336
2845
                                frame->root->unique, strerror (op_errno));
2337
2846
                }
2338
2847
 
2339
 
                fuse_reply_err (state->req, op_errno);
 
2848
                send_fuse_err (this, state->finh, op_errno);
2340
2849
        }
2341
2850
 
2342
2851
        free_state (state);
2347
2856
 
2348
2857
 
2349
2858
static void
2350
 
fuse_setlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
2351
 
            struct flock *lock, int sleep)
 
2859
fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg)
2352
2860
{
 
2861
        struct fuse_lk_in *fli = msg;
 
2862
 
2353
2863
        fuse_state_t *state = NULL;
2354
2864
        fd_t         *fd = NULL;
 
2865
        struct flock  lock = {0, };
2355
2866
 
2356
 
        fd = FI_TO_FD (fi);
2357
 
        state = state_from_req (req);
2358
 
        state->req = req;
 
2867
        fd = FH_TO_FD (fli->fh);
 
2868
        GET_STATE (this, finh, state);
 
2869
        state->finh = finh;
2359
2870
        state->fd = fd;
 
2871
        convert_fuse_file_lock (&fli->lk, &lock);
 
2872
 
 
2873
        state->lk_owner = fli->owner;
2360
2874
 
2361
2875
        gf_log ("glusterfs-fuse", GF_LOG_TRACE,
2362
 
                "%"PRId64": SETLK %p (sleep=%d)", req_callid (req), fd,
2363
 
                sleep);
 
2876
                "%"PRIu64": SETLK%s %p", finh->unique,
 
2877
                finh->opcode == FUSE_SETLK ? "" : "W", fd);
2364
2878
 
2365
2879
        FUSE_FOP (state, fuse_setlk_cbk, GF_FOP_LK,
2366
 
                  lk, fd, (sleep ? F_SETLKW : F_SETLK), lock);
2367
 
 
2368
 
        return;
2369
 
}
2370
 
 
2371
 
 
2372
 
static void
2373
 
fuse_init (void *data, struct fuse_conn_info *conn)
2374
 
{
2375
 
        return;
2376
 
}
2377
 
 
2378
 
static void
2379
 
fuse_destroy (void *data)
2380
 
{
2381
 
 
2382
 
}
2383
 
 
2384
 
static struct fuse_lowlevel_ops fuse_ops = {
2385
 
        .init         = fuse_init,
2386
 
        .destroy      = fuse_destroy,
2387
 
        .lookup       = fuse_lookup,
2388
 
        .forget       = fuse_forget,
2389
 
        .getattr      = fuse_getattr,
2390
 
        .setattr      = fuse_setattr,
2391
 
        .opendir      = fuse_opendir,
2392
 
        .readdir      = fuse_readdir,
2393
 
        .releasedir   = fuse_releasedir,
2394
 
        .access       = fuse_access,
2395
 
        .readlink     = fuse_readlink,
2396
 
        .mknod        = fuse_mknod,
2397
 
        .mkdir        = fuse_mkdir,
2398
 
        .unlink       = fuse_unlink,
2399
 
        .rmdir        = fuse_rmdir,
2400
 
        .symlink      = fuse_symlink,
2401
 
        .rename       = fuse_rename,
2402
 
        .link         = fuse_link,
2403
 
        .create       = fuse_create,
2404
 
        .open         = fuse_open,
2405
 
        .read         = fuse_readv,
2406
 
        .write        = fuse_write,
2407
 
        .flush        = fuse_flush,
2408
 
        .release      = fuse_release,
2409
 
        .fsync        = fuse_fsync,
2410
 
        .fsyncdir     = fuse_fsyncdir,
2411
 
        .statfs       = fuse_statfs,
2412
 
        .setxattr     = fuse_setxattr,
2413
 
        .getxattr     = fuse_getxattr,
2414
 
        .listxattr    = fuse_listxattr,
2415
 
        .removexattr  = fuse_removexattr,
2416
 
        .getlk        = fuse_getlk,
2417
 
        .setlk        = fuse_setlk
2418
 
};
2419
 
 
 
2880
                  lk, fd, finh->opcode == FUSE_SETLK ? F_SETLK : F_SETLKW,
 
2881
                  &lock);
 
2882
 
 
2883
        return;
 
2884
}
 
2885
 
 
2886
 
 
2887
static void
 
2888
fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg)
 
2889
{
 
2890
        struct fuse_init_in *fini = msg;
 
2891
 
 
2892
        struct fuse_init_out fino;
 
2893
        fuse_private_t *priv = NULL;
 
2894
        int ret;
 
2895
 
 
2896
        priv = this->private;
 
2897
 
 
2898
        if (!priv->first_call) {
 
2899
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
2900
                        "got INIT after first message");
 
2901
 
 
2902
                close (priv->fd);
 
2903
                goto out;
 
2904
        }
 
2905
 
 
2906
        if (fini->major != FUSE_KERNEL_VERSION) {
 
2907
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
2908
                        "unsupported FUSE protocol version %d.%d",
 
2909
                        fini->major, fini->minor);
 
2910
 
 
2911
                close (priv->fd);
 
2912
                goto out;
 
2913
        }
 
2914
        priv->proto_minor = fini->minor;
 
2915
 
 
2916
        fino.major = FUSE_KERNEL_VERSION;
 
2917
        fino.minor = FUSE_KERNEL_MINOR_VERSION;
 
2918
        fino.max_readahead = 1 << 17;
 
2919
        fino.max_write = 1 << 17;
 
2920
        fino.flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
 
2921
        if (fini->minor >= 6 /* fuse_init_in has flags */ &&
 
2922
            fini->flags & FUSE_BIG_WRITES) {
 
2923
                /* no need for direct I/O mode if big writes are supported */
 
2924
                priv->direct_io_mode = 0;
 
2925
                fino.flags |= FUSE_BIG_WRITES;
 
2926
        }
 
2927
        if (fini->minor >= 13) {
 
2928
                /* these values seemed to work fine during testing */
 
2929
 
 
2930
                fino.max_background = 64;
 
2931
                fino.congestion_threshold = 48;
 
2932
        }
 
2933
        if (fini->minor < 9)
 
2934
                *priv->msg0_len_p = sizeof(*finh) + FUSE_COMPAT_WRITE_IN_SIZE;
 
2935
 
 
2936
        ret = send_fuse_obj (this, finh, &fino);
 
2937
        if (ret == 0)
 
2938
                gf_log ("glusterfs-fuse", GF_LOG_INFO,
 
2939
                        "FUSE inited with protocol versions:"
 
2940
                        " glusterfs %d.%d kernel %d.%d",
 
2941
                        FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION,
 
2942
                        fini->major, fini->minor);
 
2943
        else {
 
2944
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
2945
                        "FUSE init failed (%s)", strerror (ret));
 
2946
 
 
2947
                close (priv->fd);
 
2948
        }
 
2949
 
 
2950
 out:
 
2951
        FREE (finh);
 
2952
}
 
2953
 
 
2954
 
 
2955
static void
 
2956
fuse_enosys (xlator_t *this, fuse_in_header_t *finh, void *msg)
 
2957
{
 
2958
        send_fuse_err (this, finh, ENOSYS);
 
2959
 
 
2960
        FREE (finh);
 
2961
}
 
2962
 
 
2963
 
 
2964
static void
 
2965
fuse_destroy (xlator_t *this, fuse_in_header_t *finh, void *msg)
 
2966
{
 
2967
        send_fuse_err (this, finh, 0);
 
2968
 
 
2969
        FREE (finh);
 
2970
}
 
2971
 
 
2972
static fuse_handler_t *fuse_ops[FUSE_713_OP_HIGH];
2420
2973
 
2421
2974
int
2422
 
fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
2423
 
                      int32_t op_ret, int32_t op_errno,
2424
 
                      inode_t *inode, struct stat *buf, dict_t *xattr)
 
2975
fuse_first_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 
2976
                       int32_t op_ret, int32_t op_errno,
 
2977
                       inode_t *inode, struct stat *buf, dict_t *xattr,
 
2978
                       struct stat *postparent)
2425
2979
{
2426
2980
        fuse_private_t *priv = NULL;
2427
2981
 
2430
2984
        if (op_ret == 0) {
2431
2985
                gf_log (this->name, GF_LOG_TRACE,
2432
2986
                        "first lookup on root succeeded.");
2433
 
                inode_lookup (inode);
2434
2987
        } else {
2435
2988
                gf_log (this->name, GF_LOG_DEBUG,
2436
2989
                        "first lookup on root failed.");
2447
3000
 
2448
3001
 
2449
3002
int
2450
 
fuse_root_lookup (xlator_t *this)
 
3003
fuse_first_lookup (xlator_t *this)
2451
3004
{
2452
3005
        fuse_private_t *priv = NULL;
2453
3006
        loc_t           loc;
2463
3016
        loc.path = "/";
2464
3017
        loc.name = "";
2465
3018
        loc.ino = 1;
2466
 
        loc.inode = inode_search (this->itable, 1, NULL);
 
3019
        loc.inode = fuse_ino_to_inode (1, this->itable);
2467
3020
        loc.parent = NULL;
2468
3021
 
2469
3022
        dict = dict_new ();
2471
3024
        frame->root->type = GF_OP_TYPE_FOP_REQUEST;
2472
3025
        xl = this->children->xlator;
2473
3026
 
2474
 
        STACK_WIND (frame, fuse_root_lookup_cbk, xl, xl->fops->lookup,
 
3027
        STACK_WIND (frame, fuse_first_lookup_cbk, xl, xl->fops->lookup,
2475
3028
                    &loc, dict);
2476
3029
        dict_unref (dict);
2477
3030
 
2488
3041
}
2489
3042
 
2490
3043
 
 
3044
 
2491
3045
static void *
2492
3046
fuse_thread_proc (void *data)
2493
3047
{
2494
3048
        char           *mount_point = NULL;
2495
3049
        xlator_t       *this = NULL;
2496
3050
        fuse_private_t *priv = NULL;
2497
 
        int32_t         res = 0;
 
3051
        ssize_t         res = 0;
2498
3052
        struct iobuf   *iobuf = NULL;
2499
 
        size_t          chan_size = 0;
 
3053
        fuse_in_header_t *finh;
 
3054
        struct iovec iov_in[2];
 
3055
        void *msg = NULL;
 
3056
        const size_t msg0_size = sizeof (*finh) + 128;
2500
3057
        int             ret  = -1;
2501
3058
 
2502
3059
        struct timeval  now;
2503
3060
        struct timespec timeout;
2504
3061
 
2505
 
 
2506
3062
        this = data;
2507
3063
        priv = this->private;
2508
 
        chan_size = fuse_chan_bufsize (priv->ch);
 
3064
 
 
3065
        THIS = this;
 
3066
 
 
3067
        iov_in[0].iov_len = sizeof (*finh) + sizeof (struct fuse_write_in);
 
3068
        iov_in[1].iov_len = ((struct iobuf_pool *)this->ctx->iobuf_pool)
 
3069
                              ->page_size;
 
3070
        priv->msg0_len_p = &iov_in[0].iov_len;
2509
3071
 
2510
3072
        pthread_mutex_lock (&priv->child_up_mutex);
2511
3073
        {
2514
3076
                timeout.tv_nsec = now.tv_usec * 1000;
2515
3077
 
2516
3078
                while (priv->child_up_value) {
 
3079
 
2517
3080
                        ret = pthread_cond_timedwait (&priv->child_up_cond,
2518
3081
                                                &priv->child_up_mutex,
2519
3082
                                                &timeout);
2528
3091
                " pthread_cond_timedout returned non zero value"
2529
3092
                " ret: %d errno: %d", ret, errno);
2530
3093
 
2531
 
        while (!fuse_session_exited (priv->se)) {
 
3094
        for (;;) {
2532
3095
                iobuf = iobuf_get (this->ctx->iobuf_pool);
 
3096
                /* Add extra 128 byte to the first iov so that it can
 
3097
                 * accomodate "ordinary" non-write requests. It's not
 
3098
                 * guaranteed to be big enough, as SETXATTR and namespace
 
3099
                 * operations with very long names may grow behind it,
 
3100
                 * but it's good enough in most cases (and we can handle
 
3101
                 * rest via realloc).
 
3102
                 */
 
3103
                iov_in[0].iov_base = CALLOC (1, msg0_size);
2533
3104
 
2534
 
                if (!iobuf) {
 
3105
                if (!iobuf || !iov_in[0].iov_base) {
2535
3106
                        gf_log (this->name, GF_LOG_ERROR,
2536
3107
                                "Out of memory");
 
3108
                        if (iobuf)
 
3109
                                iobuf_unref (iobuf);
 
3110
                        FREE (iov_in[0].iov_base);
2537
3111
                        sleep (10);
2538
3112
                        continue;
2539
3113
                }
2540
3114
 
2541
 
                res = fuse_chan_receive (priv->ch, iobuf->ptr, chan_size);
 
3115
                iov_in[1].iov_base = iobuf->ptr;
 
3116
 
 
3117
                res = readv (priv->fd, iov_in, 2);
2542
3118
 
2543
3119
                if (priv->first_call) {
2544
3120
                        if (priv->first_call > 1) {
2545
3121
                                priv->first_call--;
2546
3122
                        } else {
2547
 
                                fuse_root_lookup (this);
 
3123
                                fuse_first_lookup (this);
2548
3124
                        }
2549
3125
                }
2550
3126
 
2551
3127
                if (res == -1) {
2552
 
                        iobuf_unref (iobuf);
 
3128
                        if (errno == ENODEV || errno == EBADF) {
 
3129
                                gf_log ("glusterfs-fuse", GF_LOG_NORMAL,
 
3130
                                        "terminating upon getting %s when "
 
3131
                                        "reading /dev/fuse",
 
3132
                                        errno == ENODEV ? "ENODEV" : "EBADF");
 
3133
 
 
3134
                                break;
 
3135
                        }
2553
3136
                        if (errno != EINTR) {
2554
3137
                                gf_log ("glusterfs-fuse", GF_LOG_WARNING,
2555
 
                                        "fuse_chan_receive() returned -1 (%d)", errno);
 
3138
                                        "read from /dev/fuse returned -1 (%s)",
 
3139
                                        strerror (errno));
2556
3140
                        }
2557
 
                        if (errno == ENODEV)
2558
 
                                break;
2559
 
                        continue;
 
3141
 
 
3142
                        goto cont_err;
 
3143
                }
 
3144
                if (res < sizeof (finh)) {
 
3145
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING, "short read on /dev/fuse");
 
3146
                        break;
 
3147
                }
 
3148
 
 
3149
                finh = (fuse_in_header_t *)iov_in[0].iov_base;
 
3150
                if (res != finh->len) {
 
3151
                        gf_log ("glusterfs-fuse", GF_LOG_WARNING, "inconsistent read on /dev/fuse");
 
3152
                        break;
2560
3153
                }
2561
3154
 
2562
3155
                priv->iobuf = iobuf;
2563
3156
 
2564
 
                if (res && res != -1) {
2565
 
                        fuse_session_process (priv->se, iobuf->ptr,
2566
 
                                              res, priv->ch);
 
3157
                if (finh->opcode == FUSE_WRITE)
 
3158
                        msg = iov_in[1].iov_base;
 
3159
                else {
 
3160
                        if (res > msg0_size) {
 
3161
                                iov_in[0].iov_base =
 
3162
                                  realloc (iov_in[0].iov_base, res);
 
3163
                                if (iov_in[0].iov_base)
 
3164
                                        finh = (fuse_in_header_t *)
 
3165
                                                 iov_in[0].iov_base;
 
3166
                                else {
 
3167
                                        gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
3168
                                                "Out of memory");
 
3169
                                        send_fuse_err (this, finh, ENOMEM);
 
3170
 
 
3171
                                        goto cont_err;
 
3172
                                }
 
3173
                        }
 
3174
 
 
3175
                        if (res > iov_in[0].iov_len)
 
3176
                                memcpy (iov_in[0].iov_base + iov_in[0].iov_len,
 
3177
                                        iov_in[1].iov_base,
 
3178
                                        res - iov_in[0].iov_len);
 
3179
 
 
3180
                        msg = finh + 1;
2567
3181
                }
2568
 
 
2569
 
                iobuf_unref (iobuf);
 
3182
                fuse_ops[finh->opcode] (this, finh, msg);
 
3183
 
 
3184
                iobuf_unref (iobuf);
 
3185
                continue;
 
3186
 
 
3187
 cont_err:
 
3188
                iobuf_unref (iobuf);
 
3189
                FREE (iov_in[0].iov_base);
2570
3190
        }
2571
3191
 
 
3192
        iobuf_unref (iobuf);
 
3193
        FREE (iov_in[0].iov_base);
 
3194
 
2572
3195
        if (dict_get (this->options, ZR_MOUNTPOINT_OPT))
2573
3196
                mount_point = data_to_str (dict_get (this->options,
2574
3197
                                                     ZR_MOUNTPOINT_OPT));
2578
3201
                dict_del (this->options, ZR_MOUNTPOINT_OPT);
2579
3202
        }
2580
3203
 
2581
 
        fuse_session_remove_chan (priv->ch);
2582
 
        fuse_session_destroy (priv->se);
2583
 
        //  fuse_unmount (priv->mount_point, priv->ch);
2584
 
 
2585
3204
        raise (SIGTERM);
2586
3205
 
2587
3206
        return NULL;
2588
3207
}
2589
3208
 
 
3209
int32_t
 
3210
fuse_itable_dump (xlator_t  *this)
 
3211
{
 
3212
        if (!this)
 
3213
                 return -1;
 
3214
 
 
3215
        gf_proc_dump_add_section("xlator.mount.fuse.itable");
 
3216
        inode_table_dump(this->itable, "xlator.mount.fuse.itable");
 
3217
 
 
3218
        return 0;
 
3219
}
 
3220
 
 
3221
int32_t
 
3222
fuse_priv_dump (xlator_t  *this)
 
3223
{
 
3224
        fuse_private_t  *private = NULL;
 
3225
 
 
3226
        if (!this)
 
3227
                return -1;
 
3228
 
 
3229
        private = this->private;
 
3230
 
 
3231
        if (!private)
 
3232
                return -1;
 
3233
 
 
3234
        gf_proc_dump_add_section("xlator.mount.fuse.priv");
 
3235
 
 
3236
        gf_proc_dump_write("xlator.mount.fuse.priv.fd", "%d", private->fd);
 
3237
        gf_proc_dump_write("xlator.mount.fuse.priv.proto_minor", "%u",
 
3238
                            private->proto_minor);
 
3239
        gf_proc_dump_write("xlator.mount.fuse.priv.volfile", "%s",
 
3240
                            private->volfile?private->volfile:"None");
 
3241
        gf_proc_dump_write("xlator.mount.fuse.volfile_size", "%d",
 
3242
                            private->volfile_size);
 
3243
        gf_proc_dump_write("xlator.mount.fuse.mount_point", "%s",
 
3244
                            private->mount_point);
 
3245
        gf_proc_dump_write("xlator.mount.fuse.iobuf", "%u",
 
3246
                            private->iobuf);
 
3247
        gf_proc_dump_write("xlator.mount.fuse.fuse_thread_started", "%d",
 
3248
                            (int)private->fuse_thread_started);
 
3249
        gf_proc_dump_write("xlator.mount.fuse.direct_io_mode", "%d",
 
3250
                            private->direct_io_mode);
 
3251
        gf_proc_dump_write("xlator.mount.fuse.entry_timeout", "%lf",
 
3252
                            private->entry_timeout);
 
3253
        gf_proc_dump_write("xlator.mount.fuse.attribute_timeout", "%lf",
 
3254
                            private->attribute_timeout);
 
3255
        gf_proc_dump_write("xlator.mount.fuse.first_call", "%d",
 
3256
                            (int)private->first_call);
 
3257
        gf_proc_dump_write("xlator.mount.fuse.strict_volfile_check", "%d",
 
3258
                            (int)private->strict_volfile_check);
 
3259
 
 
3260
        return 0;
 
3261
}
 
3262
 
2590
3263
 
2591
3264
int32_t
2592
3265
notify (xlator_t *this, int32_t event, void *data, ...)
2607
3280
                        pthread_cond_broadcast (&private->child_up_cond);
2608
3281
                }
2609
3282
                pthread_mutex_unlock (&private->child_up_mutex);
 
3283
 
2610
3284
                break;
2611
3285
        }
2612
3286
 
2613
3287
        case GF_EVENT_PARENT_UP:
2614
3288
        {
2615
 
          if (!private->fuse_thread_started)
 
3289
                if (!private->fuse_thread_started)
2616
3290
                {
2617
3291
                        private->fuse_thread_started = 1;
2618
3292
 
2653
3327
        return 0;
2654
3328
}
2655
3329
 
2656
 
static struct fuse_opt subtype_workaround[] = {
2657
 
        FUSE_OPT_KEY ("subtype=", 0),
2658
 
        FUSE_OPT_KEY ("fssubtype=", 0),
2659
 
        FUSE_OPT_END
2660
 
};
2661
 
 
2662
 
static int
2663
 
subtype_workaround_optproc (void *data, const char *arg, int key,
2664
 
                           struct fuse_args *outargs)
2665
 
{
2666
 
        return key ? 1 : 0;
2667
 
}
2668
3330
 
2669
3331
int
2670
3332
init (xlator_t *this_xl)
2673
3335
        dict_t            *options = NULL;
2674
3336
        char              *value_string = NULL;
2675
3337
        char              *fsname = NULL;
2676
 
        char              *fsname_opt = NULL;
2677
3338
        fuse_private_t    *priv = NULL;
2678
3339
        struct stat        stbuf = {0,};
2679
 
        struct fuse_args   args = FUSE_ARGS_INIT (0, NULL);
 
3340
        int                i = 0;
 
3341
        int                xl_name_allocated = 0;
2680
3342
 
2681
3343
        if (this_xl == NULL)
2682
3344
                return -1;
2688
3350
 
2689
3351
        if (this_xl->name == NULL) {
2690
3352
                this_xl->name = strdup ("fuse");
2691
 
                ERR_ABORT (this_xl->name);
 
3353
                if (!this_xl->name) {
 
3354
                        gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
3355
                                "Out of memory");
 
3356
 
 
3357
                        goto cleanup_exit;
 
3358
                }
 
3359
                xl_name_allocated = 1;
2692
3360
        }
2693
3361
 
2694
 
        fsname = this_xl->ctx->cmd_args.volume_file;
2695
 
        fsname = (fsname ? fsname : this_xl->ctx->cmd_args.volfile_server);
2696
 
        fsname = (fsname ? fsname : "glusterfs");
2697
 
        ret = asprintf (&fsname_opt, "-ofsname=%s", fsname);
2698
 
 
2699
 
        if (ret != -1)
2700
 
                ret = fuse_opt_add_arg (&args, "glusterfs");
2701
 
        if (ret != -1)
2702
 
                ret = fuse_opt_add_arg (&args, fsname_opt);
2703
 
        if (ret != -1)
2704
 
                ret = fuse_opt_add_arg (&args, "-oallow_other");
2705
 
        if (ret != -1)
2706
 
                ret = fuse_opt_add_arg (&args, "-odefault_permissions");
2707
 
#ifdef GF_DARWIN_HOST_OS
2708
 
        if (ret != -1)
2709
 
                ret = fuse_opt_add_arg (&args, "-ofssubtype=glusterfs");
2710
 
        if (ret != -1 && !dict_get (options, "macfuse-local"))
2711
 
                /* This way, GlusterFS will be detected as 'servers' instead
2712
 
                 *  of 'devices'. This method is useful if you want to do
2713
 
                 * 'umount <mount_point>' over network,  instead of 'eject'ing
2714
 
                 * it from desktop. Works better for servers
2715
 
                 */
2716
 
                ret = fuse_opt_add_arg (&args, "-olocal");
2717
 
#else /* ! DARWIN_OS */
2718
 
        if (ret != -1)
2719
 
                ret = fuse_opt_add_arg (&args, "-osubtype=glusterfs");
2720
 
        if (ret != -1)
2721
 
                ret = fuse_opt_add_arg (&args, "-omax_readahead=131072");
2722
 
        if (ret != -1)
2723
 
                ret = fuse_opt_add_arg (&args, "-omax_read=131072");
2724
 
        if (ret != -1)
2725
 
                ret = fuse_opt_add_arg (&args, "-omax_write=131072");
2726
 
        if (ret != -1)
2727
 
                ret = fuse_opt_add_arg (&args, "-osuid");
2728
 
#if GF_LINUX_HOST_OS /* LINUX */
2729
 
        /* '-o dev', '-o nonempty' is supported only on Linux */
2730
 
        if (ret != -1)
2731
 
                ret = fuse_opt_add_arg (&args, "-ononempty");
2732
 
        if (ret != -1)
2733
 
                ret = fuse_opt_add_arg (&args, "-odev");
2734
 
#ifdef HAVE_FUSE_VERSION_28
2735
 
        if (ret != -1)
2736
 
                ret = fuse_opt_add_arg (&args, "-obig_writes");
2737
 
#endif /* FUSE 2.8 */
2738
 
 
2739
 
#endif /* LINUX */
2740
 
#endif /* ! DARWIN_OS */
2741
 
 
2742
 
        if (ret == -1)
2743
 
                ERR_ABORT (NULL);
2744
 
 
2745
3362
        priv = CALLOC (1, sizeof (*priv));
2746
 
        ERR_ABORT (priv);
 
3363
        if (!priv) {
 
3364
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
3365
                        "Out of memory");
 
3366
 
 
3367
                goto cleanup_exit;
 
3368
        }
2747
3369
        this_xl->private = (void *) priv;
 
3370
        priv->mount_point = NULL;
 
3371
        priv->fd = -1;
2748
3372
 
2749
3373
        /* get options from option dictionary */
2750
3374
        ret = dict_get_str (options, ZR_MOUNTPOINT_OPT, &value_string);
2780
3404
                goto cleanup_exit;
2781
3405
        }
2782
3406
        priv->mount_point = strdup (value_string);
2783
 
        ERR_ABORT (priv->mount_point);
 
3407
        if (!priv->mount_point) {
 
3408
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
3409
                        "Out of memory");
 
3410
 
 
3411
                goto cleanup_exit;
 
3412
        }
2784
3413
 
2785
3414
        ret = dict_get_double (options, "attribute-timeout",
2786
3415
                               &priv->attribute_timeout);
2787
 
        if (!priv->attribute_timeout)
 
3416
        if (ret != 0)
2788
3417
                priv->attribute_timeout = 1.0; /* default */
2789
3418
 
2790
3419
        ret = dict_get_double (options, "entry-timeout",
2806
3435
                                         &priv->strict_volfile_check);
2807
3436
        }
2808
3437
 
2809
 
        priv->ch = fuse_mount (priv->mount_point, &args);
2810
 
        if (priv->ch == NULL) {
2811
 
                if (errno == ENOTCONN) {
2812
 
                        gf_log ("glusterfs-fuse", GF_LOG_ERROR,
2813
 
                                "A stale mount is present on %s. "
2814
 
                                "Run 'umount %s' and try again",
2815
 
                                priv->mount_point,
2816
 
                                priv->mount_point);
2817
 
                } else {
2818
 
                        if (errno == ENOENT) {
2819
 
                                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
2820
 
                                        "Unable to mount on %s. Run "
2821
 
                                        "'modprobe fuse' and try again",
2822
 
                                        priv->mount_point);
2823
 
                        } else {
2824
 
                                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
2825
 
                                        "fuse_mount() failed%s%s "
2826
 
                                        "on mount point %s",
2827
 
                                        errno ? " with error " : "",
2828
 
                                        errno ? strerror (errno) : "",
2829
 
                                        priv->mount_point);
2830
 
                        }
2831
 
                }
2832
 
 
2833
 
                goto cleanup_exit;
2834
 
        }
2835
 
 
2836
 
        errno = 0;
2837
 
 
2838
 
        priv->se = fuse_lowlevel_new (&args, &fuse_ops,
2839
 
                                      sizeof (fuse_ops), this_xl);
2840
 
        if (priv->se == NULL && !errno) {
2841
 
                /*
2842
 
                 * Option parsing misery. Can happen if libfuse is of
2843
 
                 * FUSE < 2.7.0, as then the "-o subtype" option is not
2844
 
                 * handled.
2845
 
                 *
2846
 
                 * Best we can do to is to handle it at runtime -- this is not
2847
 
                 * a binary incompatibility issue (which should dealt with at
2848
 
                 * compile time), but a behavioural incompatibility issue. Ie.
2849
 
                 * we can't tell in advance whether the lib we use supports
2850
 
                 * "-o subtype". So try to be clever now.
2851
 
                 *
2852
 
                 * Delete the subtype option, and try again.
2853
 
                 */
2854
 
                if (fuse_opt_parse (&args, NULL, subtype_workaround,
2855
 
                                   subtype_workaround_optproc) == 0)
2856
 
                        priv->se = fuse_lowlevel_new (&args, &fuse_ops,
2857
 
                                                      sizeof (fuse_ops),
2858
 
                                                      this_xl);
2859
 
        }
2860
 
 
2861
 
        if (priv->se == NULL) {
2862
 
                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
2863
 
                        "fuse_lowlevel_new() failed with error %s on "
2864
 
                        "mount point %s",
2865
 
                        strerror (errno), priv->mount_point);
2866
 
                goto umount_exit;
2867
 
        }
2868
 
 
2869
 
        ret = fuse_set_signal_handlers (priv->se);
2870
 
        if (ret == -1) {
2871
 
                gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
2872
 
                        "fuse_set_signal_handlers() failed on mount point %s",
2873
 
                        priv->mount_point);
2874
 
                goto umount_exit;
2875
 
        }
2876
 
 
2877
 
        fuse_opt_free_args (&args);
2878
 
        FREE (fsname_opt);
2879
 
 
2880
 
        fuse_session_add_chan (priv->se, priv->ch);
2881
 
 
2882
 
        priv->fd = fuse_chan_fd (priv->ch);
 
3438
        fsname = this_xl->ctx->cmd_args.volume_file;
 
3439
        fsname = (fsname ? fsname : this_xl->ctx->cmd_args.volfile_server);
 
3440
        fsname = (fsname ? fsname : "glusterfs");
 
3441
 
 
3442
        this_xl->itable = inode_table_new (0, this_xl);
 
3443
        if (!this_xl->itable) {
 
3444
                gf_log ("glusterfs-fuse", GF_LOG_ERROR,
 
3445
                        "Out of memory");
 
3446
 
 
3447
                goto cleanup_exit;
 
3448
        }
 
3449
 
 
3450
        priv->fd = gf_fuse_mount (priv->mount_point, fsname,
 
3451
                                  "allow_other,default_permissions,"
 
3452
                                  "max_read=131072");
 
3453
        if (priv->fd == -1)
 
3454
                goto cleanup_exit;
2883
3455
 
2884
3456
        this_xl->ctx->top = this_xl;
2885
3457
 
 
3458
        priv->first_call = 2;
 
3459
 
2886
3460
        pthread_cond_init (&priv->child_up_cond, NULL);
2887
3461
        pthread_mutex_init (&priv->child_up_mutex, NULL);
2888
3462
        priv->child_up_value = 1;
2889
3463
 
2890
 
        priv->first_call = 2;
2891
 
        this_xl->itable = inode_table_new (0, this_xl);
 
3464
        for (i = 0; i < FUSE_713_OP_HIGH; i++)
 
3465
                fuse_ops[i] = fuse_enosys;
 
3466
        fuse_ops[FUSE_INIT]        = fuse_init;
 
3467
        fuse_ops[FUSE_DESTROY]     = fuse_destroy;
 
3468
        fuse_ops[FUSE_LOOKUP]      = fuse_lookup;
 
3469
        fuse_ops[FUSE_FORGET]      = fuse_forget;
 
3470
        fuse_ops[FUSE_GETATTR]     = fuse_getattr;
 
3471
        fuse_ops[FUSE_SETATTR]     = fuse_setattr;
 
3472
        fuse_ops[FUSE_OPENDIR]     = fuse_opendir;
 
3473
        fuse_ops[FUSE_READDIR]     = fuse_readdir;
 
3474
        fuse_ops[FUSE_RELEASEDIR]  = fuse_releasedir;
 
3475
        fuse_ops[FUSE_ACCESS]      = fuse_access;
 
3476
        fuse_ops[FUSE_READLINK]    = fuse_readlink;
 
3477
        fuse_ops[FUSE_MKNOD]       = fuse_mknod;
 
3478
        fuse_ops[FUSE_MKDIR]       = fuse_mkdir;
 
3479
        fuse_ops[FUSE_UNLINK]      = fuse_unlink;
 
3480
        fuse_ops[FUSE_RMDIR]       = fuse_rmdir;
 
3481
        fuse_ops[FUSE_SYMLINK]     = fuse_symlink;
 
3482
        fuse_ops[FUSE_RENAME]      = fuse_rename;
 
3483
        fuse_ops[FUSE_LINK]        = fuse_link;
 
3484
        fuse_ops[FUSE_CREATE]      = fuse_create;
 
3485
        fuse_ops[FUSE_OPEN]        = fuse_open;
 
3486
        fuse_ops[FUSE_READ]        = fuse_readv;
 
3487
        fuse_ops[FUSE_WRITE]       = fuse_write;
 
3488
        fuse_ops[FUSE_FLUSH]       = fuse_flush;
 
3489
        fuse_ops[FUSE_RELEASE]     = fuse_release;
 
3490
        fuse_ops[FUSE_FSYNC]       = fuse_fsync;
 
3491
        fuse_ops[FUSE_FSYNCDIR]    = fuse_fsyncdir;
 
3492
        fuse_ops[FUSE_STATFS]      = fuse_statfs;
 
3493
        fuse_ops[FUSE_SETXATTR]    = fuse_setxattr;
 
3494
        fuse_ops[FUSE_GETXATTR]    = fuse_getxattr;
 
3495
        fuse_ops[FUSE_LISTXATTR]   = fuse_listxattr;
 
3496
        fuse_ops[FUSE_REMOVEXATTR] = fuse_removexattr;
 
3497
        fuse_ops[FUSE_GETLK]       = fuse_getlk;
 
3498
        fuse_ops[FUSE_SETLK]       = fuse_setlk;
 
3499
        fuse_ops[FUSE_SETLKW]      = fuse_setlk;
 
3500
 
2892
3501
        return 0;
2893
3502
 
2894
 
umount_exit:
2895
 
        fuse_unmount (priv->mount_point, priv->ch);
2896
3503
cleanup_exit:
2897
 
        fuse_opt_free_args (&args);
2898
 
        FREE (fsname_opt);
2899
 
        if (priv)
 
3504
        if (xl_name_allocated)
 
3505
                FREE (this_xl->name);
 
3506
        if (priv) {
2900
3507
                FREE (priv->mount_point);
 
3508
                close (priv->fd);
 
3509
        }
2901
3510
        FREE (priv);
2902
3511
        return -1;
2903
3512
}
2923
3532
                        "Unmounting '%s'.", mount_point);
2924
3533
 
2925
3534
                dict_del (this_xl->options, ZR_MOUNTPOINT_OPT);
2926
 
                fuse_session_exit (priv->se);
2927
 
                fuse_unmount (mount_point, priv->ch);
 
3535
                gf_fuse_unmount (mount_point, priv->fd);
2928
3536
        }
2929
3537
}
2930
3538
 
2937
3545
struct xlator_mops mops = {
2938
3546
};
2939
3547
 
 
3548
struct xlator_dumpops dumpops = {
 
3549
        .priv  = fuse_priv_dump,
 
3550
        .inode = fuse_itable_dump,
 
3551
};
 
3552
 
2940
3553
struct volume_options options[] = {
2941
3554
        { .key  = {"direct-io-mode"},
2942
3555
          .type = GF_OPTION_TYPE_BOOL