From 1b22d8e098abf1f2cf4f479dab158c7a93805d11 Mon Sep 17 00:00:00 2001 From: Bob Gilligan Date: Mon, 17 Mar 2008 16:53:30 -0700 Subject: Bugfix: 2885 Place the "changes only" directory that is used by the configuration subsystem in its union mount into /tmp. We see kernel panics in unionfs at umount time in some cases when the "changes only" directory is located in a tmpfs filesystem. --- src/commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/commit.c') diff --git a/src/commit.c b/src/commit.c index c3219e5..980a98b 100644 --- a/src/commit.c +++ b/src/commit.c @@ -1359,7 +1359,7 @@ static int fin_commit(boolean ok) system(command); my_free(command); - command = my_malloc(strlen(format3) + c_len, ""); + command = my_malloc(strlen(format3) + t_len, ""); sprintf(command, format3, get_tmpp()); system(command); my_free(command); -- cgit v1.2.3 From 06702f2ed04408962d7e8e6323db97e29dd32669 Mon Sep 17 00:00:00 2001 From: An-Cheng Huang Date: Mon, 31 Mar 2008 16:40:33 -0700 Subject: fix for bug 2675: correctly detect newly created config nodes. --- src/commit.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/commit.c') diff --git a/src/commit.c b/src/commit.c index 980a98b..8fbc1d6 100644 --- a/src/commit.c +++ b/src/commit.c @@ -747,17 +747,16 @@ static boolean commit_delete_child(vtw_def *pdefp, char *child, mark_paths(&mark); if (!deleting) { int status; - /* are we marked with opaque */ push_path(&m_path, child); - push_path(&m_path, opaque_name); + switch_path(APATH); /* switch to active */ status = lstat(m_path.path, &statbuf); + switch_path(CPATH); /* back to changes */ pop_path(&m_path); - pop_path(&m_path); - if (status >= 0) { - /* brand new directory, nothing is - deleted there; - update will handle txn (both begin and end) - */ + if (status < 0) { + /* node doesn't exist in active config. it's newly created + * so we don't need to handle delete. update will handle the + * transaction (if any). + */ return TRUE; } } -- cgit v1.2.3 From bcdf7826a9e29cd48627ffb57b665fcad9a714fa Mon Sep 17 00:00:00 2001 From: An-Cheng Huang Date: Thu, 3 Apr 2008 12:19:50 -0700 Subject: code cleanup (remove some evil copy-and-paste instances). --- src/commit.c | 206 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 113 insertions(+), 93 deletions(-) (limited to 'src/commit.c') diff --git a/src/commit.c b/src/commit.c index 8fbc1d6..6ed8632 100644 --- a/src/commit.c +++ b/src/commit.c @@ -53,6 +53,23 @@ static void make_dir() } #endif +static struct dirent * +get_next_filtered_dirent(DIR *dp, int exclude_wh) +{ + struct dirent *dirp = NULL; + while ((dirp = readdir(dp)) != NULL) { + if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0 + || strcmp(dirp->d_name, MOD_NAME) == 0 + || strcmp(dirp->d_name, opaque_name) == 0 + || (exclude_wh && strncmp(dirp->d_name, ".wh.", 4) == 0)) { + continue; + } else { + return dirp; + } + } + return dirp; +} + /************************************************* validate_dir_for_commit: validate value.value if there is one, validate @@ -114,16 +131,7 @@ static boolean validate_dir_for_commit() push_path(&t_path, tag_name); /* PUSH 2a */ } - while ((dirp = readdir(dp)) != NULL) { - - if (strcmp(dirp->d_name, ".") == 0 || - strcmp(dirp->d_name, "..") == 0 || - strcmp(dirp->d_name, MOD_NAME) == 0 || - strcmp(dirp->d_name, opaque_name) == 0 || - strncmp(dirp->d_name, ".wh.", 4) == 0) { - continue; /*ignore dot and dot-dot*/ - } - + while ((dirp = get_next_filtered_dirent(dp, 1)) != NULL) { subdirs_number++; if(uename) @@ -916,25 +924,82 @@ static boolean commit_delete_child(vtw_def *pdefp, char *child, return ok; } +/* add a value to the valstruct. struct must be initialized (memset 0). + * cp: pointer to value + * type: type of value + */ +static void +valstruct_append(valstruct *mvals, char *cp, vtw_type_e type) +{ + if (!(mvals->free_me)) { + /* empty struct. add 1st value */ + mvals->free_me = TRUE; + mvals->val = cp; + mvals->val_type = type; + } else { + if ((mvals->cnt % MULTI_ALLOC) == 0) { + /* convert into multivalue */ + mvals->vals = my_realloc(mvals->vals, (mvals->cnt + MULTI_ALLOC) + * sizeof(char *), "add_value"); + if (mvals->cnt == 0) { /* single value - convert */ + mvals->vals[0] = mvals->val; + mvals->cnt= 1; + mvals->val = NULL; + } + } + mvals->vals[mvals->cnt] = cp; + ++mvals->cnt; + } +} + +/* get the filtered directory listing and put the names in valstruct. + * dp: target directory + * mvals: structure for storing the names + * type: type of the names + * exclude_wh: exclude whiteouts + */ +static void +get_filtered_directory_listing(DIR *dp, valstruct *mvals, vtw_type_e type, + int exclude_wh) +{ + struct dirent *dirp = NULL; + char *cp = NULL; + + memset(mvals, 0, sizeof (valstruct)); + while ((dirp = get_next_filtered_dirent(dp, exclude_wh)) != NULL) { + cp = clind_unescape(dirp->d_name); + valstruct_append(mvals, cp, type); + } +} + static boolean commit_delete_children(vtw_def *defp, boolean deleting, boolean in_txn) { - DIR *dp; - int status; - struct dirent *dirp; + DIR *dp, *adp = NULL, *mdp = NULL; boolean ok = TRUE; char *child; vtw_type_e type; - valstruct mvals; - boolean first; - char *cp; + valstruct mvals, valsA, valsM; int elem, curi; vtw_sorted cur_sorted; - char *uename = NULL; + + if (!deleting) { + switch_path(APATH); /* switch to active */ + if ((adp = opendir(m_path.path)) == NULL) { + INTERNAL; + } + switch_path(MPATH); /* switch to modified */ + if ((mdp = opendir(m_path.path)) == NULL) { + INTERNAL; + } + switch_path(CPATH); /* back to changes */ + } if ((dp = opendir(m_path.path)) == NULL){ - if (deleting) + if (deleting) { + /* deleting. adp & mdp are not opened so no need to close. */ return TRUE; + } INTERNAL; } if (defp) @@ -943,46 +1008,37 @@ static boolean commit_delete_children(vtw_def *defp, boolean deleting, type = TEXT_TYPE; if (type == ERROR_TYPE) type = TEXT_TYPE; - first = TRUE; memset(&mvals, 0, sizeof (valstruct)); + memset(&valsA, 0, sizeof (valstruct)); + memset(&valsM, 0, sizeof (valstruct)); memset(&cur_sorted, 0, sizeof(vtw_sorted)); - while ((dirp = readdir(dp)) != NULL) { - child = dirp->d_name; - if (strcmp(child, ".") == 0 || - strcmp(child, "..") == 0 || - strcmp(child, MOD_NAME) == 0 || - strcmp(child, OPQ_NAME) == 0) - continue; - uename = clind_unescape(child); - cp = uename; - if (first) { - mvals.free_me = TRUE; - mvals.val = cp; - mvals.val_type = type; - first = FALSE; - } else { - if (mvals.cnt%MULTI_ALLOC == 0) { - /* convert into multivalue */ - mvals.vals = my_realloc(mvals.vals, - (mvals.cnt + MULTI_ALLOC) * - sizeof(char *), "add_value"); - if (mvals.cnt == 0) { /* single value - convert */ - mvals.vals[0] = mvals.val; - mvals.cnt= 1; - mvals.val = NULL; - } - } - mvals.vals[mvals.cnt] = cp; - ++mvals.cnt; + get_filtered_directory_listing(dp, &mvals, type, 0); + if (closedir(dp) != 0) { + INTERNAL; + } + if (adp) { + get_filtered_directory_listing(adp, &valsA, type, 0); + if (closedir(adp) != 0) { + INTERNAL; } } - status = closedir(dp); - if (status) - INTERNAL; - if (first) { + if (mdp) { + get_filtered_directory_listing(mdp, &valsM, type, 0); + if (closedir(mdp) != 0) { + INTERNAL; + } + } + + if (!(mvals.free_me)) { + /* empty struct. nothing to do. */ return TRUE; } + /* XXX TODO */ + /* for each "node" in A but not in M + * if ".wh.node" is not in mvals + * add ".wh.node" to mvals + */ vtw_sort(&mvals, &cur_sorted); for (curi = 0; curi < cur_sorted.num && ok; ++curi){ if (type == TEXT_TYPE || @@ -1006,18 +1062,12 @@ static boolean commit_update_children(vtw_def *defp, boolean creating, boolean in_txn, boolean *parent_update) { DIR *dp; - int status; - struct dirent *dirp; boolean ok = TRUE; char *child; vtw_type_e type; valstruct mvals; - boolean first; - char *cp; int elem, curi; vtw_sorted cur_sorted; - char *uename = NULL; - if ((dp = opendir(m_path.path)) == NULL){ printf("%s:%d: opendir error: path=%s\n", @@ -1033,43 +1083,14 @@ static boolean commit_update_children(vtw_def *defp, boolean creating, type = TEXT_TYPE; if (type == ERROR_TYPE) type = TEXT_TYPE; - first = TRUE; - while ((dirp = readdir(dp)) != NULL) { - child = dirp->d_name; - if (strcmp(child, ".") == 0 || - strcmp(child, "..") == 0 || - strcmp(child, MOD_NAME) == 0 || - strcmp(child, OPQ_NAME) == 0) - continue; - cp = uename = clind_unescape(child); - if (first) { - mvals.free_me = TRUE; - mvals.val = cp; - mvals.val_type = type; - first = FALSE; - } else { - if (mvals.cnt%MULTI_ALLOC == 0) { - /* convert into multivalue */ - mvals.vals = my_realloc(mvals.vals, - (mvals.cnt + MULTI_ALLOC) * - sizeof(char *), "add_value"); - if (mvals.cnt == 0) { /* single value - convert */ - mvals.vals[0] = mvals.val; - mvals.cnt= 1; - mvals.val = NULL; - } - } - mvals.vals[mvals.cnt] = cp; - ++mvals.cnt; - } - } - status = closedir(dp); - if (status) + get_filtered_directory_listing(dp, &mvals, type, 0); + if (closedir(dp) != 0) { INTERNAL; - if (first) { - if (uename) - my_free(uename); + } + + if (!(mvals.free_me)) { + /* empty struct. nothing to do. */ return TRUE; } vtw_sort(&mvals, &cur_sorted); @@ -1164,7 +1185,6 @@ static boolean commit_value(vtw_def *defp, char *cp, /* act_value will be freed by freeing cur_value do not zero out it here */ } - acti = 0; curi = 0; total = act_sorted.num + cur_sorted.num; -- cgit v1.2.3 From 9158b59fd7cdd018a5c9b1e36c097b0436fd02a4 Mon Sep 17 00:00:00 2001 From: An-Cheng Huang Date: Thu, 3 Apr 2008 15:09:34 -0700 Subject: fix for bug 3097: correctly detect deleted tag --- src/commit.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 8 deletions(-) (limited to 'src/commit.c') diff --git a/src/commit.c b/src/commit.c index 6ed8632..534757c 100644 --- a/src/commit.c +++ b/src/commit.c @@ -972,6 +972,65 @@ get_filtered_directory_listing(DIR *dp, valstruct *mvals, vtw_type_e type, } } +/* check if a value is one of those in a valstruct. + * cp: pointer to value + * vals: pointer to valstruct + * + * return 1 if yes, 0 otherwise. + * TODO: optimization + */ +static int +is_val_in_valstruct(char *cp, valstruct *vals) +{ + int i = 0; + if (!(vals->free_me)) { + /* empty struct. */ + return 0; + } + if (vals->cnt == 0) { + /* single-value struct */ + if (strcmp(cp, vals->val) == 0) { + return 1; + } + return 0; + } + /* multi-value */ + for (i = 0; i < vals->cnt; i++) { + if (strcmp(cp, vals->vals[i]) == 0) { + return 1; + } + } + return 0; +} + +/* returns the value at a particular index in a valstruct. + * vals: pointer to the valstruct + * idx: index of the value + * + * return pointer to the value, NULL if idx is not valid. + */ +static char * +idx_val_in_valstruct(valstruct *vals, int idx) +{ + if (!(vals->free_me)) { + /* empty struct. */ + return NULL; + } + if (vals->cnt == 0) { + /* single-value struct */ + if (idx == 0) { + return vals->val; + } + return NULL; + } + /* multi-value */ + if ((idx < 0) || (idx >= vals->cnt)) { + return NULL; + } + return vals->vals[idx]; +} + + static boolean commit_delete_children(vtw_def *defp, boolean deleting, boolean in_txn) { @@ -1013,32 +1072,53 @@ static boolean commit_delete_children(vtw_def *defp, boolean deleting, memset(&valsM, 0, sizeof (valstruct)); memset(&cur_sorted, 0, sizeof(vtw_sorted)); + /* changes directory */ get_filtered_directory_listing(dp, &mvals, type, 0); if (closedir(dp) != 0) { INTERNAL; } - if (adp) { + + if (adp && mdp) { + /* active directory */ get_filtered_directory_listing(adp, &valsA, type, 0); if (closedir(adp) != 0) { INTERNAL; } - } - if (mdp) { + /* modified directory */ get_filtered_directory_listing(mdp, &valsM, type, 0); if (closedir(mdp) != 0) { INTERNAL; } + + if (valsA.free_me) { + /* A is not empty */ + int idx = 0; + char *cp = NULL; + for (idx = 0; (cp = idx_val_in_valstruct(&valsA, idx)); idx++) { + if (!is_val_in_valstruct(cp, &valsM)) { + /* cp is in A but not in M */ + /* construct whiteout name */ + char *wh_name = my_malloc(strlen(cp) + 4 + 1, "del_children"); + strcpy(wh_name, ".wh."); + strcpy(wh_name + 4, cp); + if (!is_val_in_valstruct(wh_name, &mvals)) { + /* whiteout not in C */ + /* add whiteout to mvals */ + valstruct_append(&mvals, wh_name, type); + } + } + } + free_val(&valsA); + } + if (valsM.free_me) { + free_val(&valsM); + } } if (!(mvals.free_me)) { /* empty struct. nothing to do. */ return TRUE; } - /* XXX TODO */ - /* for each "node" in A but not in M - * if ".wh.node" is not in mvals - * add ".wh.node" to mvals - */ vtw_sort(&mvals, &cur_sorted); for (curi = 0; curi < cur_sorted.num && ok; ++curi){ if (type == TEXT_TYPE || -- cgit v1.2.3