aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/pohmelfs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/pohmelfs')
-rw-r--r--drivers/staging/pohmelfs/Kconfig20
-rw-r--r--drivers/staging/pohmelfs/Makefile3
-rw-r--r--drivers/staging/pohmelfs/config.c611
-rw-r--r--drivers/staging/pohmelfs/crypto.c878
-rw-r--r--drivers/staging/pohmelfs/dir.c1102
-rw-r--r--drivers/staging/pohmelfs/inode.c2055
-rw-r--r--drivers/staging/pohmelfs/lock.c182
-rw-r--r--drivers/staging/pohmelfs/mcache.c171
-rw-r--r--drivers/staging/pohmelfs/net.c1209
-rw-r--r--drivers/staging/pohmelfs/netfs.h919
-rw-r--r--drivers/staging/pohmelfs/path_entry.c120
-rw-r--r--drivers/staging/pohmelfs/trans.c706
12 files changed, 0 insertions, 7976 deletions
diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig
deleted file mode 100644
index 8d53b1a1e71..00000000000
--- a/drivers/staging/pohmelfs/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
1config POHMELFS
2 tristate "POHMELFS filesystem support"
3 depends on NET
4 select CONNECTOR
5 select CRYPTO
6 select CRYPTO_BLKCIPHER
7 select CRYPTO_HMAC
8 help
9 POHMELFS stands for Parallel Optimized Host Message Exchange Layered
10 File System. This is a network filesystem which supports coherent
11 caching of data and metadata on clients.
12
13config POHMELFS_DEBUG
14 bool "POHMELFS debugging"
15 depends on POHMELFS
16 default n
17 help
18 Turns on excessive POHMELFS debugging facilities.
19 You usually do not want to slow things down noticeably and get really
20 lots of kernel messages in syslog.
diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile
deleted file mode 100644
index 196561ca26b..00000000000
--- a/drivers/staging/pohmelfs/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
1obj-$(CONFIG_POHMELFS) += pohmelfs.o
2
3pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
deleted file mode 100644
index b6c42cb0d1c..00000000000
--- a/drivers/staging/pohmelfs/config.c
+++ /dev/null
@@ -1,611 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/kernel.h>
17#include <linux/connector.h>
18#include <linux/crypto.h>
19#include <linux/list.h>
20#include <linux/mutex.h>
21#include <linux/string.h>
22#include <linux/in.h>
23#include <linux/slab.h>
24
25#include "netfs.h"
26
27/*
28 * Global configuration list.
29 * Each client can be asked to get one of them.
30 *
31 * Allows to provide remote server address (ipv4/v6/whatever), port
32 * and so on via kernel connector.
33 */
34
35static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL};
36static LIST_HEAD(pohmelfs_config_list);
37static DEFINE_MUTEX(pohmelfs_config_lock);
38
39static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl)
40{
41 if (sc->idx == ctl->idx && sc->type == ctl->type &&
42 sc->proto == ctl->proto &&
43 sc->addrlen == ctl->addrlen &&
44 !memcmp(&sc->addr, &ctl->addr, ctl->addrlen))
45 return 1;
46
47 return 0;
48}
49
50static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx)
51{
52 struct pohmelfs_config_group *g, *group = NULL;
53
54 list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
55 if (g->idx == idx) {
56 group = g;
57 break;
58 }
59 }
60
61 return group;
62}
63
64static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx)
65{
66 struct pohmelfs_config_group *g;
67
68 g = pohmelfs_find_config_group(idx);
69 if (g)
70 return g;
71
72 g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL);
73 if (!g)
74 return NULL;
75
76 INIT_LIST_HEAD(&g->config_list);
77 g->idx = idx;
78 g->num_entry = 0;
79
80 list_add_tail(&g->group_entry, &pohmelfs_config_list);
81
82 return g;
83}
84
85static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst)
86{
87 struct pohmelfs_config *tmp;
88
89 INIT_LIST_HEAD(&dst->config_entry);
90
91 list_for_each_entry(tmp, &psb->state_list, config_entry) {
92 if (dst->state.ctl.prio > tmp->state.ctl.prio)
93 list_add_tail(&dst->config_entry, &tmp->config_entry);
94 }
95 if (list_empty(&dst->config_entry))
96 list_add_tail(&dst->config_entry, &psb->state_list);
97}
98
99static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb,
100 struct pohmelfs_config *dst, struct pohmelfs_config *new)
101{
102 if ((dst->state.ctl.prio == new->state.ctl.prio) &&
103 (dst->state.ctl.perm == new->state.ctl.perm))
104 return 0;
105
106 dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n",
107 __func__, dst->state.ctl.prio, dst->state.ctl.perm,
108 new->state.ctl.prio, new->state.ctl.perm);
109 dst->state.ctl.prio = new->state.ctl.prio;
110 dst->state.ctl.perm = new->state.ctl.perm;
111
112 list_del_init(&dst->config_entry);
113 pohmelfs_insert_config_entry(psb, dst);
114 return 0;
115}
116
117/*
118 * pohmelfs_copy_config() is used to copy new state configs from the
119 * config group (controlled by the netlink messages) into the superblock.
120 * This happens either at startup time where no transactions can access
121 * the list of the configs (and thus list of the network states), or at
122 * run-time, where it is protected by the psb->state_lock.
123 */
124int pohmelfs_copy_config(struct pohmelfs_sb *psb)
125{
126 struct pohmelfs_config_group *g;
127 struct pohmelfs_config *c, *dst;
128 int err = -ENODEV;
129
130 mutex_lock(&pohmelfs_config_lock);
131
132 g = pohmelfs_find_config_group(psb->idx);
133 if (!g)
134 goto out_unlock;
135
136 /*
137 * Run over all entries in given config group and try to create and
138 * initialize those, which do not exist in superblock list.
139 * Skip all existing entries.
140 */
141
142 list_for_each_entry(c, &g->config_list, config_entry) {
143 err = 0;
144 list_for_each_entry(dst, &psb->state_list, config_entry) {
145 if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) {
146 err = pohmelfs_move_config_entry(psb, dst, c);
147 if (!err)
148 err = -EEXIST;
149 break;
150 }
151 }
152
153 if (err)
154 continue;
155
156 dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
157 if (!dst) {
158 err = -ENOMEM;
159 break;
160 }
161
162 memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl));
163
164 pohmelfs_insert_config_entry(psb, dst);
165
166 err = pohmelfs_state_init_one(psb, dst);
167 if (err) {
168 list_del(&dst->config_entry);
169 kfree(dst);
170 }
171
172 err = 0;
173 }
174
175out_unlock:
176 mutex_unlock(&pohmelfs_config_lock);
177
178 return err;
179}
180
181int pohmelfs_copy_crypto(struct pohmelfs_sb *psb)
182{
183 struct pohmelfs_config_group *g;
184 int err = -ENOENT;
185
186 mutex_lock(&pohmelfs_config_lock);
187 g = pohmelfs_find_config_group(psb->idx);
188 if (!g)
189 goto err_out_exit;
190
191 if (g->hash_string) {
192 err = -ENOMEM;
193 psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL);
194 if (!psb->hash_string)
195 goto err_out_exit;
196 psb->hash_strlen = g->hash_strlen;
197 }
198
199 if (g->cipher_string) {
200 psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL);
201 if (!psb->cipher_string)
202 goto err_out_free_hash_string;
203 psb->cipher_strlen = g->cipher_strlen;
204 }
205
206 if (g->hash_keysize) {
207 psb->hash_key = kmemdup(g->hash_key, g->hash_keysize,
208 GFP_KERNEL);
209 if (!psb->hash_key)
210 goto err_out_free_cipher_string;
211 psb->hash_keysize = g->hash_keysize;
212 }
213
214 if (g->cipher_keysize) {
215 psb->cipher_key = kmemdup(g->cipher_key, g->cipher_keysize,
216 GFP_KERNEL);
217 if (!psb->cipher_key)
218 goto err_out_free_hash;
219 psb->cipher_keysize = g->cipher_keysize;
220 }
221
222 mutex_unlock(&pohmelfs_config_lock);
223
224 return 0;
225
226err_out_free_hash:
227 kfree(psb->hash_key);
228err_out_free_cipher_string:
229 kfree(psb->cipher_string);
230err_out_free_hash_string:
231 kfree(psb->hash_string);
232err_out_exit:
233 mutex_unlock(&pohmelfs_config_lock);
234 return err;
235}
236
237static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl)
238{
239 struct pohmelfs_cn_ack *ack;
240
241 ack = kzalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL);
242 if (!ack)
243 return -ENOMEM;
244
245 memcpy(&ack->msg, msg, sizeof(struct cn_msg));
246
247 if (action == POHMELFS_CTLINFO_ACK)
248 memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl));
249
250 ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg);
251 ack->msg.ack = msg->ack + 1;
252 ack->error = err;
253 ack->msg_num = msg_num;
254
255 cn_netlink_send(&ack->msg, 0, GFP_KERNEL);
256 kfree(ack);
257 return 0;
258}
259
260static int pohmelfs_cn_disp(struct cn_msg *msg)
261{
262 struct pohmelfs_config_group *g;
263 struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
264 struct pohmelfs_config *c, *tmp;
265 int err = 0, i = 1;
266
267 if (msg->len != sizeof(struct pohmelfs_ctl))
268 return -EBADMSG;
269
270 mutex_lock(&pohmelfs_config_lock);
271
272 g = pohmelfs_find_config_group(ctl->idx);
273 if (!g) {
274 pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL);
275 goto out_unlock;
276 }
277
278 list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
279 struct pohmelfs_ctl *sc = &c->state.ctl;
280 if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) {
281 err = -ENOMEM;
282 goto out_unlock;
283 }
284 i += 1;
285 }
286
287 out_unlock:
288 mutex_unlock(&pohmelfs_config_lock);
289 return err;
290}
291
292static int pohmelfs_cn_dump(struct cn_msg *msg)
293{
294 struct pohmelfs_config_group *g;
295 struct pohmelfs_config *c, *tmp;
296 int err = 0, i = 1;
297 int total_msg = 0;
298
299 if (msg->len != sizeof(struct pohmelfs_ctl))
300 return -EBADMSG;
301
302 mutex_lock(&pohmelfs_config_lock);
303
304 list_for_each_entry(g, &pohmelfs_config_list, group_entry)
305 total_msg += g->num_entry;
306 if (total_msg == 0) {
307 if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
308 err = -ENOMEM;
309 goto out_unlock;
310 }
311
312 list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
313 list_for_each_entry_safe(c, tmp, &g->config_list,
314 config_entry) {
315 struct pohmelfs_ctl *sc = &c->state.ctl;
316 if (pohmelfs_send_reply(err, total_msg - i,
317 POHMELFS_CTLINFO_ACK, msg,
318 sc)) {
319 err = -ENOMEM;
320 goto out_unlock;
321 }
322 i += 1;
323 }
324 }
325
326out_unlock:
327 mutex_unlock(&pohmelfs_config_lock);
328 return err;
329}
330
331static int pohmelfs_cn_flush(struct cn_msg *msg)
332{
333 struct pohmelfs_config_group *g;
334 struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
335 struct pohmelfs_config *c, *tmp;
336 int err = 0;
337
338 if (msg->len != sizeof(struct pohmelfs_ctl))
339 return -EBADMSG;
340
341 mutex_lock(&pohmelfs_config_lock);
342
343 if (ctl->idx != POHMELFS_NULL_IDX) {
344 g = pohmelfs_find_config_group(ctl->idx);
345
346 if (!g)
347 goto out_unlock;
348
349 list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
350 list_del(&c->config_entry);
351 g->num_entry--;
352 kfree(c);
353 }
354 } else {
355 list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
356 list_for_each_entry_safe(c, tmp, &g->config_list,
357 config_entry) {
358 list_del(&c->config_entry);
359 g->num_entry--;
360 kfree(c);
361 }
362 }
363 }
364
365out_unlock:
366 mutex_unlock(&pohmelfs_config_lock);
367 pohmelfs_cn_dump(msg);
368
369 return err;
370}
371
372static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new)
373{
374 old->perm = new->perm;
375 old->prio = new->prio;
376 return 0;
377}
378
379static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
380{
381 struct pohmelfs_config_group *g;
382 struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
383 struct pohmelfs_config *c, *tmp;
384 int err = 0;
385
386 if (msg->len != sizeof(struct pohmelfs_ctl))
387 return -EBADMSG;
388
389 mutex_lock(&pohmelfs_config_lock);
390
391 g = pohmelfs_find_create_config_group(ctl->idx);
392 if (!g) {
393 err = -ENOMEM;
394 goto out_unlock;
395 }
396
397 list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
398 struct pohmelfs_ctl *sc = &c->state.ctl;
399
400 if (pohmelfs_config_eql(sc, ctl)) {
401 if (action == POHMELFS_FLAGS_ADD) {
402 err = -EEXIST;
403 goto out_unlock;
404 } else if (action == POHMELFS_FLAGS_DEL) {
405 list_del(&c->config_entry);
406 g->num_entry--;
407 kfree(c);
408 goto out_unlock;
409 } else if (action == POHMELFS_FLAGS_MODIFY) {
410 err = pohmelfs_modify_config(sc, ctl);
411 goto out_unlock;
412 } else {
413 err = -EEXIST;
414 goto out_unlock;
415 }
416 }
417 }
418 if (action == POHMELFS_FLAGS_DEL) {
419 err = -EBADMSG;
420 goto out_unlock;
421 }
422
423 c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
424 if (!c) {
425 err = -ENOMEM;
426 goto out_unlock;
427 }
428 memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl));
429 g->num_entry++;
430
431 list_add_tail(&c->config_entry, &g->config_list);
432
433 out_unlock:
434 mutex_unlock(&pohmelfs_config_lock);
435 if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
436 err = -ENOMEM;
437
438 return err;
439}
440
441static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
442{
443 char *algo = (char *)c->data;
444 u8 *key = (u8 *)(algo + c->strlen);
445
446 if (g->hash_string)
447 return -EEXIST;
448
449 g->hash_string = kstrdup(algo, GFP_KERNEL);
450 if (!g->hash_string)
451 return -ENOMEM;
452 g->hash_strlen = c->strlen;
453 g->hash_keysize = c->keysize;
454
455 g->hash_key = kmemdup(key, c->keysize, GFP_KERNEL);
456 if (!g->hash_key) {
457 kfree(g->hash_string);
458 return -ENOMEM;
459 }
460
461 return 0;
462}
463
464static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
465{
466 char *algo = (char *)c->data;
467 u8 *key = (u8 *)(algo + c->strlen);
468
469 if (g->cipher_string)
470 return -EEXIST;
471
472 g->cipher_string = kstrdup(algo, GFP_KERNEL);
473 if (!g->cipher_string)
474 return -ENOMEM;
475 g->cipher_strlen = c->strlen;
476 g->cipher_keysize = c->keysize;
477
478 g->cipher_key = kmemdup(key, c->keysize, GFP_KERNEL);
479 if (!g->cipher_key) {
480 kfree(g->cipher_string);
481 return -ENOMEM;
482 }
483
484 return 0;
485}
486
487static int pohmelfs_cn_crypto(struct cn_msg *msg)
488{
489 struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data;
490 struct pohmelfs_config_group *g;
491 int err = 0;
492
493 dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n",
494 __func__, crypto->idx, crypto->strlen, crypto->type,
495 crypto->keysize, (char *)crypto->data);
496
497 mutex_lock(&pohmelfs_config_lock);
498 g = pohmelfs_find_create_config_group(crypto->idx);
499 if (!g) {
500 err = -ENOMEM;
501 goto out_unlock;
502 }
503
504 switch (crypto->type) {
505 case POHMELFS_CRYPTO_HASH:
506 err = pohmelfs_crypto_hash_init(g, crypto);
507 break;
508 case POHMELFS_CRYPTO_CIPHER:
509 err = pohmelfs_crypto_cipher_init(g, crypto);
510 break;
511 default:
512 err = -ENOTSUPP;
513 break;
514 }
515
516out_unlock:
517 mutex_unlock(&pohmelfs_config_lock);
518 if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
519 err = -ENOMEM;
520
521 return err;
522}
523
524static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
525{
526 int err;
527
528 if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
529 return;
530
531 switch (msg->flags) {
532 case POHMELFS_FLAGS_ADD:
533 case POHMELFS_FLAGS_DEL:
534 case POHMELFS_FLAGS_MODIFY:
535 err = pohmelfs_cn_ctl(msg, msg->flags);
536 break;
537 case POHMELFS_FLAGS_FLUSH:
538 err = pohmelfs_cn_flush(msg);
539 break;
540 case POHMELFS_FLAGS_SHOW:
541 err = pohmelfs_cn_disp(msg);
542 break;
543 case POHMELFS_FLAGS_DUMP:
544 err = pohmelfs_cn_dump(msg);
545 break;
546 case POHMELFS_FLAGS_CRYPTO:
547 err = pohmelfs_cn_crypto(msg);
548 break;
549 default:
550 err = -ENOSYS;
551 break;
552 }
553}
554
555int pohmelfs_config_check(struct pohmelfs_config *config, int idx)
556{
557 struct pohmelfs_ctl *ctl = &config->state.ctl;
558 struct pohmelfs_config *tmp;
559 int err = -ENOENT;
560 struct pohmelfs_ctl *sc;
561 struct pohmelfs_config_group *g;
562
563 mutex_lock(&pohmelfs_config_lock);
564
565 g = pohmelfs_find_config_group(ctl->idx);
566 if (g) {
567 list_for_each_entry(tmp, &g->config_list, config_entry) {
568 sc = &tmp->state.ctl;
569
570 if (pohmelfs_config_eql(sc, ctl)) {
571 err = 0;
572 break;
573 }
574 }
575 }
576
577 mutex_unlock(&pohmelfs_config_lock);
578
579 return err;
580}
581
582int __init pohmelfs_config_init(void)
583{
584 /* XXX remove (void *) cast when vanilla connector got synced */
585 return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", (void *)pohmelfs_cn_callback);
586}
587
588void pohmelfs_config_exit(void)
589{
590 struct pohmelfs_config *c, *tmp;
591 struct pohmelfs_config_group *g, *gtmp;
592
593 cn_del_callback(&pohmelfs_cn_id);
594
595 mutex_lock(&pohmelfs_config_lock);
596 list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) {
597 list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
598 list_del(&c->config_entry);
599 kfree(c);
600 }
601
602 list_del(&g->group_entry);
603
604 kfree(g->hash_string);
605
606 kfree(g->cipher_string);
607
608 kfree(g);
609 }
610 mutex_unlock(&pohmelfs_config_lock);
611}
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
deleted file mode 100644
index ad92771dce5..00000000000
--- a/drivers/staging/pohmelfs/crypto.c
+++ /dev/null
@@ -1,878 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/crypto.h>
17#include <linux/highmem.h>
18#include <linux/kthread.h>
19#include <linux/pagemap.h>
20#include <linux/scatterlist.h>
21#include <linux/slab.h>
22
23#include "netfs.h"
24
25static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb)
26{
27 int err;
28 struct crypto_hash *hash;
29
30 hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC);
31 if (IS_ERR(hash)) {
32 err = PTR_ERR(hash);
33 dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n",
34 __func__, psb->idx, psb->hash_string, err);
35 goto err_out_exit;
36 }
37
38 psb->crypto_attached_size = crypto_hash_digestsize(hash);
39
40 if (!psb->hash_keysize)
41 return hash;
42
43 err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize);
44 if (err) {
45 dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n",
46 __func__, psb->idx, psb->hash_string, err);
47 goto err_out_free;
48 }
49
50 return hash;
51
52err_out_free:
53 crypto_free_hash(hash);
54err_out_exit:
55 return ERR_PTR(err);
56}
57
58static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb)
59{
60 int err = -EINVAL;
61 struct crypto_ablkcipher *cipher;
62
63 if (!psb->cipher_keysize)
64 goto err_out_exit;
65
66 cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0);
67 if (IS_ERR(cipher)) {
68 err = PTR_ERR(cipher);
69 dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n",
70 __func__, psb->idx, psb->cipher_string, err);
71 goto err_out_exit;
72 }
73
74 crypto_ablkcipher_clear_flags(cipher, ~0);
75
76 err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize);
77 if (err) {
78 dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n",
79 __func__, psb->idx, psb->cipher_string, err);
80 goto err_out_free;
81 }
82
83 return cipher;
84
85err_out_free:
86 crypto_free_ablkcipher(cipher);
87err_out_exit:
88 return ERR_PTR(err);
89}
90
91int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
92{
93 int err;
94
95 e->page_num = 0;
96
97 e->size = PAGE_SIZE;
98 e->data = kmalloc(e->size, GFP_KERNEL);
99 if (!e->data) {
100 err = -ENOMEM;
101 goto err_out_exit;
102 }
103
104 if (psb->hash_string) {
105 e->hash = pohmelfs_init_hash(psb);
106 if (IS_ERR(e->hash)) {
107 err = PTR_ERR(e->hash);
108 e->hash = NULL;
109 goto err_out_free;
110 }
111 }
112
113 if (psb->cipher_string) {
114 e->cipher = pohmelfs_init_cipher(psb);
115 if (IS_ERR(e->cipher)) {
116 err = PTR_ERR(e->cipher);
117 e->cipher = NULL;
118 goto err_out_free_hash;
119 }
120 }
121
122 return 0;
123
124err_out_free_hash:
125 crypto_free_hash(e->hash);
126err_out_free:
127 kfree(e->data);
128err_out_exit:
129 return err;
130}
131
132void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e)
133{
134 crypto_free_hash(e->hash);
135 crypto_free_ablkcipher(e->cipher);
136 kfree(e->data);
137}
138
139static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err)
140{
141 struct pohmelfs_crypto_completion *c = req->data;
142
143 if (err == -EINPROGRESS)
144 return;
145
146 dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
147 c->error = err;
148 complete(&c->complete);
149}
150
151static int pohmelfs_crypto_process(struct ablkcipher_request *req,
152 struct scatterlist *sg_dst, struct scatterlist *sg_src,
153 void *iv, int enc, unsigned long timeout)
154{
155 struct pohmelfs_crypto_completion complete;
156 int err;
157
158 init_completion(&complete.complete);
159 complete.error = -EINPROGRESS;
160
161 ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
162 pohmelfs_crypto_complete, &complete);
163
164 ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
165
166 if (enc)
167 err = crypto_ablkcipher_encrypt(req);
168 else
169 err = crypto_ablkcipher_decrypt(req);
170
171 switch (err) {
172 case -EINPROGRESS:
173 case -EBUSY:
174 err = wait_for_completion_interruptible_timeout(&complete.complete,
175 timeout);
176 if (!err)
177 err = -ETIMEDOUT;
178 else if (err > 0)
179 err = complete.error;
180 break;
181 default:
182 break;
183 }
184
185 return err;
186}
187
188int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv,
189 void *data, struct page *page, unsigned int size)
190{
191 int err;
192 struct scatterlist sg;
193
194 if (!e->cipher && !e->hash)
195 return 0;
196
197 dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n",
198 __func__, e, cmd_iv, data, page, (page) ? page->index : 0, size);
199
200 if (data) {
201 sg_init_one(&sg, data, size);
202 } else {
203 sg_init_table(&sg, 1);
204 sg_set_page(&sg, page, size, 0);
205 }
206
207 if (e->cipher) {
208 struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash);
209 u8 iv[32];
210
211 memset(iv, 0, sizeof(iv));
212 memcpy(iv, &cmd_iv, sizeof(cmd_iv));
213
214 ablkcipher_request_set_tfm(req, e->cipher);
215
216 err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout);
217 if (err)
218 goto err_out_exit;
219 }
220
221 if (e->hash) {
222 struct hash_desc desc;
223 void *dst = e->data + e->size/2;
224
225 desc.tfm = e->hash;
226 desc.flags = 0;
227
228 err = crypto_hash_init(&desc);
229 if (err)
230 goto err_out_exit;
231
232 err = crypto_hash_update(&desc, &sg, size);
233 if (err)
234 goto err_out_exit;
235
236 err = crypto_hash_final(&desc, dst);
237 if (err)
238 goto err_out_exit;
239
240 err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash));
241
242 if (err) {
243#ifdef CONFIG_POHMELFS_DEBUG
244 unsigned int i;
245 unsigned char *recv = e->data, *calc = dst;
246
247 dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ",
248 __func__, e, e->hash, e->cipher, cmd_iv);
249 for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) {
250#if 0
251 dprintka("%02x ", recv[i]);
252 if (recv[i] != calc[i]) {
253 dprintka("| calc byte: %02x.\n", calc[i]);
254 break;
255 }
256#else
257 dprintka("%02x/%02x ", recv[i], calc[i]);
258#endif
259 }
260 dprintk("\n");
261#endif
262 goto err_out_exit;
263 } else {
264 dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n",
265 __func__, e, e->hash, e->cipher);
266 }
267 }
268
269 dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n",
270 __func__, e, e->size, e->hash, e->cipher);
271
272 return 0;
273
274err_out_exit:
275 dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n",
276 __func__, e, e->hash, e->cipher, err);
277 return err;
278}
279
280static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e,
281 int (*iterator) (struct pohmelfs_crypto_engine *e,
282 struct scatterlist *dst,
283 struct scatterlist *src))
284{
285 void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size;
286 unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size;
287 struct netfs_cmd *cmd = data;
288 unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx;
289 struct scatterlist sg_src, sg_dst;
290 int err;
291
292 while (size) {
293 cmd = data;
294 cmd_cmd = __be16_to_cpu(cmd->cmd);
295 csize = __be32_to_cpu(cmd->size);
296 cmd->iv = __cpu_to_be64(e->iv);
297
298 if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE)
299 csize = __be16_to_cpu(cmd->ext);
300
301 sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd);
302
303 dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n",
304 __func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad));
305
306 data += sz;
307 size -= sz;
308
309 sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd));
310 sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd));
311
312 err = iterator(e, &sg_dst, &sg_src);
313 if (err)
314 return err;
315 }
316
317 if (!pages)
318 return 0;
319
320 dpage_idx = 0;
321 for (i = 0; i < t->page_num; ++i) {
322 struct page *page = t->pages[i];
323 struct page *dpage = e->pages[dpage_idx];
324
325 if (!page)
326 continue;
327
328 sg_init_table(&sg_src, 1);
329 sg_init_table(&sg_dst, 1);
330 sg_set_page(&sg_src, page, page_private(page), 0);
331 sg_set_page(&sg_dst, dpage, page_private(page), 0);
332
333 err = iterator(e, &sg_dst, &sg_src);
334 if (err)
335 return err;
336
337 pages--;
338 if (!pages)
339 break;
340 dpage_idx++;
341 }
342
343 return 0;
344}
345
346static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e,
347 struct scatterlist *sg_dst, struct scatterlist *sg_src)
348{
349 struct ablkcipher_request *req = e->data;
350 u8 iv[32];
351
352 memset(iv, 0, sizeof(iv));
353
354 memcpy(iv, &e->iv, sizeof(e->iv));
355
356 return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout);
357}
358
359static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc)
360{
361 struct netfs_trans *t = tc->trans;
362 struct pohmelfs_crypto_engine *e = &tc->eng;
363 struct ablkcipher_request *req = e->data;
364
365 memset(req, 0, sizeof(struct ablkcipher_request));
366 ablkcipher_request_set_tfm(req, e->cipher);
367
368 e->iv = pohmelfs_gen_iv(t);
369
370 return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator);
371}
372
373static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e,
374 struct scatterlist *sg_dst, struct scatterlist *sg_src)
375{
376 return crypto_hash_update(e->data, sg_src, sg_src->length);
377}
378
379static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc)
380{
381 struct pohmelfs_crypto_engine *e = &tc->eng;
382 struct hash_desc *desc = e->data;
383 unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd);
384 int err;
385
386 desc->tfm = e->hash;
387 desc->flags = 0;
388
389 err = crypto_hash_init(desc);
390 if (err)
391 return err;
392
393 err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator);
394 if (err)
395 return err;
396
397 err = crypto_hash_final(desc, dst);
398 if (err)
399 return err;
400
401 {
402 unsigned int i;
403 dprintk("%s: ", __func__);
404 for (i = 0; i < tc->psb->crypto_attached_size; ++i)
405 dprintka("%02x ", dst[i]);
406 dprintka("\n");
407 }
408
409 return 0;
410}
411
412static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e)
413{
414 unsigned int i;
415
416 for (i = 0; i < e->page_num; ++i)
417 __free_page(e->pages[i]);
418 kfree(e->pages);
419}
420
421static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
422{
423 unsigned int i;
424
425 e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL);
426 if (!e->pages)
427 return -ENOMEM;
428
429 for (i = 0; i < psb->trans_max_pages; ++i) {
430 e->pages[i] = alloc_page(GFP_KERNEL);
431 if (!e->pages[i])
432 break;
433 }
434
435 e->page_num = i;
436 if (!e->page_num)
437 goto err_out_free;
438
439 return 0;
440
441err_out_free:
442 kfree(e->pages);
443 return -ENOMEM;
444}
445
446static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t)
447{
448 struct pohmelfs_sb *psb = t->psb;
449
450 if (t->thread)
451 kthread_stop(t->thread);
452
453 mutex_lock(&psb->crypto_thread_lock);
454 list_del(&t->thread_entry);
455 psb->crypto_thread_num--;
456 mutex_unlock(&psb->crypto_thread_lock);
457
458 pohmelfs_crypto_engine_exit(&t->eng);
459 pohmelfs_crypto_pages_free(&t->eng);
460 kfree(t);
461}
462
463static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err)
464{
465 struct netfs_cmd *cmd = t->iovec.iov_base;
466 netfs_convert_cmd(cmd);
467
468 if (likely(!err))
469 err = netfs_trans_finish_send(t, psb);
470
471 t->result = err;
472 netfs_trans_put(t);
473
474 return err;
475}
476
477void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th)
478{
479 struct pohmelfs_sb *psb = th->psb;
480
481 th->page = NULL;
482 th->trans = NULL;
483
484 mutex_lock(&psb->crypto_thread_lock);
485 list_move_tail(&th->thread_entry, &psb->crypto_ready_list);
486 mutex_unlock(&psb->crypto_thread_lock);
487 wake_up(&psb->wait);
488}
489
490static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t)
491{
492 struct netfs_trans *trans;
493 int err = 0;
494
495 trans = t->trans;
496 trans->eng = NULL;
497
498 if (t->eng.hash) {
499 err = pohmelfs_hash(t);
500 if (err)
501 goto out_complete;
502 }
503
504 if (t->eng.cipher) {
505 err = pohmelfs_encrypt(t);
506 if (err)
507 goto out_complete;
508 trans->eng = &t->eng;
509 }
510
511out_complete:
512 t->page = NULL;
513 t->trans = NULL;
514
515 if (!trans->eng)
516 pohmelfs_crypto_thread_make_ready(t);
517
518 pohmelfs_crypto_finish(trans, t->psb, err);
519 return err;
520}
521
522static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t)
523{
524 struct pohmelfs_crypto_engine *e = &t->eng;
525 struct page *page = t->page;
526 int err;
527
528 WARN_ON(!PageChecked(page));
529
530 err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size);
531 if (!err)
532 SetPageUptodate(page);
533 else
534 SetPageError(page);
535 unlock_page(page);
536 page_cache_release(page);
537
538 pohmelfs_crypto_thread_make_ready(t);
539
540 return err;
541}
542
543static int pohmelfs_crypto_thread_func(void *data)
544{
545 struct pohmelfs_crypto_thread *t = data;
546
547 while (!kthread_should_stop()) {
548 wait_event_interruptible(t->wait, kthread_should_stop() ||
549 t->trans || t->page);
550
551 if (kthread_should_stop())
552 break;
553
554 if (!t->trans && !t->page)
555 continue;
556
557 dprintk("%s: thread: %p, trans: %p, page: %p.\n",
558 __func__, t, t->trans, t->page);
559
560 if (t->trans)
561 pohmelfs_crypto_thread_trans(t);
562 else if (t->page)
563 pohmelfs_crypto_thread_page(t);
564 }
565
566 return 0;
567}
568
569static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head)
570{
571 while (!list_empty(head)) {
572 struct pohmelfs_crypto_thread *t = NULL;
573
574 mutex_lock(&psb->crypto_thread_lock);
575 if (!list_empty(head)) {
576 t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry);
577 list_del_init(&t->thread_entry);
578 }
579 mutex_unlock(&psb->crypto_thread_lock);
580
581 if (t)
582 pohmelfs_sys_crypto_exit_one(t);
583 }
584}
585
586static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb)
587{
588 while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) {
589 dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num);
590 pohmelfs_crypto_flush(psb, &psb->crypto_active_list);
591 pohmelfs_crypto_flush(psb, &psb->crypto_ready_list);
592 }
593}
594
595static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb)
596{
597 unsigned int i;
598 struct pohmelfs_crypto_thread *t;
599 struct pohmelfs_config *c;
600 struct netfs_state *st;
601 int err;
602
603 list_for_each_entry(c, &psb->state_list, config_entry) {
604 st = &c->state;
605
606 err = pohmelfs_crypto_engine_init(&st->eng, psb);
607 if (err)
608 goto err_out_exit;
609
610 dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n",
611 __func__, st, &st->eng, &st->eng.hash, &st->eng.cipher);
612 }
613
614 for (i = 0; i < psb->crypto_thread_num; ++i) {
615 err = -ENOMEM;
616 t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL);
617 if (!t)
618 goto err_out_free_state_engines;
619
620 init_waitqueue_head(&t->wait);
621
622 t->psb = psb;
623 t->trans = NULL;
624 t->eng.thread = t;
625
626 err = pohmelfs_crypto_engine_init(&t->eng, psb);
627 if (err)
628 goto err_out_free_state_engines;
629
630 err = pohmelfs_crypto_pages_alloc(&t->eng, psb);
631 if (err)
632 goto err_out_free;
633
634 t->thread = kthread_run(pohmelfs_crypto_thread_func, t,
635 "pohmelfs-crypto-%d-%d", psb->idx, i);
636 if (IS_ERR(t->thread)) {
637 err = PTR_ERR(t->thread);
638 t->thread = NULL;
639 goto err_out_free;
640 }
641
642 if (t->eng.cipher)
643 psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher);
644
645 mutex_lock(&psb->crypto_thread_lock);
646 list_add_tail(&t->thread_entry, &psb->crypto_ready_list);
647 mutex_unlock(&psb->crypto_thread_lock);
648 }
649
650 psb->crypto_thread_num = i;
651 return 0;
652
653err_out_free:
654 pohmelfs_sys_crypto_exit_one(t);
655err_out_free_state_engines:
656 list_for_each_entry(c, &psb->state_list, config_entry) {
657 st = &c->state;
658 pohmelfs_crypto_engine_exit(&st->eng);
659 }
660err_out_exit:
661 pohmelfs_sys_crypto_exit(psb);
662 return err;
663}
664
665void pohmelfs_crypto_exit(struct pohmelfs_sb *psb)
666{
667 pohmelfs_sys_crypto_exit(psb);
668
669 kfree(psb->hash_string);
670 kfree(psb->cipher_string);
671}
672
673static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num,
674 void *private, int err)
675{
676 struct pohmelfs_sb *psb = private;
677
678 psb->flags = -err;
679 dprintk("%s: err: %d.\n", __func__, err);
680
681 wake_up(&psb->wait);
682
683 return err;
684}
685
686static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb)
687{
688 struct netfs_trans *t;
689 struct netfs_crypto_capabilities *cap;
690 struct netfs_cmd *cmd;
691 char *str;
692 int err = -ENOMEM, size;
693
694 size = sizeof(struct netfs_crypto_capabilities) +
695 psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */
696
697 t = netfs_trans_alloc(psb, size, 0, 0);
698 if (!t)
699 goto err_out_exit;
700
701 t->complete = pohmelfs_crypt_init_complete;
702 t->private = psb;
703
704 cmd = netfs_trans_current(t);
705 cap = (struct netfs_crypto_capabilities *)(cmd + 1);
706 str = (char *)(cap + 1);
707
708 cmd->cmd = NETFS_CAPABILITIES;
709 cmd->id = POHMELFS_CRYPTO_CAPABILITIES;
710 cmd->size = size;
711 cmd->start = 0;
712 cmd->ext = 0;
713 cmd->csize = 0;
714
715 netfs_convert_cmd(cmd);
716 netfs_trans_update(cmd, t, size);
717
718 cap->hash_strlen = psb->hash_strlen;
719 if (cap->hash_strlen) {
720 sprintf(str, "%s", psb->hash_string);
721 str += cap->hash_strlen;
722 }
723
724 cap->cipher_strlen = psb->cipher_strlen;
725 cap->cipher_keysize = psb->cipher_keysize;
726 if (cap->cipher_strlen)
727 sprintf(str, "%s", psb->cipher_string);
728
729 netfs_convert_crypto_capabilities(cap);
730
731 psb->flags = ~0;
732 err = netfs_trans_finish(t, psb);
733 if (err)
734 goto err_out_exit;
735
736 err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0),
737 psb->wait_on_page_timeout);
738 if (!err)
739 err = -ETIMEDOUT;
740 else if (err > 0)
741 err = -psb->flags;
742
743 if (!err)
744 psb->perform_crypto = 1;
745 psb->flags = 0;
746
747 /*
748 * At this point NETFS_CAPABILITIES response command
749 * should setup superblock in a way, which is acceptable
750 * for both client and server, so if server refuses connection,
751 * it will send error in transaction response.
752 */
753
754 if (err)
755 goto err_out_exit;
756
757 return 0;
758
759err_out_exit:
760 return err;
761}
762
763int pohmelfs_crypto_init(struct pohmelfs_sb *psb)
764{
765 int err;
766
767 if (!psb->cipher_string && !psb->hash_string)
768 return 0;
769
770 err = pohmelfs_crypto_init_handshake(psb);
771 if (err)
772 return err;
773
774 err = pohmelfs_sys_crypto_init(psb);
775 if (err)
776 return err;
777
778 return 0;
779}
780
781static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb,
782 int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data)
783{
784 struct pohmelfs_crypto_thread *t = NULL;
785 int err;
786
787 while (!t) {
788 err = wait_event_interruptible_timeout(psb->wait,
789 !list_empty(&psb->crypto_ready_list),
790 psb->wait_on_page_timeout);
791
792 t = NULL;
793 err = 0;
794 mutex_lock(&psb->crypto_thread_lock);
795 if (!list_empty(&psb->crypto_ready_list)) {
796 t = list_entry(psb->crypto_ready_list.prev,
797 struct pohmelfs_crypto_thread,
798 thread_entry);
799
800 list_move_tail(&t->thread_entry,
801 &psb->crypto_active_list);
802
803 action(t, data);
804 wake_up(&t->wait);
805
806 }
807 mutex_unlock(&psb->crypto_thread_lock);
808 }
809
810 return err;
811}
812
813static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data)
814{
815 struct netfs_trans *trans = data;
816
817 netfs_trans_get(trans);
818 t->trans = trans;
819
820 dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t);
821 return 0;
822}
823
824int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
825{
826 if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) {
827 netfs_trans_get(trans);
828 return pohmelfs_crypto_finish(trans, psb, 0);
829 }
830
831 return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
832}
833
834struct pohmelfs_crypto_input_action_data {
835 struct page *page;
836 struct pohmelfs_crypto_engine *e;
837 u64 iv;
838 unsigned int size;
839};
840
841static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data)
842{
843 struct pohmelfs_crypto_input_action_data *act = data;
844
845 memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size);
846
847 t->size = act->size;
848 t->eng.iv = act->iv;
849
850 t->page = act->page;
851 return 0;
852}
853
854int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
855 struct page *page, unsigned int size, u64 iv)
856{
857 struct inode *inode = page->mapping->host;
858 struct pohmelfs_crypto_input_action_data act;
859 int err = -ENOENT;
860
861 act.page = page;
862 act.e = e;
863 act.size = size;
864 act.iv = iv;
865
866 err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb),
867 pohmelfs_crypt_input_page_action, &act);
868 if (err)
869 goto err_out_exit;
870
871 return 0;
872
873err_out_exit:
874 SetPageUptodate(page);
875 page_cache_release(page);
876
877 return err;
878}
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
deleted file mode 100644
index 2ee4491b713..00000000000
--- a/drivers/staging/pohmelfs/dir.c
+++ /dev/null
@@ -1,1102 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/kernel.h>
17#include <linux/fs.h>
18#include <linux/jhash.h>
19#include <linux/namei.h>
20#include <linux/slab.h>
21#include <linux/pagemap.h>
22
23#include "netfs.h"
24
25static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash)
26{
27 if (n->hash > hash)
28 return -1;
29 if (n->hash < hash)
30 return 1;
31
32 return 0;
33}
34
35static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash)
36{
37 struct rb_node *n = pi->hash_root.rb_node;
38 struct pohmelfs_name *tmp = NULL;
39 int cmp;
40
41 while (n) {
42 tmp = rb_entry(n, struct pohmelfs_name, hash_node);
43
44 cmp = pohmelfs_cmp_hash(tmp, hash);
45 if (cmp < 0)
46 n = n->rb_left;
47 else if (cmp > 0)
48 n = n->rb_right;
49 else
50 break;
51
52 }
53
54 return tmp;
55}
56
57struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash)
58{
59 struct pohmelfs_name *tmp;
60
61 tmp = pohmelfs_search_hash_unprecise(pi, hash);
62 if (tmp && (tmp->hash == hash))
63 return tmp;
64
65 return NULL;
66}
67
68static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
69{
70 rb_erase(&node->hash_node, &parent->hash_root);
71}
72
73/*
74 * Remove name cache entry from its caches and free it.
75 */
76static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
77{
78 __pohmelfs_name_del(parent, node);
79 list_del(&node->sync_create_entry);
80 kfree(node);
81}
82
83static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi,
84 struct pohmelfs_name *new)
85{
86 struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL;
87 struct pohmelfs_name *ret = NULL, *tmp;
88 int cmp;
89
90 while (*n) {
91 parent = *n;
92
93 tmp = rb_entry(parent, struct pohmelfs_name, hash_node);
94
95 cmp = pohmelfs_cmp_hash(tmp, new->hash);
96 if (cmp < 0)
97 n = &parent->rb_left;
98 else if (cmp > 0)
99 n = &parent->rb_right;
100 else {
101 ret = tmp;
102 break;
103 }
104 }
105
106 if (ret) {
107 printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
108 "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
109 __func__, pi->ino,
110 ret->ino, ret->hash, ret->len, ret->data,
111 new->ino, new->hash, new->len, new->data);
112 ret->ino = new->ino;
113 return ret;
114 }
115
116 rb_link_node(&new->hash_node, parent, n);
117 rb_insert_color(&new->hash_node, &pi->hash_root);
118
119 return NULL;
120}
121
122/*
123 * Free name cache for given inode.
124 */
125void pohmelfs_free_names(struct pohmelfs_inode *parent)
126{
127 struct rb_node *rb_node;
128 struct pohmelfs_name *n;
129
130 for (rb_node = rb_first(&parent->hash_root); rb_node;) {
131 n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
132 rb_node = rb_next(rb_node);
133
134 pohmelfs_name_free(parent, n);
135 }
136}
137
138static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
139{
140 parent->total_len -= node->len;
141}
142
143/*
144 * Free name cache entry helper.
145 */
146void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
147{
148 pohmelfs_fix_offset(parent, node);
149 pohmelfs_name_free(parent, node);
150}
151
152/*
153 * Insert new name cache entry into all hash cache.
154 */
155static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n)
156{
157 struct pohmelfs_name *name;
158
159 name = pohmelfs_insert_hash(parent, n);
160 if (name)
161 return -EEXIST;
162
163 parent->total_len += n->len;
164 list_add_tail(&n->sync_create_entry, &parent->sync_create_list);
165
166 return 0;
167}
168
169/*
170 * Allocate new name cache entry.
171 */
172static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len)
173{
174 struct pohmelfs_name *n;
175
176 n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL);
177 if (!n)
178 return NULL;
179
180 INIT_LIST_HEAD(&n->sync_create_entry);
181
182 n->data = (char *)(n+1);
183
184 return n;
185}
186
187/*
188 * Add new name entry into directory's cache.
189 */
190static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent,
191 struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link)
192{
193 int err = -ENOMEM;
194 struct pohmelfs_name *n;
195
196 n = pohmelfs_name_alloc(str->len + 1);
197 if (!n)
198 goto err_out_exit;
199
200 n->ino = npi->ino;
201 n->mode = mode;
202 n->len = str->len;
203 n->hash = str->hash;
204 sprintf(n->data, "%s", str->name);
205
206 mutex_lock(&parent->offset_lock);
207 err = pohmelfs_insert_name(parent, n);
208 mutex_unlock(&parent->offset_lock);
209
210 if (err) {
211 if (err != -EEXIST)
212 goto err_out_free;
213 kfree(n);
214 }
215
216 return 0;
217
218err_out_free:
219 kfree(n);
220err_out_exit:
221 return err;
222}
223
224/*
225 * Create new inode for given parameters (name, inode info, parent).
226 * This does not create object on the server, it will be synced there during writeback.
227 */
228struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
229 struct pohmelfs_inode *parent, struct qstr *str,
230 struct netfs_inode_info *info, int link)
231{
232 struct inode *new = NULL;
233 struct pohmelfs_inode *npi;
234 int err = -EEXIST;
235
236 dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
237 __func__, (parent) ? parent->ino : 0, info->ino, str);
238
239 err = -ENOMEM;
240 new = iget_locked(psb->sb, info->ino);
241 if (!new)
242 goto err_out_exit;
243
244 npi = POHMELFS_I(new);
245 npi->ino = info->ino;
246 err = 0;
247
248 if (new->i_state & I_NEW) {
249 dprintk("%s: filling VFS inode: %lu/%llu.\n",
250 __func__, new->i_ino, info->ino);
251 pohmelfs_fill_inode(new, info);
252
253 if (S_ISDIR(info->mode)) {
254 struct qstr s;
255
256 s.name = ".";
257 s.len = 1;
258 s.hash = jhash(s.name, s.len, 0);
259
260 err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0);
261 if (err)
262 goto err_out_put;
263
264 s.name = "..";
265 s.len = 2;
266 s.hash = jhash(s.name, s.len, 0);
267
268 err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s,
269 (parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0);
270 if (err)
271 goto err_out_put;
272 }
273 }
274
275 if (str) {
276 if (parent) {
277 err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link);
278
279 dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
280 __func__, (err) ? "unsuccessfully" : "successfully",
281 str->name, parent->total_len, info->ino, parent->ino);
282
283 if (err && err != -EEXIST)
284 goto err_out_put;
285 }
286 }
287
288 if (new->i_state & I_NEW) {
289 if (parent)
290 mark_inode_dirty(&parent->vfs_inode);
291 mark_inode_dirty(new);
292 }
293
294 set_bit(NETFS_INODE_OWNED, &npi->state);
295 npi->lock_type = POHMELFS_WRITE_LOCK;
296 unlock_new_inode(new);
297
298 return npi;
299
300err_out_put:
301 printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err);
302 iput(new);
303err_out_exit:
304 return ERR_PTR(err);
305}
306
307static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num,
308 void *private, int err)
309{
310 struct pohmelfs_inode *pi = private;
311 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
312
313 dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
314
315 if (err)
316 pi->error = err;
317 wake_up(&psb->wait);
318 pohmelfs_put_inode(pi);
319
320 return err;
321}
322
323/*
324 * Receive directory content from the server.
325 * This should be only done for objects, which were not created locally,
326 * and which were not synced previously.
327 */
328static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
329{
330 struct inode *inode = &pi->vfs_inode;
331 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
332 long ret = psb->wait_on_page_timeout;
333 int err;
334
335 dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
336 __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state));
337
338 if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state))
339 return 0;
340
341 if (!igrab(inode)) {
342 err = -ENOENT;
343 goto err_out_exit;
344 }
345
346 err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST,
347 pohmelfs_remote_sync_complete, pi, 0);
348 if (err)
349 goto err_out_exit;
350
351 pi->error = 0;
352 ret = wait_event_interruptible_timeout(psb->wait,
353 test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret);
354 dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error);
355 if (ret <= 0) {
356 err = ret;
357 if (!err)
358 err = -ETIMEDOUT;
359 goto err_out_exit;
360 }
361
362 if (pi->error)
363 return pi->error;
364
365 return 0;
366
367err_out_exit:
368 clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
369
370 return err;
371}
372
373static int pohmelfs_dir_open(struct inode *inode, struct file *file)
374{
375 file->private_data = NULL;
376 return 0;
377}
378
379/*
380 * VFS readdir callback. Syncs directory content from server if needed,
381 * and provides direntry info to the userspace.
382 */
383static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
384{
385 struct inode *inode = file->f_path.dentry->d_inode;
386 struct pohmelfs_inode *pi = POHMELFS_I(inode);
387 struct pohmelfs_name *n;
388 struct rb_node *rb_node;
389 int err = 0, mode;
390 u64 len;
391
392 dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
393 __func__, pi->ino, (u64)file->f_pos,
394 (unsigned long)file->private_data);
395#if 0
396 err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
397 if (err)
398 return err;
399#endif
400 err = pohmelfs_sync_remote_dir(pi);
401 if (err)
402 return err;
403
404 if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos))
405 return 0;
406
407 mutex_lock(&pi->offset_lock);
408 n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data);
409
410 while (n) {
411 mode = (n->mode >> 12) & 15;
412
413 dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
414 "mode: %o/%o, fpos: %llu, hash: %08x.\n",
415 __func__, file->f_pos, pi->ino, n->data, n->len,
416 n->ino, n->mode, mode, file->f_pos, n->hash);
417
418 file->private_data = (void *)(unsigned long)n->hash;
419
420 len = n->len;
421 err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode);
422
423 if (err < 0) {
424 dprintk("%s: err: %d.\n", __func__, err);
425 err = 0;
426 break;
427 }
428
429 file->f_pos += len;
430
431 rb_node = rb_next(&n->hash_node);
432
433 if (!rb_node || (rb_node == &n->hash_node)) {
434 file->private_data = (void *)(unsigned long)file->f_pos;
435 break;
436 }
437
438 n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
439 }
440 mutex_unlock(&pi->offset_lock);
441
442 return err;
443}
444
445static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin)
446{
447 file->f_pos = offset;
448 file->private_data = NULL;
449 return offset;
450}
451
452const struct file_operations pohmelfs_dir_fops = {
453 .open = pohmelfs_dir_open,
454 .read = generic_read_dir,
455 .llseek = pohmelfs_dir_lseek,
456 .readdir = pohmelfs_readdir,
457};
458
459/*
460 * Lookup single object on server.
461 */
462static int pohmelfs_lookup_single(struct pohmelfs_inode *parent,
463 struct qstr *str, u64 ino)
464{
465 struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb);
466 long ret = msecs_to_jiffies(5000);
467 int err;
468
469 set_bit(NETFS_COMMAND_PENDING, &parent->state);
470 err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP,
471 (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino);
472 if (err)
473 goto err_out_exit;
474
475 err = 0;
476 ret = wait_event_interruptible_timeout(psb->wait,
477 !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret);
478 if (ret <= 0) {
479 err = ret;
480 if (!err)
481 err = -ETIMEDOUT;
482 }
483
484 if (err)
485 goto err_out_exit;
486
487 return 0;
488
489err_out_exit:
490 clear_bit(NETFS_COMMAND_PENDING, &parent->state);
491
492 printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
493 __func__, parent->ino, ino, str->name, err);
494
495 return err;
496}
497
498/*
499 * VFS lookup callback.
500 * We first try to get inode number from local name cache, if we have one,
501 * then inode can be found in inode cache. If there is no inode or no object in
502 * local cache, try to lookup it on server. This only should be done for directories,
503 * which were not created locally, otherwise remote server does not know about dir at all,
504 * so no need to try to know that.
505 */
506struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
507{
508 struct pohmelfs_inode *parent = POHMELFS_I(dir);
509 struct pohmelfs_name *n;
510 struct inode *inode = NULL;
511 unsigned long ino = 0;
512 int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
513 struct qstr str = dentry->d_name;
514
515 if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
516 lock_type = POHMELFS_WRITE_LOCK;
517
518 if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
519 if (lock_type == parent->lock_type)
520 need_lock = 0;
521 if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK))
522 need_lock = 0;
523 }
524
525 if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state))
526 need_lock = 1;
527
528 str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
529
530 mutex_lock(&parent->offset_lock);
531 n = pohmelfs_search_hash(parent, str.hash);
532 if (n)
533 ino = n->ino;
534 mutex_unlock(&parent->offset_lock);
535
536 dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
537 __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
538
539 if (ino) {
540 inode = ilookup(dir->i_sb, ino);
541 if (inode)
542 goto out;
543 }
544
545 dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
546 __func__, dir, parent->ino,
547 str.name, str.len, parent->state, ino);
548
549 if (!ino) {
550 if (!need_lock)
551 goto out;
552 }
553
554 err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
555 if (err)
556 goto out;
557
558 err = pohmelfs_lookup_single(parent, &str, ino);
559 if (err)
560 goto out;
561
562 if (!ino) {
563 mutex_lock(&parent->offset_lock);
564 n = pohmelfs_search_hash(parent, str.hash);
565 if (n)
566 ino = n->ino;
567 mutex_unlock(&parent->offset_lock);
568 }
569
570 if (ino) {
571 inode = ilookup(dir->i_sb, ino);
572 dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
573 __func__, ino, inode, str.name, str.hash);
574 if (!inode) {
575 dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
576 __func__, ino, str.name, str.hash);
577 /* return NULL; */
578 return ERR_PTR(-EACCES);
579 }
580 } else {
581 printk("%s: No inode number : name: '%s', hash: %x.\n",
582 __func__, str.name, str.hash);
583 }
584out:
585 return d_splice_alias(inode, dentry);
586}
587
588/*
589 * Create new object in local cache. Object will be synced to server
590 * during writeback for given inode.
591 */
592struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
593 struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode)
594{
595 struct pohmelfs_inode *npi;
596 int err = -ENOMEM;
597 struct netfs_inode_info info;
598
599 dprintk("%s: name: '%s', mode: %ho, start: %llu.\n",
600 __func__, str->name, mode, start);
601
602 info.mode = mode;
603 info.ino = start;
604
605 if (!start)
606 info.ino = pohmelfs_new_ino(psb);
607
608 info.nlink = S_ISDIR(mode) ? 2 : 1;
609 info.uid = current_fsuid();
610 info.gid = current_fsgid();
611 info.size = 0;
612 info.blocksize = 512;
613 info.blocks = 0;
614 info.rdev = 0;
615 info.version = 0;
616
617 npi = pohmelfs_new_inode(psb, parent, str, &info, !!start);
618 if (IS_ERR(npi)) {
619 err = PTR_ERR(npi);
620 goto err_out_unlock;
621 }
622
623 return npi;
624
625err_out_unlock:
626 dprintk("%s: err: %d.\n", __func__, err);
627 return ERR_PTR(err);
628}
629
630/*
631 * Create local object and bind it to dentry.
632 */
633static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry,
634 u64 start, umode_t mode)
635{
636 struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
637 struct pohmelfs_inode *npi, *parent;
638 struct qstr str = dentry->d_name;
639 int err;
640
641 parent = POHMELFS_I(dir);
642
643 err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
644 if (err)
645 return err;
646
647 str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
648
649 npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode);
650 if (IS_ERR(npi))
651 return PTR_ERR(npi);
652
653 d_instantiate(dentry, &npi->vfs_inode);
654
655 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
656 __func__, parent->ino, npi->ino, dentry->d_name.name,
657 (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink);
658
659 return 0;
660}
661
662/*
663 * VFS create and mkdir callbacks.
664 */
665static int pohmelfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
666 struct nameidata *nd)
667{
668 return pohmelfs_create_entry(dir, dentry, 0, mode);
669}
670
671static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
672{
673 int err;
674
675 inode_inc_link_count(dir);
676 err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR);
677 if (err)
678 inode_dec_link_count(dir);
679
680 return err;
681}
682
683static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
684{
685 struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
686 struct inode *inode = dentry->d_inode;
687 struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode);
688 struct pohmelfs_name *n;
689 int err = -ENOENT;
690 struct qstr str = dentry->d_name;
691
692 err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
693 if (err)
694 return err;
695
696 str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
697
698 dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
699 __func__, parent->ino, pi->ino,
700 str.name, (signed)inode->i_nlink);
701
702 BUG_ON(!inode);
703
704 mutex_lock(&parent->offset_lock);
705 n = pohmelfs_search_hash(parent, str.hash);
706 if (n) {
707 pohmelfs_fix_offset(parent, n);
708 if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
709 pohmelfs_remove_child(pi, n);
710
711 pohmelfs_name_free(parent, n);
712 err = 0;
713 }
714 mutex_unlock(&parent->offset_lock);
715
716 if (!err) {
717 psb->avail_size += inode->i_size;
718
719 pohmelfs_inode_del_inode(psb, pi);
720
721 mark_inode_dirty(dir);
722
723 inode->i_ctime = dir->i_ctime;
724 if (inode->i_nlink)
725 inode_dec_link_count(inode);
726 }
727
728 return err;
729}
730
731/*
732 * Unlink and rmdir VFS callbacks.
733 */
734static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry)
735{
736 return pohmelfs_remove_entry(dir, dentry);
737}
738
739static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry)
740{
741 int err;
742 struct inode *inode = dentry->d_inode;
743
744 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
745 __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino,
746 dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink);
747
748 err = pohmelfs_remove_entry(dir, dentry);
749 if (!err) {
750 inode_dec_link_count(dir);
751 inode_dec_link_count(inode);
752 }
753
754 return err;
755}
756
757/*
758 * Link creation is synchronous.
759 * I'm lazy.
760 * Earth is somewhat round.
761 */
762static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj,
763 struct pohmelfs_inode *target, struct qstr *tstr)
764{
765 struct super_block *sb = parent->vfs_inode.i_sb;
766 struct pohmelfs_sb *psb = POHMELFS_SB(sb);
767 struct netfs_cmd *cmd;
768 struct netfs_trans *t;
769 void *data;
770 int err, parent_len, target_len = 0, cur_len, path_size = 0;
771
772 err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
773 if (err)
774 return err;
775
776 err = sb->s_op->write_inode(&parent->vfs_inode, 0);
777 if (err)
778 goto err_out_exit;
779
780 if (tstr)
781 target_len = tstr->len;
782
783 parent_len = pohmelfs_path_length(parent);
784 if (target)
785 target_len += pohmelfs_path_length(target);
786
787 if (parent_len < 0) {
788 err = parent_len;
789 goto err_out_exit;
790 }
791
792 if (target_len < 0) {
793 err = target_len;
794 goto err_out_exit;
795 }
796
797 t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0);
798 if (!t) {
799 err = -ENOMEM;
800 goto err_out_exit;
801 }
802 cur_len = netfs_trans_cur_len(t);
803
804 cmd = netfs_trans_current(t);
805 if (IS_ERR(cmd)) {
806 err = PTR_ERR(cmd);
807 goto err_out_free;
808 }
809
810 data = (void *)(cmd + 1);
811 cur_len -= sizeof(struct netfs_cmd);
812
813 err = pohmelfs_construct_path_string(parent, data, parent_len);
814 if (err > 0) {
815 /* Do not place null-byte before the slash */
816 path_size = err - 1;
817 cur_len -= path_size;
818
819 err = snprintf(data + path_size, cur_len, "/%s|", obj->name);
820
821 path_size += err;
822 cur_len -= err;
823
824 cmd->ext = path_size - 1; /* No | symbol */
825
826 if (target) {
827 err = pohmelfs_construct_path_string(target, data + path_size, target_len);
828 if (err > 0) {
829 path_size += err;
830 cur_len -= err;
831 }
832 }
833 }
834
835 if (err < 0)
836 goto err_out_free;
837
838 cmd->start = 0;
839
840 if (!target && tstr) {
841 if (tstr->len > cur_len - 1) {
842 err = -ENAMETOOLONG;
843 goto err_out_free;
844 }
845
846 err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */
847 path_size += err;
848 cur_len -= err;
849 cmd->start = 1;
850 }
851
852 dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
853 __func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL,
854 (char *)data);
855
856 cmd->cmd = NETFS_LINK;
857 cmd->size = path_size;
858 cmd->id = parent->ino;
859
860 netfs_convert_cmd(cmd);
861
862 netfs_trans_update(cmd, t, path_size);
863
864 err = netfs_trans_finish(t, psb);
865 if (err)
866 goto err_out_exit;
867
868 return 0;
869
870err_out_free:
871 t->result = err;
872 netfs_trans_put(t);
873err_out_exit:
874 return err;
875}
876
877/*
878 * VFS hard and soft link callbacks.
879 */
880static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir,
881 struct dentry *dentry)
882{
883 struct inode *inode = old_dentry->d_inode;
884 struct pohmelfs_inode *pi = POHMELFS_I(inode);
885 int err;
886 struct qstr str = dentry->d_name;
887
888 str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
889
890 err = inode->i_sb->s_op->write_inode(inode, 0);
891 if (err)
892 return err;
893
894 err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL);
895 if (err)
896 return err;
897
898 return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode);
899}
900
901static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
902{
903 struct qstr sym_str;
904 struct qstr str = dentry->d_name;
905 struct inode *inode;
906 int err;
907
908 str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
909
910 sym_str.name = symname;
911 sym_str.len = strlen(symname);
912
913 err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str);
914 if (err)
915 goto err_out_exit;
916
917 err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
918 if (err)
919 goto err_out_exit;
920
921 inode = dentry->d_inode;
922
923 err = page_symlink(inode, symname, sym_str.len + 1);
924 if (err)
925 goto err_out_put;
926
927 return 0;
928
929err_out_put:
930 iput(inode);
931err_out_exit:
932 return err;
933}
934
935static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent,
936 struct qstr *str)
937{
938 int path_len, err, total_len = 0, inode_len, parent_len;
939 char *path;
940 struct netfs_trans *t;
941 struct netfs_cmd *cmd;
942 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
943
944 parent_len = pohmelfs_path_length(parent);
945 inode_len = pohmelfs_path_length(pi);
946
947 if (parent_len < 0 || inode_len < 0)
948 return -EINVAL;
949
950 path_len = parent_len + inode_len + str->len + 3;
951
952 t = netfs_trans_alloc(psb, path_len, 0, 0);
953 if (!t)
954 return -ENOMEM;
955
956 cmd = netfs_trans_current(t);
957 path = (char *)(cmd + 1);
958
959 err = pohmelfs_construct_path_string(pi, path, inode_len);
960 if (err < 0)
961 goto err_out_unlock;
962
963 cmd->ext = err;
964
965 path += err;
966 total_len += err;
967 path_len -= err;
968
969 *path = '|';
970 path++;
971 total_len++;
972 path_len--;
973
974 err = pohmelfs_construct_path_string(parent, path, parent_len);
975 if (err < 0)
976 goto err_out_unlock;
977
978 /*
979 * Do not place a null-byte before the final slash and the name.
980 */
981 err--;
982 path += err;
983 total_len += err;
984 path_len -= err;
985
986 err = snprintf(path, path_len - 1, "/%s", str->name);
987
988 total_len += err + 1; /* 0 symbol */
989 path_len -= err + 1;
990
991 cmd->cmd = NETFS_RENAME;
992 cmd->id = pi->ino;
993 cmd->start = parent->ino;
994 cmd->size = total_len;
995
996 netfs_convert_cmd(cmd);
997
998 netfs_trans_update(cmd, t, total_len);
999
1000 return netfs_trans_finish(t, psb);
1001
1002err_out_unlock:
1003 netfs_trans_free(t);
1004 return err;
1005}
1006
1007static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1008 struct inode *new_dir, struct dentry *new_dentry)
1009{
1010 struct inode *inode = old_dentry->d_inode;
1011 struct pohmelfs_inode *old_parent, *pi, *new_parent;
1012 struct qstr str = new_dentry->d_name;
1013 struct pohmelfs_name *n;
1014 unsigned int old_hash;
1015 int err = -ENOENT;
1016
1017 pi = POHMELFS_I(inode);
1018 old_parent = POHMELFS_I(old_dir);
1019
1020 if (new_dir)
1021 new_dir->i_sb->s_op->write_inode(new_dir, 0);
1022
1023 old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
1024 str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
1025
1026 str.len = new_dentry->d_name.len;
1027 str.name = new_dentry->d_name.name;
1028 str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
1029
1030 if (new_dir) {
1031 new_parent = POHMELFS_I(new_dir);
1032 err = -ENOTEMPTY;
1033
1034 if (S_ISDIR(inode->i_mode) &&
1035 new_parent->total_len <= 3)
1036 goto err_out_exit;
1037 } else {
1038 new_parent = old_parent;
1039 }
1040
1041 dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
1042 __func__, pi->ino, old_parent->ino, old_dentry->d_name.name,
1043 new_parent->ino, new_dentry->d_name.name, inode->i_size);
1044
1045 if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) &&
1046 test_bit(NETFS_INODE_OWNED, &pi->state)) {
1047 err = pohmelfs_send_rename(pi, new_parent, &str);
1048 if (err)
1049 goto err_out_exit;
1050 }
1051
1052 n = pohmelfs_name_alloc(str.len + 1);
1053 if (!n)
1054 goto err_out_exit;
1055
1056 mutex_lock(&new_parent->offset_lock);
1057 n->ino = pi->ino;
1058 n->mode = inode->i_mode;
1059 n->len = str.len;
1060 n->hash = str.hash;
1061 sprintf(n->data, "%s", str.name);
1062
1063 err = pohmelfs_insert_name(new_parent, n);
1064 mutex_unlock(&new_parent->offset_lock);
1065
1066 if (err)
1067 goto err_out_exit;
1068
1069 mutex_lock(&old_parent->offset_lock);
1070 n = pohmelfs_search_hash(old_parent, old_hash);
1071 if (n)
1072 pohmelfs_name_del(old_parent, n);
1073 mutex_unlock(&old_parent->offset_lock);
1074
1075 mark_inode_dirty(inode);
1076 mark_inode_dirty(&new_parent->vfs_inode);
1077
1078 WARN_ON_ONCE(list_empty(&inode->i_dentry));
1079
1080 return 0;
1081
1082err_out_exit:
1083
1084 clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
1085
1086 return err;
1087}
1088
1089/*
1090 * POHMELFS directory inode operations.
1091 */
1092const struct inode_operations pohmelfs_dir_inode_ops = {
1093 .link = pohmelfs_link,
1094 .symlink = pohmelfs_symlink,
1095 .unlink = pohmelfs_unlink,
1096 .mkdir = pohmelfs_mkdir,
1097 .rmdir = pohmelfs_rmdir,
1098 .create = pohmelfs_create,
1099 .lookup = pohmelfs_lookup,
1100 .setattr = pohmelfs_setattr,
1101 .rename = pohmelfs_rename,
1102};
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
deleted file mode 100644
index 807e3f32411..00000000000
--- a/drivers/staging/pohmelfs/inode.c
+++ /dev/null
@@ -1,2055 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/module.h>
17#include <linux/backing-dev.h>
18#include <linux/crypto.h>
19#include <linux/fs.h>
20#include <linux/jhash.h>
21#include <linux/hash.h>
22#include <linux/ktime.h>
23#include <linux/mm.h>
24#include <linux/mount.h>
25#include <linux/pagemap.h>
26#include <linux/pagevec.h>
27#include <linux/parser.h>
28#include <linux/swap.h>
29#include <linux/slab.h>
30#include <linux/statfs.h>
31#include <linux/writeback.h>
32#include <linux/prefetch.h>
33
34#include "netfs.h"
35
36#define POHMELFS_MAGIC_NUM 0x504f482e
37
38static struct kmem_cache *pohmelfs_inode_cache;
39static atomic_t psb_bdi_num = ATOMIC_INIT(0);
40
41/*
42 * Removes inode from all trees, drops local name cache and removes all queued
43 * requests for object removal.
44 */
45void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi)
46{
47 mutex_lock(&pi->offset_lock);
48 pohmelfs_free_names(pi);
49 mutex_unlock(&pi->offset_lock);
50
51 dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino);
52}
53
54/*
55 * Sync inode to server.
56 * Returns zero in success and negative error value otherwise.
57 * It will gather path to root directory into structures containing
58 * creation mode, permissions and names, so that the whole path
59 * to given inode could be created using only single network command.
60 */
61int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans)
62{
63 struct pohmelfs_inode *pi = POHMELFS_I(inode);
64 int err = -ENOMEM, size;
65 struct netfs_cmd *cmd;
66 void *data;
67 int cur_len = netfs_trans_cur_len(trans);
68
69 if (unlikely(cur_len < 0))
70 return -ETOOSMALL;
71
72 cmd = netfs_trans_current(trans);
73 cur_len -= sizeof(struct netfs_cmd);
74
75 data = (void *)(cmd + 1);
76
77 err = pohmelfs_construct_path_string(pi, data, cur_len);
78 if (err < 0)
79 goto err_out_exit;
80
81 size = err;
82
83 cmd->start = i_size_read(inode);
84 cmd->cmd = NETFS_CREATE;
85 cmd->size = size;
86 cmd->id = pi->ino;
87 cmd->ext = inode->i_mode;
88
89 netfs_convert_cmd(cmd);
90
91 netfs_trans_update(cmd, trans, size);
92
93 return 0;
94
95err_out_exit:
96 printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err);
97 return err;
98}
99
100static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num,
101 void *private, int err)
102{
103 unsigned i;
104
105 dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n",
106 __func__, pages[0]->index, pages[page_num-1]->index,
107 page_num, err);
108
109 for (i = 0; i < page_num; i++) {
110 struct page *page = pages[i];
111
112 if (!page)
113 continue;
114
115 end_page_writeback(page);
116
117 if (err < 0) {
118 SetPageError(page);
119 set_page_dirty(page);
120 }
121
122 unlock_page(page);
123 page_cache_release(page);
124
125 /* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */
126 }
127 return err;
128}
129
130static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index)
131{
132 int ret;
133 struct page *page;
134
135 rcu_read_lock();
136 ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
137 (void **)&page, index, 1, PAGECACHE_TAG_DIRTY);
138 rcu_read_unlock();
139 return ret;
140}
141
142static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
143{
144 struct inode *inode = mapping->host;
145 struct pohmelfs_inode *pi = POHMELFS_I(inode);
146 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
147 int err = 0;
148 int done = 0;
149 int nr_pages;
150 pgoff_t index;
151 pgoff_t end; /* Inclusive */
152 int scanned = 0;
153 int range_whole = 0;
154
155 if (wbc->range_cyclic) {
156 index = mapping->writeback_index; /* Start from prev offset */
157 end = -1;
158 } else {
159 index = wbc->range_start >> PAGE_CACHE_SHIFT;
160 end = wbc->range_end >> PAGE_CACHE_SHIFT;
161 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
162 range_whole = 1;
163 scanned = 1;
164 }
165retry:
166 while (!done && (index <= end)) {
167 unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages);
168 int path_len;
169 struct netfs_trans *trans;
170
171 err = pohmelfs_inode_has_dirty_pages(mapping, index);
172 if (!err)
173 break;
174
175 err = pohmelfs_path_length(pi);
176 if (err < 0)
177 break;
178
179 path_len = err;
180
181 if (path_len <= 2) {
182 err = -ENOENT;
183 break;
184 }
185
186 trans = netfs_trans_alloc(psb, path_len, 0, i);
187 if (!trans) {
188 err = -ENOMEM;
189 break;
190 }
191 trans->complete = &pohmelfs_write_trans_complete;
192
193 trans->page_num = nr_pages = find_get_pages_tag(mapping, &index,
194 PAGECACHE_TAG_DIRTY, trans->page_num,
195 trans->pages);
196
197 dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n",
198 __func__, trans, nr_pages, end, index, trans->page_num);
199
200 if (!nr_pages)
201 goto err_out_reset;
202
203 err = pohmelfs_write_inode_create(inode, trans);
204 if (err)
205 goto err_out_reset;
206
207 err = 0;
208 scanned = 1;
209
210 for (i = 0; i < trans->page_num; i++) {
211 struct page *page = trans->pages[i];
212
213 lock_page(page);
214
215 if (unlikely(page->mapping != mapping))
216 goto out_continue;
217
218 if (!wbc->range_cyclic && page->index > end) {
219 done = 1;
220 goto out_continue;
221 }
222
223 if (wbc->sync_mode != WB_SYNC_NONE)
224 wait_on_page_writeback(page);
225
226 if (PageWriteback(page) ||
227 !clear_page_dirty_for_io(page)) {
228 dprintk("%s: not clear for io page: %p, writeback: %d.\n",
229 __func__, page, PageWriteback(page));
230 goto out_continue;
231 }
232
233 set_page_writeback(page);
234
235 trans->attached_size += page_private(page);
236 trans->attached_pages++;
237#if 0
238 dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n",
239 __func__, i, trans->page_num, trans, trans->gen, page,
240 !!PageHighMem(page), page_private(page), page->index);
241#endif
242 wbc->nr_to_write--;
243
244 if (wbc->nr_to_write <= 0)
245 done = 1;
246
247 continue;
248out_continue:
249 unlock_page(page);
250 trans->pages[i] = NULL;
251 }
252
253 err = netfs_trans_finish(trans, psb);
254 if (err)
255 break;
256
257 continue;
258
259err_out_reset:
260 trans->result = err;
261 netfs_trans_reset(trans);
262 netfs_trans_put(trans);
263 break;
264 }
265
266 if (!scanned && !done) {
267 /*
268 * We hit the last page and there is more work to be done: wrap
269 * back to the start of the file
270 */
271 scanned = 1;
272 index = 0;
273 goto retry;
274 }
275
276 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
277 mapping->writeback_index = index;
278
279 return err;
280}
281
282/*
283 * Inode writeback creation completion callback.
284 * Only invoked for just created inodes, which do not have pages attached,
285 * like dirs and empty files.
286 */
287static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num,
288 void *private, int err)
289{
290 struct inode *inode = private;
291 struct pohmelfs_inode *pi = POHMELFS_I(inode);
292
293 if (inode) {
294 if (err) {
295 mark_inode_dirty(inode);
296 clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
297 } else {
298 set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
299 }
300
301 pohmelfs_put_inode(pi);
302 }
303
304 return err;
305}
306
307int pohmelfs_write_create_inode(struct pohmelfs_inode *pi)
308{
309 struct netfs_trans *t;
310 struct inode *inode = &pi->vfs_inode;
311 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
312 int err;
313
314 if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
315 return 0;
316
317 dprintk("%s: started ino: %llu.\n", __func__, pi->ino);
318
319 err = pohmelfs_path_length(pi);
320 if (err < 0)
321 goto err_out_exit;
322
323 t = netfs_trans_alloc(psb, err + 1, 0, 0);
324 if (!t) {
325 err = -ENOMEM;
326 goto err_out_exit;
327 }
328 t->complete = pohmelfs_write_inode_complete;
329 t->private = igrab(inode);
330 if (!t->private) {
331 err = -ENOENT;
332 goto err_out_put;
333 }
334
335 err = pohmelfs_write_inode_create(inode, t);
336 if (err)
337 goto err_out_put;
338
339 netfs_trans_finish(t, POHMELFS_SB(inode->i_sb));
340
341 return 0;
342
343err_out_put:
344 t->result = err;
345 netfs_trans_put(t);
346err_out_exit:
347 return err;
348}
349
350/*
351 * Sync all not-yet-created children in given directory to the server.
352 */
353static int pohmelfs_write_inode_create_children(struct inode *inode)
354{
355 struct pohmelfs_inode *parent = POHMELFS_I(inode);
356 struct super_block *sb = inode->i_sb;
357 struct pohmelfs_name *n;
358
359 while (!list_empty(&parent->sync_create_list)) {
360 n = NULL;
361 mutex_lock(&parent->offset_lock);
362 if (!list_empty(&parent->sync_create_list)) {
363 n = list_first_entry(&parent->sync_create_list,
364 struct pohmelfs_name, sync_create_entry);
365 list_del_init(&n->sync_create_entry);
366 }
367 mutex_unlock(&parent->offset_lock);
368
369 if (!n)
370 break;
371
372 inode = ilookup(sb, n->ino);
373
374 dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n",
375 __func__, parent->ino, n->ino, inode);
376
377 if (inode && (inode->i_state & I_DIRTY)) {
378 struct pohmelfs_inode *pi = POHMELFS_I(inode);
379 pohmelfs_write_create_inode(pi);
380 /* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */
381 iput(inode);
382 }
383 }
384
385 return 0;
386}
387
388/*
389 * Removes given child from given inode on server.
390 */
391int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n)
392{
393 return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0);
394}
395
396/*
397 * Writeback for given inode.
398 */
399static int pohmelfs_write_inode(struct inode *inode,
400 struct writeback_control *wbc)
401{
402 struct pohmelfs_inode *pi = POHMELFS_I(inode);
403
404 pohmelfs_write_create_inode(pi);
405 pohmelfs_write_inode_create_children(inode);
406
407 return 0;
408}
409
410/*
411 * It is not exported, sorry...
412 */
413static inline wait_queue_head_t *page_waitqueue(struct page *page)
414{
415 const struct zone *zone = page_zone(page);
416
417 return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
418}
419
420static int pohmelfs_wait_on_page_locked(struct page *page)
421{
422 struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb);
423 long ret = psb->wait_on_page_timeout;
424 DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
425 int err = 0;
426
427 if (!PageLocked(page))
428 return 0;
429
430 for (;;) {
431 prepare_to_wait(page_waitqueue(page),
432 &wait.wait, TASK_INTERRUPTIBLE);
433
434 dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n",
435 __func__, page, PageLocked(page), PageUptodate(page),
436 PageError(page), page->flags);
437
438 if (!PageLocked(page))
439 break;
440
441 if (!signal_pending(current)) {
442 ret = schedule_timeout(ret);
443 if (!ret)
444 break;
445 continue;
446 }
447 ret = -ERESTARTSYS;
448 break;
449 }
450 finish_wait(page_waitqueue(page), &wait.wait);
451
452 if (!ret)
453 err = -ETIMEDOUT;
454
455
456 if (!err)
457 SetPageUptodate(page);
458
459 if (err)
460 printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n",
461 __func__, page, PageUptodate(page), PageLocked(page), err);
462
463 return err;
464}
465
466static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num,
467 void *private, int err)
468{
469 struct page *page = private;
470
471 if (PageChecked(page))
472 return err;
473
474 if (err < 0) {
475 dprintk("%s: page: %p, err: %d.\n", __func__, page, err);
476 SetPageError(page);
477 }
478
479 unlock_page(page);
480
481 return err;
482}
483
484/*
485 * Read a page from remote server.
486 * Function will wait until page is unlocked.
487 */
488static int pohmelfs_readpage(struct file *file, struct page *page)
489{
490 struct inode *inode = page->mapping->host;
491 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
492 struct pohmelfs_inode *pi = POHMELFS_I(inode);
493 struct netfs_trans *t;
494 struct netfs_cmd *cmd;
495 int err, path_len;
496 void *data;
497 u64 isize;
498
499 err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT,
500 PAGE_SIZE, POHMELFS_READ_LOCK);
501 if (err)
502 goto err_out_exit;
503
504 isize = i_size_read(inode);
505 if (isize <= page->index << PAGE_CACHE_SHIFT) {
506 SetPageUptodate(page);
507 unlock_page(page);
508 return 0;
509 }
510
511 path_len = pohmelfs_path_length(pi);
512 if (path_len < 0) {
513 err = path_len;
514 goto err_out_exit;
515 }
516
517 t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
518 if (!t) {
519 err = -ENOMEM;
520 goto err_out_exit;
521 }
522
523 t->complete = pohmelfs_read_page_complete;
524 t->private = page;
525
526 cmd = netfs_trans_current(t);
527 data = (void *)(cmd + 1);
528
529 err = pohmelfs_construct_path_string(pi, data, path_len);
530 if (err < 0)
531 goto err_out_free;
532
533 path_len = err;
534
535 cmd->id = pi->ino;
536 cmd->start = page->index;
537 cmd->start <<= PAGE_CACHE_SHIFT;
538 cmd->size = PAGE_CACHE_SIZE + path_len;
539 cmd->cmd = NETFS_READ_PAGE;
540 cmd->ext = path_len;
541
542 dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n",
543 __func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE);
544
545 netfs_convert_cmd(cmd);
546 netfs_trans_update(cmd, t, path_len);
547
548 err = netfs_trans_finish(t, psb);
549 if (err)
550 goto err_out_return;
551
552 return pohmelfs_wait_on_page_locked(page);
553
554err_out_free:
555 t->result = err;
556 netfs_trans_put(t);
557err_out_exit:
558 SetPageError(page);
559 if (PageLocked(page))
560 unlock_page(page);
561err_out_return:
562 printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n",
563 __func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err);
564
565 return err;
566}
567
568/*
569 * Write begin/end magic.
570 * Allocates a page and writes inode if it was not synced to server before.
571 */
572static int pohmelfs_write_begin(struct file *file, struct address_space *mapping,
573 loff_t pos, unsigned len, unsigned flags,
574 struct page **pagep, void **fsdata)
575{
576 struct inode *inode = mapping->host;
577 struct page *page;
578 pgoff_t index;
579 unsigned start, end;
580 int err;
581
582 *pagep = NULL;
583
584 index = pos >> PAGE_CACHE_SHIFT;
585 start = pos & (PAGE_CACHE_SIZE - 1);
586 end = start + len;
587
588 page = grab_cache_page(mapping, index);
589#if 0
590 dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n",
591 __func__, page, pos, len, index, start, end, PageUptodate(page));
592#endif
593 if (!page) {
594 err = -ENOMEM;
595 goto err_out_exit;
596 }
597
598 while (!PageUptodate(page)) {
599 if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) {
600 err = pohmelfs_readpage(file, page);
601 if (err)
602 goto err_out_exit;
603
604 lock_page(page);
605 continue;
606 }
607
608 if (len != PAGE_CACHE_SIZE) {
609 void *kaddr = kmap_atomic(page, KM_USER0);
610
611 memset(kaddr + start, 0, PAGE_CACHE_SIZE - start);
612 flush_dcache_page(page);
613 kunmap_atomic(kaddr, KM_USER0);
614 }
615 SetPageUptodate(page);
616 }
617
618 set_page_private(page, end);
619
620 *pagep = page;
621
622 return 0;
623
624err_out_exit:
625 page_cache_release(page);
626 *pagep = NULL;
627
628 return err;
629}
630
631static int pohmelfs_write_end(struct file *file, struct address_space *mapping,
632 loff_t pos, unsigned len, unsigned copied,
633 struct page *page, void *fsdata)
634{
635 struct inode *inode = mapping->host;
636
637 if (copied != len) {
638 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
639 void *kaddr = kmap_atomic(page, KM_USER0);
640
641 memset(kaddr + from + copied, 0, len - copied);
642 flush_dcache_page(page);
643 kunmap_atomic(kaddr, KM_USER0);
644 }
645
646 SetPageUptodate(page);
647 set_page_dirty(page);
648#if 0
649 dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n",
650 __func__, page,
651 PageUptodate(page), PageDirty(page), PageLocked(page),
652 pos, len, copied);
653#endif
654 flush_dcache_page(page);
655
656 unlock_page(page);
657 page_cache_release(page);
658
659 if (pos + copied > inode->i_size) {
660 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
661
662 psb->avail_size -= pos + copied - inode->i_size;
663
664 i_size_write(inode, pos + copied);
665 }
666
667 return copied;
668}
669
670static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num,
671 void *private, int err)
672{
673 struct pohmelfs_inode *pi = private;
674 unsigned int i, num;
675 struct page **pages, *page = (struct page *)__pages;
676 loff_t index = page->index;
677
678 pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO);
679 if (!pages)
680 return -ENOMEM;
681
682 num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages);
683 if (num <= 0) {
684 err = num;
685 goto err_out_free;
686 }
687
688 for (i = 0; i < num; ++i) {
689 page = pages[i];
690
691 if (err)
692 printk("%s: %u/%u: page: %p, index: %lu, uptodate: %d, locked: %d, err: %d.\n",
693 __func__, i, num, page, page->index,
694 PageUptodate(page), PageLocked(page), err);
695
696 if (!PageChecked(page)) {
697 if (err < 0)
698 SetPageError(page);
699 unlock_page(page);
700 }
701 page_cache_release(page);
702 page_cache_release(page);
703 }
704
705err_out_free:
706 kfree(pages);
707 return err;
708}
709
710static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num)
711{
712 struct netfs_trans *t;
713 struct netfs_cmd *cmd;
714 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
715 int err, path_len;
716 void *data;
717
718 err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT,
719 num * PAGE_SIZE, POHMELFS_READ_LOCK);
720 if (err)
721 goto err_out_exit;
722
723 path_len = pohmelfs_path_length(pi);
724 if (path_len < 0) {
725 err = path_len;
726 goto err_out_exit;
727 }
728
729 t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
730 if (!t) {
731 err = -ENOMEM;
732 goto err_out_exit;
733 }
734
735 cmd = netfs_trans_current(t);
736 data = (void *)(cmd + 1);
737
738 t->complete = pohmelfs_readpages_trans_complete;
739 t->private = pi;
740 t->page_num = num;
741 t->pages = (struct page **)first;
742
743 err = pohmelfs_construct_path_string(pi, data, path_len);
744 if (err < 0)
745 goto err_out_put;
746
747 path_len = err;
748
749 cmd->cmd = NETFS_READ_PAGES;
750 cmd->start = first->index;
751 cmd->start <<= PAGE_CACHE_SHIFT;
752 cmd->size = (num << 8 | PAGE_CACHE_SHIFT);
753 cmd->id = pi->ino;
754 cmd->ext = path_len;
755
756 dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, "
757 "start: %lu, num: %u.\n",
758 __func__, t, t->gen, (char *)data, path_len,
759 first->index, num);
760
761 netfs_convert_cmd(cmd);
762 netfs_trans_update(cmd, t, path_len);
763
764 return netfs_trans_finish(t, psb);
765
766err_out_put:
767 netfs_trans_free(t);
768err_out_exit:
769 pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err);
770 return err;
771}
772
773#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
774
775static int pohmelfs_readpages(struct file *file, struct address_space *mapping,
776 struct list_head *pages, unsigned nr_pages)
777{
778 unsigned int page_idx, num = 0;
779 struct page *page = NULL, *first = NULL;
780
781 for (page_idx = 0; page_idx < nr_pages; page_idx++) {
782 page = list_to_page(pages);
783
784 prefetchw(&page->flags);
785 list_del(&page->lru);
786
787 if (!add_to_page_cache_lru(page, mapping,
788 page->index, GFP_KERNEL)) {
789
790 if (!num) {
791 num = 1;
792 first = page;
793 continue;
794 }
795
796 dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n",
797 __func__, page, page->index, first->index);
798
799 if (unlikely(first->index + num != page->index) || (num > 500)) {
800 pohmelfs_send_readpages(POHMELFS_I(mapping->host),
801 first, num);
802 first = page;
803 num = 0;
804 }
805
806 num++;
807 }
808 }
809 pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num);
810
811 /*
812 * This will be sync read, so when last page is processed,
813 * all previous are alerady unlocked and ready to be used.
814 */
815 return 0;
816}
817
818/*
819 * Small address space operations for POHMELFS.
820 */
821const struct address_space_operations pohmelfs_aops = {
822 .readpage = pohmelfs_readpage,
823 .readpages = pohmelfs_readpages,
824 .writepages = pohmelfs_writepages,
825 .write_begin = pohmelfs_write_begin,
826 .write_end = pohmelfs_write_end,
827 .set_page_dirty = __set_page_dirty_nobuffers,
828};
829
830static void pohmelfs_i_callback(struct rcu_head *head)
831{
832 struct inode *inode = container_of(head, struct inode, i_rcu);
833 kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode));
834}
835
836/*
837 * ->destroy_inode() callback. Deletes inode from the caches
838 * and frees private data.
839 */
840static void pohmelfs_destroy_inode(struct inode *inode)
841{
842 struct super_block *sb = inode->i_sb;
843 struct pohmelfs_sb *psb = POHMELFS_SB(sb);
844 struct pohmelfs_inode *pi = POHMELFS_I(inode);
845
846 /* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */
847
848 pohmelfs_inode_del_inode(psb, pi);
849
850 dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
851 __func__, pi, &pi->vfs_inode, pi->ino);
852 atomic_long_dec(&psb->total_inodes);
853 call_rcu(&inode->i_rcu, pohmelfs_i_callback);
854}
855
856/*
857 * ->alloc_inode() callback. Allocates inode and initializes private data.
858 */
859static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
860{
861 struct pohmelfs_inode *pi;
862
863 pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO);
864 if (!pi)
865 return NULL;
866
867 pi->hash_root = RB_ROOT;
868 mutex_init(&pi->offset_lock);
869
870 INIT_LIST_HEAD(&pi->sync_create_list);
871
872 INIT_LIST_HEAD(&pi->inode_entry);
873
874 pi->lock_type = 0;
875 pi->state = 0;
876 pi->total_len = 0;
877 pi->drop_count = 0;
878
879 dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode);
880
881 atomic_long_inc(&POHMELFS_SB(sb)->total_inodes);
882
883 return &pi->vfs_inode;
884}
885
886/*
887 * We want fsync() to work on POHMELFS.
888 */
889static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
890{
891 struct inode *inode = file->f_mapping->host;
892 int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
893 if (!err) {
894 mutex_lock(&inode->i_mutex);
895 err = sync_inode_metadata(inode, 1);
896 mutex_unlock(&inode->i_mutex);
897 }
898 return err;
899}
900
901ssize_t pohmelfs_write(struct file *file, const char __user *buf,
902 size_t len, loff_t *ppos)
903{
904 struct address_space *mapping = file->f_mapping;
905 struct inode *inode = mapping->host;
906 struct pohmelfs_inode *pi = POHMELFS_I(inode);
907 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
908 struct kiocb kiocb;
909 ssize_t ret;
910 loff_t pos = *ppos;
911
912 init_sync_kiocb(&kiocb, file);
913 kiocb.ki_pos = pos;
914 kiocb.ki_left = len;
915
916 dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos);
917
918 mutex_lock(&inode->i_mutex);
919 ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK);
920 if (ret)
921 goto err_out_unlock;
922
923 ret = __generic_file_aio_write(&kiocb, &iov, 1, &kiocb.ki_pos);
924 *ppos = kiocb.ki_pos;
925
926 mutex_unlock(&inode->i_mutex);
927 WARN_ON(ret < 0);
928
929 if (ret > 0) {
930 ssize_t err;
931
932 err = generic_write_sync(file, pos, ret);
933 if (err < 0)
934 ret = err;
935 WARN_ON(ret < 0);
936 }
937
938 return ret;
939
940err_out_unlock:
941 mutex_unlock(&inode->i_mutex);
942 return ret;
943}
944
945static const struct file_operations pohmelfs_file_ops = {
946 .open = generic_file_open,
947 .fsync = pohmelfs_fsync,
948
949 .llseek = generic_file_llseek,
950
951 .read = do_sync_read,
952 .aio_read = generic_file_aio_read,
953
954 .mmap = generic_file_mmap,
955
956 .splice_read = generic_file_splice_read,
957 .splice_write = generic_file_splice_write,
958
959 .write = pohmelfs_write,
960 .aio_write = generic_file_aio_write,
961};
962
963const struct inode_operations pohmelfs_symlink_inode_operations = {
964 .readlink = generic_readlink,
965 .follow_link = page_follow_link_light,
966 .put_link = page_put_link,
967};
968
969int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr)
970{
971 int err;
972
973 err = inode_change_ok(inode, attr);
974 if (err) {
975 dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino);
976 goto err_out_exit;
977 }
978
979 if ((attr->ia_valid & ATTR_SIZE) &&
980 attr->ia_size != i_size_read(inode)) {
981 err = vmtruncate(inode, attr->ia_size);
982 if (err) {
983 dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
984 goto err_out_exit;
985 }
986 }
987
988 setattr_copy(inode, attr);
989 mark_inode_dirty(inode);
990
991 dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n",
992 __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode,
993 inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size);
994
995 return 0;
996
997err_out_exit:
998 return err;
999}
1000
1001int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr)
1002{
1003 struct inode *inode = dentry->d_inode;
1004 struct pohmelfs_inode *pi = POHMELFS_I(inode);
1005 int err;
1006
1007 err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
1008 if (err)
1009 goto err_out_exit;
1010
1011 err = security_inode_setattr(dentry, attr);
1012 if (err)
1013 goto err_out_exit;
1014
1015 err = pohmelfs_setattr_raw(inode, attr);
1016 if (err)
1017 goto err_out_exit;
1018
1019 return 0;
1020
1021err_out_exit:
1022 return err;
1023}
1024
1025static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start,
1026 const char *name, const void *value, size_t attrsize, int command)
1027{
1028 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
1029 int err, path_len, namelen = strlen(name) + 1; /* 0-byte */
1030 struct netfs_trans *t;
1031 struct netfs_cmd *cmd;
1032 void *data;
1033
1034 dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n",
1035 __func__, id, start, name, attrsize, command);
1036
1037 path_len = pohmelfs_path_length(pi);
1038 if (path_len < 0) {
1039 err = path_len;
1040 goto err_out_exit;
1041 }
1042
1043 t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0);
1044 if (!t) {
1045 err = -ENOMEM;
1046 goto err_out_exit;
1047 }
1048
1049 cmd = netfs_trans_current(t);
1050 data = cmd + 1;
1051
1052 path_len = pohmelfs_construct_path_string(pi, data, path_len);
1053 if (path_len < 0) {
1054 err = path_len;
1055 goto err_out_put;
1056 }
1057 data += path_len;
1058
1059 /*
1060 * 'name' is a NUL-terminated string already and
1061 * 'namelen' includes 0-byte.
1062 */
1063 memcpy(data, name, namelen);
1064 data += namelen;
1065
1066 memcpy(data, value, attrsize);
1067
1068 cmd->cmd = command;
1069 cmd->id = id;
1070 cmd->start = start;
1071 cmd->size = attrsize + namelen + path_len;
1072 cmd->ext = path_len;
1073 cmd->csize = 0;
1074 cmd->cpad = 0;
1075
1076 netfs_convert_cmd(cmd);
1077 netfs_trans_update(cmd, t, namelen + path_len + attrsize);
1078
1079 return netfs_trans_finish(t, psb);
1080
1081err_out_put:
1082 t->result = err;
1083 netfs_trans_put(t);
1084err_out_exit:
1085 return err;
1086}
1087
1088static int pohmelfs_setxattr(struct dentry *dentry, const char *name,
1089 const void *value, size_t attrsize, int flags)
1090{
1091 struct inode *inode = dentry->d_inode;
1092 struct pohmelfs_inode *pi = POHMELFS_I(inode);
1093 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
1094
1095 if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
1096 return -EOPNOTSUPP;
1097
1098 return pohmelfs_send_xattr_req(pi, flags, attrsize, name,
1099 value, attrsize, NETFS_XATTR_SET);
1100}
1101
1102static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name,
1103 void *value, size_t attrsize)
1104{
1105 struct inode *inode = dentry->d_inode;
1106 struct pohmelfs_inode *pi = POHMELFS_I(inode);
1107 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
1108 struct pohmelfs_mcache *m;
1109 int err;
1110 long timeout = psb->mcache_timeout;
1111
1112 if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
1113 return -EOPNOTSUPP;
1114
1115 m = pohmelfs_mcache_alloc(psb, 0, attrsize, value);
1116 if (IS_ERR(m))
1117 return PTR_ERR(m);
1118
1119 dprintk("%s: ino: %llu, name: '%s', size: %zu.\n",
1120 __func__, pi->ino, name, attrsize);
1121
1122 err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET);
1123 if (err)
1124 goto err_out_put;
1125
1126 do {
1127 err = wait_for_completion_timeout(&m->complete, timeout);
1128 if (err) {
1129 err = m->err;
1130 break;
1131 }
1132
1133 /*
1134 * This loop is a bit ugly, since it waits until reference counter
1135 * hits 1 and then puts the object here. Main goal is to prevent race with
1136 * the network thread, when it can start processing the given request, i.e.
1137 * increase its reference counter but yet not complete it, while
1138 * we will exit from ->getxattr() with timeout, and although request
1139 * will not be freed (its reference counter was increased by network
1140 * thread), data pointer provided by user may be released, so we will
1141 * overwrite an already freed area in the network thread.
1142 *
1143 * Now after timeout we remove request from the cache, so it can not be
1144 * found by network thread, and wait for its reference counter to hit 1,
1145 * i.e. if network thread already started to process this request, we wait
1146 * for it to finish, and then free object locally. If reference counter is
1147 * already 1, i.e. request is not used by anyone else, we can free it without
1148 * problem.
1149 */
1150 err = -ETIMEDOUT;
1151 timeout = HZ;
1152
1153 pohmelfs_mcache_remove_locked(psb, m);
1154 } while (atomic_read(&m->refcnt) != 1);
1155
1156 pohmelfs_mcache_put(psb, m);
1157
1158 dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
1159
1160 return err;
1161
1162err_out_put:
1163 pohmelfs_mcache_put(psb, m);
1164 return err;
1165}
1166
1167static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1168{
1169 struct inode *inode = dentry->d_inode;
1170#if 0
1171 struct pohmelfs_inode *pi = POHMELFS_I(inode);
1172 int err;
1173
1174 err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
1175 if (err)
1176 return err;
1177 dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n",
1178 __func__, pi->ino, inode->i_mode, inode->i_uid,
1179 inode->i_gid, inode->i_size);
1180#endif
1181
1182 generic_fillattr(inode, stat);
1183 return 0;
1184}
1185
1186const struct inode_operations pohmelfs_file_inode_operations = {
1187 .setattr = pohmelfs_setattr,
1188 .getattr = pohmelfs_getattr,
1189 .setxattr = pohmelfs_setxattr,
1190 .getxattr = pohmelfs_getxattr,
1191};
1192
1193/*
1194 * Fill inode data: mode, size, operation callbacks and so on...
1195 */
1196void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
1197{
1198 inode->i_mode = info->mode;
1199 set_nlink(inode, info->nlink);
1200 inode->i_uid = info->uid;
1201 inode->i_gid = info->gid;
1202 inode->i_blocks = info->blocks;
1203 inode->i_rdev = info->rdev;
1204 inode->i_size = info->size;
1205 inode->i_version = info->version;
1206 inode->i_blkbits = ffs(info->blocksize);
1207
1208 dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n",
1209 __func__, inode, inode->i_ino, info->ino,
1210 S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode),
1211 S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size);
1212
1213 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
1214
1215 /*
1216 * i_mapping is a pointer to i_data during inode initialization.
1217 */
1218 inode->i_data.a_ops = &pohmelfs_aops;
1219
1220 if (S_ISREG(inode->i_mode)) {
1221 inode->i_fop = &pohmelfs_file_ops;
1222 inode->i_op = &pohmelfs_file_inode_operations;
1223 } else if (S_ISDIR(inode->i_mode)) {
1224 inode->i_fop = &pohmelfs_dir_fops;
1225 inode->i_op = &pohmelfs_dir_inode_ops;
1226 } else if (S_ISLNK(inode->i_mode)) {
1227 inode->i_op = &pohmelfs_symlink_inode_operations;
1228 inode->i_fop = &pohmelfs_file_ops;
1229 } else {
1230 inode->i_fop = &generic_ro_fops;
1231 }
1232}
1233
1234static int pohmelfs_drop_inode(struct inode *inode)
1235{
1236 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
1237 struct pohmelfs_inode *pi = POHMELFS_I(inode);
1238
1239 spin_lock(&psb->ino_lock);
1240 list_del_init(&pi->inode_entry);
1241 spin_unlock(&psb->ino_lock);
1242
1243 return generic_drop_inode(inode);
1244}
1245
1246static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
1247 struct list_head *head, unsigned int *count)
1248{
1249 struct pohmelfs_inode *pi = NULL;
1250
1251 spin_lock(&psb->ino_lock);
1252 if (!list_empty(head)) {
1253 pi = list_entry(head->next, struct pohmelfs_inode,
1254 inode_entry);
1255 list_del_init(&pi->inode_entry);
1256 *count = pi->drop_count;
1257 pi->drop_count = 0;
1258 }
1259 spin_unlock(&psb->ino_lock);
1260
1261 return pi;
1262}
1263
1264static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb)
1265{
1266 struct pohmelfs_config *c;
1267
1268 mutex_lock(&psb->state_lock);
1269 list_for_each_entry(c, &psb->state_list, config_entry) {
1270 pohmelfs_state_flush_transactions(&c->state);
1271 }
1272 mutex_unlock(&psb->state_lock);
1273}
1274
1275/*
1276 * ->put_super() callback. Invoked before superblock is destroyed,
1277 * so it has to clean all private data.
1278 */
1279static void pohmelfs_put_super(struct super_block *sb)
1280{
1281 struct pohmelfs_sb *psb = POHMELFS_SB(sb);
1282 struct pohmelfs_inode *pi;
1283 unsigned int count = 0;
1284 unsigned int in_drop_list = 0;
1285 struct inode *inode, *tmp;
1286
1287 dprintk("%s.\n", __func__);
1288
1289 /*
1290 * Kill pending transactions, which could affect inodes in-flight.
1291 */
1292 pohmelfs_flush_transactions(psb);
1293
1294 while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) {
1295 inode = &pi->vfs_inode;
1296
1297 dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
1298 __func__, pi->ino, pi, inode, count);
1299
1300 if (atomic_read(&inode->i_count) != count) {
1301 printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n",
1302 __func__, pi->ino, pi, inode, count,
1303 atomic_read(&inode->i_count));
1304 count = atomic_read(&inode->i_count);
1305 in_drop_list++;
1306 }
1307
1308 while (count--)
1309 iput(&pi->vfs_inode);
1310 }
1311
1312 list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) {
1313 pi = POHMELFS_I(inode);
1314
1315 dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n",
1316 __func__, pi->ino, pi, inode, atomic_read(&inode->i_count));
1317
1318 /*
1319 * These are special inodes, they were created during
1320 * directory reading or lookup, and were not bound to dentry,
1321 * so they live here with reference counter being 1 and prevent
1322 * umount from succeed since it believes that they are busy.
1323 */
1324 count = atomic_read(&inode->i_count);
1325 if (count) {
1326 list_del_init(&inode->i_sb_list);
1327 while (count--)
1328 iput(&pi->vfs_inode);
1329 }
1330 }
1331
1332 psb->trans_scan_timeout = psb->drop_scan_timeout = 0;
1333 cancel_delayed_work_sync(&psb->dwork);
1334 cancel_delayed_work_sync(&psb->drop_dwork);
1335 flush_scheduled_work();
1336
1337 dprintk("%s: stopped workqueues.\n", __func__);
1338
1339 pohmelfs_crypto_exit(psb);
1340 pohmelfs_state_exit(psb);
1341
1342 bdi_destroy(&psb->bdi);
1343
1344 kfree(psb);
1345 sb->s_fs_info = NULL;
1346}
1347
1348static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1349{
1350 struct super_block *sb = dentry->d_sb;
1351 struct pohmelfs_sb *psb = POHMELFS_SB(sb);
1352
1353 /*
1354 * There are no filesystem size limits yet.
1355 */
1356 memset(buf, 0, sizeof(struct kstatfs));
1357
1358 buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */
1359 buf->f_bsize = sb->s_blocksize;
1360 buf->f_files = psb->ino;
1361 buf->f_namelen = 255;
1362 buf->f_files = atomic_long_read(&psb->total_inodes);
1363 buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT;
1364 buf->f_blocks = psb->total_size >> PAGE_SHIFT;
1365
1366 dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n",
1367 __func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize);
1368
1369 return 0;
1370}
1371
1372static int pohmelfs_show_options(struct seq_file *seq, struct dentry *root)
1373{
1374 struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
1375
1376 seq_printf(seq, ",idx=%u", psb->idx);
1377 seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout));
1378 seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout));
1379 seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout));
1380 seq_printf(seq, ",trans_retries=%u", psb->trans_retries);
1381 seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num);
1382 seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages);
1383 seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout));
1384 if (psb->crypto_fail_unsupported)
1385 seq_printf(seq, ",crypto_fail_unsupported");
1386
1387 return 0;
1388}
1389
1390enum {
1391 pohmelfs_opt_idx,
1392 pohmelfs_opt_crypto_thread_num,
1393 pohmelfs_opt_trans_max_pages,
1394 pohmelfs_opt_crypto_fail_unsupported,
1395
1396 /* Remountable options */
1397 pohmelfs_opt_trans_scan_timeout,
1398 pohmelfs_opt_drop_scan_timeout,
1399 pohmelfs_opt_wait_on_page_timeout,
1400 pohmelfs_opt_trans_retries,
1401 pohmelfs_opt_mcache_timeout,
1402};
1403
1404static struct match_token pohmelfs_tokens[] = {
1405 {pohmelfs_opt_idx, "idx=%u"},
1406 {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
1407 {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
1408 {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
1409 {pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"},
1410 {pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"},
1411 {pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"},
1412 {pohmelfs_opt_trans_retries, "trans_retries=%u"},
1413 {pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"},
1414};
1415
1416static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount)
1417{
1418 char *p;
1419 substring_t args[MAX_OPT_ARGS];
1420 int option, err;
1421
1422 if (!options)
1423 return 0;
1424
1425 while ((p = strsep(&options, ",")) != NULL) {
1426 int token;
1427 if (!*p)
1428 continue;
1429
1430 token = match_token(p, pohmelfs_tokens, args);
1431
1432 err = match_int(&args[0], &option);
1433 if (err)
1434 return err;
1435
1436 if (remount && token <= pohmelfs_opt_crypto_fail_unsupported)
1437 continue;
1438
1439 switch (token) {
1440 case pohmelfs_opt_idx:
1441 psb->idx = option;
1442 break;
1443 case pohmelfs_opt_trans_scan_timeout:
1444 psb->trans_scan_timeout = msecs_to_jiffies(option);
1445 break;
1446 case pohmelfs_opt_drop_scan_timeout:
1447 psb->drop_scan_timeout = msecs_to_jiffies(option);
1448 break;
1449 case pohmelfs_opt_wait_on_page_timeout:
1450 psb->wait_on_page_timeout = msecs_to_jiffies(option);
1451 break;
1452 case pohmelfs_opt_mcache_timeout:
1453 psb->mcache_timeout = msecs_to_jiffies(option);
1454 break;
1455 case pohmelfs_opt_trans_retries:
1456 psb->trans_retries = option;
1457 break;
1458 case pohmelfs_opt_crypto_thread_num:
1459 psb->crypto_thread_num = option;
1460 break;
1461 case pohmelfs_opt_trans_max_pages:
1462 psb->trans_max_pages = option;
1463 break;
1464 case pohmelfs_opt_crypto_fail_unsupported:
1465 psb->crypto_fail_unsupported = 1;
1466 break;
1467 default:
1468 return -EINVAL;
1469 }
1470 }
1471
1472 return 0;
1473}
1474
1475static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
1476{
1477 int err;
1478 struct pohmelfs_sb *psb = POHMELFS_SB(sb);
1479 unsigned long old_sb_flags = sb->s_flags;
1480
1481 err = pohmelfs_parse_options(data, psb, 1);
1482 if (err)
1483 goto err_out_restore;
1484
1485 if (!(*flags & MS_RDONLY))
1486 sb->s_flags &= ~MS_RDONLY;
1487 return 0;
1488
1489err_out_restore:
1490 sb->s_flags = old_sb_flags;
1491 return err;
1492}
1493
1494static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count)
1495{
1496 struct inode *inode = &pi->vfs_inode;
1497
1498 dprintk("%s: %p: ino: %llu, owned: %d.\n",
1499 __func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state));
1500
1501 mutex_lock(&inode->i_mutex);
1502 if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) {
1503 filemap_fdatawrite(inode->i_mapping);
1504 inode->i_sb->s_op->write_inode(inode, 0);
1505 }
1506
1507#ifdef POHMELFS_TRUNCATE_ON_INODE_FLUSH
1508 truncate_inode_pages(inode->i_mapping, 0);
1509#endif
1510
1511 pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
1512 mutex_unlock(&inode->i_mutex);
1513}
1514
1515static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count)
1516{
1517 dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
1518 __func__, pi->ino, pi, &pi->vfs_inode, count);
1519
1520 if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state))
1521 pohmelfs_flush_inode(pi, count);
1522
1523 while (count--)
1524 iput(&pi->vfs_inode);
1525}
1526
1527static void pohmelfs_drop_scan(struct work_struct *work)
1528{
1529 struct pohmelfs_sb *psb =
1530 container_of(work, struct pohmelfs_sb, drop_dwork.work);
1531 struct pohmelfs_inode *pi;
1532 unsigned int count = 0;
1533
1534 while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count)))
1535 pohmelfs_put_inode_count(pi, count);
1536
1537 pohmelfs_check_states(psb);
1538
1539 if (psb->drop_scan_timeout)
1540 schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
1541}
1542
1543/*
1544 * Run through all transactions starting from the oldest,
1545 * drop transaction from current state and try to send it
1546 * to all remote nodes, which are currently installed.
1547 */
1548static void pohmelfs_trans_scan_state(struct netfs_state *st)
1549{
1550 struct rb_node *rb_node;
1551 struct netfs_trans_dst *dst;
1552 struct pohmelfs_sb *psb = st->psb;
1553 unsigned int timeout = psb->trans_scan_timeout;
1554 struct netfs_trans *t;
1555 int err;
1556
1557 mutex_lock(&st->trans_lock);
1558 for (rb_node = rb_first(&st->trans_root); rb_node; ) {
1559 dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
1560 t = dst->trans;
1561
1562 if (timeout && time_after(dst->send_time + timeout, jiffies)
1563 && dst->retries == 0)
1564 break;
1565
1566 dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n",
1567 __func__, t, t->gen, st, dst->retries, psb->trans_retries);
1568 netfs_trans_get(t);
1569
1570 rb_node = rb_next(rb_node);
1571
1572 err = -ETIMEDOUT;
1573 if (timeout && (++dst->retries < psb->trans_retries))
1574 err = netfs_trans_resend(t, psb);
1575
1576 if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) {
1577 if (netfs_trans_remove_nolock(dst, st))
1578 netfs_trans_drop_dst_nostate(dst);
1579 }
1580
1581 t->result = err;
1582 netfs_trans_put(t);
1583 }
1584 mutex_unlock(&st->trans_lock);
1585}
1586
1587/*
1588 * Walk through all installed network states and resend all
1589 * transactions, which are old enough.
1590 */
1591static void pohmelfs_trans_scan(struct work_struct *work)
1592{
1593 struct pohmelfs_sb *psb =
1594 container_of(work, struct pohmelfs_sb, dwork.work);
1595 struct netfs_state *st;
1596 struct pohmelfs_config *c;
1597
1598 mutex_lock(&psb->state_lock);
1599 list_for_each_entry(c, &psb->state_list, config_entry) {
1600 st = &c->state;
1601
1602 pohmelfs_trans_scan_state(st);
1603 }
1604 mutex_unlock(&psb->state_lock);
1605
1606 /*
1607 * If no timeout specified then system is in the middle of umount process,
1608 * so no need to reschedule scanning process again.
1609 */
1610 if (psb->trans_scan_timeout)
1611 schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
1612}
1613
1614int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
1615 unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start)
1616{
1617 struct inode *inode = &pi->vfs_inode;
1618 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
1619 int err = 0, sz;
1620 struct netfs_trans *t;
1621 int path_len, addon_len = 0;
1622 void *data;
1623 struct netfs_inode_info *info;
1624 struct netfs_cmd *cmd;
1625
1626 dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon);
1627
1628 path_len = pohmelfs_path_length(pi);
1629 if (path_len < 0) {
1630 err = path_len;
1631 goto err_out_exit;
1632 }
1633
1634 if (addon)
1635 addon_len = strlen(addon) + 1; /* 0-byte */
1636 sz = addon_len;
1637
1638 if (cmd_op == NETFS_INODE_INFO)
1639 sz += sizeof(struct netfs_inode_info);
1640
1641 t = netfs_trans_alloc(psb, sz + path_len, flags, 0);
1642 if (!t) {
1643 err = -ENOMEM;
1644 goto err_out_exit;
1645 }
1646 t->complete = complete;
1647 t->private = priv;
1648
1649 cmd = netfs_trans_current(t);
1650 data = (void *)(cmd + 1);
1651
1652 if (cmd_op == NETFS_INODE_INFO) {
1653 info = (struct netfs_inode_info *)(cmd + 1);
1654 data = (void *)(info + 1);
1655
1656 /*
1657 * We are under i_mutex, can read and change whatever we want...
1658 */
1659 info->mode = inode->i_mode;
1660 info->nlink = inode->i_nlink;
1661 info->uid = inode->i_uid;
1662 info->gid = inode->i_gid;
1663 info->blocks = inode->i_blocks;
1664 info->rdev = inode->i_rdev;
1665 info->size = inode->i_size;
1666 info->version = inode->i_version;
1667
1668 netfs_convert_inode_info(info);
1669 }
1670
1671 path_len = pohmelfs_construct_path_string(pi, data, path_len);
1672 if (path_len < 0)
1673 goto err_out_free;
1674
1675 dprintk("%s: path_len: %d.\n", __func__, path_len);
1676
1677 if (addon) {
1678 path_len--; /* Do not place null-byte before the addon */
1679 path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */
1680 }
1681
1682 sz += path_len;
1683
1684 cmd->cmd = cmd_op;
1685 cmd->ext = path_len;
1686 cmd->size = sz;
1687 cmd->id = id;
1688 cmd->start = start;
1689
1690 netfs_convert_cmd(cmd);
1691 netfs_trans_update(cmd, t, sz);
1692
1693 /*
1694 * Note, that it is possible to leak error here: transaction callback will not
1695 * be invoked for allocation path failure.
1696 */
1697 return netfs_trans_finish(t, psb);
1698
1699err_out_free:
1700 netfs_trans_free(t);
1701err_out_exit:
1702 if (complete)
1703 complete(NULL, 0, priv, err);
1704 return err;
1705}
1706
1707int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
1708 netfs_trans_complete_t complete, void *priv, u64 start)
1709{
1710 return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start);
1711}
1712
1713/*
1714 * Send request and wait for POHMELFS root capabilities response,
1715 * which will update server's informaion about size of the export,
1716 * permissions, number of objects, available size and so on.
1717 */
1718static int pohmelfs_root_handshake(struct pohmelfs_sb *psb)
1719{
1720 struct netfs_trans *t;
1721 struct netfs_cmd *cmd;
1722 int err = -ENOMEM;
1723
1724 t = netfs_trans_alloc(psb, 0, 0, 0);
1725 if (!t)
1726 goto err_out_exit;
1727
1728 cmd = netfs_trans_current(t);
1729
1730 cmd->cmd = NETFS_CAPABILITIES;
1731 cmd->id = POHMELFS_ROOT_CAPABILITIES;
1732 cmd->size = 0;
1733 cmd->start = 0;
1734 cmd->ext = 0;
1735 cmd->csize = 0;
1736
1737 netfs_convert_cmd(cmd);
1738 netfs_trans_update(cmd, t, 0);
1739
1740 err = netfs_trans_finish(t, psb);
1741 if (err)
1742 goto err_out_exit;
1743
1744 psb->flags = ~0;
1745 err = wait_event_interruptible_timeout(psb->wait,
1746 (psb->flags != ~0),
1747 psb->wait_on_page_timeout);
1748 if (!err)
1749 err = -ETIMEDOUT;
1750 else if (err > 0)
1751 err = -psb->flags;
1752
1753 if (err)
1754 goto err_out_exit;
1755
1756 return 0;
1757
1758err_out_exit:
1759 return err;
1760}
1761
1762static int pohmelfs_show_stats(struct seq_file *m, struct dentry *root)
1763{
1764 struct netfs_state *st;
1765 struct pohmelfs_ctl *ctl;
1766 struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
1767 struct pohmelfs_config *c;
1768
1769 mutex_lock(&psb->state_lock);
1770
1771 seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n");
1772
1773 list_for_each_entry(c, &psb->state_list, config_entry) {
1774 st = &c->state;
1775 ctl = &st->ctl;
1776
1777 seq_printf(m, "%u ", ctl->idx);
1778 if (ctl->addr.sa_family == AF_INET) {
1779 struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
1780 seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
1781 } else if (ctl->addr.sa_family == AF_INET6) {
1782 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
1783 seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
1784 } else {
1785 unsigned int i;
1786 for (i = 0; i < ctl->addrlen; ++i)
1787 seq_printf(m, "%02x.", ctl->addr.addr[i]);
1788 }
1789
1790 seq_printf(m, " %u %u %d %u %x\n",
1791 ctl->type, ctl->proto,
1792 st->socket != NULL,
1793 ctl->prio, ctl->perm);
1794 }
1795 mutex_unlock(&psb->state_lock);
1796
1797 return 0;
1798}
1799
1800static const struct super_operations pohmelfs_sb_ops = {
1801 .alloc_inode = pohmelfs_alloc_inode,
1802 .destroy_inode = pohmelfs_destroy_inode,
1803 .drop_inode = pohmelfs_drop_inode,
1804 .write_inode = pohmelfs_write_inode,
1805 .put_super = pohmelfs_put_super,
1806 .remount_fs = pohmelfs_remount,
1807 .statfs = pohmelfs_statfs,
1808 .show_options = pohmelfs_show_options,
1809 .show_stats = pohmelfs_show_stats,
1810};
1811
1812/*
1813 * Allocate private superblock and create root dir.
1814 */
1815static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
1816{
1817 struct pohmelfs_sb *psb;
1818 int err = -ENOMEM;
1819 struct inode *root;
1820 struct pohmelfs_inode *npi;
1821 struct qstr str;
1822
1823 psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL);
1824 if (!psb)
1825 goto err_out_exit;
1826
1827 err = bdi_init(&psb->bdi);
1828 if (err)
1829 goto err_out_free_sb;
1830
1831 err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
1832 if (err) {
1833 bdi_destroy(&psb->bdi);
1834 goto err_out_free_sb;
1835 }
1836
1837 sb->s_fs_info = psb;
1838 sb->s_op = &pohmelfs_sb_ops;
1839 sb->s_magic = POHMELFS_MAGIC_NUM;
1840 sb->s_maxbytes = MAX_LFS_FILESIZE;
1841 sb->s_blocksize = PAGE_SIZE;
1842 sb->s_bdi = &psb->bdi;
1843
1844 psb->sb = sb;
1845
1846 psb->ino = 2;
1847 psb->idx = 0;
1848 psb->active_state = NULL;
1849 psb->trans_retries = 5;
1850 psb->trans_data_size = PAGE_SIZE;
1851 psb->drop_scan_timeout = msecs_to_jiffies(1000);
1852 psb->trans_scan_timeout = msecs_to_jiffies(5000);
1853 psb->wait_on_page_timeout = msecs_to_jiffies(5000);
1854 init_waitqueue_head(&psb->wait);
1855
1856 spin_lock_init(&psb->ino_lock);
1857
1858 INIT_LIST_HEAD(&psb->drop_list);
1859
1860 mutex_init(&psb->mcache_lock);
1861 psb->mcache_root = RB_ROOT;
1862 psb->mcache_timeout = msecs_to_jiffies(5000);
1863 atomic_long_set(&psb->mcache_gen, 0);
1864
1865 psb->trans_max_pages = 100;
1866
1867 psb->crypto_align_size = 16;
1868 psb->crypto_attached_size = 0;
1869 psb->hash_strlen = 0;
1870 psb->cipher_strlen = 0;
1871 psb->perform_crypto = 0;
1872 psb->crypto_thread_num = 2;
1873 psb->crypto_fail_unsupported = 0;
1874 mutex_init(&psb->crypto_thread_lock);
1875 INIT_LIST_HEAD(&psb->crypto_ready_list);
1876 INIT_LIST_HEAD(&psb->crypto_active_list);
1877
1878 atomic_set(&psb->trans_gen, 1);
1879 atomic_long_set(&psb->total_inodes, 0);
1880
1881 mutex_init(&psb->state_lock);
1882 INIT_LIST_HEAD(&psb->state_list);
1883
1884 err = pohmelfs_parse_options((char *) data, psb, 0);
1885 if (err)
1886 goto err_out_free_bdi;
1887
1888 err = pohmelfs_copy_crypto(psb);
1889 if (err)
1890 goto err_out_free_bdi;
1891
1892 err = pohmelfs_state_init(psb);
1893 if (err)
1894 goto err_out_free_strings;
1895
1896 err = pohmelfs_crypto_init(psb);
1897 if (err)
1898 goto err_out_state_exit;
1899
1900 err = pohmelfs_root_handshake(psb);
1901 if (err)
1902 goto err_out_crypto_exit;
1903
1904 str.name = "/";
1905 str.hash = jhash("/", 1, 0);
1906 str.len = 1;
1907
1908 npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR);
1909 if (IS_ERR(npi)) {
1910 err = PTR_ERR(npi);
1911 goto err_out_crypto_exit;
1912 }
1913 set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
1914 clear_bit(NETFS_INODE_OWNED, &npi->state);
1915
1916 root = &npi->vfs_inode;
1917
1918 sb->s_root = d_alloc_root(root);
1919 if (!sb->s_root)
1920 goto err_out_put_root;
1921
1922 INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan);
1923 schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
1924
1925 INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan);
1926 schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
1927
1928 return 0;
1929
1930err_out_put_root:
1931 iput(root);
1932err_out_crypto_exit:
1933 pohmelfs_crypto_exit(psb);
1934err_out_state_exit:
1935 pohmelfs_state_exit(psb);
1936err_out_free_strings:
1937 kfree(psb->cipher_string);
1938 kfree(psb->hash_string);
1939err_out_free_bdi:
1940 bdi_destroy(&psb->bdi);
1941err_out_free_sb:
1942 kfree(psb);
1943err_out_exit:
1944
1945 dprintk("%s: err: %d.\n", __func__, err);
1946 return err;
1947}
1948
1949/*
1950 * Some VFS magic here...
1951 */
1952static struct dentry *pohmelfs_mount(struct file_system_type *fs_type,
1953 int flags, const char *dev_name, void *data)
1954{
1955 return mount_nodev(fs_type, flags, data, pohmelfs_fill_super);
1956}
1957
1958/*
1959 * We need this to sync all inodes earlier, since when writeback
1960 * is invoked from the umount/mntput path dcache is already shrunk,
1961 * see generic_shutdown_super(), and no inodes can access the path.
1962 */
1963static void pohmelfs_kill_super(struct super_block *sb)
1964{
1965 sync_inodes_sb(sb);
1966 kill_anon_super(sb);
1967}
1968
1969static struct file_system_type pohmel_fs_type = {
1970 .owner = THIS_MODULE,
1971 .name = "pohmel",
1972 .mount = pohmelfs_mount,
1973 .kill_sb = pohmelfs_kill_super,
1974};
1975
1976/*
1977 * Cache and module initializations and freeing routings.
1978 */
1979static void pohmelfs_init_once(void *data)
1980{
1981 struct pohmelfs_inode *pi = data;
1982
1983 inode_init_once(&pi->vfs_inode);
1984}
1985
1986static int __init pohmelfs_init_inodecache(void)
1987{
1988 pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache",
1989 sizeof(struct pohmelfs_inode),
1990 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
1991 pohmelfs_init_once);
1992 if (!pohmelfs_inode_cache)
1993 return -ENOMEM;
1994
1995 return 0;
1996}
1997
1998static void pohmelfs_destroy_inodecache(void)
1999{
2000 kmem_cache_destroy(pohmelfs_inode_cache);
2001}
2002
2003static int __init init_pohmel_fs(void)
2004{
2005 int err;
2006
2007 err = pohmelfs_config_init();
2008 if (err)
2009 goto err_out_exit;
2010
2011 err = pohmelfs_init_inodecache();
2012 if (err)
2013 goto err_out_config_exit;
2014
2015 err = pohmelfs_mcache_init();
2016 if (err)
2017 goto err_out_destroy;
2018
2019 err = netfs_trans_init();
2020 if (err)
2021 goto err_out_mcache_exit;
2022
2023 err = register_filesystem(&pohmel_fs_type);
2024 if (err)
2025 goto err_out_trans;
2026
2027 return 0;
2028
2029err_out_trans:
2030 netfs_trans_exit();
2031err_out_mcache_exit:
2032 pohmelfs_mcache_exit();
2033err_out_destroy:
2034 pohmelfs_destroy_inodecache();
2035err_out_config_exit:
2036 pohmelfs_config_exit();
2037err_out_exit:
2038 return err;
2039}
2040
2041static void __exit exit_pohmel_fs(void)
2042{
2043 unregister_filesystem(&pohmel_fs_type);
2044 pohmelfs_destroy_inodecache();
2045 pohmelfs_mcache_exit();
2046 pohmelfs_config_exit();
2047 netfs_trans_exit();
2048}
2049
2050module_init(init_pohmel_fs);
2051module_exit(exit_pohmel_fs);
2052
2053MODULE_LICENSE("GPL");
2054MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
2055MODULE_DESCRIPTION("Pohmel filesystem");
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c
deleted file mode 100644
index 6710114cd42..00000000000
--- a/drivers/staging/pohmelfs/lock.c
+++ /dev/null
@@ -1,182 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/module.h>
17#include <linux/backing-dev.h>
18#include <linux/fs.h>
19#include <linux/fsnotify.h>
20#include <linux/mempool.h>
21
22#include "netfs.h"
23
24static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
25 u64 id, u64 start, u32 size, int type)
26{
27 struct inode *inode = &pi->vfs_inode;
28 struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
29 struct netfs_trans *t;
30 struct netfs_cmd *cmd;
31 int path_len, err;
32 void *data;
33 struct netfs_lock *l;
34 int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info);
35
36 err = pohmelfs_path_length(pi);
37 if (err < 0)
38 goto err_out_exit;
39
40 path_len = err;
41
42 err = -ENOMEM;
43 t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
44 NETFS_TRANS_SINGLE_DST, 0);
45 if (!t)
46 goto err_out_exit;
47
48 cmd = netfs_trans_current(t);
49 data = cmd + 1;
50
51 err = pohmelfs_construct_path_string(pi, data, path_len);
52 if (err < 0)
53 goto err_out_free;
54 path_len = err;
55
56 l = data + path_len;
57
58 l->start = start;
59 l->size = size;
60 l->type = type;
61 l->ino = pi->ino;
62
63 cmd->cmd = NETFS_LOCK;
64 cmd->start = 0;
65 cmd->id = id;
66 cmd->size = sizeof(struct netfs_lock) + path_len + isize;
67 cmd->ext = path_len;
68 cmd->csize = 0;
69
70 netfs_convert_cmd(cmd);
71 netfs_convert_lock(l);
72
73 if (isize) {
74 struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1);
75
76 info->mode = inode->i_mode;
77 info->nlink = inode->i_nlink;
78 info->uid = inode->i_uid;
79 info->gid = inode->i_gid;
80 info->blocks = inode->i_blocks;
81 info->rdev = inode->i_rdev;
82 info->size = inode->i_size;
83 info->version = inode->i_version;
84
85 netfs_convert_inode_info(info);
86 }
87
88 netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize);
89
90 return netfs_trans_finish(t, psb);
91
92err_out_free:
93 netfs_trans_free(t);
94err_out_exit:
95 printk("%s: err: %d.\n", __func__, err);
96 return err;
97}
98
99int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
100{
101 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
102 struct pohmelfs_mcache *m;
103 int err = -ENOMEM;
104 struct iattr iattr;
105 struct inode *inode = &pi->vfs_inode;
106
107 dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
108 "type: %d, locked as: %d, owned: %d.\n",
109 __func__, &pi->vfs_inode, pi->ino,
110 start, size, type, pi->lock_type,
111 !!test_bit(NETFS_INODE_OWNED, &pi->state));
112
113 if (!pohmelfs_need_lock(pi, type))
114 return 0;
115
116 m = pohmelfs_mcache_alloc(psb, start, size, NULL);
117 if (IS_ERR(m))
118 return PTR_ERR(m);
119
120 err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
121 type | POHMELFS_LOCK_GRAB);
122 if (err)
123 goto err_out_put;
124
125 err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
126 if (err)
127 err = m->err;
128 else
129 err = -ETIMEDOUT;
130
131 if (err) {
132 printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
133 __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
134 }
135
136 if (err && (err != -ENOENT))
137 goto err_out_put;
138
139 if (!err) {
140 netfs_convert_inode_info(&m->info);
141
142 iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
143 iattr.ia_mode = m->info.mode;
144 iattr.ia_uid = m->info.uid;
145 iattr.ia_gid = m->info.gid;
146 iattr.ia_size = m->info.size;
147 iattr.ia_atime = CURRENT_TIME;
148
149 dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
150 __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);
151
152 err = pohmelfs_setattr_raw(inode, &iattr);
153 if (!err) {
154 struct dentry *dentry = d_find_alias(inode);
155 if (dentry) {
156 fsnotify_change(dentry, iattr.ia_valid);
157 dput(dentry);
158 }
159 }
160 }
161
162 pi->lock_type = type;
163 set_bit(NETFS_INODE_OWNED, &pi->state);
164
165 pohmelfs_mcache_put(psb, m);
166
167 return 0;
168
169err_out_put:
170 pohmelfs_mcache_put(psb, m);
171 return err;
172}
173
174int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
175{
176 dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
177 __func__, &pi->vfs_inode, pi->ino, start, size, type);
178 pi->lock_type = 0;
179 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state);
180 clear_bit(NETFS_INODE_OWNED, &pi->state);
181 return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type);
182}
diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c
deleted file mode 100644
index e22665cdd16..00000000000
--- a/drivers/staging/pohmelfs/mcache.c
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/module.h>
17#include <linux/slab.h>
18#include <linux/mempool.h>
19
20#include "netfs.h"
21
22static struct kmem_cache *pohmelfs_mcache_cache;
23static mempool_t *pohmelfs_mcache_pool;
24
25static inline int pohmelfs_mcache_cmp(u64 gen, u64 new)
26{
27 if (gen < new)
28 return 1;
29 if (gen > new)
30 return -1;
31 return 0;
32}
33
34struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen)
35{
36 struct rb_root *root = &psb->mcache_root;
37 struct rb_node *n = root->rb_node;
38 struct pohmelfs_mcache *tmp, *ret = NULL;
39 int cmp;
40
41 while (n) {
42 tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry);
43
44 cmp = pohmelfs_mcache_cmp(tmp->gen, gen);
45 if (cmp < 0)
46 n = n->rb_left;
47 else if (cmp > 0)
48 n = n->rb_right;
49 else {
50 ret = tmp;
51 pohmelfs_mcache_get(ret);
52 break;
53 }
54 }
55
56 return ret;
57}
58
59static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
60{
61 struct rb_root *root = &psb->mcache_root;
62 struct rb_node **n = &root->rb_node, *parent = NULL;
63 struct pohmelfs_mcache *ret = NULL, *tmp;
64 int cmp;
65
66 while (*n) {
67 parent = *n;
68
69 tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry);
70
71 cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen);
72 if (cmp < 0)
73 n = &parent->rb_left;
74 else if (cmp > 0)
75 n = &parent->rb_right;
76 else {
77 ret = tmp;
78 break;
79 }
80 }
81
82 if (ret)
83 return -EEXIST;
84
85 rb_link_node(&m->mcache_entry, parent, n);
86 rb_insert_color(&m->mcache_entry, root);
87
88 return 0;
89}
90
91static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
92{
93 if (m && m->mcache_entry.rb_parent_color) {
94 rb_erase(&m->mcache_entry, &psb->mcache_root);
95 m->mcache_entry.rb_parent_color = 0;
96 return 1;
97 }
98 return 0;
99}
100
101void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
102{
103 mutex_lock(&psb->mcache_lock);
104 pohmelfs_mcache_remove(psb, m);
105 mutex_unlock(&psb->mcache_lock);
106}
107
108struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
109 unsigned int size, void *data)
110{
111 struct pohmelfs_mcache *m;
112 int err = -ENOMEM;
113
114 m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL);
115 if (!m)
116 goto err_out_exit;
117
118 init_completion(&m->complete);
119 m->err = 0;
120 atomic_set(&m->refcnt, 1);
121 m->data = data;
122 m->start = start;
123 m->size = size;
124 m->gen = atomic_long_inc_return(&psb->mcache_gen);
125
126 mutex_lock(&psb->mcache_lock);
127 err = pohmelfs_mcache_insert(psb, m);
128 mutex_unlock(&psb->mcache_lock);
129 if (err)
130 goto err_out_free;
131
132 return m;
133
134err_out_free:
135 mempool_free(m, pohmelfs_mcache_pool);
136err_out_exit:
137 return ERR_PTR(err);
138}
139
140void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
141{
142 pohmelfs_mcache_remove_locked(psb, m);
143
144 mempool_free(m, pohmelfs_mcache_pool);
145}
146
147int __init pohmelfs_mcache_init(void)
148{
149 pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache",
150 sizeof(struct pohmelfs_mcache),
151 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL);
152 if (!pohmelfs_mcache_cache)
153 goto err_out_exit;
154
155 pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache);
156 if (!pohmelfs_mcache_pool)
157 goto err_out_free;
158
159 return 0;
160
161err_out_free:
162 kmem_cache_destroy(pohmelfs_mcache_cache);
163err_out_exit:
164 return -ENOMEM;
165}
166
167void pohmelfs_mcache_exit(void)
168{
169 mempool_destroy(pohmelfs_mcache_pool);
170 kmem_cache_destroy(pohmelfs_mcache_cache);
171}
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
deleted file mode 100644
index b2e91862208..00000000000
--- a/drivers/staging/pohmelfs/net.c
+++ /dev/null
@@ -1,1209 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/fsnotify.h>
17#include <linux/jhash.h>
18#include <linux/in.h>
19#include <linux/in6.h>
20#include <linux/kthread.h>
21#include <linux/pagemap.h>
22#include <linux/poll.h>
23#include <linux/slab.h>
24#include <linux/swap.h>
25#include <linux/syscalls.h>
26#include <linux/vmalloc.h>
27
28#include "netfs.h"
29
30/*
31 * Async machinery lives here.
32 * All commands being sent to server do _not_ require sync reply,
33 * instead, if it is really needed, like readdir or readpage, caller
34 * sleeps waiting for data, which will be placed into provided buffer
35 * and caller will be awakened.
36 *
37 * Every command response can come without some listener. For example
38 * readdir response will add new objects into cache without appropriate
39 * request from userspace. This is used in cache coherency.
40 *
41 * If object is not found for given data, it is discarded.
42 *
43 * All requests are received by dedicated kernel thread.
44 */
45
46/*
47 * Basic network sending/receiving functions.
48 * Blocked mode is used.
49 */
50static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size)
51{
52 struct msghdr msg;
53 struct kvec iov;
54 int err;
55
56 BUG_ON(!size);
57
58 iov.iov_base = buf;
59 iov.iov_len = size;
60
61 msg.msg_iov = (struct iovec *)&iov;
62 msg.msg_iovlen = 1;
63 msg.msg_name = NULL;
64 msg.msg_namelen = 0;
65 msg.msg_control = NULL;
66 msg.msg_controllen = 0;
67 msg.msg_flags = MSG_DONTWAIT;
68
69 err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
70 msg.msg_flags);
71 if (err <= 0) {
72 printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err);
73 if (err == 0)
74 err = -ECONNRESET;
75 }
76
77 return err;
78}
79
80static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size)
81{
82 unsigned int revents = 0;
83 unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
84 unsigned int mask = err_mask | POLLIN;
85 int err = 0;
86
87 while (size && !err) {
88 revents = netfs_state_poll(st);
89
90 if (!(revents & mask)) {
91 DEFINE_WAIT(wait);
92
93 for (;;) {
94 prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE);
95 if (kthread_should_stop())
96 break;
97
98 revents = netfs_state_poll(st);
99
100 if (revents & mask)
101 break;
102
103 if (signal_pending(current))
104 break;
105
106 schedule();
107 continue;
108 }
109 finish_wait(&st->thread_wait, &wait);
110 }
111
112 err = 0;
113 netfs_state_lock(st);
114 if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) {
115 err = netfs_data_recv(st, data, size);
116 if (err > 0) {
117 data += err;
118 size -= err;
119 err = 0;
120 } else if (err == 0)
121 err = -ECONNRESET;
122 }
123
124 if (revents & err_mask) {
125 printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
126 __func__, revents, st->socket, size, err);
127 err = -ECONNRESET;
128 }
129 netfs_state_unlock(st);
130
131 if (err < 0) {
132 if (netfs_state_trylock_send(st)) {
133 netfs_state_exit(st);
134 err = netfs_state_init(st);
135 if (!err)
136 err = -EAGAIN;
137 netfs_state_unlock_send(st);
138 } else {
139 st->need_reset = 1;
140 }
141 }
142
143 if (kthread_should_stop())
144 err = -ENODEV;
145
146 if (err)
147 printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
148 "should_stop: %d, size: %u, err: %d.\n",
149 __func__, st->socket, st->read_socket,
150 revents, revents & err_mask, kthread_should_stop(), size, err);
151 }
152
153 return err;
154}
155
156int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size)
157{
158 struct netfs_cmd *cmd = &st->cmd;
159 int err;
160
161 err = pohmelfs_data_recv(st, data, size);
162 if (err)
163 return err;
164
165 return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size);
166}
167
168/*
169 * Polling machinery.
170 */
171
172struct netfs_poll_helper {
173 poll_table pt;
174 struct netfs_state *st;
175};
176
177static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key)
178{
179 struct netfs_state *st = container_of(wait, struct netfs_state, wait);
180
181 wake_up(&st->thread_wait);
182 return 1;
183}
184
185static void netfs_queue_func(struct file *file, wait_queue_head_t *whead,
186 poll_table *pt)
187{
188 struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st;
189
190 st->whead = whead;
191 init_waitqueue_func_entry(&st->wait, netfs_queue_wake);
192 add_wait_queue(whead, &st->wait);
193}
194
195static void netfs_poll_exit(struct netfs_state *st)
196{
197 if (st->whead) {
198 remove_wait_queue(st->whead, &st->wait);
199 st->whead = NULL;
200 }
201}
202
203static int netfs_poll_init(struct netfs_state *st)
204{
205 struct netfs_poll_helper ph;
206
207 ph.st = st;
208 init_poll_funcptr(&ph.pt, &netfs_queue_func);
209
210 st->socket->ops->poll(NULL, st->socket, &ph.pt);
211 return 0;
212}
213
214/*
215 * Get response for readpage command. We search inode and page in its mapping
216 * and copy data into. If it was async request, then we queue page into shared
217 * data and wakeup listener, who will copy it to userspace.
218 *
219 * There is a work in progress of allowing to call copy_to_user() directly from
220 * async receiving kernel thread.
221 */
222static int pohmelfs_read_page_response(struct netfs_state *st)
223{
224 struct pohmelfs_sb *psb = st->psb;
225 struct netfs_cmd *cmd = &st->cmd;
226 struct inode *inode;
227 struct page *page;
228 int err = 0;
229
230 if (cmd->size > PAGE_CACHE_SIZE) {
231 err = -EINVAL;
232 goto err_out_exit;
233 }
234
235 inode = ilookup(st->psb->sb, cmd->id);
236 if (!inode) {
237 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
238 err = -ENOENT;
239 goto err_out_exit;
240 }
241
242 page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT);
243 if (!page || !PageLocked(page)) {
244 printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
245 __func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT);
246
247 while (cmd->size) {
248 unsigned int sz = min(cmd->size, st->size);
249
250 err = pohmelfs_data_recv(st, st->data, sz);
251 if (err)
252 break;
253
254 cmd->size -= sz;
255 }
256
257 err = -ENODEV;
258 if (page)
259 goto err_out_page_put;
260 goto err_out_put;
261 }
262
263 if (cmd->size) {
264 void *addr;
265
266 addr = kmap(page);
267 err = pohmelfs_data_recv(st, addr, cmd->size);
268 kunmap(page);
269
270 if (err)
271 goto err_out_page_unlock;
272 }
273
274 dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
275 __func__, page, cmd->start, cmd->size, PageLocked(page));
276
277 SetPageChecked(page);
278 if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) {
279 err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv);
280 if (err < 0)
281 goto err_out_page_unlock;
282 } else {
283 SetPageUptodate(page);
284 unlock_page(page);
285 page_cache_release(page);
286 }
287
288 pohmelfs_put_inode(POHMELFS_I(inode));
289 wake_up(&st->psb->wait);
290
291 return 0;
292
293err_out_page_unlock:
294 SetPageError(page);
295 unlock_page(page);
296err_out_page_put:
297 page_cache_release(page);
298err_out_put:
299 pohmelfs_put_inode(POHMELFS_I(inode));
300err_out_exit:
301 wake_up(&st->psb->wait);
302 return err;
303}
304
305static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str,
306 struct netfs_inode_info *info)
307{
308 struct inode *inode;
309 struct pohmelfs_name *n;
310 int err = 0;
311 u64 ino = 0;
312
313 mutex_lock(&parent->offset_lock);
314 n = pohmelfs_search_hash(parent, str->hash);
315 if (n)
316 ino = n->ino;
317 mutex_unlock(&parent->offset_lock);
318
319 if (!ino)
320 goto out;
321
322 inode = ilookup(parent->vfs_inode.i_sb, ino);
323 if (!inode)
324 goto out;
325
326 dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino);
327
328 pohmelfs_fill_inode(inode, info);
329 pohmelfs_put_inode(POHMELFS_I(inode));
330 err = -EEXIST;
331out:
332 return err;
333}
334
335/*
336 * Readdir response from server. If special field is set, we wakeup
337 * listener (readdir() call), which will copy data to userspace.
338 */
339static int pohmelfs_readdir_response(struct netfs_state *st)
340{
341 struct inode *inode;
342 struct netfs_cmd *cmd = &st->cmd;
343 struct netfs_inode_info *info;
344 struct pohmelfs_inode *parent = NULL, *npi;
345 int err = 0, last = cmd->ext;
346 struct qstr str;
347
348 if (cmd->size > st->size)
349 return -EINVAL;
350
351 inode = ilookup(st->psb->sb, cmd->id);
352 if (!inode) {
353 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
354 return -ENOENT;
355 }
356 parent = POHMELFS_I(inode);
357
358 if (!cmd->size && cmd->start) {
359 err = -cmd->start;
360 goto out;
361 }
362
363 if (cmd->size) {
364 char *name;
365
366 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
367 if (err)
368 goto err_out_put;
369
370 info = (struct netfs_inode_info *)(st->data);
371
372 name = (char *)(info + 1);
373 str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
374 name[str.len] = 0;
375 str.name = name;
376 str.hash = jhash(str.name, str.len, 0);
377
378 netfs_convert_inode_info(info);
379
380 if (parent) {
381 err = pohmelfs_check_name(parent, &str, info);
382 if (err) {
383 if (err == -EEXIST)
384 err = 0;
385 goto out;
386 }
387 }
388
389 info->ino = cmd->start;
390 if (!info->ino)
391 info->ino = pohmelfs_new_ino(st->psb);
392
393 dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
394 __func__, parent->ino, info->ino, str.name, str.hash, str.len,
395 info->mode);
396
397 npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
398 if (IS_ERR(npi)) {
399 err = PTR_ERR(npi);
400
401 if (err != -EEXIST)
402 goto err_out_put;
403 } else {
404 struct dentry *dentry, *alias, *pd;
405
406 set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
407 clear_bit(NETFS_INODE_OWNED, &npi->state);
408
409 pd = d_find_alias(&parent->vfs_inode);
410 if (pd) {
411 str.hash = full_name_hash(str.name, str.len);
412 dentry = d_alloc(pd, &str);
413 if (dentry) {
414 alias = d_materialise_unique(dentry, &npi->vfs_inode);
415 if (alias)
416 dput(alias);
417 }
418
419 dput(dentry);
420 dput(pd);
421 }
422 }
423 }
424out:
425 if (last) {
426 set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
427 set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state);
428 wake_up(&st->psb->wait);
429 }
430 pohmelfs_put_inode(parent);
431
432 return err;
433
434err_out_put:
435 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
436 printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id);
437 pohmelfs_put_inode(parent);
438 wake_up(&st->psb->wait);
439 return err;
440}
441
442/*
443 * Lookup command response.
444 * It searches for inode to be looked at (if it exists) and substitutes
445 * its inode information (size, permission, mode and so on), if inode does
446 * not exist, new one will be created and inserted into caches.
447 */
448static int pohmelfs_lookup_response(struct netfs_state *st)
449{
450 struct inode *inode = NULL;
451 struct netfs_cmd *cmd = &st->cmd;
452 struct netfs_inode_info *info;
453 struct pohmelfs_inode *parent = NULL, *npi;
454 int err = -EINVAL;
455 char *name;
456
457 inode = ilookup(st->psb->sb, cmd->id);
458 if (!inode) {
459 printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
460 __func__, cmd->id, cmd->start, cmd->size);
461 err = -ENOENT;
462 goto err_out_exit;
463 }
464 parent = POHMELFS_I(inode);
465
466 if (!cmd->size) {
467 err = -cmd->start;
468 goto err_out_put;
469 }
470
471 if (cmd->size < sizeof(struct netfs_inode_info)) {
472 printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
473 __func__, cmd->id, cmd->start, cmd->size);
474 err = -EINVAL;
475 goto err_out_put;
476 }
477
478 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
479 if (err)
480 goto err_out_put;
481
482 info = (struct netfs_inode_info *)(st->data);
483 name = (char *)(info + 1);
484
485 netfs_convert_inode_info(info);
486
487 info->ino = cmd->start;
488 if (!info->ino)
489 info->ino = pohmelfs_new_ino(st->psb);
490
491 dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
492 __func__, parent->ino, info->ino, name, cmd->start);
493
494 if (cmd->start)
495 npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0);
496 else {
497 struct qstr str;
498
499 str.name = name;
500 str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
501 str.hash = jhash(name, str.len, 0);
502
503 npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
504 }
505 if (IS_ERR(npi)) {
506 err = PTR_ERR(npi);
507
508 if (err != -EEXIST)
509 goto err_out_put;
510 } else {
511 set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
512 clear_bit(NETFS_INODE_OWNED, &npi->state);
513 }
514
515 clear_bit(NETFS_COMMAND_PENDING, &parent->state);
516 pohmelfs_put_inode(parent);
517
518 wake_up(&st->psb->wait);
519
520 return 0;
521
522err_out_put:
523 pohmelfs_put_inode(parent);
524err_out_exit:
525 clear_bit(NETFS_COMMAND_PENDING, &parent->state);
526 wake_up(&st->psb->wait);
527 printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
528 __func__, inode, cmd->id, cmd->start, cmd->size, err);
529 return err;
530}
531
532/*
533 * Create response, just marks local inode as 'created', so that writeback
534 * for any of its children (or own) would not try to sync it again.
535 */
536static int pohmelfs_create_response(struct netfs_state *st)
537{
538 struct inode *inode;
539 struct netfs_cmd *cmd = &st->cmd;
540 struct pohmelfs_inode *pi;
541
542 inode = ilookup(st->psb->sb, cmd->id);
543 if (!inode) {
544 printk("%s: failed to find inode: id: %llu, start: %llu.\n",
545 __func__, cmd->id, cmd->start);
546 goto err_out_exit;
547 }
548
549 pi = POHMELFS_I(inode);
550
551 /*
552 * To lock or not to lock?
553 * We actually do not care if it races...
554 */
555 if (cmd->start)
556 make_bad_inode(inode);
557 set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
558
559 pohmelfs_put_inode(pi);
560
561 wake_up(&st->psb->wait);
562 return 0;
563
564err_out_exit:
565 wake_up(&st->psb->wait);
566 return -ENOENT;
567}
568
569/*
570 * Object remove response. Just says that remove request has been received.
571 * Used in cache coherency protocol.
572 */
573static int pohmelfs_remove_response(struct netfs_state *st)
574{
575 struct netfs_cmd *cmd = &st->cmd;
576 int err;
577
578 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
579 if (err)
580 return err;
581
582 dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data);
583
584 return 0;
585}
586
587/*
588 * Transaction reply processing.
589 *
590 * Find transaction based on its generation number, bump its reference counter,
591 * so that none could free it under us, drop from the trees and lists and
592 * drop reference counter. When it hits zero (when all destinations replied
593 * and all timeout handled by async scanning code), completion will be called
594 * and transaction will be freed.
595 */
596static int pohmelfs_transaction_response(struct netfs_state *st)
597{
598 struct netfs_trans_dst *dst;
599 struct netfs_trans *t = NULL;
600 struct netfs_cmd *cmd = &st->cmd;
601 short err = (signed)cmd->ext;
602
603 mutex_lock(&st->trans_lock);
604 dst = netfs_trans_search(st, cmd->start);
605 if (dst) {
606 netfs_trans_remove_nolock(dst, st);
607 t = dst->trans;
608 }
609 mutex_unlock(&st->trans_lock);
610
611 if (!t) {
612 printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
613 __func__, cmd->start, cmd->id, cmd->size, cmd->ext);
614 err = -EINVAL;
615 goto out;
616 }
617
618 t->result = err;
619 netfs_trans_drop_dst_nostate(dst);
620
621out:
622 wake_up(&st->psb->wait);
623 return err;
624}
625
626/*
627 * Inode metadata cache coherency message.
628 */
629static int pohmelfs_page_cache_response(struct netfs_state *st)
630{
631 struct netfs_cmd *cmd = &st->cmd;
632 struct inode *inode;
633
634 dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size);
635
636 inode = ilookup(st->psb->sb, cmd->id);
637 if (!inode) {
638 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
639 return -ENOENT;
640 }
641
642 set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state);
643 pohmelfs_put_inode(POHMELFS_I(inode));
644
645 return 0;
646}
647
648/*
649 * Root capabilities response: export statistics
650 * like used and available size, number of files and dirs,
651 * permissions.
652 */
653static int pohmelfs_root_cap_response(struct netfs_state *st)
654{
655 struct netfs_cmd *cmd = &st->cmd;
656 struct netfs_root_capabilities *cap;
657 struct pohmelfs_sb *psb = st->psb;
658
659 if (cmd->size != sizeof(struct netfs_root_capabilities)) {
660 psb->flags = EPROTO;
661 wake_up(&psb->wait);
662 return -EPROTO;
663 }
664
665 cap = st->data;
666
667 netfs_convert_root_capabilities(cap);
668
669 if (psb->total_size < cap->used + cap->avail)
670 psb->total_size = cap->used + cap->avail;
671 if (cap->avail)
672 psb->avail_size = cap->avail;
673 psb->state_flags = cap->flags;
674
675 if (psb->state_flags & POHMELFS_FLAGS_RO) {
676 psb->sb->s_flags |= MS_RDONLY;
677 printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx);
678 }
679
680 if (psb->state_flags & POHMELFS_FLAGS_XATTR)
681 printk(KERN_INFO "Mounting POHMELFS (%d) "
682 "with extended attributes support.\n", psb->idx);
683
684 if (atomic_long_read(&psb->total_inodes) <= 1)
685 atomic_long_set(&psb->total_inodes, cap->nr_files);
686
687 dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
688 __func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files);
689
690 psb->flags = 0;
691 wake_up(&psb->wait);
692 return 0;
693}
694
695/*
696 * Crypto capabilities of the server, where it says that
697 * it supports or does not requested hash/cipher algorithms.
698 */
699static int pohmelfs_crypto_cap_response(struct netfs_state *st)
700{
701 struct netfs_cmd *cmd = &st->cmd;
702 struct netfs_crypto_capabilities *cap;
703 struct pohmelfs_sb *psb = st->psb;
704 int err = 0;
705
706 if (cmd->size != sizeof(struct netfs_crypto_capabilities)) {
707 psb->flags = EPROTO;
708 wake_up(&psb->wait);
709 return -EPROTO;
710 }
711
712 cap = st->data;
713
714 dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
715 __func__,
716 psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED",
717 psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED");
718
719 if (!cap->hash_strlen) {
720 if (psb->hash_strlen && psb->crypto_fail_unsupported)
721 err = -ENOTSUPP;
722 psb->hash_strlen = 0;
723 kfree(psb->hash_string);
724 psb->hash_string = NULL;
725 }
726
727 if (!cap->cipher_strlen) {
728 if (psb->cipher_strlen && psb->crypto_fail_unsupported)
729 err = -ENOTSUPP;
730 psb->cipher_strlen = 0;
731 kfree(psb->cipher_string);
732 psb->cipher_string = NULL;
733 }
734
735 return err;
736}
737
738/*
739 * Capabilities handshake response.
740 */
741static int pohmelfs_capabilities_response(struct netfs_state *st)
742{
743 struct netfs_cmd *cmd = &st->cmd;
744 int err = 0;
745
746 err = pohmelfs_data_recv(st, st->data, cmd->size);
747 if (err)
748 return err;
749
750 switch (cmd->id) {
751 case POHMELFS_CRYPTO_CAPABILITIES:
752 return pohmelfs_crypto_cap_response(st);
753 case POHMELFS_ROOT_CAPABILITIES:
754 return pohmelfs_root_cap_response(st);
755 default:
756 break;
757 }
758 return -EINVAL;
759}
760
761/*
762 * Receiving extended attribute.
763 * Does not work properly if received size is more than requested one,
764 * it should not happen with current request/reply model though.
765 */
766static int pohmelfs_getxattr_response(struct netfs_state *st)
767{
768 struct pohmelfs_sb *psb = st->psb;
769 struct netfs_cmd *cmd = &st->cmd;
770 struct pohmelfs_mcache *m;
771 short error = (signed short)cmd->ext, err;
772 unsigned int sz, total_size;
773
774 m = pohmelfs_mcache_search(psb, cmd->id);
775
776 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
777 __func__, cmd->id, (m) ? m->gen : 0, error);
778
779 if (!m) {
780 printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id);
781 return -ENOENT;
782 }
783
784 if (cmd->size) {
785 sz = min_t(unsigned int, cmd->size, m->size);
786 err = pohmelfs_data_recv_and_check(st, m->data, sz);
787 if (err) {
788 error = err;
789 goto out;
790 }
791
792 m->size = sz;
793 total_size = cmd->size - sz;
794
795 while (total_size) {
796 sz = min(total_size, st->size);
797
798 err = pohmelfs_data_recv_and_check(st, st->data, sz);
799 if (err) {
800 error = err;
801 break;
802 }
803
804 total_size -= sz;
805 }
806 }
807
808out:
809 m->err = error;
810 complete(&m->complete);
811 pohmelfs_mcache_put(psb, m);
812
813 return error;
814}
815
816int pohmelfs_data_lock_response(struct netfs_state *st)
817{
818 struct pohmelfs_sb *psb = st->psb;
819 struct netfs_cmd *cmd = &st->cmd;
820 struct pohmelfs_mcache *m;
821 short err = (signed short)cmd->ext;
822 u64 id = cmd->id;
823
824 m = pohmelfs_mcache_search(psb, id);
825
826 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
827 __func__, cmd->id, (m) ? m->gen : 0, err);
828
829 if (!m) {
830 pohmelfs_data_recv(st, st->data, cmd->size);
831 printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id);
832 return -ENOENT;
833 }
834
835 if (cmd->size)
836 err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size);
837
838 m->err = err;
839 complete(&m->complete);
840 pohmelfs_mcache_put(psb, m);
841
842 return err;
843}
844
845static void __inline__ netfs_state_reset(struct netfs_state *st)
846{
847 netfs_state_lock_send(st);
848 netfs_state_exit(st);
849 netfs_state_init(st);
850 netfs_state_unlock_send(st);
851}
852
853/*
854 * Main receiving function, called from dedicated kernel thread.
855 */
856static int pohmelfs_recv(void *data)
857{
858 int err = -EINTR;
859 struct netfs_state *st = data;
860 struct netfs_cmd *cmd = &st->cmd;
861
862 while (!kthread_should_stop()) {
863 /*
864 * If socket will be reset after this statement, then
865 * pohmelfs_data_recv() will just fail and loop will
866 * start again, so it can be done without any locks.
867 *
868 * st->read_socket is needed to prevents state machine
869 * breaking between this data reading and subsequent one
870 * in protocol specific functions during connection reset.
871 * In case of reset we have to read next command and do
872 * not expect data for old command to magically appear in
873 * new connection.
874 */
875 st->read_socket = st->socket;
876 err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd));
877 if (err) {
878 msleep(1000);
879 continue;
880 }
881
882 netfs_convert_cmd(cmd);
883
884 dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
885 "ext: %u, csize: %u, cpad: %u.\n",
886 __func__, cmd->cmd, cmd->id, cmd->start,
887 cmd->size, cmd->ext, cmd->csize, cmd->cpad);
888
889 if (cmd->csize) {
890 struct pohmelfs_crypto_engine *e = &st->eng;
891
892 if (unlikely(cmd->csize > e->size/2)) {
893 netfs_state_reset(st);
894 continue;
895 }
896
897 if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) {
898 dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
899 "csize: %u != digest size %u.\n",
900 __func__, cmd->cmd, cmd->id, cmd->start, cmd->size,
901 cmd->csize, st->psb->crypto_attached_size);
902 netfs_state_reset(st);
903 continue;
904 }
905
906 err = pohmelfs_data_recv(st, e->data, cmd->csize);
907 if (err) {
908 netfs_state_reset(st);
909 continue;
910 }
911
912#ifdef CONFIG_POHMELFS_DEBUG
913 {
914 unsigned int i;
915 unsigned char *hash = e->data;
916
917 dprintk("%s: received hash: ", __func__);
918 for (i = 0; i < cmd->csize; ++i)
919 printk("%02x ", hash[i]);
920
921 printk("\n");
922 }
923#endif
924 cmd->size -= cmd->csize;
925 }
926
927 /*
928 * This should catch protocol breakage and random garbage instead of commands.
929 */
930 if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) {
931 netfs_state_reset(st);
932 continue;
933 }
934
935 switch (cmd->cmd) {
936 case NETFS_READ_PAGE:
937 err = pohmelfs_read_page_response(st);
938 break;
939 case NETFS_READDIR:
940 err = pohmelfs_readdir_response(st);
941 break;
942 case NETFS_LOOKUP:
943 err = pohmelfs_lookup_response(st);
944 break;
945 case NETFS_CREATE:
946 err = pohmelfs_create_response(st);
947 break;
948 case NETFS_REMOVE:
949 err = pohmelfs_remove_response(st);
950 break;
951 case NETFS_TRANS:
952 err = pohmelfs_transaction_response(st);
953 break;
954 case NETFS_PAGE_CACHE:
955 err = pohmelfs_page_cache_response(st);
956 break;
957 case NETFS_CAPABILITIES:
958 err = pohmelfs_capabilities_response(st);
959 break;
960 case NETFS_LOCK:
961 err = pohmelfs_data_lock_response(st);
962 break;
963 case NETFS_XATTR_GET:
964 err = pohmelfs_getxattr_response(st);
965 break;
966 default:
967 printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
968 __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext);
969 netfs_state_reset(st);
970 break;
971 }
972 }
973
974 while (!kthread_should_stop())
975 schedule_timeout_uninterruptible(msecs_to_jiffies(10));
976
977 return err;
978}
979
980int netfs_state_init(struct netfs_state *st)
981{
982 int err;
983 struct pohmelfs_ctl *ctl = &st->ctl;
984
985 err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket);
986 if (err) {
987 printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
988 __func__, ctl->addr.sa_family, ctl->type, ctl->proto, err);
989 goto err_out_exit;
990 }
991
992 st->socket->sk->sk_allocation = GFP_NOIO;
993 st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
994
995 err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0);
996 if (err) {
997 printk("%s: failed to connect to server: idx: %u, err: %d.\n",
998 __func__, st->psb->idx, err);
999 goto err_out_release;
1000 }
1001 st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
1002
1003 err = netfs_poll_init(st);
1004 if (err)
1005 goto err_out_release;
1006
1007 if (st->socket->ops->family == AF_INET) {
1008 struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr;
1009 printk(KERN_INFO "%s: (re)connected to peer %pi4:%d.\n", __func__,
1010 &sin->sin_addr.s_addr, ntohs(sin->sin_port));
1011 } else if (st->socket->ops->family == AF_INET6) {
1012 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr;
1013 printk(KERN_INFO "%s: (re)connected to peer %pi6:%d", __func__,
1014 &sin->sin6_addr, ntohs(sin->sin6_port));
1015 }
1016
1017 return 0;
1018
1019err_out_release:
1020 sock_release(st->socket);
1021err_out_exit:
1022 st->socket = NULL;
1023 return err;
1024}
1025
1026void netfs_state_exit(struct netfs_state *st)
1027{
1028 if (st->socket) {
1029 netfs_poll_exit(st);
1030 st->socket->ops->shutdown(st->socket, 2);
1031
1032 if (st->socket->ops->family == AF_INET) {
1033 struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
1034 printk(KERN_INFO "%s: disconnected from peer %pi4:%d.\n", __func__,
1035 &sin->sin_addr.s_addr, ntohs(sin->sin_port));
1036 } else if (st->socket->ops->family == AF_INET6) {
1037 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
1038 printk(KERN_INFO "%s: disconnected from peer %pi6:%d", __func__,
1039 &sin->sin6_addr, ntohs(sin->sin6_port));
1040 }
1041
1042 sock_release(st->socket);
1043 st->socket = NULL;
1044 st->read_socket = NULL;
1045 st->need_reset = 0;
1046 }
1047}
1048
1049int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf)
1050{
1051 struct netfs_state *st = &conf->state;
1052 int err = -ENOMEM;
1053
1054 mutex_init(&st->__state_lock);
1055 mutex_init(&st->__state_send_lock);
1056 init_waitqueue_head(&st->thread_wait);
1057
1058 st->psb = psb;
1059 st->trans_root = RB_ROOT;
1060 mutex_init(&st->trans_lock);
1061
1062 st->size = psb->trans_data_size;
1063 st->data = kmalloc(st->size, GFP_KERNEL);
1064 if (!st->data)
1065 goto err_out_exit;
1066
1067 if (psb->perform_crypto) {
1068 err = pohmelfs_crypto_engine_init(&st->eng, psb);
1069 if (err)
1070 goto err_out_free_data;
1071 }
1072
1073 err = netfs_state_init(st);
1074 if (err)
1075 goto err_out_free_engine;
1076
1077 st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx);
1078 if (IS_ERR(st->thread)) {
1079 err = PTR_ERR(st->thread);
1080 goto err_out_netfs_exit;
1081 }
1082
1083 if (!psb->active_state)
1084 psb->active_state = conf;
1085
1086 dprintk("%s: conf: %p, st: %p, socket: %p.\n",
1087 __func__, conf, st, st->socket);
1088 return 0;
1089
1090err_out_netfs_exit:
1091 netfs_state_exit(st);
1092err_out_free_engine:
1093 pohmelfs_crypto_engine_exit(&st->eng);
1094err_out_free_data:
1095 kfree(st->data);
1096err_out_exit:
1097 return err;
1098
1099}
1100
1101void pohmelfs_state_flush_transactions(struct netfs_state *st)
1102{
1103 struct rb_node *rb_node;
1104 struct netfs_trans_dst *dst;
1105
1106 mutex_lock(&st->trans_lock);
1107 for (rb_node = rb_first(&st->trans_root); rb_node; ) {
1108 dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
1109 rb_node = rb_next(rb_node);
1110
1111 dst->trans->result = -EINVAL;
1112 netfs_trans_remove_nolock(dst, st);
1113 netfs_trans_drop_dst_nostate(dst);
1114 }
1115 mutex_unlock(&st->trans_lock);
1116}
1117
1118static void pohmelfs_state_exit_one(struct pohmelfs_config *c)
1119{
1120 struct netfs_state *st = &c->state;
1121
1122 dprintk("%s: exiting, st: %p.\n", __func__, st);
1123 if (st->thread) {
1124 kthread_stop(st->thread);
1125 st->thread = NULL;
1126 }
1127
1128 netfs_state_lock_send(st);
1129 netfs_state_exit(st);
1130 netfs_state_unlock_send(st);
1131
1132 pohmelfs_state_flush_transactions(st);
1133
1134 pohmelfs_crypto_engine_exit(&st->eng);
1135 kfree(st->data);
1136
1137 kfree(c);
1138}
1139
1140/*
1141 * Initialize network stack. It searches for given ID in global
1142 * configuration table, this contains information of the remote server
1143 * (address (any supported by socket interface) and port, protocol and so on).
1144 */
1145int pohmelfs_state_init(struct pohmelfs_sb *psb)
1146{
1147 int err = -ENOMEM;
1148
1149 err = pohmelfs_copy_config(psb);
1150 if (err) {
1151 pohmelfs_state_exit(psb);
1152 return err;
1153 }
1154
1155 return 0;
1156}
1157
1158void pohmelfs_state_exit(struct pohmelfs_sb *psb)
1159{
1160 struct pohmelfs_config *c, *tmp;
1161
1162 list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
1163 list_del(&c->config_entry);
1164 pohmelfs_state_exit_one(c);
1165 }
1166}
1167
1168void pohmelfs_switch_active(struct pohmelfs_sb *psb)
1169{
1170 struct pohmelfs_config *c = psb->active_state;
1171
1172 if (!list_empty(&psb->state_list)) {
1173 if (c->config_entry.next != &psb->state_list) {
1174 psb->active_state = list_entry(c->config_entry.next,
1175 struct pohmelfs_config, config_entry);
1176 } else {
1177 psb->active_state = list_entry(psb->state_list.next,
1178 struct pohmelfs_config, config_entry);
1179 }
1180
1181 dprintk("%s: empty: %d, active %p -> %p.\n",
1182 __func__, list_empty(&psb->state_list), c,
1183 psb->active_state);
1184 } else
1185 psb->active_state = NULL;
1186}
1187
1188void pohmelfs_check_states(struct pohmelfs_sb *psb)
1189{
1190 struct pohmelfs_config *c, *tmp;
1191 LIST_HEAD(delete_list);
1192
1193 mutex_lock(&psb->state_lock);
1194 list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
1195 if (pohmelfs_config_check(c, psb->idx)) {
1196
1197 if (psb->active_state == c)
1198 pohmelfs_switch_active(psb);
1199 list_move(&c->config_entry, &delete_list);
1200 }
1201 }
1202 pohmelfs_copy_config(psb);
1203 mutex_unlock(&psb->state_lock);
1204
1205 list_for_each_entry_safe(c, tmp, &delete_list, config_entry) {
1206 list_del(&c->config_entry);
1207 pohmelfs_state_exit_one(c);
1208 }
1209}
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
deleted file mode 100644
index f26894f2a57..00000000000
--- a/drivers/staging/pohmelfs/netfs.h
+++ /dev/null
@@ -1,919 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#ifndef __NETFS_H
17#define __NETFS_H
18
19#include <linux/types.h>
20#include <linux/connector.h>
21#include <linux/backing-dev.h>
22
23#define POHMELFS_CN_IDX 5
24#define POHMELFS_CN_VAL 0
25
26#define POHMELFS_CTLINFO_ACK 1
27#define POHMELFS_NOINFO_ACK 2
28
29#define POHMELFS_NULL_IDX 65535
30
31/*
32 * Network command structure.
33 * Will be extended.
34 */
35struct netfs_cmd {
36 __u16 cmd; /* Command number */
37 __u16 csize; /* Attached crypto information size */
38 __u16 cpad; /* Attached padding size */
39 __u16 ext; /* External flags */
40 __u32 size; /* Size of the attached data */
41 __u32 trans; /* Transaction id */
42 __u64 id; /* Object ID to operate on. Used for feedback.*/
43 __u64 start; /* Start of the object. */
44 __u64 iv; /* IV sequence */
45 __u8 data[0];
46};
47
48static inline void netfs_convert_cmd(struct netfs_cmd *cmd)
49{
50 cmd->id = __be64_to_cpu(cmd->id);
51 cmd->start = __be64_to_cpu(cmd->start);
52 cmd->iv = __be64_to_cpu(cmd->iv);
53 cmd->cmd = __be16_to_cpu(cmd->cmd);
54 cmd->ext = __be16_to_cpu(cmd->ext);
55 cmd->csize = __be16_to_cpu(cmd->csize);
56 cmd->cpad = __be16_to_cpu(cmd->cpad);
57 cmd->size = __be32_to_cpu(cmd->size);
58}
59
60#define NETFS_TRANS_SINGLE_DST (1<<0)
61
62enum {
63 NETFS_READDIR = 1, /* Read directory for given inode number */
64 NETFS_READ_PAGE, /* Read data page from the server */
65 NETFS_WRITE_PAGE, /* Write data page to the server */
66 NETFS_CREATE, /* Create directory entry */
67 NETFS_REMOVE, /* Remove directory entry */
68
69 NETFS_LOOKUP, /* Lookup single object */
70 NETFS_LINK, /* Create a link */
71 NETFS_TRANS, /* Transaction */
72 NETFS_OPEN, /* Open intent */
73 NETFS_INODE_INFO, /* Metadata cache coherency synchronization message */
74
75 NETFS_PAGE_CACHE, /* Page cache invalidation message */
76 NETFS_READ_PAGES, /* Read multiple contiguous pages in one go */
77 NETFS_RENAME, /* Rename object */
78 NETFS_CAPABILITIES, /* Capabilities of the client, for example supported crypto */
79 NETFS_LOCK, /* Distributed lock message */
80
81 NETFS_XATTR_SET, /* Set extended attribute */
82 NETFS_XATTR_GET, /* Get extended attribute */
83 NETFS_CMD_MAX
84};
85
86enum {
87 POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */
88 POHMELFS_FLAGS_DEL, /* Network state control message for DEL */
89 POHMELFS_FLAGS_SHOW, /* Network state control message for SHOW */
90 POHMELFS_FLAGS_CRYPTO, /* Crypto data control message */
91 POHMELFS_FLAGS_MODIFY, /* Network state modification message */
92 POHMELFS_FLAGS_DUMP, /* Network state control message for SHOW ALL */
93 POHMELFS_FLAGS_FLUSH, /* Network state control message for FLUSH */
94};
95
96/*
97 * Always wanted to copy it from socket headers into public one,
98 * since they are __KERNEL__ protected there.
99 */
100#define _K_SS_MAXSIZE 128
101
102struct saddr {
103 unsigned short sa_family;
104 char addr[_K_SS_MAXSIZE];
105};
106
107enum {
108 POHMELFS_CRYPTO_HASH = 0,
109 POHMELFS_CRYPTO_CIPHER,
110};
111
112struct pohmelfs_crypto {
113 unsigned int idx; /* Config index */
114 unsigned short strlen; /* Size of the attached crypto string including 0-byte
115 * "cbc(aes)" for example */
116 unsigned short type; /* HMAC, cipher, both */
117 unsigned int keysize; /* Key size */
118 unsigned char data[0]; /* Algorithm string, key and IV */
119};
120
121#define POHMELFS_IO_PERM_READ (1<<0)
122#define POHMELFS_IO_PERM_WRITE (1<<1)
123
124/*
125 * Configuration command used to create table of different remote servers.
126 */
127struct pohmelfs_ctl {
128 __u32 idx; /* Config index */
129 __u32 type; /* Socket type */
130 __u32 proto; /* Socket protocol */
131 __u16 addrlen; /* Size of the address */
132 __u16 perm; /* IO permission */
133 __u16 prio; /* IO priority */
134 struct saddr addr; /* Remote server address */
135};
136
137/*
138 * Ack for userspace about requested command.
139 */
140struct pohmelfs_cn_ack {
141 struct cn_msg msg;
142 int error;
143 int msg_num;
144 int unused[3];
145 struct pohmelfs_ctl ctl;
146};
147
148/*
149 * Inode info structure used to sync with server.
150 * Check what stat() returns.
151 */
152struct netfs_inode_info {
153 unsigned int mode;
154 unsigned int nlink;
155 unsigned int uid;
156 unsigned int gid;
157 unsigned int blocksize;
158 unsigned int padding;
159 __u64 ino;
160 __u64 blocks;
161 __u64 rdev;
162 __u64 size;
163 __u64 version;
164};
165
166static inline void netfs_convert_inode_info(struct netfs_inode_info *info)
167{
168 info->mode = __cpu_to_be32(info->mode);
169 info->nlink = __cpu_to_be32(info->nlink);
170 info->uid = __cpu_to_be32(info->uid);
171 info->gid = __cpu_to_be32(info->gid);
172 info->blocksize = __cpu_to_be32(info->blocksize);
173 info->blocks = __cpu_to_be64(info->blocks);
174 info->rdev = __cpu_to_be64(info->rdev);
175 info->size = __cpu_to_be64(info->size);
176 info->version = __cpu_to_be64(info->version);
177 info->ino = __cpu_to_be64(info->ino);
178}
179
180/*
181 * Cache state machine.
182 */
183enum {
184 NETFS_COMMAND_PENDING = 0, /* Command is being executed */
185 NETFS_INODE_REMOTE_SYNCED, /* Inode was synced to server */
186 NETFS_INODE_REMOTE_DIR_SYNCED, /* Inode (directory) was synced from the server */
187 NETFS_INODE_OWNED, /* Inode is owned by given host */
188 NETFS_INODE_NEED_FLUSH, /* Inode has to be flushed to the server */
189};
190
191/*
192 * POHMELFS capabilities: information about supported
193 * crypto operations (hash/cipher, modes, key sizes and so on),
194 * root information (used/available size, number of objects, permissions)
195 */
196enum pohmelfs_capabilities {
197 POHMELFS_CRYPTO_CAPABILITIES = 0,
198 POHMELFS_ROOT_CAPABILITIES,
199};
200
201/* Read-only mount */
202#define POHMELFS_FLAGS_RO (1<<0)
203/* Extended attributes support on/off */
204#define POHMELFS_FLAGS_XATTR (1<<1)
205
206struct netfs_root_capabilities {
207 __u64 nr_files;
208 __u64 used, avail;
209 __u64 flags;
210};
211
212static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap)
213{
214 cap->nr_files = __cpu_to_be64(cap->nr_files);
215 cap->used = __cpu_to_be64(cap->used);
216 cap->avail = __cpu_to_be64(cap->avail);
217 cap->flags = __cpu_to_be64(cap->flags);
218}
219
220struct netfs_crypto_capabilities {
221 unsigned short hash_strlen; /* Hash string length, like "hmac(sha1) including 0 byte "*/
222 unsigned short cipher_strlen; /* Cipher string length with the same format */
223 unsigned int cipher_keysize; /* Cipher key size */
224};
225
226static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap)
227{
228 cap->hash_strlen = __cpu_to_be16(cap->hash_strlen);
229 cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen);
230 cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize);
231}
232
233enum pohmelfs_lock_type {
234 POHMELFS_LOCK_GRAB = (1<<15),
235
236 POHMELFS_READ_LOCK = 0,
237 POHMELFS_WRITE_LOCK,
238};
239
240struct netfs_lock {
241 __u64 start;
242 __u64 ino;
243 __u32 size;
244 __u32 type;
245};
246
247static inline void netfs_convert_lock(struct netfs_lock *lock)
248{
249 lock->start = __cpu_to_be64(lock->start);
250 lock->ino = __cpu_to_be64(lock->ino);
251 lock->size = __cpu_to_be32(lock->size);
252 lock->type = __cpu_to_be32(lock->type);
253}
254
255#ifdef __KERNEL__
256
257#include <linux/kernel.h>
258#include <linux/completion.h>
259#include <linux/rbtree.h>
260#include <linux/net.h>
261#include <linux/poll.h>
262
263/*
264 * Private POHMELFS cache of objects in directory.
265 */
266struct pohmelfs_name {
267 struct rb_node hash_node;
268
269 struct list_head sync_create_entry;
270
271 u64 ino;
272
273 u32 hash;
274 u32 mode;
275 u32 len;
276
277 char *data;
278};
279
280/*
281 * POHMELFS inode. Main object.
282 */
283struct pohmelfs_inode {
284 struct list_head inode_entry; /* Entry in superblock list.
285 * Objects which are not bound to dentry require to be dropped
286 * in ->put_super()
287 */
288 struct rb_root hash_root; /* The same, but indexed by name hash and len */
289 struct mutex offset_lock; /* Protect both above trees */
290
291 struct list_head sync_create_list; /* List of created but not yet synced to the server children */
292
293 unsigned int drop_count;
294
295 int lock_type; /* How this inode is locked: read or write */
296
297 int error; /* Transaction error for given inode */
298
299 long state; /* State machine above */
300
301 u64 ino; /* Inode number */
302 u64 total_len; /* Total length of all children names, used to create offsets */
303
304 struct inode vfs_inode;
305};
306
307struct netfs_trans;
308typedef int (*netfs_trans_complete_t)(struct page **pages, unsigned int page_num,
309 void *private, int err);
310
311struct netfs_state;
312struct pohmelfs_sb;
313
314struct netfs_trans {
315 /*
316 * Transaction header and attached contiguous data live here.
317 */
318 struct iovec iovec;
319
320 /*
321 * Pages attached to transaction.
322 */
323 struct page **pages;
324
325 /*
326 * List and protecting lock for transaction destination
327 * network states.
328 */
329 spinlock_t dst_lock;
330 struct list_head dst_list;
331
332 /*
333 * Number of users for given transaction.
334 * For example each network state attached to transaction
335 * via dst_list increases it.
336 */
337 atomic_t refcnt;
338
339 /*
340 * Number of pages attached to given transaction.
341 * Some slots in above page array can be NULL, since
342 * for example page can be under writeback already,
343 * so we skip it in this transaction.
344 */
345 unsigned int page_num;
346
347 /*
348 * Transaction flags: single dst or broadcast and so on.
349 */
350 unsigned int flags;
351
352 /*
353 * Size of the data, which can be placed into
354 * iovec.iov_base area.
355 */
356 unsigned int total_size;
357
358 /*
359 * Number of pages to be sent to remote server.
360 * Usually equal to above page_num, but in case of partial
361 * writeback it can accumulate only pages already completed
362 * previous writeback.
363 */
364 unsigned int attached_pages;
365
366 /*
367 * Attached number of bytes in all above pages.
368 */
369 unsigned int attached_size;
370
371 /*
372 * Unique transacton generation number.
373 * Used as identity in the network state tree of transactions.
374 */
375 unsigned int gen;
376
377 /*
378 * Transaction completion status.
379 */
380 int result;
381
382 /*
383 * Superblock this transaction belongs to
384 */
385 struct pohmelfs_sb *psb;
386
387 /*
388 * Crypto engine, which processed this transaction.
389 * Can be not NULL only if crypto engine holds encrypted pages.
390 */
391 struct pohmelfs_crypto_engine *eng;
392
393 /* Private data */
394 void *private;
395
396 /* Completion callback, invoked just before transaction is destroyed */
397 netfs_trans_complete_t complete;
398};
399
400static inline int netfs_trans_cur_len(struct netfs_trans *t)
401{
402 return (signed)(t->total_size - t->iovec.iov_len);
403}
404
405static inline void *netfs_trans_current(struct netfs_trans *t)
406{
407 return t->iovec.iov_base + t->iovec.iov_len;
408}
409
410struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
411 unsigned int flags, unsigned int nr);
412void netfs_trans_free(struct netfs_trans *t);
413int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb);
414int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb);
415
416static inline void netfs_trans_reset(struct netfs_trans *t)
417{
418 t->complete = NULL;
419}
420
421struct netfs_trans_dst {
422 struct list_head trans_entry;
423 struct rb_node state_entry;
424
425 unsigned long send_time;
426
427 /*
428 * Times this transaction was resent to its old or new,
429 * depending on flags, destinations. When it reaches maximum
430 * allowed number, specified in superblock->trans_retries,
431 * transaction will be freed with ETIMEDOUT error.
432 */
433 unsigned int retries;
434
435 struct netfs_trans *trans;
436 struct netfs_state *state;
437};
438
439struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen);
440void netfs_trans_drop_dst(struct netfs_trans_dst *dst);
441void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst);
442void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st);
443void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st);
444int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb);
445int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st);
446
447int netfs_trans_init(void);
448void netfs_trans_exit(void);
449
450struct pohmelfs_crypto_engine {
451 u64 iv; /* Crypto IV for current operation */
452 unsigned long timeout; /* Crypto waiting timeout */
453 unsigned int size; /* Size of crypto scratchpad */
454 void *data; /* Temporal crypto scratchpad */
455 /*
456 * Crypto operations performed on objects.
457 */
458 struct crypto_hash *hash;
459 struct crypto_ablkcipher *cipher;
460
461 struct pohmelfs_crypto_thread *thread; /* Crypto thread which hosts this engine */
462
463 struct page **pages;
464 unsigned int page_num;
465};
466
467struct pohmelfs_crypto_thread {
468 struct list_head thread_entry;
469
470 struct task_struct *thread;
471 struct pohmelfs_sb *psb;
472
473 struct pohmelfs_crypto_engine eng;
474
475 struct netfs_trans *trans;
476
477 wait_queue_head_t wait;
478 int error;
479
480 unsigned int size;
481 struct page *page;
482};
483
484void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th);
485
486/*
487 * Network state, attached to one server.
488 */
489struct netfs_state {
490 struct mutex __state_lock; /* Can not allow to use the same socket simultaneously */
491 struct mutex __state_send_lock;
492 struct netfs_cmd cmd; /* Cached command */
493 struct netfs_inode_info info; /* Cached inode info */
494
495 void *data; /* Cached some data */
496 unsigned int size; /* Size of that data */
497
498 struct pohmelfs_sb *psb; /* Superblock */
499
500 struct task_struct *thread; /* Async receiving thread */
501
502 /* Waiting/polling machinery */
503 wait_queue_t wait;
504 wait_queue_head_t *whead;
505 wait_queue_head_t thread_wait;
506
507 struct mutex trans_lock;
508 struct rb_root trans_root;
509
510 struct pohmelfs_ctl ctl; /* Remote peer */
511
512 struct socket *socket; /* Socket object */
513 struct socket *read_socket; /* Cached pointer to socket object.
514 * Used to determine if between lock drops socket was changed.
515 * Never used to read data or any kind of access.
516 */
517 /*
518 * Crypto engines to process incoming data.
519 */
520 struct pohmelfs_crypto_engine eng;
521
522 int need_reset;
523};
524
525int netfs_state_init(struct netfs_state *st);
526void netfs_state_exit(struct netfs_state *st);
527
528static inline void netfs_state_lock_send(struct netfs_state *st)
529{
530 mutex_lock(&st->__state_send_lock);
531}
532
533static inline int netfs_state_trylock_send(struct netfs_state *st)
534{
535 return mutex_trylock(&st->__state_send_lock);
536}
537
538static inline void netfs_state_unlock_send(struct netfs_state *st)
539{
540 BUG_ON(!mutex_is_locked(&st->__state_send_lock));
541
542 mutex_unlock(&st->__state_send_lock);
543}
544
545static inline void netfs_state_lock(struct netfs_state *st)
546{
547 mutex_lock(&st->__state_lock);
548}
549
550static inline void netfs_state_unlock(struct netfs_state *st)
551{
552 BUG_ON(!mutex_is_locked(&st->__state_lock));
553
554 mutex_unlock(&st->__state_lock);
555}
556
557static inline unsigned int netfs_state_poll(struct netfs_state *st)
558{
559 unsigned int revents = POLLHUP | POLLERR;
560
561 netfs_state_lock(st);
562 if (st->socket)
563 revents = st->socket->ops->poll(NULL, st->socket, NULL);
564 netfs_state_unlock(st);
565
566 return revents;
567}
568
569struct pohmelfs_config;
570
571struct pohmelfs_sb {
572 struct rb_root mcache_root;
573 struct mutex mcache_lock;
574 atomic_long_t mcache_gen;
575 unsigned long mcache_timeout;
576
577 unsigned int idx;
578
579 unsigned int trans_retries;
580
581 atomic_t trans_gen;
582
583 unsigned int crypto_attached_size;
584 unsigned int crypto_align_size;
585
586 unsigned int crypto_fail_unsupported;
587
588 unsigned int crypto_thread_num;
589 struct list_head crypto_active_list, crypto_ready_list;
590 struct mutex crypto_thread_lock;
591
592 unsigned int trans_max_pages;
593 unsigned long trans_data_size;
594 unsigned long trans_timeout;
595
596 unsigned long drop_scan_timeout;
597 unsigned long trans_scan_timeout;
598
599 unsigned long wait_on_page_timeout;
600
601 struct list_head flush_list;
602 struct list_head drop_list;
603 spinlock_t ino_lock;
604 u64 ino;
605
606 /*
607 * Remote nodes POHMELFS connected to.
608 */
609 struct list_head state_list;
610 struct mutex state_lock;
611
612 /*
613 * Currently active state to request data from.
614 */
615 struct pohmelfs_config *active_state;
616
617
618 wait_queue_head_t wait;
619
620 /*
621 * Timed checks: stale transactions, inodes to be freed and so on.
622 */
623 struct delayed_work dwork;
624 struct delayed_work drop_dwork;
625
626 struct super_block *sb;
627
628 struct backing_dev_info bdi;
629
630 /*
631 * Algorithm strings.
632 */
633 char *hash_string;
634 char *cipher_string;
635
636 u8 *hash_key;
637 u8 *cipher_key;
638
639 /*
640 * Algorithm string lengths.
641 */
642 unsigned int hash_strlen;
643 unsigned int cipher_strlen;
644 unsigned int hash_keysize;
645 unsigned int cipher_keysize;
646
647 /*
648 * Controls whether to perfrom crypto processing or not.
649 */
650 int perform_crypto;
651
652 /*
653 * POHMELFS statistics.
654 */
655 u64 total_size;
656 u64 avail_size;
657 atomic_long_t total_inodes;
658
659 /*
660 * Xattr support, read-only and so on.
661 */
662 u64 state_flags;
663
664 /*
665 * Temporary storage to detect changes in the wait queue.
666 */
667 long flags;
668};
669
670static inline void netfs_trans_update(struct netfs_cmd *cmd,
671 struct netfs_trans *t, unsigned int size)
672{
673 unsigned int sz = ALIGN(size, t->psb->crypto_align_size);
674
675 t->iovec.iov_len += sizeof(struct netfs_cmd) + sz;
676 cmd->cpad = __cpu_to_be16(sz - size);
677}
678
679static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb)
680{
681 return sb->s_fs_info;
682}
683
684static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode)
685{
686 return container_of(inode, struct pohmelfs_inode, vfs_inode);
687}
688
689static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb)
690{
691 u64 ino;
692
693 spin_lock(&psb->ino_lock);
694 ino = psb->ino++;
695 spin_unlock(&psb->ino_lock);
696
697 return ino;
698}
699
700static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi)
701{
702 struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
703
704 spin_lock(&psb->ino_lock);
705 list_move_tail(&pi->inode_entry, &psb->drop_list);
706 pi->drop_count++;
707 spin_unlock(&psb->ino_lock);
708}
709
710struct pohmelfs_config {
711 struct list_head config_entry;
712
713 struct netfs_state state;
714};
715
716struct pohmelfs_config_group {
717 /*
718 * Entry in the global config group list.
719 */
720 struct list_head group_entry;
721
722 /*
723 * Index of the current group.
724 */
725 unsigned int idx;
726 /*
727 * Number of config_list entries in this group entry.
728 */
729 unsigned int num_entry;
730 /*
731 * Algorithm strings.
732 */
733 char *hash_string;
734 char *cipher_string;
735
736 /*
737 * Algorithm string lengths.
738 */
739 unsigned int hash_strlen;
740 unsigned int cipher_strlen;
741
742 /*
743 * Key and its size.
744 */
745 unsigned int hash_keysize;
746 unsigned int cipher_keysize;
747 u8 *hash_key;
748 u8 *cipher_key;
749
750 /*
751 * List of config entries (network state info) for given idx.
752 */
753 struct list_head config_list;
754};
755
756int __init pohmelfs_config_init(void);
757void pohmelfs_config_exit(void);
758int pohmelfs_copy_config(struct pohmelfs_sb *psb);
759int pohmelfs_copy_crypto(struct pohmelfs_sb *psb);
760int pohmelfs_config_check(struct pohmelfs_config *config, int idx);
761int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf);
762
763extern const struct file_operations pohmelfs_dir_fops;
764extern const struct inode_operations pohmelfs_dir_inode_ops;
765
766int pohmelfs_state_init(struct pohmelfs_sb *psb);
767void pohmelfs_state_exit(struct pohmelfs_sb *psb);
768void pohmelfs_state_flush_transactions(struct netfs_state *st);
769
770void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info);
771
772void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
773void pohmelfs_free_names(struct pohmelfs_inode *parent);
774struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash);
775
776void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi);
777
778struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
779 struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode);
780
781int pohmelfs_write_create_inode(struct pohmelfs_inode *pi);
782
783int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans);
784int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
785
786struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
787 struct pohmelfs_inode *parent, struct qstr *str,
788 struct netfs_inode_info *info, int link);
789
790int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr);
791int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr);
792
793int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
794 netfs_trans_complete_t complete, void *priv, u64 start);
795int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
796 unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start);
797
798void pohmelfs_check_states(struct pohmelfs_sb *psb);
799void pohmelfs_switch_active(struct pohmelfs_sb *psb);
800
801int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len);
802int pohmelfs_path_length(struct pohmelfs_inode *pi);
803
804struct pohmelfs_crypto_completion {
805 struct completion complete;
806 int error;
807};
808
809int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb);
810void pohmelfs_crypto_exit(struct pohmelfs_sb *psb);
811int pohmelfs_crypto_init(struct pohmelfs_sb *psb);
812
813int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb);
814void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e);
815
816int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv,
817 void *data, struct page *page, unsigned int size);
818int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
819 struct page *page, unsigned int size, u64 iv);
820
821static inline u64 pohmelfs_gen_iv(struct netfs_trans *t)
822{
823 u64 iv = t->gen;
824
825 iv <<= 32;
826 iv |= ((unsigned long)t) & 0xffffffff;
827
828 return iv;
829}
830
831int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
832int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
833int pohmelfs_data_lock_response(struct netfs_state *st);
834
835static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type)
836{
837 if (test_bit(NETFS_INODE_OWNED, &pi->state)) {
838 if (type == pi->lock_type)
839 return 0;
840 if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK))
841 return 0;
842 }
843
844 if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
845 return 0;
846
847 return 1;
848}
849
850int __init pohmelfs_mcache_init(void);
851void pohmelfs_mcache_exit(void);
852
853/* #define CONFIG_POHMELFS_DEBUG */
854
855#ifdef CONFIG_POHMELFS_DEBUG
856#define dprintka(f, a...) printk(f, ##a)
857#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a)
858#else
859#define dprintka(f, a...) do {} while (0)
860#define dprintk(f, a...) do {} while (0)
861#endif
862
863static inline void netfs_trans_get(struct netfs_trans *t)
864{
865 atomic_inc(&t->refcnt);
866}
867
868static inline void netfs_trans_put(struct netfs_trans *t)
869{
870 if (atomic_dec_and_test(&t->refcnt)) {
871 dprintk("%s: t: %p, gen: %u, err: %d.\n",
872 __func__, t, t->gen, t->result);
873 if (t->complete)
874 t->complete(t->pages, t->page_num,
875 t->private, t->result);
876 netfs_trans_free(t);
877 }
878}
879
880struct pohmelfs_mcache {
881 struct rb_node mcache_entry;
882 struct completion complete;
883
884 atomic_t refcnt;
885
886 u64 gen;
887
888 void *data;
889 u64 start;
890 u32 size;
891 int err;
892
893 struct netfs_inode_info info;
894};
895
896struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
897 unsigned int size, void *data);
898void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
899struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen);
900void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
901
902static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m)
903{
904 atomic_inc(&m->refcnt);
905}
906
907static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb,
908 struct pohmelfs_mcache *m)
909{
910 if (atomic_dec_and_test(&m->refcnt))
911 pohmelfs_mcache_free(psb, m);
912}
913
914/*#define POHMELFS_TRUNCATE_ON_INODE_FLUSH
915 */
916
917#endif /* __KERNEL__*/
918
919#endif /* __NETFS_H */
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
deleted file mode 100644
index 400a9fc386a..00000000000
--- a/drivers/staging/pohmelfs/path_entry.c
+++ /dev/null
@@ -1,120 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/module.h>
17#include <linux/fs.h>
18#include <linux/ktime.h>
19#include <linux/fs_struct.h>
20#include <linux/pagemap.h>
21#include <linux/writeback.h>
22#include <linux/mount.h>
23#include <linux/mm.h>
24
25#include "netfs.h"
26
27#define UNHASHED_OBSCURE_STRING_SIZE sizeof(" (deleted)")
28
29/*
30 * Create path from root for given inode.
31 * Path is formed as set of stuctures, containing name of the object
32 * and its inode data (mode, permissions and so on).
33 */
34int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len)
35{
36 struct path path;
37 struct dentry *d;
38 char *ptr;
39 int err = 0, strlen, reduce = 0;
40
41 d = d_find_alias(&pi->vfs_inode);
42 if (!d) {
43 printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry));
44 return -ENOENT;
45 }
46
47 spin_lock(&current->fs->lock);
48 path.mnt = mntget(current->fs->root.mnt);
49 spin_unlock(&current->fs->lock);
50
51 path.dentry = d;
52
53 if (!IS_ROOT(d) && d_unhashed(d))
54 reduce = 1;
55
56 ptr = d_path(&path, data, len);
57 if (IS_ERR(ptr)) {
58 err = PTR_ERR(ptr);
59 goto out;
60 }
61
62 if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) {
63 char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE;
64 *end = '\0';
65 }
66
67 strlen = len - (ptr - (char *)data);
68 memmove(data, ptr, strlen);
69 ptr = data;
70
71 err = strlen;
72
73 dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n",
74 __func__, d->d_name.name, d->d_name.len, len, ptr, strlen);
75
76out:
77 dput(d);
78 mntput(path.mnt);
79
80 return err;
81}
82
83int pohmelfs_path_length(struct pohmelfs_inode *pi)
84{
85 struct dentry *d, *root, *first;
86 int len;
87 unsigned seq;
88
89 first = d_find_alias(&pi->vfs_inode);
90 if (!first) {
91 dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
92 return -ENOENT;
93 }
94
95 spin_lock(&current->fs->lock);
96 root = dget(current->fs->root.dentry);
97 spin_unlock(&current->fs->lock);
98
99rename_retry:
100 len = 1; /* Root slash */
101 d = first;
102 seq = read_seqbegin(&rename_lock);
103 rcu_read_lock();
104
105 if (!IS_ROOT(d) && d_unhashed(d))
106 len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
107
108 while (d && d != root && !IS_ROOT(d)) {
109 len += d->d_name.len + 1; /* Plus slash */
110 d = d->d_parent;
111 }
112 rcu_read_unlock();
113 if (read_seqretry(&rename_lock, seq))
114 goto rename_retry;
115
116 dput(root);
117 dput(first);
118
119 return len + 1; /* Including zero-byte */
120}
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
deleted file mode 100644
index 06c1a7451b1..00000000000
--- a/drivers/staging/pohmelfs/trans.c
+++ /dev/null
@@ -1,706 +0,0 @@
1/*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
4 *
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.
9 *
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.
14 */
15
16#include <linux/module.h>
17#include <linux/crypto.h>
18#include <linux/fs.h>
19#include <linux/jhash.h>
20#include <linux/hash.h>
21#include <linux/ktime.h>
22#include <linux/mempool.h>
23#include <linux/mm.h>
24#include <linux/mount.h>
25#include <linux/pagemap.h>
26#include <linux/parser.h>
27#include <linux/poll.h>
28#include <linux/swap.h>
29#include <linux/slab.h>
30#include <linux/statfs.h>
31#include <linux/writeback.h>
32
33#include "netfs.h"
34
35static struct kmem_cache *netfs_trans_dst;
36static mempool_t *netfs_trans_dst_pool;
37
38static void netfs_trans_init_static(struct netfs_trans *t, int num, int size)
39{
40 t->page_num = num;
41 t->total_size = size;
42 atomic_set(&t->refcnt, 1);
43
44 spin_lock_init(&t->dst_lock);
45 INIT_LIST_HEAD(&t->dst_list);
46}
47
48static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
49{
50 int err = 0;
51 unsigned int i, attached_pages = t->attached_pages, ci;
52 struct msghdr msg;
53 struct page **pages = (t->eng) ? t->eng->pages : t->pages;
54 struct page *p;
55 unsigned int size;
56
57 msg.msg_name = NULL;
58 msg.msg_namelen = 0;
59 msg.msg_control = NULL;
60 msg.msg_controllen = 0;
61 msg.msg_flags = MSG_WAITALL | MSG_MORE;
62
63 ci = 0;
64 for (i = 0; i < t->page_num; ++i) {
65 struct page *page = pages[ci];
66 struct netfs_cmd cmd;
67 struct iovec io;
68
69 p = t->pages[i];
70
71 if (!p)
72 continue;
73
74 size = page_private(p);
75
76 io.iov_base = &cmd;
77 io.iov_len = sizeof(struct netfs_cmd);
78
79 cmd.cmd = NETFS_WRITE_PAGE;
80 cmd.ext = 0;
81 cmd.id = 0;
82 cmd.size = size;
83 cmd.start = p->index;
84 cmd.start <<= PAGE_CACHE_SHIFT;
85 cmd.csize = 0;
86 cmd.cpad = 0;
87 cmd.iv = pohmelfs_gen_iv(t);
88
89 netfs_convert_cmd(&cmd);
90
91 msg.msg_iov = &io;
92 msg.msg_iovlen = 1;
93 msg.msg_flags = MSG_WAITALL | MSG_MORE;
94
95 err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd));
96 if (err <= 0) {
97 printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n",
98 __func__, i, t->page_num, t, t->gen, err);
99 if (err == 0)
100 err = -ECONNRESET;
101 goto err_out;
102 }
103
104 msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 :
105 MSG_MORE);
106
107 err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags);
108 if (err <= 0) {
109 printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n",
110 __func__, i, t->page_num, t, t->gen, size, err);
111 if (err == 0)
112 err = -ECONNRESET;
113 goto err_out;
114 }
115
116 dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n",
117 __func__, i, t->page_num, t, t->gen, page, p, size);
118
119 err = 0;
120 attached_pages--;
121 if (!attached_pages)
122 break;
123 ci++;
124
125 continue;
126
127err_out:
128 printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err);
129 netfs_state_exit(st);
130 break;
131 }
132
133 return err;
134}
135
136int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
137{
138 int err;
139 struct msghdr msg;
140
141 BUG_ON(!t->iovec.iov_len);
142 BUG_ON(t->iovec.iov_len > 1024*1024*1024);
143
144 netfs_state_lock_send(st);
145 if (!st->socket) {
146 err = netfs_state_init(st);
147 if (err)
148 goto err_out_unlock_return;
149 }
150
151 msg.msg_iov = &t->iovec;
152 msg.msg_iovlen = 1;
153 msg.msg_name = NULL;
154 msg.msg_namelen = 0;
155 msg.msg_control = NULL;
156 msg.msg_controllen = 0;
157 msg.msg_flags = MSG_WAITALL;
158
159 if (t->attached_pages)
160 msg.msg_flags |= MSG_MORE;
161
162 err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len);
163 if (err <= 0) {
164 printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n",
165 __func__, t, t->gen, t->iovec.iov_len, err);
166 if (err == 0)
167 err = -ECONNRESET;
168 goto err_out_unlock_return;
169 }
170
171 dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
172 __func__, (t->page_num) ? "partial" : "full",
173 t, t->gen, t->iovec.iov_len, t->page_num);
174
175 err = 0;
176 if (t->attached_pages)
177 err = netfs_trans_send_pages(t, st);
178
179err_out_unlock_return:
180
181 if (st->need_reset)
182 netfs_state_exit(st);
183
184 netfs_state_unlock_send(st);
185
186 dprintk("%s: t: %p, gen: %u, err: %d.\n",
187 __func__, t, t->gen, err);
188
189 t->result = err;
190 return err;
191}
192
193static inline int netfs_trans_cmp(unsigned int gen, unsigned int new)
194{
195 if (gen < new)
196 return 1;
197 if (gen > new)
198 return -1;
199 return 0;
200}
201
202struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen)
203{
204 struct rb_root *root = &st->trans_root;
205 struct rb_node *n = root->rb_node;
206 struct netfs_trans_dst *tmp, *ret = NULL;
207 struct netfs_trans *t;
208 int cmp;
209
210 while (n) {
211 tmp = rb_entry(n, struct netfs_trans_dst, state_entry);
212 t = tmp->trans;
213
214 cmp = netfs_trans_cmp(t->gen, gen);
215 if (cmp < 0)
216 n = n->rb_left;
217 else if (cmp > 0)
218 n = n->rb_right;
219 else {
220 ret = tmp;
221 break;
222 }
223 }
224
225 return ret;
226}
227
228static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st)
229{
230 struct rb_root *root = &st->trans_root;
231 struct rb_node **n = &root->rb_node, *parent = NULL;
232 struct netfs_trans_dst *ret = NULL, *tmp;
233 struct netfs_trans *t = NULL, *new = ndst->trans;
234 int cmp;
235
236 while (*n) {
237 parent = *n;
238
239 tmp = rb_entry(parent, struct netfs_trans_dst, state_entry);
240 t = tmp->trans;
241
242 cmp = netfs_trans_cmp(t->gen, new->gen);
243 if (cmp < 0)
244 n = &parent->rb_left;
245 else if (cmp > 0)
246 n = &parent->rb_right;
247 else {
248 ret = tmp;
249 break;
250 }
251 }
252
253 if (ret) {
254 printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, "
255 "new: gen: %u, flags: %x, send_time: %lu.\n",
256 __func__, t->gen, t->flags, ret->send_time,
257 new->gen, new->flags, ndst->send_time);
258 return -EEXIST;
259 }
260
261 rb_link_node(&ndst->state_entry, parent, n);
262 rb_insert_color(&ndst->state_entry, root);
263 ndst->send_time = jiffies;
264
265 return 0;
266}
267
268int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st)
269{
270 if (dst && dst->state_entry.rb_parent_color) {
271 rb_erase(&dst->state_entry, &st->trans_root);
272 dst->state_entry.rb_parent_color = 0;
273 return 1;
274 }
275 return 0;
276}
277
278static int netfs_trans_remove_state(struct netfs_trans_dst *dst)
279{
280 int ret;
281 struct netfs_state *st = dst->state;
282
283 mutex_lock(&st->trans_lock);
284 ret = netfs_trans_remove_nolock(dst, st);
285 mutex_unlock(&st->trans_lock);
286
287 return ret;
288}
289
290/*
291 * Create new destination for given transaction associated with given network state.
292 * Transaction's reference counter is bumped and will be dropped when either
293 * reply is received or when async timeout detection task will fail resending
294 * and drop transaction.
295 */
296static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st)
297{
298 struct netfs_trans_dst *dst;
299 int err;
300
301 dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL);
302 if (!dst)
303 return -ENOMEM;
304
305 dst->retries = 0;
306 dst->send_time = 0;
307 dst->state = st;
308 dst->trans = t;
309 netfs_trans_get(t);
310
311 mutex_lock(&st->trans_lock);
312 err = netfs_trans_insert(dst, st);
313 mutex_unlock(&st->trans_lock);
314
315 if (err)
316 goto err_out_free;
317
318 spin_lock(&t->dst_lock);
319 list_add_tail(&dst->trans_entry, &t->dst_list);
320 spin_unlock(&t->dst_lock);
321
322 return 0;
323
324err_out_free:
325 t->result = err;
326 netfs_trans_put(t);
327 mempool_free(dst, netfs_trans_dst_pool);
328 return err;
329}
330
331static void netfs_trans_free_dst(struct netfs_trans_dst *dst)
332{
333 netfs_trans_put(dst->trans);
334 mempool_free(dst, netfs_trans_dst_pool);
335}
336
337static void netfs_trans_remove_dst(struct netfs_trans_dst *dst)
338{
339 if (netfs_trans_remove_state(dst))
340 netfs_trans_free_dst(dst);
341}
342
343/*
344 * Drop destination transaction entry when we know it.
345 */
346void netfs_trans_drop_dst(struct netfs_trans_dst *dst)
347{
348 struct netfs_trans *t = dst->trans;
349
350 spin_lock(&t->dst_lock);
351 list_del_init(&dst->trans_entry);
352 spin_unlock(&t->dst_lock);
353
354 netfs_trans_remove_dst(dst);
355}
356
357/*
358 * Drop destination transaction entry when we know it and when we
359 * already removed dst from state tree.
360 */
361void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst)
362{
363 struct netfs_trans *t = dst->trans;
364
365 spin_lock(&t->dst_lock);
366 list_del_init(&dst->trans_entry);
367 spin_unlock(&t->dst_lock);
368
369 netfs_trans_free_dst(dst);
370}
371
372/*
373 * This drops destination transaction entry from appropriate network state
374 * tree and drops related reference counter. It is possible that transaction
375 * will be freed here if its reference counter hits zero.
376 * Destination transaction entry will be freed.
377 */
378void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st)
379{
380 struct netfs_trans_dst *dst, *tmp, *ret = NULL;
381
382 spin_lock(&t->dst_lock);
383 list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
384 if (dst->state == st) {
385 ret = dst;
386 list_del(&dst->trans_entry);
387 break;
388 }
389 }
390 spin_unlock(&t->dst_lock);
391
392 if (ret)
393 netfs_trans_remove_dst(ret);
394}
395
396/*
397 * This drops destination transaction entry from appropriate network state
398 * tree and drops related reference counter. It is possible that transaction
399 * will be freed here if its reference counter hits zero.
400 * Destination transaction entry will be freed.
401 */
402void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st)
403{
404 struct netfs_trans_dst *dst, *tmp, *ret;
405
406 spin_lock(&t->dst_lock);
407 ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry);
408 if (ret->state != st) {
409 ret = NULL;
410 list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
411 if (dst->state == st) {
412 ret = dst;
413 list_del_init(&dst->trans_entry);
414 break;
415 }
416 }
417 } else {
418 list_del(&ret->trans_entry);
419 }
420 spin_unlock(&t->dst_lock);
421
422 if (ret)
423 netfs_trans_remove_dst(ret);
424}
425
426static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st)
427{
428 int err;
429
430 err = netfs_trans_push_dst(t, st);
431 if (err)
432 return err;
433
434 err = netfs_trans_send(t, st);
435 if (err)
436 goto err_out_free;
437
438 if (t->flags & NETFS_TRANS_SINGLE_DST)
439 pohmelfs_switch_active(st->psb);
440
441 return 0;
442
443err_out_free:
444 t->result = err;
445 netfs_trans_drop_last(t, st);
446
447 return err;
448}
449
450int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb)
451{
452 struct pohmelfs_config *c;
453 int err = -ENODEV;
454 struct netfs_state *st;
455#if 0
456 dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n",
457 __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state);
458#endif
459 mutex_lock(&psb->state_lock);
460 list_for_each_entry(c, &psb->state_list, config_entry) {
461 st = &c->state;
462
463 if (t->flags & NETFS_TRANS_SINGLE_DST) {
464 if (!(st->ctl.perm & POHMELFS_IO_PERM_READ))
465 continue;
466 } else {
467 if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE))
468 continue;
469 }
470
471 if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) &&
472 (t->flags & NETFS_TRANS_SINGLE_DST))
473 st = &psb->active_state->state;
474
475 err = netfs_trans_push(t, st);
476 if (!err && (t->flags & NETFS_TRANS_SINGLE_DST))
477 break;
478 }
479
480 mutex_unlock(&psb->state_lock);
481#if 0
482 dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n",
483 __func__, t, t->gen, t->iovec.iov_len, t->page_num, err);
484#endif
485 if (err)
486 t->result = err;
487 return err;
488}
489
490int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb)
491{
492 int err;
493 struct netfs_cmd *cmd = t->iovec.iov_base;
494
495 t->gen = atomic_inc_return(&psb->trans_gen);
496
497 cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
498 t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
499 cmd->cmd = NETFS_TRANS;
500 cmd->start = t->gen;
501 cmd->id = 0;
502
503 if (psb->perform_crypto) {
504 cmd->ext = psb->crypto_attached_size;
505 cmd->csize = psb->crypto_attached_size;
506 }
507
508 dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n",
509 __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages);
510 err = pohmelfs_trans_crypt(t, psb);
511 if (err) {
512 t->result = err;
513 netfs_convert_cmd(cmd);
514 dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n",
515 __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err);
516 }
517 netfs_trans_put(t);
518 return err;
519}
520
521/*
522 * Resend transaction to remote server(s).
523 * If new servers were added into superblock, we can try to send data
524 * to them too.
525 *
526 * It is called under superblock's state_lock, so we can safely
527 * dereference psb->state_list. Also, transaction's reference counter is
528 * bumped, so it can not go away under us, thus we can safely access all
529 * its members. State is locked.
530 *
531 * This function returns 0 if transaction was successfully sent to at
532 * least one destination target.
533 */
534int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb)
535{
536 struct netfs_trans_dst *dst;
537 struct netfs_state *st;
538 struct pohmelfs_config *c;
539 int err, exist, error = -ENODEV;
540
541 list_for_each_entry(c, &psb->state_list, config_entry) {
542 st = &c->state;
543
544 exist = 0;
545 spin_lock(&t->dst_lock);
546 list_for_each_entry(dst, &t->dst_list, trans_entry) {
547 if (st == dst->state) {
548 exist = 1;
549 break;
550 }
551 }
552 spin_unlock(&t->dst_lock);
553
554 if (exist) {
555 if (!(t->flags & NETFS_TRANS_SINGLE_DST) ||
556 (c->config_entry.next == &psb->state_list)) {
557 dprintk("%s: resending st: %p, t: %p, gen: %u.\n",
558 __func__, st, t, t->gen);
559 err = netfs_trans_send(t, st);
560 if (!err)
561 error = 0;
562 }
563 continue;
564 }
565
566 dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n",
567 __func__, st, t, t->gen);
568 err = netfs_trans_push(t, st);
569 if (err)
570 continue;
571 error = 0;
572 if (t->flags & NETFS_TRANS_SINGLE_DST)
573 break;
574 }
575
576 t->result = error;
577 return error;
578}
579
580void *netfs_trans_add(struct netfs_trans *t, unsigned int size)
581{
582 struct iovec *io = &t->iovec;
583 void *ptr;
584
585 if (size > t->total_size) {
586 ptr = ERR_PTR(-EINVAL);
587 goto out;
588 }
589
590 if (io->iov_len + size > t->total_size) {
591 dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n",
592 __func__, t, t->gen, io->iov_len, size, t->total_size);
593 ptr = ERR_PTR(-E2BIG);
594 goto out;
595 }
596
597 ptr = io->iov_base + io->iov_len;
598 io->iov_len += size;
599
600out:
601 dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n",
602 __func__, t, t->gen, size, io->iov_len);
603 return ptr;
604}
605
606void netfs_trans_free(struct netfs_trans *t)
607{
608 if (t->eng)
609 pohmelfs_crypto_thread_make_ready(t->eng->thread);
610 kfree(t);
611}
612
613struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
614 unsigned int flags, unsigned int nr)
615{
616 struct netfs_trans *t;
617 unsigned int num, cont, pad, size_no_trans;
618 unsigned int crypto_added = 0;
619 struct netfs_cmd *cmd;
620
621 if (psb->perform_crypto)
622 crypto_added = psb->crypto_attached_size;
623
624 /*
625 * |sizeof(struct netfs_trans)|
626 * |sizeof(struct netfs_cmd)| - transaction header
627 * |size| - buffer with requested size
628 * |padding| - crypto padding, zero bytes
629 * |nr * sizeof(struct page *)| - array of page pointers
630 *
631 * Overall size should be less than PAGE_SIZE for guaranteed allocation.
632 */
633
634 cont = size;
635 size = ALIGN(size, psb->crypto_align_size);
636 pad = size - cont;
637
638 size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added;
639
640 cont = sizeof(struct netfs_trans) + size_no_trans;
641
642 num = (PAGE_SIZE - cont)/sizeof(struct page *);
643
644 if (nr > num)
645 nr = num;
646
647 t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO);
648 if (!t)
649 goto err_out_exit;
650
651 t->iovec.iov_base = (void *)(t + 1);
652 t->pages = (struct page **)(t->iovec.iov_base + size_no_trans);
653
654 /*
655 * Reserving space for transaction header.
656 */
657 t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added;
658
659 netfs_trans_init_static(t, nr, size_no_trans);
660
661 t->flags = flags;
662 t->psb = psb;
663
664 cmd = (struct netfs_cmd *)t->iovec.iov_base;
665
666 cmd->size = size;
667 cmd->cpad = pad;
668 cmd->csize = crypto_added;
669
670 dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, "
671 "page_num: %u, base: %p, pages: %p.\n",
672 __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr,
673 t->iovec.iov_base, t->pages);
674
675 return t;
676
677err_out_exit:
678 return NULL;
679}
680
681int netfs_trans_init(void)
682{
683 int err = -ENOMEM;
684
685 netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst),
686 0, 0, NULL);
687 if (!netfs_trans_dst)
688 goto err_out_exit;
689
690 netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst);
691 if (!netfs_trans_dst_pool)
692 goto err_out_free;
693
694 return 0;
695
696err_out_free:
697 kmem_cache_destroy(netfs_trans_dst);
698err_out_exit:
699 return err;
700}
701
702void netfs_trans_exit(void)
703{
704 mempool_destroy(netfs_trans_dst_pool);
705 kmem_cache_destroy(netfs_trans_dst);
706}