mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-23 12:14:15 +08:00
fixes
This commit is contained in:
parent
ff1e0d476d
commit
7e7fa1fb94
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
2006-10-08 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Make sure inode numers wrap around at 2^32. This is needed on
|
||||
dual 64bit/32bit architectures, because 32bit applications using
|
||||
the non-largefile interface would otherwise break (EOVERFLOW error
|
||||
would be returned by the stat() system call family)
|
||||
|
||||
* ulockmgr: handle the case, when a locking operation fails
|
||||
because no more file desctriptors are available in
|
||||
ulockmgr_server. Also work around a Linux kernel bug (known to
|
||||
exist for all Linux kernel versions <= 2.6.19) which may cause
|
||||
sent file descriptors to be lost in the above case
|
||||
|
||||
* ulockmgr: optimize file descriptor use
|
||||
|
||||
* restore needed cpp flags to util/Makefile.am
|
||||
|
||||
* Install udev rules as 99-fuse.rules instead of 60-fuse.rules
|
||||
|
||||
* Minor clean up of udev rules
|
||||
|
||||
2006-10-01 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Released 2.6.0-rc2
|
||||
|
@ -256,10 +256,11 @@ static void unref_node(struct fuse *f, struct node *node)
|
||||
static fuse_ino_t next_id(struct fuse *f)
|
||||
{
|
||||
do {
|
||||
f->ctr++;
|
||||
f->ctr = (f->ctr + 1) & 0xffffffff;
|
||||
if (!f->ctr)
|
||||
f->generation ++;
|
||||
} while (f->ctr == 0 || get_node_nocheck(f, f->ctr) != NULL);
|
||||
} while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
|
||||
get_node_nocheck(f, f->ctr) != NULL);
|
||||
return f->ctr;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
51
test/test.c
51
test/test.c
@ -841,6 +841,56 @@ static int test_symlink(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_link(void)
|
||||
{
|
||||
const char *data = testdata;
|
||||
int datalen = testdatalen;
|
||||
int err = 0;
|
||||
int res;
|
||||
|
||||
start_test("link");
|
||||
res = create_file(testfile, data, datalen);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
|
||||
unlink(testfile2);
|
||||
res = link(testfile, testfile2);
|
||||
if (res == -1) {
|
||||
PERROR("link");
|
||||
return -1;
|
||||
}
|
||||
res = check_type(testfile2, S_IFREG);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
err += check_mode(testfile2, 0644);
|
||||
err += check_nlink(testfile2, 2);
|
||||
err += check_size(testfile2, datalen);
|
||||
err += check_data(testfile2, data, 0, datalen);
|
||||
res = unlink(testfile);
|
||||
if (res == -1) {
|
||||
PERROR("unlink");
|
||||
return -1;
|
||||
}
|
||||
res = check_nonexist(testfile);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
|
||||
err += check_nlink(testfile2, 1);
|
||||
res = unlink(testfile2);
|
||||
if (res == -1) {
|
||||
PERROR("unlink");
|
||||
return -1;
|
||||
}
|
||||
res = check_nonexist(testfile2);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
success();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_rename_file(void)
|
||||
{
|
||||
const char *data = testdata;
|
||||
@ -1014,6 +1064,7 @@ int main(int argc, char *argv[])
|
||||
sprintf(testdir2, "%s/testdir2", basepath);
|
||||
err += test_create();
|
||||
err += test_symlink();
|
||||
err += test_link();
|
||||
err += test_mkfifo();
|
||||
err += test_mkdir();
|
||||
err += test_rename_file();
|
||||
|
@ -1,10 +1,12 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AM_CPPFLAGS = -D_FILE_OFFSET_BITS=64
|
||||
bin_PROGRAMS = fusermount ulockmgr_server
|
||||
|
||||
fusermount_SOURCES = fusermount.c
|
||||
|
||||
ulockmgr_server_SOURCES = ulockmgr_server.c
|
||||
ulockmgr_server_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D_REENTRANT
|
||||
ulockmgr_server_LDFLAGS = -pthread
|
||||
|
||||
install-exec-hook:
|
||||
@ -34,11 +36,11 @@ install-exec-local:
|
||||
|
||||
install-data-local:
|
||||
$(mkdir_p) $(DESTDIR)$(UDEV_RULES_PATH)
|
||||
$(INSTALL_DATA) $(srcdir)/udev.rules $(DESTDIR)$(UDEV_RULES_PATH)/60-fuse.rules
|
||||
$(INSTALL_DATA) $(srcdir)/udev.rules $(DESTDIR)$(UDEV_RULES_PATH)/99-fuse.rules
|
||||
|
||||
uninstall-local:
|
||||
rm -f $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse
|
||||
rm -f $(DESTDIR)$(UDEV_RULES_PATH)/60-fuse.rules
|
||||
rm -f $(DESTDIR)$(UDEV_RULES_PATH)/99-fuse.rules
|
||||
rm -f $(DESTDIR)$(INIT_D_PATH)/fuse
|
||||
@if test -x /usr/sbin/update-rc.d; then \
|
||||
echo "/usr/sbin/update-rc.d fuse remove"; \
|
||||
|
@ -1 +1 @@
|
||||
KERNEL=="fuse", NAME="%k", MODE="0666"
|
||||
KERNEL=="fuse", MODE="0666"
|
||||
|
@ -23,7 +23,8 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
struct message {
|
||||
int intr;
|
||||
unsigned intr : 1;
|
||||
unsigned nofd : 1;
|
||||
pthread_t thr;
|
||||
int cmd;
|
||||
int fd;
|
||||
@ -35,7 +36,7 @@ struct fd_store {
|
||||
struct fd_store *next;
|
||||
int fd;
|
||||
int origfd;
|
||||
int finished;
|
||||
int inuse;
|
||||
};
|
||||
|
||||
struct owner {
|
||||
@ -53,19 +54,21 @@ struct req_data {
|
||||
#define MAX_SEND_FDS 2
|
||||
|
||||
static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
|
||||
int numfds)
|
||||
int *numfds)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
char ccmsg[CMSG_SPACE(sizeof(int)) * MAX_SEND_FDS];
|
||||
struct cmsghdr *cmsg;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
assert(numfds <= MAX_SEND_FDS);
|
||||
assert(*numfds <= MAX_SEND_FDS);
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = buflen;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(ccmsg, -1, sizeof(ccmsg));
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = ccmsg;
|
||||
@ -90,7 +93,26 @@ static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
|
||||
cmsg->cmsg_type);
|
||||
return -1;
|
||||
}
|
||||
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * numfds);
|
||||
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
|
||||
if (msg.msg_flags & MSG_CTRUNC) {
|
||||
fprintf(stderr, "ulockmgr_server: control message truncated\n");
|
||||
for (i = 0; i < *numfds; i++)
|
||||
close(fdp[i]);
|
||||
*numfds = 0;
|
||||
}
|
||||
} else {
|
||||
if (msg.msg_flags & MSG_CTRUNC) {
|
||||
fprintf(stderr, "ulockmgr_server: control message truncated(*)\n");
|
||||
|
||||
/* There's a bug in the Linux kernel, that if not all file
|
||||
descriptors were allocated, then the cmsg header is not
|
||||
filled in */
|
||||
cmsg = (struct cmsghdr *) ccmsg;
|
||||
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
|
||||
for (i = 0; i < *numfds; i++)
|
||||
close(fdp[i]);
|
||||
}
|
||||
*numfds = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -137,7 +159,7 @@ static void *process_request(void *d_)
|
||||
}
|
||||
d->msg.error = (res == -1) ? errno : 0;
|
||||
pthread_mutex_lock(&d->o->lock);
|
||||
d->f->finished = 1;
|
||||
d->f->inuse--;
|
||||
pthread_mutex_unlock(&d->o->lock);
|
||||
send_reply(d->cfd, &d->msg);
|
||||
close(d->cfd);
|
||||
@ -149,7 +171,9 @@ static void *process_request(void *d_)
|
||||
static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
int fd)
|
||||
{
|
||||
struct fd_store *f;
|
||||
struct fd_store *f = NULL;
|
||||
struct fd_store *newf = NULL;
|
||||
struct fd_store **fp;
|
||||
struct req_data *d;
|
||||
pthread_t tid;
|
||||
int res;
|
||||
@ -162,18 +186,17 @@ static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
|
||||
if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
|
||||
msg->lock.l_start == 0 && msg->lock.l_len == 0) {
|
||||
struct fd_store **fp;
|
||||
|
||||
for (fp = &o->fds; *fp;) {
|
||||
struct fd_store *f = *fp;
|
||||
if (f->origfd == msg->fd && f->finished) {
|
||||
f = *fp;
|
||||
if (f->origfd == msg->fd && !f->inuse) {
|
||||
close(f->fd);
|
||||
*fp = f->next;
|
||||
free(f);
|
||||
} else
|
||||
fp = &f->next;
|
||||
}
|
||||
close(fd);
|
||||
if (!msg->nofd)
|
||||
close(fd);
|
||||
|
||||
msg->error = 0;
|
||||
send_reply(cfd, msg);
|
||||
@ -181,16 +204,32 @@ static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
return;
|
||||
}
|
||||
|
||||
f = malloc(sizeof(struct fd_store));
|
||||
if (!f) {
|
||||
msg->error = ENOLCK;
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
return;
|
||||
}
|
||||
if (msg->nofd) {
|
||||
for (fp = &o->fds; *fp; fp = &(*fp)->next) {
|
||||
f = *fp;
|
||||
if (f->origfd == msg->fd)
|
||||
break;
|
||||
}
|
||||
if (!*fp) {
|
||||
fprintf(stderr, "ulockmgr_server: fd %i not found\n", msg->fd);
|
||||
msg->error = EIO;
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
newf = f = malloc(sizeof(struct fd_store));
|
||||
if (!f) {
|
||||
msg->error = ENOLCK;
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
return;
|
||||
}
|
||||
|
||||
f->fd = fd;
|
||||
f->origfd = msg->fd;
|
||||
f->fd = fd;
|
||||
f->origfd = msg->fd;
|
||||
f->inuse = 0;
|
||||
}
|
||||
|
||||
if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
|
||||
msg->lock.l_type == F_UNLCK) {
|
||||
@ -198,9 +237,10 @@ static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
msg->error = (res == -1) ? errno : 0;
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
f->next = o->fds;
|
||||
o->fds = f;
|
||||
f->finished = 1;
|
||||
if (newf) {
|
||||
newf->next = o->fds;
|
||||
o->fds = newf;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -209,10 +249,11 @@ static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
msg->error = ENOLCK;
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
free(f);
|
||||
free(newf);
|
||||
return;
|
||||
}
|
||||
|
||||
f->inuse++;
|
||||
d->o = o;
|
||||
d->cfd = cfd;
|
||||
d->f = f;
|
||||
@ -223,12 +264,15 @@ static void process_message(struct owner *o, struct message *msg, int cfd,
|
||||
send_reply(cfd, msg);
|
||||
close(cfd);
|
||||
free(d);
|
||||
free(f);
|
||||
f->inuse--;
|
||||
free(newf);
|
||||
return;
|
||||
}
|
||||
|
||||
f->next = o->fds;
|
||||
o->fds = f;
|
||||
if (newf) {
|
||||
newf->next = o->fds;
|
||||
o->fds = newf;
|
||||
}
|
||||
pthread_detach(tid);
|
||||
}
|
||||
|
||||
@ -258,16 +302,22 @@ static void process_owner(int cfd)
|
||||
struct message msg;
|
||||
int rfds[2];
|
||||
int res;
|
||||
int numfds = 2;
|
||||
|
||||
res = receive_message(cfd, &msg, sizeof(msg), rfds, 2);
|
||||
res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
|
||||
if (!res)
|
||||
break;
|
||||
if (res == -1)
|
||||
exit(1);
|
||||
|
||||
if (msg.intr)
|
||||
if (msg.intr) {
|
||||
if (numfds != 0)
|
||||
fprintf(stderr, "ulockmgr_server: too many fds for intr\n");
|
||||
pthread_kill(msg.thr, SIGUSR1);
|
||||
else {
|
||||
} else {
|
||||
if (numfds != 2)
|
||||
continue;
|
||||
|
||||
pthread_mutex_lock(&o.lock);
|
||||
process_message(&o, &msg, rfds[0], rfds[1]);
|
||||
pthread_mutex_unlock(&o.lock);
|
||||
@ -313,11 +363,13 @@ int main(int argc, char *argv[])
|
||||
char c;
|
||||
int sock;
|
||||
int pid;
|
||||
int res = receive_message(cfd, &c, sizeof(c), &sock, 1);
|
||||
int numfds = 1;
|
||||
int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
|
||||
if (!res)
|
||||
break;
|
||||
if (res == -1)
|
||||
exit(1);
|
||||
assert(numfds == 1);
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
|
Loading…
Reference in New Issue
Block a user