~ubuntu-branches/ubuntu/precise/linux-ti-omap/precise

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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * Copyright (C) 2005-2009 Junjiro R. 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
 */

/*
 * file operations
 */

#ifndef __AUFS_FILE_H__
#define __AUFS_FILE_H__

#ifdef __KERNEL__

#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/aufs_type.h>
#include "rwsem.h"

struct au_branch;
struct au_hfile {
	struct file		*hf_file;
	struct au_branch	*hf_br;
};

struct au_vdir;
struct au_finfo {
	atomic_t		fi_generation;

	struct au_rwsem		fi_rwsem;
	struct au_hfile		*fi_hfile;
	aufs_bindex_t		fi_bstart, fi_bend;

	union {
		/* non-dir only */
		struct {
			struct vm_operations_struct	*fi_h_vm_ops;
			struct vm_operations_struct	*fi_vm_ops;
			struct mutex			fi_vm_mtx;
		};

		/* dir only */
		struct {
			struct au_vdir		*fi_vdir_cache;
			int			fi_maintain_plink;
		};
	};
};

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

/* file.c */
extern struct address_space_operations aufs_aop;
unsigned int au_file_roflags(unsigned int flags);
struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
		       struct file *file);
int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
int au_reopen_nondir(struct file *file);
struct au_pin;
int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
			  int wlock);

/* poll.c */
#ifdef CONFIG_AUFS_POLL
unsigned int aufs_poll(struct file *file, poll_table *wait);
#endif

/* f_op.c */
extern const struct file_operations aufs_file_fop;
int aufs_flush(struct file *file, fl_owner_t id);

/* finfo.c */
void au_hfput(struct au_hfile *hf, struct file *file);
void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
		   struct file *h_file);

void au_update_figen(struct file *file);

void au_finfo_fin(struct file *file);
int au_finfo_init(struct file *file);
int au_fi_realloc(struct au_finfo *finfo, int nbr);

/* ioctl.c */
long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);

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

static inline struct au_finfo *au_fi(struct file *file)
{
	return file->private_data;
}

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

/*
 * fi_read_lock, fi_write_lock,
 * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
 */
AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);

#define FiMustNoWaiters(f)	AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
#define FiMustAnyLock(f)	AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
#define FiMustWriteLock(f)	AuRwMustWriteLock(&au_fi(f)->fi_rwsem)

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

/* todo: hard/soft set? */
static inline aufs_bindex_t au_fbstart(struct file *file)
{
	FiMustAnyLock(file);
	return au_fi(file)->fi_bstart;
}

static inline aufs_bindex_t au_fbend(struct file *file)
{
	FiMustAnyLock(file);
	return au_fi(file)->fi_bend;
}

static inline struct au_vdir *au_fvdir_cache(struct file *file)
{
	FiMustAnyLock(file);
	return au_fi(file)->fi_vdir_cache;
}

static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
{
	FiMustWriteLock(file);
	au_fi(file)->fi_bstart = bindex;
}

static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
{
	FiMustWriteLock(file);
	au_fi(file)->fi_bend = bindex;
}

static inline void au_set_fvdir_cache(struct file *file,
				      struct au_vdir *vdir_cache)
{
	FiMustWriteLock(file);
	au_fi(file)->fi_vdir_cache = vdir_cache;
}

static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
{
	FiMustAnyLock(file);
	return au_fi(file)->fi_hfile[0 + bindex].hf_file;
}

/* todo: memory barrier? */
static inline unsigned int au_figen(struct file *f)
{
	return atomic_read(&au_fi(f)->fi_generation);
}

static inline int au_test_mmapped(struct file *f)
{
	/* FiMustAnyLock(f); */
	return !!(au_fi(f)->fi_h_vm_ops);
}

#endif /* __KERNEL__ */
#endif /* __AUFS_FILE_H__ */