summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/bug-1126048.c37
-rwxr-xr-xtests/bugs/bug-1126048.t30
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c79
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h178
-rw-r--r--xlators/mount/fuse/src/fuse-helpers.c2
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c10
6 files changed, 149 insertions, 187 deletions
diff --git a/tests/bugs/bug-1126048.c b/tests/bugs/bug-1126048.c
new file mode 100644
index 00000000000..2282bb2025e
--- /dev/null
+++ b/tests/bugs/bug-1126048.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+/*
+ * This function opens a file and to trigger migration failure, unlinks the
+ * file and performs graph switch (cmd passed in argv). If everything goes fine,
+ * fsync should fail without crashing the mount process.
+ */
+int
+main (int argc, char **argv)
+{
+ int ret = 0;
+ int fd = 0;
+ char *cmd = argv[1];
+
+ printf ("cmd is: %s\n", cmd);
+ fd = open("a.txt", O_CREAT|O_RDWR);
+ if (fd < 0)
+ printf ("open failed: %s\n", strerror(errno));
+
+ ret = unlink("a.txt");
+ if (ret < 0)
+ printf ("unlink failed: %s\n", strerror(errno));
+ if (write (fd, "abc", 3) < 0)
+ printf ("Not able to print %s\n", strerror (errno));
+ system(cmd);
+ sleep(1); //No way to confirm graph switch so sleep 1
+ ret = fsync(fd);
+ if (ret < 0)
+ printf ("Not able to fsync %s\n", strerror (errno));
+ return 0;
+}
diff --git a/tests/bugs/bug-1126048.t b/tests/bugs/bug-1126048.t
new file mode 100755
index 00000000000..fe1120ba9e7
--- /dev/null
+++ b/tests/bugs/bug-1126048.t
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+
+cleanup;
+
+function grep_for_ebadf {
+ $M0/bug-1126048 "gluster --mode=script volume add-brick $V0 $H0:$B0/brick2" | grep -i "Bad file descriptor"
+}
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info;
+
+TEST $CLI volume create $V0 $H0:$B0/brick1;
+EXPECT 'Created' volinfo_field $V0 'Status';
+
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+TEST glusterfs -s $H0 --volfile-id=$V0 $M0 --direct-io-mode=yes
+
+build_tester $(dirname $0)/bug-1126048.c
+
+TEST cp $(dirname $0)/bug-1126048 $M0
+cd $M0
+TEST grep_for_ebadf
+TEST ls -l $M0
+cd -
+TEST rm -f $(dirname $0)/bug-1126048
+cleanup;
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 26f806e0633..8ea02bc5f19 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -539,12 +539,32 @@ fuse_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
void
+fuse_fop_resume (fuse_state_t *state)
+{
+ fuse_resume_fn_t fn = NULL;
+
+ /*
+ * Fail fd resolution failures right away.
+ */
+ if (state->resolve.fd && state->resolve.op_ret < 0) {
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
+ free_fuse_state (state);
+ return;
+ }
+
+ fn = state->resume_fn;
+ fn (state);
+}
+
+void
fuse_lookup_resume (fuse_state_t *state)
{
if (!state->loc.parent && !state->loc.inode) {
gf_log ("fuse", GF_LOG_ERROR, "failed to resolve path %s",
state->loc.path);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -774,7 +794,8 @@ fuse_getattr_resume (fuse_state_t *state)
"%"PRIu64": GETATTR %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1086,7 +1107,8 @@ fuse_setattr_resume (fuse_state_t *state)
"%"PRIu64": SETATTR %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1291,7 +1313,8 @@ fuse_access_resume (fuse_state_t *state)
"%"PRIu64": ACCESS %"PRIu64" (%s) resolution failed",
state->finh->unique, state->finh->nodeid,
uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1368,7 +1391,8 @@ fuse_readlink_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_ERROR,
"READLINK %"PRIu64" (%s) resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1403,7 +1427,8 @@ fuse_mknod_resume (fuse_state_t *state)
"MKNOD %"PRIu64"/%s (%s/%s) resolution failed",
state->finh->nodeid, state->resolve.bname,
uuid_utoa (state->resolve.gfid), state->resolve.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1473,7 +1498,8 @@ fuse_mkdir_resume (fuse_state_t *state)
"MKDIR %"PRIu64" (%s/%s) resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
state->resolve.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1535,7 +1561,8 @@ fuse_unlink_resume (fuse_state_t *state)
"UNLINK %"PRIu64" (%s/%s) resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
state->resolve.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1571,7 +1598,8 @@ fuse_rmdir_resume (fuse_state_t *state)
"RMDIR %"PRIu64" (%s/%s) resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
state->resolve.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1607,7 +1635,8 @@ fuse_symlink_resume (fuse_state_t *state)
"SYMLINK %"PRIu64" (%s/%s) -> %s resolution failed",
state->finh->nodeid, uuid_utoa (state->resolve.gfid),
state->resolve.bname, state->name);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1723,7 +1752,8 @@ fuse_rename_resume (fuse_state_t *state)
uuid_utoa_r (state->resolve2.gfid, loc2_uuid),
state->resolve2.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1780,7 +1810,8 @@ fuse_link_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"fuse_loc_fill() failed %"PRIu64": LINK %s %s",
state->finh->unique, state->loc2.path, state->loc.path);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -1931,7 +1962,8 @@ fuse_create_resume (fuse_state_t *state)
"%"PRIu64" CREATE %s/%s resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid),
state->resolve.bname);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -2037,7 +2069,8 @@ fuse_open_resume (fuse_state_t *state)
"%"PRIu64": OPEN %s resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -2417,7 +2450,8 @@ fuse_opendir_resume (fuse_state_t *state)
gf_log ("glusterfs-fuse", GF_LOG_WARNING,
"%"PRIu64": OPENDIR (%s) resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -2948,7 +2982,8 @@ fuse_statfs_resume (fuse_state_t *state)
"%"PRIu64": STATFS (%s) resolution fail",
state->finh->unique, uuid_utoa (state->resolve.gfid));
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -2983,7 +3018,8 @@ fuse_setxattr_resume (fuse_state_t *state)
"resolution failed",
state->finh->unique, uuid_utoa (state->resolve.gfid),
state->finh->nodeid, state->name);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -3280,7 +3316,8 @@ fuse_getxattr_resume (fuse_state_t *state)
uuid_utoa (state->resolve.gfid),
state->finh->nodeid, state->name);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -3425,7 +3462,8 @@ fuse_listxattr_resume (fuse_state_t *state)
"resolution failed", state->finh->unique,
uuid_utoa (state->resolve.gfid), state->finh->nodeid);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
@@ -3480,7 +3518,8 @@ fuse_removexattr_resume (fuse_state_t *state)
state->finh->unique, uuid_utoa (state->resolve.gfid),
state->finh->nodeid, state->name);
- send_fuse_err (state->this, state->finh, ENOENT);
+ send_fuse_err (state->this, state->finh,
+ state->resolve.op_errno);
free_fuse_state (state);
return;
}
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 34794b6ea45..1a85cd348b8 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -145,10 +145,17 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
#define FUSE_FOP(state, ret, op_num, fop, args ...) \
do { \
- call_frame_t *frame = NULL; \
- xlator_t *xl = NULL; \
- int32_t op_ret = 0, op_errno = 0; \
- fuse_resolve_t *resolve = NULL; \
+ xlator_t *xl = NULL; \
+ call_frame_t *frame = NULL; \
+ \
+ xl = state->active_subvol; \
+ if (!xl) { \
+ gf_log_callingfn (state->this->name, GF_LOG_ERROR, \
+ "No active subvolume"); \
+ send_fuse_err (state->this, state->finh, ENOENT); \
+ free_fuse_state (state); \
+ break; \
+ } \
\
frame = get_call_frame_for_req (state); \
if (!frame) { \
@@ -158,13 +165,7 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
* better than trying to go on with a NULL \
* frame ... \
*/ \
- gf_log_callingfn ("glusterfs-fuse", \
- GF_LOG_ERROR, \
- "FUSE message" \
- " unique %"PRIu64" opcode %d:" \
- " frame allocation failed", \
- state->finh->unique, \
- state->finh->opcode); \
+ send_fuse_err (state->this, state->finh, ENOMEM); \
free_fuse_state (state); \
/* ideally, need to 'return', but let the */ \
/* calling function take care of it */ \
@@ -175,150 +176,15 @@ typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
frame->root->op = op_num; \
frame->op = op_num; \
\
- if ( state->resolve_now ) { \
- resolve = state->resolve_now; \
- } else { \
- resolve = &(state->resolve); \
- } \
- \
- xl = state->active_subvol; \
- if (!xl) { \
- gf_log_callingfn ("glusterfs-fuse", GF_LOG_ERROR, \
- "xl is NULL"); \
- op_errno = ENOENT; \
- op_ret = -1; \
- } else if (resolve->op_ret < 0) { \
- op_errno = resolve->op_errno; \
- op_ret = -1; \
- if (op_num == GF_FOP_LOOKUP) { \
- gf_log ("glusterfs-fuse", \
- (op_errno == ENOENT ? GF_LOG_TRACE \
- : GF_LOG_WARNING), \
- "%"PRIu64": %s() %s => -1 (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- resolve->resolve_loc.path, \
- strerror (op_errno)); \
- } else { \
- gf_log ("glusterfs-fuse", \
- GF_LOG_WARNING, \
- "%"PRIu64": %s() inode " \
- "migration of %s failed (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- resolve->resolve_loc.path, \
- strerror (op_errno)); \
- } \
- } else if (state->resolve2.op_ret < 0) { \
- op_errno = state->resolve2.op_errno; \
- op_ret = -1; \
- gf_log ("glusterfs-fuse", \
- GF_LOG_WARNING, \
- "%"PRIu64": %s() inode " \
- "migration of %s failed (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->resolve2.resolve_loc.path, \
- strerror (op_errno)); \
- } \
- \
- if (op_ret < 0) { \
- send_fuse_err (state->this, state->finh, op_errno); \
- free_fuse_state (state); \
- STACK_DESTROY (frame->root); \
- } else { \
- if (state->this->history) \
- gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \
- "(%s)", frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->loc.path, \
- (state->fd == NULL)? \
- uuid_utoa (state->loc.gfid): \
- uuid_utoa (state->fd->inode->gfid));\
- STACK_WIND (frame, ret, xl, xl->fops->fop, args); \
- } \
- \
- } while (0)
-
-
-#define FUSE_FOP_COOKIE(state, xl, ret, cky, op_num, fop, args ...) \
- do { \
- call_frame_t *frame = NULL; \
- xlator_t *xl = NULL; \
- int32_t op_ret = 0, op_errno = 0; \
- \
- frame = get_call_frame_for_req (state); \
- if (!frame) { \
- gf_log ("glusterfs-fuse", \
- GF_LOG_ERROR, \
- "FUSE message" \
- " unique %"PRIu64" opcode %d:" \
- " frame allocation failed", \
- state->finh->unique, \
- state->finh->opcode); \
- free_fuse_state (state); \
- return 0; \
- } \
- \
- frame->root->state = state; \
- frame->root->op = op_num; \
- frame->op = op_num; \
- \
- xl = state->active_subvol; \
- if (!xl) { \
- gf_log_callingfn ("glusterfs-fuse", GF_LOG_ERROR, \
- "xl is NULL"); \
- op_errno = ENOENT; \
- op_ret = -1; \
- } else if (state->resolve.op_ret < 0) { \
- op_errno = state->resolve.op_errno; \
- op_ret = -1; \
- if (op_num == GF_FOP_LOOKUP) { \
- gf_log ("glusterfs-fuse", \
- (op_errno == ENOENT ? GF_LOG_TRACE \
- : GF_LOG_WARNING), \
- "%"PRIu64": %s() %s => -1 (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->resolve.resolve_loc.path, \
- strerror (op_errno)); \
- } else { \
- gf_log ("glusterfs-fuse", \
- GF_LOG_WARNING, \
- "%"PRIu64": %s() inode " \
- "migration of %s failed (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->resolve.resolve_loc.path, \
- strerror (op_errno)); \
- } \
- } else if (state->resolve2.op_ret < 0) { \
- op_errno = state->resolve2.op_errno; \
- op_ret = -1; \
- gf_log ("glusterfs-fuse", \
- GF_LOG_WARNING, \
- "%"PRIu64": %s() inode " \
- "migration of %s failed (%s)", \
- frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->resolve2.resolve_loc.path, \
- strerror (op_errno)); \
- } \
- \
- if (op_ret < 0) { \
- send_fuse_err (state->this, state->finh, op_errno); \
- free_fuse_state (state); \
- STACK_DESTROY (frame->root); \
- } else { \
- if (xl->history) \
- gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \
- "(%s)", frame->root->unique, \
- gf_fop_list[frame->root->op], \
- state->loc.path, \
- uuid_utoa (state->loc.gfid)); \
- STACK_WIND_COOKIE (frame, ret, cky, xl, xl->fops->fop, \
- args); \
- } \
+ if (state->this->history) \
+ gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \
+ "(%s)", frame->root->unique, \
+ gf_fop_list[frame->root->op], \
+ state->loc.path, \
+ (state->fd == NULL)? \
+ uuid_utoa (state->loc.gfid): \
+ uuid_utoa (state->fd->inode->gfid)); \
+ STACK_WIND (frame, ret, xl, xl->fops->fop, args); \
} while (0)
#define GF_SELECT_LOG_LEVEL(_errno) \
@@ -446,7 +312,6 @@ typedef struct {
inode_t *hint;
u_char pargfid[16];
inode_t *parhint;
- char *resolved;
int op_ret;
int op_errno;
loc_t resolve_loc;
@@ -533,5 +398,6 @@ int fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve,
int fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve,
fd_t *fd);
int fuse_ignore_xattr_set (fuse_private_t *priv, char *key);
+void fuse_fop_resume (fuse_state_t *state);
int dump_history_fuse (circular_buffer_t *cb, void *data);
#endif /* _GF_FUSE_BRIDGE_H_ */
diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c
index 2774bdaa812..6584dcfb6fc 100644
--- a/xlators/mount/fuse/src/fuse-helpers.c
+++ b/xlators/mount/fuse/src/fuse-helpers.c
@@ -26,8 +26,6 @@ fuse_resolve_wipe (fuse_resolve_t *resolve)
GF_FREE ((void *)resolve->bname);
- GF_FREE ((void *)resolve->resolved);
-
if (resolve->fd)
fd_unref (resolve->fd);
diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c
index 8565ce0e478..bf6d66e2f6a 100644
--- a/xlators/mount/fuse/src/fuse-resolve.c
+++ b/xlators/mount/fuse/src/fuse-resolve.c
@@ -652,20 +652,13 @@ fuse_resolve (fuse_state_t *state)
return 0;
}
-
static int
fuse_resolve_done (fuse_state_t *state)
{
- fuse_resume_fn_t fn = NULL;
-
- fn = state->resume_fn;
-
- fn (state);
-
+ fuse_fop_resume (state);
return 0;
}
-
/*
* This function is called multiple times, once per resolving one location/fd.
* state->resolve_now is used to decide which location/fd is to be resolved now
@@ -710,7 +703,6 @@ fuse_resolve_continue (fuse_state_t *state)
return 0;
}
-
int
fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn)
{