diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/control.c | 4 | ||||
-rw-r--r-- | fs/fuse/dir.c | 47 | ||||
-rw-r--r-- | fs/fuse/file.c | 10 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 | ||||
-rw-r--r-- | fs/fuse/inode.c | 2 |
5 files changed, 51 insertions, 14 deletions
diff --git a/fs/fuse/control.c b/fs/fuse/control.c index a3bce3a77253..46fe60b2da23 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c | |||
@@ -105,7 +105,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, | |||
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Add a connection to the control filesystem (if it exists). Caller | 107 | * Add a connection to the control filesystem (if it exists). Caller |
108 | * must host fuse_mutex | 108 | * must hold fuse_mutex |
109 | */ | 109 | */ |
110 | int fuse_ctl_add_conn(struct fuse_conn *fc) | 110 | int fuse_ctl_add_conn(struct fuse_conn *fc) |
111 | { | 111 | { |
@@ -139,7 +139,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc) | |||
139 | 139 | ||
140 | /* | 140 | /* |
141 | * Remove a connection from the control filesystem (if it exists). | 141 | * Remove a connection from the control filesystem (if it exists). |
142 | * Caller must host fuse_mutex | 142 | * Caller must hold fuse_mutex |
143 | */ | 143 | */ |
144 | void fuse_ctl_remove_conn(struct fuse_conn *fc) | 144 | void fuse_ctl_remove_conn(struct fuse_conn *fc) |
145 | { | 145 | { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 72a74cde6de8..409ce6a7cca4 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -14,6 +14,33 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
16 | 16 | ||
17 | #if BITS_PER_LONG >= 64 | ||
18 | static inline void fuse_dentry_settime(struct dentry *entry, u64 time) | ||
19 | { | ||
20 | entry->d_time = time; | ||
21 | } | ||
22 | |||
23 | static 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 | */ | ||
31 | static 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 | |||
37 | static 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 | |||
17 | /* | 44 | /* |
18 | * FUSE caches dentries and attributes with separate timeout. The | 45 | * FUSE caches dentries and attributes with separate timeout. The |
19 | * time in jiffies until the dentry/attributes are valid is stored in | 46 | * time in jiffies until the dentry/attributes are valid is stored in |
@@ -23,10 +50,13 @@ | |||
23 | /* | 50 | /* |
24 | * Calculate the time in jiffies until a dentry/attributes are valid | 51 | * Calculate the time in jiffies until a dentry/attributes are valid |
25 | */ | 52 | */ |
26 | static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) | 53 | static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) |
27 | { | 54 | { |
28 | struct timespec ts = {sec, nsec}; | 55 | if (sec || nsec) { |
29 | return jiffies + timespec_to_jiffies(&ts); | 56 | struct timespec ts = {sec, nsec}; |
57 | return get_jiffies_64() + timespec_to_jiffies(&ts); | ||
58 | } else | ||
59 | return 0; | ||
30 | } | 60 | } |
31 | 61 | ||
32 | /* | 62 | /* |
@@ -35,7 +65,8 @@ static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) | |||
35 | */ | 65 | */ |
36 | static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) | 66 | static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) |
37 | { | 67 | { |
38 | entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec); | 68 | fuse_dentry_settime(entry, |
69 | time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); | ||
39 | if (entry->d_inode) | 70 | if (entry->d_inode) |
40 | get_fuse_inode(entry->d_inode)->i_time = | 71 | get_fuse_inode(entry->d_inode)->i_time = |
41 | time_to_jiffies(o->attr_valid, o->attr_valid_nsec); | 72 | time_to_jiffies(o->attr_valid, o->attr_valid_nsec); |
@@ -47,7 +78,7 @@ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) | |||
47 | */ | 78 | */ |
48 | void fuse_invalidate_attr(struct inode *inode) | 79 | void fuse_invalidate_attr(struct inode *inode) |
49 | { | 80 | { |
50 | get_fuse_inode(inode)->i_time = jiffies - 1; | 81 | get_fuse_inode(inode)->i_time = 0; |
51 | } | 82 | } |
52 | 83 | ||
53 | /* | 84 | /* |
@@ -60,7 +91,7 @@ void fuse_invalidate_attr(struct inode *inode) | |||
60 | */ | 91 | */ |
61 | static void fuse_invalidate_entry_cache(struct dentry *entry) | 92 | static void fuse_invalidate_entry_cache(struct dentry *entry) |
62 | { | 93 | { |
63 | entry->d_time = jiffies - 1; | 94 | fuse_dentry_settime(entry, 0); |
64 | } | 95 | } |
65 | 96 | ||
66 | /* | 97 | /* |
@@ -102,7 +133,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
102 | 133 | ||
103 | if (inode && is_bad_inode(inode)) | 134 | if (inode && is_bad_inode(inode)) |
104 | return 0; | 135 | return 0; |
105 | else if (time_after(jiffies, entry->d_time)) { | 136 | else if (fuse_dentry_time(entry) < get_jiffies_64()) { |
106 | int err; | 137 | int err; |
107 | struct fuse_entry_out outarg; | 138 | struct fuse_entry_out outarg; |
108 | struct fuse_conn *fc; | 139 | struct fuse_conn *fc; |
@@ -666,7 +697,7 @@ static int fuse_revalidate(struct dentry *entry) | |||
666 | if (!fuse_allow_task(fc, current)) | 697 | if (!fuse_allow_task(fc, current)) |
667 | return -EACCES; | 698 | return -EACCES; |
668 | if (get_node_id(inode) != FUSE_ROOT_ID && | 699 | if (get_node_id(inode) != FUSE_ROOT_ID && |
669 | time_before_eq(jiffies, fi->i_time)) | 700 | fi->i_time >= get_jiffies_64()) |
670 | return 0; | 701 | return 0; |
671 | 702 | ||
672 | return fuse_do_getattr(inode); | 703 | return fuse_do_getattr(inode); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 63614ed16336..5c4fcd1dbf59 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -395,14 +395,16 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
395 | struct fuse_readpages_data data; | 395 | struct fuse_readpages_data data; |
396 | int err; | 396 | int err; |
397 | 397 | ||
398 | err = -EIO; | ||
398 | if (is_bad_inode(inode)) | 399 | if (is_bad_inode(inode)) |
399 | return -EIO; | 400 | goto clean_pages_up; |
400 | 401 | ||
401 | data.file = file; | 402 | data.file = file; |
402 | data.inode = inode; | 403 | data.inode = inode; |
403 | data.req = fuse_get_req(fc); | 404 | data.req = fuse_get_req(fc); |
405 | err = PTR_ERR(data.req); | ||
404 | if (IS_ERR(data.req)) | 406 | if (IS_ERR(data.req)) |
405 | return PTR_ERR(data.req); | 407 | goto clean_pages_up; |
406 | 408 | ||
407 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 409 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
408 | if (!err) { | 410 | if (!err) { |
@@ -412,6 +414,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
412 | fuse_put_request(fc, data.req); | 414 | fuse_put_request(fc, data.req); |
413 | } | 415 | } |
414 | return err; | 416 | return err; |
417 | |||
418 | clean_pages_up: | ||
419 | put_pages_list(pages); | ||
420 | return err; | ||
415 | } | 421 | } |
416 | 422 | ||
417 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 423 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 0dbf96621841..69c7750d55b8 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -59,7 +59,7 @@ struct fuse_inode { | |||
59 | struct fuse_req *forget_req; | 59 | struct fuse_req *forget_req; |
60 | 60 | ||
61 | /** Time in jiffies until the file attributes are valid */ | 61 | /** Time in jiffies until the file attributes are valid */ |
62 | unsigned long i_time; | 62 | u64 i_time; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | /** FUSE specific file data */ | 65 | /** FUSE specific file data */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index dcaaabd3b9c4..7d25092262ae 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -51,7 +51,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
51 | return NULL; | 51 | return NULL; |
52 | 52 | ||
53 | fi = get_fuse_inode(inode); | 53 | fi = get_fuse_inode(inode); |
54 | fi->i_time = jiffies - 1; | 54 | fi->i_time = 0; |
55 | fi->nodeid = 0; | 55 | fi->nodeid = 0; |
56 | fi->nlookup = 0; | 56 | fi->nlookup = 0; |
57 | fi->forget_req = fuse_request_alloc(); | 57 | fi->forget_req = fuse_request_alloc(); |