Blame view

fs/fuse/file.c 50.8 KB
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1
2
  /*
    FUSE: Filesystem in Userspace
1729a16c2   Miklos Szeredi   fuse: style fixes
3
    Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
4
5
6
7
8
9
10
11
12
13
  
    This program can be distributed under the terms of the GNU GPL.
    See the file COPYING.
  */
  
  #include "fuse_i.h"
  
  #include <linux/pagemap.h>
  #include <linux/slab.h>
  #include <linux/kernel.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
14
  #include <linux/sched.h>
08cbf542b   Tejun Heo   fuse: export symb...
15
  #include <linux/module.h>
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
16
  #include <linux/compat.h>
478e0841b   Johannes Weiner   fuse: mark pages ...
17
  #include <linux/swap.h>
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
18

4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
19
  static const struct file_operations fuse_direct_io_file_operations;
45323fb76   Miklos Szeredi   [PATCH] fuse: mor...
20

91fe96b40   Miklos Szeredi   fuse: create fuse...
21
22
  static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
  			  int opcode, struct fuse_open_out *outargp)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
23
  {
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
24
  	struct fuse_open_in inarg;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
25
26
  	struct fuse_req *req;
  	int err;
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
27
28
29
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
30
31
  
  	memset(&inarg, 0, sizeof(inarg));
6ff958edb   Miklos Szeredi   fuse: add atomic ...
32
33
34
  	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
  	if (!fc->atomic_o_trunc)
  		inarg.flags &= ~O_TRUNC;
91fe96b40   Miklos Szeredi   fuse: create fuse...
35
36
  	req->in.h.opcode = opcode;
  	req->in.h.nodeid = nodeid;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
37
38
39
40
41
42
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
  	req->out.numargs = 1;
  	req->out.args[0].size = sizeof(*outargp);
  	req->out.args[0].value = outargp;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
43
  	fuse_request_send(fc, req);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
44
45
46
47
48
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  
  	return err;
  }
acf99433d   Tejun Heo   fuse: add file ke...
49
  struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
50
51
  {
  	struct fuse_file *ff;
6b2db28a7   Tejun Heo   fuse: misc cleanups
52

fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
53
  	ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
6b2db28a7   Tejun Heo   fuse: misc cleanups
54
55
  	if (unlikely(!ff))
  		return NULL;
da5e47145   Miklos Szeredi   fuse: add members...
56
  	ff->fc = fc;
6b2db28a7   Tejun Heo   fuse: misc cleanups
57
58
59
60
  	ff->reserved_req = fuse_request_alloc();
  	if (unlikely(!ff->reserved_req)) {
  		kfree(ff);
  		return NULL;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
61
  	}
6b2db28a7   Tejun Heo   fuse: misc cleanups
62
63
64
65
66
67
68
69
70
  
  	INIT_LIST_HEAD(&ff->write_entry);
  	atomic_set(&ff->count, 0);
  	RB_CLEAR_NODE(&ff->polled_node);
  	init_waitqueue_head(&ff->poll_wait);
  
  	spin_lock(&fc->lock);
  	ff->kh = ++fc->khctr;
  	spin_unlock(&fc->lock);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
71
72
73
74
75
  	return ff;
  }
  
  void fuse_file_free(struct fuse_file *ff)
  {
33649c91a   Miklos Szeredi   [PATCH] fuse: ens...
76
  	fuse_request_free(ff->reserved_req);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
77
78
  	kfree(ff);
  }
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
79
  struct fuse_file *fuse_file_get(struct fuse_file *ff)
c756e0a4d   Miklos Szeredi   fuse: add referen...
80
81
82
83
  {
  	atomic_inc(&ff->count);
  	return ff;
  }
5a18ec176   Miklos Szeredi   fuse: fix hang of...
84
85
86
87
88
89
90
91
92
93
94
95
96
  static void fuse_release_async(struct work_struct *work)
  {
  	struct fuse_req *req;
  	struct fuse_conn *fc;
  	struct path path;
  
  	req = container_of(work, struct fuse_req, misc.release.work);
  	path = req->misc.release.path;
  	fc = get_fuse_conn(path.dentry->d_inode);
  
  	fuse_put_request(fc, req);
  	path_put(&path);
  }
819c4b3b4   Miklos Szeredi   fuse: cleanup in ...
97
98
  static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
  {
5a18ec176   Miklos Szeredi   fuse: fix hang of...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  	if (fc->destroy_req) {
  		/*
  		 * If this is a fuseblk mount, then it's possible that
  		 * releasing the path will result in releasing the
  		 * super block and sending the DESTROY request.  If
  		 * the server is single threaded, this would hang.
  		 * For this reason do the path_put() in a separate
  		 * thread.
  		 */
  		atomic_inc(&req->count);
  		INIT_WORK(&req->misc.release.work, fuse_release_async);
  		schedule_work(&req->misc.release.work);
  	} else {
  		path_put(&req->misc.release.path);
  	}
819c4b3b4   Miklos Szeredi   fuse: cleanup in ...
114
  }
5a18ec176   Miklos Szeredi   fuse: fix hang of...
115
  static void fuse_file_put(struct fuse_file *ff, bool sync)
c756e0a4d   Miklos Szeredi   fuse: add referen...
116
117
118
  {
  	if (atomic_dec_and_test(&ff->count)) {
  		struct fuse_req *req = ff->reserved_req;
8b0797a49   Miklos Szeredi   fuse: don't use i...
119

5a18ec176   Miklos Szeredi   fuse: fix hang of...
120
121
122
123
124
125
126
127
  		if (sync) {
  			fuse_request_send(ff->fc, req);
  			path_put(&req->misc.release.path);
  			fuse_put_request(ff->fc, req);
  		} else {
  			req->end = fuse_release_end;
  			fuse_request_send_background(ff->fc, req);
  		}
c756e0a4d   Miklos Szeredi   fuse: add referen...
128
129
130
  		kfree(ff);
  	}
  }
08cbf542b   Tejun Heo   fuse: export symb...
131
132
  int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
  		 bool isdir)
91fe96b40   Miklos Szeredi   fuse: create fuse...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  {
  	struct fuse_open_out outarg;
  	struct fuse_file *ff;
  	int err;
  	int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
  
  	ff = fuse_file_alloc(fc);
  	if (!ff)
  		return -ENOMEM;
  
  	err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
  	if (err) {
  		fuse_file_free(ff);
  		return err;
  	}
  
  	if (isdir)
  		outarg.open_flags &= ~FOPEN_DIRECT_IO;
  
  	ff->fh = outarg.fh;
  	ff->nodeid = nodeid;
  	ff->open_flags = outarg.open_flags;
  	file->private_data = fuse_file_get(ff);
  
  	return 0;
  }
08cbf542b   Tejun Heo   fuse: export symb...
159
  EXPORT_SYMBOL_GPL(fuse_do_open);
91fe96b40   Miklos Szeredi   fuse: create fuse...
160

c7b7143c6   Miklos Szeredi   fuse: clean up ar...
161
  void fuse_finish_open(struct inode *inode, struct file *file)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
162
  {
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
163
  	struct fuse_file *ff = file->private_data;
a0822c557   Ken Sumrall   fuse: fix attribu...
164
  	struct fuse_conn *fc = get_fuse_conn(inode);
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
165
166
  
  	if (ff->open_flags & FOPEN_DIRECT_IO)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
167
  		file->f_op = &fuse_direct_io_file_operations;
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
168
  	if (!(ff->open_flags & FOPEN_KEEP_CACHE))
b10099792   Miklos Szeredi   fuse: fix page in...
169
  		invalidate_inode_pages2(inode->i_mapping);
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
170
  	if (ff->open_flags & FOPEN_NONSEEKABLE)
a7c1b990f   Tejun Heo   fuse: implement n...
171
  		nonseekable_open(inode, file);
a0822c557   Ken Sumrall   fuse: fix attribu...
172
173
174
175
176
177
178
179
180
  	if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
  		struct fuse_inode *fi = get_fuse_inode(inode);
  
  		spin_lock(&fc->lock);
  		fi->attr_version = ++fc->attr_version;
  		i_size_write(inode, 0);
  		spin_unlock(&fc->lock);
  		fuse_invalidate_attr(inode);
  	}
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
181
  }
91fe96b40   Miklos Szeredi   fuse: create fuse...
182
  int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
