[Gluster-users] gnfs split brain when 1 server in 3x1 down (high load) - help request

Erik Jacobson erik.jacobson at hpe.com
Tue Apr 7 23:29:39 UTC 2020


My co-worker prefers I keep driving the discussion since this isn't his
normal area. But he's far better at digging in to these low level calls
than I am. So I am passing along his analysis so far. We are wondering
if we have enough information yet to turn on any light bulbs in terms of
volume settings, system settings, or a code change... Or a suggested
path for further debug.

Recall from earlier in the thread, this a 3-way replicate single
subvolume gluster fileystem that gets split-brain errors under heavy
gnfs load when one of the three servers has gone down, representing a
customer-reported problem. 

Scott's analysis is below. Next steps truly appreciated !!



Apologies for misinterpreting the backtrace.

#0  afr_read_txn_refresh_done (frame=0x7ffcf4146478, 
this=0x7fff64013720, err=5) at afr-read-txn.c:312
#1  0x00007fff68938d2b in afr_txn_refresh_done 
(frame=frame at entry=0x7ffcf4146478, this=this at entry=0x7fff64013720, 
err=5, err at entry=0)
     at afr-common.c:1222
#2  0x00007fff68939003 in afr_inode_refresh_done 
(frame=frame at entry=0x7ffcf4146478, this=this at entry=0x7fff64013720, error=0)
     at afr-common.c:1294

instead of the #1/#2 above calling the functions afr_txn_refresh_done 
and afr_inode_refresh_done respectively, they are calling a function 
within afr_txn_refresh_done and afr_inode_refresh_done respectively.

So, afr_txn_refresh_done (frame=frame at entry=0x7ffcf4146478, 
this=this at entry=0x7fff64013720, err=5, err at entry=0)at 
afr-common.c:1222calls a function at line number 1222 in aft-common.c 
within the function afr_txn_refresh_done:

1163: int
1164: afr_txn_refresh_done(call_frame_t *frame, xlator_t *this, int err)
1165: {
1166:     call_frame_t *heal_frame = NULL;
1167:     afr_local_t *heal_local = NULL;
1168:     afr_local_t *local = NULL;
1169:     afr_private_t *priv = NULL;
1170:     inode_t *inode = NULL;
1171:     int event_generation = 0;
1172:     int read_subvol = -1;
1173:     int ret = 0;
1174:
1175:     local = frame->local;
1176:     inode = local->inode;
1177:     priv = this->private;
1178:
1179:     if (err)
1180:         goto refresh_done;
1181:
1182:     if (local->op == GF_FOP_LOOKUP)
1183:         goto refresh_done;
1184:
1185:     ret = afr_inode_get_readable(frame, inode, this, local->readable,
1186: &event_generation, local->transaction.type);
1187:
1188:     if (ret == -EIO || (local->is_read_txn && !event_generation)) {
1189:         /* No readable subvolume even after refresh ==> splitbrain.*/
*1190: **        if (!priv->fav_child_policy) {*
*1191:           err = EIO;
**1192:             goto refresh_done;
**1193: **        }*
1194:         read_subvol = afr_sh_get_fav_by_policy(this, 
local->replies, inode,
1195: NULL);
1196:         if (read_subvol == -1) {
1197:             err = EIO;
1198:             goto refresh_done;
1199:         }
1200:
1201:         heal_frame = afr_frame_create(this, NULL);
1202:         if (!heal_frame) {
1203:             err = EIO;
1204:             goto refresh_done;
1205:         }
1206:         heal_local = heal_frame->local;
1207:         heal_local->xdata_req = dict_new();
1208:         if (!heal_local->xdata_req) {
1209:             err = EIO;
1210: AFR_STACK_DESTROY(heal_frame);
1211:             goto refresh_done;
1212:         }
1213:         heal_local->heal_frame = frame;
1214:         ret = synctask_new(this->ctx->env, 
afr_fav_child_reset_sink_xattrs,
1215: afr_fav_child_reset_sink_xattrs_cbk, heal_frame,
1216: heal_frame);
1217:         return 0;
1218:    }
1219:
1220: refresh_done:
1221:     afr_local_replies_wipe(local, this->private);
*1222:     local->refreshfn(frame, this, err);*
1223:
1224:     return 0;
1225: }

So, backtrace #1 represents the following function call 
local->refreshfn(frame=frame at entry=0x7ffcf4146478, 
this=this at entry=0x7fff64013720, err=5, err at entry=0)
This is the 1st example of EIO being set.

Setting a breakpoint at *1190: **        if (!priv->fav_child_policy) { 
*reveals that ret is not set, but local->is_read_txn is set and 
event_generation is zero (xlators/cluster/afr/src/afr.h:108), so the 
conditional at 1188 is true.  Furthermore, priv->fav_child_policy is set 
to AFR_FAV_CHILD_NONE which is zero, so we found where the error is set 
to EIO, line 1191.

The following is the gdb output:

(gdb) print ret
$1 = 0
(gdb) print local->is_read_txn
$2 = true
(gdb) print event_generation
$3 = 0

(gdb) print priv->fav_child_policy
$4 = AFR_FAV_CHILD_NONE

I am not sure what this signifies though.  It appears to be a read 
transaction with no event generation and no favorite child policy.

Feel free to ask for clarification in case my thought process went awry 
somewhere.

Thanks,
-Scott



On Thu, Apr 02, 2020 at 02:02:46AM -0500, Erik Jacobson wrote:
> > Hmm, afr_inode_refresh_done() is called with error=0 and by the time we
> > reach afr_txn_refresh_done(), it becomes 5(i.e. EIO).
> > So afr_inode_refresh_done() is changing it to 5. Maybe you can put
> > breakpoints/ log messages in afr_inode_refresh_done() at the places where
> > error is getting changed and see where the assignment happens.
> 
> I had a lot of struggles tonight getting the system ready to go.  I had
> seg11's in glusterfs(nfs) but I think it was related to not all brick
> processes stopping with glusterd. I also re-installed and/or the print
> statements. I'm not sure. I'm not used to seeing that.
> 
> I put print statements everywhere I thought error could change and got
> no printed log messages.
> 
> I put break points where error would change and we didn't hit them.
> 
> I then point a breakpoint at
> 
> break xlators/cluster/afr/src/afr-common.c:1298 if error != 0
> 
> ---> refresh_done:
>     afr_txn_refresh_done(frame, this, error);
> 
> And it never triggered (despite split-brain messages and my crapola
> message).
> 
> So I'm unable to explain this transition. I'm also not a gdb expert.
> I still see the same back trace though.
> 
> #1  0x00007fff68938d7b in afr_txn_refresh_done (
>     frame=frame at entry=0x7ffd540ed8e8, this=this at entry=0x7fff64013720, err=5,
>     err at entry=0) at afr-common.c:1222
> #2  0x00007fff689391f0 in afr_inode_refresh_done (
>     frame=frame at entry=0x7ffd540ed8e8, this=this at entry=0x7fff64013720, error=0)
>     at afr-common.c:1299
> 
> Is there other advice you might have for me to try?
> 
> I'm very eager to solve this problem, which is why I'm staying up late
> to get machine time. I must go to bed now. I look forward to another
> shot tomorrow night if you have more ideas to try.
> 
> Erik


Erik Jacobson
Software Engineer

erik.jacobson at hpe.com
+1 612 851 0550 Office

Eagan, MN
hpe.com


More information about the Gluster-users mailing list