diff options
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 17 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-protocol.h | 11 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-resolve.c | 219 |
3 files changed, 188 insertions, 59 deletions
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index b074ab9b5d0..ae33d6848d9 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -190,11 +190,28 @@ server_loc_wipe (loc_t *loc) void server_resolve_wipe (server_resolve_t *resolve) { + struct resolve_comp *comp = NULL; + int i = 0; + if (resolve->path) FREE (resolve->path); if (resolve->bname) FREE (resolve->bname); + + if (resolve->resolved) + FREE (resolve->resolved); + + loc_wipe (&resolve->deep_loc); + + comp = resolve->components; + if (comp) { + for (i = 0; comp[i].basename; i++) { + if (comp[i].inode) + inode_unref (comp[i].inode); + } + FREE (resolve->components); + } } diff --git a/xlators/protocol/server/src/server-protocol.h b/xlators/protocol/server/src/server-protocol.h index 24e3a55f01f..cb330ef1e1a 100644 --- a/xlators/protocol/server/src/server-protocol.h +++ b/xlators/protocol/server/src/server-protocol.h @@ -118,6 +118,14 @@ typedef enum { RESOLVE_EXACT } server_resolve_type_t; + +struct resolve_comp { + char *basename; + ino_t ino; + uint64_t gen; + inode_t *inode; +}; + typedef struct { server_resolve_type_t type; uint64_t fd_no; @@ -129,6 +137,9 @@ typedef struct { char *resolved; int op_ret; int op_errno; + loc_t deep_loc; + struct resolve_comp *components; + int comp_count; } server_resolve_t; diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c index ff7d3f89328..6989bd91524 100644 --- a/xlators/protocol/server/src/server-resolve.c +++ b/xlators/protocol/server/src/server-resolve.c @@ -26,15 +26,12 @@ #include "server-helpers.h" -struct resolve_comp { - char *basename; - ino_t ino; - uint64_t gen; - inode_t *inode; -}; - int server_resolve_all (call_frame_t *frame); +int +resolve_entry_simple (call_frame_t *frame); +int +resolve_inode_simple (call_frame_t *frame); int component_count (const char *path) @@ -54,9 +51,42 @@ component_count (const char *path) int -prepare_components (server_resolve_t *resolve) +prepare_components (call_frame_t *frame) { -// char *path = NULL; + server_state_t *state = NULL; + xlator_t *this = NULL; + server_resolve_t *resolve = NULL; + char *resolved = NULL; + int count = 0; + struct resolve_comp *components = NULL; + int i = 0; + char *trav = NULL; + + + state = CALL_STATE (frame); + this = frame->this; + resolve = state->resolve_now; + + resolved = strdup (resolve->path); + resolve->resolved = resolved; + + count = component_count (resolve->path); + components = CALLOC (sizeof (*components), count); + resolve->components = components; + + components[0].basename = ""; + components[0].ino = 1; + components[0].gen = 0; + components[0].inode = state->itable->root; + + i = 1; + for (trav = resolved; *trav; trav++) { + if (*trav == '/') { + components[i].basename = trav + 1; + *trav = 0; + i++; + } + } return 0; } @@ -101,29 +131,28 @@ resolve_loc_touchup (call_frame_t *frame) } - int -server_resolve_fd (call_frame_t *frame) +resolve_deep_continue (call_frame_t *frame) { server_state_t *state = NULL; xlator_t *this = NULL; server_resolve_t *resolve = NULL; - server_connection_t *conn = NULL; - uint64_t fd_no = -1; + int ret = 0; state = CALL_STATE (frame); this = frame->this; resolve = state->resolve_now; - conn = SERVER_CONNECTION (frame); - fd_no = resolve->fd_no; + resolve->op_ret = 0; + resolve->op_errno = 0; - state->fd = gf_fd_fdptr_get (conn->fdtable, fd_no); + if (resolve->par) + ret = resolve_entry_simple (frame); + else + ret = resolve_inode_simple (frame); - if (!state->fd) { - resolve->op_ret = -1; - resolve->op_errno = EBADF; - } + if (ret == 0) + resolve_loc_touchup (frame); server_resolve_all (frame); @@ -132,11 +161,70 @@ server_resolve_fd (call_frame_t *frame) int -resolve_entry_deep (call_frame_t *frame) +resolve_deep_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, inode_t *inode, struct stat *buf, + dict_t *xattr, struct stat *postparent) +{ + server_state_t *state = NULL; + server_resolve_t *resolve = NULL; + struct resolve_comp *components = NULL; + int i = 0; + inode_t *link_inode = NULL; + + state = CALL_STATE (frame); + resolve = state->resolve_now; + components = resolve->components; + + i = (long) cookie; + + if (op_ret == -1) { + goto get_out_of_here; + } + + if (i != 0) { + /* no linking for root inode */ + link_inode = inode_link (inode, resolve->deep_loc.parent, + resolve->deep_loc.name, buf); + inode_lookup (link_inode); + components[i].inode = link_inode; + link_inode = NULL; + } + + loc_wipe (&resolve->deep_loc); + + i++; /* next component */ + + if (!components[i].basename) { + /* all components of the path are resolved */ + goto get_out_of_here; + } + + /* join the current component with the path resolved until now */ + *(components[i].basename - 1) = '/'; + + resolve->deep_loc.path = strdup (resolve->resolved); + resolve->deep_loc.parent = inode_ref (components[i-1].inode); + resolve->deep_loc.inode = inode_new (state->itable); + resolve->deep_loc.name = components[i].basename; + + STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, + BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, + &resolve->deep_loc, NULL); + return 0; + +get_out_of_here: + resolve_deep_continue (frame); + return 0; +} + + +int +resolve_path_deep (call_frame_t *frame) { server_state_t *state = NULL; xlator_t *this = NULL; server_resolve_t *resolve = NULL; + int i = 0; state = CALL_STATE (frame); this = frame->this; @@ -145,15 +233,16 @@ resolve_entry_deep (call_frame_t *frame) gf_log (frame->this->name, GF_LOG_WARNING, "seeking deep resolution of %s", resolve->path); - if (resolve->type == RESOLVE_MUST) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - } + prepare_components (frame); - resolve_loc_touchup (frame); - - server_resolve_all (frame); + /* start from the root */ + resolve->deep_loc.inode = state->itable->root; + resolve->deep_loc.path = strdup ("/"); + resolve->deep_loc.name = ""; + STACK_WIND_COOKIE (frame, resolve_deep_cbk, (void *) (long) i, + BOUND_XL (frame), BOUND_XL (frame)->fops->lookup, + &resolve->deep_loc, NULL); return 0; } @@ -183,6 +272,8 @@ resolve_entry_simple (call_frame_t *frame) if (!parent) { /* simple resolution is indecisive. need to perform deep resolution */ + resolve->op_ret = -1; + resolve->op_errno = ENOENT; ret = 1; goto out; } @@ -207,6 +298,8 @@ resolve_entry_simple (call_frame_t *frame) ret = 0; break; default: + resolve->op_ret = -1; + resolve->op_errno = ENOENT; ret = 1; break; } @@ -243,15 +336,18 @@ server_resolve_entry (call_frame_t *frame) xlator_t *this = NULL; server_resolve_t *resolve = NULL; int ret = 0; + loc_t *loc = NULL; state = CALL_STATE (frame); this = frame->this; resolve = state->resolve_now; + loc = state->loc_now; ret = resolve_entry_simple (frame); if (ret > 0) { - resolve_entry_deep (frame); + loc_wipe (loc); + resolve_path_deep (frame); return 0; } @@ -264,35 +360,6 @@ server_resolve_entry (call_frame_t *frame) int -resolve_inode_deep (call_frame_t *frame) -{ - server_state_t *state = NULL; - xlator_t *this = NULL; - server_resolve_t *resolve = NULL; - - state = CALL_STATE (frame); - this = frame->this; - resolve = state->resolve_now; - - gf_log (frame->this->name, GF_LOG_WARNING, - "seeking deep resolution of %s", resolve->path); - - if (resolve->type == RESOLVE_MUST) { - resolve->op_ret = -1; - resolve->op_errno = ENOENT; - goto out; - } - - resolve_loc_touchup (frame); - -out: - server_resolve_all (frame); - - return 0; -} - - -int resolve_inode_simple (call_frame_t *frame) { server_state_t *state = NULL; @@ -312,6 +379,8 @@ resolve_inode_simple (call_frame_t *frame) } if (!inode) { + resolve->op_ret = -1; + resolve->op_errno = ENOENT; ret = 1; goto out; } @@ -342,15 +411,18 @@ server_resolve_inode (call_frame_t *frame) xlator_t *this = NULL; server_resolve_t *resolve = NULL; int ret = 0; + loc_t *loc = NULL; state = CALL_STATE (frame); this = frame->this; resolve = state->resolve_now; + loc = state->loc_now; ret = resolve_inode_simple (frame); if (ret > 0) { - resolve_inode_deep (frame); + loc_wipe (loc); + resolve_path_deep (frame); return 0; } @@ -363,6 +435,35 @@ server_resolve_inode (call_frame_t *frame) int +server_resolve_fd (call_frame_t *frame) +{ + server_state_t *state = NULL; + xlator_t *this = NULL; + server_resolve_t *resolve = NULL; + server_connection_t *conn = NULL; + uint64_t fd_no = -1; + + state = CALL_STATE (frame); + this = frame->this; + resolve = state->resolve_now; + conn = SERVER_CONNECTION (frame); + + fd_no = resolve->fd_no; + + state->fd = gf_fd_fdptr_get (conn->fdtable, fd_no); + + if (!state->fd) { + resolve->op_ret = -1; + resolve->op_errno = EBADF; + } + + server_resolve_all (frame); + + return 0; +} + + +int server_resolve (call_frame_t *frame) { server_state_t *state = NULL; |