2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/fsnotify.h>
17 #include <linux/jhash.h>
19 #include <linux/in6.h>
20 #include <linux/kthread.h>
21 #include <linux/pagemap.h>
22 #include <linux/poll.h>
23 #include <linux/swap.h>
24 #include <linux/syscalls.h>
25 #include <linux/vmalloc.h>
30 * Async machinery lives here.
31 * All commands being sent to server do _not_ require sync reply,
32 * instead, if it is really needed, like readdir or readpage, caller
33 * sleeps waiting for data, which will be placed into provided buffer
34 * and caller will be awakened.
36 * Every command response can come without some listener. For example
37 * readdir response will add new objects into cache without appropriate
38 * request from userspace. This is used in cache coherency.
40 * If object is not found for given data, it is discarded.
42 * All requests are received by dedicated kernel thread.
46 * Basic network sending/receiving functions.
47 * Blocked mode is used.
49 static int netfs_data_recv(struct netfs_state
*st
, void *buf
, u64 size
)
60 msg
.msg_iov
= (struct iovec
*)&iov
;
64 msg
.msg_control
= NULL
;
65 msg
.msg_controllen
= 0;
66 msg
.msg_flags
= MSG_DONTWAIT
;
68 err
= kernel_recvmsg(st
->socket
, &msg
, &iov
, 1, iov
.iov_len
,
71 printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__
, size
, err
);
79 static int pohmelfs_data_recv(struct netfs_state
*st
, void *data
, unsigned int size
)
81 unsigned int revents
= 0;
82 unsigned int err_mask
= POLLERR
| POLLHUP
| POLLRDHUP
;
83 unsigned int mask
= err_mask
| POLLIN
;
86 while (size
&& !err
) {
87 revents
= netfs_state_poll(st
);
89 if (!(revents
& mask
)) {
93 prepare_to_wait(&st
->thread_wait
, &wait
, TASK_INTERRUPTIBLE
);
94 if (kthread_should_stop())
97 revents
= netfs_state_poll(st
);
102 if (signal_pending(current
))
108 finish_wait(&st
->thread_wait
, &wait
);
112 netfs_state_lock(st
);
113 if (st
->socket
&& (st
->read_socket
== st
->socket
) && (revents
& POLLIN
)) {
114 err
= netfs_data_recv(st
, data
, size
);
123 if (revents
& err_mask
) {
124 printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
125 __func__
, revents
, st
->socket
, size
, err
);
128 netfs_state_unlock(st
);
131 if (netfs_state_trylock_send(st
)) {
132 netfs_state_exit(st
);
133 err
= netfs_state_init(st
);
136 netfs_state_unlock_send(st
);
142 if (kthread_should_stop())
146 printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
147 "should_stop: %d, size: %u, err: %d.\n",
148 __func__
, st
->socket
, st
->read_socket
,
149 revents
, revents
& err_mask
, kthread_should_stop(), size
, err
);
155 int pohmelfs_data_recv_and_check(struct netfs_state
*st
, void *data
, unsigned int size
)
157 struct netfs_cmd
*cmd
= &st
->cmd
;
160 err
= pohmelfs_data_recv(st
, data
, size
);
164 return pohmelfs_crypto_process_input_data(&st
->eng
, cmd
->iv
, data
, NULL
, size
);
171 struct netfs_poll_helper
{
173 struct netfs_state
*st
;
176 static int netfs_queue_wake(wait_queue_t
*wait
, unsigned mode
, int sync
, void *key
)
178 struct netfs_state
*st
= container_of(wait
, struct netfs_state
, wait
);
180 wake_up(&st
->thread_wait
);
184 static void netfs_queue_func(struct file
*file
, wait_queue_head_t
*whead
,
187 struct netfs_state
*st
= container_of(pt
, struct netfs_poll_helper
, pt
)->st
;
190 init_waitqueue_func_entry(&st
->wait
, netfs_queue_wake
);
191 add_wait_queue(whead
, &st
->wait
);
194 static void netfs_poll_exit(struct netfs_state
*st
)
197 remove_wait_queue(st
->whead
, &st
->wait
);
202 static int netfs_poll_init(struct netfs_state
*st
)
204 struct netfs_poll_helper ph
;
207 init_poll_funcptr(&ph
.pt
, &netfs_queue_func
);
209 st
->socket
->ops
->poll(NULL
, st
->socket
, &ph
.pt
);
214 * Get response for readpage command. We search inode and page in its mapping
215 * and copy data into. If it was async request, then we queue page into shared
216 * data and wakeup listener, who will copy it to userspace.
218 * There is a work in progress of allowing to call copy_to_user() directly from
219 * async receiving kernel thread.
221 static int pohmelfs_read_page_response(struct netfs_state
*st
)
223 struct pohmelfs_sb
*psb
= st
->psb
;
224 struct netfs_cmd
*cmd
= &st
->cmd
;
229 if (cmd
->size
> PAGE_CACHE_SIZE
) {
234 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
236 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
241 page
= find_get_page(inode
->i_mapping
, cmd
->start
>> PAGE_CACHE_SHIFT
);
242 if (!page
|| !PageLocked(page
)) {
243 printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
244 __func__
, page
, cmd
->id
, cmd
->start
, cmd
->start
>> PAGE_CACHE_SHIFT
);
247 unsigned int sz
= min(cmd
->size
, st
->size
);
249 err
= pohmelfs_data_recv(st
, st
->data
, sz
);
258 goto err_out_page_put
;
266 err
= pohmelfs_data_recv(st
, addr
, cmd
->size
);
270 goto err_out_page_unlock
;
273 dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
274 __func__
, page
, cmd
->start
, cmd
->size
, PageLocked(page
));
276 SetPageChecked(page
);
277 if ((psb
->hash_string
|| psb
->cipher_string
) && psb
->perform_crypto
&& cmd
->size
) {
278 err
= pohmelfs_crypto_process_input_page(&st
->eng
, page
, cmd
->size
, cmd
->iv
);
280 goto err_out_page_unlock
;
282 SetPageUptodate(page
);
284 page_cache_release(page
);
287 pohmelfs_put_inode(POHMELFS_I(inode
));
288 wake_up(&st
->psb
->wait
);
296 page_cache_release(page
);
298 pohmelfs_put_inode(POHMELFS_I(inode
));
300 wake_up(&st
->psb
->wait
);
304 static int pohmelfs_check_name(struct pohmelfs_inode
*parent
, struct qstr
*str
,
305 struct netfs_inode_info
*info
)
308 struct pohmelfs_name
*n
;
312 mutex_lock(&parent
->offset_lock
);
313 n
= pohmelfs_search_hash(parent
, str
->hash
);
316 mutex_unlock(&parent
->offset_lock
);
321 inode
= ilookup(parent
->vfs_inode
.i_sb
, ino
);
325 dprintk("%s: parent: %llu, inode: %llu.\n", __func__
, parent
->ino
, ino
);
327 pohmelfs_fill_inode(inode
, info
);
328 pohmelfs_put_inode(POHMELFS_I(inode
));
335 * Readdir response from server. If special field is set, we wakeup
336 * listener (readdir() call), which will copy data to userspace.
338 static int pohmelfs_readdir_response(struct netfs_state
*st
)
341 struct netfs_cmd
*cmd
= &st
->cmd
;
342 struct netfs_inode_info
*info
;
343 struct pohmelfs_inode
*parent
= NULL
, *npi
;
344 int err
= 0, last
= cmd
->ext
;
347 if (cmd
->size
> st
->size
)
350 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
352 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
355 parent
= POHMELFS_I(inode
);
357 if (!cmd
->size
&& cmd
->start
) {
365 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
369 info
= (struct netfs_inode_info
*)(st
->data
);
371 name
= (char *)(info
+ 1);
372 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
375 str
.hash
= jhash(str
.name
, str
.len
, 0);
377 netfs_convert_inode_info(info
);
380 err
= pohmelfs_check_name(parent
, &str
, info
);
388 info
->ino
= cmd
->start
;
390 info
->ino
= pohmelfs_new_ino(st
->psb
);
392 dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
393 __func__
, parent
->ino
, info
->ino
, str
.name
, str
.hash
, str
.len
,
396 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
403 struct dentry
*dentry
, *alias
, *pd
;
405 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
406 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
408 pd
= d_find_alias(&parent
->vfs_inode
);
410 str
.hash
= full_name_hash(str
.name
, str
.len
);
411 dentry
= d_alloc(pd
, &str
);
413 alias
= d_materialise_unique(dentry
, &npi
->vfs_inode
);
425 set_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
426 set_bit(NETFS_INODE_REMOTE_SYNCED
, &parent
->state
);
427 wake_up(&st
->psb
->wait
);
429 pohmelfs_put_inode(parent
);
434 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
435 printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__
, parent
->ino
, cmd
->start
, cmd
->id
);
436 pohmelfs_put_inode(parent
);
437 wake_up(&st
->psb
->wait
);
442 * Lookup command response.
443 * It searches for inode to be looked at (if it exists) and substitutes
444 * its inode information (size, permission, mode and so on), if inode does
445 * not exist, new one will be created and inserted into caches.
447 static int pohmelfs_lookup_response(struct netfs_state
*st
)
449 struct inode
*inode
= NULL
;
450 struct netfs_cmd
*cmd
= &st
->cmd
;
451 struct netfs_inode_info
*info
;
452 struct pohmelfs_inode
*parent
= NULL
, *npi
;
456 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
458 printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
459 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
463 parent
= POHMELFS_I(inode
);
470 if (cmd
->size
< sizeof(struct netfs_inode_info
)) {
471 printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
472 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
477 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
481 info
= (struct netfs_inode_info
*)(st
->data
);
482 name
= (char *)(info
+ 1);
484 netfs_convert_inode_info(info
);
486 info
->ino
= cmd
->start
;
488 info
->ino
= pohmelfs_new_ino(st
->psb
);
490 dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
491 __func__
, parent
->ino
, info
->ino
, name
, cmd
->start
);
494 npi
= pohmelfs_new_inode(st
->psb
, parent
, NULL
, info
, 0);
499 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
500 str
.hash
= jhash(name
, str
.len
, 0);
502 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
510 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
511 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
514 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
515 pohmelfs_put_inode(parent
);
517 wake_up(&st
->psb
->wait
);
522 pohmelfs_put_inode(parent
);
524 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
525 wake_up(&st
->psb
->wait
);
526 printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
527 __func__
, inode
, cmd
->id
, cmd
->start
, cmd
->size
, err
);
532 * Create response, just marks local inode as 'created', so that writeback
533 * for any of its children (or own) would not try to sync it again.
535 static int pohmelfs_create_response(struct netfs_state
*st
)
538 struct netfs_cmd
*cmd
= &st
->cmd
;
539 struct pohmelfs_inode
*pi
;
541 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
543 printk("%s: failed to find inode: id: %llu, start: %llu.\n",
544 __func__
, cmd
->id
, cmd
->start
);
548 pi
= POHMELFS_I(inode
);
551 * To lock or not to lock?
552 * We actually do not care if it races...
555 make_bad_inode(inode
);
556 set_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
558 pohmelfs_put_inode(pi
);
560 wake_up(&st
->psb
->wait
);
564 wake_up(&st
->psb
->wait
);
569 * Object remove response. Just says that remove request has been received.
570 * Used in cache coherency protocol.
572 static int pohmelfs_remove_response(struct netfs_state
*st
)
574 struct netfs_cmd
*cmd
= &st
->cmd
;
577 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
581 dprintk("%s: parent: %llu, path: '%s'.\n", __func__
, cmd
->id
, (char *)st
->data
);
587 * Transaction reply processing.
589 * Find transaction based on its generation number, bump its reference counter,
590 * so that none could free it under us, drop from the trees and lists and
591 * drop reference counter. When it hits zero (when all destinations replied
592 * and all timeout handled by async scanning code), completion will be called
593 * and transaction will be freed.
595 static int pohmelfs_transaction_response(struct netfs_state
*st
)
597 struct netfs_trans_dst
*dst
;
598 struct netfs_trans
*t
= NULL
;
599 struct netfs_cmd
*cmd
= &st
->cmd
;
600 short err
= (signed)cmd
->ext
;
602 mutex_lock(&st
->trans_lock
);
603 dst
= netfs_trans_search(st
, cmd
->start
);
605 netfs_trans_remove_nolock(dst
, st
);
608 mutex_unlock(&st
->trans_lock
);
611 printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
612 __func__
, cmd
->start
, cmd
->id
, cmd
->size
, cmd
->ext
);
618 netfs_trans_drop_dst_nostate(dst
);
621 wake_up(&st
->psb
->wait
);
626 * Inode metadata cache coherency message.
628 static int pohmelfs_page_cache_response(struct netfs_state
*st
)
630 struct netfs_cmd
*cmd
= &st
->cmd
;
633 dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__
, st
, cmd
->id
, cmd
->start
, cmd
->size
);
635 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
637 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
641 set_bit(NETFS_INODE_NEED_FLUSH
, &POHMELFS_I(inode
)->state
);
642 pohmelfs_put_inode(POHMELFS_I(inode
));
648 * Root capabilities response: export statistics
649 * like used and available size, number of files and dirs,
652 static int pohmelfs_root_cap_response(struct netfs_state
*st
)
654 struct netfs_cmd
*cmd
= &st
->cmd
;
655 struct netfs_root_capabilities
*cap
;
656 struct pohmelfs_sb
*psb
= st
->psb
;
658 if (cmd
->size
!= sizeof(struct netfs_root_capabilities
)) {
666 netfs_convert_root_capabilities(cap
);
668 if (psb
->total_size
< cap
->used
+ cap
->avail
)
669 psb
->total_size
= cap
->used
+ cap
->avail
;
671 psb
->avail_size
= cap
->avail
;
672 psb
->state_flags
= cap
->flags
;
674 if (psb
->state_flags
& POHMELFS_FLAGS_RO
) {
675 psb
->sb
->s_flags
|= MS_RDONLY
;
676 printk(KERN_INFO
"Mounting POHMELFS (%d) read-only.\n", psb
->idx
);
679 if (psb
->state_flags
& POHMELFS_FLAGS_XATTR
)
680 printk(KERN_INFO
"Mounting POHMELFS (%d) "
681 "with extended attributes support.\n", psb
->idx
);
683 if (atomic_long_read(&psb
->total_inodes
) <= 1)
684 atomic_long_set(&psb
->total_inodes
, cap
->nr_files
);
686 dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
687 __func__
, psb
->total_size
, psb
->avail_size
, psb
->state_flags
, cap
->nr_files
);
695 * Crypto capabilities of the server, where it says that
696 * it supports or does not requested hash/cipher algorithms.
698 static int pohmelfs_crypto_cap_response(struct netfs_state
*st
)
700 struct netfs_cmd
*cmd
= &st
->cmd
;
701 struct netfs_crypto_capabilities
*cap
;
702 struct pohmelfs_sb
*psb
= st
->psb
;
705 if (cmd
->size
!= sizeof(struct netfs_crypto_capabilities
)) {
713 dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
715 psb
->cipher_string
, (cap
->cipher_strlen
)?"SUPPORTED":"NOT SUPPORTED",
716 psb
->hash_string
, (cap
->hash_strlen
)?"SUPPORTED":"NOT SUPPORTED");
718 if (!cap
->hash_strlen
) {
719 if (psb
->hash_strlen
&& psb
->crypto_fail_unsupported
)
721 psb
->hash_strlen
= 0;
722 kfree(psb
->hash_string
);
723 psb
->hash_string
= NULL
;
726 if (!cap
->cipher_strlen
) {
727 if (psb
->cipher_strlen
&& psb
->crypto_fail_unsupported
)
729 psb
->cipher_strlen
= 0;
730 kfree(psb
->cipher_string
);
731 psb
->cipher_string
= NULL
;
738 * Capabilities handshake response.
740 static int pohmelfs_capabilities_response(struct netfs_state
*st
)
742 struct netfs_cmd
*cmd
= &st
->cmd
;
745 err
= pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
750 case POHMELFS_CRYPTO_CAPABILITIES
:
751 return pohmelfs_crypto_cap_response(st
);
752 case POHMELFS_ROOT_CAPABILITIES
:
753 return pohmelfs_root_cap_response(st
);
761 * Receiving extended attribute.
762 * Does not work properly if received size is more than requested one,
763 * it should not happen with current request/reply model though.
765 static int pohmelfs_getxattr_response(struct netfs_state
*st
)
767 struct pohmelfs_sb
*psb
= st
->psb
;
768 struct netfs_cmd
*cmd
= &st
->cmd
;
769 struct pohmelfs_mcache
*m
;
770 short error
= (signed short)cmd
->ext
, err
;
771 unsigned int sz
, total_size
;
773 m
= pohmelfs_mcache_search(psb
, cmd
->id
);
775 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
776 __func__
, cmd
->id
, (m
)?m
->gen
:0, error
);
779 printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__
, cmd
->id
);
784 sz
= min_t(unsigned int, cmd
->size
, m
->size
);
785 err
= pohmelfs_data_recv_and_check(st
, m
->data
, sz
);
792 total_size
= cmd
->size
- sz
;
795 sz
= min(total_size
, st
->size
);
797 err
= pohmelfs_data_recv_and_check(st
, st
->data
, sz
);
809 complete(&m
->complete
);
810 pohmelfs_mcache_put(psb
, m
);
815 int pohmelfs_data_lock_response(struct netfs_state
*st
)
817 struct pohmelfs_sb
*psb
= st
->psb
;
818 struct netfs_cmd
*cmd
= &st
->cmd
;
819 struct pohmelfs_mcache
*m
;
820 short err
= (signed short)cmd
->ext
;
823 m
= pohmelfs_mcache_search(psb
, id
);
825 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
826 __func__
, cmd
->id
, (m
)?m
->gen
:0, err
);
829 pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
830 printk("%s: failed to find data lock response: id: %llu.\n", __func__
, cmd
->id
);
835 err
= pohmelfs_data_recv_and_check(st
, &m
->info
, cmd
->size
);
838 complete(&m
->complete
);
839 pohmelfs_mcache_put(psb
, m
);
844 static void __inline__
netfs_state_reset(struct netfs_state
*st
)
846 netfs_state_lock_send(st
);
847 netfs_state_exit(st
);
848 netfs_state_init(st
);
849 netfs_state_unlock_send(st
);
853 * Main receiving function, called from dedicated kernel thread.
855 static int pohmelfs_recv(void *data
)
858 struct netfs_state
*st
= data
;
859 struct netfs_cmd
*cmd
= &st
->cmd
;
861 while (!kthread_should_stop()) {
863 * If socket will be reset after this statement, then
864 * pohmelfs_data_recv() will just fail and loop will
865 * start again, so it can be done without any locks.
867 * st->read_socket is needed to prevents state machine
868 * breaking between this data reading and subsequent one
869 * in protocol specific functions during connection reset.
870 * In case of reset we have to read next command and do
871 * not expect data for old command to magically appear in
874 st
->read_socket
= st
->socket
;
875 err
= pohmelfs_data_recv(st
, cmd
, sizeof(struct netfs_cmd
));
881 netfs_convert_cmd(cmd
);
883 dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
884 "ext: %u, csize: %u, cpad: %u.\n",
885 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
,
886 cmd
->size
, cmd
->ext
, cmd
->csize
, cmd
->cpad
);
889 struct pohmelfs_crypto_engine
*e
= &st
->eng
;
891 if (unlikely(cmd
->csize
> e
->size
/2)) {
892 netfs_state_reset(st
);
896 if (e
->hash
&& unlikely(cmd
->csize
!= st
->psb
->crypto_attached_size
)) {
897 dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
898 "csize: %u != digest size %u.\n",
899 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
,
900 cmd
->csize
, st
->psb
->crypto_attached_size
);
901 netfs_state_reset(st
);
905 err
= pohmelfs_data_recv(st
, e
->data
, cmd
->csize
);
907 netfs_state_reset(st
);
911 #ifdef CONFIG_POHMELFS_DEBUG
914 unsigned char *hash
= e
->data
;
916 dprintk("%s: received hash: ", __func__
);
917 for (i
=0; i
<cmd
->csize
; ++i
)
918 printk("%02x ", hash
[i
]);
923 cmd
->size
-= cmd
->csize
;
927 * This should catch protocol breakage and random garbage instead of commands.
929 if (unlikely((cmd
->size
> st
->size
) && (cmd
->cmd
!= NETFS_XATTR_GET
))) {
930 netfs_state_reset(st
);
935 case NETFS_READ_PAGE
:
936 err
= pohmelfs_read_page_response(st
);
939 err
= pohmelfs_readdir_response(st
);
942 err
= pohmelfs_lookup_response(st
);
945 err
= pohmelfs_create_response(st
);
948 err
= pohmelfs_remove_response(st
);
951 err
= pohmelfs_transaction_response(st
);
953 case NETFS_PAGE_CACHE
:
954 err
= pohmelfs_page_cache_response(st
);
956 case NETFS_CAPABILITIES
:
957 err
= pohmelfs_capabilities_response(st
);
960 err
= pohmelfs_data_lock_response(st
);
962 case NETFS_XATTR_GET
:
963 err
= pohmelfs_getxattr_response(st
);
966 printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
967 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
, cmd
->ext
);
968 netfs_state_reset(st
);
973 while (!kthread_should_stop())
974 schedule_timeout_uninterruptible(msecs_to_jiffies(10));
979 int netfs_state_init(struct netfs_state
*st
)
982 struct pohmelfs_ctl
*ctl
= &st
->ctl
;
984 err
= sock_create(ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, &st
->socket
);
986 printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
987 __func__
, ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, err
);
991 st
->socket
->sk
->sk_allocation
= GFP_NOIO
;
992 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
994 err
= kernel_connect(st
->socket
, (struct sockaddr
*)&ctl
->addr
, ctl
->addrlen
, 0);
996 printk("%s: failed to connect to server: idx: %u, err: %d.\n",
997 __func__
, st
->psb
->idx
, err
);
998 goto err_out_release
;
1000 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
1002 err
= netfs_poll_init(st
);
1004 goto err_out_release
;
1006 if (st
->socket
->ops
->family
== AF_INET
) {
1007 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ctl
->addr
;
1008 printk(KERN_INFO
"%s: (re)connected to peer %pi4:%d.\n", __func__
,
1009 &sin
->sin_addr
.s_addr
, ntohs(sin
->sin_port
));
1010 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1011 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&ctl
->addr
;
1012 printk(KERN_INFO
"%s: (re)connected to peer %pi6:%d", __func__
,
1013 &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1019 sock_release(st
->socket
);
1025 void netfs_state_exit(struct netfs_state
*st
)
1028 netfs_poll_exit(st
);
1029 st
->socket
->ops
->shutdown(st
->socket
, 2);
1031 if (st
->socket
->ops
->family
== AF_INET
) {
1032 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&st
->ctl
.addr
;
1033 printk(KERN_INFO
"%s: disconnected from peer %pi4:%d.\n", __func__
,
1034 &sin
->sin_addr
.s_addr
, ntohs(sin
->sin_port
));
1035 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1036 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&st
->ctl
.addr
;
1037 printk(KERN_INFO
"%s: disconnected from peer %pi6:%d", __func__
,
1038 &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1041 sock_release(st
->socket
);
1043 st
->read_socket
= NULL
;
1048 int pohmelfs_state_init_one(struct pohmelfs_sb
*psb
, struct pohmelfs_config
*conf
)
1050 struct netfs_state
*st
= &conf
->state
;
1053 mutex_init(&st
->__state_lock
);
1054 mutex_init(&st
->__state_send_lock
);
1055 init_waitqueue_head(&st
->thread_wait
);
1058 st
->trans_root
= RB_ROOT
;
1059 mutex_init(&st
->trans_lock
);
1061 st
->size
= psb
->trans_data_size
;
1062 st
->data
= kmalloc(st
->size
, GFP_KERNEL
);
1066 if (psb
->perform_crypto
) {
1067 err
= pohmelfs_crypto_engine_init(&st
->eng
, psb
);
1069 goto err_out_free_data
;
1072 err
= netfs_state_init(st
);
1074 goto err_out_free_engine
;
1076 st
->thread
= kthread_run(pohmelfs_recv
, st
, "pohmelfs/%u", psb
->idx
);
1077 if (IS_ERR(st
->thread
)) {
1078 err
= PTR_ERR(st
->thread
);
1079 goto err_out_netfs_exit
;
1082 if (!psb
->active_state
)
1083 psb
->active_state
= conf
;
1085 dprintk("%s: conf: %p, st: %p, socket: %p.\n",
1086 __func__
, conf
, st
, st
->socket
);
1090 netfs_state_exit(st
);
1091 err_out_free_engine
:
1092 pohmelfs_crypto_engine_exit(&st
->eng
);
1100 void pohmelfs_state_flush_transactions(struct netfs_state
*st
)
1102 struct rb_node
*rb_node
;
1103 struct netfs_trans_dst
*dst
;
1105 mutex_lock(&st
->trans_lock
);
1106 for (rb_node
= rb_first(&st
->trans_root
); rb_node
; ) {
1107 dst
= rb_entry(rb_node
, struct netfs_trans_dst
, state_entry
);
1108 rb_node
= rb_next(rb_node
);
1110 dst
->trans
->result
= -EINVAL
;
1111 netfs_trans_remove_nolock(dst
, st
);
1112 netfs_trans_drop_dst_nostate(dst
);
1114 mutex_unlock(&st
->trans_lock
);
1117 static void pohmelfs_state_exit_one(struct pohmelfs_config
*c
)
1119 struct netfs_state
*st
= &c
->state
;
1121 dprintk("%s: exiting, st: %p.\n", __func__
, st
);
1123 kthread_stop(st
->thread
);
1127 netfs_state_lock_send(st
);
1128 netfs_state_exit(st
);
1129 netfs_state_unlock_send(st
);
1131 pohmelfs_state_flush_transactions(st
);
1133 pohmelfs_crypto_engine_exit(&st
->eng
);
1140 * Initialize network stack. It searches for given ID in global
1141 * configuration table, this contains information of the remote server
1142 * (address (any supported by socket interface) and port, protocol and so on).
1144 int pohmelfs_state_init(struct pohmelfs_sb
*psb
)
1148 err
= pohmelfs_copy_config(psb
);
1150 pohmelfs_state_exit(psb
);
1157 void pohmelfs_state_exit(struct pohmelfs_sb
*psb
)
1159 struct pohmelfs_config
*c
, *tmp
;
1161 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1162 list_del(&c
->config_entry
);
1163 pohmelfs_state_exit_one(c
);
1167 void pohmelfs_switch_active(struct pohmelfs_sb
*psb
)
1169 struct pohmelfs_config
*c
= psb
->active_state
;
1171 if (!list_empty(&psb
->state_list
)) {
1172 if (c
->config_entry
.next
!= &psb
->state_list
) {
1173 psb
->active_state
= list_entry(c
->config_entry
.next
,
1174 struct pohmelfs_config
, config_entry
);
1176 psb
->active_state
= list_entry(psb
->state_list
.next
,
1177 struct pohmelfs_config
, config_entry
);
1180 dprintk("%s: empty: %d, active %p -> %p.\n",
1181 __func__
, list_empty(&psb
->state_list
), c
,
1184 psb
->active_state
= NULL
;
1187 void pohmelfs_check_states(struct pohmelfs_sb
*psb
)
1189 struct pohmelfs_config
*c
, *tmp
;
1190 LIST_HEAD(delete_list
);
1192 mutex_lock(&psb
->state_lock
);
1193 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1194 if (pohmelfs_config_check(c
, psb
->idx
)) {
1196 if (psb
->active_state
== c
)
1197 pohmelfs_switch_active(psb
);
1198 list_move(&c
->config_entry
, &delete_list
);
1201 pohmelfs_copy_config(psb
);
1202 mutex_unlock(&psb
->state_lock
);
1204 list_for_each_entry_safe(c
, tmp
, &delete_list
, config_entry
) {
1205 list_del(&c
->config_entry
);
1206 pohmelfs_state_exit_one(c
);