183
  {
acf99433d   Tejun Heo   fuse: add file ke...
184
  	struct fuse_conn *fc = get_fuse_conn(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
185
  	int err;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
186

dd190d066   Miklos Szeredi   [PATCH] fuse: che...
187
188
189
  	/* VFS checks this, but only _after_ ->open() */
  	if (file->f_flags & O_DIRECT)
  		return -EINVAL;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
190
191
192
  	err = generic_file_open(inode, file);
  	if (err)
  		return err;
91fe96b40   Miklos Szeredi   fuse: create fuse...
193
  	err = fuse_do_open(fc, get_node_id(inode), file, isdir);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
194
  	if (err)
91fe96b40   Miklos Szeredi   fuse: create fuse...
195
  		return err;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
196

91fe96b40   Miklos Szeredi   fuse: create fuse...
197
198
199
  	fuse_finish_open(inode, file);
  
  	return 0;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
200
  }
8b0797a49   Miklos Szeredi   fuse: don't use i...
201
  static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
64c6d8ed4   Miklos Szeredi   [PATCH] fuse: add...
202
  {
8b0797a49   Miklos Szeredi   fuse: don't use i...
203
  	struct fuse_conn *fc = ff->fc;
33649c91a   Miklos Szeredi   [PATCH] fuse: ens...
204
  	struct fuse_req *req = ff->reserved_req;
b57d42644   Miklos Szeredi   fuse: save space ...
205
  	struct fuse_release_in *inarg = &req->misc.release.in;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
206

8b0797a49   Miklos Szeredi   fuse: don't use i...
207
208
209
210
211
  	spin_lock(&fc->lock);
  	list_del(&ff->write_entry);
  	if (!RB_EMPTY_NODE(&ff->polled_node))
  		rb_erase(&ff->polled_node, &fc->polled_files);
  	spin_unlock(&fc->lock);
357ccf2b6   Bryan Green   fuse: wakeup poll...
212
  	wake_up_interruptible_all(&ff->poll_wait);
8b0797a49   Miklos Szeredi   fuse: don't use i...
213

b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
214
  	inarg->fh = ff->fh;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
215
  	inarg->flags = flags;
51eb01e73   Miklos Szeredi   [PATCH] fuse: no ...
216
  	req->in.h.opcode = opcode;
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
217
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
218
219
220
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(struct fuse_release_in);
  	req->in.args[0].value = inarg;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
221
  }
8b0797a49   Miklos Szeredi   fuse: don't use i...
222
  void fuse_release_common(struct file *file, int opcode)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
223
  {
6b2db28a7   Tejun Heo   fuse: misc cleanups
224
225
  	struct fuse_file *ff;
  	struct fuse_req *req;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
226

6b2db28a7   Tejun Heo   fuse: misc cleanups
227
228
  	ff = file->private_data;
  	if (unlikely(!ff))
8b0797a49   Miklos Szeredi   fuse: don't use i...
229
  		return;
6b2db28a7   Tejun Heo   fuse: misc cleanups
230

6b2db28a7   Tejun Heo   fuse: misc cleanups
231
  	req = ff->reserved_req;
8b0797a49   Miklos Szeredi   fuse: don't use i...
232
  	fuse_prepare_release(ff, file->f_flags, opcode);
6b2db28a7   Tejun Heo   fuse: misc cleanups
233

37fb3a30b   Miklos Szeredi   fuse: fix flock
234
235
236
237
238
239
  	if (ff->flock) {
  		struct fuse_release_in *inarg = &req->misc.release.in;
  		inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
  		inarg->lock_owner = fuse_lock_owner_id(ff->fc,
  						       (fl_owner_t) file);
  	}
6b2db28a7   Tejun Heo   fuse: misc cleanups
240
  	/* Hold vfsmount and dentry until release is finished */
b0be46ebf   Miklos Szeredi   fuse: use struct ...
241
242
  	path_get(&file->f_path);
  	req->misc.release.path = file->f_path;
6b2db28a7   Tejun Heo   fuse: misc cleanups
243

6b2db28a7   Tejun Heo   fuse: misc cleanups
244
245
246
247
  	/*
  	 * Normally this will send the RELEASE request, however if
  	 * some asynchronous READ or WRITE requests are outstanding,
  	 * the sending will be delayed.
5a18ec176   Miklos Szeredi   fuse: fix hang of...
248
249
250
251
  	 *
  	 * Make the release synchronous if this is a fuseblk mount,
  	 * synchronous RELEASE is allowed (and desirable) in this case
  	 * because the server can be trusted not to screw up.
6b2db28a7   Tejun Heo   fuse: misc cleanups
252
  	 */
5a18ec176   Miklos Szeredi   fuse: fix hang of...
253
  	fuse_file_put(ff, ff->fc->destroy_req != NULL);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
254
  }
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
255
256
  static int fuse_open(struct inode *inode, struct file *file)
  {
91fe96b40   Miklos Szeredi   fuse: create fuse...
257
  	return fuse_open_common(inode, file, false);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
258
259
260
261
  }
  
  static int fuse_release(struct inode *inode, struct file *file)
  {
8b0797a49   Miklos Szeredi   fuse: don't use i...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  	fuse_release_common(file, FUSE_RELEASE);
  
  	/* return value is ignored by VFS */
  	return 0;
  }
  
  void fuse_sync_release(struct fuse_file *ff, int flags)
  {
  	WARN_ON(atomic_read(&ff->count) > 1);
  	fuse_prepare_release(ff, flags, FUSE_RELEASE);
  	ff->reserved_req->force = 1;
  	fuse_request_send(ff->fc, ff->reserved_req);
  	fuse_put_request(ff->fc, ff->reserved_req);
  	kfree(ff);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
276
  }
08cbf542b   Tejun Heo   fuse: export symb...
277
  EXPORT_SYMBOL_GPL(fuse_sync_release);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
278

714212593   Miklos Szeredi   [PATCH] fuse: add...
279
  /*
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
280
281
   * Scramble the ID space with XTEA, so that the value of the files_struct
   * pointer is not exposed to userspace.
714212593   Miklos Szeredi   [PATCH] fuse: add...
282
   */
f33321141   Miklos Szeredi   fuse: add support...
283
  u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
714212593   Miklos Szeredi   [PATCH] fuse: add...
284
  {
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  	u32 *k = fc->scramble_key;
  	u64 v = (unsigned long) id;
  	u32 v0 = v;
  	u32 v1 = v >> 32;
  	u32 sum = 0;
  	int i;
  
  	for (i = 0; i < 32; i++) {
  		v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
  		sum += 0x9E3779B9;
  		v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
  	}
  
  	return (u64) v0 + ((u64) v1 << 32);
714212593   Miklos Szeredi   [PATCH] fuse: add...
299
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  /*
   * Check if page is under writeback
   *
   * This is currently done by walking the list of writepage requests
   * for the inode, which can be pretty inefficient.
   */
  static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  	struct fuse_req *req;
  	bool found = false;
  
  	spin_lock(&fc->lock);
  	list_for_each_entry(req, &fi->writepages, writepages_entry) {
  		pgoff_t curr_index;
  
  		BUG_ON(req->inode != inode);
  		curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
  		if (curr_index == index) {
  			found = true;
  			break;
  		}
  	}
  	spin_unlock(&fc->lock);
  
  	return found;
  }
  
  /*
   * Wait for page writeback to be completed.
   *
   * Since fuse doesn't rely on the VM writeback tracking, this has to
   * use some other means.
   */
  static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
  {
  	struct fuse_inode *fi = get_fuse_inode(inode);
  
  	wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index));
  	return 0;
  }
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
342
  static int fuse_flush(struct file *file, fl_owner_t id)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
343
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
344
  	struct inode *inode = file->f_path.dentry->d_inode;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
345
346
347
348
349
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_file *ff = file->private_data;
  	struct fuse_req *req;
  	struct fuse_flush_in inarg;
  	int err;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
350
351
  	if (is_bad_inode(inode))
  		return -EIO;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
352
353
  	if (fc->no_flush)
  		return 0;
33649c91a   Miklos Szeredi   [PATCH] fuse: ens...
354
  	req = fuse_get_req_nofail(fc, file);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
355
356
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.fh = ff->fh;
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
357
  	inarg.lock_owner = fuse_lock_owner_id(fc, id);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
