aboutsummaryrefslogtreecommitdiff
path: root/lib/ulockmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ulockmgr.c')
-rw-r--r--lib/ulockmgr.c56
1 files changed, 38 insertions, 18 deletions
diff --git a/lib/ulockmgr.c b/lib/ulockmgr.c
index 012a450..9e9c2b6 100644
--- a/lib/ulockmgr.c
+++ b/lib/ulockmgr.c
@@ -22,7 +22,8 @@
#include <sys/wait.h>
struct message {
- int intr;
+ unsigned intr : 1;
+ unsigned nofd : 1;
pthread_t thr;
int cmd;
int fd;
@@ -33,7 +34,7 @@ struct message {
struct fd_store {
struct fd_store *next;
int fd;
- int finished;
+ int inuse;
};
struct owner {
@@ -176,7 +177,9 @@ static int ulockmgr_send_request(struct message *msg, const void *id,
int sv[2];
int cfd;
struct owner *o;
- struct fd_store *f;
+ struct fd_store *f = NULL;
+ struct fd_store *newf = NULL;
+ struct fd_store **fp;
int fd = msg->fd;
int cmd = msg->cmd;
int res;
@@ -203,32 +206,51 @@ static int ulockmgr_send_request(struct message *msg, const void *id,
return -ENOLCK;
}
- f = calloc(1, sizeof(struct fd_store));
- if (!f) {
- fprintf(stderr, "libulockmgr: failed to allocate memory\n");
- return -ENOLCK;
+ if (unlockall)
+ msg->nofd = 1;
+ else {
+ for (fp = &o->fds; *fp; fp = &(*fp)->next) {
+ f = *fp;
+ if (f->fd == fd) {
+ msg->nofd = 1;
+ break;
+ }
+ }
+ }
+
+ if (!msg->nofd) {
+ newf = f = calloc(1, sizeof(struct fd_store));
+ if (!f) {
+ fprintf(stderr, "libulockmgr: failed to allocate memory\n");
+ return -ENOLCK;
+ }
}
res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
if (res == -1) {
perror("libulockmgr: socketpair");
- free(f);
+ free(newf);
return -ENOLCK;
}
cfd = sv[1];
sv[1] = msg->fd;
- res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv, 2);
+ res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv,
+ msg->nofd ? 1 : 2);
close(sv[0]);
if (res == -1) {
- free(f);
+ free(newf);
close(cfd);
return -EIO;
}
- f->fd = msg->fd;
- f->next = o->fds;
- o->fds = f;
+ if (newf) {
+ newf->fd = msg->fd;
+ newf->next = o->fds;
+ o->fds = newf;
+ }
+ if (f)
+ f->inuse++;
res = recv(cfd, msg, sizeof(struct message), MSG_WAITALL);
if (res == -1) {
@@ -278,15 +300,13 @@ static int ulockmgr_send_request(struct message *msg, const void *id,
pthread_mutex_lock(&ulockmgr_lock);
}
-
- f->finished = 1;
+ if (f)
+ f->inuse--;
close(cfd);
if (unlockall) {
- struct fd_store **fp;
-
for (fp = &o->fds; *fp;) {
f = *fp;
- if (f->fd == fd && f->finished) {
+ if (f->fd == fd && !f->inuse) {
*fp = f->next;
free(f);
} else