2 * Copyright (C) 2011+ Evgeniy Polyakov <zbr@ioremap.net>
8 #include <linux/backing-dev.h>
9 #include <linux/crypto.h>
11 #include <linux/kref.h>
12 #include <linux/list.h>
13 #include <linux/mutex.h>
14 #include <linux/net.h>
15 #include <linux/pagemap.h>
16 #include <linux/pagevec.h>
17 #include <linux/printk.h>
18 #include <linux/slab.h>
19 #include <linux/time.h>
20 #include <linux/wait.h>
21 #include <linux/workqueue.h>
23 #include <crypto/sha.h>
25 #define dnet_bswap16(x) cpu_to_le16(x)
26 #define dnet_bswap32(x) cpu_to_le32(x)
27 #define dnet_bswap64(x) cpu_to_le64(x)
29 /* theese are needed for packet.h below to compile */
30 #define DNET_ID_SIZE SHA512_DIGEST_SIZE
31 #define DNET_CSUM_SIZE SHA512_DIGEST_SIZE
33 #define POHMELFS_INODE_COLUMN 3
36 * is not used in kernel, but we want to share the same header
37 * with userspace, so I put it here for compiler to shut up
39 int gettimeofday(struct timeval
*, struct timezone
*);
43 static inline struct timespec
pohmelfs_date(struct dnet_time
*tm
)
48 ts
.tv_nsec
= tm
->tnsec
;
55 struct dnet_attr attr
;
57 struct dnet_io_attr io
;
63 * Returns 1 when id1 > id2
67 static inline int dnet_id_cmp_str(const unsigned char *id1
, const unsigned char *id2
)
71 for (i
*=sizeof(unsigned long); i
<DNET_ID_SIZE
; ++i
) {
81 struct pohmelfs_state
;
83 struct pohmelfs_trans
;
85 struct pohmelfs_trans_cb
{
86 int (* init
)(struct pohmelfs_trans
*t
);
87 int (* complete
)(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
);
88 int (* recv_reply
)(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
);
89 void (* destroy
)(struct pohmelfs_trans
*t
);
92 struct pohmelfs_trans
{
93 struct list_head trans_entry
;
94 struct rb_node trans_node
;
102 struct pohmelfs_state
*st
;
104 struct pohmelfs_cmd cmd
;
106 u64 header_size
, data_size
;
108 unsigned long long io_offset
;
113 struct pohmelfs_write_ctl
*wctl
;
116 struct pohmelfs_trans_cb cb
;
119 struct pohmelfs_trans
*pohmelfs_trans_alloc(struct inode
*inode
);
120 struct pohmelfs_trans
*pohmelfs_trans_alloc_io_buf(struct inode
*inode
, int group
, int command
,
121 void *data
, u64 offset
, u64 size
, int aflags
, int ioflags
, int type
);
122 void pohmelfs_trans_put(struct pohmelfs_trans
*t
);
124 int pohmelfs_trans_insert(struct pohmelfs_trans
*t
);
125 int pohmelfs_trans_insert_tree(struct pohmelfs_state
*st
, struct pohmelfs_trans
*t
);
126 void pohmelfs_trans_remove(struct pohmelfs_trans
*t
);
127 struct pohmelfs_trans
*pohmelfs_trans_lookup(struct pohmelfs_state
*st
, struct dnet_cmd
*cmd
);
129 struct pohmelfs_state
{
130 struct pohmelfs_connection
*conn
;
131 struct list_head state_entry
;
133 struct sockaddr_storage sa
;
139 struct mutex trans_lock
;
140 struct list_head trans_list
;
141 struct rb_root trans_root
;
147 /* Waiting/polling machinery */
149 wait_queue_head_t
*whead
;
151 struct work_struct io_work
;
153 /* is set when dnet_cmd is being read, otherwise attached data */
155 /* currently read command reply */
158 uint64_t bsize
; /* Block size */
159 uint64_t frsize
; /* Fragment size */
160 uint64_t blocks
; /* Filesystem size in frsize units */
161 uint64_t bfree
; /* # free blocks */
162 uint64_t bavail
; /* # free blocks for non-root */
165 struct pohmelfs_state
*pohmelfs_state_create(struct pohmelfs_connection
*conn
, struct sockaddr_storage
*sa
, int addrlen
,
166 int ask_route
, int group_id
);
167 struct pohmelfs_state
*pohmelfs_state_lookup(struct pohmelfs_sb
*psb
, struct dnet_raw_id
*id
, int group
, ssize_t size
);
168 int pohmelfs_grab_states(struct pohmelfs_sb
*psb
, struct pohmelfs_state
***stp
);
170 static inline void pohmelfs_state_get(struct pohmelfs_state
*st
)
172 kref_get(&st
->refcnt
);
175 void pohmelfs_state_put(struct pohmelfs_state
*st
);
176 void pohmelfs_state_kill(struct pohmelfs_state
*st
);
178 struct pohmelfs_state
*pohmelfs_addr_exist(struct pohmelfs_connection
*conn
, struct sockaddr_storage
*sa
, int addrlen
);
180 void pohmelfs_state_schedule(struct pohmelfs_state
*st
);
182 __attribute__ ((format (printf
, 2, 3))) void pohmelfs_print_addr(struct sockaddr_storage
*addr
, const char *fmt
, ...);
184 #define POHMELFS_INODE_INFO_REMOVED (1<<0)
186 struct pohmelfs_inode_info
{
187 struct dnet_raw_id id
;
193 unsigned int blocksize
;
194 unsigned int namelen
;
203 struct dnet_time ctime
;
204 struct dnet_time mtime
;
205 struct dnet_time atime
;
206 } __attribute__ ((packed
));
208 void pohmelfs_fill_inode_info(struct inode
*inode
, struct pohmelfs_inode_info
*info
);
209 void pohmelfs_fill_inode(struct inode
*inode
, struct pohmelfs_inode_info
*info
);
210 void pohmelfs_convert_inode_info(struct pohmelfs_inode_info
*info
);
212 struct pohmelfs_inode
{
213 struct inode vfs_inode
;
214 struct dnet_raw_id id
;
227 int pohmelfs_send_dentry(struct pohmelfs_inode
*pi
, struct dnet_raw_id
*id
, const char *sname
, int len
, int sync
);
228 struct pohmelfs_inode
*pohmelfs_sb_inode_lookup(struct pohmelfs_sb
*psb
, struct dnet_raw_id
*id
);
230 struct pohmelfs_reconnect
{
231 struct list_head reconnect_entry
;
232 struct sockaddr_storage sa
;
237 int pohmelfs_state_add_reconnect(struct pohmelfs_state
*st
);
239 struct pohmelfs_path
{
244 int pohmelfs_http_compat_id(struct pohmelfs_inode
*pi
);
246 struct pohmelfs_addr
{
247 struct list_head addr_entry
;
248 struct sockaddr_storage sa
;
252 struct pohmelfs_connection
{
253 struct pohmelfs_sb
*psb
;
257 struct rb_root route_root
;
258 struct list_head state_list
;
259 spinlock_t state_lock
;
261 struct mutex reconnect_lock
;
262 struct list_head reconnect_list
;
263 struct list_head kill_state_list
;
265 struct workqueue_struct
*wq
;
268 struct delayed_work reconnect_work
;
271 void pohmelfs_pool_clean(struct pohmelfs_connection
*conn
, int conn_num
);
272 int pohmelfs_pool_resize(struct pohmelfs_sb
*psb
, int num
);
275 struct super_block
*sb
;
276 struct backing_dev_info bdi
;
278 struct pohmelfs_inode
*root
;
280 spinlock_t inode_lock
;
281 struct rb_root inode_root
;
284 struct pohmelfs_path
*path
;
288 struct pohmelfs_connection
*conn
;
290 int bulk_idx
, bulk_num
;
291 int meta_idx
, meta_num
;
292 struct mutex conn_lock
;
294 /* protected by conn_lock */
295 struct list_head addr_list
;
297 long read_wait_timeout
;
298 long write_wait_timeout
;
300 long reconnect_timeout
;
303 struct delayed_work sync_work
;
304 struct workqueue_struct
*wq
;
312 struct crypto_hash
*hash
;
318 * number of copies to be successfully written to mark write as successful
319 * if not set, half of groups plus one must be successfully written, i.e. plain write quorum
321 int successful_write_count
;
322 int keepalive_cnt
, keepalive_interval
, keepalive_idle
;
323 int readdir_allocation
;
328 static inline struct pohmelfs_sb
*pohmelfs_sb(struct super_block
*sb
)
330 return (struct pohmelfs_sb
*)sb
->s_fs_info
;
333 static inline struct pohmelfs_inode
*pohmelfs_inode(struct inode
*inode
)
335 return container_of(inode
, struct pohmelfs_inode
, vfs_inode
);
338 struct pohmelfs_wait
{
339 wait_queue_head_t wq
;
340 struct pohmelfs_inode
*pi
;
347 int pohmelfs_wait_init(struct pohmelfs_wait
*wait
, struct pohmelfs_inode
*pi
);
348 struct pohmelfs_wait
*pohmelfs_wait_alloc(struct pohmelfs_inode
*pi
);
349 void pohmelfs_wait_put(struct pohmelfs_wait
*wait
);
350 static inline void pohmelfs_wait_get(struct pohmelfs_wait
*wait
)
352 kref_get(&wait
->refcnt
);
355 struct pohmelfs_inode_info_binary_package
{
356 struct pohmelfs_inode_info info
;
358 struct pohmelfs_wait wait
;
361 struct pohmelfs_write_ctl
{
363 struct pohmelfs_inode_info
*info
;
366 atomic_t good_writes
;
369 struct pohmelfs_dentry_disk
{
370 struct dnet_raw_id id
;
375 } __attribute__((packed
));
377 struct pohmelfs_dentry
{
378 struct dnet_raw_id parent_id
;
379 struct pohmelfs_dentry_disk disk
;
382 extern struct kmem_cache
*pohmelfs_inode_cache
;
383 extern struct kmem_cache
*pohmelfs_trans_cache
;
384 extern struct kmem_cache
*pohmelfs_inode_info_cache
;
385 extern struct kmem_cache
*pohmelfs_route_cache
;
386 extern struct kmem_cache
*pohmelfs_wait_cache
;
387 extern struct kmem_cache
*pohmelfs_io_cache
;
388 extern struct kmem_cache
*pohmelfs_inode_info_binary_package_cache
;
389 extern struct kmem_cache
*pohmelfs_write_cache
;
390 extern struct kmem_cache
*pohmelfs_dentry_cache
;
392 struct inode
*pohmelfs_alloc_inode(struct super_block
*sb
);
393 void pohmelfs_destroy_inode(struct inode
*);
395 struct pohmelfs_inode
*pohmelfs_existing_inode(struct pohmelfs_sb
*psb
, struct pohmelfs_inode_info
*info
);
396 struct pohmelfs_inode
*pohmelfs_new_inode(struct pohmelfs_sb
*psb
, int mode
);
397 int pohmelfs_hash(struct pohmelfs_sb
*psb
, const void *data
, const size_t size
, struct dnet_raw_id
*id
);
399 char *pohmelfs_dump_id(const unsigned char *id
);
400 char *pohmelfs_dump_id_len_raw(const unsigned char *id
, unsigned int len
, char *dst
);
402 int pohmelfs_write_command(struct pohmelfs_inode
*pi
, struct pohmelfs_write_ctl
*ctl
, loff_t offset
, size_t len
);
403 void pohmelfs_write_ctl_release(struct kref
*kref
);
404 int pohmelfs_metadata_inode(struct pohmelfs_inode
*pi
, int sync
);
406 extern const struct file_operations pohmelfs_dir_fops
;
407 extern const struct inode_operations pohmelfs_dir_inode_operations
;
409 extern const struct file_operations pohmelfs_file_ops
;
410 extern const struct inode_operations pohmelfs_file_inode_operations
;
412 extern const struct inode_operations pohmelfs_symlink_inode_operations
;
413 extern const struct inode_operations pohmelfs_special_inode_operations
;
415 extern void *pohmelfs_scratch_buf
;
416 extern int pohmelfs_scratch_buf_size
;
419 * if this flag is set, pohmelfs_inode_info->data is owned by the caller,
420 * so sending path may use it on its own and free (using kfree) when it's done
422 * This logic does not work for shared buffers or
423 * when multiple transactions will be sent for single pohmelfs_inode_info
425 #define POHMELFS_IO_OWN (1<<0)
428 struct pohmelfs_inode
*pi
;
430 struct dnet_raw_id
*id
;
447 struct pohmelfs_write_ctl
*wctl
;
450 struct pohmelfs_trans_cb cb
;
453 int pohmelfs_send_io_group(struct pohmelfs_io
*pio
, int group_id
);
454 int pohmelfs_send_io(struct pohmelfs_io
*pio
);
455 int pohmelfs_send_buf_single(struct pohmelfs_io
*pio
, struct pohmelfs_state
*st
);
456 int pohmelfs_send_buf(struct pohmelfs_io
*pio
);
458 int pohmelfs_data_recv(struct pohmelfs_state
*st
, void *buf
, u64 size
, unsigned int flags
);
459 int pohmelfs_recv(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
, void *data
, int size
);
461 struct pohmelfs_route
{
464 struct dnet_raw_id id
;
465 struct pohmelfs_state
*st
;
468 int pohmelfs_route_request(struct pohmelfs_state
*st
);
469 void pohmelfs_route_remove_all(struct pohmelfs_state
*st
);
471 struct pohmelfs_script_req
{
486 struct dnet_raw_id
*id
;
488 int (* complete
)(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
);
493 int pohmelfs_send_script_request(struct pohmelfs_inode
*parent
, struct pohmelfs_script_req
*req
);
495 int pohmelfs_stat(struct pohmelfs_sb
*psb
, int sync
);
497 static inline int pohmelfs_need_resync(struct pohmelfs_inode
*pi
)
499 struct pohmelfs_sb
*psb
= pohmelfs_sb(pi
->vfs_inode
.i_sb
);
500 return get_seconds() > pi
->update
+ psb
->sync_timeout
;
503 #endif /* __POHMELFS_H */