358
359
  	req->in.h.opcode = FUSE_FLUSH;
  	req->in.h.nodeid = get_node_id(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
360
361
362
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
714212593   Miklos Szeredi   [PATCH] fuse: add...
363
  	req->force = 1;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
364
  	fuse_request_send(fc, req);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
365
366
367
368
369
370
371
372
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  	if (err == -ENOSYS) {
  		fc->no_flush = 1;
  		err = 0;
  	}
  	return err;
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  /*
   * Wait for all pending writepages on the inode to finish.
   *
   * This is currently done by blocking further writes with FUSE_NOWRITE
   * and waiting for all sent writes to complete.
   *
   * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
   * could conflict with truncation.
   */
  static void fuse_sync_writes(struct inode *inode)
  {
  	fuse_set_nowrite(inode);
  	fuse_release_nowrite(inode);
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
387
388
  int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
  		      int datasync, int isdir)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
389
  {
7ea808591   Christoph Hellwig   drop unused dentr...
390
  	struct inode *inode = file->f_mapping->host;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
391
392
393
394
395
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_file *ff = file->private_data;
  	struct fuse_req *req;
  	struct fuse_fsync_in inarg;
  	int err;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
396
397
  	if (is_bad_inode(inode))
  		return -EIO;
02c24a821   Josef Bacik   fs: push i_mutex ...
398
399
400
  	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
  	if (err)
  		return err;
825479819   Miklos Szeredi   [PATCH] FUSE: add...
401
  	if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
402
  		return 0;
02c24a821   Josef Bacik   fs: push i_mutex ...
403
  	mutex_lock(&inode->i_mutex);
3be5a52b3   Miklos Szeredi   fuse: support wri...
404
405
406
407
408
409
410
  	/*
  	 * Start writeback against all dirty pages of the inode, then
  	 * wait for all outstanding writes, before sending the FSYNC
  	 * request.
  	 */
  	err = write_inode_now(inode, 0);
  	if (err)
02c24a821   Josef Bacik   fs: push i_mutex ...
411
  		goto out;
3be5a52b3   Miklos Szeredi   fuse: support wri...
412
413
  
  	fuse_sync_writes(inode);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
414
  	req = fuse_get_req(fc);
02c24a821   Josef Bacik   fs: push i_mutex ...
415
416
417
418
  	if (IS_ERR(req)) {
  		err = PTR_ERR(req);
  		goto out;
  	}
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
419
420
421
422
  
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.fh = ff->fh;
  	inarg.fsync_flags = datasync ? 1 : 0;
825479819   Miklos Szeredi   [PATCH] FUSE: add...
423
  	req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
424
  	req->in.h.nodeid = get_node_id(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
425
426
427
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
428
  	fuse_request_send(fc, req);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
429
430
431
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  	if (err == -ENOSYS) {
825479819   Miklos Szeredi   [PATCH] FUSE: add...
432
433
434
435
  		if (isdir)
  			fc->no_fsyncdir = 1;
  		else
  			fc->no_fsync = 1;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
436
437
  		err = 0;
  	}
02c24a821   Josef Bacik   fs: push i_mutex ...
438
439
  out:
  	mutex_unlock(&inode->i_mutex);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
440
441
  	return err;
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
442
443
  static int fuse_fsync(struct file *file, loff_t start, loff_t end,
  		      int datasync)
825479819   Miklos Szeredi   [PATCH] FUSE: add...
444
  {
02c24a821   Josef Bacik   fs: push i_mutex ...
445
  	return fuse_fsync_common(file, start, end, datasync, 0);
825479819   Miklos Szeredi   [PATCH] FUSE: add...
446
  }
2106cb189   Miklos Szeredi   fuse: don't use i...
447
448
  void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
  		    size_t count, int opcode)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
449
  {
5c5c5e51b   Miklos Szeredi   fuse: update file...
450
  	struct fuse_read_in *inarg = &req->misc.read.in;
a6643094e   Miklos Szeredi   fuse: pass open f...
451
  	struct fuse_file *ff = file->private_data;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
452

361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
453
454
455
  	inarg->fh = ff->fh;
  	inarg->offset = pos;
  	inarg->size = count;
a6643094e   Miklos Szeredi   fuse: pass open f...
456
  	inarg->flags = file->f_flags;
361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
457
  	req->in.h.opcode = opcode;
2106cb189   Miklos Szeredi   fuse: don't use i...
458
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
459
460
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(struct fuse_read_in);
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
461
  	req->in.args[0].value = inarg;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
462
463
464
  	req->out.argvar = 1;
  	req->out.numargs = 1;
  	req->out.args[0].size = count;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
465
  }
8bfc016d2   Miklos Szeredi   [PATCH] fuse: uni...
466
  static size_t fuse_send_read(struct fuse_req *req, struct file *file,
2106cb189   Miklos Szeredi   fuse: don't use i...
467
  			     loff_t pos, size_t count, fl_owner_t owner)
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
468
  {
2106cb189   Miklos Szeredi   fuse: don't use i...
469
470
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
f33321141   Miklos Szeredi   fuse: add support...
471

2106cb189   Miklos Szeredi   fuse: don't use i...
472
  	fuse_read_fill(req, file, pos, count, FUSE_READ);
f33321141   Miklos Szeredi   fuse: add support...
473
  	if (owner != NULL) {
5c5c5e51b   Miklos Szeredi   fuse: update file...
474
  		struct fuse_read_in *inarg = &req->misc.read.in;
f33321141   Miklos Szeredi   fuse: add support...
475
476
477
478
  
  		inarg->read_flags |= FUSE_READ_LOCKOWNER;
  		inarg->lock_owner = fuse_lock_owner_id(fc, owner);
  	}
b93f858ab   Tejun Heo   fuse: add fuse_ p...
479
  	fuse_request_send(fc, req);
361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
480
  	return req->out.args[0].size;
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
481
  }
5c5c5e51b   Miklos Szeredi   fuse: update file...
482
483
484
485
486
487
488
489
490
491
492
493
494
  static void fuse_read_update_size(struct inode *inode, loff_t size,
  				  u64 attr_ver)
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  
  	spin_lock(&fc->lock);
  	if (attr_ver == fi->attr_version && size < inode->i_size) {
  		fi->attr_version = ++fc->attr_version;
  		i_size_write(inode, size);
  	}
  	spin_unlock(&fc->lock);
  }
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
495
496
497
498
  static int fuse_readpage(struct file *file, struct page *page)
  {
  	struct inode *inode = page->mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
499
  	struct fuse_req *req;
5c5c5e51b   Miklos Szeredi   fuse: update file...
500
501
502
503
  	size_t num_read;
  	loff_t pos = page_offset(page);
  	size_t count = PAGE_CACHE_SIZE;
  	u64 attr_ver;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
504
505
506
507
508
  	int err;
  
  	err = -EIO;
  	if (is_bad_inode(inode))
  		goto out;
3be5a52b3   Miklos Szeredi   fuse: support wri...
509
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
510
  	 * Page writeback can extend beyond the lifetime of the
3be5a52b3   Miklos Szeredi   fuse: support wri...
511
512
513
514
  	 * page-cache page, so make sure we read a properly synced
  	 * page.
  	 */
  	fuse_wait_on_page_writeback(inode, page->index);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
515
516
517
  	req = fuse_get_req(fc);
  	err = PTR_ERR(req);
  	if (IS_ERR(req))
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
518
  		goto out;
5c5c5e51b   Miklos Szeredi   fuse: update file...
519
  	attr_ver = fuse_get_attr_version(fc);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
520
  	req->out.page_zeroing = 1;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
521
  	req->out.argpages = 1;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
522
523
  	req->num_pages = 1;
  	req->pages[0] = page;
2106cb189   Miklos Szeredi   fuse: don't use i...
524
  	num_read = fuse_send_read(req, file, pos, count, NULL);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
525
526
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
5c5c5e51b   Miklos Szeredi   fuse: update file...
527
528
529
530
531
532
533
  
  	if (!err) {
  		/*
  		 * Short read means EOF.  If file size is larger, truncate it
  		 */
  		if (num_read < count)
  			fuse_read_update_size(inode, pos + num_read, attr_ver);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
534
  		SetPageUptodate(page);
5c5c5e51b   Miklos Szeredi   fuse: update file...
535
  	}
b36c31ba9   Miklos Szeredi   [PATCH] fuse: don...
536
  	fuse_invalidate_attr(inode); /* atime changed */
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
537
538
539
540
   out:
  	unlock_page(page);
  	return err;
  }
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
541
  static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
542
  {
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
543
  	int i;
5c5c5e51b   Miklos Szeredi   fuse: update file...
544
545
  	size_t count = req->misc.read.in.size;
  	size_t num_read = req->out.args[0].size;
ce534fb05   Miklos Szeredi   fuse: allow splic...
546
  	struct address_space *mapping = NULL;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
547

ce534fb05   Miklos Szeredi   fuse: allow splic...
548
549
  	for (i = 0; mapping == NULL && i < req->num_pages; i++)
  		mapping = req->pages[i]->mapping;
5c5c5e51b   Miklos Szeredi   fuse: update file...
550

ce534fb05   Miklos Szeredi   fuse: allow splic...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  	if (mapping) {
  		struct inode *inode = mapping->host;
  
  		/*
  		 * Short read means EOF. If file size is larger, truncate it
  		 */
  		if (!req->out.h.error && num_read < count) {
  			loff_t pos;
  
  			pos = page_offset(req->pages[0]) + num_read;
  			fuse_read_update_size(inode, pos,
  					      req->misc.read.attr_ver);
  		}
  		fuse_invalidate_attr(inode); /* atime changed */
  	}
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
566

db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
567
568
569
570
  	for (i = 0; i < req->num_pages; i++) {
  		struct page *page = req->pages[i];
  		if (!req->out.h.error)
  			SetPageUptodate(page);
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
571
572
  		else
  			SetPageError(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
573
  		unlock_page(page);
b5dd32853   Miklos Szeredi   fuse: get page re...
574
  		page_cache_release(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
575
  	}
c756e0a4d   Miklos Szeredi   fuse: add referen...
576
  	if (req->ff)
5a18ec176   Miklos Szeredi   fuse: fix hang of...
577
  		fuse_file_put(req->ff, false);
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
578
  }
2106cb189   Miklos Szeredi   fuse: don't use i...
579
  static void fuse_send_readpages(struct fuse_req *req, struct file *file)
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
580
  {
2106cb189   Miklos Szeredi   fuse: don't use i...
581
582
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
583
584
  	loff_t pos = page_offset(req->pages[0]);
  	size_t count = req->num_pages << PAGE_CACHE_SHIFT;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
585
586
  
  	req->out.argpages = 1;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
587
  	req->out.page_zeroing = 1;
ce534fb05   Miklos Szeredi   fuse: allow splic...
588
  	req->out.page_replace = 1;
2106cb189   Miklos Szeredi   fuse: don't use i...
589
  	fuse_read_fill(req, file, pos, count, FUSE_READ);
5c5c5e51b   Miklos Szeredi   fuse: update file...
590
  	req->misc.read.attr_ver = fuse_get_attr_version(fc);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
591
  	if (fc->async_read) {
c756e0a4d   Miklos Szeredi   fuse: add referen...
592
  		req->ff = fuse_file_get(ff);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
593
  		req->end = fuse_readpages_end;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
594
  		fuse_request_send_background(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
595
  	} else {
b93f858ab   Tejun Heo   fuse: add fuse_ p...
596
  		fuse_request_send(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
597
  		fuse_readpages_end(fc, req);
e9bb09dd6   Tejun Heo   fuse: don't let f...
598
  		fuse_put_request(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
599
  	}
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
600
  }
c756e0a4d   Miklos Szeredi   fuse: add referen...
601
  struct fuse_fill_data {
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
602
  	struct fuse_req *req;
a6643094e   Miklos Szeredi   fuse: pass open f...
603
  	struct file *file;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
604
605
606
607
608
  	struct inode *inode;
  };
  
  static int fuse_readpages_fill(void *_data, struct page *page)
  {
c756e0a4d   Miklos Szeredi   fuse: add referen...
609
  	struct fuse_fill_data *data = _data;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
610
611
612
  	struct fuse_req *req = data->req;
  	struct inode *inode = data->inode;
  	struct fuse_conn *fc = get_fuse_conn(inode);
3be5a52b3   Miklos Szeredi   fuse: support wri...
613
  	fuse_wait_on_page_writeback(inode, page->index);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
614
615
616
617
  	if (req->num_pages &&
  	    (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
  	     (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
  	     req->pages[req->num_pages - 1]->index + 1 != page->index)) {
2106cb189   Miklos Szeredi   fuse: don't use i...
618
  		fuse_send_readpages(req, data->file);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
619
620
  		data->req = req = fuse_get_req(fc);
  		if (IS_ERR(req)) {
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
621
  			unlock_page(page);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
622
  			return PTR_ERR(req);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
623
  		}
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
624
  	}
b5dd32853   Miklos Szeredi   fuse: get page re...
625
  	page_cache_get(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
626
  	req->pages[req->num_pages] = page;
1729a16c2   Miklos Szeredi   fuse: style fixes
627
  	req->num_pages++;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
628
629
630
631
632
633
634
635
  	return 0;
  }
  
  static int fuse_readpages(struct file *file, struct address_space *mapping,
  			  struct list_head *pages, unsigned nr_pages)
  {
  	struct inode *inode = mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
c756e0a4d   Miklos Szeredi   fuse: add referen...
636
  	struct fuse_fill_data data;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
637
  	int err;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
638

1d7ea7324   Alexander Zarochentsev   [PATCH] fuse: fix...
639
  	err = -EIO;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
640
  	if (is_bad_inode(inode))
2e990021b   OGAWA Hirofumi   [PATCH] fuse: ->r...
641
  		goto out;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
642

a6643094e   Miklos Szeredi   fuse: pass open f...
643
  	data.file = file;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
644
  	data.inode = inode;
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
645
  	data.req = fuse_get_req(fc);
1d7ea7324   Alexander Zarochentsev   [PATCH] fuse: fix...
646
  	err = PTR_ERR(data.req);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
647
  	if (IS_ERR(data.req))
2e990021b   OGAWA Hirofumi   [PATCH] fuse: ->r...
648
  		goto out;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
649
650
  
  	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
d3406ffa4   Miklos Szeredi   [PATCH] fuse: fix...
651
652
  	if (!err) {
  		if (data.req->num_pages)
2106cb189   Miklos Szeredi   fuse: don't use i...
653
  			fuse_send_readpages(data.req, file);
d3406ffa4   Miklos Szeredi   [PATCH] fuse: fix...
654
655
656
  		else
  			fuse_put_request(fc, data.req);
  	}
2e990021b   OGAWA Hirofumi   [PATCH] fuse: ->r...
657
  out:
1d7ea7324   Alexander Zarochentsev   [PATCH] fuse: fix...
658
  	return err;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
659
  }
bcb4be809   Miklos Szeredi   fuse: fix reading...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
  				  unsigned long nr_segs, loff_t pos)
  {
  	struct inode *inode = iocb->ki_filp->f_mapping->host;
  
  	if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) {
  		int err;
  		/*
  		 * If trying to read past EOF, make sure the i_size
  		 * attribute is up-to-date.
  		 */
  		err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL);
  		if (err)
  			return err;
  	}
  
  	return generic_file_aio_read(iocb, iov, nr_segs, pos);
  }
2d698b070   Miklos Szeredi   fuse: clean up fu...
678
  static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
2106cb189   Miklos Szeredi   fuse: don't use i...
679
  			    loff_t pos, size_t count)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
680
  {
b25e82e56   Miklos Szeredi   fuse: add helper ...
681
682
  	struct fuse_write_in *inarg = &req->misc.write.in;
  	struct fuse_write_out *outarg = &req->misc.write.out;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
683

b25e82e56   Miklos Szeredi   fuse: add helper ...
684
685
686
  	inarg->fh = ff->fh;
  	inarg->offset = pos;
  	inarg->size = count;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
687
  	req->in.h.opcode = FUSE_WRITE;
2106cb189   Miklos Szeredi   fuse: don't use i...
688
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
689
  	req->in.numargs = 2;
2106cb189   Miklos Szeredi   fuse: don't use i...
690
  	if (ff->fc->minor < 9)
f33321141   Miklos Szeredi   fuse: add support...
691
692
693
  		req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
  	else
  		req->in.args[0].size = sizeof(struct fuse_write_in);
b25e82e56   Miklos Szeredi   fuse: add helper ...
694
  	req->in.args[0].value = inarg;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
695
696
697
  	req->in.args[1].size = count;
  	req->out.numargs = 1;
  	req->out.args[0].size = sizeof(struct fuse_write_out);
b25e82e56   Miklos Szeredi   fuse: add helper ...
698
699
700
701
  	req->out.args[0].value = outarg;
  }
  
  static size_t fuse_send_write(struct fuse_req *req, struct file *file,
2106cb189   Miklos Szeredi   fuse: don't use i...
702
  			      loff_t pos, size_t count, fl_owner_t owner)
b25e82e56   Miklos Szeredi   fuse: add helper ...
703
  {
2106cb189   Miklos Szeredi   fuse: don't use i...
704
705
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
2d698b070   Miklos Szeredi   fuse: clean up fu...
706
  	struct fuse_write_in *inarg = &req->misc.write.in;
2106cb189   Miklos Szeredi   fuse: don't use i...
707
  	fuse_write_fill(req, ff, pos, count);
2d698b070   Miklos Szeredi   fuse: clean up fu...
708
  	inarg->flags = file->f_flags;
f33321141   Miklos Szeredi   fuse: add support...
709
  	if (owner != NULL) {
f33321141   Miklos Szeredi   fuse: add support...
710
711
712
  		inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
  		inarg->lock_owner = fuse_lock_owner_id(fc, owner);
  	}
b93f858ab   Tejun Heo   fuse: add fuse_ p...
713
  	fuse_request_send(fc, req);
b25e82e56   Miklos Szeredi   fuse: add helper ...
714
  	return req->misc.write.out.size;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
715
  }
a1d75f258   Miklos Szeredi   fuse: add store r...
716
  void fuse_write_update_size(struct inode *inode, loff_t pos)
854512ec3   Miklos Szeredi   fuse: clean up se...
717
718
719
720
721
722
723
724
725
726
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  
  	spin_lock(&fc->lock);
  	fi->attr_version = ++fc->attr_version;
  	if (pos > inode->i_size)
  		i_size_write(inode, pos);
  	spin_unlock(&fc->lock);
  }
ea9b9907b   Nick Piggin   fuse: implement p...
727
728
729
730
731
732
733
734
735
736
  static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
  				    struct inode *inode, loff_t pos,
  				    size_t count)
  {
  	size_t res;
  	unsigned offset;
  	unsigned i;
  
  	for (i = 0; i < req->num_pages; i++)
  		fuse_wait_on_page_writeback(inode, req->pages[i]->index);
2106cb189   Miklos Szeredi   fuse: don't use i...
737
  	res = fuse_send_write(req, file, pos, count, NULL);
ea9b9907b   Nick Piggin   fuse: implement p...
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
  
  	offset = req->page_offset;
  	count = res;
  	for (i = 0; i < req->num_pages; i++) {
  		struct page *page = req->pages[i];
  
  		if (!req->out.h.error && !offset && count >= PAGE_CACHE_SIZE)
  			SetPageUptodate(page);
  
  		if (count > PAGE_CACHE_SIZE - offset)
  			count -= PAGE_CACHE_SIZE - offset;
  		else
  			count = 0;
  		offset = 0;
  
  		unlock_page(page);
  		page_cache_release(page);
  	}
  
  	return res;
  }
  
  static ssize_t fuse_fill_write_pages(struct fuse_req *req,
  			       struct address_space *mapping,
  			       struct iov_iter *ii, loff_t pos)
  {
  	struct fuse_conn *fc = get_fuse_conn(mapping->host);
  	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
  	size_t count = 0;
  	int err;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
768
  	req->in.argpages = 1;
ea9b9907b   Nick Piggin   fuse: implement p...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  	req->page_offset = offset;
  
  	do {
  		size_t tmp;
  		struct page *page;
  		pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  		size_t bytes = min_t(size_t, PAGE_CACHE_SIZE - offset,
  				     iov_iter_count(ii));
  
  		bytes = min_t(size_t, bytes, fc->max_write - count);
  
   again:
  		err = -EFAULT;
  		if (iov_iter_fault_in_readable(ii, bytes))
  			break;
  
  		err = -ENOMEM;
54566b2c1   Nick Piggin   fs: symlink write...
786
  		page = grab_cache_page_write_begin(mapping, index, 0);
ea9b9907b   Nick Piggin   fuse: implement p...
787
788
  		if (!page)
  			break;
931e80e4b   anfei zhou   mm: flush dcache ...
789
790
  		if (mapping_writably_mapped(mapping))
  			flush_dcache_page(page);
ea9b9907b   Nick Piggin   fuse: implement p...
791
792
793
794
  		pagefault_disable();
  		tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
  		pagefault_enable();
  		flush_dcache_page(page);
478e0841b   Johannes Weiner   fuse: mark pages ...
795
  		mark_page_accessed(page);
ea9b9907b   Nick Piggin   fuse: implement p...
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  		if (!tmp) {
  			unlock_page(page);
  			page_cache_release(page);
  			bytes = min(bytes, iov_iter_single_seg_count(ii));
  			goto again;
  		}
  
  		err = 0;
  		req->pages[req->num_pages] = page;
  		req->num_pages++;
  
  		iov_iter_advance(ii, tmp);
  		count += tmp;
  		pos += tmp;
  		offset += tmp;
  		if (offset == PAGE_CACHE_SIZE)
  			offset = 0;
78bb6cb9a   Miklos Szeredi   fuse: add flag to...
813
814
  		if (!fc->big_writes)
  			break;
ea9b9907b   Nick Piggin   fuse: implement p...
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  	} while (iov_iter_count(ii) && count < fc->max_write &&
  		 req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0);
  
  	return count > 0 ? count : err;
  }
  
  static ssize_t fuse_perform_write(struct file *file,
  				  struct address_space *mapping,
  				  struct iov_iter *ii, loff_t pos)
  {
  	struct inode *inode = mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int err = 0;
  	ssize_t res = 0;
  
  	if (is_bad_inode(inode))
  		return -EIO;
  
  	do {
  		struct fuse_req *req;
  		ssize_t count;
  
  		req = fuse_get_req(fc);
  		if (IS_ERR(req)) {
  			err = PTR_ERR(req);
  			break;
  		}
  
  		count = fuse_fill_write_pages(req, mapping, ii, pos);
  		if (count <= 0) {
  			err = count;
  		} else {
  			size_t num_written;
  
  			num_written = fuse_send_write_pages(req, file, inode,
  							    pos, count);
  			err = req->out.h.error;
  			if (!err) {
  				res += num_written;
  				pos += num_written;
  
  				/* break out of the loop on short write */
  				if (num_written != count)
  					err = -EIO;
  			}
  		}
  		fuse_put_request(fc, req);
  	} while (!err && iov_iter_count(ii));
  
  	if (res > 0)
  		fuse_write_update_size(inode, pos);
  
  	fuse_invalidate_attr(inode);
  
  	return res > 0 ? res : err;
  }
  
  static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
  				   unsigned long nr_segs, loff_t pos)
  {
  	struct file *file = iocb->ki_filp;
  	struct address_space *mapping = file->f_mapping;
  	size_t count = 0;
  	ssize_t written = 0;
  	struct inode *inode = mapping->host;
  	ssize_t err;
  	struct iov_iter i;
  
  	WARN_ON(iocb->ki_pos != pos);
  
  	err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
  	if (err)
  		return err;
  
  	mutex_lock(&inode->i_mutex);
  	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
  
  	/* We can write back this queue in page reclaim */
  	current->backing_dev_info = mapping->backing_dev_info;
  
  	err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
  	if (err)
  		goto out;
  
  	if (count == 0)
  		goto out;
2f1936b87   Miklos Szeredi   [patch 3/5] vfs: ...
901
  	err = file_remove_suid(file);
ea9b9907b   Nick Piggin   fuse: implement p...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  	if (err)
  		goto out;
  
  	file_update_time(file);
  
  	iov_iter_init(&i, iov, nr_segs, count, 0);
  	written = fuse_perform_write(file, mapping, &i, pos);
  	if (written >= 0)
  		iocb->ki_pos = pos + written;
  
  out:
  	current->backing_dev_info = NULL;
  	mutex_unlock(&inode->i_mutex);
  
  	return written ? written : err;
  }
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
918
919
920
921
922
923
924
925
926
927
928
929
930
  static void fuse_release_user_pages(struct fuse_req *req, int write)
  {
  	unsigned i;
  
  	for (i = 0; i < req->num_pages; i++) {
  		struct page *page = req->pages[i];
  		if (write)
  			set_page_dirty_lock(page);
  		put_page(page);
  	}
  }
  
  static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
ce60a2f15   Miklos Szeredi   fuse: fix argumen...
931
  			       size_t *nbytesp, int write)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
