~ubuntu-branches/ubuntu/quantal/aufs/quantal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Copyright (C) 2005-2008 Junjiro Okajima
 *
 * This program, aufs is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/*
 * directory operations
 *
 * $Id: dir.h,v 1.26 2008/03/31 07:45:32 sfjro Exp $
 */

#ifndef __AUFS_DIR_H__
#define __AUFS_DIR_H__

#ifdef __KERNEL__

#include <linux/fs.h>
#include <linux/version.h>
#include <linux/aufs_type.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
typedef u64	au_filldir_ino_t;
#else
typedef ino_t	au_filldir_ino_t;
#endif

/* ---------------------------------------------------------------------- */

/* need to be faster and smaller */

#define AuSize_DEBLK	512 // todo: changeable
#define AuSize_NHASH	32 // todo: changeable
#if AuSize_DEBLK < NAME_MAX || PAGE_SIZE < AuSize_DEBLK
#error invalid size AuSize_DEBLK
#endif

typedef char aufs_deblk_t[AuSize_DEBLK];

struct aufs_nhash {
	struct hlist_head heads[AuSize_NHASH];
};

struct aufs_destr {
	unsigned char	len;
	char		name[0];
} __packed;

struct aufs_dehstr {
	struct hlist_node hash;
	struct aufs_destr *str;
};

struct aufs_de {
	ino_t			de_ino;
	unsigned char		de_type;
	/* caution: packed */
	struct aufs_destr	de_str;
} __packed;

struct aufs_wh {
	struct hlist_node	wh_hash;
	aufs_bindex_t		wh_bindex;
#ifdef CONFIG_AUFS_SHWH
	ino_t			wh_ino;
	unsigned char		wh_type;
	/* caution: packed */
#endif
	struct aufs_destr	wh_str;
} __packed;

union aufs_deblk_p {
	unsigned char	*p;
	aufs_deblk_t	*deblk;
	struct aufs_de	*de;
};

struct aufs_vdir {
	aufs_deblk_t	**vd_deblk;
	int		vd_nblk;
	struct {
		int			i;
		union aufs_deblk_p	p;
	} vd_last;

	unsigned long	vd_version;
	unsigned long	vd_jiffy;
};

/* ---------------------------------------------------------------------- */

/* dir.c */
extern struct file_operations aufs_dir_fop;
int au_test_empty_lower(struct dentry *dentry);
int au_test_empty(struct dentry *dentry, struct aufs_nhash *whlist);
void au_add_nlink(struct inode *dir, struct inode *h_dir);
void au_sub_nlink(struct inode *dir, struct inode *h_dir);

/* vdir.c */
struct aufs_nhash *nhash_new(gfp_t gfp);
void nhash_del(struct aufs_nhash *nhash);
void nhash_init(struct aufs_nhash *nhash);
void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src);
void nhash_fin(struct aufs_nhash *nhash);
int nhash_test_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt,
			 int limit);
int nhash_test_known_wh(struct aufs_nhash *whlist, char *name, int namelen);
int nhash_append_wh(struct aufs_nhash *whlist, char *name, int namelen,
		    ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
		    unsigned char shwh);
void au_vdir_free(struct aufs_vdir *vdir);
int au_vdir_init(struct file *file);
int au_fill_de(struct file *file, void *dirent, filldir_t filldir);

/* ---------------------------------------------------------------------- */

static inline
unsigned int au_name_hash(const unsigned char *name, unsigned int len)
{
	return (full_name_hash(name, len) % AuSize_NHASH);
}

static inline
void au_shwh_init_wh(struct aufs_wh *wh, ino_t ino, unsigned char d_type)
{
#ifdef CONFIG_AUFS_SHWH
	wh->wh_ino = ino;
	wh->wh_type = d_type;
#endif
}

#endif /* __KERNEL__ */
#endif /* __AUFS_DIR_H__ */