2
Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.com>
3
This file is part of GlusterFS.
5
This file is licensed to you under your choice of the GNU Lesser
6
General Public License, version 3 or any later version (LGPLv3 or
7
later), or the GNU General Public License, version 2 (GPLv2), in all
8
cases as published by the Free Software Foundation.
12
#include "server-helpers.h"
13
#include "server-messages.h"
16
server_resolve_all(call_frame_t *frame, server_state_t *state);
18
resolve_entry_simple(call_frame_t *frame, server_state_t *state,
19
server_resolve_t *resolve);
21
resolve_inode_simple(call_frame_t *frame, server_state_t *state,
22
server_resolve_t *resolve);
24
resolve_continue(call_frame_t *frame, server_state_t *state,
25
server_resolve_t *resolve);
27
resolve_anonfd_simple(call_frame_t *frame, server_state_t *state,
28
server_resolve_t *resolve);
31
resolve_name_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
32
int op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata,
33
struct iatt *postparent)
35
server_state_t *state = NULL;
36
server_resolve_t *resolve = NULL;
37
inode_t *link_inode = NULL;
38
loc_t *resolve_loc = NULL;
40
state = CALL_STATE(frame);
41
resolve = state->resolve_now;
42
resolve_loc = &resolve->resolve_loc;
45
if (op_errno == ENOENT) {
46
gf_msg_debug(this->name, op_errno, "%s/%s: failed to resolve",
47
uuid_utoa(resolve_loc->pargfid), resolve_loc->name);
48
if (resolve->type == RESOLVE_NOT) {
50
inode = inode_grep(state->itable, resolve_loc->parent,
54
gf_msg_debug(this->name, 0,
56
"removing stale dentry",
57
uuid_utoa(resolve_loc->pargfid),
59
inode_unlink(inode, resolve_loc->parent,
65
gf_msg(this->name, GF_LOG_WARNING, op_errno,
66
PS_MSG_GFID_RESOLVE_FAILED,
69
uuid_utoa(resolve_loc->pargfid), resolve_loc->name,
75
link_inode = inode_link(inode, resolve_loc->parent, resolve_loc->name, buf);
80
inode_lookup(link_inode);
82
inode_unref(link_inode);
85
loc_wipe(resolve_loc);
87
resolve_continue(frame, state, resolve);
92
resolve_name(call_frame_t *frame, inode_t *parent, server_state_t *state,
93
server_resolve_t *resolve)
95
loc_t *resolve_loc = NULL;
98
resolve_loc = &resolve->resolve_loc;
99
resolve_loc->parent = inode_ref(parent);
100
gf_uuid_copy(resolve_loc->pargfid, resolve_loc->parent->gfid);
102
resolve_loc->name = resolve->bname;
104
resolve_loc->inode = server_inode_new(state->itable, resolve_loc->gfid);
106
inode_path(resolve_loc->parent, resolve_loc->name,
107
(char **)&resolve_loc->path);
110
dict = dict_copy_with_ref(state->xdata, NULL);
112
gf_msg(frame->this->name, GF_LOG_ERROR, ENOMEM, PS_MSG_NO_MEMORY,
113
"BUG: dict allocation failed (pargfid: %s, name: %s), "
115
uuid_utoa(resolve_loc->gfid), resolve_loc->name);
118
STACK_WIND(frame, resolve_name_cbk, frame->root->client->bound_xl,
119
frame->root->client->bound_xl->fops->lookup,
120
&resolve->resolve_loc, dict);
127
resolve_gfid_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
128
int op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata,
129
struct iatt *postparent)
131
server_state_t *state = NULL;
132
server_resolve_t *resolve = NULL;
133
inode_t *link_inode = NULL;
134
loc_t *resolve_loc = NULL;
136
state = CALL_STATE(frame);
137
resolve = state->resolve_now;
138
resolve_loc = &resolve->resolve_loc;
141
if (op_errno == ENOENT) {
142
gf_msg_debug(this->name, op_errno, "%s: failed to resolve",
143
uuid_utoa(resolve_loc->gfid));
145
gf_msg(this->name, GF_LOG_WARNING, op_errno,
146
PS_MSG_GFID_RESOLVE_FAILED, "%s: failed to resolve (%s)",
147
uuid_utoa(resolve_loc->gfid), strerror(op_errno));
149
loc_wipe(&resolve->resolve_loc);
153
link_inode = inode_link(inode, NULL, NULL, buf);
156
loc_wipe(resolve_loc);
160
inode_lookup(link_inode);
162
/* wipe the loc only after the inode has been linked to the inode
163
table. Otherwise before inode gets linked to the inode table,
164
inode would have been unrefed (this might have been destroyed
165
if refcount becomes 0, and put back to mempool). So once the
166
inode gets destroyed, inode_link is a redundant operation. But
167
without knowing that the destroyed inode's pointer is saved in
168
the resolved_loc as parent (while constructing loc for resolving
169
the entry) and the inode_new call for resolving the entry will
170
return the same pointer to the inode as the parent (because in
171
reality the inode is a free inode present in cold list of the
174
loc_wipe(resolve_loc);
176
if (gf_uuid_is_null(resolve->pargfid)) {
177
inode_unref(link_inode);
181
resolve_name(frame, link_inode, state, resolve);
182
inode_unref(link_inode);
186
resolve_continue(frame, state, resolve);
191
resolve_gfid(call_frame_t *frame, server_state_t *state,
192
server_resolve_t *resolve)
194
loc_t *resolve_loc = NULL;
195
dict_t *xdata = NULL;
197
resolve_loc = &resolve->resolve_loc;
199
if (!gf_uuid_is_null(resolve->pargfid))
200
gf_uuid_copy(resolve_loc->gfid, resolve->pargfid);
201
else if (!gf_uuid_is_null(resolve->gfid))
202
gf_uuid_copy(resolve_loc->gfid, resolve->gfid);
204
resolve_loc->inode = server_inode_new(state->itable, resolve_loc->gfid);
205
(void)loc_path(resolve_loc, NULL);
208
xdata = dict_copy_with_ref(state->xdata, NULL);
210
gf_msg(frame->this->name, GF_LOG_ERROR, ENOMEM, PS_MSG_NO_MEMORY,
211
"BUG: dict allocation failed (gfid: %s), "
213
uuid_utoa(resolve_loc->gfid));
216
STACK_WIND(frame, resolve_gfid_cbk, frame->root->client->bound_xl,
217
frame->root->client->bound_xl->fops->lookup,
218
&resolve->resolve_loc, xdata);
225
resolve_continue(call_frame_t *frame, server_state_t *state,
226
server_resolve_t *resolve)
231
resolve->op_errno = 0;
233
if (resolve->fd_no != -1) {
234
ret = resolve_anonfd_simple(frame, state, resolve);
236
} else if (!gf_uuid_is_null(resolve->pargfid))
237
ret = resolve_entry_simple(frame, state, resolve);
238
else if (!gf_uuid_is_null(resolve->gfid))
239
ret = resolve_inode_simple(frame, state, resolve);
241
gf_msg_debug(frame->this->name, 0,
242
"return value of resolve_*_"
246
loc_touchup(state->loc_now, resolve->bname);
248
server_resolve_all(frame, state);
252
Check if the requirements are fulfilled by entries in the inode cache itself
254
<= 0 - simple resolution was decisive and complete (either success or failure)
255
> 0 - indecisive, need to perform deep resolution
259
resolve_entry_simple(call_frame_t *frame, server_state_t *state,
260
server_resolve_t *resolve)
262
inode_t *parent = NULL;
263
inode_t *inode = NULL;
266
parent = inode_find(state->itable, resolve->pargfid);
268
/* simple resolution is indecisive. need to perform
270
resolve->op_ret = -1;
271
resolve->op_errno = ESTALE;
276
if (parent->ia_type != IA_IFDIR) {
277
/* Parent type should be 'directory', and nothing else */
278
gf_msg(frame->this->name, GF_LOG_ERROR, EPERM,
279
PS_MSG_GFID_RESOLVE_FAILED, "%s: parent type not directory (%d)",
280
uuid_utoa(parent->gfid), parent->ia_type);
281
resolve->op_ret = -1;
282
resolve->op_errno = EPERM;
287
/* expected @parent was found from the inode cache */
288
gf_uuid_copy(state->loc_now->pargfid, resolve->pargfid);
289
state->loc_now->parent = inode_ref(parent);
290
if (strchr(resolve->bname, '/')) {
291
/* basename should be a string (without '/') in a directory,
292
it can't span multiple levels. This can also lead to
293
resolving outside the parent's tree, which is not allowed */
294
gf_msg(frame->this->name, GF_LOG_ERROR, EPERM,
295
PS_MSG_GFID_RESOLVE_FAILED,
296
"%s: basename sent by client not allowed", resolve->bname);
297
resolve->op_ret = -1;
298
resolve->op_errno = EPERM;
303
state->loc_now->name = resolve->bname;
305
inode = inode_grep(state->itable, parent, resolve->bname);
307
switch (resolve->type) {
308
case RESOLVE_DONTCARE:
316
resolve->op_ret = -1;
317
resolve->op_errno = ENOENT;
325
if (resolve->type == RESOLVE_NOT) {
326
gf_msg_debug(frame->this->name, 0,
327
"inode (pointer: %p gfid:%s found"
328
" for path (%s) while type is RESOLVE_NOT. "
329
"Performing lookup on backend to rule out any "
330
"possible stale dentries in inode table",
331
inode, uuid_utoa(inode->gfid), resolve->path);
332
resolve->op_ret = -1;
333
resolve->op_errno = EEXIST;
340
state->loc_now->inode = inode_ref(inode);
353
server_resolve_entry(call_frame_t *frame, server_state_t *state,
354
server_resolve_t *resolve)
357
inode_t *parent = NULL;
359
ret = resolve_entry_simple(frame, state, resolve);
363
parent = inode_ref(state->loc_now->parent);
365
/*Wipe state->loc_now before calling resolve_xxxx()*/
366
loc_wipe(state->loc_now);
368
resolve_name(frame, parent, state, resolve);
371
resolve_gfid(frame, state, resolve);
374
loc_touchup(state->loc_now, resolve->bname);
375
server_resolve_all(frame, state);
380
resolve_inode_simple(call_frame_t *frame, server_state_t *state,
381
server_resolve_t *resolve)
383
inode_t *inode = NULL;
386
inode = inode_find(state->itable, resolve->gfid);
389
if (resolve->type == RESOLVE_DONTCARE) {
390
gf_uuid_copy(state->loc_now->gfid, resolve->gfid);
392
resolve->op_ret = -1;
393
resolve->op_errno = ESTALE;
399
state->loc_now->inode = inode_ref(inode);
400
gf_uuid_copy(state->loc_now->gfid, resolve->gfid);
410
server_resolve_inode(call_frame_t *frame, server_state_t *state,
411
server_resolve_t *resolve)
416
ret = resolve_inode_simple(frame, state, resolve);
419
loc = state->loc_now;
421
resolve_gfid(frame, state, resolve);
423
loc_touchup(state->loc_now, resolve->bname);
424
server_resolve_all(frame, state);
429
resolve_anonfd_simple(call_frame_t *frame, server_state_t *state,
430
server_resolve_t *resolve)
432
inode_t *inode = NULL;
435
inode = inode_find(state->itable, resolve->gfid);
438
resolve->op_ret = -1;
439
resolve->op_errno = ENOENT;
441
gf_msg_debug("server", 0,
443
"(%s) is not found. anonymous fd creation failed",
444
uuid_utoa(resolve->gfid));
448
if (frame->root->op == GF_FOP_READ || frame->root->op == GF_FOP_WRITE)
449
state->fd = fd_anonymous_with_flags(inode, state->flags);
451
state->fd = fd_anonymous(inode);
460
server_resolve_anonfd(call_frame_t *frame, server_state_t *state,
461
server_resolve_t *resolve)
466
ret = resolve_anonfd_simple(frame, state, resolve);
469
loc = state->loc_now;
471
resolve_gfid(frame, state, resolve);
473
server_resolve_all(frame, state);
478
server_resolve_fd(call_frame_t *frame, server_state_t *state,
479
server_resolve_t *resolve)
481
server_ctx_t *serv_ctx = NULL;
482
client_t *client = NULL;
485
fd_no = resolve->fd_no;
487
if (fd_no == GF_ANON_FD_NO) {
488
server_resolve_anonfd(frame, state, resolve);
492
client = frame->root->client;
494
serv_ctx = server_ctx_get(client, client->this);
496
if (serv_ctx == NULL) {
497
gf_msg("", GF_LOG_INFO, ENOMEM, PS_MSG_NO_MEMORY,
498
"server_ctx_get() failed");
499
resolve->op_ret = -1;
500
resolve->op_errno = ENOMEM;
505
* With copy_file_range, there will be 2 fds to resolve.
506
* This same function is called to resolve both the source
507
* fd and the destination fd. As of now, this function does
508
* not have any mechanism to distinguish between the 2 fds
509
* being resolved except for checking the value of state->fd.
510
* The assumption is that, if source fd the one which is
511
* being resolved here, then state->fd would be NULL. If it
512
* is not NULL, then it is the destination fd which is being
514
* This method (provided the above assumption is true) is
515
* to achieve the ability to distinguish between 2 fds with
516
* minimum changes being done to this function. If this way
517
* is not correct, then more changes might be needed.
520
state->fd = gf_fd_fdptr_get(serv_ctx->fdtable, fd_no);
522
gf_msg("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND,
525
resolve->op_ret = -1;
526
resolve->op_errno = EBADF;
529
state->fd_out = gf_fd_fdptr_get(serv_ctx->fdtable, fd_no);
530
if (!state->fd_out) {
531
gf_msg("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND,
534
resolve->op_ret = -1;
535
resolve->op_errno = EBADF;
539
server_resolve_all(frame, state);
543
server_resolve(call_frame_t *frame, server_state_t *state)
545
server_resolve_t *resolve = NULL;
547
resolve = state->resolve_now;
549
if (resolve->fd_no != -1) {
550
server_resolve_fd(frame, state, resolve);
552
} else if (!gf_uuid_is_null(resolve->pargfid)) {
553
server_resolve_entry(frame, state, resolve);
555
} else if (!gf_uuid_is_null(resolve->gfid)) {
556
server_resolve_inode(frame, state, resolve);
559
if (resolve == &state->resolve)
560
gf_msg(frame->this->name, GF_LOG_WARNING, 0, PS_MSG_INVALID_ENTRY,
561
"no resolution type for %s (%s)", resolve->path,
562
gf_fop_list[frame->root->op]);
564
resolve->op_ret = -1;
565
resolve->op_errno = EINVAL;
567
server_resolve_all(frame, state);
572
server_resolve_done(call_frame_t *frame, server_state_t *state)
574
server_print_request(frame);
576
state->resume_fn(frame, frame->root->client->bound_xl);
580
* This function is called multiple times, once per resolving one location/fd.
581
* state->resolve_now is used to decide which location/fd is to be resolved now
584
server_resolve_all(call_frame_t *frame, server_state_t *state)
586
if (state->resolve_now == NULL) {
587
state->resolve_now = &state->resolve;
588
state->loc_now = &state->loc;
590
server_resolve(frame, state);
592
} else if (state->resolve_now == &state->resolve) {
593
state->resolve_now = &state->resolve2;
594
state->loc_now = &state->loc2;
596
server_resolve(frame, state);
598
} else if (state->resolve_now == &state->resolve2) {
599
server_resolve_done(frame, state);
602
gf_msg(frame->this->name, GF_LOG_ERROR, EINVAL, PS_MSG_INVALID_ENTRY,
603
"Invalid pointer for "
604
"state->resolve_now");
609
resolve_and_resume(call_frame_t *frame, server_resume_fn_t fn)
611
server_state_t *state = NULL;
613
state = CALL_STATE(frame);
614
state->resume_fn = fn;
616
server_resolve_all(frame, state);