932
  {
ce60a2f15   Miklos Szeredi   fuse: fix argumen...
933
  	size_t nbytes = *nbytesp;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
934
935
936
  	unsigned long user_addr = (unsigned long) buf;
  	unsigned offset = user_addr & ~PAGE_MASK;
  	int npages;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
937
938
939
940
941
942
943
944
945
  	/* Special case for kernel I/O: can copy directly into the buffer */
  	if (segment_eq(get_fs(), KERNEL_DS)) {
  		if (write)
  			req->in.args[1].value = (void *) user_addr;
  		else
  			req->out.args[0].value = (void *) user_addr;
  
  		return 0;
  	}
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
946

ce60a2f15   Miklos Szeredi   fuse: fix argumen...
947
  	nbytes = min_t(size_t, nbytes, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
948
  	npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
bd7309677   Harvey Harrison   fuse: use clamp()...
949
  	npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ);
1bf94ca73   Miklos Szeredi   fuse: use get_use...
950
  	npages = get_user_pages_fast(user_addr, npages, !write, req->pages);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
951
952
953
954
955
  	if (npages < 0)
  		return npages;
  
  	req->num_pages = npages;
  	req->page_offset = offset;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
956
957
958
959
960
961
962
963
  
  	if (write)
  		req->in.argpages = 1;
  	else
  		req->out.argpages = 1;
  
  	nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
  	*nbytesp = min(*nbytesp, nbytes);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
964
965
  	return 0;
  }
08cbf542b   Tejun Heo   fuse: export symb...
966
967
  ssize_t fuse_direct_io(struct file *file, const char __user *buf,
  		       size_t count, loff_t *ppos, int write)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
