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>
29 static int pohmelfs_ftrans_size
= 10240;
30 static u32
*pohmelfs_ftrans
;
32 int pohmelfs_ftrans_init(void)
34 pohmelfs_ftrans
= vmalloc(pohmelfs_ftrans_size
* 4);
41 void pohmelfs_ftrans_exit(void)
43 vfree(pohmelfs_ftrans
);
46 void pohmelfs_ftrans_clean(u64 id
)
48 if (pohmelfs_ftrans
) {
49 u32 i
= id
& 0xffffffff;
50 int idx
= i
% pohmelfs_ftrans_size
;
52 pohmelfs_ftrans
[idx
] = 0;
56 void pohmelfs_ftrans_update(u64 id
)
58 if (pohmelfs_ftrans
) {
59 u32 i
= id
& 0xffffffff;
60 int idx
= i
% pohmelfs_ftrans_size
;
62 pohmelfs_ftrans
[idx
] = i
;
66 int pohmelfs_ftrans_check(u64 id
)
68 if (pohmelfs_ftrans
) {
69 u32 i
= id
& 0xffffffff;
70 int idx
= i
% pohmelfs_ftrans_size
;
72 return (pohmelfs_ftrans
[idx
] == i
);
79 * Async machinery lives here.
80 * All commands being sent to server do _not_ require sync reply,
81 * instead, if it is really needed, like readdir or readpage, caller
82 * sleeps waiting for data, which will be placed into provided buffer
83 * and caller will be awakened.
85 * Every command response can come without some listener. For example
86 * readdir response will add new objects into cache without appropriate
87 * request from userspace. This is used in cache coherency.
89 * If object is not found for given data, it is discarded.
91 * All requests are received by dedicated kernel thread.
95 * Basic network sending/receiving functions.
96 * Blocked mode is used.
98 static int netfs_data_recv(struct netfs_state
*st
, void *buf
, u64 size
)
109 msg
.msg_iov
= (struct iovec
*)&iov
;
113 msg
.msg_control
= NULL
;
114 msg
.msg_controllen
= 0;
115 msg
.msg_flags
= MSG_DONTWAIT
;
117 err
= kernel_recvmsg(st
->socket
, &msg
, &iov
, 1, iov
.iov_len
,
120 printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__
, size
, err
);
128 static int pohmelfs_data_recv(struct netfs_state
*st
, void *data
, unsigned int size
)
130 unsigned int revents
= 0;
131 unsigned int err_mask
= POLLERR
| POLLHUP
| POLLRDHUP
;
132 unsigned int mask
= err_mask
| POLLIN
;
135 while (size
&& !err
) {
136 revents
= netfs_state_poll(st
);
138 if (!(revents
& mask
)) {
142 prepare_to_wait(&st
->thread_wait
, &wait
, TASK_INTERRUPTIBLE
);
143 if (kthread_should_stop())
146 revents
= netfs_state_poll(st
);
151 if (signal_pending(current
))
157 finish_wait(&st
->thread_wait
, &wait
);
161 netfs_state_lock(st
);
162 if (st
->socket
&& (st
->read_socket
== st
->socket
) && (revents
& POLLIN
)) {
163 err
= netfs_data_recv(st
, data
, size
);
172 if (revents
& err_mask
) {
173 printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
174 __func__
, revents
, st
->socket
, size
, err
);
177 netfs_state_unlock(st
);
180 if (netfs_state_trylock_send(st
)) {
181 netfs_state_exit(st
);
182 err
= netfs_state_init(st
);
185 netfs_state_unlock_send(st
);
191 if (kthread_should_stop())
195 printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
196 "should_stop: %d, size: %u, err: %d.\n",
197 __func__
, st
->socket
, st
->read_socket
,
198 revents
, revents
& err_mask
, kthread_should_stop(), size
, err
);
204 int pohmelfs_data_recv_and_check(struct netfs_state
*st
, void *data
, unsigned int size
)
206 struct netfs_cmd
*cmd
= &st
->cmd
;
209 err
= pohmelfs_data_recv(st
, data
, size
);
213 return pohmelfs_crypto_process_input_data(&st
->eng
, cmd
->iv
, data
, NULL
, size
);
220 struct netfs_poll_helper
223 struct netfs_state
*st
;
226 static int netfs_queue_wake(wait_queue_t
*wait
, unsigned mode
, int sync
, void *key
)
228 struct netfs_state
*st
= container_of(wait
, struct netfs_state
, wait
);
230 wake_up(&st
->thread_wait
);
234 static void netfs_queue_func(struct file
*file
, wait_queue_head_t
*whead
,
237 struct netfs_state
*st
= container_of(pt
, struct netfs_poll_helper
, pt
)->st
;
240 init_waitqueue_func_entry(&st
->wait
, netfs_queue_wake
);
241 add_wait_queue(whead
, &st
->wait
);
244 static void netfs_poll_exit(struct netfs_state
*st
)
247 remove_wait_queue(st
->whead
, &st
->wait
);
252 static int netfs_poll_init(struct netfs_state
*st
)
254 struct netfs_poll_helper ph
;
257 init_poll_funcptr(&ph
.pt
, &netfs_queue_func
);
259 st
->socket
->ops
->poll(NULL
, st
->socket
, &ph
.pt
);
264 * Get response for readpage command. We search inode and page in its mapping
265 * and copy data into. If it was async request, then we queue page into shared
266 * data and wakeup listener, who will copy it to userspace.
268 * There is a work in progress of allowing to call copy_to_user() directly from
269 * async receiving kernel thread.
271 static int pohmelfs_read_page_response(struct netfs_state
*st
)
273 struct pohmelfs_sb
*psb
= st
->psb
;
274 struct netfs_cmd
*cmd
= &st
->cmd
;
279 if (cmd
->size
> PAGE_CACHE_SIZE
) {
284 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
286 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
291 page
= find_get_page(inode
->i_mapping
, cmd
->start
>> PAGE_CACHE_SHIFT
);
292 if (!page
|| !PageLocked(page
)) {
293 printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
294 __func__
, page
, cmd
->id
, cmd
->start
, cmd
->start
>> PAGE_CACHE_SHIFT
);
297 unsigned int sz
= min(cmd
->size
, st
->size
);
299 err
= pohmelfs_data_recv(st
, st
->data
, sz
);
308 goto err_out_page_put
;
316 err
= pohmelfs_data_recv(st
, addr
, cmd
->size
);
320 goto err_out_page_unlock
;
323 dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
324 __func__
, page
, cmd
->start
, cmd
->size
, PageLocked(page
));
326 SetPageChecked(page
);
327 if ((psb
->hash_string
|| psb
->cipher_string
) && psb
->perform_crypto
&& cmd
->size
) {
328 err
= pohmelfs_crypto_process_input_page(&st
->eng
, page
, cmd
->size
, cmd
->iv
);
330 goto err_out_page_unlock
;
332 SetPageUptodate(page
);
334 page_cache_release(page
);
337 pohmelfs_put_inode(POHMELFS_I(inode
));
338 wake_up(&st
->psb
->wait
);
346 page_cache_release(page
);
348 pohmelfs_put_inode(POHMELFS_I(inode
));
350 wake_up(&st
->psb
->wait
);
354 static int pohmelfs_check_name(struct pohmelfs_inode
*parent
, struct qstr
*str
,
355 struct netfs_inode_info
*info
)
358 struct pohmelfs_name
*n
;
362 mutex_lock(&parent
->offset_lock
);
363 n
= pohmelfs_search_hash(parent
, str
->hash
);
366 mutex_unlock(&parent
->offset_lock
);
371 inode
= ilookup(parent
->vfs_inode
.i_sb
, ino
);
375 dprintk("%s: parent: %llu, inode: %llu.\n", __func__
, parent
->ino
, ino
);
377 pohmelfs_fill_inode(inode
, info
);
378 pohmelfs_put_inode(POHMELFS_I(inode
));
385 * Readdir response from server. If special field is set, we wakeup
386 * listener (readdir() call), which will copy data to userspace.
388 static int pohmelfs_readdir_response(struct netfs_state
*st
)
391 struct netfs_cmd
*cmd
= &st
->cmd
;
392 struct netfs_inode_info
*info
;
393 struct pohmelfs_inode
*parent
= NULL
, *npi
;
394 int err
= 0, last
= cmd
->ext
;
397 if (cmd
->size
> st
->size
)
400 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
402 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
405 parent
= POHMELFS_I(inode
);
407 if (!cmd
->size
&& cmd
->start
) {
415 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
419 info
= (struct netfs_inode_info
*)(st
->data
);
421 name
= (char *)(info
+ 1);
422 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
425 str
.hash
= jhash(str
.name
, str
.len
, 0);
427 netfs_convert_inode_info(info
);
430 err
= pohmelfs_check_name(parent
, &str
, info
);
438 info
->ino
= cmd
->start
;
440 info
->ino
= pohmelfs_new_ino(st
->psb
);
442 dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
443 __func__
, parent
->ino
, info
->ino
, str
.name
, str
.hash
, str
.len
,
446 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
453 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
454 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
459 set_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
460 set_bit(NETFS_INODE_REMOTE_SYNCED
, &parent
->state
);
461 wake_up(&st
->psb
->wait
);
463 pohmelfs_put_inode(parent
);
468 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
469 printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__
, parent
->ino
, cmd
->start
, cmd
->id
);
470 pohmelfs_put_inode(parent
);
471 wake_up(&st
->psb
->wait
);
476 * Lookup command response.
477 * It searches for inode to be looked at (if it exists) and substitutes
478 * its inode information (size, permission, mode and so on), if inode does
479 * not exist, new one will be created and inserted into caches.
481 static int pohmelfs_lookup_response(struct netfs_state
*st
)
483 struct inode
*inode
= NULL
;
484 struct netfs_cmd
*cmd
= &st
->cmd
;
485 struct netfs_inode_info
*info
;
486 struct pohmelfs_inode
*parent
= NULL
, *npi
;
490 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
492 printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
493 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
497 parent
= POHMELFS_I(inode
);
504 if (cmd
->size
< sizeof(struct netfs_inode_info
)) {
505 printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
506 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
511 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
515 info
= (struct netfs_inode_info
*)(st
->data
);
516 name
= (char *)(info
+ 1);
518 netfs_convert_inode_info(info
);
520 info
->ino
= cmd
->start
;
522 info
->ino
= pohmelfs_new_ino(st
->psb
);
524 dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
525 __func__
, parent
->ino
, info
->ino
, name
, cmd
->start
);
528 npi
= pohmelfs_new_inode(st
->psb
, parent
, NULL
, info
, 0);
533 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
534 str
.hash
= jhash(name
, str
.len
, 0);
536 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
544 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
545 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
548 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
549 pohmelfs_put_inode(parent
);
551 wake_up(&st
->psb
->wait
);
556 pohmelfs_put_inode(parent
);
558 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
559 wake_up(&st
->psb
->wait
);
560 printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
561 __func__
, inode
, cmd
->id
, cmd
->start
, cmd
->size
, err
);
566 * Create response, just marks local inode as 'created', so that writeback
567 * for any of its children (or own) would not try to sync it again.
569 static int pohmelfs_create_response(struct netfs_state
*st
)
572 struct netfs_cmd
*cmd
= &st
->cmd
;
573 struct pohmelfs_inode
*pi
;
575 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
577 printk("%s: failed to find inode: id: %llu, start: %llu.\n",
578 __func__
, cmd
->id
, cmd
->start
);
582 pi
= POHMELFS_I(inode
);
585 * To lock or not to lock?
586 * We actually do not care if it races...
589 make_bad_inode(inode
);
590 set_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
592 pohmelfs_put_inode(pi
);
594 wake_up(&st
->psb
->wait
);
598 wake_up(&st
->psb
->wait
);
603 * Object remove response. Just says that remove request has been received.
604 * Used in cache coherency protocol.
606 static int pohmelfs_remove_response(struct netfs_state
*st
)
608 struct netfs_cmd
*cmd
= &st
->cmd
;
611 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
615 dprintk("%s: parent: %llu, path: '%s'.\n", __func__
, cmd
->id
, (char *)st
->data
);
621 * Transaction reply processing.
623 * Find transaction based on its generation number, bump its reference counter,
624 * so that none could free it under us, drop from the trees and lists and
625 * drop reference counter. When it hits zero (when all destinations replied
626 * and all timeout handled by async scanning code), completion will be called
627 * and transaction will be freed.
629 static int pohmelfs_transaction_response(struct netfs_state
*st
)
631 struct netfs_trans_dst
*dst
;
632 struct netfs_trans
*t
= NULL
;
633 struct netfs_cmd
*cmd
= &st
->cmd
;
634 short err
= (signed)cmd
->ext
;
636 mutex_lock(&st
->trans_lock
);
637 dst
= netfs_trans_search(st
, cmd
->start
);
639 netfs_trans_remove_nolock(dst
, st
);
642 pohmelfs_ftrans_update(cmd
->start
);
644 mutex_unlock(&st
->trans_lock
);
647 int check
= pohmelfs_ftrans_check(cmd
->start
);
648 printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u, double: %d.\n",
649 __func__
, cmd
->start
, cmd
->id
, cmd
->size
, cmd
->ext
, check
);
655 netfs_trans_drop_dst_nostate(dst
);
658 wake_up(&st
->psb
->wait
);
663 * Inode metadata cache coherency message.
665 static int pohmelfs_page_cache_response(struct netfs_state
*st
)
667 struct netfs_cmd
*cmd
= &st
->cmd
;
670 dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__
, st
, cmd
->id
, cmd
->start
, cmd
->size
);
672 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
674 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
678 set_bit(NETFS_INODE_NEED_FLUSH
, &POHMELFS_I(inode
)->state
);
679 pohmelfs_put_inode(POHMELFS_I(inode
));
685 * Root capabilities response: export statistics
686 * like used and available size, number of files and dirs,
689 static int pohmelfs_root_cap_response(struct netfs_state
*st
)
691 struct netfs_cmd
*cmd
= &st
->cmd
;
692 struct netfs_root_capabilities
*cap
;
693 struct pohmelfs_sb
*psb
= st
->psb
;
695 if (cmd
->size
!= sizeof(struct netfs_root_capabilities
)) {
703 netfs_convert_root_capabilities(cap
);
705 if (psb
->total_size
< cap
->used
+ cap
->avail
)
706 psb
->total_size
= cap
->used
+ cap
->avail
;
708 psb
->avail_size
= cap
->avail
;
709 psb
->state_flags
= cap
->flags
;
711 if (psb
->state_flags
& POHMELFS_FLAGS_RO
) {
712 psb
->sb
->s_flags
|= MS_RDONLY
;
713 printk(KERN_INFO
"Mounting POHMELFS (%d) read-only.\n", psb
->idx
);
716 if (psb
->state_flags
& POHMELFS_FLAGS_XATTR
)
717 printk(KERN_INFO
"Mounting POHMELFS (%d) "
718 "with extended attributes support.\n", psb
->idx
);
720 if (atomic_read(&psb
->total_inodes
) <= 1)
721 atomic_long_set(&psb
->total_inodes
, cap
->nr_files
);
723 dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
724 __func__
, psb
->total_size
, psb
->avail_size
, psb
->state_flags
, cap
->nr_files
);
732 * Crypto capabilities of the server, where it says that
733 * it supports or does not requested hash/cipher algorithms.
735 static int pohmelfs_crypto_cap_response(struct netfs_state
*st
)
737 struct netfs_cmd
*cmd
= &st
->cmd
;
738 struct netfs_crypto_capabilities
*cap
;
739 struct pohmelfs_sb
*psb
= st
->psb
;
742 if (cmd
->size
!= sizeof(struct netfs_crypto_capabilities
)) {
750 dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
752 psb
->cipher_string
, (cap
->cipher_strlen
)?"SUPPORTED":"NOT SUPPORTED",
753 psb
->hash_string
, (cap
->hash_strlen
)?"SUPPORTED":"NOT SUPPORTED");
755 if (!cap
->hash_strlen
) {
756 if (psb
->hash_strlen
&& psb
->crypto_fail_unsupported
)
758 psb
->hash_strlen
= 0;
759 kfree(psb
->hash_string
);
760 psb
->hash_string
= NULL
;
763 if (!cap
->cipher_strlen
) {
764 if (psb
->cipher_strlen
&& psb
->crypto_fail_unsupported
)
766 psb
->cipher_strlen
= 0;
767 kfree(psb
->cipher_string
);
768 psb
->cipher_string
= NULL
;
775 * Capabilities handshake response.
777 static int pohmelfs_capabilities_response(struct netfs_state
*st
)
779 struct netfs_cmd
*cmd
= &st
->cmd
;
782 err
= pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
787 case POHMELFS_CRYPTO_CAPABILITIES
:
788 return pohmelfs_crypto_cap_response(st
);
789 case POHMELFS_ROOT_CAPABILITIES
:
790 return pohmelfs_root_cap_response(st
);
798 * Receiving extended attribute.
799 * Does not work properly if received size is more than requested one,
800 * it should not happen with current request/reply model though.
802 static int pohmelfs_getxattr_response(struct netfs_state
*st
)
804 struct pohmelfs_sb
*psb
= st
->psb
;
805 struct netfs_cmd
*cmd
= &st
->cmd
;
806 struct pohmelfs_mcache
*m
;
807 short error
= (signed short)cmd
->ext
, err
;
808 unsigned int sz
, total_size
;
810 m
= pohmelfs_mcache_search(psb
, cmd
->id
);
812 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
813 __func__
, cmd
->id
, (m
)?m
->gen
:0, error
);
816 printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__
, cmd
->id
);
821 sz
= min_t(unsigned int, cmd
->size
, m
->size
);
822 err
= pohmelfs_data_recv_and_check(st
, m
->data
, sz
);
829 total_size
= cmd
->size
- sz
;
832 sz
= min(total_size
, st
->size
);
834 err
= pohmelfs_data_recv_and_check(st
, st
->data
, sz
);
846 complete(&m
->complete
);
847 pohmelfs_mcache_put(psb
, m
);
852 int pohmelfs_data_lock_response(struct netfs_state
*st
)
854 struct pohmelfs_sb
*psb
= st
->psb
;
855 struct netfs_cmd
*cmd
= &st
->cmd
;
856 struct pohmelfs_mcache
*m
;
857 short err
= (signed short)cmd
->ext
;
860 m
= pohmelfs_mcache_search(psb
, id
);
862 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
863 __func__
, cmd
->id
, (m
)?m
->gen
:0, err
);
866 pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
867 printk("%s: failed to find data lock response: id: %llu.\n", __func__
, cmd
->id
);
872 err
= pohmelfs_data_recv_and_check(st
, &m
->info
, cmd
->size
);
875 complete(&m
->complete
);
876 pohmelfs_mcache_put(psb
, m
);
881 static void __inline__
netfs_state_reset(struct netfs_state
*st
)
883 netfs_state_lock_send(st
);
884 netfs_state_exit(st
);
885 netfs_state_init(st
);
886 netfs_state_unlock_send(st
);
890 * Main receiving function, called from dedicated kernel thread.
892 static int pohmelfs_recv(void *data
)
895 struct netfs_state
*st
= data
;
896 struct netfs_cmd
*cmd
= &st
->cmd
;
898 while (!kthread_should_stop()) {
900 * If socket will be reset after this statement, then
901 * pohmelfs_data_recv() will just fail and loop will
902 * start again, so it can be done without any locks.
904 * st->read_socket is needed to prevents state machine
905 * breaking between this data reading and subsequent one
906 * in protocol specific functions during connection reset.
907 * In case of reset we have to read next command and do
908 * not expect data for old command to magically appear in
911 st
->read_socket
= st
->socket
;
912 err
= pohmelfs_data_recv(st
, cmd
, sizeof(struct netfs_cmd
));
918 netfs_convert_cmd(cmd
);
920 dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
921 "ext: %u, csize: %u, cpad: %u.\n",
922 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
,
923 cmd
->size
, cmd
->ext
, cmd
->csize
, cmd
->cpad
);
926 struct pohmelfs_crypto_engine
*e
= &st
->eng
;
928 if (unlikely(cmd
->csize
> e
->size
/2)) {
929 netfs_state_reset(st
);
933 if (e
->hash
&& unlikely(cmd
->csize
!= st
->psb
->crypto_attached_size
)) {
934 dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
935 "csize: %u != digest size %u.\n",
936 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
,
937 cmd
->csize
, st
->psb
->crypto_attached_size
);
938 netfs_state_reset(st
);
942 err
= pohmelfs_data_recv(st
, e
->data
, cmd
->csize
);
944 netfs_state_reset(st
);
948 #ifdef CONFIG_POHMELFS_DEBUG
951 unsigned char *hash
= e
->data
;
953 dprintk("%s: received hash: ", __func__
);
954 for (i
=0; i
<cmd
->csize
; ++i
) {
955 printk("%02x ", hash
[i
]);
960 cmd
->size
-= cmd
->csize
;
964 * This should catch protocol breakage and random garbage instead of commands.
966 if (unlikely((cmd
->size
> st
->size
) && (cmd
->cmd
!= NETFS_XATTR_GET
))) {
967 netfs_state_reset(st
);
972 case NETFS_READ_PAGE
:
973 err
= pohmelfs_read_page_response(st
);
976 err
= pohmelfs_readdir_response(st
);
979 err
= pohmelfs_lookup_response(st
);
982 err
= pohmelfs_create_response(st
);
985 err
= pohmelfs_remove_response(st
);
988 err
= pohmelfs_transaction_response(st
);
990 case NETFS_PAGE_CACHE
:
991 err
= pohmelfs_page_cache_response(st
);
993 case NETFS_CAPABILITIES
:
994 err
= pohmelfs_capabilities_response(st
);
997 err
= pohmelfs_data_lock_response(st
);
999 case NETFS_XATTR_GET
:
1000 err
= pohmelfs_getxattr_response(st
);
1003 printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
1004 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
, cmd
->ext
);
1005 netfs_state_reset(st
);
1010 while (!kthread_should_stop())
1011 schedule_timeout_uninterruptible(msecs_to_jiffies(10));
1016 int netfs_state_init(struct netfs_state
*st
)
1019 struct pohmelfs_ctl
*ctl
= &st
->ctl
;
1021 err
= sock_create(ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, &st
->socket
);
1023 printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
1024 __func__
, ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, err
);
1028 st
->socket
->sk
->sk_allocation
= GFP_NOIO
;
1029 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
1031 err
= kernel_connect(st
->socket
, (struct sockaddr
*)&ctl
->addr
, ctl
->addrlen
, 0);
1033 printk("%s: failed to connect to server: idx: %u, err: %d.\n",
1034 __func__
, st
->psb
->idx
, err
);
1035 goto err_out_release
;
1037 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
1039 err
= netfs_poll_init(st
);
1041 goto err_out_release
;
1043 if (st
->socket
->ops
->family
== AF_INET
) {
1044 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ctl
->addr
;
1045 printk(KERN_INFO
"%s: (re)connected to peer %u.%u.%u.%u:%d.\n", __func__
,
1046 NIPQUAD(sin
->sin_addr
.s_addr
), ntohs(sin
->sin_port
));
1047 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1048 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&ctl
->addr
;
1049 printk(KERN_INFO
"%s: (re)connected to peer "
1051 __func__
, &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1057 sock_release(st
->socket
);
1063 void netfs_state_exit(struct netfs_state
*st
)
1066 netfs_poll_exit(st
);
1067 st
->socket
->ops
->shutdown(st
->socket
, 2);
1069 if (st
->socket
->ops
->family
== AF_INET
) {
1070 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&st
->ctl
.addr
;
1071 printk("%s: disconnected from peer %u.%u.%u.%u:%d.\n", __func__
,
1072 NIPQUAD(sin
->sin_addr
.s_addr
), ntohs(sin
->sin_port
));
1073 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1074 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&st
->ctl
.addr
;
1075 printk("%s: disconnected from peer "
1077 __func__
, &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1080 sock_release(st
->socket
);
1082 st
->read_socket
= NULL
;
1087 int pohmelfs_state_init_one(struct pohmelfs_sb
*psb
, struct pohmelfs_config
*conf
)
1089 struct netfs_state
*st
= &conf
->state
;
1092 mutex_init(&st
->__state_lock
);
1093 mutex_init(&st
->__state_send_lock
);
1094 init_waitqueue_head(&st
->thread_wait
);
1097 st
->trans_root
= RB_ROOT
;
1098 mutex_init(&st
->trans_lock
);
1100 st
->size
= psb
->trans_data_size
;
1101 st
->data
= kmalloc(st
->size
, GFP_KERNEL
);
1105 if (psb
->perform_crypto
) {
1106 err
= pohmelfs_crypto_engine_init(&st
->eng
, psb
);
1108 goto err_out_free_data
;
1111 err
= netfs_state_init(st
);
1113 goto err_out_free_engine
;
1115 st
->thread
= kthread_run(pohmelfs_recv
, st
, "pohmelfs/%u", psb
->idx
);
1116 if (IS_ERR(st
->thread
)) {
1117 err
= PTR_ERR(st
->thread
);
1118 goto err_out_netfs_exit
;
1121 if (!psb
->active_state
)
1122 psb
->active_state
= conf
;
1124 dprintk("%s: conf: %p, st: %p, socket: %p.\n",
1125 __func__
, conf
, st
, st
->socket
);
1129 netfs_state_exit(st
);
1130 err_out_free_engine
:
1131 pohmelfs_crypto_engine_exit(&st
->eng
);
1139 void pohmelfs_state_flush_transactions(struct netfs_state
*st
)
1141 struct rb_node
*rb_node
;
1142 struct netfs_trans_dst
*dst
;
1144 mutex_lock(&st
->trans_lock
);
1145 for (rb_node
= rb_first(&st
->trans_root
); rb_node
; ) {
1146 dst
= rb_entry(rb_node
, struct netfs_trans_dst
, state_entry
);
1147 rb_node
= rb_next(rb_node
);
1149 dst
->trans
->result
= -EINVAL
;
1150 netfs_trans_remove_nolock(dst
, st
);
1151 netfs_trans_drop_dst_nostate(dst
);
1153 mutex_unlock(&st
->trans_lock
);
1156 static void pohmelfs_state_exit_one(struct pohmelfs_config
*c
)
1158 struct netfs_state
*st
= &c
->state
;
1160 dprintk("%s: exiting, st: %p.\n", __func__
, st
);
1162 kthread_stop(st
->thread
);
1166 netfs_state_lock_send(st
);
1167 netfs_state_exit(st
);
1168 netfs_state_unlock_send(st
);
1170 pohmelfs_state_flush_transactions(st
);
1172 pohmelfs_crypto_engine_exit(&st
->eng
);
1179 * Initialize network stack. It searches for given ID in global
1180 * configuration table, this contains information of the remote server
1181 * (address (any supported by socket interface) and port, protocol and so on).
1183 int pohmelfs_state_init(struct pohmelfs_sb
*psb
)
1187 err
= pohmelfs_copy_config(psb
);
1189 pohmelfs_state_exit(psb
);
1196 void pohmelfs_state_exit(struct pohmelfs_sb
*psb
)
1198 struct pohmelfs_config
*c
, *tmp
;
1200 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1201 list_del(&c
->config_entry
);
1202 pohmelfs_state_exit_one(c
);
1206 void pohmelfs_switch_active(struct pohmelfs_sb
*psb
)
1208 struct pohmelfs_config
*c
= psb
->active_state
;
1210 if (!list_empty(&psb
->state_list
)) {
1211 if (c
->config_entry
.next
!= &psb
->state_list
) {
1212 psb
->active_state
= list_entry(c
->config_entry
.next
,
1213 struct pohmelfs_config
, config_entry
);
1215 psb
->active_state
= list_entry(psb
->state_list
.next
,
1216 struct pohmelfs_config
, config_entry
);
1219 dprintk("%s: empty: %d, active %p -> %p.\n",
1220 __func__
, list_empty(&psb
->state_list
), c
,
1223 psb
->active_state
= NULL
;
1226 void pohmelfs_check_states(struct pohmelfs_sb
*psb
)
1228 struct pohmelfs_config
*c
, *tmp
;
1229 LIST_HEAD(delete_list
);
1231 mutex_lock(&psb
->state_lock
);
1232 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1233 if (pohmelfs_config_check(c
, psb
->idx
)) {
1235 if (psb
->active_state
== c
)
1236 pohmelfs_switch_active(psb
);
1237 list_move(&c
->config_entry
, &delete_list
);
1240 pohmelfs_copy_config(psb
);
1241 mutex_unlock(&psb
->state_lock
);
1243 list_for_each_entry_safe(c
, tmp
, &delete_list
, config_entry
) {
1244 list_del(&c
->config_entry
);
1245 pohmelfs_state_exit_one(c
);