blob: 076d9662b4b311aa7ee550d8e4a41ca2b3955ca9 [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
Miklos Szeredie56818b2004-12-12 11:45:24 +00002 FUSE: Filesystem in Userspace
Miklos Szeredi149f6072005-01-10 12:29:28 +00003 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00004
Miklos Szeredie56818b2004-12-12 11:45:24 +00005 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00007*/
8
9#include "fuse_i.h"
10
Miklos Szeredi05033042001-11-13 16:11:35 +000011#include <linux/pagemap.h>
Miklos Szeredi5e183482001-10-31 14:52:35 +000012#include <linux/file.h>
Miklos Szeredi13ed4822004-11-20 11:12:21 +000013#ifdef KERNEL_2_6
14#include <linux/gfp.h>
15#else
16#include <linux/mm.h>
17#endif
18#include <linux/sched.h>
Miklos Szeredi81394522005-01-11 14:24:18 +000019#ifdef KERNEL_2_6_7_PLUS
20#include <linux/namei.h>
21#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000022
Miklos Szeredi254d5ed2004-03-02 11:11:24 +000023static inline unsigned long time_to_jiffies(unsigned long sec,
24 unsigned long nsec)
25{
Miklos Szeredi81394522005-01-11 14:24:18 +000026 struct timespec ts = {sec, nsec};
27 return jiffies + timespec_to_jiffies(&ts);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +000028}
29
Miklos Szeredi0f62d722005-01-04 12:45:54 +000030static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
31 struct dentry *entry,
32 struct fuse_entry_out *outarg)
33{
34 req->in.h.opcode = FUSE_LOOKUP;
35 req->in.h.nodeid = get_node_id(dir);
36 req->inode = dir;
37 req->in.numargs = 1;
38 req->in.args[0].size = entry->d_name.len + 1;
39 req->in.args[0].value = entry->d_name.name;
40 req->out.numargs = 1;
41 req->out.args[0].size = sizeof(struct fuse_entry_out);
42 req->out.args[0].value = outarg;
43}
44
45static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
46{
47 if (!entry->d_inode || is_bad_inode(entry->d_inode))
48 return 0;
Miklos Szeredi81394522005-01-11 14:24:18 +000049 else if (time_after(jiffies, entry->d_time)) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +000050 int err;
51 int version;
52 struct fuse_entry_out outarg;
53 struct inode *inode = entry->d_inode;
54 struct fuse_inode *fi = get_fuse_inode(inode);
55 struct fuse_conn *fc = get_fuse_conn(inode);
56 struct fuse_req *req = fuse_get_request_nonint(fc);
57 if (!req)
58 return 0;
59
60 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
61 request_send_nonint(fc, req);
62 version = req->out.h.unique;
63 err = req->out.h.error;
64 fuse_put_request(fc, req);
65 if (err || outarg.nodeid != get_node_id(inode) ||
66 (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
67 return 0;
68
69 fuse_change_attributes(inode, &outarg.attr);
70 inode->i_version = version;
71 entry->d_time = time_to_jiffies(outarg.entry_valid,
72 outarg.entry_valid_nsec);
73 fi->i_time = time_to_jiffies(outarg.attr_valid,
74 outarg.attr_valid_nsec);
75 }
76 return 1;
77}
78#ifndef KERNEL_2_6
79static int fuse_dentry_revalidate_2_4(struct dentry *entry, int flags)
80{
81 return fuse_dentry_revalidate(entry, NULL);
82}
83#endif
84
85static struct dentry_operations fuse_dentry_operations = {
86#ifdef KERNEL_2_6
87 .d_revalidate = fuse_dentry_revalidate,
88#else
89 .d_revalidate = fuse_dentry_revalidate_2_4,
90#endif
91};
92
Miklos Szeredie815c032004-01-19 18:20:49 +000093static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
94 struct inode **inodep)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +000095{
Miklos Szeredie815c032004-01-19 18:20:49 +000096 int err;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +000097 int version;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +000098 struct fuse_entry_out outarg;
Miklos Szeredie815c032004-01-19 18:20:49 +000099 struct inode *inode = NULL;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000100 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000101 struct fuse_req *req;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000102
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000103 if (entry->d_name.len > FUSE_NAME_MAX)
104 return -ENAMETOOLONG;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000105
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000106 req = fuse_get_request(fc);
107 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000108 return -ERESTARTNOINTR;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000109
Miklos Szeredie56818b2004-12-12 11:45:24 +0000110 fuse_lookup_init(req, dir, entry, &outarg);
111 request_send(fc, req);
112 version = req->out.h.unique;
113 err = req->out.h.error;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000114 if (!err) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000115 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000116 &outarg.attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000117 if (!inode) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000118 fuse_send_forget(fc, req, outarg.nodeid, version);
Miklos Szeredie815c032004-01-19 18:20:49 +0000119 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000120 }
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000121 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000122 fuse_put_request(fc, req);
123 if (err && err != -ENOENT)
Miklos Szeredie815c032004-01-19 18:20:49 +0000124 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000125
Miklos Szeredi069c9502004-07-16 16:17:02 +0000126 if (inode) {
Miklos Szeredi039322d2004-12-01 18:39:12 +0000127 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000128 entry->d_time = time_to_jiffies(outarg.entry_valid,
Miklos Szerediad051c32004-07-02 09:22:50 +0000129 outarg.entry_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000130 fi->i_time = time_to_jiffies(outarg.attr_valid,
131 outarg.attr_valid_nsec);
132 }
Miklos Szerediad051c32004-07-02 09:22:50 +0000133
Miklos Szeredi307242f2004-01-26 11:28:44 +0000134 entry->d_op = &fuse_dentry_operations;
Miklos Szeredie815c032004-01-19 18:20:49 +0000135 *inodep = inode;
136 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000137}
138
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000139void fuse_invalidate_attr(struct inode *inode)
Miklos Szeredi015fe702004-07-12 11:52:24 +0000140{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000141 get_fuse_inode(inode)->i_time = jiffies - 1;
Miklos Szeredi015fe702004-07-12 11:52:24 +0000142}
143
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000144static void fuse_invalidate_entry(struct dentry *entry)
145{
146 d_invalidate(entry);
147 entry->d_time = jiffies - 1;
148}
149
150static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000151 struct inode *dir, struct dentry *entry,
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000152 int mode)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000153{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000154 struct fuse_entry_out outarg;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000155 struct inode *inode;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000156 struct fuse_inode *fi;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000157 int version;
158 int err;
159
160 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000161 req->inode = dir;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000162 req->out.numargs = 1;
163 req->out.args[0].size = sizeof(outarg);
164 req->out.args[0].value = &outarg;
165 request_send(fc, req);
166 version = req->out.h.unique;
167 err = req->out.h.error;
168 if (err) {
169 fuse_put_request(fc, req);
170 return err;
171 }
172 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
173 &outarg.attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000174 if (!inode) {
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000175 fuse_send_forget(fc, req, outarg.nodeid, version);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000176 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000177 }
178 fuse_put_request(fc, req);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000179
180 /* Don't allow userspace to do really stupid things... */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000181 if ((inode->i_mode ^ mode) & S_IFMT) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000182 iput(inode);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000183 return -EIO;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000184 }
185
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000186 entry->d_time = time_to_jiffies(outarg.entry_valid,
187 outarg.entry_valid_nsec);
Miklos Szerediad051c32004-07-02 09:22:50 +0000188
Miklos Szeredi039322d2004-12-01 18:39:12 +0000189 fi = get_fuse_inode(inode);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000190 fi->i_time = time_to_jiffies(outarg.attr_valid,
191 outarg.attr_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000192
Miklos Szeredi76f65782004-02-19 16:55:40 +0000193 d_instantiate(entry, inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000194 fuse_invalidate_attr(dir);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000195 return 0;
196}
197
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000198static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000199 dev_t rdev)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000200{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000201 struct fuse_mknod_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000202 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000203 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000204 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000205 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000206
207 memset(&inarg, 0, sizeof(inarg));
208 inarg.mode = mode;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +0000209 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000210 req->in.h.opcode = FUSE_MKNOD;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000211 req->in.numargs = 2;
212 req->in.args[0].size = sizeof(inarg);
213 req->in.args[0].value = &inarg;
214 req->in.args[1].size = entry->d_name.len + 1;
215 req->in.args[1].value = entry->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000216 return create_new_entry(fc, req, dir, entry, mode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000217}
218
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000219static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
220 struct nameidata *nd)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000221{
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000222 return fuse_mknod(dir, entry, mode, 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000223}
224
Miklos Szeredib483c932001-10-29 14:57:57 +0000225static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
226{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000227 struct fuse_mkdir_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000228 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000229 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000230 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000231 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000232
233 memset(&inarg, 0, sizeof(inarg));
234 inarg.mode = mode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000235 req->in.h.opcode = FUSE_MKDIR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000236 req->in.numargs = 2;
237 req->in.args[0].size = sizeof(inarg);
238 req->in.args[0].value = &inarg;
239 req->in.args[1].size = entry->d_name.len + 1;
240 req->in.args[1].value = entry->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000241 return create_new_entry(fc, req, dir, entry, S_IFDIR);
Miklos Szeredib483c932001-10-29 14:57:57 +0000242}
243
244static int fuse_symlink(struct inode *dir, struct dentry *entry,
245 const char *link)
246{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000247 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi83a07442004-11-30 18:25:20 +0000248 unsigned len = strlen(link) + 1;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000249 struct fuse_req *req;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000250
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000251 if (len > FUSE_SYMLINK_MAX)
252 return -ENAMETOOLONG;
Miklos Szeredib483c932001-10-29 14:57:57 +0000253
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000254 req = fuse_get_request(fc);
255 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000256 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000257
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000258 req->in.h.opcode = FUSE_SYMLINK;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000259 req->in.numargs = 2;
260 req->in.args[0].size = entry->d_name.len + 1;
261 req->in.args[0].value = entry->d_name.name;
262 req->in.args[1].size = len;
263 req->in.args[1].value = link;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000264 return create_new_entry(fc, req, dir, entry, S_IFLNK);
Miklos Szeredib483c932001-10-29 14:57:57 +0000265}
266
Miklos Szeredib5958612004-02-20 14:10:49 +0000267static int fuse_unlink(struct inode *dir, struct dentry *entry)
Miklos Szeredib483c932001-10-29 14:57:57 +0000268{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000269 int err;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000270 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000271 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000272 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000273 return -ERESTARTNOINTR;
Miklos Szeredib483c932001-10-29 14:57:57 +0000274
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000275 req->in.h.opcode = FUSE_UNLINK;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000276 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000277 req->inode = dir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000278 req->in.numargs = 1;
279 req->in.args[0].size = entry->d_name.len + 1;
280 req->in.args[0].value = entry->d_name.name;
281 request_send(fc, req);
282 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000283 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000284 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000285 struct inode *inode = entry->d_inode;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000286
Miklos Szeredib5958612004-02-20 14:10:49 +0000287 /* Set nlink to zero so the inode can be cleared, if
288 the inode does have more links this will be
289 discovered at the next lookup/getattr */
Miklos Szeredi069c9502004-07-16 16:17:02 +0000290 inode->i_nlink = 0;
291 fuse_invalidate_attr(inode);
292 fuse_invalidate_attr(dir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000293 } else if (err == -EINTR)
294 fuse_invalidate_entry(entry);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000295 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000296}
297
298static int fuse_rmdir(struct inode *dir, struct dentry *entry)
299{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000300 int err;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000301 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000302 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000303 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000304 return -ERESTARTNOINTR;
Miklos Szeredib5958612004-02-20 14:10:49 +0000305
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000306 req->in.h.opcode = FUSE_RMDIR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000307 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000308 req->inode = dir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000309 req->in.numargs = 1;
310 req->in.args[0].size = entry->d_name.len + 1;
311 req->in.args[0].value = entry->d_name.name;
312 request_send(fc, req);
313 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000314 fuse_put_request(fc, req);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000315 if (!err) {
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000316 entry->d_inode->i_nlink = 0;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000317 fuse_invalidate_attr(dir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000318 } else if (err == -EINTR)
319 fuse_invalidate_entry(entry);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000320 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000321}
322
323static int fuse_rename(struct inode *olddir, struct dentry *oldent,
324 struct inode *newdir, struct dentry *newent)
325{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000326 int err;
327 struct fuse_rename_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000328 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000329 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000330 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000331 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000332
Miklos Szeredi43696432001-11-18 19:15:05 +0000333 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi039322d2004-12-01 18:39:12 +0000334 inarg.newdir = get_node_id(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000335 req->in.h.opcode = FUSE_RENAME;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000336 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000337 req->inode = olddir;
338 req->inode2 = newdir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000339 req->in.numargs = 3;
340 req->in.args[0].size = sizeof(inarg);
341 req->in.args[0].value = &inarg;
342 req->in.args[1].size = oldent->d_name.len + 1;
343 req->in.args[1].value = oldent->d_name.name;
344 req->in.args[2].size = newent->d_name.len + 1;
345 req->in.args[2].value = newent->d_name.name;
346 request_send(fc, req);
347 err = req->out.h.error;
348 fuse_put_request(fc, req);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000349 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000350 fuse_invalidate_attr(olddir);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000351 if (olddir != newdir)
Miklos Szeredi069c9502004-07-16 16:17:02 +0000352 fuse_invalidate_attr(newdir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000353 } else if (err == -EINTR) {
354 /* If request was interrupted, DEITY only knows if the
355 rename actually took place. If the invalidation
356 fails (e.g. some process has CWD under the renamed
357 directory), then there can be inconsistency between
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000358 the dcache and the real filesystem. Tough luck. */
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000359 fuse_invalidate_entry(oldent);
360 if (newent->d_inode)
361 fuse_invalidate_entry(newent);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000362 }
Miklos Szeredicdae16e2005-01-14 11:43:22 +0000363
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000364 return err;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000365}
366
367static int fuse_link(struct dentry *entry, struct inode *newdir,
368 struct dentry *newent)
369{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000370 int err;
371 struct fuse_link_in inarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000372 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000373 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000374 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000375 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000376 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000377
Miklos Szeredi43696432001-11-18 19:15:05 +0000378 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi039322d2004-12-01 18:39:12 +0000379 inarg.newdir = get_node_id(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000380 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000381 req->inode2 = newdir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000382 req->in.numargs = 2;
383 req->in.args[0].size = sizeof(inarg);
384 req->in.args[0].value = &inarg;
385 req->in.args[1].size = newent->d_name.len + 1;
386 req->in.args[1].value = newent->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000387 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
388 /* Contrary to "normal" filesystems it can happen that link
389 makes two "logical" inodes point to the same "physical"
390 inode. We invalidate the attributes of the old one, so it
391 will reflect changes in the backing inode (link count,
392 etc.)
393 */
394 if (!err || err == -EINTR)
395 fuse_invalidate_attr(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000396 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000397}
398
Miklos Szeredif85ab242004-01-07 12:16:45 +0000399int fuse_do_getattr(struct inode *inode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000400{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000401 int err;
402 struct fuse_attr_out arg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000403 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000404 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000405 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000406 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000407
408 req->in.h.opcode = FUSE_GETATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000409 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000410 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000411 req->out.numargs = 1;
412 req->out.args[0].size = sizeof(arg);
413 req->out.args[0].value = &arg;
414 request_send(fc, req);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000415 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000416 fuse_put_request(fc, req);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000417 if (!err) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000418 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
Miklos Szeredidbe0f652005-01-15 14:32:56 +0000419 if (get_node_id(inode) != FUSE_ROOT_ID)
420 make_bad_inode(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000421 err = -EIO;
422 } else {
423 struct fuse_inode *fi = get_fuse_inode(inode);
424 fuse_change_attributes(inode, &arg.attr);
425 fi->i_time = time_to_jiffies(arg.attr_valid,
426 arg.attr_valid_nsec);
427 }
Miklos Szeredi069c9502004-07-16 16:17:02 +0000428 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000429 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000430}
431
Miklos Szeredife25def2001-12-20 15:38:05 +0000432static int fuse_revalidate(struct dentry *entry)
433{
434 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000435 struct fuse_inode *fi = get_fuse_inode(inode);
436 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000437
Miklos Szeredi039322d2004-12-01 18:39:12 +0000438 if (get_node_id(inode) == FUSE_ROOT_ID) {
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000439 if (!(fc->flags & FUSE_ALLOW_OTHER) &&
Miklos Szeredi3c7d41b2005-01-09 20:05:27 +0000440 current->fsuid != fc->user_id &&
Miklos Szeredi180ff692004-11-01 16:01:05 +0000441 (!(fc->flags & FUSE_ALLOW_ROOT) ||
Miklos Szeredi9ed69ba2005-01-13 12:11:49 +0000442 !capable(CAP_DAC_OVERRIDE)))
Miklos Szeredife25def2001-12-20 15:38:05 +0000443 return -EACCES;
Miklos Szeredi81394522005-01-11 14:24:18 +0000444 } else if (time_before_eq(jiffies, fi->i_time))
Miklos Szeredife25def2001-12-20 15:38:05 +0000445 return 0;
446
Miklos Szeredif85ab242004-01-07 12:16:45 +0000447 return fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000448}
449
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000450static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
Miklos Szeredife25def2001-12-20 15:38:05 +0000451{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000452 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000453
Miklos Szeredi3c7d41b2005-01-09 20:05:27 +0000454 if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id &&
Miklos Szeredi9ed69ba2005-01-13 12:11:49 +0000455 (!(fc->flags & FUSE_ALLOW_ROOT) || !capable(CAP_DAC_OVERRIDE)))
Miklos Szeredife25def2001-12-20 15:38:05 +0000456 return -EACCES;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000457 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000458#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000459 int err = generic_permission(inode, mask, NULL);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000460#else
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000461 int err = vfs_permission(inode, mask);
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000462#endif
Miklos Szeredife25def2001-12-20 15:38:05 +0000463
464 /* If permission is denied, try to refresh file
465 attributes. This is also needed, because the root
466 node will at first have no permissions */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000467 if (err == -EACCES) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000468 err = fuse_do_getattr(inode);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000469 if (!err)
470#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000471 err = generic_permission(inode, mask, NULL);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000472#else
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000473 err = vfs_permission(inode, mask);
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000474#endif
Miklos Szeredife25def2001-12-20 15:38:05 +0000475 }
476
477 /* FIXME: Need some mechanism to revoke permissions:
478 currently if the filesystem suddenly changes the
Miklos Szeredi064efb02004-11-09 17:30:29 +0000479 file mode, we will not be informed about it, and
Miklos Szeredife25def2001-12-20 15:38:05 +0000480 continue to allow access to the file/directory.
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000481
Miklos Szeredife25def2001-12-20 15:38:05 +0000482 This is actually not so grave, since the user can
483 simply keep access to the file/directory anyway by
484 keeping it open... */
485
486 return err;
Miklos Szeredi96dfad72004-11-30 00:00:02 +0000487 } else {
488 int mode = inode->i_mode;
489 if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
490 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
491 return -EROFS;
492 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
493 return -EACCES;
Miklos Szeredife25def2001-12-20 15:38:05 +0000494 return 0;
Miklos Szeredi96dfad72004-11-30 00:00:02 +0000495 }
Miklos Szeredife25def2001-12-20 15:38:05 +0000496}
497
Miklos Szeredib483c932001-10-29 14:57:57 +0000498static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
499 void *dstbuf, filldir_t filldir)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000500{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000501 while (nbytes >= FUSE_NAME_OFFSET) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000502 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000503 size_t reclen = FUSE_DIRENT_SIZE(dirent);
504 int over;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000505 if (dirent->namelen > FUSE_NAME_MAX)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000506 return -EIO;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000507 if (reclen > nbytes)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000508 break;
509
510 over = filldir(dstbuf, dirent->name, dirent->namelen,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000511 file->f_pos, dirent->ino, dirent->type);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000512 if (over)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000513 break;
514
Miklos Szeredib483c932001-10-29 14:57:57 +0000515 buf += reclen;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000516 file->f_pos += reclen;
517 nbytes -= reclen;
518 }
519
Miklos Szeredib483c932001-10-29 14:57:57 +0000520 return 0;
521}
522
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000523static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
524 struct inode *inode, loff_t pos,
525 size_t count)
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000526{
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000527 return fuse_send_read_common(req, file, inode, pos, count, 1);
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000528}
529
Miklos Szeredib483c932001-10-29 14:57:57 +0000530static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
531{
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000532 int err;
533 size_t nbytes;
534 struct page *page;
535 struct inode *inode = file->f_dentry->d_inode;
536 struct fuse_conn *fc = get_fuse_conn(inode);
537 struct fuse_req *req = fuse_get_request(fc);
538 if (!req)
539 return -ERESTARTNOINTR;
Miklos Szeredie815c032004-01-19 18:20:49 +0000540
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000541 page = alloc_page(GFP_KERNEL);
542 if (!page) {
543 fuse_put_request(fc, req);
Miklos Szeredib483c932001-10-29 14:57:57 +0000544 return -ENOMEM;
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000545 }
546 req->num_pages = 1;
547 req->pages[0] = page;
548 nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
549 err = req->out.h.error;
550 fuse_put_request(fc, req);
551 if (!err)
552 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
553 filldir);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000554
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000555 __free_page(page);
556 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000557}
558
Miklos Szeredi05033042001-11-13 16:11:35 +0000559static char *read_link(struct dentry *dentry)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000560{
561 struct inode *inode = dentry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000562 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000563 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi05033042001-11-13 16:11:35 +0000564 char *link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000565
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000566 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000567 return ERR_PTR(-ERESTARTNOINTR);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000568
Miklos Szeredi05033042001-11-13 16:11:35 +0000569 link = (char *) __get_free_page(GFP_KERNEL);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000570 if (!link) {
571 link = ERR_PTR(-ENOMEM);
572 goto out;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000573 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000574 req->in.h.opcode = FUSE_READLINK;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000575 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000576 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000577 req->out.argvar = 1;
578 req->out.numargs = 1;
579 req->out.args[0].size = PAGE_SIZE - 1;
580 req->out.args[0].value = link;
581 request_send(fc, req);
582 if (req->out.h.error) {
583 free_page((unsigned long) link);
584 link = ERR_PTR(req->out.h.error);
585 } else
586 link[req->out.args[0].size] = '\0';
587 out:
588 fuse_put_request(fc, req);
Miklos Szeredi05033042001-11-13 16:11:35 +0000589 return link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000590}
591
592static void free_link(char *link)
593{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000594 if (!IS_ERR(link))
Miklos Szeredi05033042001-11-13 16:11:35 +0000595 free_page((unsigned long) link);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000596}
597
Miklos Szeredi81394522005-01-11 14:24:18 +0000598#ifdef KERNEL_2_6_7_PLUS
599static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
600{
601 nd_set_link(nd, read_link(dentry));
602 return 0;
603}
604
605static void fuse_put_link(struct dentry *dentry, struct nameidata *nd)
606{
607 free_link(nd_get_link(nd));
608}
609#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000610static int fuse_readlink(struct dentry *dentry, char __user *buffer,
611 int buflen)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000612{
613 int ret;
614 char *link;
615
Miklos Szeredi05033042001-11-13 16:11:35 +0000616 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000617 ret = vfs_readlink(dentry, buffer, buflen, link);
618 free_link(link);
619 return ret;
620}
621
622static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
623{
624 int ret;
625 char *link;
626
Miklos Szeredi05033042001-11-13 16:11:35 +0000627 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000628 ret = vfs_follow_link(nd, link);
629 free_link(link);
630 return ret;
631}
Miklos Szeredi81394522005-01-11 14:24:18 +0000632#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000633
634static int fuse_dir_open(struct inode *inode, struct file *file)
635{
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000636 return fuse_open_common(inode, file, 1);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000637}
638
639static int fuse_dir_release(struct inode *inode, struct file *file)
640{
Miklos Szeredi1adb2272005-01-18 21:19:58 +0000641 return fuse_release_common(inode, file, 1);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000642}
643
Miklos Szeredi83a07442004-11-30 18:25:20 +0000644static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000645{
Miklos Szeredi83a07442004-11-30 18:25:20 +0000646 unsigned ivalid = iattr->ia_valid;
647 unsigned fvalid = 0;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000648
Miklos Szeredi5e183482001-10-31 14:52:35 +0000649 memset(fattr, 0, sizeof(*fattr));
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000650
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000651 if (ivalid & ATTR_MODE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000652 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000653 if (ivalid & ATTR_UID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000654 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000655 if (ivalid & ATTR_GID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000656 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000657 if (ivalid & ATTR_SIZE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000658 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
659 /* You can only _set_ these together (they may change by themselves) */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000660 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000661 fvalid |= FATTR_ATIME | FATTR_MTIME;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000662#ifdef KERNEL_2_6
663 fattr->atime = iattr->ia_atime.tv_sec;
664 fattr->mtime = iattr->ia_mtime.tv_sec;
665#else
Miklos Szeredi5e183482001-10-31 14:52:35 +0000666 fattr->atime = iattr->ia_atime;
667 fattr->mtime = iattr->ia_mtime;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000668#endif
Miklos Szeredi5e183482001-10-31 14:52:35 +0000669 }
670
671 return fvalid;
672}
673
674static int fuse_setattr(struct dentry *entry, struct iattr *attr)
675{
676 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000677 struct fuse_conn *fc = get_fuse_conn(inode);
678 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi58615e02004-07-04 21:21:08 +0000679 struct fuse_req *req;
Miklos Szeredia181e612001-11-06 12:03:23 +0000680 struct fuse_setattr_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000681 struct fuse_attr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000682 int err;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000683 int is_truncate = 0;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000684
Miklos Szeredi94ed76a2004-07-26 19:38:45 +0000685 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
686 err = inode_change_ok(inode, attr);
687 if (err)
688 return err;
689 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000690
Miklos Szeredi069c9502004-07-16 16:17:02 +0000691 if (attr->ia_valid & ATTR_SIZE) {
692 unsigned long limit;
693 is_truncate = 1;
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000694#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000695 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000696#else
697 limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000698#endif
699 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000700 send_sig(SIGXFSZ, current, 0);
701 return -EFBIG;
702 }
Miklos Szeredi069c9502004-07-16 16:17:02 +0000703 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000704
705 req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000706 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000707 return -ERESTARTNOINTR;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000708
Miklos Szeredi43696432001-11-18 19:15:05 +0000709 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia181e612001-11-06 12:03:23 +0000710 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000711 req->in.h.opcode = FUSE_SETATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000712 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000713 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000714 req->in.numargs = 1;
715 req->in.args[0].size = sizeof(inarg);
716 req->in.args[0].value = &inarg;
717 req->out.numargs = 1;
718 req->out.args[0].size = sizeof(outarg);
719 req->out.args[0].value = &outarg;
720 request_send(fc, req);
721 err = req->out.h.error;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000722 fuse_put_request(fc, req);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000723 if (!err) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000724 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredidbe0f652005-01-15 14:32:56 +0000725 if (get_node_id(inode) != FUSE_ROOT_ID)
726 make_bad_inode(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000727 err = -EIO;
728 } else {
729 if (is_truncate) {
730 loff_t origsize = i_size_read(inode);
731 i_size_write(inode, outarg.attr.size);
732 if (origsize > outarg.attr.size)
733 vmtruncate(inode, outarg.attr.size);
734 }
735 fuse_change_attributes(inode, &outarg.attr);
736 fi->i_time = time_to_jiffies(outarg.attr_valid,
737 outarg.attr_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000738 }
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000739 } else if (err == -EINTR)
740 fuse_invalidate_attr(inode);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000741
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000742 return err;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000743}
744
Miklos Szeredif85ab242004-01-07 12:16:45 +0000745#ifdef KERNEL_2_6
Miklos Szeredif85ab242004-01-07 12:16:45 +0000746static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
747 struct kstat *stat)
748{
749 struct inode *inode = entry->d_inode;
750 int err = fuse_revalidate(entry);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000751 if (!err)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000752 generic_fillattr(inode, stat);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000753
Miklos Szeredif85ab242004-01-07 12:16:45 +0000754 return err;
755}
756
757static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000758 struct nameidata *nd)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000759{
Miklos Szeredie815c032004-01-19 18:20:49 +0000760 struct inode *inode;
761 int err = fuse_lookup_iget(dir, entry, &inode);
762 if (err)
763 return ERR_PTR(err);
764 return d_splice_alias(inode, entry);
Miklos Szeredif85ab242004-01-07 12:16:45 +0000765}
Miklos Szeredi689f5632004-05-04 08:49:16 +0000766#else /* KERNEL_2_6 */
Miklos Szeredi689f5632004-05-04 08:49:16 +0000767static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
768{
769 struct inode *inode;
770 struct dentry *alias;
771
772 int err = fuse_lookup_iget(dir, entry, &inode);
773 if (err)
774 return ERR_PTR(err);
775
776 if (inode && S_ISDIR(inode->i_mode) &&
777 (alias = d_find_alias(inode)) != NULL) {
778 dput(alias);
779 iput(inode);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000780 return ERR_PTR(-EIO);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000781 }
782
783 d_add(entry, inode);
784 return NULL;
785}
786
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000787static int fuse_mknod_2_4(struct inode *dir, struct dentry *entry, int mode,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000788 int rdev)
Miklos Szeredi689f5632004-05-04 08:49:16 +0000789{
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000790 return fuse_mknod(dir, entry, mode, rdev);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000791}
792
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000793static int fuse_create_2_4(struct inode *dir, struct dentry *entry, int mode)
794{
795 return fuse_create(dir, entry, mode, NULL);
796}
797
798static int fuse_permission_2_4(struct inode *inode, int mask)
799{
800 return fuse_permission(inode, mask, NULL);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000801}
802#endif /* KERNEL_2_6 */
803
804#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi689f5632004-05-04 08:49:16 +0000805#ifdef KERNEL_2_6
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000806static int fuse_setxattr(struct dentry *entry, const char *name,
807 const void *value, size_t size, int flags)
Miklos Szeredi689f5632004-05-04 08:49:16 +0000808#else
809static int fuse_setxattr(struct dentry *entry, const char *name,
810 void *value, size_t size, int flags)
811#endif
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000812{
813 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000814 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000815 struct fuse_req *req;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000816 struct fuse_setxattr_in inarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000817 int err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000818
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000819 if (size > FUSE_XATTR_SIZE_MAX)
820 return -E2BIG;
821
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000822 if (fc->no_setxattr)
823 return -EOPNOTSUPP;
824
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000825 req = fuse_get_request(fc);
826 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000827 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000828
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000829 memset(&inarg, 0, sizeof(inarg));
830 inarg.size = size;
831 inarg.flags = flags;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000832 req->in.h.opcode = FUSE_SETXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000833 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000834 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000835 req->in.numargs = 3;
836 req->in.args[0].size = sizeof(inarg);
837 req->in.args[0].value = &inarg;
838 req->in.args[1].size = strlen(name) + 1;
839 req->in.args[1].value = name;
840 req->in.args[2].size = size;
841 req->in.args[2].value = value;
842 request_send(fc, req);
843 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000844 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000845 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000846 fc->no_setxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000847 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000848 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000849 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000850}
851
852static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
853 void *value, size_t size)
854{
855 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000856 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000857 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000858 struct fuse_getxattr_in inarg;
859 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000860 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000861
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000862 if (fc->no_getxattr)
863 return -EOPNOTSUPP;
864
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000865 req = fuse_get_request(fc);
866 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000867 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000868
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000869 memset(&inarg, 0, sizeof(inarg));
870 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000871 req->in.h.opcode = FUSE_GETXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000872 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000873 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000874 req->in.numargs = 2;
875 req->in.args[0].size = sizeof(inarg);
876 req->in.args[0].value = &inarg;
877 req->in.args[1].size = strlen(name) + 1;
878 req->in.args[1].value = name;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000879 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000880 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000881 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000882 req->out.argvar = 1;
883 req->out.args[0].size = size;
884 req->out.args[0].value = value;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000885 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000886 req->out.args[0].size = sizeof(outarg);
887 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000888 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000889 request_send(fc, req);
890 ret = req->out.h.error;
891 if (!ret)
892 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000893 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000894 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000895 fc->no_getxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000896 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000897 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000898 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000899 fuse_put_request(fc, req);
900 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000901}
902
903static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
904{
905 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000906 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000907 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000908 struct fuse_getxattr_in inarg;
909 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000910 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000911
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000912 if (fc->no_listxattr)
913 return -EOPNOTSUPP;
914
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000915 req = fuse_get_request(fc);
916 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000917 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000918
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000919 memset(&inarg, 0, sizeof(inarg));
920 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000921 req->in.h.opcode = FUSE_LISTXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000922 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000923 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000924 req->in.numargs = 1;
925 req->in.args[0].size = sizeof(inarg);
926 req->in.args[0].value = &inarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000927 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000928 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000929 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000930 req->out.argvar = 1;
931 req->out.args[0].size = size;
932 req->out.args[0].value = list;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000933 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000934 req->out.args[0].size = sizeof(outarg);
935 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000936 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000937 request_send(fc, req);
938 ret = req->out.h.error;
939 if (!ret)
940 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000941 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000942 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000943 fc->no_listxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000944 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000945 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000946 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000947 fuse_put_request(fc, req);
948 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000949}
950
951static int fuse_removexattr(struct dentry *entry, const char *name)
952{
953 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000954 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000955 struct fuse_req *req;
956 int err;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000957
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000958 if (fc->no_removexattr)
959 return -EOPNOTSUPP;
960
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000961 req = fuse_get_request(fc);
962 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000963 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000964
965 req->in.h.opcode = FUSE_REMOVEXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000966 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000967 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000968 req->in.numargs = 1;
969 req->in.args[0].size = strlen(name) + 1;
970 req->in.args[0].value = name;
971 request_send(fc, req);
972 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000973 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000974 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000975 fc->no_removexattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000976 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000977 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000978 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000979}
Miklos Szeredi689f5632004-05-04 08:49:16 +0000980#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +0000981
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000982static struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000983 .lookup = fuse_lookup,
Miklos Szeredie8663f32004-01-13 15:33:12 +0000984 .mkdir = fuse_mkdir,
985 .symlink = fuse_symlink,
986 .unlink = fuse_unlink,
987 .rmdir = fuse_rmdir,
988 .rename = fuse_rename,
989 .link = fuse_link,
990 .setattr = fuse_setattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000991#ifdef KERNEL_2_6
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000992 .create = fuse_create,
993 .mknod = fuse_mknod,
994 .permission = fuse_permission,
Miklos Szeredie8663f32004-01-13 15:33:12 +0000995 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +0000996#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000997 .create = fuse_create_2_4,
998 .mknod = fuse_mknod_2_4,
999 .permission = fuse_permission_2_4,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001000 .revalidate = fuse_revalidate,
1001#endif
1002#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001003 .setxattr = fuse_setxattr,
1004 .getxattr = fuse_getxattr,
1005 .listxattr = fuse_listxattr,
1006 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001007#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001008};
1009
1010static struct file_operations fuse_dir_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001011 .read = generic_read_dir,
1012 .readdir = fuse_readdir,
1013 .open = fuse_dir_open,
1014 .release = fuse_dir_release,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001015};
1016
Miklos Szeredi0f62d722005-01-04 12:45:54 +00001017static struct inode_operations fuse_common_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001018 .setattr = fuse_setattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001019#ifdef KERNEL_2_6
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001020 .permission = fuse_permission,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001021 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001022#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001023 .permission = fuse_permission_2_4,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001024 .revalidate = fuse_revalidate,
1025#endif
1026#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001027 .setxattr = fuse_setxattr,
1028 .getxattr = fuse_getxattr,
1029 .listxattr = fuse_listxattr,
1030 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001031#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001032};
1033
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001034static struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001035 .setattr = fuse_setattr,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001036 .follow_link = fuse_follow_link,
Miklos Szeredi81394522005-01-11 14:24:18 +00001037#ifdef KERNEL_2_6_7_PLUS
1038 .put_link = fuse_put_link,
1039 .readlink = generic_readlink,
1040#else
1041 .readlink = fuse_readlink,
1042#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +00001043#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +00001044 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001045#else
1046 .revalidate = fuse_revalidate,
1047#endif
1048#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001049 .setxattr = fuse_setxattr,
1050 .getxattr = fuse_getxattr,
1051 .listxattr = fuse_listxattr,
1052 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001053#endif
Miklos Szeredi19dff1b2001-10-30 15:06:52 +00001054};
1055
Miklos Szeredi0f62d722005-01-04 12:45:54 +00001056void fuse_init_common(struct inode *inode)
1057{
1058 inode->i_op = &fuse_common_inode_operations;
1059}
1060
1061void fuse_init_dir(struct inode *inode)
1062{
1063 inode->i_op = &fuse_dir_inode_operations;
1064 inode->i_fop = &fuse_dir_operations;
1065}
1066
1067void fuse_init_symlink(struct inode *inode)
1068{
1069 inode->i_op = &fuse_symlink_inode_operations;
1070}