968
  {
2106cb189   Miklos Szeredi   fuse: don't use i...
969
970
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
971
972
973
  	size_t nmax = write ? fc->max_write : fc->max_read;
  	loff_t pos = *ppos;
  	ssize_t res = 0;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
974
  	struct fuse_req *req;
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
975
976
977
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
978
979
  
  	while (count) {
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
980
  		size_t nres;
2106cb189   Miklos Szeredi   fuse: don't use i...
981
  		fl_owner_t owner = current->files;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
982
983
  		size_t nbytes = min(count, nmax);
  		int err = fuse_get_user_pages(req, buf, &nbytes, write);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
984
985
986
987
  		if (err) {
  			res = err;
  			break;
  		}
f4975c67d   Miklos Szeredi   fuse: allow kerne...
988

413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
989
  		if (write)
2106cb189   Miklos Szeredi   fuse: don't use i...
990
  			nres = fuse_send_write(req, file, pos, nbytes, owner);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
991
  		else
2106cb189   Miklos Szeredi   fuse: don't use i...
992
  			nres = fuse_send_read(req, file, pos, nbytes, owner);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  		fuse_release_user_pages(req, !write);
  		if (req->out.h.error) {
  			if (!res)
  				res = req->out.h.error;
  			break;
  		} else if (nres > nbytes) {
  			res = -EIO;
  			break;
  		}
  		count -= nres;
  		res += nres;
  		pos += nres;
  		buf += nres;
  		if (nres != nbytes)
  			break;
56cf34ff0   Miklos Szeredi   [fuse] Direct I/O...
1008
1009
1010
1011
1012
1013
  		if (count) {
  			fuse_put_request(fc, req);
  			req = fuse_get_req(fc);
  			if (IS_ERR(req))
  				break;
  		}
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1014
  	}
f60311d5f   Anand V. Avati   fuse: prevent fus...
1015
1016
  	if (!IS_ERR(req))
  		fuse_put_request(fc, req);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1017
  	if (res > 0)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1018
  		*ppos = pos;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1019
1020
1021
  
  	return res;
  }
08cbf542b   Tejun Heo   fuse: export symb...
1022
  EXPORT_SYMBOL_GPL(fuse_direct_io);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1023
1024
1025
1026
  
  static ssize_t fuse_direct_read(struct file *file, char __user *buf,
  				     size_t count, loff_t *ppos)
  {
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  	ssize_t res;
  	struct inode *inode = file->f_path.dentry->d_inode;
  
  	if (is_bad_inode(inode))
  		return -EIO;
  
  	res = fuse_direct_io(file, buf, count, ppos, 0);
  
  	fuse_invalidate_attr(inode);
  
  	return res;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1038
1039
1040
1041
1042
  }
  
  static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
  				 size_t count, loff_t *ppos)
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
1043
  	struct inode *inode = file->f_path.dentry->d_inode;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1044
  	ssize_t res;
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1045
1046
1047
  
  	if (is_bad_inode(inode))
  		return -EIO;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1048
  	/* Don't allow parallel writes to the same file */
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
1049
  	mutex_lock(&inode->i_mutex);
889f78483   Miklos Szeredi   fuse: generic_wri...
1050
  	res = generic_write_checks(file, ppos, &count, 0);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1051
  	if (!res) {
889f78483   Miklos Szeredi   fuse: generic_wri...
1052
  		res = fuse_direct_io(file, buf, count, ppos, 1);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1053
1054
1055
  		if (res > 0)
  			fuse_write_update_size(inode, *ppos);
  	}
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
1056
  	mutex_unlock(&inode->i_mutex);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1057
1058
  
  	fuse_invalidate_attr(inode);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1059
1060
  	return res;
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1061
  static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1062
  {
3be5a52b3   Miklos Szeredi   fuse: support wri...
1063
  	__free_page(req->pages[0]);
5a18ec176   Miklos Szeredi   fuse: fix hang of...
1064
  	fuse_file_put(req->ff, false);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
  }
  
  static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
  {
  	struct inode *inode = req->inode;
  	struct fuse_inode *fi = get_fuse_inode(inode);
  	struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
  
  	list_del(&req->writepages_entry);
  	dec_bdi_stat(bdi, BDI_WRITEBACK);
  	dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
  	bdi_writeout_inc(bdi);
  	wake_up(&fi->page_waitq);
  }
  
  /* Called under fc->lock, may release and reacquire it */
  static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req)
b9ca67b2d   Miklos Szeredi   fuse: fix lock an...
1082
1083
  __releases(fc->lock)
  __acquires(fc->lock)
3be5a52b3   Miklos Szeredi   fuse: support wri...
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  {
  	struct fuse_inode *fi = get_fuse_inode(req->inode);
  	loff_t size = i_size_read(req->inode);
  	struct fuse_write_in *inarg = &req->misc.write.in;
  
  	if (!fc->connected)
  		goto out_free;
  
  	if (inarg->offset + PAGE_CACHE_SIZE <= size) {
  		inarg->size = PAGE_CACHE_SIZE;
  	} else if (inarg->offset < size) {
  		inarg->size = size & (PAGE_CACHE_SIZE - 1);
  	} else {
  		/* Got truncated off completely */
  		goto out_free;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1099
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1100
1101
1102
  
  	req->in.args[1].size = inarg->size;
  	fi->writectr++;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1103
  	fuse_request_send_background_locked(fc, req);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1104
1105
1106
1107
1108
1109
  	return;
  
   out_free:
  	fuse_writepage_finish(fc, req);
  	spin_unlock(&fc->lock);
  	fuse_writepage_free(fc, req);
e9bb09dd6   Tejun Heo   fuse: don't let f...
1110
  	fuse_put_request(fc, req);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1111
  	spin_lock(&fc->lock);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1112
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1113
1114
1115
1116
1117
1118
1119
  /*
   * If fi->writectr is positive (no truncate or fsync going on) send
   * all queued writepage requests.
   *
   * Called with fc->lock
   */
  void fuse_flush_writepages(struct inode *inode)
b9ca67b2d   Miklos Szeredi   fuse: fix lock an...
1120
1121
  __releases(fc->lock)
  __acquires(fc->lock)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1122
  {
3be5a52b3   Miklos Szeredi   fuse: support wri...
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  	struct fuse_req *req;
  
  	while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
  		req = list_entry(fi->queued_writes.next, struct fuse_req, list);
  		list_del_init(&req->list);
  		fuse_send_writepage(fc, req);
  	}
  }
  
  static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
  {
  	struct inode *inode = req->inode;
  	struct fuse_inode *fi = get_fuse_inode(inode);
  
  	mapping_set_error(inode->i_mapping, req->out.h.error);
  	spin_lock(&fc->lock);
  	fi->writectr--;
  	fuse_writepage_finish(fc, req);
  	spin_unlock(&fc->lock);
  	fuse_writepage_free(fc, req);
  }
  
  static int fuse_writepage_locked(struct page *page)
  {
  	struct address_space *mapping = page->mapping;
  	struct inode *inode = mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  	struct fuse_req *req;
  	struct fuse_file *ff;
  	struct page *tmp_page;
  
  	set_page_writeback(page);
  
  	req = fuse_request_alloc_nofs();
  	if (!req)
  		goto err;
  
  	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
  	if (!tmp_page)
  		goto err_free;
  
  	spin_lock(&fc->lock);
  	BUG_ON(list_empty(&fi->write_files));
  	ff = list_entry(fi->write_files.next, struct fuse_file, write_entry);
  	req->ff = fuse_file_get(ff);
  	spin_unlock(&fc->lock);
2106cb189   Miklos Szeredi   fuse: don't use i...
1172
  	fuse_write_fill(req, ff, page_offset(page), 0);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1173
1174
  
  	copy_highpage(tmp_page, page);
2d698b070   Miklos Szeredi   fuse: clean up fu...
1175
  	req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1176
  	req->in.argpages = 1;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
  	req->num_pages = 1;
  	req->pages[0] = tmp_page;
  	req->page_offset = 0;
  	req->end = fuse_writepage_end;
  	req->inode = inode;
  
  	inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
  	inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
  	end_page_writeback(page);
  
  	spin_lock(&fc->lock);
  	list_add(&req->writepages_entry, &fi->writepages);
  	list_add_tail(&req->list, &fi->queued_writes);
  	fuse_flush_writepages(inode);
  	spin_unlock(&fc->lock);
  
  	return 0;
  
  err_free:
  	fuse_request_free(req);
  err:
  	end_page_writeback(page);
  	return -ENOMEM;
  }
  
  static int fuse_writepage(struct page *page, struct writeback_control *wbc)
  {
  	int err;
  
  	err = fuse_writepage_locked(page);
  	unlock_page(page);
  
  	return err;
  }
  
  static int fuse_launder_page(struct page *page)
  {
  	int err = 0;
  	if (clear_page_dirty_for_io(page)) {
  		struct inode *inode = page->mapping->host;
  		err = fuse_writepage_locked(page);
  		if (!err)
  			fuse_wait_on_page_writeback(inode, page->index);
  	}
  	return err;
  }
  
  /*
   * Write back dirty pages now, because there may not be any suitable
   * open files later
   */
  static void fuse_vma_close(struct vm_area_struct *vma)
  {
  	filemap_write_and_wait(vma->vm_file->f_mapping);
  }
  
  /*
   * Wait for writeback against this page to complete before allowing it
   * to be marked dirty again, and hence written back again, possibly
   * before the previous writepage completed.
   *
   * Block here, instead of in ->writepage(), so that the userspace fs
   * can only block processes actually operating on the filesystem.
   *
   * Otherwise unprivileged userspace fs would be able to block
   * unrelated:
   *
   * - page migration
   * - sync(2)
   * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
   */
c2ec175c3   Nick Piggin   mm: page_mkwrite ...
1248
  static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
3be5a52b3   Miklos Szeredi   fuse: support wri...
1249
  {
c2ec175c3   Nick Piggin   mm: page_mkwrite ...
1250
  	struct page *page = vmf->page;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1251
1252
1253
1254
1255
1256
1257
1258
1259
  	/*
  	 * Don't use page->mapping as it may become NULL from a
  	 * concurrent truncate.
  	 */
  	struct inode *inode = vma->vm_file->f_mapping->host;
  
  	fuse_wait_on_page_writeback(inode, page->index);
  	return 0;
  }
f0f37e2f7   Alexey Dobriyan   const: mark struc...
1260
  static const struct vm_operations_struct fuse_file_vm_ops = {
3be5a52b3   Miklos Szeredi   fuse: support wri...
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
  	.close		= fuse_vma_close,
  	.fault		= filemap_fault,
  	.page_mkwrite	= fuse_page_mkwrite,
  };
  
  static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
  {
  	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
  		struct inode *inode = file->f_dentry->d_inode;
  		struct fuse_conn *fc = get_fuse_conn(inode);
  		struct fuse_inode *fi = get_fuse_inode(inode);
  		struct fuse_file *ff = file->private_data;
  		/*
  		 * file may be written through mmap, so chain it onto the
  		 * inodes's write_file list
  		 */
  		spin_lock(&fc->lock);
  		if (list_empty(&ff->write_entry))
  			list_add(&ff->write_entry, &fi->write_files);
  		spin_unlock(&fc->lock);
  	}
  	file_accessed(file);
  	vma->vm_ops = &fuse_file_vm_ops;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1284
1285
  	return 0;
  }
