• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/pohmelfs/
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 informaion (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, int 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 */
920