blob: 9d0ef5e18740cb49493b3524bfdc630494fbf509 [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;
141
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800142 /* Doesn't hurt to "reset" the validity timeout */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800143 fuse_invalidate_entry_cache(entry);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800144
145 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800146 if (!inode)
147 return 0;
148
149 fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700150 req = fuse_get_req(fc);
151 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700152 return 0;
153
154 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
Miklos Szeredi7c352bd2005-09-09 13:10:39 -0700155 request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700156 err = req->out.h.error;
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800157 /* Zero nodeid is same as -ENOENT */
158 if (!err && !outarg.nodeid)
159 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700160 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800161 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700162 if (outarg.nodeid != get_node_id(inode)) {
163 fuse_send_forget(fc, req, outarg.nodeid, 1);
164 return 0;
165 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700166 spin_lock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700167 fi->nlookup ++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700168 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700169 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700170 fuse_put_request(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700171 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700172 return 0;
173
174 fuse_change_attributes(inode, &outarg.attr);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800175 fuse_change_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700176 }
177 return 1;
178}
179
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800180static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800181{
182 return !nodeid || nodeid == FUSE_ROOT_ID;
183}
184
Miklos Szeredie5e55582005-09-09 13:10:28 -0700185static struct dentry_operations fuse_dentry_operations = {
186 .d_revalidate = fuse_dentry_revalidate,
187};
188
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800189static int valid_mode(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800190{
191 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
192 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
193}
194
Miklos Szeredid2a85162006-10-17 00:10:11 -0700195/*
196 * Add a directory inode to a dentry, ensuring that no other dentry
197 * refers to this inode. Called with fc->inst_mutex.
198 */
199static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
200{
201 struct dentry *alias = d_find_alias(inode);
202 if (alias) {
203 /* This tries to shrink the subtree below alias */
204 fuse_invalidate_entry(alias);
205 dput(alias);
206 if (!list_empty(&inode->i_dentry))
207 return -EBUSY;
208 }
209 d_add(entry, inode);
210 return 0;
211}
212
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800213static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
214 struct nameidata *nd)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700215{
216 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700217 struct fuse_entry_out outarg;
218 struct inode *inode = NULL;
219 struct fuse_conn *fc = get_fuse_conn(dir);
220 struct fuse_req *req;
221
222 if (entry->d_name.len > FUSE_NAME_MAX)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800223 return ERR_PTR(-ENAMETOOLONG);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700224
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700225 req = fuse_get_req(fc);
226 if (IS_ERR(req))
227 return ERR_PTR(PTR_ERR(req));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700228
229 fuse_lookup_init(req, dir, entry, &outarg);
230 request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700231 err = req->out.h.error;
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800232 /* Zero nodeid is same as -ENOENT, but with valid timeout */
233 if (!err && outarg.nodeid &&
234 (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
Miklos Szerediee4e5272005-09-27 21:45:21 -0700235 err = -EIO;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800236 if (!err && outarg.nodeid) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700237 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700238 &outarg.attr);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700239 if (!inode) {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700240 fuse_send_forget(fc, req, outarg.nodeid, 1);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800241 return ERR_PTR(-ENOMEM);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700242 }
243 }
244 fuse_put_request(fc, req);
245 if (err && err != -ENOENT)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800246 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700247
Miklos Szeredid2a85162006-10-17 00:10:11 -0700248 if (inode && S_ISDIR(inode->i_mode)) {
249 mutex_lock(&fc->inst_mutex);
250 err = fuse_d_add_directory(entry, inode);
251 mutex_unlock(&fc->inst_mutex);
252 if (err) {
253 iput(inode);
254 return ERR_PTR(err);
255 }
256 } else
257 d_add(entry, inode);
258
Miklos Szeredie5e55582005-09-09 13:10:28 -0700259 entry->d_op = &fuse_dentry_operations;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800260 if (!err)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800261 fuse_change_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800262 else
263 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800264 return NULL;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700265}
266
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800267/*
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700268 * Synchronous release for the case when something goes wrong in CREATE_OPEN
269 */
270static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
271 u64 nodeid, int flags)
272{
273 struct fuse_req *req;
274
275 req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
276 req->force = 1;
277 request_send(fc, req);
278 fuse_put_request(fc, req);
279}
280
281/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800282 * Atomic create+open operation
283 *
284 * If the filesystem doesn't support this, then fall back to separate
285 * 'mknod' + 'open' requests.
286 */
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800287static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
288 struct nameidata *nd)
289{
290 int err;
291 struct inode *inode;
292 struct fuse_conn *fc = get_fuse_conn(dir);
293 struct fuse_req *req;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700294 struct fuse_req *forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800295 struct fuse_open_in inarg;
296 struct fuse_open_out outopen;
297 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800298 struct fuse_file *ff;
299 struct file *file;
300 int flags = nd->intent.open.flags - 1;
301
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800302 if (fc->no_create)
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700303 return -ENOSYS;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800304
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700305 forget_req = fuse_get_req(fc);
306 if (IS_ERR(forget_req))
307 return PTR_ERR(forget_req);
308
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700309 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700310 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700311 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700312 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800313
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700314 err = -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800315 ff = fuse_file_alloc();
316 if (!ff)
317 goto out_put_request;
318
319 flags &= ~O_NOCTTY;
320 memset(&inarg, 0, sizeof(inarg));
321 inarg.flags = flags;
322 inarg.mode = mode;
323 req->in.h.opcode = FUSE_CREATE;
324 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800325 req->in.numargs = 2;
326 req->in.args[0].size = sizeof(inarg);
327 req->in.args[0].value = &inarg;
328 req->in.args[1].size = entry->d_name.len + 1;
329 req->in.args[1].value = entry->d_name.name;
330 req->out.numargs = 2;
331 req->out.args[0].size = sizeof(outentry);
332 req->out.args[0].value = &outentry;
333 req->out.args[1].size = sizeof(outopen);
334 req->out.args[1].value = &outopen;
335 request_send(fc, req);
336 err = req->out.h.error;
337 if (err) {
338 if (err == -ENOSYS)
339 fc->no_create = 1;
340 goto out_free_ff;
341 }
342
343 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800344 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800345 goto out_free_ff;
346
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700347 fuse_put_request(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800348 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
349 &outentry.attr);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800350 if (!inode) {
351 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
352 ff->fh = outopen.fh;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700353 fuse_sync_release(fc, ff, outentry.nodeid, flags);
354 fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
355 return -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800356 }
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700357 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800358 d_instantiate(entry, inode);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800359 fuse_change_timeout(entry, &outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800360 file = lookup_instantiate_filp(nd, entry, generic_file_open);
361 if (IS_ERR(file)) {
362 ff->fh = outopen.fh;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700363 fuse_sync_release(fc, ff, outentry.nodeid, flags);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800364 return PTR_ERR(file);
365 }
366 fuse_finish_open(inode, file, ff, &outopen);
367 return 0;
368
369 out_free_ff:
370 fuse_file_free(ff);
371 out_put_request:
372 fuse_put_request(fc, req);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700373 out_put_forget_req:
374 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800375 return err;
376}
377
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800378/*
379 * Code shared between mknod, mkdir, symlink and link
380 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700381static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
382 struct inode *dir, struct dentry *entry,
383 int mode)
384{
385 struct fuse_entry_out outarg;
386 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700387 int err;
388
389 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700390 req->out.numargs = 1;
391 req->out.args[0].size = sizeof(outarg);
392 req->out.args[0].value = &outarg;
393 request_send(fc, req);
394 err = req->out.h.error;
395 if (err) {
396 fuse_put_request(fc, req);
397 return err;
398 }
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800399 err = -EIO;
400 if (invalid_nodeid(outarg.nodeid))
401 goto out_put_request;
402
403 if ((outarg.attr.mode ^ mode) & S_IFMT)
404 goto out_put_request;
405
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700406 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
407 &outarg.attr);
408 if (!inode) {
409 fuse_send_forget(fc, req, outarg.nodeid, 1);
410 return -ENOMEM;
411 }
412 fuse_put_request(fc, req);
413
Miklos Szeredid2a85162006-10-17 00:10:11 -0700414 if (S_ISDIR(inode->i_mode)) {
415 struct dentry *alias;
416 mutex_lock(&fc->inst_mutex);
417 alias = d_find_alias(inode);
418 if (alias) {
419 /* New directory must have moved since mkdir */
420 mutex_unlock(&fc->inst_mutex);
421 dput(alias);
422 iput(inode);
423 return -EBUSY;
424 }
425 d_instantiate(entry, inode);
426 mutex_unlock(&fc->inst_mutex);
427 } else
428 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700429
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800430 fuse_change_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700431 fuse_invalidate_attr(dir);
432 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800433
434 out_put_request:
435 fuse_put_request(fc, req);
436 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700437}
438
439static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
440 dev_t rdev)
441{
442 struct fuse_mknod_in inarg;
443 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700444 struct fuse_req *req = fuse_get_req(fc);
445 if (IS_ERR(req))
446 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700447
448 memset(&inarg, 0, sizeof(inarg));
449 inarg.mode = mode;
450 inarg.rdev = new_encode_dev(rdev);
451 req->in.h.opcode = FUSE_MKNOD;
452 req->in.numargs = 2;
453 req->in.args[0].size = sizeof(inarg);
454 req->in.args[0].value = &inarg;
455 req->in.args[1].size = entry->d_name.len + 1;
456 req->in.args[1].value = entry->d_name.name;
457 return create_new_entry(fc, req, dir, entry, mode);
458}
459
460static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
461 struct nameidata *nd)
462{
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800463 if (nd && (nd->flags & LOOKUP_CREATE)) {
464 int err = fuse_create_open(dir, entry, mode, nd);
465 if (err != -ENOSYS)
466 return err;
467 /* Fall back on mknod */
468 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700469 return fuse_mknod(dir, entry, mode, 0);
470}
471
472static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
473{
474 struct fuse_mkdir_in inarg;
475 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700476 struct fuse_req *req = fuse_get_req(fc);
477 if (IS_ERR(req))
478 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700479
480 memset(&inarg, 0, sizeof(inarg));
481 inarg.mode = mode;
482 req->in.h.opcode = FUSE_MKDIR;
483 req->in.numargs = 2;
484 req->in.args[0].size = sizeof(inarg);
485 req->in.args[0].value = &inarg;
486 req->in.args[1].size = entry->d_name.len + 1;
487 req->in.args[1].value = entry->d_name.name;
488 return create_new_entry(fc, req, dir, entry, S_IFDIR);
489}
490
491static int fuse_symlink(struct inode *dir, struct dentry *entry,
492 const char *link)
493{
494 struct fuse_conn *fc = get_fuse_conn(dir);
495 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700496 struct fuse_req *req = fuse_get_req(fc);
497 if (IS_ERR(req))
498 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700499
500 req->in.h.opcode = FUSE_SYMLINK;
501 req->in.numargs = 2;
502 req->in.args[0].size = entry->d_name.len + 1;
503 req->in.args[0].value = entry->d_name.name;
504 req->in.args[1].size = len;
505 req->in.args[1].value = link;
506 return create_new_entry(fc, req, dir, entry, S_IFLNK);
507}
508
509static int fuse_unlink(struct inode *dir, struct dentry *entry)
510{
511 int err;
512 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700513 struct fuse_req *req = fuse_get_req(fc);
514 if (IS_ERR(req))
515 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700516
517 req->in.h.opcode = FUSE_UNLINK;
518 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700519 req->in.numargs = 1;
520 req->in.args[0].size = entry->d_name.len + 1;
521 req->in.args[0].value = entry->d_name.name;
522 request_send(fc, req);
523 err = req->out.h.error;
524 fuse_put_request(fc, req);
525 if (!err) {
526 struct inode *inode = entry->d_inode;
527
528 /* Set nlink to zero so the inode can be cleared, if
529 the inode does have more links this will be
530 discovered at the next lookup/getattr */
Dave Hansence71ec32006-09-30 23:29:06 -0700531 clear_nlink(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700532 fuse_invalidate_attr(inode);
533 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800534 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700535 } else if (err == -EINTR)
536 fuse_invalidate_entry(entry);
537 return err;
538}
539
540static int fuse_rmdir(struct inode *dir, struct dentry *entry)
541{
542 int err;
543 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700544 struct fuse_req *req = fuse_get_req(fc);
545 if (IS_ERR(req))
546 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700547
548 req->in.h.opcode = FUSE_RMDIR;
549 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700550 req->in.numargs = 1;
551 req->in.args[0].size = entry->d_name.len + 1;
552 req->in.args[0].value = entry->d_name.name;
553 request_send(fc, req);
554 err = req->out.h.error;
555 fuse_put_request(fc, req);
556 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700557 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700558 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800559 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700560 } else if (err == -EINTR)
561 fuse_invalidate_entry(entry);
562 return err;
563}
564
565static int fuse_rename(struct inode *olddir, struct dentry *oldent,
566 struct inode *newdir, struct dentry *newent)
567{
568 int err;
569 struct fuse_rename_in inarg;
570 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700571 struct fuse_req *req = fuse_get_req(fc);
572 if (IS_ERR(req))
573 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700574
575 memset(&inarg, 0, sizeof(inarg));
576 inarg.newdir = get_node_id(newdir);
577 req->in.h.opcode = FUSE_RENAME;
578 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700579 req->in.numargs = 3;
580 req->in.args[0].size = sizeof(inarg);
581 req->in.args[0].value = &inarg;
582 req->in.args[1].size = oldent->d_name.len + 1;
583 req->in.args[1].value = oldent->d_name.name;
584 req->in.args[2].size = newent->d_name.len + 1;
585 req->in.args[2].value = newent->d_name.name;
586 request_send(fc, req);
587 err = req->out.h.error;
588 fuse_put_request(fc, req);
589 if (!err) {
590 fuse_invalidate_attr(olddir);
591 if (olddir != newdir)
592 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800593
594 /* newent will end up negative */
595 if (newent->d_inode)
596 fuse_invalidate_entry_cache(newent);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700597 } else if (err == -EINTR) {
598 /* If request was interrupted, DEITY only knows if the
599 rename actually took place. If the invalidation
600 fails (e.g. some process has CWD under the renamed
601 directory), then there can be inconsistency between
602 the dcache and the real filesystem. Tough luck. */
603 fuse_invalidate_entry(oldent);
604 if (newent->d_inode)
605 fuse_invalidate_entry(newent);
606 }
607
608 return err;
609}
610
611static int fuse_link(struct dentry *entry, struct inode *newdir,
612 struct dentry *newent)
613{
614 int err;
615 struct fuse_link_in inarg;
616 struct inode *inode = entry->d_inode;
617 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700618 struct fuse_req *req = fuse_get_req(fc);
619 if (IS_ERR(req))
620 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700621
622 memset(&inarg, 0, sizeof(inarg));
623 inarg.oldnodeid = get_node_id(inode);
624 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700625 req->in.numargs = 2;
626 req->in.args[0].size = sizeof(inarg);
627 req->in.args[0].value = &inarg;
628 req->in.args[1].size = newent->d_name.len + 1;
629 req->in.args[1].value = newent->d_name.name;
630 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
631 /* Contrary to "normal" filesystems it can happen that link
632 makes two "logical" inodes point to the same "physical"
633 inode. We invalidate the attributes of the old one, so it
634 will reflect changes in the backing inode (link count,
635 etc.)
636 */
637 if (!err || err == -EINTR)
638 fuse_invalidate_attr(inode);
639 return err;
640}
641
Miklos Szeredie5e55582005-09-09 13:10:28 -0700642int fuse_do_getattr(struct inode *inode)
643{
644 int err;
645 struct fuse_attr_out arg;
646 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700647 struct fuse_req *req = fuse_get_req(fc);
648 if (IS_ERR(req))
649 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700650
651 req->in.h.opcode = FUSE_GETATTR;
652 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700653 req->out.numargs = 1;
654 req->out.args[0].size = sizeof(arg);
655 req->out.args[0].value = &arg;
656 request_send(fc, req);
657 err = req->out.h.error;
658 fuse_put_request(fc, req);
659 if (!err) {
660 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
661 make_bad_inode(inode);
662 err = -EIO;
663 } else {
664 struct fuse_inode *fi = get_fuse_inode(inode);
665 fuse_change_attributes(inode, &arg.attr);
666 fi->i_time = time_to_jiffies(arg.attr_valid,
667 arg.attr_valid_nsec);
668 }
669 }
670 return err;
671}
672
Miklos Szeredi87729a52005-09-09 13:10:34 -0700673/*
674 * Calling into a user-controlled filesystem gives the filesystem
675 * daemon ptrace-like capabilities over the requester process. This
676 * means, that the filesystem daemon is able to record the exact
677 * filesystem operations performed, and can also control the behavior
678 * of the requester process in otherwise impossible ways. For example
679 * it can delay the operation for arbitrary length of time allowing
680 * DoS against the requester.
681 *
682 * For this reason only those processes can call into the filesystem,
683 * for which the owner of the mount has ptrace privilege. This
684 * excludes processes started by other users, suid or sgid processes.
685 */
686static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
687{
688 if (fc->flags & FUSE_ALLOW_OTHER)
689 return 1;
690
691 if (task->euid == fc->user_id &&
692 task->suid == fc->user_id &&
693 task->uid == fc->user_id &&
694 task->egid == fc->group_id &&
695 task->sgid == fc->group_id &&
696 task->gid == fc->group_id)
697 return 1;
698
699 return 0;
700}
701
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800702/*
703 * Check whether the inode attributes are still valid
704 *
705 * If the attribute validity timeout has expired, then fetch the fresh
706 * attributes with a 'getattr' request
707 *
708 * I'm not sure why cached attributes are never returned for the root
709 * inode, this is probably being too cautious.
710 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700711static int fuse_revalidate(struct dentry *entry)
712{
713 struct inode *inode = entry->d_inode;
714 struct fuse_inode *fi = get_fuse_inode(inode);
715 struct fuse_conn *fc = get_fuse_conn(inode);
716
Miklos Szeredi87729a52005-09-09 13:10:34 -0700717 if (!fuse_allow_task(fc, current))
718 return -EACCES;
719 if (get_node_id(inode) != FUSE_ROOT_ID &&
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700720 fi->i_time >= get_jiffies_64())
Miklos Szeredie5e55582005-09-09 13:10:28 -0700721 return 0;
722
723 return fuse_do_getattr(inode);
724}
725
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800726static int fuse_access(struct inode *inode, int mask)
727{
728 struct fuse_conn *fc = get_fuse_conn(inode);
729 struct fuse_req *req;
730 struct fuse_access_in inarg;
731 int err;
732
733 if (fc->no_access)
734 return 0;
735
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700736 req = fuse_get_req(fc);
737 if (IS_ERR(req))
738 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800739
740 memset(&inarg, 0, sizeof(inarg));
741 inarg.mask = mask;
742 req->in.h.opcode = FUSE_ACCESS;
743 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800744 req->in.numargs = 1;
745 req->in.args[0].size = sizeof(inarg);
746 req->in.args[0].value = &inarg;
747 request_send(fc, req);
748 err = req->out.h.error;
749 fuse_put_request(fc, req);
750 if (err == -ENOSYS) {
751 fc->no_access = 1;
752 err = 0;
753 }
754 return err;
755}
756
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800757/*
758 * Check permission. The two basic access models of FUSE are:
759 *
760 * 1) Local access checking ('default_permissions' mount option) based
761 * on file mode. This is the plain old disk filesystem permission
762 * modell.
763 *
764 * 2) "Remote" access checking, where server is responsible for
765 * checking permission in each inode operation. An exception to this
766 * is if ->permission() was invoked from sys_access() in which case an
767 * access request is sent. Execute permission is still checked
768 * locally based on file mode.
769 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700770static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
771{
772 struct fuse_conn *fc = get_fuse_conn(inode);
773
Miklos Szeredi87729a52005-09-09 13:10:34 -0700774 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700775 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700776 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
777 int err = generic_permission(inode, mask, NULL);
778
779 /* If permission is denied, try to refresh file
780 attributes. This is also needed, because the root
781 node will at first have no permissions */
782 if (err == -EACCES) {
783 err = fuse_do_getattr(inode);
784 if (!err)
785 err = generic_permission(inode, mask, NULL);
786 }
787
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800788 /* Note: the opposite of the above test does not
789 exist. So if permissions are revoked this won't be
790 noticed immediately, only after the attribute
791 timeout has expired */
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700792
793 return err;
794 } else {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700795 int mode = inode->i_mode;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700796 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
797 return -EACCES;
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800798
Miklos Szeredi650a8982006-09-29 01:59:35 -0700799 if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800800 return fuse_access(inode, mask);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700801 return 0;
802 }
803}
804
805static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
806 void *dstbuf, filldir_t filldir)
807{
808 while (nbytes >= FUSE_NAME_OFFSET) {
809 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
810 size_t reclen = FUSE_DIRENT_SIZE(dirent);
811 int over;
812 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
813 return -EIO;
814 if (reclen > nbytes)
815 break;
816
817 over = filldir(dstbuf, dirent->name, dirent->namelen,
818 file->f_pos, dirent->ino, dirent->type);
819 if (over)
820 break;
821
822 buf += reclen;
823 nbytes -= reclen;
824 file->f_pos = dirent->off;
825 }
826
827 return 0;
828}
829
Miklos Szeredie5e55582005-09-09 13:10:28 -0700830static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
831{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700832 int err;
833 size_t nbytes;
834 struct page *page;
835 struct inode *inode = file->f_dentry->d_inode;
836 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -0800837 struct fuse_req *req;
838
839 if (is_bad_inode(inode))
840 return -EIO;
841
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700842 req = fuse_get_req(fc);
843 if (IS_ERR(req))
844 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700845
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700846 page = alloc_page(GFP_KERNEL);
847 if (!page) {
848 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700849 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700850 }
851 req->num_pages = 1;
852 req->pages[0] = page;
Miklos Szeredi361b1eb52006-01-16 22:14:45 -0800853 fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
854 request_send(fc, req);
855 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700856 err = req->out.h.error;
857 fuse_put_request(fc, req);
858 if (!err)
859 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
860 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700861
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700862 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -0700863 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700864 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700865}
866
867static char *read_link(struct dentry *dentry)
868{
869 struct inode *inode = dentry->d_inode;
870 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700871 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700872 char *link;
873
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700874 if (IS_ERR(req))
875 return ERR_PTR(PTR_ERR(req));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700876
877 link = (char *) __get_free_page(GFP_KERNEL);
878 if (!link) {
879 link = ERR_PTR(-ENOMEM);
880 goto out;
881 }
882 req->in.h.opcode = FUSE_READLINK;
883 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700884 req->out.argvar = 1;
885 req->out.numargs = 1;
886 req->out.args[0].size = PAGE_SIZE - 1;
887 req->out.args[0].value = link;
888 request_send(fc, req);
889 if (req->out.h.error) {
890 free_page((unsigned long) link);
891 link = ERR_PTR(req->out.h.error);
892 } else
893 link[req->out.args[0].size] = '\0';
894 out:
895 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -0700896 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700897 return link;
898}
899
900static void free_link(char *link)
901{
902 if (!IS_ERR(link))
903 free_page((unsigned long) link);
904}
905
906static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
907{
908 nd_set_link(nd, read_link(dentry));
909 return NULL;
910}
911
912static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
913{
914 free_link(nd_get_link(nd));
915}
916
917static int fuse_dir_open(struct inode *inode, struct file *file)
918{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700919 return fuse_open_common(inode, file, 1);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700920}
921
922static int fuse_dir_release(struct inode *inode, struct file *file)
923{
Miklos Szeredi04730fe2005-09-09 13:10:36 -0700924 return fuse_release_common(inode, file, 1);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700925}
926
Miklos Szeredi82547982005-09-09 13:10:38 -0700927static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
928{
929 /* nfsd can call this with no file */
930 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
931}
932
Miklos Szeredibefc6492005-11-07 00:59:52 -0800933static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700934{
935 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700936
937 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800938 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700939 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800940 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700941 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800942 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700943 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -0800944 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700945 /* You can only _set_ these together (they may change by themselves) */
946 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredibefc6492005-11-07 00:59:52 -0800947 arg->valid |= FATTR_ATIME | FATTR_MTIME;
948 arg->atime = iattr->ia_atime.tv_sec;
949 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700950 }
Miklos Szeredibefc6492005-11-07 00:59:52 -0800951 if (ivalid & ATTR_FILE) {
952 struct fuse_file *ff = iattr->ia_file->private_data;
953 arg->valid |= FATTR_FH;
954 arg->fh = ff->fh;
955 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700956}
957
Miklos Szeredi9ffbb912006-10-17 00:10:06 -0700958static void fuse_vmtruncate(struct inode *inode, loff_t offset)
959{
960 struct fuse_conn *fc = get_fuse_conn(inode);
961 int need_trunc;
962
963 spin_lock(&fc->lock);
964 need_trunc = inode->i_size > offset;
965 i_size_write(inode, offset);
966 spin_unlock(&fc->lock);
967
968 if (need_trunc) {
969 struct address_space *mapping = inode->i_mapping;
970 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
971 truncate_inode_pages(mapping, offset);
972 }
973}
974
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800975/*
976 * Set attributes, and at the same time refresh them.
977 *
978 * Truncation is slightly complicated, because the 'truncate' request
979 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -0700980 * vmtruncate() doesn't allow for this case, so do the rlimit checking
981 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800982 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700983static int fuse_setattr(struct dentry *entry, struct iattr *attr)
984{
985 struct inode *inode = entry->d_inode;
986 struct fuse_conn *fc = get_fuse_conn(inode);
987 struct fuse_inode *fi = get_fuse_inode(inode);
988 struct fuse_req *req;
989 struct fuse_setattr_in inarg;
990 struct fuse_attr_out outarg;
991 int err;
992 int is_truncate = 0;
993
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700994 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
995 err = inode_change_ok(inode, attr);
996 if (err)
997 return err;
998 }
999
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001000 if (attr->ia_valid & ATTR_SIZE) {
1001 unsigned long limit;
1002 is_truncate = 1;
1003 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1004 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
1005 send_sig(SIGXFSZ, current, 0);
1006 return -EFBIG;
1007 }
1008 }
1009
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001010 req = fuse_get_req(fc);
1011 if (IS_ERR(req))
1012 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001013
1014 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001015 iattr_to_fattr(attr, &inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001016 req->in.h.opcode = FUSE_SETATTR;
1017 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001018 req->in.numargs = 1;
1019 req->in.args[0].size = sizeof(inarg);
1020 req->in.args[0].value = &inarg;
1021 req->out.numargs = 1;
1022 req->out.args[0].size = sizeof(outarg);
1023 req->out.args[0].value = &outarg;
1024 request_send(fc, req);
1025 err = req->out.h.error;
1026 fuse_put_request(fc, req);
1027 if (!err) {
1028 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1029 make_bad_inode(inode);
1030 err = -EIO;
1031 } else {
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001032 if (is_truncate)
1033 fuse_vmtruncate(inode, outarg.attr.size);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001034 fuse_change_attributes(inode, &outarg.attr);
1035 fi->i_time = time_to_jiffies(outarg.attr_valid,
1036 outarg.attr_valid_nsec);
1037 }
1038 } else if (err == -EINTR)
1039 fuse_invalidate_attr(inode);
1040
1041 return err;
1042}
1043
Miklos Szeredie5e55582005-09-09 13:10:28 -07001044static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1045 struct kstat *stat)
1046{
1047 struct inode *inode = entry->d_inode;
1048 int err = fuse_revalidate(entry);
1049 if (!err)
1050 generic_fillattr(inode, stat);
1051
1052 return err;
1053}
1054
Miklos Szeredi92a87802005-09-09 13:10:31 -07001055static int fuse_setxattr(struct dentry *entry, const char *name,
1056 const void *value, size_t size, int flags)
1057{
1058 struct inode *inode = entry->d_inode;
1059 struct fuse_conn *fc = get_fuse_conn(inode);
1060 struct fuse_req *req;
1061 struct fuse_setxattr_in inarg;
1062 int err;
1063
Miklos Szeredi92a87802005-09-09 13:10:31 -07001064 if (fc->no_setxattr)
1065 return -EOPNOTSUPP;
1066
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001067 req = fuse_get_req(fc);
1068 if (IS_ERR(req))
1069 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001070
1071 memset(&inarg, 0, sizeof(inarg));
1072 inarg.size = size;
1073 inarg.flags = flags;
1074 req->in.h.opcode = FUSE_SETXATTR;
1075 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001076 req->in.numargs = 3;
1077 req->in.args[0].size = sizeof(inarg);
1078 req->in.args[0].value = &inarg;
1079 req->in.args[1].size = strlen(name) + 1;
1080 req->in.args[1].value = name;
1081 req->in.args[2].size = size;
1082 req->in.args[2].value = value;
1083 request_send(fc, req);
1084 err = req->out.h.error;
1085 fuse_put_request(fc, req);
1086 if (err == -ENOSYS) {
1087 fc->no_setxattr = 1;
1088 err = -EOPNOTSUPP;
1089 }
1090 return err;
1091}
1092
1093static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1094 void *value, size_t size)
1095{
1096 struct inode *inode = entry->d_inode;
1097 struct fuse_conn *fc = get_fuse_conn(inode);
1098 struct fuse_req *req;
1099 struct fuse_getxattr_in inarg;
1100 struct fuse_getxattr_out outarg;
1101 ssize_t ret;
1102
1103 if (fc->no_getxattr)
1104 return -EOPNOTSUPP;
1105
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001106 req = fuse_get_req(fc);
1107 if (IS_ERR(req))
1108 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001109
1110 memset(&inarg, 0, sizeof(inarg));
1111 inarg.size = size;
1112 req->in.h.opcode = FUSE_GETXATTR;
1113 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001114 req->in.numargs = 2;
1115 req->in.args[0].size = sizeof(inarg);
1116 req->in.args[0].value = &inarg;
1117 req->in.args[1].size = strlen(name) + 1;
1118 req->in.args[1].value = name;
1119 /* This is really two different operations rolled into one */
1120 req->out.numargs = 1;
1121 if (size) {
1122 req->out.argvar = 1;
1123 req->out.args[0].size = size;
1124 req->out.args[0].value = value;
1125 } else {
1126 req->out.args[0].size = sizeof(outarg);
1127 req->out.args[0].value = &outarg;
1128 }
1129 request_send(fc, req);
1130 ret = req->out.h.error;
1131 if (!ret)
1132 ret = size ? req->out.args[0].size : outarg.size;
1133 else {
1134 if (ret == -ENOSYS) {
1135 fc->no_getxattr = 1;
1136 ret = -EOPNOTSUPP;
1137 }
1138 }
1139 fuse_put_request(fc, req);
1140 return ret;
1141}
1142
1143static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1144{
1145 struct inode *inode = entry->d_inode;
1146 struct fuse_conn *fc = get_fuse_conn(inode);
1147 struct fuse_req *req;
1148 struct fuse_getxattr_in inarg;
1149 struct fuse_getxattr_out outarg;
1150 ssize_t ret;
1151
1152 if (fc->no_listxattr)
1153 return -EOPNOTSUPP;
1154
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001155 req = fuse_get_req(fc);
1156 if (IS_ERR(req))
1157 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001158
1159 memset(&inarg, 0, sizeof(inarg));
1160 inarg.size = size;
1161 req->in.h.opcode = FUSE_LISTXATTR;
1162 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001163 req->in.numargs = 1;
1164 req->in.args[0].size = sizeof(inarg);
1165 req->in.args[0].value = &inarg;
1166 /* This is really two different operations rolled into one */
1167 req->out.numargs = 1;
1168 if (size) {
1169 req->out.argvar = 1;
1170 req->out.args[0].size = size;
1171 req->out.args[0].value = list;
1172 } else {
1173 req->out.args[0].size = sizeof(outarg);
1174 req->out.args[0].value = &outarg;
1175 }
1176 request_send(fc, req);
1177 ret = req->out.h.error;
1178 if (!ret)
1179 ret = size ? req->out.args[0].size : outarg.size;
1180 else {
1181 if (ret == -ENOSYS) {
1182 fc->no_listxattr = 1;
1183 ret = -EOPNOTSUPP;
1184 }
1185 }
1186 fuse_put_request(fc, req);
1187 return ret;
1188}
1189
1190static int fuse_removexattr(struct dentry *entry, const char *name)
1191{
1192 struct inode *inode = entry->d_inode;
1193 struct fuse_conn *fc = get_fuse_conn(inode);
1194 struct fuse_req *req;
1195 int err;
1196
1197 if (fc->no_removexattr)
1198 return -EOPNOTSUPP;
1199
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001200 req = fuse_get_req(fc);
1201 if (IS_ERR(req))
1202 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001203
1204 req->in.h.opcode = FUSE_REMOVEXATTR;
1205 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001206 req->in.numargs = 1;
1207 req->in.args[0].size = strlen(name) + 1;
1208 req->in.args[0].value = name;
1209 request_send(fc, req);
1210 err = req->out.h.error;
1211 fuse_put_request(fc, req);
1212 if (err == -ENOSYS) {
1213 fc->no_removexattr = 1;
1214 err = -EOPNOTSUPP;
1215 }
1216 return err;
1217}
1218
Miklos Szeredie5e55582005-09-09 13:10:28 -07001219static struct inode_operations fuse_dir_inode_operations = {
1220 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001221 .mkdir = fuse_mkdir,
1222 .symlink = fuse_symlink,
1223 .unlink = fuse_unlink,
1224 .rmdir = fuse_rmdir,
1225 .rename = fuse_rename,
1226 .link = fuse_link,
1227 .setattr = fuse_setattr,
1228 .create = fuse_create,
1229 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001230 .permission = fuse_permission,
1231 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001232 .setxattr = fuse_setxattr,
1233 .getxattr = fuse_getxattr,
1234 .listxattr = fuse_listxattr,
1235 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001236};
1237
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001238static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001239 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001240 .read = generic_read_dir,
1241 .readdir = fuse_readdir,
1242 .open = fuse_dir_open,
1243 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001244 .fsync = fuse_dir_fsync,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001245};
1246
1247static struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001248 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001249 .permission = fuse_permission,
1250 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001251 .setxattr = fuse_setxattr,
1252 .getxattr = fuse_getxattr,
1253 .listxattr = fuse_listxattr,
1254 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001255};
1256
1257static struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001258 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001259 .follow_link = fuse_follow_link,
1260 .put_link = fuse_put_link,
1261 .readlink = generic_readlink,
1262 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001263 .setxattr = fuse_setxattr,
1264 .getxattr = fuse_getxattr,
1265 .listxattr = fuse_listxattr,
1266 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001267};
1268
1269void fuse_init_common(struct inode *inode)
1270{
1271 inode->i_op = &fuse_common_inode_operations;
1272}
1273
1274void fuse_init_dir(struct inode *inode)
1275{
1276 inode->i_op = &fuse_dir_inode_operations;
1277 inode->i_fop = &fuse_dir_operations;
1278}
1279
1280void fuse_init_symlink(struct inode *inode)
1281{
1282 inode->i_op = &fuse_symlink_inode_operations;
1283}