2 * Copyright (C) 2011+ Evgeniy Polyakov <zbr@ioremap.net>
5 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7 #include <linux/module.h>
8 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/inet.h>
12 #include <linux/init.h>
14 #include <linux/in6.h>
15 #include <linux/blkdev.h>
16 #include <linux/parser.h>
17 #include <linux/random.h>
18 #include <linux/buffer_head.h>
19 #include <linux/exportfs.h>
20 #include <linux/vfs.h>
21 #include <linux/seq_file.h>
22 #include <linux/mount.h>
23 #include <linux/quotaops.h>
24 #include <asm/uaccess.h>
28 #define POHMELFS_MAGIC_NUM 0x504f482e
30 struct kmem_cache
*pohmelfs_inode_cache
;
31 struct kmem_cache
*pohmelfs_trans_cache
;
32 struct kmem_cache
*pohmelfs_inode_info_cache
;
33 struct kmem_cache
*pohmelfs_route_cache
;
34 struct kmem_cache
*pohmelfs_wait_cache
;
35 struct kmem_cache
*pohmelfs_io_cache
;
36 struct kmem_cache
*pohmelfs_inode_info_binary_package_cache
;
37 struct kmem_cache
*pohmelfs_write_cache
;
38 struct kmem_cache
*pohmelfs_dentry_cache
;
40 static atomic_t psb_bdi_num
= ATOMIC_INIT(0);
42 static void pohmelfs_http_compat_cleanup(struct pohmelfs_sb
*psb
)
44 struct pohmelfs_path
*p
;
47 for (i
= 0; i
< psb
->http_compat
; ++i
) {
50 mutex_destroy(&p
->lock
);
55 static int pohmelfs_http_compat_init(struct pohmelfs_sb
*psb
)
58 struct pohmelfs_path
*path
, *p
;
60 path
= kmalloc(psb
->http_compat
* sizeof(struct pohmelfs_path
), GFP_KERNEL
);
66 for (i
= 0; i
< psb
->http_compat
; ++i
) {
71 p
->data
= kmalloc(PAGE_SIZE
, GFP_KERNEL
);
85 mutex_destroy(&p
->lock
);
95 static void pohmelfs_cleanup_psb(struct pohmelfs_sb
*psb
)
97 struct pohmelfs_addr
*a
, *tmp
;
100 cancel_delayed_work(&psb
->sync_work
);
101 destroy_workqueue(psb
->wq
);
103 pohmelfs_pool_clean(psb
->conn
, psb
->conn_num
);
105 list_for_each_entry_safe(a
, tmp
, &psb
->addr_list
, addr_entry
) {
106 list_del(&a
->addr_entry
);
110 crypto_free_hash(psb
->hash
);
112 pohmelfs_http_compat_cleanup(psb
);
118 static void pohmelfs_put_super(struct super_block
*sb
)
120 struct pohmelfs_sb
*psb
= pohmelfs_sb(sb
);
122 pohmelfs_cleanup_psb(psb
);
123 bdi_destroy(&psb
->bdi
);
126 struct pohmelfs_size
{
128 uint64_t bsize
; /* Block size */
129 uint64_t frsize
; /* Fragment size */
130 uint64_t blocks
; /* Filesystem size in frsize units */
131 uint64_t bfree
; /* # free blocks */
132 uint64_t bavail
; /* # free blocks for non-root */
135 static int pohmelfs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
137 struct super_block
*sb
= dentry
->d_sb
;
138 struct pohmelfs_sb
*psb
= pohmelfs_sb(sb
);
139 struct pohmelfs_connection
*c
;
140 struct pohmelfs_state
*st
;
141 struct pohmelfs_size
*sz
;
142 uint64_t min_size
= ~0ULL;
146 sz
= kzalloc(psb
->group_num
* sizeof(struct pohmelfs_size
), GFP_KERNEL
);
152 for (i
= 0; i
< psb
->group_num
; ++i
) {
153 sz
[i
].group_id
= psb
->groups
[i
];
156 memset(buf
, 0, sizeof(struct kstatfs
));
158 buf
->f_type
= POHMELFS_MAGIC_NUM
; /* 'POH.' */
159 buf
->f_namelen
= 4096;
161 buf
->f_bfree
= buf
->f_bavail
= buf
->f_blocks
= 0;
163 mutex_lock(&psb
->conn_lock
);
166 spin_lock(&c
->state_lock
);
167 list_for_each_entry(st
, &c
->state_list
, state_entry
) {
168 for (i
= 0; i
< psb
->group_num
; ++i
) {
169 if (sz
[i
].group_id
== st
->group_id
) {
170 sz
[i
].bsize
= sb
->s_blocksize
;
171 sz
[i
].frsize
= st
->frsize
;
172 sz
[i
].blocks
+= (st
->blocks
* st
->frsize
) >> PAGE_SHIFT
;
173 sz
[i
].bfree
+= (st
->bfree
* st
->bsize
) >> PAGE_SHIFT
;
174 sz
[i
].bavail
+= (st
->bavail
* st
->bsize
) >> PAGE_SHIFT
;
181 spin_unlock(&c
->state_lock
);
182 mutex_unlock(&psb
->conn_lock
);
184 for (i
= 0; i
< psb
->group_num
; ++i
) {
185 /* skip empty groups */
186 if (sz
[i
].blocks
&& (sz
[i
].bavail
< min_size
)) {
187 min_size
= sz
[i
].bavail
;
193 buf
->f_bfree
= buf
->f_bavail
= buf
->f_blocks
= ~0ULL >> PAGE_SHIFT
;
195 buf
->f_bsize
= sz
[pos
].bsize
;
196 buf
->f_frsize
= sz
[pos
].frsize
;
197 buf
->f_blocks
= sz
[pos
].blocks
;
198 buf
->f_bavail
= sz
[pos
].bfree
;
199 buf
->f_bfree
= sz
[pos
].bavail
;
210 static int pohmelfs_show_options(struct seq_file
*seq
, struct vfsmount
*vfs
)
212 struct pohmelfs_sb
*psb
= pohmelfs_sb(vfs
->mnt_sb
);
214 static int pohmelfs_show_options(struct seq_file
*seq
, struct dentry
*dentry
)
216 struct pohmelfs_sb
*psb
= pohmelfs_sb(dentry
->d_inode
->i_sb
);
218 struct pohmelfs_addr
*a
;
220 mutex_lock(&psb
->conn_lock
);
221 list_for_each_entry(a
, &psb
->addr_list
, addr_entry
) {
222 struct sockaddr
*sa
= (struct sockaddr
*)&a
->sa
;
223 if (sa
->sa_family
== AF_INET
) {
224 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
225 seq_printf(seq
, ",server=%pI4:%d:2", &sin
->sin_addr
.s_addr
, ntohs(sin
->sin_port
));
226 } else if (sa
->sa_family
== AF_INET6
) {
227 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)sa
;
228 seq_printf(seq
, ",server=%pI6:%d:6", &sin
->sin6_addr
.s6_addr
, ntohs(sin
->sin6_port
));
231 mutex_unlock(&psb
->conn_lock
);
233 if (psb
->no_read_csum
)
234 seq_printf(seq
, ",noreadcsum");
235 seq_printf(seq
, ",sync_timeout=%ld", psb
->sync_timeout
);
237 seq_printf(seq
, ",fsid=%s", psb
->fsid
);
238 if (psb
->successful_write_count
)
239 seq_printf(seq
, ",successful_write_count=%d", psb
->successful_write_count
);
240 seq_printf(seq
, ",keepalive_cnt=%d", psb
->keepalive_cnt
);
241 seq_printf(seq
, ",keepalive_interval=%d", psb
->keepalive_interval
);
242 seq_printf(seq
, ",keepalive_idle=%d", psb
->keepalive_idle
);
243 seq_printf(seq
, ",readdir_allocation=%d", psb
->readdir_allocation
);
244 if (psb
->http_compat
)
245 seq_printf(seq
, ",http_compat=%d", psb
->http_compat
);
246 if (psb
->sync_on_close
)
247 seq_printf(seq
, ",sync_on_close");
248 seq_printf(seq
, ",connection_pool_size=%d", psb
->conn_num
);
249 seq_printf(seq
, ",read_wait_timeout=%ld", psb
->read_wait_timeout
);
250 seq_printf(seq
, ",write_wait_timeout=%ld", psb
->write_wait_timeout
);
255 * This is tricky function - inode cache can be shrunk and inode is about to be dropped,
256 * since its last reference is dropped. But then icache can __iget() on this inode and
257 * later iput() it, which will again call ->drop_inode() callback.
259 * So, ->drop_inode() can be called multiple times for single inode without its reintialization
260 * And we better to be ready for this
262 static int pohmelfs_drop_inode(struct inode
*inode
)
264 struct pohmelfs_inode
*pi
= pohmelfs_inode(inode
);
265 struct pohmelfs_sb
*psb
= pohmelfs_sb(inode
->i_sb
);
267 pr_debug("%s: %ld, mapping: %p\n",
268 pohmelfs_dump_id(pi
->id
.id
), inode
->i_ino
, inode
->i_mapping
);
270 spin_lock(&psb
->inode_lock
);
271 if (rb_parent(&pi
->node
) != &pi
->node
)
272 rb_erase(&pi
->node
, &psb
->inode_root
);
273 rb_init_node(&pi
->node
);
274 spin_unlock(&psb
->inode_lock
);
276 return generic_drop_inode(inode
);
279 static int pohmelfs_write_inode_complete(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
)
281 struct dnet_cmd
*cmd
= &recv
->cmd
;
282 struct pohmelfs_inode_info_binary_package
*bin
= t
->priv
;
283 struct pohmelfs_wait
*wait
= &bin
->wait
;
285 if (cmd
->flags
& DNET_FLAGS_MORE
)
288 wait
->condition
= cmd
->status
;
289 if (!wait
->condition
)
296 static int pohmelfs_write_inode_init(struct pohmelfs_trans
*t
)
298 struct pohmelfs_inode_info_binary_package
*bin
= t
->priv
;
300 kref_get(&bin
->wait
.refcnt
);
304 static void pohmelfs_write_inode_release(struct kref
*kref
)
306 struct pohmelfs_wait
*wait
= container_of(kref
, struct pohmelfs_wait
, refcnt
);
307 struct pohmelfs_inode_info_binary_package
*bin
= container_of(wait
, struct pohmelfs_inode_info_binary_package
, wait
);
309 iput(&bin
->wait
.pi
->vfs_inode
);
310 kmem_cache_free(pohmelfs_inode_info_binary_package_cache
, bin
);
313 static void pohmelfs_write_inode_destroy(struct pohmelfs_trans
*t
)
315 struct pohmelfs_inode_info_binary_package
*bin
= t
->priv
;
318 * We own this pointer - it points to &bin->info
319 * Zero it here to prevent pohmelfs_trans_release() from freeing it
323 kref_put(&bin
->wait
.refcnt
, pohmelfs_write_inode_release
);
326 static int pohmelfs_write_inode(struct inode
*inode
, struct writeback_control
*wbc
)
328 struct pohmelfs_inode
*pi
= pohmelfs_inode(inode
);
329 struct pohmelfs_inode_info_binary_package
*bin
;
330 struct pohmelfs_sb
*psb
= pohmelfs_sb(inode
->i_sb
);
331 struct pohmelfs_io
*pio
;
337 sync
= wbc
->sync_mode
== WB_SYNC_ALL
;
339 pio
= kmem_cache_zalloc(pohmelfs_io_cache
, GFP_NOIO
);
345 bin
= kmem_cache_zalloc(pohmelfs_inode_info_binary_package_cache
, GFP_NOIO
);
348 goto err_out_free_pio
;
351 pohmelfs_fill_inode_info(inode
, &bin
->info
);
352 err
= pohmelfs_wait_init(&bin
->wait
, pi
);
354 goto err_out_put_bin
;
358 pio
->cmd
= DNET_CMD_WRITE
;
360 pio
->size
= sizeof(struct pohmelfs_inode_info
);
361 pio
->cflags
= DNET_FLAGS_NEED_ACK
;
363 pio
->type
= POHMELFS_INODE_COLUMN
;
364 pio
->ioflags
= DNET_IO_FLAGS_OVERWRITE
;
366 pio
->data
= &bin
->info
;
367 pio
->alloc_flags
= POHMELFS_IO_OWN
;
369 pio
->cb
.complete
= pohmelfs_write_inode_complete
;
370 pio
->cb
.init
= pohmelfs_write_inode_init
;
371 pio
->cb
.destroy
= pohmelfs_write_inode_destroy
;
373 err
= pohmelfs_send_io(pio
);
375 goto err_out_put_bin
;
378 struct pohmelfs_wait
*wait
= &bin
->wait
;
380 ret
= wait_event_interruptible_timeout(wait
->wq
,
381 wait
->condition
!= 0 && atomic_read(&wait
->refcnt
.refcount
) <= 2,
382 msecs_to_jiffies(psb
->write_wait_timeout
));
387 goto err_out_put_bin
;
390 if (wait
->condition
< 0) {
391 err
= wait
->condition
;
392 goto err_out_put_bin
;
397 kref_put(&bin
->wait
.refcnt
, pohmelfs_write_inode_release
);
399 kmem_cache_free(pohmelfs_io_cache
, pio
);
404 static int pohmelfs_parse_options(struct pohmelfs_sb
*psb
, char *data
);
406 static int pohmelfs_remount_fs(struct super_block
*sb
, int *flags
, char *data
)
408 struct pohmelfs_sb
*psb
= pohmelfs_sb(sb
);
410 return pohmelfs_parse_options(psb
, data
);
413 static const struct super_operations pohmelfs_sb_ops
= {
414 .alloc_inode
= pohmelfs_alloc_inode
,
415 .destroy_inode
= pohmelfs_destroy_inode
,
416 .drop_inode
= pohmelfs_drop_inode
,
417 .write_inode
= pohmelfs_write_inode
,
418 .put_super
= pohmelfs_put_super
,
419 .show_options
= pohmelfs_show_options
,
420 .statfs
= pohmelfs_statfs
,
421 .remount_fs
= pohmelfs_remount_fs
,
424 static void pohmelfs_sync(struct work_struct
*work
)
426 struct pohmelfs_sb
*psb
= container_of(to_delayed_work(work
), struct pohmelfs_sb
, sync_work
);
427 struct super_block
*sb
= psb
->sb
;
428 long timeout
= msecs_to_jiffies(psb
->sync_timeout
* 1000);
430 if (down_read_trylock(&sb
->s_umount
)) {
432 up_read(&sb
->s_umount
);
434 pohmelfs_stat(psb
, 0);
440 queue_delayed_work(psb
->wq
, &psb
->sync_work
, timeout
);
443 static int pohmelfs_init_psb(struct pohmelfs_sb
*psb
, struct super_block
*sb
)
448 psb
->inode_root
= RB_ROOT
;
449 spin_lock_init(&psb
->inode_lock
);
451 atomic_long_set(&psb
->ino
, 0);
452 atomic_long_set(&psb
->trans
, 0);
455 sb
->s_op
= &pohmelfs_sb_ops
;
456 sb
->s_magic
= POHMELFS_MAGIC_NUM
;
457 sb
->s_maxbytes
= MAX_LFS_FILESIZE
;
458 sb
->s_blocksize
= PAGE_SIZE
;
459 sb
->s_bdi
= &psb
->bdi
;
462 psb
->read_wait_timeout
= 5000;
463 psb
->write_wait_timeout
= 5000;
465 psb
->sync_timeout
= 300;
467 psb
->keepalive_cnt
= 5;
468 psb
->keepalive_interval
= 10;
469 psb
->keepalive_idle
= 30;
471 psb
->readdir_allocation
= 4;
472 psb
->reconnect_timeout
= msecs_to_jiffies(30000);
478 psb
->hash
= crypto_alloc_hash("sha512", 0, CRYPTO_ALG_ASYNC
);
479 if (IS_ERR(psb
->hash
)) {
480 err
= PTR_ERR(psb
->hash
);
484 snprintf(name
, sizeof(name
), "pohmelfs-sync-%d", psb
->bdi_num
);
485 psb
->wq
= alloc_workqueue(name
, WQ_NON_REENTRANT
| WQ_UNBOUND
| WQ_FREEZABLE
| WQ_MEM_RECLAIM
, 0);
488 goto err_out_crypto_free
;
491 mutex_init(&psb
->conn_lock
);
492 INIT_LIST_HEAD(&psb
->addr_list
);
494 INIT_DELAYED_WORK(&psb
->sync_work
, pohmelfs_sync
);
499 crypto_free_hash(psb
->hash
);
502 sb
->s_fs_info
= NULL
;
506 static int pohmelfs_parse_addr(char *addr
, struct sockaddr_storage
*a
, int *addrlen
)
512 ptr
= strrchr(addr
, ':');
514 goto err_out_print_wrong_param
;
517 goto err_out_print_wrong_param
;
519 family
= simple_strtol(ptr
, NULL
, 10);
521 ptr
= strrchr(addr
, ':');
523 goto err_out_print_wrong_param
;
526 goto err_out_print_wrong_param
;
528 port
= simple_strtol(ptr
, NULL
, 10);
530 if (family
== AF_INET
) {
531 struct sockaddr_in
*sin
= (struct sockaddr_in
*)a
;
533 sin
->sin_family
= family
;
534 sin
->sin_port
= htons(port
);
536 err
= in4_pton(addr
, strlen(addr
), (u8
*)&sin
->sin_addr
, ':', NULL
);
537 *addrlen
= sizeof(struct sockaddr_in
);
538 } else if (family
== AF_INET6
) {
539 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)a
;
541 sin
->sin6_family
= family
;
542 sin
->sin6_port
= htons(port
);
543 err
= in6_pton(addr
, strlen(addr
), (u8
*)&sin
->sin6_addr
, ':', NULL
);
544 *addrlen
= sizeof(struct sockaddr_in6
);
555 goto err_out_print_wrong_param
;
559 err_out_print_wrong_param
:
560 pr_err("%s: wrong addr: '%s', should be 'addr:port:family': %d\n",
561 __func__
, addr
, err
);
565 static int pohmelfs_option(char *option
, char *data
, int *lenp
, int have_data
)
570 if (!strncmp(option
, data
, strlen(option
))) {
571 len
= strlen(option
);
574 if (have_data
&& (!ptr
|| !*ptr
))
584 static int pohmelfs_set_groups(struct pohmelfs_sb
*psb
, char *value
, int len
)
586 int i
, num
= 0, start
= 0, pos
= 0;
589 for (i
= 0; i
< len
; ++i
) {
603 * We do not allow to mess with different group sets for already built filesystem
604 * But to prevent remount from failing, we just pretend that things went the right way
609 psb
->groups
= kzalloc(sizeof(int) * num
, GFP_KERNEL
);
612 psb
->group_num
= num
;
615 for (i
= 0; i
< len
; ++i
) {
616 if (value
[i
] == ':') {
619 psb
->groups
[pos
] = simple_strtol(ptr
, NULL
, 10);
630 psb
->groups
[pos
] = simple_strtol(ptr
, NULL
, 10);
637 static int pohmelfs_parse_option(struct pohmelfs_sb
*psb
, char *data
)
642 pr_debug("option: %s\n", data
);
644 if (pohmelfs_option("server=", data
, &len
, 1)) {
645 struct pohmelfs_addr
*a
, *tmp
;
646 char *addr_str
= data
+ len
;
648 a
= kzalloc(sizeof(struct pohmelfs_addr
), GFP_KERNEL
);
654 err
= pohmelfs_parse_addr(addr_str
, &a
->sa
, &a
->addrlen
);
658 mutex_lock(&psb
->conn_lock
);
659 list_for_each_entry(tmp
, &psb
->addr_list
, addr_entry
) {
660 if (tmp
->addrlen
!= a
->addrlen
)
663 if (!memcmp(&tmp
->sa
, &a
->sa
, a
->addrlen
)) {
670 list_add_tail(&a
->addr_entry
, &psb
->addr_list
);
673 mutex_unlock(&psb
->conn_lock
);
675 } else if (pohmelfs_option("fsid=", data
, &len
, 1)) {
679 psb
->fsid
= kmalloc(len
+ 1, GFP_KERNEL
);
685 snprintf(psb
->fsid
, len
+ 1, "%s", data
);
687 } else if (pohmelfs_option("sync_timeout=", data
, &len
, 1)) {
688 psb
->sync_timeout
= simple_strtol(data
+ len
, NULL
, 10);
689 } else if (pohmelfs_option("http_compat=", data
, &len
, 1)) {
690 psb
->http_compat
= simple_strtol(data
+ len
, NULL
, 10);
691 err
= pohmelfs_http_compat_init(psb
);
692 } else if (pohmelfs_option("groups=", data
, &len
, 1)) {
696 err
= pohmelfs_set_groups(psb
, data
, len
);
697 } else if (pohmelfs_option("noatime", data
, &len
, 0)) {
698 psb
->sb
->s_flags
|= FS_NOATIME_FL
;
699 } else if (pohmelfs_option("relatime", data
, &len
, 0)) {
700 psb
->sb
->s_flags
|= MS_RELATIME
;
701 } else if (pohmelfs_option("noreadcsum", data
, &len
, 0)) {
702 psb
->no_read_csum
= 1;
703 } else if (pohmelfs_option("readcsum", data
, &len
, 0)) {
704 psb
->no_read_csum
= 0;
705 } else if (pohmelfs_option("successful_write_count=", data
, &len
, 1)) {
706 psb
->successful_write_count
= simple_strtol(data
+ len
, NULL
, 10);
707 } else if (pohmelfs_option("keepalive_cnt=", data
, &len
, 1)) {
708 psb
->keepalive_cnt
= simple_strtol(data
+ len
, NULL
, 10);
709 } else if (pohmelfs_option("keepalive_idle=", data
, &len
, 1)) {
710 psb
->keepalive_idle
= simple_strtol(data
+ len
, NULL
, 10);
711 } else if (pohmelfs_option("keepalive_interval=", data
, &len
, 1)) {
712 psb
->keepalive_interval
= simple_strtol(data
+ len
, NULL
, 10);
713 } else if (pohmelfs_option("readdir_allocation=", data
, &len
, 1)) {
714 psb
->readdir_allocation
= simple_strtol(data
+ len
, NULL
, 10);
715 } else if (pohmelfs_option("sync_on_close", data
, &len
, 0)) {
716 psb
->sync_on_close
= 1;
717 } else if (pohmelfs_option("connection_pool_size=", data
, &len
, 1)) {
718 psb
->conn_num
= simple_strtol(data
+ len
, NULL
, 10);
719 if (psb
->conn_num
< 2)
721 } else if (pohmelfs_option("read_wait_timeout=", data
, &len
, 1)) {
722 psb
->read_wait_timeout
= simple_strtol(data
+ len
, NULL
, 10);
723 } else if (pohmelfs_option("write_wait_timeout=", data
, &len
, 1)) {
724 psb
->write_wait_timeout
= simple_strtol(data
+ len
, NULL
, 10);
733 static int pohmelfs_parse_options(struct pohmelfs_sb
*psb
, char *data
)
740 while (ptr
&& *ptr
) {
743 err
= pohmelfs_parse_option(psb
, start
);
757 err
= pohmelfs_parse_option(psb
, start
);
766 static int pohmelfs_fill_super(struct super_block
*sb
, void *data
, int silent
)
768 struct pohmelfs_sb
*psb
;
771 psb
= kzalloc(sizeof(struct pohmelfs_sb
), GFP_KERNEL
);
777 psb
->bdi_num
= atomic_inc_return(&psb_bdi_num
);
779 err
= bdi_init(&psb
->bdi
);
781 goto err_out_free_psb
;
783 psb
->bdi
.ra_pages
= default_backing_dev_info
.ra_pages
;
785 err
= bdi_register(&psb
->bdi
, NULL
, "pfs-%d", psb
->bdi_num
);
787 bdi_destroy(&psb
->bdi
);
788 goto err_out_free_psb
;
791 err
= pohmelfs_init_psb(psb
, sb
);
793 goto err_out_free_bdi
;
795 psb
->root
= pohmelfs_new_inode(psb
, 0755|S_IFDIR
);
796 if (IS_ERR(psb
->root
)) {
797 err
= PTR_ERR(psb
->root
);
798 goto err_out_cleanup_psb
;
801 err
= pohmelfs_parse_options(psb
, data
);
803 goto err_out_put_root
;
805 if (!psb
->group_num
|| list_empty(&psb
->addr_list
)) {
807 pr_err("you have to specify number of groups and add remote node address (at least one)\n");
808 goto err_out_put_root
;
811 if (!psb
->fsid_len
) {
812 char str
[] = "pohmelfs";
813 err
= pohmelfs_hash(psb
, str
, 8, &psb
->root
->id
);
815 err
= pohmelfs_hash(psb
, psb
->fsid
, psb
->fsid_len
, &psb
->root
->id
);
818 goto err_out_put_root
;
822 err
= pohmelfs_pool_resize(psb
, err
);
824 goto err_out_put_root
;
826 sb
->s_root
= d_make_root(&psb
->root
->vfs_inode
);
829 goto err_out_cleanup_psb
;
832 queue_delayed_work(psb
->wq
, &psb
->sync_work
, msecs_to_jiffies(psb
->sync_timeout
* 1000));
833 pohmelfs_stat(psb
, 0);
838 iput(&psb
->root
->vfs_inode
);
840 pohmelfs_cleanup_psb(psb
);
842 bdi_destroy(&psb
->bdi
);
846 pr_err("%s: error: %d\n", __func__
, err
);
850 static struct dentry
*pohmelfs_mount(struct file_system_type
*fs_type
,
851 int flags
, const char *dev_name
, void *data
)
853 return mount_nodev(fs_type
, flags
, data
, pohmelfs_fill_super
);
856 static void pohmelfs_kill_sb(struct super_block
*sb
)
862 static struct file_system_type pohmelfs_type
= {
863 .owner
= THIS_MODULE
,
865 .mount
= pohmelfs_mount
,
866 .kill_sb
= pohmelfs_kill_sb
,
869 static void pohmelfs_cleanup_cache(void)
871 kmem_cache_destroy(pohmelfs_trans_cache
);
872 kmem_cache_destroy(pohmelfs_inode_cache
);
873 kmem_cache_destroy(pohmelfs_inode_info_cache
);
874 kmem_cache_destroy(pohmelfs_route_cache
);
875 kmem_cache_destroy(pohmelfs_wait_cache
);
876 kmem_cache_destroy(pohmelfs_io_cache
);
877 kmem_cache_destroy(pohmelfs_inode_info_binary_package_cache
);
878 kfree(pohmelfs_scratch_buf
);
879 kmem_cache_destroy(pohmelfs_write_cache
);
880 kmem_cache_destroy(pohmelfs_dentry_cache
);
883 static int pohmelfs_init_cache(void)
887 pohmelfs_inode_cache
= KMEM_CACHE(pohmelfs_inode
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
888 if (!pohmelfs_inode_cache
)
891 pohmelfs_trans_cache
= KMEM_CACHE(pohmelfs_trans
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
892 if (!pohmelfs_trans_cache
)
893 goto err_out_destroy_inode_cache
;
895 pohmelfs_inode_info_cache
= KMEM_CACHE(pohmelfs_inode_info
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
896 if (!pohmelfs_inode_info_cache
)
897 goto err_out_destroy_trans_cache
;
899 pohmelfs_route_cache
= KMEM_CACHE(pohmelfs_route
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
900 if (!pohmelfs_route_cache
)
901 goto err_out_destroy_inode_info_cache
;
903 pohmelfs_wait_cache
= KMEM_CACHE(pohmelfs_wait
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
904 if (!pohmelfs_wait_cache
)
905 goto err_out_destroy_inode_info_cache
;
907 pohmelfs_io_cache
= KMEM_CACHE(pohmelfs_io
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
908 if (!pohmelfs_io_cache
)
909 goto err_out_destroy_wait_cache
;
911 pohmelfs_scratch_buf
= kmalloc(pohmelfs_scratch_buf_size
, GFP_KERNEL
);
912 if (!pohmelfs_scratch_buf
) {
914 goto err_out_destroy_io_cache
;
917 pohmelfs_inode_info_binary_package_cache
= KMEM_CACHE(pohmelfs_inode_info_binary_package
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
918 if (!pohmelfs_inode_info_binary_package_cache
)
919 goto err_out_free_scratch
;
921 pohmelfs_write_cache
= KMEM_CACHE(pohmelfs_write_ctl
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
922 if (!pohmelfs_write_cache
)
923 goto err_out_destroy_inode_info_binary_package_cache
;
925 pohmelfs_dentry_cache
= KMEM_CACHE(pohmelfs_dentry
, SLAB_RECLAIM_ACCOUNT
|SLAB_MEM_SPREAD
);
926 if (!pohmelfs_dentry_cache
)
927 goto err_out_destroy_write_cache
;
931 err_out_destroy_write_cache
:
932 kmem_cache_destroy(pohmelfs_write_cache
);
933 err_out_destroy_inode_info_binary_package_cache
:
934 kmem_cache_destroy(pohmelfs_inode_info_binary_package_cache
);
935 err_out_free_scratch
:
936 kfree(pohmelfs_scratch_buf
);
937 err_out_destroy_io_cache
:
938 kmem_cache_destroy(pohmelfs_io_cache
);
939 err_out_destroy_wait_cache
:
940 kmem_cache_destroy(pohmelfs_wait_cache
);
941 err_out_destroy_inode_info_cache
:
942 kmem_cache_destroy(pohmelfs_inode_info_cache
);
943 err_out_destroy_trans_cache
:
944 kmem_cache_destroy(pohmelfs_trans_cache
);
945 err_out_destroy_inode_cache
:
946 kmem_cache_destroy(pohmelfs_inode_cache
);
951 static int __init
pohmelfs_init(void)
955 err
= pohmelfs_init_cache();
959 err
= register_filesystem(&pohmelfs_type
);
961 goto err_out_cleanup_cache
;
965 err_out_cleanup_cache
:
966 pohmelfs_cleanup_cache();
971 static void __exit
pohmelfs_exit(void)
973 unregister_filesystem(&pohmelfs_type
);
974 pohmelfs_cleanup_cache();
977 module_init(pohmelfs_init
)
978 module_exit(pohmelfs_exit
)
980 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
981 MODULE_DESCRIPTION("POHMELFS");
982 MODULE_LICENSE("GPL");