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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
# HG changeset patch
# User mszeredi
# Date 1197485983 0
# Node ID 5b8914cfe0fb7ccfb6e7f61512374d8541f2a193
# Parent 81a85541800582144b7381e0b022c10245facc61
Fix kernel module compile for 2.6.24
--- a/kernel/dir.c Wed Dec 12 14:33:17 2007 +0000
+++ b/kernel/dir.c Wed Dec 12 18:59:43 2007 +0000
@@ -191,7 +191,7 @@ static int invalid_nodeid(u64 nodeid)
return !nodeid || nodeid == FUSE_ROOT_ID;
}
-static struct dentry_operations fuse_dentry_operations = {
+struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
@@ -378,6 +378,7 @@ static int fuse_create_open(struct inode
}
fuse_put_request(fc, forget_req);
d_instantiate(entry, inode);
+ fuse_invalidate_attr(dir);
fuse_change_timeout(entry, &outentry);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
@@ -619,6 +620,9 @@ static int fuse_rename(struct inode *old
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err) {
+ /* ctime changes */
+ fuse_invalidate_attr(oldent->d_inode);
+
fuse_invalidate_attr(olddir);
if (olddir != newdir)
fuse_invalidate_attr(newdir);
--- a/kernel/fuse_i.h Wed Dec 12 14:33:17 2007 +0000
+++ b/kernel/fuse_i.h Wed Dec 12 18:59:43 2007 +0000
@@ -47,6 +47,9 @@
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
# define KERNEL_2_6_23_PLUS
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define KERNEL_2_6_24_PLUS
#endif
#if defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
@@ -647,3 +650,5 @@ int fuse_valid_type(int m);
* Is task allowed to perform filesystem operation?
*/
int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
+
+extern struct dentry_operations fuse_dentry_operations;
--- a/kernel/inode.c Wed Dec 12 14:33:17 2007 +0000
+++ b/kernel/inode.c Wed Dec 12 18:59:43 2007 +0000
@@ -520,21 +520,26 @@ static struct inode *get_root_inode(stru
#ifdef HAVE_EXPORTFS_H
#include <linux/exportfs.h>
#endif
-static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
+
+struct fuse_inode_handle
{
- __u32 *objp = vobjp;
- unsigned long nodeid = objp[0];
- __u32 generation = objp[1];
+ u64 nodeid;
+ u32 generation;
+};
+
+static struct dentry *fuse_get_dentry(struct super_block *sb,
+ struct fuse_inode_handle *handle)
+{
struct inode *inode;
struct dentry *entry;
- if (nodeid == 0)
+ if (handle->nodeid == 0)
return ERR_PTR(-ESTALE);
- inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
+ inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
if (!inode)
return ERR_PTR(-ESTALE);
- if (inode->i_generation != generation) {
+ if (inode->i_generation != handle->generation) {
iput(inode);
return ERR_PTR(-ESTALE);
}
@@ -544,42 +549,130 @@ static struct dentry *fuse_get_dentry(st
iput(inode);
return ERR_PTR(-ENOMEM);
}
+ entry->d_op = &fuse_dentry_operations;
return entry;
}
-static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
- int connectable)
+static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
+ int connectable)
{
struct inode *inode = dentry->d_inode;
int len = *max_len;
int type = 1;
+ u64 nodeid;
+ u32 generation;
- if (len < 2 || (connectable && len < 4))
- return 255;
+ if (len < 3 || (connectable && len < 6))
+ return 255;
- len = 2;
- fh[0] = get_fuse_inode(inode)->nodeid;
- fh[1] = inode->i_generation;
+ nodeid = get_fuse_inode(inode)->nodeid;
+ generation = inode->i_generation;
+
+ len = 3;
+ fh[0] = (u32)(nodeid >> 32);
+ fh[1] = (u32)(nodeid & 0xffffffff);
+ fh[2] = generation;
+
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
- fh[2] = get_fuse_inode(parent)->nodeid;
- fh[3] = parent->i_generation;
+ nodeid = get_fuse_inode(parent)->nodeid;
+ generation = parent->i_generation;
+
+ fh[3] = (u32)(nodeid >> 32);
+ fh[4] = (u32)(nodeid & 0xffffffff);
+ fh[5] = generation;
spin_unlock(&dentry->d_lock);
- len = 4;
+
+ len = 6;
type = 2;
}
+
*max_len = len;
return type;
}
+#ifdef KERNEL_2_6_24_PLUS
+static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle handle;
+
+ if (fh_len < 3 || fh_type > 2)
+ return NULL;
+
+ handle.nodeid = (u64) fid->raw[0] << 32;
+ handle.nodeid |= (u64) fid->raw[1];
+ handle.generation = fid->raw[2];
+ return fuse_get_dentry(sb, &handle);
+}
+
+static struct dentry *fuse_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle parent;
+
+ if (fh_type != 2 || fh_len < 6)
+ return NULL;
+
+ parent.nodeid = (u64) fid->raw[3] << 32;
+ parent.nodeid |= (u64) fid->raw[4];
+ parent.generation = fid->raw[5];
+ return fuse_get_dentry(sb, &parent);
+}
+
+
+static const struct export_operations fuse_export_operations = {
+ .fh_to_dentry = fuse_fh_to_dentry,
+ .fh_to_parent = fuse_fh_to_parent,
+ .encode_fh = fuse_encode_fh,
+};
+#else
+static struct dentry *fuse_get_dentry_old(struct super_block *sb, void *objp)
+{
+ return fuse_get_dentry(sb, objp);
+}
+
+static struct dentry *fuse_decode_fh(struct super_block *sb, u32 *fh,
+ int fh_len, int fileid_type,
+ int (*acceptable)(void *context, struct dentry *de),
+ void *context)
+{
+ struct fuse_inode_handle handle;
+ struct fuse_inode_handle parent;
+
+ if (fh_len < 3 || fileid_type > 2)
+ return NULL;
+
+ if (fileid_type == 2) {
+ if (fh_len < 6)
+ return NULL;
+
+ parent.nodeid = (u64) fh[3] << 32;
+ parent.nodeid |= (u64) fh[4];
+ parent.generation = fh[5];
+ } else {
+ parent.nodeid = 0;
+ parent.generation = 0;
+ }
+
+ handle.nodeid = (u64) fh[0] << 32;
+ handle.nodeid |= (u64) fh[1];
+ handle.generation = fh[2];
+
+ return ret = fuse_export_operations.
+ find_exported_dentry(sb, &handle, &parent, acceptable, context);
+}
+
static struct export_operations fuse_export_operations = {
- .get_dentry = fuse_get_dentry,
+ .get_dentry = fuse_get_dentry_old,
.encode_fh = fuse_encode_fh,
+ .decode_fh = fuse_decode_fh,
};
+#endif
#endif
static struct super_operations fuse_super_operations = {
@@ -845,8 +938,12 @@ static decl_subsys(fuse, NULL, NULL);
static decl_subsys(fuse, NULL, NULL);
static decl_subsys(connections, NULL, NULL);
+#ifdef KERNEL_2_6_24_PLUS
+static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo)
+#else
static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
unsigned long flags)
+#endif
{
struct inode * inode = foo;
|