diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 230 |
1 files changed, 78 insertions, 152 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index bf50259012ab..760b2c552197 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -24,30 +24,22 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
24 | int opcode, struct fuse_open_out *outargp) | 24 | int opcode, struct fuse_open_out *outargp) |
25 | { | 25 | { |
26 | struct fuse_open_in inarg; | 26 | struct fuse_open_in inarg; |
27 | struct fuse_req *req; | 27 | FUSE_ARGS(args); |
28 | int err; | ||
29 | |||
30 | req = fuse_get_req_nopages(fc); | ||
31 | if (IS_ERR(req)) | ||
32 | return PTR_ERR(req); | ||
33 | 28 | ||
34 | memset(&inarg, 0, sizeof(inarg)); | 29 | memset(&inarg, 0, sizeof(inarg)); |
35 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); | 30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
36 | if (!fc->atomic_o_trunc) | 31 | if (!fc->atomic_o_trunc) |
37 | inarg.flags &= ~O_TRUNC; | 32 | inarg.flags &= ~O_TRUNC; |
38 | req->in.h.opcode = opcode; | 33 | args.in.h.opcode = opcode; |
39 | req->in.h.nodeid = nodeid; | 34 | args.in.h.nodeid = nodeid; |
40 | req->in.numargs = 1; | 35 | args.in.numargs = 1; |
41 | req->in.args[0].size = sizeof(inarg); | 36 | args.in.args[0].size = sizeof(inarg); |
42 | req->in.args[0].value = &inarg; | 37 | args.in.args[0].value = &inarg; |
43 | req->out.numargs = 1; | 38 | args.out.numargs = 1; |
44 | req->out.args[0].size = sizeof(*outargp); | 39 | args.out.args[0].size = sizeof(*outargp); |
45 | req->out.args[0].value = outargp; | 40 | args.out.args[0].value = outargp; |
46 | fuse_request_send(fc, req); | ||
47 | err = req->out.h.error; | ||
48 | fuse_put_request(fc, req); | ||
49 | 41 | ||
50 | return err; | 42 | return fuse_simple_request(fc, &args); |
51 | } | 43 | } |
52 | 44 | ||
53 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | 45 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) |
@@ -89,37 +81,9 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) | |||
89 | return ff; | 81 | return ff; |
90 | } | 82 | } |
91 | 83 | ||
92 | static void fuse_release_async(struct work_struct *work) | ||
93 | { | ||
94 | struct fuse_req *req; | ||
95 | struct fuse_conn *fc; | ||
96 | struct path path; | ||
97 | |||
98 | req = container_of(work, struct fuse_req, misc.release.work); | ||
99 | path = req->misc.release.path; | ||
100 | fc = get_fuse_conn(path.dentry->d_inode); | ||
101 | |||
102 | fuse_put_request(fc, req); | ||
103 | path_put(&path); | ||
104 | } | ||
105 | |||
106 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 84 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) |
107 | { | 85 | { |
108 | if (fc->destroy_req) { | 86 | iput(req->misc.release.inode); |
109 | /* | ||
110 | * If this is a fuseblk mount, then it's possible that | ||
111 | * releasing the path will result in releasing the | ||
112 | * super block and sending the DESTROY request. If | ||
113 | * the server is single threaded, this would hang. | ||
114 | * For this reason do the path_put() in a separate | ||
115 | * thread. | ||
116 | */ | ||
117 | atomic_inc(&req->count); | ||
118 | INIT_WORK(&req->misc.release.work, fuse_release_async); | ||
119 | schedule_work(&req->misc.release.work); | ||
120 | } else { | ||
121 | path_put(&req->misc.release.path); | ||
122 | } | ||
123 | } | 87 | } |
124 | 88 | ||
125 | static void fuse_file_put(struct fuse_file *ff, bool sync) | 89 | static void fuse_file_put(struct fuse_file *ff, bool sync) |
@@ -133,12 +97,12 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) | |||
133 | * implement 'open' | 97 | * implement 'open' |
134 | */ | 98 | */ |
135 | req->background = 0; | 99 | req->background = 0; |
136 | path_put(&req->misc.release.path); | 100 | iput(req->misc.release.inode); |
137 | fuse_put_request(ff->fc, req); | 101 | fuse_put_request(ff->fc, req); |
138 | } else if (sync) { | 102 | } else if (sync) { |
139 | req->background = 0; | 103 | req->background = 0; |
140 | fuse_request_send(ff->fc, req); | 104 | fuse_request_send(ff->fc, req); |
141 | path_put(&req->misc.release.path); | 105 | iput(req->misc.release.inode); |
142 | fuse_put_request(ff->fc, req); | 106 | fuse_put_request(ff->fc, req); |
143 | } else { | 107 | } else { |
144 | req->end = fuse_release_end; | 108 | req->end = fuse_release_end; |
@@ -297,9 +261,8 @@ void fuse_release_common(struct file *file, int opcode) | |||
297 | inarg->lock_owner = fuse_lock_owner_id(ff->fc, | 261 | inarg->lock_owner = fuse_lock_owner_id(ff->fc, |
298 | (fl_owner_t) file); | 262 | (fl_owner_t) file); |
299 | } | 263 | } |
300 | /* Hold vfsmount and dentry until release is finished */ | 264 | /* Hold inode until release is finished */ |
301 | path_get(&file->f_path); | 265 | req->misc.release.inode = igrab(file_inode(file)); |
302 | req->misc.release.path = file->f_path; | ||
303 | 266 | ||
304 | /* | 267 | /* |
305 | * Normally this will send the RELEASE request, however if | 268 | * Normally this will send the RELEASE request, however if |
@@ -480,7 +443,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
480 | struct inode *inode = file->f_mapping->host; | 443 | struct inode *inode = file->f_mapping->host; |
481 | struct fuse_conn *fc = get_fuse_conn(inode); | 444 | struct fuse_conn *fc = get_fuse_conn(inode); |
482 | struct fuse_file *ff = file->private_data; | 445 | struct fuse_file *ff = file->private_data; |
483 | struct fuse_req *req; | 446 | FUSE_ARGS(args); |
484 | struct fuse_fsync_in inarg; | 447 | struct fuse_fsync_in inarg; |
485 | int err; | 448 | int err; |
486 | 449 | ||
@@ -506,23 +469,15 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
506 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | 469 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
507 | goto out; | 470 | goto out; |
508 | 471 | ||
509 | req = fuse_get_req_nopages(fc); | ||
510 | if (IS_ERR(req)) { | ||
511 | err = PTR_ERR(req); | ||
512 | goto out; | ||
513 | } | ||
514 | |||
515 | memset(&inarg, 0, sizeof(inarg)); | 472 | memset(&inarg, 0, sizeof(inarg)); |
516 | inarg.fh = ff->fh; | 473 | inarg.fh = ff->fh; |
517 | inarg.fsync_flags = datasync ? 1 : 0; | 474 | inarg.fsync_flags = datasync ? 1 : 0; |
518 | req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; | 475 | args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; |
519 | req->in.h.nodeid = get_node_id(inode); | 476 | args.in.h.nodeid = get_node_id(inode); |
520 | req->in.numargs = 1; | 477 | args.in.numargs = 1; |
521 | req->in.args[0].size = sizeof(inarg); | 478 | args.in.args[0].size = sizeof(inarg); |
522 | req->in.args[0].value = &inarg; | 479 | args.in.args[0].value = &inarg; |
523 | fuse_request_send(fc, req); | 480 | err = fuse_simple_request(fc, &args); |
524 | err = req->out.h.error; | ||
525 | fuse_put_request(fc, req); | ||
526 | if (err == -ENOSYS) { | 481 | if (err == -ENOSYS) { |
527 | if (isdir) | 482 | if (isdir) |
528 | fc->no_fsyncdir = 1; | 483 | fc->no_fsyncdir = 1; |
@@ -2156,49 +2111,44 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, | |||
2156 | return 0; | 2111 | return 0; |
2157 | } | 2112 | } |
2158 | 2113 | ||
2159 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, | 2114 | static void fuse_lk_fill(struct fuse_args *args, struct file *file, |
2160 | const struct file_lock *fl, int opcode, pid_t pid, | 2115 | const struct file_lock *fl, int opcode, pid_t pid, |
2161 | int flock) | 2116 | int flock, struct fuse_lk_in *inarg) |
2162 | { | 2117 | { |
2163 | struct inode *inode = file_inode(file); | 2118 | struct inode *inode = file_inode(file); |
2164 | struct fuse_conn *fc = get_fuse_conn(inode); | 2119 | struct fuse_conn *fc = get_fuse_conn(inode); |
2165 | struct fuse_file *ff = file->private_data; | 2120 | struct fuse_file *ff = file->private_data; |
2166 | struct fuse_lk_in *arg = &req->misc.lk_in; | 2121 | |
2167 | 2122 | memset(inarg, 0, sizeof(*inarg)); | |
2168 | arg->fh = ff->fh; | 2123 | inarg->fh = ff->fh; |
2169 | arg->owner = fuse_lock_owner_id(fc, fl->fl_owner); | 2124 | inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner); |
2170 | arg->lk.start = fl->fl_start; | 2125 | inarg->lk.start = fl->fl_start; |
2171 | arg->lk.end = fl->fl_end; | 2126 | inarg->lk.end = fl->fl_end; |
2172 | arg->lk.type = fl->fl_type; | 2127 | inarg->lk.type = fl->fl_type; |
2173 | arg->lk.pid = pid; | 2128 | inarg->lk.pid = pid; |
2174 | if (flock) | 2129 | if (flock) |
2175 | arg->lk_flags |= FUSE_LK_FLOCK; | 2130 | inarg->lk_flags |= FUSE_LK_FLOCK; |
2176 | req->in.h.opcode = opcode; | 2131 | args->in.h.opcode = opcode; |
2177 | req->in.h.nodeid = get_node_id(inode); | 2132 | args->in.h.nodeid = get_node_id(inode); |
2178 | req->in.numargs = 1; | 2133 | args->in.numargs = 1; |
2179 | req->in.args[0].size = sizeof(*arg); | 2134 | args->in.args[0].size = sizeof(*inarg); |
2180 | req->in.args[0].value = arg; | 2135 | args->in.args[0].value = inarg; |
2181 | } | 2136 | } |
2182 | 2137 | ||
2183 | static int fuse_getlk(struct file *file, struct file_lock *fl) | 2138 | static int fuse_getlk(struct file *file, struct file_lock *fl) |
2184 | { | 2139 | { |
2185 | struct inode *inode = file_inode(file); | 2140 | struct inode *inode = file_inode(file); |
2186 | struct fuse_conn *fc = get_fuse_conn(inode); | 2141 | struct fuse_conn *fc = get_fuse_conn(inode); |
2187 | struct fuse_req *req; | 2142 | FUSE_ARGS(args); |
2143 | struct fuse_lk_in inarg; | ||
2188 | struct fuse_lk_out outarg; | 2144 | struct fuse_lk_out outarg; |
2189 | int err; | 2145 | int err; |
2190 | 2146 | ||
2191 | req = fuse_get_req_nopages(fc); | 2147 | fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg); |
2192 | if (IS_ERR(req)) | 2148 | args.out.numargs = 1; |
2193 | return PTR_ERR(req); | 2149 | args.out.args[0].size = sizeof(outarg); |
2194 | 2150 | args.out.args[0].value = &outarg; | |
2195 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0); | 2151 | err = fuse_simple_request(fc, &args); |
2196 | req->out.numargs = 1; | ||
2197 | req->out.args[0].size = sizeof(outarg); | ||
2198 | req->out.args[0].value = &outarg; | ||
2199 | fuse_request_send(fc, req); | ||
2200 | err = req->out.h.error; | ||
2201 | fuse_put_request(fc, req); | ||
2202 | if (!err) | 2152 | if (!err) |
2203 | err = convert_fuse_file_lock(&outarg.lk, fl); | 2153 | err = convert_fuse_file_lock(&outarg.lk, fl); |
2204 | 2154 | ||
@@ -2209,7 +2159,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
2209 | { | 2159 | { |
2210 | struct inode *inode = file_inode(file); | 2160 | struct inode *inode = file_inode(file); |
2211 | struct fuse_conn *fc = get_fuse_conn(inode); | 2161 | struct fuse_conn *fc = get_fuse_conn(inode); |
2212 | struct fuse_req *req; | 2162 | FUSE_ARGS(args); |
2163 | struct fuse_lk_in inarg; | ||
2213 | int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; | 2164 | int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; |
2214 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; | 2165 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; |
2215 | int err; | 2166 | int err; |
@@ -2223,17 +2174,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
2223 | if (fl->fl_flags & FL_CLOSE) | 2174 | if (fl->fl_flags & FL_CLOSE) |
2224 | return 0; | 2175 | return 0; |
2225 | 2176 | ||
2226 | req = fuse_get_req_nopages(fc); | 2177 | fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg); |
2227 | if (IS_ERR(req)) | 2178 | err = fuse_simple_request(fc, &args); |
2228 | return PTR_ERR(req); | ||
2229 | 2179 | ||
2230 | fuse_lk_fill(req, file, fl, opcode, pid, flock); | ||
2231 | fuse_request_send(fc, req); | ||
2232 | err = req->out.h.error; | ||
2233 | /* locking is restartable */ | 2180 | /* locking is restartable */ |
2234 | if (err == -EINTR) | 2181 | if (err == -EINTR) |
2235 | err = -ERESTARTSYS; | 2182 | err = -ERESTARTSYS; |
2236 | fuse_put_request(fc, req); | 2183 | |
2237 | return err; | 2184 | return err; |
2238 | } | 2185 | } |
2239 | 2186 | ||
@@ -2283,7 +2230,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
2283 | { | 2230 | { |
2284 | struct inode *inode = mapping->host; | 2231 | struct inode *inode = mapping->host; |
2285 | struct fuse_conn *fc = get_fuse_conn(inode); | 2232 | struct fuse_conn *fc = get_fuse_conn(inode); |
2286 | struct fuse_req *req; | 2233 | FUSE_ARGS(args); |
2287 | struct fuse_bmap_in inarg; | 2234 | struct fuse_bmap_in inarg; |
2288 | struct fuse_bmap_out outarg; | 2235 | struct fuse_bmap_out outarg; |
2289 | int err; | 2236 | int err; |
@@ -2291,24 +2238,18 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
2291 | if (!inode->i_sb->s_bdev || fc->no_bmap) | 2238 | if (!inode->i_sb->s_bdev || fc->no_bmap) |
2292 | return 0; | 2239 | return 0; |
2293 | 2240 | ||
2294 | req = fuse_get_req_nopages(fc); | ||
2295 | if (IS_ERR(req)) | ||
2296 | return 0; | ||
2297 | |||
2298 | memset(&inarg, 0, sizeof(inarg)); | 2241 | memset(&inarg, 0, sizeof(inarg)); |
2299 | inarg.block = block; | 2242 | inarg.block = block; |
2300 | inarg.blocksize = inode->i_sb->s_blocksize; | 2243 | inarg.blocksize = inode->i_sb->s_blocksize; |
2301 | req->in.h.opcode = FUSE_BMAP; | 2244 | args.in.h.opcode = FUSE_BMAP; |
2302 | req->in.h.nodeid = get_node_id(inode); | 2245 | args.in.h.nodeid = get_node_id(inode); |
2303 | req->in.numargs = 1; | 2246 | args.in.numargs = 1; |
2304 | req->in.args[0].size = sizeof(inarg); | 2247 | args.in.args[0].size = sizeof(inarg); |
2305 | req->in.args[0].value = &inarg; | 2248 | args.in.args[0].value = &inarg; |
2306 | req->out.numargs = 1; | 2249 | args.out.numargs = 1; |
2307 | req->out.args[0].size = sizeof(outarg); | 2250 | args.out.args[0].size = sizeof(outarg); |
2308 | req->out.args[0].value = &outarg; | 2251 | args.out.args[0].value = &outarg; |
2309 | fuse_request_send(fc, req); | 2252 | err = fuse_simple_request(fc, &args); |
2310 | err = req->out.h.error; | ||
2311 | fuse_put_request(fc, req); | ||
2312 | if (err == -ENOSYS) | 2253 | if (err == -ENOSYS) |
2313 | fc->no_bmap = 1; | 2254 | fc->no_bmap = 1; |
2314 | 2255 | ||
@@ -2776,7 +2717,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2776 | struct fuse_conn *fc = ff->fc; | 2717 | struct fuse_conn *fc = ff->fc; |
2777 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; | 2718 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; |
2778 | struct fuse_poll_out outarg; | 2719 | struct fuse_poll_out outarg; |
2779 | struct fuse_req *req; | 2720 | FUSE_ARGS(args); |
2780 | int err; | 2721 | int err; |
2781 | 2722 | ||
2782 | if (fc->no_poll) | 2723 | if (fc->no_poll) |
@@ -2794,21 +2735,15 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2794 | fuse_register_polled_file(fc, ff); | 2735 | fuse_register_polled_file(fc, ff); |
2795 | } | 2736 | } |
2796 | 2737 | ||
2797 | req = fuse_get_req_nopages(fc); | 2738 | args.in.h.opcode = FUSE_POLL; |
2798 | if (IS_ERR(req)) | 2739 | args.in.h.nodeid = ff->nodeid; |
2799 | return POLLERR; | 2740 | args.in.numargs = 1; |
2800 | 2741 | args.in.args[0].size = sizeof(inarg); | |
2801 | req->in.h.opcode = FUSE_POLL; | 2742 | args.in.args[0].value = &inarg; |
2802 | req->in.h.nodeid = ff->nodeid; | 2743 | args.out.numargs = 1; |
2803 | req->in.numargs = 1; | 2744 | args.out.args[0].size = sizeof(outarg); |
2804 | req->in.args[0].size = sizeof(inarg); | 2745 | args.out.args[0].value = &outarg; |
2805 | req->in.args[0].value = &inarg; | 2746 | err = fuse_simple_request(fc, &args); |
2806 | req->out.numargs = 1; | ||
2807 | req->out.args[0].size = sizeof(outarg); | ||
2808 | req->out.args[0].value = &outarg; | ||
2809 | fuse_request_send(fc, req); | ||
2810 | err = req->out.h.error; | ||
2811 | fuse_put_request(fc, req); | ||
2812 | 2747 | ||
2813 | if (!err) | 2748 | if (!err) |
2814 | return outarg.revents; | 2749 | return outarg.revents; |
@@ -2949,10 +2884,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2949 | loff_t length) | 2884 | loff_t length) |
2950 | { | 2885 | { |
2951 | struct fuse_file *ff = file->private_data; | 2886 | struct fuse_file *ff = file->private_data; |
2952 | struct inode *inode = file->f_inode; | 2887 | struct inode *inode = file_inode(file); |
2953 | struct fuse_inode *fi = get_fuse_inode(inode); | 2888 | struct fuse_inode *fi = get_fuse_inode(inode); |
2954 | struct fuse_conn *fc = ff->fc; | 2889 | struct fuse_conn *fc = ff->fc; |
2955 | struct fuse_req *req; | 2890 | FUSE_ARGS(args); |
2956 | struct fuse_fallocate_in inarg = { | 2891 | struct fuse_fallocate_in inarg = { |
2957 | .fh = ff->fh, | 2892 | .fh = ff->fh, |
2958 | .offset = offset, | 2893 | .offset = offset, |
@@ -2985,25 +2920,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2985 | if (!(mode & FALLOC_FL_KEEP_SIZE)) | 2920 | if (!(mode & FALLOC_FL_KEEP_SIZE)) |
2986 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | 2921 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
2987 | 2922 | ||
2988 | req = fuse_get_req_nopages(fc); | 2923 | args.in.h.opcode = FUSE_FALLOCATE; |
2989 | if (IS_ERR(req)) { | 2924 | args.in.h.nodeid = ff->nodeid; |
2990 | err = PTR_ERR(req); | 2925 | args.in.numargs = 1; |
2991 | goto out; | 2926 | args.in.args[0].size = sizeof(inarg); |
2992 | } | 2927 | args.in.args[0].value = &inarg; |
2993 | 2928 | err = fuse_simple_request(fc, &args); | |
2994 | req->in.h.opcode = FUSE_FALLOCATE; | ||
2995 | req->in.h.nodeid = ff->nodeid; | ||
2996 | req->in.numargs = 1; | ||
2997 | req->in.args[0].size = sizeof(inarg); | ||
2998 | req->in.args[0].value = &inarg; | ||
2999 | fuse_request_send(fc, req); | ||
3000 | err = req->out.h.error; | ||
3001 | if (err == -ENOSYS) { | 2929 | if (err == -ENOSYS) { |
3002 | fc->no_fallocate = 1; | 2930 | fc->no_fallocate = 1; |
3003 | err = -EOPNOTSUPP; | 2931 | err = -EOPNOTSUPP; |
3004 | } | 2932 | } |
3005 | fuse_put_request(fc, req); | ||
3006 | |||
3007 | if (err) | 2933 | if (err) |
3008 | goto out; | 2934 | goto out; |
3009 | 2935 | ||