From 30019e51ddefc266c939a61d26d324b7ebf3ad95 Mon Sep 17 00:00:00 2001 From: Poornima G Date: Tue, 19 Jul 2016 15:20:09 +0530 Subject: gfapi: Fix IO error caused when there is consecutive graph switches This is part 2 of the fix, the part 1 can be found at: http://review.gluster.org/#/c/14656/ Problem: ======= Consider a race between, __glfs_active_subvol() and graph_setup(). Lets say @TIME T1: fs->active_subvol = A fs->next_subvol = B __glfs_active_subvol() //under lock fs->mutex { .... new_subvol = fs->next_subvol //which is B .... //Start migration from A to B __glfs_first_lookup(){ .... unlock fs->mutex //@TIME T2 network fop lock fs->mutex .... } .... //migration continue on B fs->active_subvol = fs->next_subvol //which is C (explained below) .... } @Time T2, lets say in another thread, graph_setup() is called with C, note that at T2, fs->mutex is unlocked. graph_stup(C...) { lock fs->mutex .... if (fs->next_subvol) // which is B destroy subvol (fs->next_subvol) .... fs->next_subvol = C .... unlock fs->mutex } Thus at the end of this, fs->old_subvol = A; fs->active_subvol = C; fs->next_subvol = NULL; which is wrong, as B completed migration, but was destroyed by graph_setup, and C never was migrated. Solution: ========= Any new graph can be in one of the 2 states: - Picked for migration, migration in progress (fs->mip_subvol) - Not picked so far for migration (fs->next_subvol) graph_setup() updates fs->next_subvol only, __glfs_active_subvol() moves fs->next_subvol to fs->mip_subvol and fs->next_subvol = NULL atomically, and then once the migration is complete, make that the fs->active_subvol Change-Id: Ib6ff0565105c5eedb912a43da4017cd413243612 BUG: 1343038 Signed-off-by: Poornima G Reviewed-on: http://review.gluster.org/14722 NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Smoke: Gluster Build System Reviewed-by: Raghavendra Talur Reviewed-by: Rajesh Joseph Reviewed-by: Niels de Vos --- api/src/glfs-internal.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'api/src/glfs-internal.h') diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index a6c2709961d..dc4c3f7c18e 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -187,8 +187,16 @@ struct glfs { int ret; int err; - xlator_t *active_subvol; - xlator_t *next_subvol; + xlator_t *active_subvol; /* active graph */ + xlator_t *mip_subvol; /* graph for which migration is in + * progress */ + xlator_t *next_subvol; /* Any new graph is put to + * next_subvol, the graph in + * next_subvol can either be move to + * mip_subvol (if any IO picks it up + * for migration), or be detroyed (if + * there is a new graph, and this was + * never picked for migration) */ xlator_t *old_subvol; char *oldvolfile; -- cgit