3 * Copyright (C) 2002 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
8 * LUFS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * LUFS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/version.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/socket.h>
30 #include <linux/types.h>
31 #include <linux/list.h>
32 #include <linux/smp_lock.h>
33 #include <linux/net.h>
34 #include <linux/vfs.h>
35 #include <linux/mount.h>
37 #include <asm/system.h>
38 #include <asm/uaccess.h>
43 static int sock_send(struct socket *sock, struct iovec *iov, int len)
57 for(i = 0, size = 0; i < len; i++)
58 size += iov[i].iov_len;
62 res = sock_sendmsg(sock, &msg, size);
68 static int sock_recv(struct socket *sock, struct iovec *iov, int len, int rsize, unsigned flags)
82 for(i = 0, size = 0; i < len; i++)
83 size += iov[i].iov_len;
86 VERBOSE("Trying to overflow old me?! Truncating...\n");
92 res = sock_recvmsg(sock, &msg, rsize, flags);
98 static int sock_connect(char *path, struct socket **s)
100 struct sockaddr_un addr;
103 if(strlen(path) > UNIX_PATH_MAX - 1){
104 WARN("unix domain path too long: %s", path);
108 addr.sun_family = AF_UNIX;
109 strcpy(addr.sun_path, path);
111 if((res = sock_create(PF_UNIX, SOCK_STREAM, 0, s)) < 0){
112 WARN("failed to create a unix domain socket!\n");
116 if((res = (*s)->ops->connect(*s, (struct sockaddr*)&addr, sizeof(addr), 0)) < 0){
117 WARN("failed to connect the socket: %d!\n", res);
123 static int slot_reconnect(struct lufs_sb_info *info, struct server_slot *slot)
125 int res = 0, tries = 0;
128 TRACE("closing socket.\n");
129 sock_release(slot->s_sock);
133 while(tries++ < LU_MAXTRIES && (res = sock_connect(info->server_socket, &slot->s_sock)) < 0){
134 TRACE("retrying...\n");
135 sock_release(slot->s_sock);
140 TRACE("successfully reconnected.\n");
146 void lu_empty_slots(struct lufs_sb_info *info)
148 struct server_slot *slot;
150 while(!list_empty(&info->slots)){
151 slot = list_entry(info->slots.next, struct server_slot, s_list);
153 sock_release(slot->s_sock);
154 list_del(&slot->s_list);
161 static int do_execute(struct socket *sock, unsigned short cmd, unsigned short msglen, struct iovec *siov, unsigned short slen, struct iovec *riov, unsigned short rlen)
167 TRACE("msg_len: %d\n", msglen);
169 msg.msg_version = PVERSION;
171 msg.msg_datalen = msglen;
172 msg.msg_pid = current->pid;
175 iov.iov_len = sizeof(struct lu_msg);
177 if((res = sock_send(sock, &iov, 1)) < 0){
178 WARN("sock_send failed!\n");
181 if((res = sock_send(sock, siov, slen)) < 0){
182 WARN("sock_send failed!\n");
187 iov.iov_len = sizeof(struct lu_msg);
188 if((res = sock_recv(sock, &iov, 1, sizeof(struct lu_msg), 0)) < 0){
189 WARN("sock_recv failed!\n");
192 if(res != sizeof(struct lu_msg)){
193 WARN("Ayeeee, didn't read a whole header!\n");
197 if((msg.msg_datalen == 0))
201 WARN("Unexpected data!!! Getting out of sync...\n");
205 if((res = sock_recv(sock, riov, rlen, msg.msg_datalen, 0)) < 0){
206 WARN("sock_recv failed!\n");
213 struct server_slot* lu_getslot(struct lufs_sb_info *info)
215 struct list_head *p, *nd_best = NULL;
216 struct server_slot *slot;
219 /* Look for a slot used by this process before */
220 read_lock(&info->lock);
221 list_for_each(p, &info->slots)
222 if(list_entry(p, struct server_slot, s_list)->s_lastpid == current->pid){
223 TRACE("found a previous used slot for %u.\n", current->pid);
224 if(down_trylock(&list_entry(p, struct server_slot, s_list)->s_lock) == 0){
228 TRACE("oops! I still hold the lock! forget this one...\n");
234 /* if we couldn't find one, take the first not locked by us */
235 if(p == &info->slots){
237 ERROR("deadlock: all locks owned by us!\n");
238 read_unlock(&info->lock);
244 read_unlock(&info->lock);
246 slot = list_entry(p, struct server_slot, s_list);
248 /* Get the lock on that slot */
250 if(down_interruptible(&slot->s_lock))
253 slot->s_lastpid = current->pid;
255 /* Move it to the tail */
256 write_lock(&info->lock);
258 list_add_tail(p, &info->slots);
259 write_unlock(&info->lock);
264 void lu_putslot(struct server_slot *slot)
269 int lu_execute(struct lufs_sb_info *info, struct server_slot *slot, unsigned short cmd, struct iovec *siov, unsigned short slen, struct iovec *riov, unsigned short rlen)
272 struct iovec bkup[LU_MAXIOVEC];
274 for(i = 0, msglen = 0; i < slen; i++){
276 msglen += siov[i].iov_len;
279 if(slot->s_sock == NULL){
280 TRACE("slot not connected.\n");
281 if((res = slot_reconnect(info, slot)) < 0){
282 ERROR("failed to connect!\n");
287 if((res = do_execute(slot->s_sock, cmd, msglen, siov, slen, riov, rlen)) < 0){
288 TRACE("do_execute failed!\n");
290 if(signal_pending(current) && (!sigismember(¤t->pending.signal, SIGPIPE))){
291 TRACE("interrupted by a signal. disconnecting this slot...\n");
292 sock_release(slot->s_sock);
297 if(sigismember(¤t->pending.signal, SIGPIPE)){
298 TRACE("got a SIGPIPE\n");
299 sigdelset(¤t->pending.signal, SIGPIPE);
302 if((res = slot_reconnect(info, slot)) < 0){
303 ERROR("could't reconnect!\n");
307 for(i = 0; i < slen; i++)
310 if((res = do_execute(slot->s_sock, cmd, msglen, siov, slen, riov, rlen)) < 0){
311 ERROR("error executing command!\n");
320 int lu_getname(struct dentry *d, char *name, int max)
324 struct lufs_sb_info *info = GET_INFO(d->d_sb);
326 for(p = d; p != p->d_parent; p = p->d_parent)
327 len += p->d_name.len + 1;
329 TRACE("root: %s, rootlen: %d, namelen: %d\n", info->root, info->rootlen, len);
331 if(len + info->rootlen > max)
334 strcpy(name, info->root);
336 if(len + info->rootlen == 0){
341 len += info->rootlen;
344 for(p = d; p != p->d_parent; p = p->d_parent){
345 len -= p->d_name.len;
346 strncpy(&(name[len]), p->d_name.name, p->d_name.len);
351 TRACE("name resolved to %s\n", name);
355 int lu_getname_dumb(struct dentry *d, char *name, int max)
360 for(p = d; p != p->d_parent; p = p->d_parent)
361 len += p->d_name.len + 1;
373 for(p = d; p != p->d_parent; p = p->d_parent){
374 len -= p->d_name.len;
375 strncpy(&(name[len]), p->d_name.name, p->d_name.len);
383 static void init_root_dirent(struct lufs_sb_info *server, struct lufs_fattr *fattr)
385 memset(fattr, 0, sizeof(struct lufs_fattr));
387 fattr->f_uid = server->config.uid;
388 fattr->f_gid = server->config.gid;
389 fattr->f_blksize = 512;
391 fattr->f_mtime = CURRENT_TIME.tv_sec;
392 fattr->f_mode = S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH | S_IFDIR | server->config.dmode;
397 void lu_lookup_root(struct lufs_sb_info *server, struct lufs_fattr *fattr)
399 struct server_slot *slot;
400 struct iovec siov, riov;
405 if((slot = lu_getslot(server)) == NULL){
406 init_root_dirent(server, fattr);
411 strcpy(slot->s_buf, server->root);
413 strcpy(slot->s_buf, "/");
415 TRACE("stating root %s\n", slot->s_buf);
417 siov.iov_base = slot->s_buf;
418 siov.iov_len = strlen(slot->s_buf) + 1;
419 riov.iov_base = fattr;
420 riov.iov_len = sizeof(struct lufs_fattr);
422 if((res = lu_execute(server, slot, PTYPE_STAT, &siov, 1, &riov, 1)) < 0){
423 init_root_dirent(server, fattr);
428 WARN("stat failed!\n");
429 init_root_dirent(server, fattr);
433 lu_fixattrs(server, fattr);
442 void lu_fixattrs(struct lufs_sb_info *info, struct lufs_fattr *fattr)
445 fattr->f_blksize = LU_BLOCKSIZE;
447 if(S_ISREG(fattr->f_mode) || S_ISDIR(fattr->f_mode))
448 fattr->f_blocks = (fattr->f_size + LU_BLOCKSIZE - 1) / LU_BLOCKSIZE;
452 if(info->config.own_fs){
455 fattr->f_mode = (fattr->f_mode & ~S_IRWXU) | ((fattr->f_mode & S_IRWXO)*(S_IRWXU/S_IRWXO));
458 fattr->f_mode = (fattr->f_mode & ~S_IRWXG) | ((fattr->f_mode & S_IRWXO)*(S_IRWXG/S_IRWXO));
460 fattr->f_uid = info->config.uid;
461 fattr->f_gid = info->config.gid;
466 fattr->f_uid = info->config.uid;
468 fattr->f_uid = LU_DEF_UID;
471 fattr->f_gid = info->config.gid;
473 fattr->f_gid = LU_DEF_GID;
476 if(fattr->f_mode & S_IFDIR)
477 fattr->f_mode |= info->config.dmode;
479 fattr->f_mode |= info->config.fmode;
482 void lu_xlate_symlink(char *link, char *target, char *buf)
485 char *c1, *c2 = link;
487 TRACE("translating %s->%s\n", link, target);
489 for(c1 = strchr(link, '/'); c1 && !strncmp(link, target, c1 - link); c2 = c1, c1 = strchr(c1 + 1, '/'));
491 TRACE("disjoint paths: %s, %s\n", c2, target + (c2 - link));
493 for(i = 0, c1 = c2; (c1 = strchr(c1 + 1, '/')); i++);
500 strcat(buf, target + (c2 - link) + 1);
502 TRACE("absolute link resolved to %s\n", buf);