aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r--fs/fuse/file.c230
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
53struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) 45struct 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
92static 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
106static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) 84static 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
125static void fuse_file_put(struct fuse_file *ff, bool sync) 89static 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
2159static void fuse_lk_fill(struct fuse_req *req, struct file *file, 2114static 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
2183static int fuse_getlk(struct file *file, struct file_lock *fl) 2138static 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