This commit is contained in:
Miklos Szeredi 2006-10-08 15:41:20 +00:00
parent ff1e0d476d
commit 7e7fa1fb94
7 changed files with 202 additions and 55 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View 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"; \

View File

@ -1 +1 @@
KERNEL=="fuse", NAME="%k", MODE="0666"
KERNEL=="fuse", MODE="0666"

View File

@ -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) {