--- attachtab.c 1999/11/23 20:05:47 1.10 +++ attachtab.c 2002/01/31 15:54:42 @@ -44,9 +44,9 @@ static int delete_attachent(locker_context context, locker_attachent *at); static int get_attachent(locker_context context, char *name, char *mountpoint, int create, - locker_attachent **atp); + locker_attachent **atp, int *lockp); static int read_attachent(locker_context context, int kind, - char *name, locker_attachent **atp); + char *name, locker_attachent **atp, int *lockp); static int lock_attachtab(locker_context context, int *lock); static void unlock_attachtab(locker_context context, int *lock); static int compare_locker__dirents(const void *a, const void *b); @@ -85,17 +85,19 @@ { /* Look for a pre-attached locker. */ at = NULL; - status = get_attachent(context, name, mountpoint, 0, &at); + status = get_attachent(context, name, mountpoint, 0, &at, &lock); if (status != LOCKER_ENOTATTACHED) { - unlock_attachtab(context, &lock); + if (lock >= 0) + unlock_attachtab(context, &lock); if (status == LOCKER_SUCCESS) *atp = at; return status; } else if (!which) { - unlock_attachtab(context, &lock); + if (lock >= 0) + unlock_attachtab(context, &lock); locker__error(context, "%s: Not attached.\n", name ? name : mountpoint); return status; @@ -167,10 +169,13 @@ } if (mountpoint) - status = get_attachent(context, NULL, at->mountpoint, which != 0, &at); + status = get_attachent(context, NULL, at->mountpoint, + which != 0, &at, &lock); else - status = get_attachent(context, name, at->mountpoint, which != 0, &at); - unlock_attachtab(context, &lock); + status = get_attachent(context, name, at->mountpoint, + which != 0, &at, &lock); + if (lock >= 0) + unlock_attachtab(context, &lock); if (status == LOCKER_SUCCESS) *atp = at; else @@ -207,8 +212,9 @@ locker_free_attachent(context, at); return status; } - status = get_attachent(context, NULL, at->mountpoint, create, &at); - unlock_attachtab(context, &lock); + status = get_attachent(context, NULL, at->mountpoint, create, &at, &lock); + if (lock >= 0) + unlock_attachtab(context, &lock); if (status == LOCKER_SUCCESS) *atp = at; else @@ -385,16 +391,21 @@ if (status == LOCKER_ENOMEM) locker__error(context, "Out of memory reading attachtab.\n"); + unlock_attachtab(context, &lock); goto cleanup; } /* Sort the entries. */ qsort(files, nfiles, sizeof(*files), compare_locker__dirents); + /* Unlock the attachtab directory, since callbacks might take a while. */ + unlock_attachtab(context, &lock); + /* Now run through the callbacks. */ for (i = 0; i < nfiles; i++) { - status = read_attachent(context, LOCKER_FULL_PATH, files[i].name, &at); + status = read_attachent(context, LOCKER_FULL_PATH, + files[i].name, &at, NULL); if (status == LOCKER_SUCCESS) { if (!test || test(context, at, testarg)) @@ -409,7 +420,6 @@ free(files[i].name); free(files); - unlock_attachtab(context, &lock); return status; } @@ -444,7 +454,7 @@ */ static int get_attachent(locker_context context, char *name, char *mountpoint, int create, - locker_attachent **atp) + locker_attachent **atp, int *lockp) { locker_attachent *at = NULL; int fd = 0; @@ -456,9 +466,9 @@ /* Try opening an existing file */ if (mountpoint) - status = read_attachent(context, LOCKER_MOUNTPOINT, mountpoint, &at); + status = read_attachent(context, LOCKER_MOUNTPOINT, mountpoint, &at, lockp); else - status = read_attachent(context, LOCKER_NAME, name, &at); + status = read_attachent(context, LOCKER_NAME, name, &at, lockp); if (status == LOCKER_SUCCESS) { @@ -635,16 +645,19 @@ } } -/* Read the named attachtab file into a locker_attachent. */ +/* Read the named attachtab file into a locker_attachent. + * May not release the attachtab lock when returning + * LOCKER_ENOTATTACHED. + */ static int read_attachent(locker_context context, int kind, char *name, - locker_attachent **atp) + locker_attachent **atp, int *lockp) { FILE *fp; char *path, *pmem = NULL, *buf = NULL, *p, *q; int bufsize, status, i; struct flock fl; locker_attachent *at; - struct stat st1, st2; + struct stat st; if (kind != LOCKER_FULL_PATH) { @@ -671,6 +684,11 @@ return LOCKER_EATTACHTAB; } + if (lockp) { + unlock_attachtab(context, lockp); + *lockp = -1; + } + fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = fl.l_len = 0; @@ -684,50 +702,6 @@ return LOCKER_EATTACHTAB; } - /* The file might have been deleted while we were waiting on the lock. - * Worse yet, someone else might have created a new one after the one - * we're waiting for was deleted, but before the deleter gave up its - * lock. So check first that it's there, and second that it's still - * the right file. - */ - if (stat(path, &st1) == -1) - { - fclose(fp); - if (errno == ENOENT) - { - free(pmem); - return LOCKER_ENOTATTACHED; - } - else - { - locker__error(context, "Could not stat attachent file %s:\n%s.\n", - path, strerror(errno)); - free(pmem); - return LOCKER_EATTACHTAB; - } - } - if (fstat(fileno(fp), &st2) == -1) - { - fclose(fp); - locker__error(context, "Could not fstat attachent file %s:\n%s.\n", - path, strerror(errno)); - free(pmem); - return LOCKER_EATTACHTAB; - } - if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) - { - fclose(fp); - free(pmem); - return LOCKER_ENOTATTACHED; - } - if (st1.st_size == 0) - { - /* "This can't happen." (Ha ha) */ - unlink(path); - fclose(fp); - free(pmem); - return LOCKER_ENOTATTACHED; - } free(pmem); /* Start building the attachent. */ @@ -1202,7 +1176,7 @@ else name = NULL; - status = get_attachent(context, name, at->mountpoint, 1, &at); + status = get_attachent(context, name, at->mountpoint, 1, &at, NULL); if (status != LOCKER_SUCCESS) { locker__error(context, "Could not create attachent for %s.\n",