fc280c969   Miklos Szeredi   fuse: allow priva...
1286
1287
1288
1289
1290
  static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
  {
  	/* Can't provide the coherency needed for MAP_SHARED */
  	if (vma->vm_flags & VM_MAYSHARE)
  		return -ENODEV;
3121bfe76   Miklos Szeredi   fuse: fix "direct...
1291
  	invalidate_inode_pages2(file->f_mapping);
fc280c969   Miklos Szeredi   fuse: allow priva...
1292
1293
  	return generic_file_mmap(file, vma);
  }
714212593   Miklos Szeredi   [PATCH] fuse: add...
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
  				  struct file_lock *fl)
  {
  	switch (ffl->type) {
  	case F_UNLCK:
  		break;
  
  	case F_RDLCK:
  	case F_WRLCK:
  		if (ffl->start > OFFSET_MAX || ffl->end > OFFSET_MAX ||
  		    ffl->end < ffl->start)
  			return -EIO;
  
  		fl->fl_start = ffl->start;
  		fl->fl_end = ffl->end;
  		fl->fl_pid = ffl->pid;
  		break;
  
  	default:
  		return -EIO;
  	}
  	fl->fl_type = ffl->type;
  	return 0;
  }
  
  static void fuse_lk_fill(struct fuse_req *req, struct file *file,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1320
1321
  			 const struct file_lock *fl, int opcode, pid_t pid,
  			 int flock)
714212593   Miklos Szeredi   [PATCH] fuse: add...
1322
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
1323
  	struct inode *inode = file->f_path.dentry->d_inode;
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
1324
  	struct fuse_conn *fc = get_fuse_conn(inode);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1325
1326
1327
1328
  	struct fuse_file *ff = file->private_data;
  	struct fuse_lk_in *arg = &req->misc.lk_in;
  
  	arg->fh = ff->fh;
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
1329
  	arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1330
1331
1332
1333
  	arg->lk.start = fl->fl_start;
  	arg->lk.end = fl->fl_end;
  	arg->lk.type = fl->fl_type;
  	arg->lk.pid = pid;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1334
1335
  	if (flock)
  		arg->lk_flags |= FUSE_LK_FLOCK;
714212593   Miklos Szeredi   [PATCH] fuse: add...
1336
1337
1338
1339
1340
1341
1342
1343
1344
  	req->in.h.opcode = opcode;
  	req->in.h.nodeid = get_node_id(inode);
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(*arg);
  	req->in.args[0].value = arg;
  }
  
  static int fuse_getlk(struct file *file, struct file_lock *fl)
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
1345
  	struct inode *inode = file->f_path.dentry->d_inode;
714212593   Miklos Szeredi   [PATCH] fuse: add...
1346
1347
1348
1349
1350
1351
1352
1353
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_req *req;
  	struct fuse_lk_out outarg;
  	int err;
  
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1354
  	fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1355
1356
1357
  	req->out.numargs = 1;
  	req->out.args[0].size = sizeof(outarg);
  	req->out.args[0].value = &outarg;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1358
  	fuse_request_send(fc, req);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1359
1360
1361
1362
1363
1364
1365
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  	if (!err)
  		err = convert_fuse_file_lock(&outarg.lk, fl);
  
  	return err;
  }
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1366
  static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
714212593   Miklos Szeredi   [PATCH] fuse: add...
1367
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
1368
  	struct inode *inode = file->f_path.dentry->d_inode;
714212593   Miklos Szeredi   [PATCH] fuse: add...
1369
1370
1371
1372
1373
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_req *req;
  	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
  	pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
  	int err;
8fb47a4fb   J. Bruce Fields   locks: rename loc...
1374
  	if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
48e90761b   Miklos Szeredi   fuse: lockd support
1375
1376
1377
  		/* NLM needs asynchronous locks, which we don't support yet */
  		return -ENOLCK;
  	}
714212593   Miklos Szeredi   [PATCH] fuse: add...
1378
1379
1380
1381
1382
1383
1384
  	/* Unlock on close is handled by the flush method */
  	if (fl->fl_flags & FL_CLOSE)
  		return 0;
  
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1385
  	fuse_lk_fill(req, file, fl, opcode, pid, flock);
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1386
  	fuse_request_send(fc, req);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1387
  	err = req->out.h.error;
a4d27e75f   Miklos Szeredi   [PATCH] fuse: add...
1388
1389
1390
  	/* locking is restartable */
  	if (err == -EINTR)
  		err = -ERESTARTSYS;
714212593   Miklos Szeredi   [PATCH] fuse: add...
1391
1392
1393
1394
1395
1396
  	fuse_put_request(fc, req);
  	return err;
  }
  
  static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
  {
7706a9d61   Josef Sipek   [PATCH] struct pa...
1397
  	struct inode *inode = file->f_path.dentry->d_inode;
714212593   Miklos Szeredi   [PATCH] fuse: add...
1398
1399
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int err;
48e90761b   Miklos Szeredi   fuse: lockd support
1400
1401
1402
  	if (cmd == F_CANCELLK) {
  		err = 0;
  	} else if (cmd == F_GETLK) {
714212593   Miklos Szeredi   [PATCH] fuse: add...
1403
  		if (fc->no_lock) {
9d6a8c5c2   Marc Eshel   locks: give posix...
1404
  			posix_test_lock(file, fl);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1405
1406
1407
1408
1409
  			err = 0;
  		} else
  			err = fuse_getlk(file, fl);
  	} else {
  		if (fc->no_lock)
48e90761b   Miklos Szeredi   fuse: lockd support
1410
  			err = posix_lock_file(file, fl, NULL);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1411
  		else
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1412
  			err = fuse_setlk(file, fl, 0);
714212593   Miklos Szeredi   [PATCH] fuse: add...
1413
1414
1415
  	}
  	return err;
  }
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1416
1417
1418
1419
1420
  static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
  {
  	struct inode *inode = file->f_path.dentry->d_inode;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int err;
37fb3a30b   Miklos Szeredi   fuse: fix flock
1421
  	if (fc->no_flock) {
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1422
1423
  		err = flock_lock_file_wait(file, fl);
  	} else {
37fb3a30b   Miklos Szeredi   fuse: fix flock
1424
  		struct fuse_file *ff = file->private_data;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1425
1426
  		/* emulate flock with POSIX locks */
  		fl->fl_owner = (fl_owner_t) file;
37fb3a30b   Miklos Szeredi   fuse: fix flock
1427
  		ff->flock = true;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1428
1429
1430
1431
1432
  		err = fuse_setlk(file, fl, 1);
  	}
  
  	return err;
  }
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
  static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
  {
  	struct inode *inode = mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_req *req;
  	struct fuse_bmap_in inarg;
  	struct fuse_bmap_out outarg;
  	int err;
  
  	if (!inode->i_sb->s_bdev || fc->no_bmap)
  		return 0;
  
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
  		return 0;
  
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.block = block;
  	inarg.blocksize = inode->i_sb->s_blocksize;
  	req->in.h.opcode = FUSE_BMAP;
  	req->in.h.nodeid = get_node_id(inode);
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
  	req->out.numargs = 1;
  	req->out.args[0].size = sizeof(outarg);
  	req->out.args[0].value = &outarg;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1460
  	fuse_request_send(fc, req);
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
1461
1462
1463
1464
1465
1466
1467
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  	if (err == -ENOSYS)
  		fc->no_bmap = 1;
  
  	return err ? 0 : outarg.block;
  }
5559b8f4d   Miklos Szeredi   fuse: fix race in...
1468
1469
1470
1471
  static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
  {
  	loff_t retval;
  	struct inode *inode = file->f_path.dentry->d_inode;
c07c3d193   Miklos Szeredi   fuse: llseek opti...
1472
1473
1474
  	/* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
  	if (origin == SEEK_CUR || origin == SEEK_SET)
  		return generic_file_llseek(file, offset, origin);
06222e491   Josef Bacik   fs: handle SEEK_H...
1475

c07c3d193   Miklos Szeredi   fuse: llseek opti...
1476
1477
1478
1479
  	mutex_lock(&inode->i_mutex);
  	retval = fuse_update_attributes(inode, NULL, file, NULL);
  	if (!retval)
  		retval = generic_file_llseek(file, offset, origin);
5559b8f4d   Miklos Szeredi   fuse: fix race in...
1480
  	mutex_unlock(&inode->i_mutex);
c07c3d193   Miklos Szeredi   fuse: llseek opti...
1481

5559b8f4d   Miklos Szeredi   fuse: fix race in...
1482
1483
  	return retval;
  }
59efec7b9   Tejun Heo   fuse: implement i...
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
  			unsigned int nr_segs, size_t bytes, bool to_user)
  {
  	struct iov_iter ii;
  	int page_idx = 0;
  
  	if (!bytes)
  		return 0;
  
  	iov_iter_init(&ii, iov, nr_segs, bytes, 0);
  
  	while (iov_iter_count(&ii)) {
  		struct page *page = pages[page_idx++];
  		size_t todo = min_t(size_t, PAGE_SIZE, iov_iter_count(&ii));
4aa0edd29   Dan Carpenter   fuse: remove unne...
1498
  		void *kaddr;
59efec7b9   Tejun Heo   fuse: implement i...
1499

4aa0edd29   Dan Carpenter   fuse: remove unne...
1500
  		kaddr = kmap(page);
59efec7b9   Tejun Heo   fuse: implement i...
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  
  		while (todo) {
  			char __user *uaddr = ii.iov->iov_base + ii.iov_offset;
  			size_t iov_len = ii.iov->iov_len - ii.iov_offset;
  			size_t copy = min(todo, iov_len);
  			size_t left;
  
  			if (!to_user)
  				left = copy_from_user(kaddr, uaddr, copy);
  			else
  				left = copy_to_user(uaddr, kaddr, copy);
  
  			if (unlikely(left))
  				return -EFAULT;
  
  			iov_iter_advance(&ii, copy);
  			todo -= copy;
  			kaddr += copy;
  		}
0bd87182d   Jens Axboe   fuse: fix kunmap ...
1520
  		kunmap(page);
59efec7b9   Tejun Heo   fuse: implement i...
1521
1522
1523
1524
1525
1526
  	}
  
  	return 0;
  }
  
  /*
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
1527
1528
1529
1530
1531
   * CUSE servers compiled on 32bit broke on 64bit kernels because the
   * ABI was defined to be 'struct iovec' which is different on 32bit
   * and 64bit.  Fortunately we can determine which structure the server
   * used from the size of the reply.
   */
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
1532
1533
1534
  static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src,
  				     size_t transferred, unsigned count,
  				     bool is_compat)
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
  {
  #ifdef CONFIG_COMPAT
  	if (count * sizeof(struct compat_iovec) == transferred) {
  		struct compat_iovec *ciov = src;
  		unsigned i;
  
  		/*
  		 * With this interface a 32bit server cannot support
  		 * non-compat (i.e. ones coming from 64bit apps) ioctl
  		 * requests
  		 */
  		if (!is_compat)
  			return -EINVAL;
  
  		for (i = 0; i < count; i++) {
  			dst[i].iov_base = compat_ptr(ciov[i].iov_base);
  			dst[i].iov_len = ciov[i].iov_len;
  		}
  		return 0;
  	}
  #endif
  
  	if (count * sizeof(struct iovec) != transferred)
  		return -EIO;
  
  	memcpy(dst, src, transferred);
  	return 0;
  }
