blob: cfc8f81e60d0133a060a9d5374fc399820de9c9a [file] [log] [blame]
Miklos Szeredie5e55582005-09-09 13:10:28 -07001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi51eb01e2006-06-25 05:48:50 -07003 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredie5e55582005-09-09 13:10:28 -07004
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
13#include <linux/gfp.h>
14#include <linux/sched.h>
15#include <linux/namei.h>
16
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070017#if BITS_PER_LONG >= 64
18static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
19{
20 entry->d_time = time;
21}
22
23static inline u64 fuse_dentry_time(struct dentry *entry)
24{
25 return entry->d_time;
26}
27#else
28/*
29 * On 32 bit archs store the high 32 bits of time in d_fsdata
30 */
31static void fuse_dentry_settime(struct dentry *entry, u64 time)
32{
33 entry->d_time = time;
34 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
35}
36
37static u64 fuse_dentry_time(struct dentry *entry)
38{
39 return (u64) entry->d_time +
40 ((u64) (unsigned long) entry->d_fsdata << 32);
41}
42#endif
43
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080044/*
45 * FUSE caches dentries and attributes with separate timeout. The
46 * time in jiffies until the dentry/attributes are valid is stored in
47 * dentry->d_time and fuse_inode->i_time respectively.
48 */
49
50/*
51 * Calculate the time in jiffies until a dentry/attributes are valid
52 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070053static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070054{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070055 if (sec || nsec) {
56 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070057 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070058 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070059 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070060}
61
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080062/*
63 * Set dentry and possibly attribute timeouts from the lookup/mk*
64 * replies
65 */
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080066static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
67{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070068 fuse_dentry_settime(entry,
69 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080070 if (entry->d_inode)
71 get_fuse_inode(entry->d_inode)->i_time =
72 time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
73}
74
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080075/*
76 * Mark the attributes as stale, so that at the next call to
77 * ->getattr() they will be fetched from userspace
78 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080079void fuse_invalidate_attr(struct inode *inode)
80{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070081 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080082}
83
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080084/*
85 * Just mark the entry as stale, so that a next attempt to look it up
86 * will result in a new lookup call to userspace
87 *
88 * This is called when a dentry is about to become negative and the
89 * timeout is unknown (unlink, rmdir, rename and in some cases
90 * lookup)
91 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080092static void fuse_invalidate_entry_cache(struct dentry *entry)
93{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070094 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080095}
96
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080097/*
98 * Same as fuse_invalidate_entry_cache(), but also try to remove the
99 * dentry from the hash
100 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800101static void fuse_invalidate_entry(struct dentry *entry)
102{
103 d_invalidate(entry);
104 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800105}
106
Miklos Szeredie5e55582005-09-09 13:10:28 -0700107static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
108 struct dentry *entry,
109 struct fuse_entry_out *outarg)
110{
111 req->in.h.opcode = FUSE_LOOKUP;
112 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700113 req->in.numargs = 1;
114 req->in.args[0].size = entry->d_name.len + 1;
115 req->in.args[0].value = entry->d_name.name;
116 req->out.numargs = 1;
117 req->out.args[0].size = sizeof(struct fuse_entry_out);
118 req->out.args[0].value = outarg;
119}
120
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800121/*
122 * Check whether the dentry is still valid
123 *
124 * If the entry validity timeout has expired and the dentry is
125 * positive, try to redo the lookup. If the lookup results in a
126 * different inode, then let the VFS invalidate the dentry and redo
127 * the lookup once more. If the lookup results in the same inode,
128 * then refresh the attributes, timeouts and mark the dentry valid.
129 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700130static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
131{
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800132 struct inode *inode = entry->d_inode;
133
134 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700135 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700136 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700137 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700138 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800139 struct fuse_conn *fc;
140 struct fuse_req *req;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700141 struct dentry *parent;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800142
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800143 /* Doesn't hurt to "reset" the validity timeout */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800144 fuse_invalidate_entry_cache(entry);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800145
146 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800147 if (!inode)
148 return 0;
149
150 fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700151 req = fuse_get_req(fc);
152 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700153 return 0;
154
Miklos Szeredie956edd2006-10-17 00:10:12 -0700155 parent = dget_parent(entry);
156 fuse_lookup_init(req, parent->d_inode, entry, &outarg);
Miklos Szeredi7c352bd2005-09-09 13:10:39 -0700157 request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700158 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700159 err = req->out.h.error;
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800160 /* Zero nodeid is same as -ENOENT */
161 if (!err && !outarg.nodeid)
162 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700163 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800164 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700165 if (outarg.nodeid != get_node_id(inode)) {
166 fuse_send_forget(fc, req, outarg.nodeid, 1);
167 return 0;
168 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700169 spin_lock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700170 fi->nlookup ++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700171 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700172 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700173 fuse_put_request(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700174 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700175 return 0;
176
177 fuse_change_attributes(inode, &outarg.attr);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800178 fuse_change_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700179 }
180 return 1;
181}
182
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800183static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800184{
185 return !nodeid || nodeid == FUSE_ROOT_ID;
186}
187
Miklos Szeredie5e55582005-09-09 13:10:28 -0700188static struct dentry_operations fuse_dentry_operations = {
189 .d_revalidate = fuse_dentry_revalidate,
190};
191
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800192static int valid_mode(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800193{
194 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
195 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
196}
197
Miklos Szeredid2a85162006-10-17 00:10:11 -0700198/*
199 * Add a directory inode to a dentry, ensuring that no other dentry
200 * refers to this inode. Called with fc->inst_mutex.
201 */
202static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
203{
204 struct dentry *alias = d_find_alias(inode);
205 if (alias) {
206 /* This tries to shrink the subtree below alias */
207 fuse_invalidate_entry(alias);
208 dput(alias);
209 if (!list_empty(&inode->i_dentry))
210 return -EBUSY;
211 }
212 d_add(entry, inode);
213 return 0;
214}
215
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800216static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
217 struct nameidata *nd)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700218{
219 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700220 struct fuse_entry_out outarg;
221 struct inode *inode = NULL;
222 struct fuse_conn *fc = get_fuse_conn(dir);
223 struct fuse_req *req;
224
225 if (entry->d_name.len > FUSE_NAME_MAX)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800226 return ERR_PTR(-ENAMETOOLONG);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700227
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700228 req = fuse_get_req(fc);
229 if (IS_ERR(req))
230 return ERR_PTR(PTR_ERR(req));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700231
232 fuse_lookup_init(req, dir, entry, &outarg);
233 request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700234 err = req->out.h.error;
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800235 /* Zero nodeid is same as -ENOENT, but with valid timeout */
236 if (!err && outarg.nodeid &&
237 (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
Miklos Szerediee4e5272005-09-27 21:45:21 -0700238 err = -EIO;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800239 if (!err && outarg.nodeid) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700240 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700241 &outarg.attr);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700242 if (!inode) {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700243 fuse_send_forget(fc, req, outarg.nodeid, 1);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800244 return ERR_PTR(-ENOMEM);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700245 }
246 }
247 fuse_put_request(fc, req);
248 if (err && err != -ENOENT)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800249 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700250
Miklos Szeredid2a85162006-10-17 00:10:11 -0700251 if (inode && S_ISDIR(inode->i_mode)) {
252 mutex_lock(&fc->inst_mutex);
253 err = fuse_d_add_directory(entry, inode);
254 mutex_unlock(&fc->inst_mutex);
255 if (err) {
256 iput(inode);
257 return ERR_PTR(err);
258 }
259 } else
260 d_add(entry, inode);
261
Miklos Szeredie5e55582005-09-09 13:10:28 -0700262 entry->d_op = &fuse_dentry_operations;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800263 if (!err)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800264 fuse_change_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800265 else
266 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800267 return NULL;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700268}
269
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800270/*
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700271 * Synchronous release for the case when something goes wrong in CREATE_OPEN
272 */
273static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
274 u64 nodeid, int flags)
275{
276 struct fuse_req *req;
277
278 req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
279 req->force = 1;
280 request_send(fc, req);
281 fuse_put_request(fc, req);
282}
283
284/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800285 * Atomic create+open operation
286 *
287 * If the filesystem doesn't support this, then fall back to separate
288 * 'mknod' + 'open' requests.
289 */
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800290static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
291 struct nameidata *nd)
292{
293 int err;
294 struct inode *inode;
295 struct fuse_conn *fc = get_fuse_conn(dir);
296 struct fuse_req *req;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700297 struct fuse_req *forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800298 struct fuse_open_in inarg;
299 struct fuse_open_out outopen;
300 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800301 struct fuse_file *ff;
302 struct file *file;
303 int flags = nd->intent.open.flags - 1;
304
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800305 if (fc->no_create)
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700306 return -ENOSYS;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800307
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700308 forget_req = fuse_get_req(fc);
309 if (IS_ERR(forget_req))
310 return PTR_ERR(forget_req);
311
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700312 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700313 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700314 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700315 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800316
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700317 err = -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800318 ff = fuse_file_alloc();
319 if (!ff)
320 goto out_put_request;
321
322 flags &= ~O_NOCTTY;
323 memset(&inarg, 0, sizeof(inarg));
324 inarg.flags = flags;
325 inarg.mode = mode;
326 req->in.h.opcode = FUSE_CREATE;
327 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800328 req->in.numargs = 2;
329 req->in.args[0].size = sizeof(inarg);
330 req->in.args[0].value = &inarg;
331 req->in.args[1].size = entry->d_name.len + 1;
332 req->in.args[1].value = entry->d_name.name;
333 req->out.numargs = 2;
334 req->out.args[0].size = sizeof(outentry);
335 req->out.args[0].value = &outentry;
336 req->out.args[1].size = sizeof(outopen);
337 req->out.args[1].value = &outopen;
338 request_send(fc, req);
339 err = req->out.h.error;
340 if (err) {
341 if (err == -ENOSYS)
342 fc->no_create = 1;
343 goto out_free_ff;
344 }
345
346 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800347 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800348 goto out_free_ff;
349
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700350 fuse_put_request(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800351 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
352 &outentry.attr);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800353 if (!inode) {
354 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
355 ff->fh = outopen.fh;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700356 fuse_sync_release(fc, ff, outentry.nodeid, flags);
357 fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
358 return -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800359 }
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700360 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800361 d_instantiate(entry, inode);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800362 fuse_change_timeout(entry, &outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800363 file = lookup_instantiate_filp(nd, entry, generic_file_open);
364 if (IS_ERR(file)) {
365 ff->fh = outopen.fh;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700366 fuse_sync_release(fc, ff, outentry.nodeid, flags);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800367 return PTR_ERR(file);
368 }
369 fuse_finish_open(inode, file, ff, &outopen);
370 return 0;
371
372 out_free_ff:
373 fuse_file_free(ff);
374 out_put_request:
375 fuse_put_request(fc, req);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700376 out_put_forget_req:
377 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800378 return err;
379}
380
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800381/*
382 * Code shared between mknod, mkdir, symlink and link
383 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700384static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
385 struct inode *dir, struct dentry *entry,
386 int mode)
387{
388 struct fuse_entry_out outarg;
389 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700390 int err;
391
392 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700393 req->out.numargs = 1;
394 req->out.args[0].size = sizeof(outarg);
395 req->out.args[0].value = &outarg;
396 request_send(fc, req);
397 err = req->out.h.error;
398 if (err) {
399 fuse_put_request(fc, req);
400 return err;
401 }
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800402 err = -EIO;
403 if (invalid_nodeid(outarg.nodeid))
404 goto out_put_request;
405
406 if ((outarg.attr.mode ^ mode) & S_IFMT)
407 goto out_put_request;
408
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700409 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
410 &outarg.attr);
411 if (!inode) {
412 fuse_send_forget(fc, req, outarg.nodeid, 1);
413 return -ENOMEM;
414 }
415 fuse_put_request(fc, req);
416
Miklos Szeredid2a85162006-10-17 00:10:11 -0700417 if (S_ISDIR(inode->i_mode)) {
418 struct dentry *alias;
419 mutex_lock(&fc->inst_mutex);
420 alias = d_find_alias(inode);
421 if (alias) {
422 /* New directory must have moved since mkdir */
423 mutex_unlock(&fc->inst_mutex);
424 dput(alias);
425 iput(inode);
426 return -EBUSY;
427 }
428 d_instantiate(entry, inode);
429 mutex_unlock(&fc->inst_mutex);
430 } else
431 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700432
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800433 fuse_change_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700434 fuse_invalidate_attr(dir);
435 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800436
437 out_put_request:
438 fuse_put_request(fc, req);
439 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700440}
441
442static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
443 dev_t rdev)
444{
445 struct fuse_mknod_in inarg;
446 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700447 struct fuse_req *req = fuse_get_req(fc);
448 if (IS_ERR(req))
449 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700450
451 memset(&inarg, 0, sizeof(inarg));
452 inarg.mode = mode;
453 inarg.rdev = new_encode_dev(rdev);
454 req->in.h.opcode = FUSE_MKNOD;
455 req->in.numargs = 2;
456 req->in.args[0].size = sizeof(inarg);
457 req->in.args[0].value = &inarg;
458 req->in.args[1].size = entry->d_name.len + 1;
459 req->in.args[1].value = entry->d_name.name;
460 return create_new_entry(fc, req, dir, entry, mode);
461}
462
463static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
464 struct nameidata *nd)
465{
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800466 if (nd && (nd->flags & LOOKUP_CREATE)) {
467 int err = fuse_create_open(dir, entry, mode, nd);
468 if (err != -ENOSYS)
469 return err;
470 /* Fall back on mknod */
471 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700472 return fuse_mknod(dir, entry, mode, 0);
473}
474
475static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
476{
477 struct fuse_mkdir_in inarg;
478 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700479 struct fuse_req *req = fuse_get_req(fc);
480 if (IS_ERR(req))
481 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700482
483 memset(&inarg, 0, sizeof(inarg));
484 inarg.mode = mode;
485 req->in.h.opcode = FUSE_MKDIR;
486 req->in.numargs = 2;
487 req->in.args[0].size = sizeof(inarg);
488 req->in.args[0].value = &inarg;
489 req->in.args[1].size = entry->d_name.len + 1;
490 req->in.args[1].value = entry->d_name.name;
491 return create_new_entry(fc, req, dir, entry, S_IFDIR);
492}
493
494static int fuse_symlink(struct inode *dir, struct dentry *entry,
495 const char *link)
496{
497 struct fuse_conn *fc = get_fuse_conn(dir);
498 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700499 struct fuse_req *req = fuse_get_req(fc);
500 if (IS_ERR(req))
501 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700502
503 req->in.h.opcode = FUSE_SYMLINK;
504 req->in.numargs = 2;
505 req->in.args[0].size = entry->d_name.len + 1;
506 req->in.args[0].value = entry->d_name.name;
507 req->in.args[1].size = len;
508 req->in.args[1].value = link;
509 return create_new_entry(fc, req, dir, entry, S_IFLNK);
510}
511
512static int fuse_unlink(struct inode *dir, struct dentry *entry)
513{
514 int err;
515 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700516 struct fuse_req *req = fuse_get_req(fc);
517 if (IS_ERR(req))
518 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700519
520 req->in.h.opcode = FUSE_UNLINK;
521 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700522 req->in.numargs = 1;
523 req->in.args[0].size = entry->d_name.len + 1;
524 req->in.args[0].value = entry->d_name.name;
525 request_send(fc, req);
526 err = req->out.h.error;
527 fuse_put_request(fc, req);
528 if (!err) {
529 struct inode *inode = entry->d_inode;
530
531 /* Set nlink to zero so the inode can be cleared, if
532 the inode does have more links this will be
533 discovered at the next lookup/getattr */
Dave Hansence71ec32006-09-30 23:29:06 -0700534 clear_nlink(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700535 fuse_invalidate_attr(inode);
536 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800537 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700538 } else if (err == -EINTR)
539 fuse_invalidate_entry(entry);
540 return err;
541}
542
543static int fuse_rmdir(struct inode *dir, struct dentry *entry)
544{
545 int err;
546 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700547 struct fuse_req *req = fuse_get_req(fc);
548 if (IS_ERR(req))
549 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700550
551 req->in.h.opcode = FUSE_RMDIR;
552 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700553 req->in.numargs = 1;
554 req->in.args[0].size = entry->d_name.len + 1;
555 req->in.args[0].value = entry->d_name.name;
556 request_send(fc, req);
557 err = req->out.h.error;
558 fuse_put_request(fc, req);
559 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700560 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700561 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800562 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700563 } else if (err == -EINTR)
564 fuse_invalidate_entry(entry);
565 return err;
566}
567
568static int fuse_rename(struct inode *olddir, struct dentry *oldent,
569 struct inode *newdir, struct dentry *newent)
570{
571 int err;
572 struct fuse_rename_in inarg;
573 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700574 struct fuse_req *req = fuse_get_req(fc);
575 if (IS_ERR(req))
576 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700577
578 memset(&inarg, 0, sizeof(inarg));
579 inarg.newdir = get_node_id(newdir);
580 req->in.h.opcode = FUSE_RENAME;
581 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700582 req->in.numargs = 3;
583 req->in.args[0].size = sizeof(inarg);
584 req->in.args[0].value = &inarg;
585 req->in.args[1].size = oldent->d_name.len + 1;
586 req->in.args[1].value = oldent->d_name.name;
587 req->in.args[2].size = newent->d_name.len + 1;
588 req->in.args[2].value = newent->d_name.name;
589 request_send(fc, req);
590 err = req->out.h.error;
591 fuse_put_request(fc, req);
592 if (!err) {
593 fuse_invalidate_attr(olddir);
594 if (olddir != newdir)
595 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800596
597 /* newent will end up negative */
598 if (newent->d_inode)
599 fuse_invalidate_entry_cache(newent);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700600 } else if (err == -EINTR) {
601 /* If request was interrupted, DEITY only knows if the
602 rename actually took place. If the invalidation
603 fails (e.g. some process has CWD under the renamed
604 directory), then there can be inconsistency between
605 the dcache and the real filesystem. Tough luck. */
606 fuse_invalidate_entry(oldent);
607 if (newent->d_inode)
608 fuse_invalidate_entry(newent);
609 }
610
611 return err;
612}
613
614static int fuse_link(struct dentry *entry, struct inode *newdir,
615 struct dentry *newent)
616{
617 int err;
618 struct fuse_link_in inarg;
619 struct inode *inode = entry->d_inode;
620 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700621 struct fuse_req *req = fuse_get_req(fc);
622 if (IS_ERR(req))
623 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700624
625 memset(&inarg, 0, sizeof(inarg));
626 inarg.oldnodeid = get_node_id(inode);
627 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700628 req->in.numargs = 2;
629 req->in.args[0].size = sizeof(inarg);
630 req->in.args[0].value = &inarg;
631 req->in.args[1].size = newent->d_name.len + 1;
632 req->in.args[1].value = newent->d_name.name;
633 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
634 /* Contrary to "normal" filesystems it can happen that link
635 makes two "logical" inodes point to the same "physical"
636 inode. We invalidate the attributes of the old one, so it
637 will reflect changes in the backing inode (link count,
638 etc.)
639 */
640 if (!err || err == -EINTR)
641 fuse_invalidate_attr(inode);
642 return err;
643}
644
Miklos Szeredie5e55582005-09-09 13:10:28 -0700645int fuse_do_getattr(struct inode *inode)
646{
647 int err;
648 struct fuse_attr_out arg;
649 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700650 struct fuse_req *req = fuse_get_req(fc);
651 if (IS_ERR(req))
652 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700653
654 req->in.h.opcode = FUSE_GETATTR;
655 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700656 req->out.numargs = 1;
657 req->out.args[0].size = sizeof(arg);
658 req->out.args[0].value = &arg;
659 request_send(fc, req);
660 err = req->out.h.error;
661 fuse_put_request(fc, req);
662 if (!err) {
663 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
664 make_bad_inode(inode);
665 err = -EIO;
666 } else {
667 struct fuse_inode *fi = get_fuse_inode(inode);
668 fuse_change_attributes(inode, &arg.attr);
669 fi->i_time = time_to_jiffies(arg.attr_valid,
670 arg.attr_valid_nsec);
671 }
672 }
673 return err;
674}
675
Miklos Szeredi87729a52005-09-09 13:10:34 -0700676/*
677 * Calling into a user-controlled filesystem gives the filesystem
678 * daemon ptrace-like capabilities over the requester process. This
679 * means, that the filesystem daemon is able to record the exact
680 * filesystem operations performed, and can also control the behavior
681 * of the requester process in otherwise impossible ways. For example
682 * it can delay the operation for arbitrary length of time allowing
683 * DoS against the requester.
684 *
685 * For this reason only those processes can call into the filesystem,
686 * for which the owner of the mount has ptrace privilege. This
687 * excludes processes started by other users, suid or sgid processes.
688 */
689static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
690{
691 if (fc->flags & FUSE_ALLOW_OTHER)
692 return 1;
693
694 if (task->euid == fc->user_id &&
695 task->suid == fc->user_id &&
696 task->uid == fc->user_id &&
697 task->egid == fc->group_id &&
698 task->sgid == fc->group_id &&
699 task->gid == fc->group_id)
700 return 1;
701
702 return 0;
703}
704
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800705/*
706 * Check whether the inode attributes are still valid
707 *
708 * If the attribute validity timeout has expired, then fetch the fresh
709 * attributes with a 'getattr' request
710 *
711 * I'm not sure why cached attributes are never returned for the root
712 * inode, this is probably being too cautious.
713 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700714static int fuse_revalidate(struct dentry *entry)
715{
716 struct inode *inode = entry->d_inode;
717 struct fuse_inode *fi = get_fuse_inode(inode);
718 struct fuse_conn *fc = get_fuse_conn(inode);
719
Miklos Szeredi87729a52005-09-09 13:10:34 -0700720 if (!fuse_allow_task(fc, current))
721 return -EACCES;
722 if (get_node_id(inode) != FUSE_ROOT_ID &&
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700723 fi->i_time >= get_jiffies_64())
Miklos Szeredie5e55582005-09-09 13:10:28 -0700724 return 0;
725
726 return fuse_do_getattr(inode);
727}
728
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800729static int fuse_access(struct inode *inode, int mask)
730{
731 struct fuse_conn *fc = get_fuse_conn(inode);
732 struct fuse_req *req;
733 struct fuse_access_in inarg;
734 int err;
735
736 if (fc->no_access)
737 return 0;
738
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700739 req = fuse_get_req(fc);
740 if (IS_ERR(req))
741 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800742
743 memset(&inarg, 0, sizeof(inarg));
744 inarg.mask = mask;
745 req->in.h.opcode = FUSE_ACCESS;
746 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800747 req->in.numargs = 1;
748 req->in.args[0].size = sizeof(inarg);
749 req->in.args[0].value = &inarg;
750 request_send(fc, req);
751 err = req->out.h.error;
752 fuse_put_request(fc, req);
753 if (err == -ENOSYS) {
754 fc->no_access = 1;
755 err = 0;
756 }
757 return err;
758}
759
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800760/*
761 * Check permission. The two basic access models of FUSE are:
762 *
763 * 1) Local access checking ('default_permissions' mount option) based
764 * on file mode. This is the plain old disk filesystem permission
765 * modell.
766 *
767 * 2) "Remote" access checking, where server is responsible for
768 * checking permission in each inode operation. An exception to this
769 * is if ->permission() was invoked from sys_access() in which case an
770 * access request is sent. Execute permission is still checked
771 * locally based on file mode.
772 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700773static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
774{
775 struct fuse_conn *fc = get_fuse_conn(inode);
776
Miklos Szeredi87729a52005-09-09 13:10:34 -0700777 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700778 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700779 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
780 int err = generic_permission(inode, mask, NULL);
781
782 /* If permission is denied, try to refresh file
783 attributes. This is also needed, because the root
784 node will at first have no permissions */
785 if (err == -EACCES) {
786 err = fuse_do_getattr(inode);
787 if (!err)
788 err = generic_permission(inode, mask, NULL);
789 }
790
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800791 /* Note: the opposite of the above test does not
792 exist. So if permissions are revoked this won't be
793 noticed immediately, only after the attribute
794 timeout has expired */
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700795
796 return err;
797 } else {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700798 int mode = inode->i_mode;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700799 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
800 return -EACCES;
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800801
Miklos Szeredi650a8982006-09-29 01:59:35 -0700802 if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800803 return fuse_access(inode, mask);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700804 return 0;
805 }
806}
807
808static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
809 void *dstbuf, filldir_t filldir)
810{
811 while (nbytes >= FUSE_NAME_OFFSET) {
812 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
813 size_t reclen = FUSE_DIRENT_SIZE(dirent);
814 int over;
815 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
816 return -EIO;
817 if (reclen > nbytes)
818 break;
819
820 over = filldir(dstbuf, dirent->name, dirent->namelen,
821 file->f_pos, dirent->ino, dirent->type);
822 if (over)
823 break;
824
825 buf += reclen;
826 nbytes -= reclen;
827 file->f_pos = dirent->off;
828 }
829
830 return 0;
831}
832
Miklos Szeredie5e55582005-09-09 13:10:28 -0700833static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
834{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700835 int err;
836 size_t nbytes;
837 struct page *page;
838 struct inode *inode = file->f_dentry->d_inode;
839 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -0800840 struct fuse_req *req;
841
842 if (is_bad_inode(inode))
843 return -EIO;
844
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700845 req = fuse_get_req(fc);
846 if (IS_ERR(req))
847 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700848
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700849 page = alloc_page(GFP_KERNEL);
850 if (!page) {
851 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700852 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700853 }
854 req->num_pages = 1;
855 req->pages[0] = page;
Miklos Szeredi361b1eb52006-01-16 22:14:45 -0800856 fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
857 request_send(fc, req);
858 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700859 err = req->out.h.error;
860 fuse_put_request(fc, req);
861 if (!err)
862 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
863 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700864
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700865 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -0700866 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700867 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700868}
869
870static char *read_link(struct dentry *dentry)
871{
872 struct inode *inode = dentry->d_inode;
873 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700874 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700875 char *link;
876
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700877 if (IS_ERR(req))
878 return ERR_PTR(PTR_ERR(req));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700879
880 link = (char *) __get_free_page(GFP_KERNEL);
881 if (!link) {
882 link = ERR_PTR(-ENOMEM);
883 goto out;
884 }
885 req->in.h.opcode = FUSE_READLINK;
886 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700887 req->out.argvar = 1;
888 req->out.numargs = 1;
889 req->out.args[0].size = PAGE_SIZE - 1;
890 req->out.args[0].value = link;
891 request_send(fc, req);
892 if (req->out.h.error) {
893 free_page((unsigned long) link);
894 link = ERR_PTR(req->out.h.error);
895 } else
896 link[req->out.args[0].size] = '\0';
897 out:
898 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -0700899 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700900 return link;
901}
902
903static void free_link(char *link)
904{
905 if (!IS_ERR(link))
906 free_page((unsigned long) link);
907}
908
909static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
910{
911 nd_set_link(nd, read_link(dentry));
912 return NULL;
913}
914
915static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
916{
917 free_link(nd_get_link(nd));
918}
919
920static int fuse_dir_open(struct inode *inode, struct file *file)
921{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700922 return fuse_open_common(inode, file, 1);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700923}
924
925static int fuse_dir_release(struct inode *inode, struct file *file)
926{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700927 return fuse_release_common(inode, file, 1);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700928}
929
Miklos Szeredi82547982005-09-09 13:10:38 -0700930static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
931{
932 /* nfsd can call this with no file */
933 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
934}
935
Miklos Szeredibefc6492005-11-07 00:59:52 -0800936static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700937{
938 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700939
940 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800941 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700942 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800943 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700944 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800945 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700946 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800947 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700948 /* You can only _set_ these together (they may change by themselves) */
949 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredibefc6492005-11-07 00:59:52 -0800950 arg->valid |= FATTR_ATIME | FATTR_MTIME;
951 arg->atime = iattr->ia_atime.tv_sec;
952 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700953 }
Miklos Szeredibefc6492005-11-07 00:59:52 -0800954 if (ivalid & ATTR_FILE) {
955 struct fuse_file *ff = iattr->ia_file->private_data;
956 arg->valid |= FATTR_FH;
957 arg->fh = ff->fh;
958 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700959}
960
Miklos Szeredi9ffbb912006-10-17 00:10:06 -0700961static void fuse_vmtruncate(struct inode *inode, loff_t offset)
962{
963 struct fuse_conn *fc = get_fuse_conn(inode);
964 int need_trunc;
965
966 spin_lock(&fc->lock);
967 need_trunc = inode->i_size > offset;
968 i_size_write(inode, offset);
969 spin_unlock(&fc->lock);
970
971 if (need_trunc) {
972 struct address_space *mapping = inode->i_mapping;
973 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
974 truncate_inode_pages(mapping, offset);
975 }
976}
977
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800978/*
979 * Set attributes, and at the same time refresh them.
980 *
981 * Truncation is slightly complicated, because the 'truncate' request
982 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -0700983 * vmtruncate() doesn't allow for this case, so do the rlimit checking
984 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800985 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700986static int fuse_setattr(struct dentry *entry, struct iattr *attr)
987{
988 struct inode *inode = entry->d_inode;
989 struct fuse_conn *fc = get_fuse_conn(inode);
990 struct fuse_inode *fi = get_fuse_inode(inode);
991 struct fuse_req *req;
992 struct fuse_setattr_in inarg;
993 struct fuse_attr_out outarg;
994 int err;
995 int is_truncate = 0;
996
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700997 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
998 err = inode_change_ok(inode, attr);
999 if (err)
1000 return err;
1001 }
1002
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001003 if (attr->ia_valid & ATTR_SIZE) {
1004 unsigned long limit;
1005 is_truncate = 1;
1006 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1007 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
1008 send_sig(SIGXFSZ, current, 0);
1009 return -EFBIG;
1010 }
1011 }
1012
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001013 req = fuse_get_req(fc);
1014 if (IS_ERR(req))
1015 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001016
1017 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001018 iattr_to_fattr(attr, &inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001019 req->in.h.opcode = FUSE_SETATTR;
1020 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001021 req->in.numargs = 1;
1022 req->in.args[0].size = sizeof(inarg);
1023 req->in.args[0].value = &inarg;
1024 req->out.numargs = 1;
1025 req->out.args[0].size = sizeof(outarg);
1026 req->out.args[0].value = &outarg;
1027 request_send(fc, req);
1028 err = req->out.h.error;
1029 fuse_put_request(fc, req);
1030 if (!err) {
1031 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1032 make_bad_inode(inode);
1033 err = -EIO;
1034 } else {
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001035 if (is_truncate)
1036 fuse_vmtruncate(inode, outarg.attr.size);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001037 fuse_change_attributes(inode, &outarg.attr);
1038 fi->i_time = time_to_jiffies(outarg.attr_valid,
1039 outarg.attr_valid_nsec);
1040 }
1041 } else if (err == -EINTR)
1042 fuse_invalidate_attr(inode);
1043
1044 return err;
1045}
1046
Miklos Szeredie5e55582005-09-09 13:10:28 -07001047static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1048 struct kstat *stat)
1049{
1050 struct inode *inode = entry->d_inode;
1051 int err = fuse_revalidate(entry);
1052 if (!err)
1053 generic_fillattr(inode, stat);
1054
1055 return err;
1056}
1057
Miklos Szeredi92a87802005-09-09 13:10:31 -07001058static int fuse_setxattr(struct dentry *entry, const char *name,
1059 const void *value, size_t size, int flags)
1060{
1061 struct inode *inode = entry->d_inode;
1062 struct fuse_conn *fc = get_fuse_conn(inode);
1063 struct fuse_req *req;
1064 struct fuse_setxattr_in inarg;
1065 int err;
1066
Miklos Szeredi92a87802005-09-09 13:10:31 -07001067 if (fc->no_setxattr)
1068 return -EOPNOTSUPP;
1069
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001070 req = fuse_get_req(fc);
1071 if (IS_ERR(req))
1072 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001073
1074 memset(&inarg, 0, sizeof(inarg));
1075 inarg.size = size;
1076 inarg.flags = flags;
1077 req->in.h.opcode = FUSE_SETXATTR;
1078 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001079 req->in.numargs = 3;
1080 req->in.args[0].size = sizeof(inarg);
1081 req->in.args[0].value = &inarg;
1082 req->in.args[1].size = strlen(name) + 1;
1083 req->in.args[1].value = name;
1084 req->in.args[2].size = size;
1085 req->in.args[2].value = value;
1086 request_send(fc, req);
1087 err = req->out.h.error;
1088 fuse_put_request(fc, req);
1089 if (err == -ENOSYS) {
1090 fc->no_setxattr = 1;
1091 err = -EOPNOTSUPP;
1092 }
1093 return err;
1094}
1095
1096static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1097 void *value, size_t size)
1098{
1099 struct inode *inode = entry->d_inode;
1100 struct fuse_conn *fc = get_fuse_conn(inode);
1101 struct fuse_req *req;
1102 struct fuse_getxattr_in inarg;
1103 struct fuse_getxattr_out outarg;
1104 ssize_t ret;
1105
1106 if (fc->no_getxattr)
1107 return -EOPNOTSUPP;
1108
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001109 req = fuse_get_req(fc);
1110 if (IS_ERR(req))
1111 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001112
1113 memset(&inarg, 0, sizeof(inarg));
1114 inarg.size = size;
1115 req->in.h.opcode = FUSE_GETXATTR;
1116 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001117 req->in.numargs = 2;
1118 req->in.args[0].size = sizeof(inarg);
1119 req->in.args[0].value = &inarg;
1120 req->in.args[1].size = strlen(name) + 1;
1121 req->in.args[1].value = name;
1122 /* This is really two different operations rolled into one */
1123 req->out.numargs = 1;
1124 if (size) {
1125 req->out.argvar = 1;
1126 req->out.args[0].size = size;
1127 req->out.args[0].value = value;
1128 } else {
1129 req->out.args[0].size = sizeof(outarg);
1130 req->out.args[0].value = &outarg;
1131 }
1132 request_send(fc, req);
1133 ret = req->out.h.error;
1134 if (!ret)
1135 ret = size ? req->out.args[0].size : outarg.size;
1136 else {
1137 if (ret == -ENOSYS) {
1138 fc->no_getxattr = 1;
1139 ret = -EOPNOTSUPP;
1140 }
1141 }
1142 fuse_put_request(fc, req);
1143 return ret;
1144}
1145
1146static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1147{
1148 struct inode *inode = entry->d_inode;
1149 struct fuse_conn *fc = get_fuse_conn(inode);
1150 struct fuse_req *req;
1151 struct fuse_getxattr_in inarg;
1152 struct fuse_getxattr_out outarg;
1153 ssize_t ret;
1154
1155 if (fc->no_listxattr)
1156 return -EOPNOTSUPP;
1157
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001158 req = fuse_get_req(fc);
1159 if (IS_ERR(req))
1160 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001161
1162 memset(&inarg, 0, sizeof(inarg));
1163 inarg.size = size;
1164 req->in.h.opcode = FUSE_LISTXATTR;
1165 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001166 req->in.numargs = 1;
1167 req->in.args[0].size = sizeof(inarg);
1168 req->in.args[0].value = &inarg;
1169 /* This is really two different operations rolled into one */
1170 req->out.numargs = 1;
1171 if (size) {
1172 req->out.argvar = 1;
1173 req->out.args[0].size = size;
1174 req->out.args[0].value = list;
1175 } else {
1176 req->out.args[0].size = sizeof(outarg);
1177 req->out.args[0].value = &outarg;
1178 }
1179 request_send(fc, req);
1180 ret = req->out.h.error;
1181 if (!ret)
1182 ret = size ? req->out.args[0].size : outarg.size;
1183 else {
1184 if (ret == -ENOSYS) {
1185 fc->no_listxattr = 1;
1186 ret = -EOPNOTSUPP;
1187 }
1188 }
1189 fuse_put_request(fc, req);
1190 return ret;
1191}
1192
1193static int fuse_removexattr(struct dentry *entry, const char *name)
1194{
1195 struct inode *inode = entry->d_inode;
1196 struct fuse_conn *fc = get_fuse_conn(inode);
1197 struct fuse_req *req;
1198 int err;
1199
1200 if (fc->no_removexattr)
1201 return -EOPNOTSUPP;
1202
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001203 req = fuse_get_req(fc);
1204 if (IS_ERR(req))
1205 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001206
1207 req->in.h.opcode = FUSE_REMOVEXATTR;
1208 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001209 req->in.numargs = 1;
1210 req->in.args[0].size = strlen(name) + 1;
1211 req->in.args[0].value = name;
1212 request_send(fc, req);
1213 err = req->out.h.error;
1214 fuse_put_request(fc, req);
1215 if (err == -ENOSYS) {
1216 fc->no_removexattr = 1;
1217 err = -EOPNOTSUPP;
1218 }
1219 return err;
1220}
1221
Miklos Szeredie5e55582005-09-09 13:10:28 -07001222static struct inode_operations fuse_dir_inode_operations = {
1223 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001224 .mkdir = fuse_mkdir,
1225 .symlink = fuse_symlink,
1226 .unlink = fuse_unlink,
1227 .rmdir = fuse_rmdir,
1228 .rename = fuse_rename,
1229 .link = fuse_link,
1230 .setattr = fuse_setattr,
1231 .create = fuse_create,
1232 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001233 .permission = fuse_permission,
1234 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001235 .setxattr = fuse_setxattr,
1236 .getxattr = fuse_getxattr,
1237 .listxattr = fuse_listxattr,
1238 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001239};
1240
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001241static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001242 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001243 .read = generic_read_dir,
1244 .readdir = fuse_readdir,
1245 .open = fuse_dir_open,
1246 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001247 .fsync = fuse_dir_fsync,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001248};
1249
1250static struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001251 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001252 .permission = fuse_permission,
1253 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001254 .setxattr = fuse_setxattr,
1255 .getxattr = fuse_getxattr,
1256 .listxattr = fuse_listxattr,
1257 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001258};
1259
1260static struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001261 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001262 .follow_link = fuse_follow_link,
1263 .put_link = fuse_put_link,
1264 .readlink = generic_readlink,
1265 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001266 .setxattr = fuse_setxattr,
1267 .getxattr = fuse_getxattr,
1268 .listxattr = fuse_listxattr,
1269 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001270};
1271
1272void fuse_init_common(struct inode *inode)
1273{
1274 inode->i_op = &fuse_common_inode_operations;
1275}
1276
1277void fuse_init_dir(struct inode *inode)
1278{
1279 inode->i_op = &fuse_dir_inode_operations;
1280 inode->i_fop = &fuse_dir_operations;
1281}
1282
1283void fuse_init_symlink(struct inode *inode)
1284{
1285 inode->i_op = &fuse_symlink_inode_operations;
1286}