/** * ubifs_run_commit - run or wait for commit. * @c: UBIFS file-system description object * * This function runs commit and returns zero in case of success and a negative * error code in case of failure. */ int ubifs_run_commit(struct ubifs_info *c) { int err = 0; spin_lock(&c->cs_lock); if (c->cmt_state == COMMIT_BROKEN) { err = -EINVAL; goto out; } if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) /* * We set the commit state to 'running required' to indicate * that we want it to complete as quickly as possible. */ c->cmt_state = COMMIT_RUNNING_REQUIRED; if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { spin_unlock(&c->cs_lock); return wait_for_commit(c); } spin_unlock(&c->cs_lock); /* Ok, the commit is indeed needed */ down_write(&c->commit_sem); spin_lock(&c->cs_lock); /* * Since we unlocked 'c->cs_lock', the state may have changed, so * re-check it. */ if (c->cmt_state == COMMIT_BROKEN) { err = -EINVAL; goto out_cmt_unlock; } if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) c->cmt_state = COMMIT_RUNNING_REQUIRED; if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { up_write(&c->commit_sem); spin_unlock(&c->cs_lock); return wait_for_commit(c); } c->cmt_state = COMMIT_RUNNING_REQUIRED; spin_unlock(&c->cs_lock); err = do_commit(c); return err; out_cmt_unlock: up_write(&c->commit_sem); out: spin_unlock(&c->cs_lock); return err; }
static int sync_current_delta(struct sb *sb, enum unify_flags unify_flag) { struct delta_ref *delta_ref; unsigned delta; int err = 0; #if TUX3_FLUSHER == TUX3_FLUSHER_SYNC down_write(&sb->delta_lock); #endif /* Get delta that have to write */ delta_ref = delta_get(sb); #ifdef UNIFY_DEBUG delta_ref->unify_flag = unify_flag; #endif delta = delta_ref->delta; delta_put(sb, delta_ref); trace("delta %u", delta); /* Make sure the delta transition was done for current delta */ err = wait_for_transition(sb, delta); if (err) return err; assert(delta_after_eq(sb->staging_delta, delta)); /* Wait until committing the current delta */ err = wait_for_commit(sb, delta); assert(err || delta_after_eq(sb->committed_delta, delta)); #if TUX3_FLUSHER == TUX3_FLUSHER_SYNC up_write(&sb->delta_lock); #endif return err; }
static int cmd_subvol_delete(int argc, char **argv) { int res, e, ret = 0; int cnt; int fd = -1; struct btrfs_ioctl_vol_args args; char *dname, *vname, *cpath; char *dupdname = NULL; char *dupvname = NULL; char *path; DIR *dirstream = NULL; int verbose = 0; int commit_mode = 0; optind = 1; while (1) { int c; static const struct option long_options[] = { {"commit-after", no_argument, NULL, 'c'}, /* commit mode 1 */ {"commit-each", no_argument, NULL, 'C'}, /* commit mode 2 */ {NULL, 0, NULL, 0} }; c = getopt_long(argc, argv, "cC", long_options, NULL); if (c < 0) break; switch(c) { case 'c': commit_mode = 1; break; case 'C': commit_mode = 2; break; case 'v': verbose++; break; default: usage(cmd_subvol_delete_usage); } } if (check_argc_min(argc - optind, 1)) usage(cmd_subvol_delete_usage); if (verbose > 0) { printf("Transaction commit: %s\n", !commit_mode ? "none (default)" : commit_mode == 1 ? "at the end" : "after each"); } cnt = optind; again: path = argv[cnt]; res = test_issubvolume(path); if (res < 0) { fprintf(stderr, "ERROR: error accessing '%s'\n", path); ret = 1; goto out; } if (!res) { fprintf(stderr, "ERROR: '%s' is not a subvolume\n", path); ret = 1; goto out; } cpath = realpath(path, NULL); if (!cpath) { ret = errno; fprintf(stderr, "ERROR: finding real path for '%s': %s\n", path, strerror(errno)); goto out; } dupdname = strdup(cpath); dname = dirname(dupdname); dupvname = strdup(cpath); vname = basename(dupvname); free(cpath); fd = open_file_or_dir(dname, &dirstream); if (fd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", dname); ret = 1; goto out; } printf("Delete subvolume (%s): '%s/%s'\n", commit_mode == 2 || (commit_mode == 1 && cnt + 1 == argc) ? "commit" : "no-commit", dname, vname); memset(&args, 0, sizeof(args)); strncpy_null(args.name, vname); res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args); e = errno; if(res < 0 ){ fprintf( stderr, "ERROR: cannot delete '%s/%s' - %s\n", dname, vname, strerror(e)); ret = 1; goto out; } if (commit_mode == 1) { res = wait_for_commit(fd); if (res < 0) { fprintf(stderr, "ERROR: unable to wait for commit after '%s': %s\n", path, strerror(errno)); ret = 1; } } out: free(dupdname); free(dupvname); dupdname = NULL; dupvname = NULL; cnt++; if (cnt < argc) { close_file_or_dir(fd, dirstream); /* avoid double free */ fd = -1; dirstream = NULL; goto again; } if (commit_mode == 2 && fd != -1) { res = wait_for_commit(fd); if (res < 0) { fprintf(stderr, "ERROR: unable to do final sync: %s\n", strerror(errno)); ret = 1; } } close_file_or_dir(fd, dirstream); return ret; }