7572777ee   Miklos Szeredi   fuse: verify ioct...
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
  /* Make sure iov_length() won't overflow */
  static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
  {
  	size_t n;
  	u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
  
  	for (n = 0; n < count; n++) {
  		if (iov->iov_len > (size_t) max)
  			return -ENOMEM;
  		max -= iov->iov_len;
  	}
  	return 0;
  }
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
  static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,
  				 void *src, size_t transferred, unsigned count,
  				 bool is_compat)
  {
  	unsigned i;
  	struct fuse_ioctl_iovec *fiov = src;
  
  	if (fc->minor < 16) {
  		return fuse_copy_ioctl_iovec_old(dst, src, transferred,
  						 count, is_compat);
  	}
  
  	if (count * sizeof(struct fuse_ioctl_iovec) != transferred)
  		return -EIO;
  
  	for (i = 0; i < count; i++) {
  		/* Did the server supply an inappropriate value? */
  		if (fiov[i].base != (unsigned long) fiov[i].base ||
  		    fiov[i].len != (unsigned long) fiov[i].len)
  			return -EIO;
  
  		dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base;
  		dst[i].iov_len = (size_t) fiov[i].len;
  
  #ifdef CONFIG_COMPAT
  		if (is_compat &&
  		    (ptr_to_compat(dst[i].iov_base) != fiov[i].base ||
  		     (compat_size_t) dst[i].iov_len != fiov[i].len))
  			return -EIO;
  #endif
  	}
  
  	return 0;
  }
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
1610
  /*
59efec7b9   Tejun Heo   fuse: implement i...
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
   * For ioctls, there is no generic way to determine how much memory
   * needs to be read and/or written.  Furthermore, ioctls are allowed
   * to dereference the passed pointer, so the parameter requires deep
   * copying but FUSE has no idea whatsoever about what to copy in or
   * out.
   *
   * This is solved by allowing FUSE server to retry ioctl with
   * necessary in/out iovecs.  Let's assume the ioctl implementation
   * needs to read in the following structure.
   *
   * struct a {
   *	char	*buf;
   *	size_t	buflen;
   * }
   *
   * On the first callout to FUSE server, inarg->in_size and
   * inarg->out_size will be NULL; then, the server completes the ioctl
   * with FUSE_IOCTL_RETRY set in out->flags, out->in_iovs set to 1 and
   * the actual iov array to
   *
   * { { .iov_base = inarg.arg,	.iov_len = sizeof(struct a) } }
   *
   * which tells FUSE to copy in the requested area and retry the ioctl.
   * On the second round, the server has access to the structure and
   * from that it can tell what to look for next, so on the invocation,
   * it sets FUSE_IOCTL_RETRY, out->in_iovs to 2 and iov array to
   *
   * { { .iov_base = inarg.arg,	.iov_len = sizeof(struct a)	},
   *   { .iov_base = a.buf,	.iov_len = a.buflen		} }
   *
   * FUSE will copy both struct a and the pointed buffer from the
   * process doing the ioctl and retry ioctl with both struct a and the
   * buffer.
   *
   * This time, FUSE server has everything it needs and completes ioctl
   * without FUSE_IOCTL_RETRY which finishes the ioctl call.
   *
   * Copying data out works the same way.
   *
   * Note that if FUSE_IOCTL_UNRESTRICTED is clear, the kernel
   * automatically initializes in and out iovs by decoding @cmd with
   * _IOC_* macros and the server is not allowed to request RETRY.  This
   * limits ioctl data transfers to well-formed ioctls and is the forced
   * behavior for all FUSE servers.
   */
08cbf542b   Tejun Heo   fuse: export symb...
1656
1657
  long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
  		   unsigned int flags)
59efec7b9   Tejun Heo   fuse: implement i...
1658
  {
59efec7b9   Tejun Heo   fuse: implement i...
1659
  	struct fuse_file *ff = file->private_data;
d36f24871   Miklos Szeredi   fuse: don't use i...
1660
  	struct fuse_conn *fc = ff->fc;
59efec7b9   Tejun Heo   fuse: implement i...
1661
1662
1663
1664
1665
1666
1667
1668
1669
  	struct fuse_ioctl_in inarg = {
  		.fh = ff->fh,
  		.cmd = cmd,
  		.arg = arg,
  		.flags = flags
  	};
  	struct fuse_ioctl_out outarg;
  	struct fuse_req *req = NULL;
  	struct page **pages = NULL;
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1670
  	struct iovec *iov_page = NULL;
59efec7b9   Tejun Heo   fuse: implement i...
1671
1672
1673
1674
  	struct iovec *in_iov = NULL, *out_iov = NULL;
  	unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages;
  	size_t in_size, out_size, transferred;
  	int err;
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
1675
1676
1677
1678
1679
1680
  #if BITS_PER_LONG == 32
  	inarg.flags |= FUSE_IOCTL_32BIT;
  #else
  	if (flags & FUSE_IOCTL_COMPAT)
  		inarg.flags |= FUSE_IOCTL_32BIT;
  #endif
59efec7b9   Tejun Heo   fuse: implement i...
1681
  	/* assume all the iovs returned by client always fits in a page */
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
1682
  	BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
59efec7b9   Tejun Heo   fuse: implement i...
1683

59efec7b9   Tejun Heo   fuse: implement i...
1684
  	err = -ENOMEM;
c411cc88d   Thomas Meyer   fuse: Use kcalloc...
1685
  	pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, sizeof(pages[0]), GFP_KERNEL);
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1686
  	iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
59efec7b9   Tejun Heo   fuse: implement i...
1687
1688
1689
1690
1691
1692
1693
1694
  	if (!pages || !iov_page)
  		goto out;
  
  	/*
  	 * If restricted, initialize IO parameters as encoded in @cmd.
  	 * RETRY from server is not allowed.
  	 */
  	if (!(flags & FUSE_IOCTL_UNRESTRICTED)) {
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1695
  		struct iovec *iov = iov_page;
59efec7b9   Tejun Heo   fuse: implement i...
1696

c9f0523d8   Miklos Szeredi   fuse: fix sparse ...
1697
  		iov->iov_base = (void __user *)arg;
59efec7b9   Tejun Heo   fuse: implement i...
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
  		iov->iov_len = _IOC_SIZE(cmd);
  
  		if (_IOC_DIR(cmd) & _IOC_WRITE) {
  			in_iov = iov;
  			in_iovs = 1;
  		}
  
  		if (_IOC_DIR(cmd) & _IOC_READ) {
  			out_iov = iov;
  			out_iovs = 1;
  		}
  	}
  
   retry:
  	inarg.in_size = in_size = iov_length(in_iov, in_iovs);
  	inarg.out_size = out_size = iov_length(out_iov, out_iovs);
  
  	/*
  	 * Out data can be used either for actual out data or iovs,
  	 * make sure there always is at least one page.
  	 */
  	out_size = max_t(size_t, out_size, PAGE_SIZE);
  	max_pages = DIV_ROUND_UP(max(in_size, out_size), PAGE_SIZE);
  
  	/* make sure there are enough buffer pages and init request with them */
  	err = -ENOMEM;
  	if (max_pages > FUSE_MAX_PAGES_PER_REQ)
  		goto out;
  	while (num_pages < max_pages) {
  		pages[num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
  		if (!pages[num_pages])
  			goto out;
  		num_pages++;
  	}
  
  	req = fuse_get_req(fc);
  	if (IS_ERR(req)) {
  		err = PTR_ERR(req);
  		req = NULL;
  		goto out;
  	}
  	memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages);
  	req->num_pages = num_pages;
  
  	/* okay, let's send it to the client */
  	req->in.h.opcode = FUSE_IOCTL;
d36f24871   Miklos Szeredi   fuse: don't use i...
1744
  	req->in.h.nodeid = ff->nodeid;
59efec7b9   Tejun Heo   fuse: implement i...
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
  	if (in_size) {
  		req->in.numargs++;
  		req->in.args[1].size = in_size;
  		req->in.argpages = 1;
  
  		err = fuse_ioctl_copy_user(pages, in_iov, in_iovs, in_size,
  					   false);
  		if (err)
  			goto out;
  	}
  
  	req->out.numargs = 2;
  	req->out.args[0].size = sizeof(outarg);
  	req->out.args[0].value = &outarg;
  	req->out.args[1].size = out_size;
  	req->out.argpages = 1;
  	req->out.argvar = 1;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1765
  	fuse_request_send(fc, req);
59efec7b9   Tejun Heo   fuse: implement i...
1766
1767
1768
1769
1770
1771
1772
1773
1774
  	err = req->out.h.error;
  	transferred = req->out.args[1].size;
  	fuse_put_request(fc, req);
  	req = NULL;
  	if (err)
  		goto out;
  
  	/* did it ask for retry? */
  	if (outarg.flags & FUSE_IOCTL_RETRY) {
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1775
  		void *vaddr;
59efec7b9   Tejun Heo   fuse: implement i...
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
  
  		/* no retry if in restricted mode */
  		err = -EIO;
  		if (!(flags & FUSE_IOCTL_UNRESTRICTED))
  			goto out;
  
  		in_iovs = outarg.in_iovs;
  		out_iovs = outarg.out_iovs;
  
  		/*
  		 * Make sure things are in boundary, separate checks
  		 * are to protect against overflow.
  		 */
  		err = -ENOMEM;
  		if (in_iovs > FUSE_IOCTL_MAX_IOV ||
  		    out_iovs > FUSE_IOCTL_MAX_IOV ||
  		    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
  			goto out;
59efec7b9   Tejun Heo   fuse: implement i...
1794
  		vaddr = kmap_atomic(pages[0], KM_USER0);
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
1795
  		err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr,
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
1796
1797
  					    transferred, in_iovs + out_iovs,
  					    (flags & FUSE_IOCTL_COMPAT) != 0);
59efec7b9   Tejun Heo   fuse: implement i...
1798
  		kunmap_atomic(vaddr, KM_USER0);
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
1799
1800
  		if (err)
  			goto out;
59efec7b9   Tejun Heo   fuse: implement i...
1801

8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1802
  		in_iov = iov_page;
59efec7b9   Tejun Heo   fuse: implement i...
1803
  		out_iov = in_iov + in_iovs;
7572777ee   Miklos Szeredi   fuse: verify ioct...
1804
1805
1806
1807
1808
1809
1810
  		err = fuse_verify_ioctl_iov(in_iov, in_iovs);
  		if (err)
  			goto out;
  
  		err = fuse_verify_ioctl_iov(out_iov, out_iovs);
  		if (err)
  			goto out;
59efec7b9   Tejun Heo   fuse: implement i...
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
  		goto retry;
  	}
  
  	err = -EIO;
  	if (transferred > inarg.out_size)
  		goto out;
  
  	err = fuse_ioctl_copy_user(pages, out_iov, out_iovs, transferred, true);
   out:
  	if (req)
  		fuse_put_request(fc, req);
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
1822
  	free_page((unsigned long) iov_page);
