static int sync_lock(struct gfs2_sbd *sdp, int mode, uint32_t flags, unsigned int num, struct dlm_lksb *lksb, char *name) { struct lm_lockstruct *ls = &sdp->sd_lockstruct; char strname[GDLM_STRNAME_BYTES]; int error, status; memset(strname, 0, GDLM_STRNAME_BYTES); snprintf(strname, GDLM_STRNAME_BYTES, "%8x%16x", LM_TYPE_NONDISK, num); error = dlm_lock(ls->ls_dlm, mode, lksb, flags, strname, GDLM_STRNAME_BYTES - 1, 0, sync_wait_cb, ls, NULL); if (error) { fs_err(sdp, "%s lkid %x flags %x mode %d error %d\n", name, lksb->sb_lkid, flags, mode, error); return error; } wait_for_completion(&ls->ls_sync_wait); status = lksb->sb_status; if (status && status != -EAGAIN) { fs_err(sdp, "%s lkid %x flags %x mode %d status %d\n", name, lksb->sb_lkid, flags, mode, status); } return status; }
/* * An variation of dlm_lock_sync, which make lock request could * be interrupted */ static int dlm_lock_sync_interruptible(struct dlm_lock_resource *res, int mode, struct mddev *mddev) { int ret = 0; ret = dlm_lock(res->ls, mode, &res->lksb, res->flags, res->name, strlen(res->name), 0, sync_ast, res, res->bast); if (ret) return ret; wait_event(res->sync_locking, res->sync_locking_done || kthread_should_stop() || test_bit(MD_CLOSING, &mddev->flags)); if (!res->sync_locking_done) { /* * the convert queue contains the lock request when request is * interrupted, and sync_ast could still be run, so need to * cancel the request and reset completion */ ret = dlm_unlock(res->ls, res->lksb.sb_lkid, DLM_LKF_CANCEL, &res->lksb, res); res->sync_locking_done = false; if (unlikely(ret != 0)) pr_info("failed to cancel previous lock request " "%s return %d\n", res->name, ret); return -EPERM; } else res->sync_locking_done = false; if (res->lksb.sb_status == 0) res->mode = mode; return res->lksb.sb_status; }
static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, unsigned int flags) { struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; int req; u32 lkf; char strname[GDLM_STRNAME_BYTES] = ""; req = make_mode(req_state); lkf = make_flags(gl, flags, req); gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); if (gl->gl_lksb.sb_lkid) { gfs2_update_request_times(gl); } else { memset(strname, ' ', GDLM_STRNAME_BYTES - 1); strname[GDLM_STRNAME_BYTES - 1] = '\0'; gfs2_reverse_hex(strname + 7, gl->gl_name.ln_type); gfs2_reverse_hex(strname + 23, gl->gl_name.ln_number); gl->gl_dstamp = ktime_get_real(); } /* * Submit the actual lock request. */ return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname, GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); }
static int convert_lock(int mode) { int status; printf("pinglock: convert to %d starting\n", mode); status = dlm_lock( mode, &our_lksb, LKF_VALBLK | LKF_CONVERT, NULL, 0, 0, compast_routine, &our_lksb, blockast_routine, NULL); if (status != 0) { perror("pinglock: convert failed"); } else { cur_mode = mode; printf("pinglock: convert to %d started\n", mode); } return status; }
/* lock_resource & unlock_resource * are the simplified, synchronous API. * Aways uses the default lockspace. */ int lock_resource(const char *resource, int mode, int flags, int *lockid) { int status; struct lock_wait lwait; if (default_ls == NULL) { if (dlm_pthread_init()) { return -1; } } if (!lockid) { errno = EINVAL; return -1; } /* Conversions need the lockid in the LKSB */ if (flags & LKF_CONVERT) lwait.lksb.sb_lkid = *lockid; pthread_cond_init(&lwait.cond, NULL); pthread_mutex_init(&lwait.mutex, NULL); pthread_mutex_lock(&lwait.mutex); status = dlm_lock(mode, &lwait.lksb, flags, resource, strlen(resource), 0, sync_ast_routine, &lwait, NULL, NULL); if (status) return status; /* Wait for it to complete */ pthread_cond_wait(&lwait.cond, &lwait.mutex); pthread_mutex_unlock(&lwait.mutex); *lockid = lwait.lksb.sb_lkid; errno = lwait.lksb.sb_status; if (lwait.lksb.sb_status) return -1; else return 0; }
static int dlm_lock_sync(struct dlm_lock_resource *res, int mode) { int ret = 0; init_completion(&res->completion); ret = dlm_lock(res->ls, mode, &res->lksb, res->flags, res->name, strlen(res->name), 0, sync_ast, res, res->bast); if (ret) return ret; wait_for_completion(&res->completion); return res->lksb.sb_status; }
static int dlm_lock_sync(struct dlm_lock_resource *res, int mode) { int ret = 0; ret = dlm_lock(res->ls, mode, &res->lksb, res->flags, res->name, strlen(res->name), 0, sync_ast, res, res->bast); if (ret) return ret; wait_event(res->sync_locking, res->sync_locking_done); res->sync_locking_done = false; if (res->lksb.sb_status == 0) res->mode = mode; return res->lksb.sb_status; }
static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, unsigned int flags) { struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; int req; u32 lkf; req = make_mode(req_state); lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); /* * Submit the actual lock request. */ return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname, GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); }
static void start_lock(void) { int status; cur_mode = LKM_EXMODE; *lvb_int = us-1; printf("pinglock: starting\n"); status = dlm_lock( cur_mode, &our_lksb, LKF_VALBLK, lockname, strlen(lockname)+1, /* include trailing NUL for ease of following */ 0, /* Parent */ compast_routine, &our_lksb, blockast_routine, NULL); if (status != 0) perror("pinglock: lock failed"); }
static unsigned int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, unsigned int flags) { struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; int error; int req; u32 lkf; gl->gl_req = req_state; req = make_mode(req_state); lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); /* * Submit the actual lock request. */ error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname, GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); if (error == -EAGAIN) return 0; if (error) return LM_OUT_ERROR; return LM_OUT_ASYNC; }
int main(int argc, char *argv[]) { const char *resource = "LOCK-NAME"; int flags = 0; int delay = 0; int status; int mode = LKM_EXMODE; int convmode = -1; int do_unlock = 1; int do_crash = 0; signed char opt; /* Deal with command-line arguments */ opterr = 0; optind = 0; while ((opt=getopt(argc,argv,"?m:nqupc:d:CvV")) != EOF) { switch(opt) { case 'h': usage(argv[0], stdout); exit(0); case '?': usage(argv[0], stderr); exit(0); case 'm': mode = modetonum(optarg); break; case 'c': convmode = modetonum(optarg); break; case 'p': use_threads++; break; case 'n': flags |= LKF_NOQUEUE; break; case 'q': quiet = 1; break; case 'u': do_unlock = 0; break; case 'C': do_crash = 1; break; case 'd': delay = atoi(optarg); break; case 'V': printf("\nasttest version 0.1\n\n"); exit(1); break; } } if (argv[optind]) resource = argv[optind]; if (!quiet) fprintf(stderr, "locking %s %s %s...", resource, numtomode(mode), (flags&LKF_NOQUEUE?"(NOQUEUE)":"")); fflush(stderr); if (use_threads) { pthread_cond_init(&cond, NULL); pthread_mutex_init(&mutex, NULL); pthread_mutex_lock(&mutex); dlm_pthread_init(); } status = dlm_lock(mode, &lksb, flags, resource, strlen(resource), 0, // Parent, ast_routine, &lksb, bast_routine, NULL); // Range if (status == -1) { if (!quiet) fprintf(stderr, "\n"); perror("lock"); return -1; } printf("(lkid=%x)", lksb.sb_lkid); if (do_crash) *(int *)0 = 0xdeadbeef; /* Wait */ if (use_threads) pthread_cond_wait(&cond, &mutex); else poll_for_ast(); if (delay) sleep(delay); if (!quiet) { fprintf(stderr, "unlocking %s...", resource); fflush(stderr); } if (do_unlock) { status = dlm_unlock(lksb.sb_lkid, 0, // flags &lksb, &lksb); // AST args if (status == -1) { if (!quiet) fprintf(stderr, "\n"); perror("unlock"); return -1; } /* Wait */ if (use_threads) pthread_cond_wait(&cond, &mutex); else poll_for_ast(); } return 0; }
int main(int argc, char *argv[]) { int flags = 0; int lockops = 0; int maxlocks = 100000; int rescount = 10; int increment = 1000; int quiet = 0; int status; int i; int mode = LKM_CRMODE; int lksbnum = 0; signed char opt; char **resources; struct dlm_lksb *lksbs; /* Deal with command-line arguments */ opterr = 0; optind = 0; while ((opt=getopt(argc,argv,"?m:i:qn:vV")) != EOF) { switch(opt) { case 'h': usage(argv[0], stdout); exit(0); case '?': usage(argv[0], stderr); exit(0); case 'm': maxlocks = atoi(optarg); break; case 'i': increment = atoi(optarg); break; case 'n': rescount = atoi(optarg); break; case 'q': quiet = 1; break; case 'V': printf("\nflood version 0.3\n\n"); exit(1); break; } } if ((resources = malloc(sizeof(char*) * rescount)) == NULL) { perror("exhausted virtual memory"); return 1; } for (i=0; i < rescount; i++) { char resname[256]; sprintf(resname, "TESTLOCK%d", i); resources[i] = strdup(resname); } lksbs = malloc(sizeof(struct dlm_lksb) * maxlocks); if (!lksbs) { perror("cannot allocate lksbs"); return 1; } pthread_cond_init(&cond, NULL); pthread_mutex_init(&mutex, NULL); pthread_mutex_lock(&mutex); dlm_pthread_init(); while (1) { char *resource = resources[rand() % rescount]; status = dlm_lock(mode, &lksbs[lksbnum], flags, resource, strlen(resource), 0, // Parent, ast_routine, &lksbs[lksbnum], NULL, // bast_routine, NULL); // Range if (status == -1) { perror("lock failed"); return -1; } count++; lockops++; if ((lockops % increment) == 0 && !quiet) fprintf(stderr, "%d lockops, %d locks\n", lockops, count); while (count > maxlocks) { sleep(1); } lksbnum = (lksbnum+1)%maxlocks; } return 0; }