59efec7b9   Tejun Heo   fuse: implement i...
1823
1824
1825
1826
1827
1828
  	while (num_pages)
  		__free_page(pages[--num_pages]);
  	kfree(pages);
  
  	return err ? err : outarg.result;
  }
08cbf542b   Tejun Heo   fuse: export symb...
1829
  EXPORT_SYMBOL_GPL(fuse_do_ioctl);
59efec7b9   Tejun Heo   fuse: implement i...
1830

b18da0c56   Miklos Szeredi   fuse: support ioc...
1831
1832
  long fuse_ioctl_common(struct file *file, unsigned int cmd,
  		       unsigned long arg, unsigned int flags)
d36f24871   Miklos Szeredi   fuse: don't use i...
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
  {
  	struct inode *inode = file->f_dentry->d_inode;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  
  	if (!fuse_allow_task(fc, current))
  		return -EACCES;
  
  	if (is_bad_inode(inode))
  		return -EIO;
  
  	return fuse_do_ioctl(file, cmd, arg, flags);
  }
59efec7b9   Tejun Heo   fuse: implement i...
1845
1846
1847
  static long fuse_file_ioctl(struct file *file, unsigned int cmd,
  			    unsigned long arg)
  {
b18da0c56   Miklos Szeredi   fuse: support ioc...
1848
  	return fuse_ioctl_common(file, cmd, arg, 0);
59efec7b9   Tejun Heo   fuse: implement i...
1849
1850
1851
1852
1853
  }
  
  static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
  				   unsigned long arg)
  {
b18da0c56   Miklos Szeredi   fuse: support ioc...
1854
  	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
59efec7b9   Tejun Heo   fuse: implement i...
1855
  }
95668a69a   Tejun Heo   fuse: implement p...
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
  /*
   * All files which have been polled are linked to RB tree
   * fuse_conn->polled_files which is indexed by kh.  Walk the tree and
   * find the matching one.
   */
  static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
  					      struct rb_node **parent_out)
  {
  	struct rb_node **link = &fc->polled_files.rb_node;
  	struct rb_node *last = NULL;
  
  	while (*link) {
  		struct fuse_file *ff;
  
  		last = *link;
  		ff = rb_entry(last, struct fuse_file, polled_node);
  
  		if (kh < ff->kh)
  			link = &last->rb_left;
  		else if (kh > ff->kh)
  			link = &last->rb_right;
  		else
  			return link;
  	}
  
  	if (parent_out)
  		*parent_out = last;
  	return link;
  }
  
  /*
   * The file is about to be polled.  Make sure it's on the polled_files
   * RB tree.  Note that files once added to the polled_files tree are
   * not removed before the file is released.  This is because a file
   * polled once is likely to be polled again.
   */
  static void fuse_register_polled_file(struct fuse_conn *fc,
  				      struct fuse_file *ff)
  {
  	spin_lock(&fc->lock);
  	if (RB_EMPTY_NODE(&ff->polled_node)) {
  		struct rb_node **link, *parent;
  
  		link = fuse_find_polled_node(fc, ff->kh, &parent);
  		BUG_ON(*link);
  		rb_link_node(&ff->polled_node, parent, link);
  		rb_insert_color(&ff->polled_node, &fc->polled_files);
  	}
  	spin_unlock(&fc->lock);
  }
08cbf542b   Tejun Heo   fuse: export symb...
1906
  unsigned fuse_file_poll(struct file *file, poll_table *wait)
95668a69a   Tejun Heo   fuse: implement p...
1907
  {
95668a69a   Tejun Heo   fuse: implement p...
1908
  	struct fuse_file *ff = file->private_data;
797759aaf   Miklos Szeredi   fuse: don't use i...
1909
  	struct fuse_conn *fc = ff->fc;
95668a69a   Tejun Heo   fuse: implement p...
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
  	struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
  	struct fuse_poll_out outarg;
  	struct fuse_req *req;
  	int err;
  
  	if (fc->no_poll)
  		return DEFAULT_POLLMASK;
  
  	poll_wait(file, &ff->poll_wait, wait);
  
  	/*
  	 * Ask for notification iff there's someone waiting for it.
  	 * The client may ignore the flag and always notify.
  	 */
  	if (waitqueue_active(&ff->poll_wait)) {
  		inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
  		fuse_register_polled_file(fc, ff);
  	}
  
  	req = fuse_get_req(fc);
  	if (IS_ERR(req))
201fa69a2   Miklos Szeredi   fuse: fix bad ret...
1931
  		return POLLERR;
95668a69a   Tejun Heo   fuse: implement p...
1932
1933
  
  	req->in.h.opcode = FUSE_POLL;
797759aaf   Miklos Szeredi   fuse: don't use i...
1934
  	req->in.h.nodeid = ff->nodeid;
95668a69a   Tejun Heo   fuse: implement p...
1935
1936
1937
1938
1939
1940
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
  	req->out.numargs = 1;
  	req->out.args[0].size = sizeof(outarg);
  	req->out.args[0].value = &outarg;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1941
  	fuse_request_send(fc, req);
95668a69a   Tejun Heo   fuse: implement p...
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  
  	if (!err)
  		return outarg.revents;
  	if (err == -ENOSYS) {
  		fc->no_poll = 1;
  		return DEFAULT_POLLMASK;
  	}
  	return POLLERR;
  }
08cbf542b   Tejun Heo   fuse: export symb...
1953
  EXPORT_SYMBOL_GPL(fuse_file_poll);
95668a69a   Tejun Heo   fuse: implement p...
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
  
  /*
   * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
   * wakes up the poll waiters.
   */
  int fuse_notify_poll_wakeup(struct fuse_conn *fc,
  			    struct fuse_notify_poll_wakeup_out *outarg)
  {
  	u64 kh = outarg->kh;
  	struct rb_node **link;
  
  	spin_lock(&fc->lock);
  
  	link = fuse_find_polled_node(fc, kh, NULL);
  	if (*link) {
  		struct fuse_file *ff;
  
  		ff = rb_entry(*link, struct fuse_file, polled_node);
  		wake_up_interruptible_sync(&ff->poll_wait);
  	}
  
  	spin_unlock(&fc->lock);
  	return 0;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
1978
  static const struct file_operations fuse_file_operations = {
5559b8f4d   Miklos Szeredi   fuse: fix race in...
1979
  	.llseek		= fuse_file_llseek,
543ade1fc   Badari Pulavarty   [PATCH] Streamlin...
1980
  	.read		= do_sync_read,
bcb4be809   Miklos Szeredi   fuse: fix reading...
1981
  	.aio_read	= fuse_file_aio_read,
543ade1fc   Badari Pulavarty   [PATCH] Streamlin...
1982
  	.write		= do_sync_write,
ea9b9907b   Nick Piggin   fuse: implement p...
1983
  	.aio_write	= fuse_file_aio_write,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1984
1985
1986
1987
1988
  	.mmap		= fuse_file_mmap,
  	.open		= fuse_open,
  	.flush		= fuse_flush,
  	.release	= fuse_release,
  	.fsync		= fuse_fsync,
714212593   Miklos Szeredi   [PATCH] fuse: add...
1989
  	.lock		= fuse_file_lock,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1990
  	.flock		= fuse_file_flock,
5ffc4ef45   Jens Axboe   sendfile: remove ...
1991
  	.splice_read	= generic_file_splice_read,
59efec7b9   Tejun Heo   fuse: implement i...
1992
1993
  	.unlocked_ioctl	= fuse_file_ioctl,
  	.compat_ioctl	= fuse_file_compat_ioctl,
95668a69a   Tejun Heo   fuse: implement p...
1994
  	.poll		= fuse_file_poll,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1995
  };
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
1996
  static const struct file_operations fuse_direct_io_file_operations = {
5559b8f4d   Miklos Szeredi   fuse: fix race in...
1997
  	.llseek		= fuse_file_llseek,
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1998
1999
  	.read		= fuse_direct_read,
  	.write		= fuse_direct_write,
fc280c969   Miklos Szeredi   fuse: allow priva...
2000
  	.mmap		= fuse_direct_mmap,
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
2001
2002
2003
2004
  	.open		= fuse_open,
  	.flush		= fuse_flush,
  	.release	= fuse_release,
  	.fsync		= fuse_fsync,
714212593   Miklos Szeredi   [PATCH] fuse: add...
2005
  	.lock		= fuse_file_lock,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2006
  	.flock		= fuse_file_flock,
59efec7b9   Tejun Heo   fuse: implement i...
2007
2008
  	.unlocked_ioctl	= fuse_file_ioctl,
  	.compat_ioctl	= fuse_file_compat_ioctl,
95668a69a   Tejun Heo   fuse: implement p...
2009
  	.poll		= fuse_file_poll,
fc280c969   Miklos Szeredi   fuse: allow priva...
2010
  	/* no splice_read */
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
2011
  };
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
2012
  static const struct address_space_operations fuse_file_aops  = {
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2013
  	.readpage	= fuse_readpage,
3be5a52b3   Miklos Szeredi   fuse: support wri...
2014
2015
  	.writepage	= fuse_writepage,
  	.launder_page	= fuse_launder_page,
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
2016
  	.readpages	= fuse_readpages,
3be5a52b3   Miklos Szeredi   fuse: support wri...
2017
  	.set_page_dirty	= __set_page_dirty_nobuffers,
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2018
  	.bmap		= fuse_bmap,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2019
2020
2021
2022
  };
  
  void fuse_init_file_inode(struct inode *inode)
  {
45323fb76   Miklos Szeredi   [PATCH] fuse: mor...
2023
2024
  	inode->i_fop = &fuse_file_operations;
  	inode->i_data.a_ops = &fuse_file_aops;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2025
  }