Blame view

fs/fuse/file.c 74.9 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>
3634a6327   Brian Foster   fuse: truncate pa...
18
  #include <linux/falloc.h>
e2e40f2c1   Christoph Hellwig   fs: move struct k...
19
  #include <linux/uio.h>
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
20

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

91fe96b40   Miklos Szeredi   fuse: create fuse...
23
24
  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...
25
  {
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
26
  	struct fuse_open_in inarg;
7078187a7   Miklos Szeredi   fuse: introduce f...
27
  	FUSE_ARGS(args);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
28
29
  
  	memset(&inarg, 0, sizeof(inarg));
6ff958edb   Miklos Szeredi   fuse: add atomic ...
30
31
32
  	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
  	if (!fc->atomic_o_trunc)
  		inarg.flags &= ~O_TRUNC;
7078187a7   Miklos Szeredi   fuse: introduce f...
33
34
35
36
37
38
39
40
  	args.in.h.opcode = opcode;
  	args.in.h.nodeid = nodeid;
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	args.out.numargs = 1;
  	args.out.args[0].size = sizeof(*outargp);
  	args.out.args[0].value = outargp;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
41

7078187a7   Miklos Szeredi   fuse: introduce f...
42
  	return fuse_simple_request(fc, &args);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
43
  }
acf99433d   Tejun Heo   fuse: add file ke...
44
  struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
45
46
  {
  	struct fuse_file *ff;
6b2db28a7   Tejun Heo   fuse: misc cleanups
47

68227c03c   Mateusz Jurczyk   fuse: initialize ...
48
  	ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL);
6b2db28a7   Tejun Heo   fuse: misc cleanups
49
50
  	if (unlikely(!ff))
  		return NULL;
da5e47145   Miklos Szeredi   fuse: add members...
51
  	ff->fc = fc;
4250c0668   Maxim Patlasov   fuse: general inf...
52
  	ff->reserved_req = fuse_request_alloc(0);
6b2db28a7   Tejun Heo   fuse: misc cleanups
53
54
55
  	if (unlikely(!ff->reserved_req)) {
  		kfree(ff);
  		return NULL;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
56
  	}
6b2db28a7   Tejun Heo   fuse: misc cleanups
57
58
  
  	INIT_LIST_HEAD(&ff->write_entry);
4e8c2eb54   Elena Reshetova   fuse: convert fus...
59
  	refcount_set(&ff->count, 1);
6b2db28a7   Tejun Heo   fuse: misc cleanups
60
61
62
63
64
65
  	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...
66
67
68
69
70
  	return ff;
  }
  
  void fuse_file_free(struct fuse_file *ff)
  {
33649c91a   Miklos Szeredi   [PATCH] fuse: ens...
71
  	fuse_request_free(ff->reserved_req);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
72
73
  	kfree(ff);
  }
267d84449   Miklos Szeredi   fuse: cleanup fus...
74
  static struct fuse_file *fuse_file_get(struct fuse_file *ff)
c756e0a4d   Miklos Szeredi   fuse: add referen...
75
  {
4e8c2eb54   Elena Reshetova   fuse: convert fus...
76
  	refcount_inc(&ff->count);
c756e0a4d   Miklos Szeredi   fuse: add referen...
77
78
  	return ff;
  }
819c4b3b4   Miklos Szeredi   fuse: cleanup in ...
79
80
  static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
  {
baebccbe9   Miklos Szeredi   fuse: hold inode ...
81
  	iput(req->misc.release.inode);
819c4b3b4   Miklos Szeredi   fuse: cleanup in ...
82
  }
5a18ec176   Miklos Szeredi   fuse: fix hang of...
83
  static void fuse_file_put(struct fuse_file *ff, bool sync)
c756e0a4d   Miklos Szeredi   fuse: add referen...
84
  {
4e8c2eb54   Elena Reshetova   fuse: convert fus...
85
  	if (refcount_dec_and_test(&ff->count)) {
c756e0a4d   Miklos Szeredi   fuse: add referen...
86
  		struct fuse_req *req = ff->reserved_req;
8b0797a49   Miklos Szeredi   fuse: don't use i...
87

7678ac506   Andrew Gallagher   fuse: support cli...
88
89
90
91
92
  		if (ff->fc->no_open) {
  			/*
  			 * Drop the release request when client does not
  			 * implement 'open'
  			 */
825d6d339   Miklos Szeredi   fuse: req use bitops
93
  			__clear_bit(FR_BACKGROUND, &req->flags);
baebccbe9   Miklos Szeredi   fuse: hold inode ...
94
  			iput(req->misc.release.inode);
7678ac506   Andrew Gallagher   fuse: support cli...
95
96
  			fuse_put_request(ff->fc, req);
  		} else if (sync) {
2e38bea99   Miklos Szeredi   fuse: add missing...
97
  			__set_bit(FR_FORCE, &req->flags);
825d6d339   Miklos Szeredi   fuse: req use bitops
98
  			__clear_bit(FR_BACKGROUND, &req->flags);
5a18ec176   Miklos Szeredi   fuse: fix hang of...
99
  			fuse_request_send(ff->fc, req);
baebccbe9   Miklos Szeredi   fuse: hold inode ...
100
  			iput(req->misc.release.inode);
5a18ec176   Miklos Szeredi   fuse: fix hang of...
101
102
103
  			fuse_put_request(ff->fc, req);
  		} else {
  			req->end = fuse_release_end;
825d6d339   Miklos Szeredi   fuse: req use bitops
104
  			__set_bit(FR_BACKGROUND, &req->flags);
5a18ec176   Miklos Szeredi   fuse: fix hang of...
105
106
  			fuse_request_send_background(ff->fc, req);
  		}
c756e0a4d   Miklos Szeredi   fuse: add referen...
107
108
109
  		kfree(ff);
  	}
  }
08cbf542b   Tejun Heo   fuse: export symb...
110
111
  int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
  		 bool isdir)
91fe96b40   Miklos Szeredi   fuse: create fuse...
112
  {
91fe96b40   Miklos Szeredi   fuse: create fuse...
113
  	struct fuse_file *ff;
91fe96b40   Miklos Szeredi   fuse: create fuse...
114
115
116
117
118
  	int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
  
  	ff = fuse_file_alloc(fc);
  	if (!ff)
  		return -ENOMEM;
7678ac506   Andrew Gallagher   fuse: support cli...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  	ff->fh = 0;
  	ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
  	if (!fc->no_open || isdir) {
  		struct fuse_open_out outarg;
  		int err;
  
  		err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
  		if (!err) {
  			ff->fh = outarg.fh;
  			ff->open_flags = outarg.open_flags;
  
  		} else if (err != -ENOSYS || isdir) {
  			fuse_file_free(ff);
  			return err;
  		} else {
  			fc->no_open = 1;
  		}
91fe96b40   Miklos Szeredi   fuse: create fuse...
136
137
138
  	}
  
  	if (isdir)
7678ac506   Andrew Gallagher   fuse: support cli...
139
  		ff->open_flags &= ~FOPEN_DIRECT_IO;
91fe96b40   Miklos Szeredi   fuse: create fuse...
140

91fe96b40   Miklos Szeredi   fuse: create fuse...
141
  	ff->nodeid = nodeid;
267d84449   Miklos Szeredi   fuse: cleanup fus...
142
  	file->private_data = ff;
91fe96b40   Miklos Szeredi   fuse: create fuse...
143
144
145
  
  	return 0;
  }
08cbf542b   Tejun Heo   fuse: export symb...
146
  EXPORT_SYMBOL_GPL(fuse_do_open);
91fe96b40   Miklos Szeredi   fuse: create fuse...
147

650b22b94   Pavel Emelyanov   fuse: Linking fil...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  static void fuse_link_write_file(struct file *file)
  {
  	struct inode *inode = file_inode(file);
  	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);
  }
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
163
  void fuse_finish_open(struct inode *inode, struct file *file)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
164
  {
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
165
  	struct fuse_file *ff = file->private_data;
a0822c557   Ken Sumrall   fuse: fix attribu...
166
  	struct fuse_conn *fc = get_fuse_conn(inode);
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
167
168
  
  	if (ff->open_flags & FOPEN_DIRECT_IO)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
169
  		file->f_op = &fuse_direct_io_file_operations;
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
170
  	if (!(ff->open_flags & FOPEN_KEEP_CACHE))
b10099792   Miklos Szeredi   fuse: fix page in...
171
  		invalidate_inode_pages2(inode->i_mapping);
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
172
  	if (ff->open_flags & FOPEN_NONSEEKABLE)
a7c1b990f   Tejun Heo   fuse: implement n...
173
  		nonseekable_open(inode, file);
a0822c557   Ken Sumrall   fuse: fix attribu...
174
175
176
177
178
179
180
181
  	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);
75caeecdf   Maxim Patlasov   fuse: update mtim...
182
183
  		if (fc->writeback_cache)
  			file_update_time(file);
a0822c557   Ken Sumrall   fuse: fix attribu...
184
  	}
4d99ff8f1   Pavel Emelyanov   fuse: Turn writeb...
185
186
  	if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
  		fuse_link_write_file(file);
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
187
  }
91fe96b40   Miklos Szeredi   fuse: create fuse...
188
  int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
189
  {
acf99433d   Tejun Heo   fuse: add file ke...
190
  	struct fuse_conn *fc = get_fuse_conn(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
191
  	int err;
75caeecdf   Maxim Patlasov   fuse: update mtim...
192
193
194
  	bool lock_inode = (file->f_flags & O_TRUNC) &&
  			  fc->atomic_o_trunc &&
  			  fc->writeback_cache;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
195
196
197
198
  
  	err = generic_file_open(inode, file);
  	if (err)
  		return err;
75caeecdf   Maxim Patlasov   fuse: update mtim...
199
  	if (lock_inode)
5955102c9   Al Viro   wrappers for ->i_...
200
  		inode_lock(inode);
75caeecdf   Maxim Patlasov   fuse: update mtim...
201

91fe96b40   Miklos Szeredi   fuse: create fuse...
202
  	err = fuse_do_open(fc, get_node_id(inode), file, isdir);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
203

75caeecdf   Maxim Patlasov   fuse: update mtim...
204
205
  	if (!err)
  		fuse_finish_open(inode, file);
91fe96b40   Miklos Szeredi   fuse: create fuse...
206

75caeecdf   Maxim Patlasov   fuse: update mtim...
207
  	if (lock_inode)
5955102c9   Al Viro   wrappers for ->i_...
208
  		inode_unlock(inode);
75caeecdf   Maxim Patlasov   fuse: update mtim...
209
210
  
  	return err;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
211
  }
8b0797a49   Miklos Szeredi   fuse: don't use i...
212
  static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
64c6d8ed4   Miklos Szeredi   [PATCH] fuse: add...
213
  {
8b0797a49   Miklos Szeredi   fuse: don't use i...
214
  	struct fuse_conn *fc = ff->fc;
33649c91a   Miklos Szeredi   [PATCH] fuse: ens...
215
  	struct fuse_req *req = ff->reserved_req;
b57d42644   Miklos Szeredi   fuse: save space ...
216
  	struct fuse_release_in *inarg = &req->misc.release.in;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
217

8b0797a49   Miklos Szeredi   fuse: don't use i...
218
219
220
221
222
  	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...
223
  	wake_up_interruptible_all(&ff->poll_wait);
8b0797a49   Miklos Szeredi   fuse: don't use i...
224

b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
225
  	inarg->fh = ff->fh;
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
226
  	inarg->flags = flags;
51eb01e73   Miklos Szeredi   [PATCH] fuse: no ...
227
  	req->in.h.opcode = opcode;
c7b7143c6   Miklos Szeredi   fuse: clean up ar...
228
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
229
230
231
  	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...
232
  }
8b0797a49   Miklos Szeredi   fuse: don't use i...
233
  void fuse_release_common(struct file *file, int opcode)
fd72faac9   Miklos Szeredi   [PATCH] FUSE: ato...
234
  {
9a87ad3da   Miklos Szeredi   fuse: release: pr...
235
236
  	struct fuse_file *ff = file->private_data;
  	struct fuse_req *req = ff->reserved_req;
6b2db28a7   Tejun Heo   fuse: misc cleanups
237

8b0797a49   Miklos Szeredi   fuse: don't use i...
238
  	fuse_prepare_release(ff, file->f_flags, opcode);
6b2db28a7   Tejun Heo   fuse: misc cleanups
239

37fb3a30b   Miklos Szeredi   fuse: fix flock
240
241
242
243
244
245
  	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);
  	}
baebccbe9   Miklos Szeredi   fuse: hold inode ...
246
247
  	/* Hold inode until release is finished */
  	req->misc.release.inode = igrab(file_inode(file));
6b2db28a7   Tejun Heo   fuse: misc cleanups
248

6b2db28a7   Tejun Heo   fuse: misc cleanups
249
250
251
252
  	/*
  	 * 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...
253
254
255
256
  	 *
  	 * 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
257
  	 */
5a18ec176   Miklos Szeredi   fuse: fix hang of...
258
  	fuse_file_put(ff, ff->fc->destroy_req != NULL);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
259
  }
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
260
261
  static int fuse_open(struct inode *inode, struct file *file)
  {
91fe96b40   Miklos Szeredi   fuse: create fuse...
262
  	return fuse_open_common(inode, file, false);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
263
264
265
266
  }
  
  static int fuse_release(struct inode *inode, struct file *file)
  {
e7cc133c3   Pavel Emelyanov   fuse: Flush files...
267
268
269
270
  	struct fuse_conn *fc = get_fuse_conn(inode);
  
  	/* see fuse_vma_close() for !writeback_cache case */
  	if (fc->writeback_cache)
1e18bda86   Miklos Szeredi   fuse: add .write_...
271
  		write_inode_now(inode, 1);
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
272

8b0797a49   Miklos Szeredi   fuse: don't use i...
273
274
275
276
277
278
279
280
  	fuse_release_common(file, FUSE_RELEASE);
  
  	/* return value is ignored by VFS */
  	return 0;
  }
  
  void fuse_sync_release(struct fuse_file *ff, int flags)
  {
4e8c2eb54   Elena Reshetova   fuse: convert fus...
281
  	WARN_ON(refcount_read(&ff->count) > 1);
8b0797a49   Miklos Szeredi   fuse: don't use i...
282
  	fuse_prepare_release(ff, flags, FUSE_RELEASE);
267d84449   Miklos Szeredi   fuse: cleanup fus...
283
284
285
286
287
  	/*
  	 * iput(NULL) is a no-op and since the refcount is 1 and everything's
  	 * synchronous, we are fine with not doing igrab() here"
  	 */
  	fuse_file_put(ff, true);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
288
  }
08cbf542b   Tejun Heo   fuse: export symb...
289
  EXPORT_SYMBOL_GPL(fuse_sync_release);
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
290

714212593   Miklos Szeredi   [PATCH] fuse: add...
291
  /*
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
292
293
   * 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...
294
   */
f33321141   Miklos Szeredi   fuse: add support...
295
  u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
714212593   Miklos Szeredi   [PATCH] fuse: add...
296
  {
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  	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...
311
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
312
  /*
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
313
   * Check if any page in a range is under writeback
3be5a52b3   Miklos Szeredi   fuse: support wri...
314
315
316
317
   *
   * This is currently done by walking the list of writepage requests
   * for the inode, which can be pretty inefficient.
   */
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
318
319
  static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from,
  				   pgoff_t idx_to)
3be5a52b3   Miklos Szeredi   fuse: support wri...
320
321
322
323
324
325
326
327
328
329
330
  {
  	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);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
331
  		curr_index = req->misc.write.in.offset >> PAGE_SHIFT;
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
332
333
  		if (idx_from < curr_index + req->num_pages &&
  		    curr_index <= idx_to) {
3be5a52b3   Miklos Szeredi   fuse: support wri...
334
335
336
337
338
339
340
341
  			found = true;
  			break;
  		}
  	}
  	spin_unlock(&fc->lock);
  
  	return found;
  }
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
342
343
344
345
  static inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
  {
  	return fuse_range_is_writeback(inode, index, index);
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
346
347
348
349
350
351
352
353
354
355
356
357
358
  /*
   * 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;
  }
fe38d7df2   Maxim Patlasov   fuse: fuse_flush(...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  /*
   * 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);
  }
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
373
  static int fuse_flush(struct file *file, fl_owner_t id)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
374
  {
6131ffaa1   Al Viro   more file_inode()...
375
  	struct inode *inode = file_inode(file);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
376
377
378
379
380
  	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...
381
382
  	if (is_bad_inode(inode))
  		return -EIO;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
383
384
  	if (fc->no_flush)
  		return 0;
1e18bda86   Miklos Szeredi   fuse: add .write_...
385
  	err = write_inode_now(inode, 1);
fe38d7df2   Maxim Patlasov   fuse: fuse_flush(...
386
387
  	if (err)
  		return err;
5955102c9   Al Viro   wrappers for ->i_...
388
  	inode_lock(inode);
fe38d7df2   Maxim Patlasov   fuse: fuse_flush(...
389
  	fuse_sync_writes(inode);
5955102c9   Al Viro   wrappers for ->i_...
390
  	inode_unlock(inode);
fe38d7df2   Maxim Patlasov   fuse: fuse_flush(...
391

4a7f4e88f   Miklos Szeredi   fuse: use filemap...
392
  	err = filemap_check_errors(file->f_mapping);
9ebce595f   Maxim Patlasov   fuse: fuse_flush ...
393
394
  	if (err)
  		return err;
b111c8c0e   Maxim Patlasov   fuse: categorize ...
395
  	req = fuse_get_req_nofail_nopages(fc, file);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
396
397
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.fh = ff->fh;
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
398
  	inarg.lock_owner = fuse_lock_owner_id(fc, id);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
399
400
  	req->in.h.opcode = FUSE_FLUSH;
  	req->in.h.nodeid = get_node_id(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
401
402
403
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(inarg);
  	req->in.args[0].value = &inarg;
825d6d339   Miklos Szeredi   fuse: req use bitops
404
  	__set_bit(FR_FORCE, &req->flags);
b93f858ab   Tejun Heo   fuse: add fuse_ p...
405
  	fuse_request_send(fc, req);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
406
407
408
409
410
411
412
413
  	err = req->out.h.error;
  	fuse_put_request(fc, req);
  	if (err == -ENOSYS) {
  		fc->no_flush = 1;
  		err = 0;
  	}
  	return err;
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
414
415
  int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
  		      int datasync, int isdir)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
416
  {
7ea808591   Christoph Hellwig   drop unused dentr...
417
  	struct inode *inode = file->f_mapping->host;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
418
419
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_file *ff = file->private_data;
7078187a7   Miklos Szeredi   fuse: introduce f...
420
  	FUSE_ARGS(args);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
421
422
  	struct fuse_fsync_in inarg;
  	int err;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
423
424
  	if (is_bad_inode(inode))
  		return -EIO;
5955102c9   Al Viro   wrappers for ->i_...
425
  	inode_lock(inode);
02c24a821   Josef Bacik   fs: push i_mutex ...
426

3be5a52b3   Miklos Szeredi   fuse: support wri...
427
428
429
430
431
  	/*
  	 * Start writeback against all dirty pages of the inode, then
  	 * wait for all outstanding writes, before sending the FSYNC
  	 * request.
  	 */
7e51fe1dd   Jeff Layton   fuse: convert to ...
432
  	err = file_write_and_wait_range(file, start, end);
3be5a52b3   Miklos Szeredi   fuse: support wri...
433
  	if (err)
02c24a821   Josef Bacik   fs: push i_mutex ...
434
  		goto out;
3be5a52b3   Miklos Szeredi   fuse: support wri...
435
436
  
  	fuse_sync_writes(inode);
ac7f052b9   Alexey Kuznetsov   fuse: fsync() did...
437
438
439
  
  	/*
  	 * Due to implementation of fuse writeback
7e51fe1dd   Jeff Layton   fuse: convert to ...
440
  	 * file_write_and_wait_range() does not catch errors.
ac7f052b9   Alexey Kuznetsov   fuse: fsync() did...
441
442
  	 * We have to do this directly after fuse_sync_writes()
  	 */
7e51fe1dd   Jeff Layton   fuse: convert to ...
443
  	err = file_check_and_advance_wb_err(file);
ac7f052b9   Alexey Kuznetsov   fuse: fsync() did...
444
445
  	if (err)
  		goto out;
1e18bda86   Miklos Szeredi   fuse: add .write_...
446
447
448
  	err = sync_inode_metadata(inode, 1);
  	if (err)
  		goto out;
3be5a52b3   Miklos Szeredi   fuse: support wri...
449

22401e7b7   Miklos Szeredi   fuse: clean up fsync
450
451
  	if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
  		goto out;
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
452

b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
453
454
455
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.fh = ff->fh;
  	inarg.fsync_flags = datasync ? 1 : 0;
7078187a7   Miklos Szeredi   fuse: introduce f...
456
457
458
459
460
461
  	args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
  	args.in.h.nodeid = get_node_id(inode);
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	err = fuse_simple_request(fc, &args);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
462
  	if (err == -ENOSYS) {
825479819   Miklos Szeredi   [PATCH] FUSE: add...
463
464
465
466
  		if (isdir)
  			fc->no_fsyncdir = 1;
  		else
  			fc->no_fsync = 1;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
467
468
  		err = 0;
  	}
02c24a821   Josef Bacik   fs: push i_mutex ...
469
  out:
5955102c9   Al Viro   wrappers for ->i_...
470
  	inode_unlock(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
471
472
  	return err;
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
473
474
  static int fuse_fsync(struct file *file, loff_t start, loff_t end,
  		      int datasync)
825479819   Miklos Szeredi   [PATCH] FUSE: add...
475
  {
02c24a821   Josef Bacik   fs: push i_mutex ...
476
  	return fuse_fsync_common(file, start, end, datasync, 0);
825479819   Miklos Szeredi   [PATCH] FUSE: add...
477
  }
2106cb189   Miklos Szeredi   fuse: don't use i...
478
479
  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...
480
  {
5c5c5e51b   Miklos Szeredi   fuse: update file...
481
  	struct fuse_read_in *inarg = &req->misc.read.in;
a6643094e   Miklos Szeredi   fuse: pass open f...
482
  	struct fuse_file *ff = file->private_data;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
483

361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
484
485
486
  	inarg->fh = ff->fh;
  	inarg->offset = pos;
  	inarg->size = count;
a6643094e   Miklos Szeredi   fuse: pass open f...
487
  	inarg->flags = file->f_flags;
361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
488
  	req->in.h.opcode = opcode;
2106cb189   Miklos Szeredi   fuse: don't use i...
489
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
490
491
  	req->in.numargs = 1;
  	req->in.args[0].size = sizeof(struct fuse_read_in);
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
492
  	req->in.args[0].value = inarg;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
493
494
495
  	req->out.argvar = 1;
  	req->out.numargs = 1;
  	req->out.args[0].size = count;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
496
  }
8fba54aeb   Miklos Szeredi   fuse: direct-io: ...
497
  static void fuse_release_user_pages(struct fuse_req *req, bool should_dirty)
187c5c363   Maxim Patlasov   fuse: move fuse_r...
498
499
500
501
502
  {
  	unsigned i;
  
  	for (i = 0; i < req->num_pages; i++) {
  		struct page *page = req->pages[i];
8fba54aeb   Miklos Szeredi   fuse: direct-io: ...
503
  		if (should_dirty)
187c5c363   Maxim Patlasov   fuse: move fuse_r...
504
505
506
507
  			set_page_dirty_lock(page);
  		put_page(page);
  	}
  }
744742d69   Seth Forshee   fuse: Add referen...
508
509
510
511
  static void fuse_io_release(struct kref *kref)
  {
  	kfree(container_of(kref, struct fuse_io_priv, refcnt));
  }
9d5722b77   Christoph Hellwig   fuse: handle sync...
512
513
514
515
516
517
518
519
520
521
  static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
  {
  	if (io->err)
  		return io->err;
  
  	if (io->bytes >= 0 && io->write)
  		return -EIO;
  
  	return io->bytes < 0 ? io->size : io->bytes;
  }
01e9d11a3   Maxim Patlasov   fuse: add support...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  /**
   * In case of short read, the caller sets 'pos' to the position of
   * actual end of fuse request in IO request. Otherwise, if bytes_requested
   * == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1.
   *
   * An example:
   * User requested DIO read of 64K. It was splitted into two 32K fuse requests,
   * both submitted asynchronously. The first of them was ACKed by userspace as
   * fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The
   * second request was ACKed as short, e.g. only 1K was read, resulting in
   * pos == 33K.
   *
   * Thus, when all fuse requests are completed, the minimal non-negative 'pos'
   * will be equal to the length of the longest contiguous fragment of
   * transferred data starting from the beginning of IO request.
   */
  static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
  {
  	int left;
  
  	spin_lock(&io->lock);
  	if (err)
  		io->err = io->err ? : err;
  	else if (pos >= 0 && (io->bytes < 0 || pos < io->bytes))
  		io->bytes = pos;
  
  	left = --io->reqs;
7879c4e58   Ashish Sangwan   fuse: improve aio...
549
  	if (!left && io->blocking)
9d5722b77   Christoph Hellwig   fuse: handle sync...
550
  		complete(io->done);
01e9d11a3   Maxim Patlasov   fuse: add support...
551
  	spin_unlock(&io->lock);
7879c4e58   Ashish Sangwan   fuse: improve aio...
552
  	if (!left && !io->blocking) {
9d5722b77   Christoph Hellwig   fuse: handle sync...
553
  		ssize_t res = fuse_get_res_by_io(io);
01e9d11a3   Maxim Patlasov   fuse: add support...
554

9d5722b77   Christoph Hellwig   fuse: handle sync...
555
556
557
558
  		if (res >= 0) {
  			struct inode *inode = file_inode(io->iocb->ki_filp);
  			struct fuse_conn *fc = get_fuse_conn(inode);
  			struct fuse_inode *fi = get_fuse_inode(inode);
01e9d11a3   Maxim Patlasov   fuse: add support...
559

9d5722b77   Christoph Hellwig   fuse: handle sync...
560
561
562
  			spin_lock(&fc->lock);
  			fi->attr_version = ++fc->attr_version;
  			spin_unlock(&fc->lock);
01e9d11a3   Maxim Patlasov   fuse: add support...
563
  		}
04b2fa9f8   Christoph Hellwig   fs: split generic...
564
  		io->iocb->ki_complete(io->iocb, res, 0);
01e9d11a3   Maxim Patlasov   fuse: add support...
565
  	}
744742d69   Seth Forshee   fuse: Add referen...
566
567
  
  	kref_put(&io->refcnt, fuse_io_release);
01e9d11a3   Maxim Patlasov   fuse: add support...
568
569
570
571
572
573
  }
  
  static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
  {
  	struct fuse_io_priv *io = req->io;
  	ssize_t pos = -1;
61c12b49e   Ashish Samant   fuse: Dont call s...
574
  	fuse_release_user_pages(req, io->should_dirty);
01e9d11a3   Maxim Patlasov   fuse: add support...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  
  	if (io->write) {
  		if (req->misc.write.in.size != req->misc.write.out.size)
  			pos = req->misc.write.in.offset - io->offset +
  				req->misc.write.out.size;
  	} else {
  		if (req->misc.read.in.size != req->out.args[0].size)
  			pos = req->misc.read.in.offset - io->offset +
  				req->out.args[0].size;
  	}
  
  	fuse_aio_complete(io, req->out.h.error, pos);
  }
  
  static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req,
  		size_t num_bytes, struct fuse_io_priv *io)
  {
  	spin_lock(&io->lock);
744742d69   Seth Forshee   fuse: Add referen...
593
  	kref_get(&io->refcnt);
01e9d11a3   Maxim Patlasov   fuse: add support...
594
595
596
597
598
599
  	io->size += num_bytes;
  	io->reqs++;
  	spin_unlock(&io->lock);
  
  	req->io = io;
  	req->end = fuse_aio_complete_req;
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
600
  	__fuse_get_request(req);
01e9d11a3   Maxim Patlasov   fuse: add support...
601
602
603
604
  	fuse_request_send_background(fc, req);
  
  	return num_bytes;
  }
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
605
  static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io,
2106cb189   Miklos Szeredi   fuse: don't use i...
606
  			     loff_t pos, size_t count, fl_owner_t owner)
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
607
  {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
608
  	struct file *file = io->iocb->ki_filp;
2106cb189   Miklos Szeredi   fuse: don't use i...
609
610
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
f33321141   Miklos Szeredi   fuse: add support...
611

2106cb189   Miklos Szeredi   fuse: don't use i...
612
  	fuse_read_fill(req, file, pos, count, FUSE_READ);
f33321141   Miklos Szeredi   fuse: add support...
613
  	if (owner != NULL) {
5c5c5e51b   Miklos Szeredi   fuse: update file...
614
  		struct fuse_read_in *inarg = &req->misc.read.in;
f33321141   Miklos Szeredi   fuse: add support...
615
616
617
618
  
  		inarg->read_flags |= FUSE_READ_LOCKOWNER;
  		inarg->lock_owner = fuse_lock_owner_id(fc, owner);
  	}
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
619
620
621
  
  	if (io->async)
  		return fuse_async_req_send(fc, req, count, io);
b93f858ab   Tejun Heo   fuse: add fuse_ p...
622
  	fuse_request_send(fc, req);
361b1eb55   Miklos Szeredi   [PATCH] fuse: REA...
623
  	return req->out.args[0].size;
04730fef1   Miklos Szeredi   [PATCH] fuse: tra...
624
  }
5c5c5e51b   Miklos Szeredi   fuse: update file...
625
626
627
628
629
630
631
  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);
06a7c3c27   Maxim Patlasov   fuse: hotfix trun...
632
633
  	if (attr_ver == fi->attr_version && size < inode->i_size &&
  	    !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
5c5c5e51b   Miklos Szeredi   fuse: update file...
634
635
636
637
638
  		fi->attr_version = ++fc->attr_version;
  		i_size_write(inode, size);
  	}
  	spin_unlock(&fc->lock);
  }
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
639
640
641
642
  static void fuse_short_read(struct fuse_req *req, struct inode *inode,
  			    u64 attr_ver)
  {
  	size_t num_read = req->out.args[0].size;
8373200b1   Pavel Emelyanov   fuse: Trust kerne...
643
644
645
646
647
648
649
650
651
  	struct fuse_conn *fc = get_fuse_conn(inode);
  
  	if (fc->writeback_cache) {
  		/*
  		 * A hole in a file. Some data after the hole are in page cache,
  		 * but have not reached the client fs yet. So, the hole is not
  		 * present there.
  		 */
  		int i;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
652
653
  		int start_idx = num_read >> PAGE_SHIFT;
  		size_t off = num_read & (PAGE_SIZE - 1);
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
654

8373200b1   Pavel Emelyanov   fuse: Trust kerne...
655
  		for (i = start_idx; i < req->num_pages; i++) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
656
  			zero_user_segment(req->pages[i], off, PAGE_SIZE);
8373200b1   Pavel Emelyanov   fuse: Trust kerne...
657
658
659
660
661
662
  			off = 0;
  		}
  	} else {
  		loff_t pos = page_offset(req->pages[0]) + num_read;
  		fuse_read_update_size(inode, pos, attr_ver);
  	}
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
663
  }
482fce55d   Maxim Patlasov   fuse: restructure...
664
  static int fuse_do_readpage(struct file *file, struct page *page)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
665
  {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
666
667
  	struct kiocb iocb;
  	struct fuse_io_priv io;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
668
669
  	struct inode *inode = page->mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
670
  	struct fuse_req *req;
5c5c5e51b   Miklos Szeredi   fuse: update file...
671
672
  	size_t num_read;
  	loff_t pos = page_offset(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
673
  	size_t count = PAGE_SIZE;
5c5c5e51b   Miklos Szeredi   fuse: update file...
674
  	u64 attr_ver;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
675
  	int err;
3be5a52b3   Miklos Szeredi   fuse: support wri...
676
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
677
  	 * Page writeback can extend beyond the lifetime of the
3be5a52b3   Miklos Szeredi   fuse: support wri...
678
679
680
681
  	 * page-cache page, so make sure we read a properly synced
  	 * page.
  	 */
  	fuse_wait_on_page_writeback(inode, page->index);
b111c8c0e   Maxim Patlasov   fuse: categorize ...
682
  	req = fuse_get_req(fc, 1);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
683
  	if (IS_ERR(req))
482fce55d   Maxim Patlasov   fuse: restructure...
684
  		return PTR_ERR(req);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
685

5c5c5e51b   Miklos Szeredi   fuse: update file...
686
  	attr_ver = fuse_get_attr_version(fc);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
687
  	req->out.page_zeroing = 1;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
688
  	req->out.argpages = 1;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
689
690
  	req->num_pages = 1;
  	req->pages[0] = page;
85f40aec8   Maxim Patlasov   fuse: use req->pa...
691
  	req->page_descs[0].length = count;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
692
693
  	init_sync_kiocb(&iocb, file);
  	io = (struct fuse_io_priv) FUSE_IO_PRIV_SYNC(&iocb);
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
694
  	num_read = fuse_send_read(req, &io, pos, count, NULL);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
695
  	err = req->out.h.error;
5c5c5e51b   Miklos Szeredi   fuse: update file...
696
697
698
699
700
701
  
  	if (!err) {
  		/*
  		 * Short read means EOF.  If file size is larger, truncate it
  		 */
  		if (num_read < count)
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
702
  			fuse_short_read(req, inode, attr_ver);
5c5c5e51b   Miklos Szeredi   fuse: update file...
703

b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
704
  		SetPageUptodate(page);
5c5c5e51b   Miklos Szeredi   fuse: update file...
705
  	}
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
706
  	fuse_put_request(fc, req);
482fce55d   Maxim Patlasov   fuse: restructure...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  
  	return err;
  }
  
  static int fuse_readpage(struct file *file, struct page *page)
  {
  	struct inode *inode = page->mapping->host;
  	int err;
  
  	err = -EIO;
  	if (is_bad_inode(inode))
  		goto out;
  
  	err = fuse_do_readpage(file, page);
451418fc9   Andrew Gallagher   fuse: don't inval...
721
  	fuse_invalidate_atime(inode);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
722
723
724
725
   out:
  	unlock_page(page);
  	return err;
  }
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
726
  static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
727
  {
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
728
  	int i;
5c5c5e51b   Miklos Szeredi   fuse: update file...
729
730
  	size_t count = req->misc.read.in.size;
  	size_t num_read = req->out.args[0].size;
ce534fb05   Miklos Szeredi   fuse: allow splic...
731
  	struct address_space *mapping = NULL;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
732

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

ce534fb05   Miklos Szeredi   fuse: allow splic...
736
737
738
739
740
741
  	if (mapping) {
  		struct inode *inode = mapping->host;
  
  		/*
  		 * Short read means EOF. If file size is larger, truncate it
  		 */
a92adc824   Pavel Emelyanov   fuse: Prepare to ...
742
743
  		if (!req->out.h.error && num_read < count)
  			fuse_short_read(req, inode, req->misc.read.attr_ver);
ce534fb05   Miklos Szeredi   fuse: allow splic...
744

451418fc9   Andrew Gallagher   fuse: don't inval...
745
  		fuse_invalidate_atime(inode);
ce534fb05   Miklos Szeredi   fuse: allow splic...
746
  	}
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
747

db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
748
749
750
751
  	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...
752
753
  		else
  			SetPageError(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
754
  		unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
755
  		put_page(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
756
  	}
c756e0a4d   Miklos Szeredi   fuse: add referen...
757
  	if (req->ff)
5a18ec176   Miklos Szeredi   fuse: fix hang of...
758
  		fuse_file_put(req->ff, false);
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
759
  }
2106cb189   Miklos Szeredi   fuse: don't use i...
760
  static void fuse_send_readpages(struct fuse_req *req, struct file *file)
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
761
  {
2106cb189   Miklos Szeredi   fuse: don't use i...
762
763
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
764
  	loff_t pos = page_offset(req->pages[0]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
765
  	size_t count = req->num_pages << PAGE_SHIFT;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
766
767
  
  	req->out.argpages = 1;
c1aa96a52   Miklos Szeredi   [PATCH] fuse: use...
768
  	req->out.page_zeroing = 1;
ce534fb05   Miklos Szeredi   fuse: allow splic...
769
  	req->out.page_replace = 1;
2106cb189   Miklos Szeredi   fuse: don't use i...
770
  	fuse_read_fill(req, file, pos, count, FUSE_READ);
5c5c5e51b   Miklos Szeredi   fuse: update file...
771
  	req->misc.read.attr_ver = fuse_get_attr_version(fc);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
772
  	if (fc->async_read) {
c756e0a4d   Miklos Szeredi   fuse: add referen...
773
  		req->ff = fuse_file_get(ff);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
774
  		req->end = fuse_readpages_end;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
775
  		fuse_request_send_background(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
776
  	} else {
b93f858ab   Tejun Heo   fuse: add fuse_ p...
777
  		fuse_request_send(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
778
  		fuse_readpages_end(fc, req);
e9bb09dd6   Tejun Heo   fuse: don't let f...
779
  		fuse_put_request(fc, req);
9cd684551   Miklos Szeredi   [PATCH] fuse: fix...
780
  	}
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
781
  }
c756e0a4d   Miklos Szeredi   fuse: add referen...
782
  struct fuse_fill_data {
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
783
  	struct fuse_req *req;
a6643094e   Miklos Szeredi   fuse: pass open f...
784
  	struct file *file;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
785
  	struct inode *inode;
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
786
  	unsigned nr_pages;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
787
788
789
790
  };
  
  static int fuse_readpages_fill(void *_data, struct page *page)
  {
c756e0a4d   Miklos Szeredi   fuse: add referen...
791
  	struct fuse_fill_data *data = _data;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
792
793
794
  	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...
795
  	fuse_wait_on_page_writeback(inode, page->index);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
796
797
  	if (req->num_pages &&
  	    (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
798
  	     (req->num_pages + 1) * PAGE_SIZE > fc->max_read ||
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
799
  	     req->pages[req->num_pages - 1]->index + 1 != page->index)) {
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
800
801
  		int nr_alloc = min_t(unsigned, data->nr_pages,
  				     FUSE_MAX_PAGES_PER_REQ);
2106cb189   Miklos Szeredi   fuse: don't use i...
802
  		fuse_send_readpages(req, data->file);
8b41e6715   Maxim Patlasov   fuse: make reques...
803
804
805
806
807
808
  		if (fc->async_read)
  			req = fuse_get_req_for_background(fc, nr_alloc);
  		else
  			req = fuse_get_req(fc, nr_alloc);
  
  		data->req = req;
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
809
  		if (IS_ERR(req)) {
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
810
  			unlock_page(page);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
811
  			return PTR_ERR(req);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
812
  		}
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
813
  	}
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
814
815
816
817
818
  
  	if (WARN_ON(req->num_pages >= req->max_pages)) {
  		fuse_put_request(fc, req);
  		return -EIO;
  	}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
819
  	get_page(page);
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
820
  	req->pages[req->num_pages] = page;
85f40aec8   Maxim Patlasov   fuse: use req->pa...
821
  	req->page_descs[req->num_pages].length = PAGE_SIZE;
1729a16c2   Miklos Szeredi   fuse: style fixes
822
  	req->num_pages++;
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
823
  	data->nr_pages--;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
824
825
826
827
828
829
830
831
  	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...
832
  	struct fuse_fill_data data;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
833
  	int err;
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
834
  	int nr_alloc = min_t(unsigned, nr_pages, FUSE_MAX_PAGES_PER_REQ);
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
835

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

a6643094e   Miklos Szeredi   fuse: pass open f...
840
  	data.file = file;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
841
  	data.inode = inode;
8b41e6715   Maxim Patlasov   fuse: make reques...
842
843
844
845
  	if (fc->async_read)
  		data.req = fuse_get_req_for_background(fc, nr_alloc);
  	else
  		data.req = fuse_get_req(fc, nr_alloc);
f8dbdf818   Maxim Patlasov   fuse: rework fuse...
846
  	data.nr_pages = nr_pages;
1d7ea7324   Alexander Zarochentsev   [PATCH] fuse: fix...
847
  	err = PTR_ERR(data.req);
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
848
  	if (IS_ERR(data.req))
2e990021b   OGAWA Hirofumi   [PATCH] fuse: ->r...
849
  		goto out;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
850
851
  
  	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
d3406ffa4   Miklos Szeredi   [PATCH] fuse: fix...
852
853
  	if (!err) {
  		if (data.req->num_pages)
2106cb189   Miklos Szeredi   fuse: don't use i...
854
  			fuse_send_readpages(data.req, file);
d3406ffa4   Miklos Szeredi   [PATCH] fuse: fix...
855
856
857
  		else
  			fuse_put_request(fc, data.req);
  	}
2e990021b   OGAWA Hirofumi   [PATCH] fuse: ->r...
858
  out:
1d7ea7324   Alexander Zarochentsev   [PATCH] fuse: fix...
859
  	return err;
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
860
  }
37c20f16e   Al Viro   fuse_file_aio_rea...
861
  static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
bcb4be809   Miklos Szeredi   fuse: fix reading...
862
863
  {
  	struct inode *inode = iocb->ki_filp->f_mapping->host;
a8894274a   Brian Foster   fuse: update attr...
864
  	struct fuse_conn *fc = get_fuse_conn(inode);
bcb4be809   Miklos Szeredi   fuse: fix reading...
865

a8894274a   Brian Foster   fuse: update attr...
866
867
868
869
870
871
  	/*
  	 * In auto invalidate mode, always update attributes on read.
  	 * Otherwise, only update if we attempt to read past EOF (to ensure
  	 * i_size is up to date).
  	 */
  	if (fc->auto_inval_data ||
37c20f16e   Al Viro   fuse_file_aio_rea...
872
  	    (iocb->ki_pos + iov_iter_count(to) > i_size_read(inode))) {
bcb4be809   Miklos Szeredi   fuse: fix reading...
873
  		int err;
5b97eeacb   Miklos Szeredi   fuse: getattr cle...
874
  		err = fuse_update_attributes(inode, iocb->ki_filp);
bcb4be809   Miklos Szeredi   fuse: fix reading...
875
876
877
  		if (err)
  			return err;
  	}
37c20f16e   Al Viro   fuse_file_aio_rea...
878
  	return generic_file_read_iter(iocb, to);
bcb4be809   Miklos Szeredi   fuse: fix reading...
879
  }
2d698b070   Miklos Szeredi   fuse: clean up fu...
880
  static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
2106cb189   Miklos Szeredi   fuse: don't use i...
881
  			    loff_t pos, size_t count)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
882
  {
b25e82e56   Miklos Szeredi   fuse: add helper ...
883
884
  	struct fuse_write_in *inarg = &req->misc.write.in;
  	struct fuse_write_out *outarg = &req->misc.write.out;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
885

b25e82e56   Miklos Szeredi   fuse: add helper ...
886
887
888
  	inarg->fh = ff->fh;
  	inarg->offset = pos;
  	inarg->size = count;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
889
  	req->in.h.opcode = FUSE_WRITE;
2106cb189   Miklos Szeredi   fuse: don't use i...
890
  	req->in.h.nodeid = ff->nodeid;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
891
  	req->in.numargs = 2;
2106cb189   Miklos Szeredi   fuse: don't use i...
892
  	if (ff->fc->minor < 9)
f33321141   Miklos Szeredi   fuse: add support...
893
894
895
  		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 ...
896
  	req->in.args[0].value = inarg;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
897
898
899
  	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 ...
900
901
  	req->out.args[0].value = outarg;
  }
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
902
  static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
2106cb189   Miklos Szeredi   fuse: don't use i...
903
  			      loff_t pos, size_t count, fl_owner_t owner)
b25e82e56   Miklos Szeredi   fuse: add helper ...
904
  {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
905
906
  	struct kiocb *iocb = io->iocb;
  	struct file *file = iocb->ki_filp;
2106cb189   Miklos Szeredi   fuse: don't use i...
907
908
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
2d698b070   Miklos Szeredi   fuse: clean up fu...
909
  	struct fuse_write_in *inarg = &req->misc.write.in;
2106cb189   Miklos Szeredi   fuse: don't use i...
910
  	fuse_write_fill(req, ff, pos, count);
2d698b070   Miklos Szeredi   fuse: clean up fu...
911
  	inarg->flags = file->f_flags;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
912
913
914
915
  	if (iocb->ki_flags & IOCB_DSYNC)
  		inarg->flags |= O_DSYNC;
  	if (iocb->ki_flags & IOCB_SYNC)
  		inarg->flags |= O_SYNC;
f33321141   Miklos Szeredi   fuse: add support...
916
  	if (owner != NULL) {
f33321141   Miklos Szeredi   fuse: add support...
917
918
919
  		inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
  		inarg->lock_owner = fuse_lock_owner_id(fc, owner);
  	}
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
920
921
922
  
  	if (io->async)
  		return fuse_async_req_send(fc, req, count, io);
b93f858ab   Tejun Heo   fuse: add fuse_ p...
923
  	fuse_request_send(fc, req);
b25e82e56   Miklos Szeredi   fuse: add helper ...
924
  	return req->misc.write.out.size;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
925
  }
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
926
  bool fuse_write_update_size(struct inode *inode, loff_t pos)
854512ec3   Miklos Szeredi   fuse: clean up se...
927
928
929
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
930
  	bool ret = false;
854512ec3   Miklos Szeredi   fuse: clean up se...
931
932
933
  
  	spin_lock(&fc->lock);
  	fi->attr_version = ++fc->attr_version;
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
934
  	if (pos > inode->i_size) {
854512ec3   Miklos Szeredi   fuse: clean up se...
935
  		i_size_write(inode, pos);
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
936
937
  		ret = true;
  	}
854512ec3   Miklos Szeredi   fuse: clean up se...
938
  	spin_unlock(&fc->lock);
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
939
940
  
  	return ret;
854512ec3   Miklos Szeredi   fuse: clean up se...
941
  }
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
942
  static size_t fuse_send_write_pages(struct fuse_req *req, struct kiocb *iocb,
ea9b9907b   Nick Piggin   fuse: implement p...
943
944
945
946
947
948
  				    struct inode *inode, loff_t pos,
  				    size_t count)
  {
  	size_t res;
  	unsigned offset;
  	unsigned i;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
949
  	struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
ea9b9907b   Nick Piggin   fuse: implement p...
950
951
952
  
  	for (i = 0; i < req->num_pages; i++)
  		fuse_wait_on_page_writeback(inode, req->pages[i]->index);
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
953
  	res = fuse_send_write(req, &io, pos, count, NULL);
ea9b9907b   Nick Piggin   fuse: implement p...
954

b2430d756   Maxim Patlasov   fuse: add per-pag...
955
  	offset = req->page_descs[0].offset;
ea9b9907b   Nick Piggin   fuse: implement p...
956
957
958
  	count = res;
  	for (i = 0; i < req->num_pages; i++) {
  		struct page *page = req->pages[i];
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
959
  		if (!req->out.h.error && !offset && count >= PAGE_SIZE)
ea9b9907b   Nick Piggin   fuse: implement p...
960
  			SetPageUptodate(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
961
962
  		if (count > PAGE_SIZE - offset)
  			count -= PAGE_SIZE - offset;
ea9b9907b   Nick Piggin   fuse: implement p...
963
964
965
966
967
  		else
  			count = 0;
  		offset = 0;
  
  		unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
968
  		put_page(page);
ea9b9907b   Nick Piggin   fuse: implement p...
969
970
971
972
973
974
975
976
977
978
  	}
  
  	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);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
979
  	unsigned offset = pos & (PAGE_SIZE - 1);
ea9b9907b   Nick Piggin   fuse: implement p...
980
981
  	size_t count = 0;
  	int err;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
982
  	req->in.argpages = 1;
b2430d756   Maxim Patlasov   fuse: add per-pag...
983
  	req->page_descs[0].offset = offset;
ea9b9907b   Nick Piggin   fuse: implement p...
984
985
986
987
  
  	do {
  		size_t tmp;
  		struct page *page;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
988
989
  		pgoff_t index = pos >> PAGE_SHIFT;
  		size_t bytes = min_t(size_t, PAGE_SIZE - offset,
ea9b9907b   Nick Piggin   fuse: implement p...
990
991
992
993
994
995
996
997
998
999
  				     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...
1000
  		page = grab_cache_page_write_begin(mapping, index, 0);
ea9b9907b   Nick Piggin   fuse: implement p...
1001
1002
  		if (!page)
  			break;
931e80e4b   anfei zhou   mm: flush dcache ...
1003
1004
  		if (mapping_writably_mapped(mapping))
  			flush_dcache_page(page);
ea9b9907b   Nick Piggin   fuse: implement p...
1005
  		tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
ea9b9907b   Nick Piggin   fuse: implement p...
1006
  		flush_dcache_page(page);
3ca8138f0   Roman Gushchin   fuse: break infin...
1007
  		iov_iter_advance(ii, tmp);
ea9b9907b   Nick Piggin   fuse: implement p...
1008
1009
  		if (!tmp) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1010
  			put_page(page);
ea9b9907b   Nick Piggin   fuse: implement p...
1011
1012
1013
1014
1015
1016
  			bytes = min(bytes, iov_iter_single_seg_count(ii));
  			goto again;
  		}
  
  		err = 0;
  		req->pages[req->num_pages] = page;
85f40aec8   Maxim Patlasov   fuse: use req->pa...
1017
  		req->page_descs[req->num_pages].length = tmp;
ea9b9907b   Nick Piggin   fuse: implement p...
1018
  		req->num_pages++;
ea9b9907b   Nick Piggin   fuse: implement p...
1019
1020
1021
  		count += tmp;
  		pos += tmp;
  		offset += tmp;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1022
  		if (offset == PAGE_SIZE)
ea9b9907b   Nick Piggin   fuse: implement p...
1023
  			offset = 0;
78bb6cb9a   Miklos Szeredi   fuse: add flag to...
1024
1025
  		if (!fc->big_writes)
  			break;
ea9b9907b   Nick Piggin   fuse: implement p...
1026
  	} while (iov_iter_count(ii) && count < fc->max_write &&
d07f09f50   Maxim Patlasov   fuse: rework fuse...
1027
  		 req->num_pages < req->max_pages && offset == 0);
ea9b9907b   Nick Piggin   fuse: implement p...
1028
1029
1030
  
  	return count > 0 ? count : err;
  }
d07f09f50   Maxim Patlasov   fuse: rework fuse...
1031
1032
1033
  static inline unsigned fuse_wr_pages(loff_t pos, size_t len)
  {
  	return min_t(unsigned,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1034
1035
  		     ((pos + len - 1) >> PAGE_SHIFT) -
  		     (pos >> PAGE_SHIFT) + 1,
d07f09f50   Maxim Patlasov   fuse: rework fuse...
1036
1037
  		     FUSE_MAX_PAGES_PER_REQ);
  }
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1038
  static ssize_t fuse_perform_write(struct kiocb *iocb,
ea9b9907b   Nick Piggin   fuse: implement p...
1039
1040
1041
1042
1043
  				  struct address_space *mapping,
  				  struct iov_iter *ii, loff_t pos)
  {
  	struct inode *inode = mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
06a7c3c27   Maxim Patlasov   fuse: hotfix trun...
1044
  	struct fuse_inode *fi = get_fuse_inode(inode);
ea9b9907b   Nick Piggin   fuse: implement p...
1045
1046
1047
1048
1049
  	int err = 0;
  	ssize_t res = 0;
  
  	if (is_bad_inode(inode))
  		return -EIO;
06a7c3c27   Maxim Patlasov   fuse: hotfix trun...
1050
1051
  	if (inode->i_size < pos + iov_iter_count(ii))
  		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
ea9b9907b   Nick Piggin   fuse: implement p...
1052
1053
1054
  	do {
  		struct fuse_req *req;
  		ssize_t count;
d07f09f50   Maxim Patlasov   fuse: rework fuse...
1055
  		unsigned nr_pages = fuse_wr_pages(pos, iov_iter_count(ii));
ea9b9907b   Nick Piggin   fuse: implement p...
1056

d07f09f50   Maxim Patlasov   fuse: rework fuse...
1057
  		req = fuse_get_req(fc, nr_pages);
ea9b9907b   Nick Piggin   fuse: implement p...
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  		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;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1068
  			num_written = fuse_send_write_pages(req, iocb, inode,
ea9b9907b   Nick Piggin   fuse: implement p...
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
  							    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);
06a7c3c27   Maxim Patlasov   fuse: hotfix trun...
1085
  	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
ea9b9907b   Nick Piggin   fuse: implement p...
1086
1087
1088
1089
  	fuse_invalidate_attr(inode);
  
  	return res > 0 ? res : err;
  }
84c3d55cc   Al Viro   fuse: switch to -...
1090
  static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
ea9b9907b   Nick Piggin   fuse: implement p...
1091
1092
1093
  {
  	struct file *file = iocb->ki_filp;
  	struct address_space *mapping = file->f_mapping;
ea9b9907b   Nick Piggin   fuse: implement p...
1094
  	ssize_t written = 0;
4273b793e   Anand Avati   fuse: O_DIRECT su...
1095
  	ssize_t written_buffered = 0;
ea9b9907b   Nick Piggin   fuse: implement p...
1096
1097
  	struct inode *inode = mapping->host;
  	ssize_t err;
4273b793e   Anand Avati   fuse: O_DIRECT su...
1098
  	loff_t endbyte = 0;
ea9b9907b   Nick Piggin   fuse: implement p...
1099

4d99ff8f1   Pavel Emelyanov   fuse: Turn writeb...
1100
1101
  	if (get_fuse_conn(inode)->writeback_cache) {
  		/* Update size (EOF optimization) and mode (SUID clearing) */
5b97eeacb   Miklos Szeredi   fuse: getattr cle...
1102
  		err = fuse_update_attributes(mapping->host, file);
4d99ff8f1   Pavel Emelyanov   fuse: Turn writeb...
1103
1104
  		if (err)
  			return err;
84c3d55cc   Al Viro   fuse: switch to -...
1105
  		return generic_file_write_iter(iocb, from);
4d99ff8f1   Pavel Emelyanov   fuse: Turn writeb...
1106
  	}
5955102c9   Al Viro   wrappers for ->i_...
1107
  	inode_lock(inode);
ea9b9907b   Nick Piggin   fuse: implement p...
1108
1109
  
  	/* We can write back this queue in page reclaim */
de1414a65   Christoph Hellwig   fs: export inode_...
1110
  	current->backing_dev_info = inode_to_bdi(inode);
ea9b9907b   Nick Piggin   fuse: implement p...
1111

3309dd04c   Al Viro   switch generic_wr...
1112
1113
  	err = generic_write_checks(iocb, from);
  	if (err <= 0)
ea9b9907b   Nick Piggin   fuse: implement p...
1114
  		goto out;
5fa8e0a1c   Jan Kara   fs: Rename file_r...
1115
  	err = file_remove_privs(file);
ea9b9907b   Nick Piggin   fuse: implement p...
1116
1117
  	if (err)
  		goto out;
c3b2da314   Josef Bacik   fs: introduce ino...
1118
1119
1120
  	err = file_update_time(file);
  	if (err)
  		goto out;
ea9b9907b   Nick Piggin   fuse: implement p...
1121

2ba48ce51   Al Viro   mirror O_APPEND a...
1122
  	if (iocb->ki_flags & IOCB_DIRECT) {
3309dd04c   Al Viro   switch generic_wr...
1123
  		loff_t pos = iocb->ki_pos;
1af5bb491   Christoph Hellwig   filemap: remove t...
1124
  		written = generic_file_direct_write(iocb, from);
84c3d55cc   Al Viro   fuse: switch to -...
1125
  		if (written < 0 || !iov_iter_count(from))
4273b793e   Anand Avati   fuse: O_DIRECT su...
1126
1127
1128
  			goto out;
  
  		pos += written;
ea9b9907b   Nick Piggin   fuse: implement p...
1129

e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1130
  		written_buffered = fuse_perform_write(iocb, mapping, from, pos);
4273b793e   Anand Avati   fuse: O_DIRECT su...
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
  		if (written_buffered < 0) {
  			err = written_buffered;
  			goto out;
  		}
  		endbyte = pos + written_buffered - 1;
  
  		err = filemap_write_and_wait_range(file->f_mapping, pos,
  						   endbyte);
  		if (err)
  			goto out;
  
  		invalidate_mapping_pages(file->f_mapping,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1143
1144
  					 pos >> PAGE_SHIFT,
  					 endbyte >> PAGE_SHIFT);
4273b793e   Anand Avati   fuse: O_DIRECT su...
1145
1146
1147
1148
  
  		written += written_buffered;
  		iocb->ki_pos = pos + written_buffered;
  	} else {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1149
  		written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos);
4273b793e   Anand Avati   fuse: O_DIRECT su...
1150
  		if (written >= 0)
3309dd04c   Al Viro   switch generic_wr...
1151
  			iocb->ki_pos += written;
4273b793e   Anand Avati   fuse: O_DIRECT su...
1152
  	}
ea9b9907b   Nick Piggin   fuse: implement p...
1153
1154
  out:
  	current->backing_dev_info = NULL;
5955102c9   Al Viro   wrappers for ->i_...
1155
  	inode_unlock(inode);
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1156
1157
  	if (written > 0)
  		written = generic_write_sync(iocb, written);
ea9b9907b   Nick Piggin   fuse: implement p...
1158
1159
1160
  
  	return written ? written : err;
  }
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1161
1162
  static inline void fuse_page_descs_length_init(struct fuse_req *req,
  		unsigned index, unsigned nr_pages)
85f40aec8   Maxim Patlasov   fuse: use req->pa...
1163
1164
  {
  	int i;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1165
  	for (i = index; i < index + nr_pages; i++)
85f40aec8   Maxim Patlasov   fuse: use req->pa...
1166
1167
1168
  		req->page_descs[i].length = PAGE_SIZE -
  			req->page_descs[i].offset;
  }
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
  {
  	return (unsigned long)ii->iov->iov_base + ii->iov_offset;
  }
  
  static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
  					size_t max_size)
  {
  	return min(iov_iter_single_seg_count(ii), max_size);
  }
b98d023a2   Maxim Patlasov   fuse: pass iov[] ...
1179
  static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
ce60a2f15   Miklos Szeredi   fuse: fix argumen...
1180
  			       size_t *nbytesp, int write)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1181
  {
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1182
  	size_t nbytes = 0;  /* # bytes already packed in req */
742f99270   Ashish Samant   fuse: return patr...
1183
  	ssize_t ret = 0;
b98d023a2   Maxim Patlasov   fuse: pass iov[] ...
1184

f4975c67d   Miklos Szeredi   fuse: allow kerne...
1185
  	/* Special case for kernel I/O: can copy directly into the buffer */
62a8067a7   Al Viro   bio_vec-backed io...
1186
  	if (ii->type & ITER_KVEC) {
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1187
1188
  		unsigned long user_addr = fuse_get_user_addr(ii);
  		size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1189
1190
1191
1192
  		if (write)
  			req->in.args[1].value = (void *) user_addr;
  		else
  			req->out.args[0].value = (void *) user_addr;
b98d023a2   Maxim Patlasov   fuse: pass iov[] ...
1193
1194
  		iov_iter_advance(ii, frag_size);
  		*nbytesp = frag_size;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1195
1196
  		return 0;
  	}
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1197

5565a9d88   Maxim Patlasov   fuse: optimize __...
1198
  	while (nbytes < *nbytesp && req->num_pages < req->max_pages) {
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1199
  		unsigned npages;
f67da30c1   Al Viro   new helper: iov_i...
1200
  		size_t start;
742f99270   Ashish Samant   fuse: return patr...
1201
  		ret = iov_iter_get_pages(ii, &req->pages[req->num_pages],
2c80929c4   Miklos Szeredi   fuse: honour max_...
1202
  					*nbytesp - nbytes,
c7f3888ad   Al Viro   switch iov_iter_g...
1203
1204
  					req->max_pages - req->num_pages,
  					&start);
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1205
  		if (ret < 0)
742f99270   Ashish Samant   fuse: return patr...
1206
  			break;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1207

c9c37e2e6   Al Viro   fuse: switch to i...
1208
1209
  		iov_iter_advance(ii, ret);
  		nbytes += ret;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1210

c9c37e2e6   Al Viro   fuse: switch to i...
1211
1212
  		ret += start;
  		npages = (ret + PAGE_SIZE - 1) / PAGE_SIZE;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1213

c9c37e2e6   Al Viro   fuse: switch to i...
1214
  		req->page_descs[req->num_pages].offset = start;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1215
1216
1217
1218
  		fuse_page_descs_length_init(req, req->num_pages, npages);
  
  		req->num_pages += npages;
  		req->page_descs[req->num_pages - 1].length -=
c9c37e2e6   Al Viro   fuse: switch to i...
1219
  			(PAGE_SIZE - ret) & (PAGE_SIZE - 1);
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1220
  	}
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1221
1222
1223
1224
1225
  
  	if (write)
  		req->in.argpages = 1;
  	else
  		req->out.argpages = 1;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
1226
  	*nbytesp = nbytes;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1227

2c932d4c9   Ashish Samant   fuse: Fix return ...
1228
  	return ret < 0 ? ret : 0;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1229
  }
5565a9d88   Maxim Patlasov   fuse: optimize __...
1230
1231
  static inline int fuse_iter_npages(const struct iov_iter *ii_p)
  {
f67da30c1   Al Viro   new helper: iov_i...
1232
  	return iov_iter_npages(ii_p, FUSE_MAX_PAGES_PER_REQ);
5565a9d88   Maxim Patlasov   fuse: optimize __...
1233
  }
d22a943f4   Al Viro   fuse: pull iov_it...
1234
1235
  ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
  		       loff_t *ppos, int flags)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1236
  {
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
1237
1238
  	int write = flags & FUSE_DIO_WRITE;
  	int cuse = flags & FUSE_DIO_CUSE;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1239
  	struct file *file = io->iocb->ki_filp;
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
1240
  	struct inode *inode = file->f_mapping->host;
2106cb189   Miklos Szeredi   fuse: don't use i...
1241
1242
  	struct fuse_file *ff = file->private_data;
  	struct fuse_conn *fc = ff->fc;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1243
1244
  	size_t nmax = write ? fc->max_write : fc->max_read;
  	loff_t pos = *ppos;
d22a943f4   Al Viro   fuse: pull iov_it...
1245
  	size_t count = iov_iter_count(iter);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1246
1247
  	pgoff_t idx_from = pos >> PAGE_SHIFT;
  	pgoff_t idx_to = (pos + count - 1) >> PAGE_SHIFT;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1248
  	ssize_t res = 0;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
1249
  	struct fuse_req *req;
742f99270   Ashish Samant   fuse: return patr...
1250
  	int err = 0;
248d86e87   Miklos Szeredi   [PATCH] fuse: fai...
1251

de82b9230   Brian Foster   fuse: allocate fo...
1252
  	if (io->async)
d22a943f4   Al Viro   fuse: pull iov_it...
1253
  		req = fuse_get_req_for_background(fc, fuse_iter_npages(iter));
de82b9230   Brian Foster   fuse: allocate fo...
1254
  	else
d22a943f4   Al Viro   fuse: pull iov_it...
1255
  		req = fuse_get_req(fc, fuse_iter_npages(iter));
ce1d5a491   Miklos Szeredi   [PATCH] fuse: cle...
1256
1257
  	if (IS_ERR(req))
  		return PTR_ERR(req);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1258

ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
1259
1260
  	if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) {
  		if (!write)
5955102c9   Al Viro   wrappers for ->i_...
1261
  			inode_lock(inode);
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
1262
1263
  		fuse_sync_writes(inode);
  		if (!write)
5955102c9   Al Viro   wrappers for ->i_...
1264
  			inode_unlock(inode);
ea8cd3339   Pavel Emelyanov   fuse: Fix O_DIREC...
1265
  	}
61c12b49e   Ashish Samant   fuse: Dont call s...
1266
  	io->should_dirty = !write && iter_is_iovec(iter);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1267
  	while (count) {
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1268
  		size_t nres;
2106cb189   Miklos Szeredi   fuse: don't use i...
1269
  		fl_owner_t owner = current->files;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1270
  		size_t nbytes = min(count, nmax);
742f99270   Ashish Samant   fuse: return patr...
1271
1272
  		err = fuse_get_user_pages(req, iter, &nbytes, write);
  		if (err && !nbytes)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1273
  			break;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1274

413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1275
  		if (write)
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
1276
  			nres = fuse_send_write(req, io, pos, nbytes, owner);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1277
  		else
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
1278
  			nres = fuse_send_read(req, io, pos, nbytes, owner);
2106cb189   Miklos Szeredi   fuse: don't use i...
1279

36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
1280
  		if (!io->async)
61c12b49e   Ashish Samant   fuse: Dont call s...
1281
  			fuse_release_user_pages(req, io->should_dirty);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1282
  		if (req->out.h.error) {
742f99270   Ashish Samant   fuse: return patr...
1283
  			err = req->out.h.error;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1284
1285
  			break;
  		} else if (nres > nbytes) {
742f99270   Ashish Samant   fuse: return patr...
1286
1287
  			res = 0;
  			err = -EIO;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1288
1289
1290
1291
1292
  			break;
  		}
  		count -= nres;
  		res += nres;
  		pos += nres;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1293
1294
  		if (nres != nbytes)
  			break;
56cf34ff0   Miklos Szeredi   [fuse] Direct I/O...
1295
1296
  		if (count) {
  			fuse_put_request(fc, req);
de82b9230   Brian Foster   fuse: allocate fo...
1297
1298
  			if (io->async)
  				req = fuse_get_req_for_background(fc,
d22a943f4   Al Viro   fuse: pull iov_it...
1299
  					fuse_iter_npages(iter));
de82b9230   Brian Foster   fuse: allocate fo...
1300
  			else
d22a943f4   Al Viro   fuse: pull iov_it...
1301
  				req = fuse_get_req(fc, fuse_iter_npages(iter));
56cf34ff0   Miklos Szeredi   [fuse] Direct I/O...
1302
1303
1304
  			if (IS_ERR(req))
  				break;
  		}
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1305
  	}
f60311d5f   Anand V. Avati   fuse: prevent fus...
1306
1307
  	if (!IS_ERR(req))
  		fuse_put_request(fc, req);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1308
  	if (res > 0)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1309
  		*ppos = pos;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1310

742f99270   Ashish Samant   fuse: return patr...
1311
  	return res > 0 ? res : err;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1312
  }
08cbf542b   Tejun Heo   fuse: export symb...
1313
  EXPORT_SYMBOL_GPL(fuse_direct_io);
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1314

36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
1315
  static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
d22a943f4   Al Viro   fuse: pull iov_it...
1316
1317
  				  struct iov_iter *iter,
  				  loff_t *ppos)
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1318
  {
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1319
  	ssize_t res;
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1320
  	struct inode *inode = file_inode(io->iocb->ki_filp);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1321
1322
1323
  
  	if (is_bad_inode(inode))
  		return -EIO;
d22a943f4   Al Viro   fuse: pull iov_it...
1324
  	res = fuse_direct_io(io, iter, ppos, 0);
d09cb9d7f   Miklos Szeredi   fuse: prepare fus...
1325
1326
1327
1328
  
  	fuse_invalidate_attr(inode);
  
  	return res;
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
1329
  }
153162636   Al Viro   fuse: switch fuse...
1330
  static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
b98d023a2   Maxim Patlasov   fuse: pass iov[] ...
1331
  {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1332
  	struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
153162636   Al Viro   fuse: switch fuse...
1333
  	return __fuse_direct_read(&io, to, &iocb->ki_pos);
b98d023a2   Maxim Patlasov   fuse: pass iov[] ...
1334
  }
153162636   Al Viro   fuse: switch fuse...
1335
  static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
4273b793e   Anand Avati   fuse: O_DIRECT su...
1336
  {
e1c0eecba   Miklos Szeredi   fuse: honor iocb ...
1337
1338
  	struct inode *inode = file_inode(iocb->ki_filp);
  	struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
153162636   Al Viro   fuse: switch fuse...
1339
  	ssize_t res;
4273b793e   Anand Avati   fuse: O_DIRECT su...
1340
1341
1342
1343
1344
  
  	if (is_bad_inode(inode))
  		return -EIO;
  
  	/* Don't allow parallel writes to the same file */
5955102c9   Al Viro   wrappers for ->i_...
1345
  	inode_lock(inode);
3309dd04c   Al Viro   switch generic_wr...
1346
1347
  	res = generic_write_checks(iocb, from);
  	if (res > 0)
812408fb5   Al Viro   expand __fuse_dir...
1348
  		res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE);
812408fb5   Al Viro   expand __fuse_dir...
1349
  	fuse_invalidate_attr(inode);
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
1350
  	if (res > 0)
153162636   Al Viro   fuse: switch fuse...
1351
  		fuse_write_update_size(inode, iocb->ki_pos);
5955102c9   Al Viro   wrappers for ->i_...
1352
  	inode_unlock(inode);
4273b793e   Anand Avati   fuse: O_DIRECT su...
1353
1354
1355
  
  	return res;
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1356
  static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1357
  {
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1358
1359
1360
1361
  	int i;
  
  	for (i = 0; i < req->num_pages; i++)
  		__free_page(req->pages[i]);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1362
1363
1364
  
  	if (req->ff)
  		fuse_file_put(req->ff, false);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1365
1366
1367
1368
1369
1370
  }
  
  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);
de1414a65   Christoph Hellwig   fs: export inode_...
1371
  	struct backing_dev_info *bdi = inode_to_bdi(inode);
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1372
  	int i;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1373
1374
  
  	list_del(&req->writepages_entry);
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1375
  	for (i = 0; i < req->num_pages; i++) {
93f78d882   Tejun Heo   writeback: move b...
1376
  		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
11fb99898   Mel Gorman   mm: move most fil...
1377
  		dec_node_page_state(req->pages[i], NR_WRITEBACK_TEMP);
93f78d882   Tejun Heo   writeback: move b...
1378
  		wb_writeout_inc(&bdi->wb);
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1379
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1380
1381
1382
1383
  	wake_up(&fi->page_waitq);
  }
  
  /* Called under fc->lock, may release and reacquire it */
6eaf4782e   Maxim Patlasov   fuse: writepages:...
1384
1385
  static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req,
  				loff_t size)
b9ca67b2d   Miklos Szeredi   fuse: fix lock an...
1386
1387
  __releases(fc->lock)
  __acquires(fc->lock)
3be5a52b3   Miklos Szeredi   fuse: support wri...
1388
1389
  {
  	struct fuse_inode *fi = get_fuse_inode(req->inode);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1390
  	struct fuse_write_in *inarg = &req->misc.write.in;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1391
  	__u64 data_size = req->num_pages * PAGE_SIZE;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1392
1393
1394
  
  	if (!fc->connected)
  		goto out_free;
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1395
1396
  	if (inarg->offset + data_size <= size) {
  		inarg->size = data_size;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1397
  	} else if (inarg->offset < size) {
385b12681   Pavel Emelyanov   fuse: Prepare to ...
1398
  		inarg->size = size - inarg->offset;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1399
1400
1401
  	} else {
  		/* Got truncated off completely */
  		goto out_free;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1402
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1403
1404
1405
  
  	req->in.args[1].size = inarg->size;
  	fi->writectr++;
b93f858ab   Tejun Heo   fuse: add fuse_ p...
1406
  	fuse_request_send_background_locked(fc, req);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1407
1408
1409
1410
1411
1412
  	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...
1413
  	fuse_put_request(fc, req);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1414
  	spin_lock(&fc->lock);
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1415
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1416
1417
1418
1419
1420
1421
1422
  /*
   * 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...
1423
1424
  __releases(fc->lock)
  __acquires(fc->lock)
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1425
  {
3be5a52b3   Miklos Szeredi   fuse: support wri...
1426
1427
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
6eaf4782e   Maxim Patlasov   fuse: writepages:...
1428
  	size_t crop = i_size_read(inode);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1429
1430
1431
1432
1433
  	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);
6eaf4782e   Maxim Patlasov   fuse: writepages:...
1434
  		fuse_send_writepage(fc, req, crop);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
  	}
  }
  
  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);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1445
  	while (req->misc.write.next) {
6eaf4782e   Maxim Patlasov   fuse: writepages:...
1446
1447
  		struct fuse_conn *fc = get_fuse_conn(inode);
  		struct fuse_write_in *inarg = &req->misc.write.in;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1448
1449
1450
  		struct fuse_req *next = req->misc.write.next;
  		req->misc.write.next = next->misc.write.next;
  		next->misc.write.next = NULL;
ce128de62   Maxim Patlasov   fuse: writepages:...
1451
  		next->ff = fuse_file_get(req->ff);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1452
  		list_add(&next->writepages_entry, &fi->writepages);
6eaf4782e   Maxim Patlasov   fuse: writepages:...
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
  
  		/*
  		 * Skip fuse_flush_writepages() to make it easy to crop requests
  		 * based on primary request size.
  		 *
  		 * 1st case (trivial): there are no concurrent activities using
  		 * fuse_set/release_nowrite.  Then we're on safe side because
  		 * fuse_flush_writepages() would call fuse_send_writepage()
  		 * anyway.
  		 *
  		 * 2nd case: someone called fuse_set_nowrite and it is waiting
  		 * now for completion of all in-flight requests.  This happens
  		 * rarely and no more than once per page, so this should be
  		 * okay.
  		 *
  		 * 3rd case: someone (e.g. fuse_do_setattr()) is in the middle
  		 * of fuse_set_nowrite..fuse_release_nowrite section.  The fact
  		 * that fuse_set_nowrite returned implies that all in-flight
  		 * requests were completed along with all of their secondary
  		 * requests.  Further primary requests are blocked by negative
  		 * writectr.  Hence there cannot be any in-flight requests and
  		 * no invocations of fuse_writepage_end() while we're in
  		 * fuse_set_nowrite..fuse_release_nowrite section.
  		 */
  		fuse_send_writepage(fc, next, inarg->offset + inarg->size);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1478
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1479
1480
1481
1482
1483
  	fi->writectr--;
  	fuse_writepage_finish(fc, req);
  	spin_unlock(&fc->lock);
  	fuse_writepage_free(fc, req);
  }
1e18bda86   Miklos Szeredi   fuse: add .write_...
1484
1485
  static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
  					       struct fuse_inode *fi)
adcadfa8f   Pavel Emelyanov   fuse: Getting fil...
1486
  {
72523425f   Miklos Szeredi   fuse: don't BUG o...
1487
  	struct fuse_file *ff = NULL;
adcadfa8f   Pavel Emelyanov   fuse: Getting fil...
1488
1489
  
  	spin_lock(&fc->lock);
1e18bda86   Miklos Szeredi   fuse: add .write_...
1490
  	if (!list_empty(&fi->write_files)) {
72523425f   Miklos Szeredi   fuse: don't BUG o...
1491
1492
1493
1494
  		ff = list_entry(fi->write_files.next, struct fuse_file,
  				write_entry);
  		fuse_file_get(ff);
  	}
adcadfa8f   Pavel Emelyanov   fuse: Getting fil...
1495
1496
1497
1498
  	spin_unlock(&fc->lock);
  
  	return ff;
  }
1e18bda86   Miklos Szeredi   fuse: add .write_...
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
  static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
  					     struct fuse_inode *fi)
  {
  	struct fuse_file *ff = __fuse_write_file_get(fc, fi);
  	WARN_ON(!ff);
  	return ff;
  }
  
  int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
  	struct fuse_file *ff;
  	int err;
  
  	ff = __fuse_write_file_get(fc, fi);
ab9e13f7c   Maxim Patlasov   fuse: allow ctime...
1515
  	err = fuse_flush_times(inode, ff);
1e18bda86   Miklos Szeredi   fuse: add .write_...
1516
1517
1518
1519
1520
  	if (ff)
  		fuse_file_put(ff, 0);
  
  	return err;
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1521
1522
1523
1524
1525
1526
1527
  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;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1528
  	struct page *tmp_page;
72523425f   Miklos Szeredi   fuse: don't BUG o...
1529
  	int error = -ENOMEM;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1530
1531
  
  	set_page_writeback(page);
4250c0668   Maxim Patlasov   fuse: general inf...
1532
  	req = fuse_request_alloc_nofs(1);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1533
1534
  	if (!req)
  		goto err;
825d6d339   Miklos Szeredi   fuse: req use bitops
1535
1536
  	/* writeback always goes to bg_queue */
  	__set_bit(FR_BACKGROUND, &req->flags);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1537
1538
1539
  	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
  	if (!tmp_page)
  		goto err_free;
72523425f   Miklos Szeredi   fuse: don't BUG o...
1540
  	error = -EIO;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1541
  	req->ff = fuse_write_file_get(fc, fi);
72523425f   Miklos Szeredi   fuse: don't BUG o...
1542
  	if (!req->ff)
27f1b3632   Maxim Patlasov   fuse: release tem...
1543
  		goto err_nofile;
72523425f   Miklos Szeredi   fuse: don't BUG o...
1544

adcadfa8f   Pavel Emelyanov   fuse: Getting fil...
1545
  	fuse_write_fill(req, req->ff, page_offset(page), 0);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1546
1547
  
  	copy_highpage(tmp_page, page);
2d698b070   Miklos Szeredi   fuse: clean up fu...
1548
  	req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1549
  	req->misc.write.next = NULL;
f4975c67d   Miklos Szeredi   fuse: allow kerne...
1550
  	req->in.argpages = 1;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1551
1552
  	req->num_pages = 1;
  	req->pages[0] = tmp_page;
b2430d756   Maxim Patlasov   fuse: add per-pag...
1553
  	req->page_descs[0].offset = 0;
85f40aec8   Maxim Patlasov   fuse: use req->pa...
1554
  	req->page_descs[0].length = PAGE_SIZE;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1555
1556
  	req->end = fuse_writepage_end;
  	req->inode = inode;
93f78d882   Tejun Heo   writeback: move b...
1557
  	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
11fb99898   Mel Gorman   mm: move most fil...
1558
  	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1559
1560
1561
1562
1563
1564
  
  	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);
4a4ac4eba   Maxim Patlasov   fuse: postpone en...
1565
  	end_page_writeback(page);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1566
  	return 0;
27f1b3632   Maxim Patlasov   fuse: release tem...
1567
1568
  err_nofile:
  	__free_page(tmp_page);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1569
1570
1571
  err_free:
  	fuse_request_free(req);
  err:
9183976ef   Jeff Layton   fuse: set mapping...
1572
  	mapping_set_error(page->mapping, error);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1573
  	end_page_writeback(page);
72523425f   Miklos Szeredi   fuse: don't BUG o...
1574
  	return error;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1575
1576
1577
1578
1579
  }
  
  static int fuse_writepage(struct page *page, struct writeback_control *wbc)
  {
  	int err;
ff17be086   Miklos Szeredi   fuse: writepage: ...
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
  	if (fuse_page_is_writeback(page->mapping->host, page->index)) {
  		/*
  		 * ->writepages() should be called for sync() and friends.  We
  		 * should only get here on direct reclaim and then we are
  		 * allowed to skip a page which is already in flight
  		 */
  		WARN_ON(wbc->sync_mode == WB_SYNC_ALL);
  
  		redirty_page_for_writepage(wbc, page);
  		return 0;
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1591
1592
1593
1594
1595
  	err = fuse_writepage_locked(page);
  	unlock_page(page);
  
  	return err;
  }
26d614df1   Pavel Emelyanov   fuse: Implement w...
1596
1597
1598
1599
  struct fuse_fill_wb_data {
  	struct fuse_req *req;
  	struct fuse_file *ff;
  	struct inode *inode;
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1600
  	struct page **orig_pages;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1601
1602
1603
1604
1605
1606
1607
1608
  };
  
  static void fuse_writepages_send(struct fuse_fill_wb_data *data)
  {
  	struct fuse_req *req = data->req;
  	struct inode *inode = data->inode;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_inode *fi = get_fuse_inode(inode);
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1609
1610
  	int num_pages = req->num_pages;
  	int i;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1611
1612
1613
1614
1615
1616
  
  	req->ff = fuse_file_get(data->ff);
  	spin_lock(&fc->lock);
  	list_add_tail(&req->list, &fi->queued_writes);
  	fuse_flush_writepages(inode);
  	spin_unlock(&fc->lock);
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1617
1618
1619
  
  	for (i = 0; i < num_pages; i++)
  		end_page_writeback(data->orig_pages[i]);
26d614df1   Pavel Emelyanov   fuse: Implement w...
1620
  }
8b284dc47   Miklos Szeredi   fuse: writepages:...
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
  static bool fuse_writepage_in_flight(struct fuse_req *new_req,
  				     struct page *page)
  {
  	struct fuse_conn *fc = get_fuse_conn(new_req->inode);
  	struct fuse_inode *fi = get_fuse_inode(new_req->inode);
  	struct fuse_req *tmp;
  	struct fuse_req *old_req;
  	bool found = false;
  	pgoff_t curr_index;
  
  	BUG_ON(new_req->num_pages != 0);
  
  	spin_lock(&fc->lock);
  	list_del(&new_req->writepages_entry);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1635
1636
  	list_for_each_entry(old_req, &fi->writepages, writepages_entry) {
  		BUG_ON(old_req->inode != new_req->inode);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1637
  		curr_index = old_req->misc.write.in.offset >> PAGE_SHIFT;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1638
1639
1640
1641
1642
1643
  		if (curr_index <= page->index &&
  		    page->index < curr_index + old_req->num_pages) {
  			found = true;
  			break;
  		}
  	}
f6011081f   Maxim Patlasov   fuse: writepages:...
1644
1645
  	if (!found) {
  		list_add(&new_req->writepages_entry, &fi->writepages);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1646
  		goto out_unlock;
f6011081f   Maxim Patlasov   fuse: writepages:...
1647
  	}
8b284dc47   Miklos Szeredi   fuse: writepages:...
1648

f6011081f   Maxim Patlasov   fuse: writepages:...
1649
  	new_req->num_pages = 1;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1650
1651
  	for (tmp = old_req; tmp != NULL; tmp = tmp->misc.write.next) {
  		BUG_ON(tmp->inode != new_req->inode);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1652
  		curr_index = tmp->misc.write.in.offset >> PAGE_SHIFT;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1653
1654
1655
1656
1657
  		if (tmp->num_pages == 1 &&
  		    curr_index == page->index) {
  			old_req = tmp;
  		}
  	}
33e14b4df   Miklos Szeredi   fuse: req state u...
1658
  	if (old_req->num_pages == 1 && test_bit(FR_PENDING, &old_req->flags)) {
de1414a65   Christoph Hellwig   fs: export inode_...
1659
  		struct backing_dev_info *bdi = inode_to_bdi(page->mapping->host);
41b6e41fc   Maxim Patlasov   fuse: writepages:...
1660

8b284dc47   Miklos Szeredi   fuse: writepages:...
1661
1662
  		copy_highpage(old_req->pages[0], page);
  		spin_unlock(&fc->lock);
93f78d882   Tejun Heo   writeback: move b...
1663
  		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
11fb99898   Mel Gorman   mm: move most fil...
1664
  		dec_node_page_state(page, NR_WRITEBACK_TEMP);
93f78d882   Tejun Heo   writeback: move b...
1665
  		wb_writeout_inc(&bdi->wb);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
  		fuse_writepage_free(fc, new_req);
  		fuse_request_free(new_req);
  		goto out;
  	} else {
  		new_req->misc.write.next = old_req->misc.write.next;
  		old_req->misc.write.next = new_req;
  	}
  out_unlock:
  	spin_unlock(&fc->lock);
  out:
  	return found;
  }
26d614df1   Pavel Emelyanov   fuse: Implement w...
1678
1679
1680
1681
1682
1683
1684
1685
  static int fuse_writepages_fill(struct page *page,
  		struct writeback_control *wbc, void *_data)
  {
  	struct fuse_fill_wb_data *data = _data;
  	struct fuse_req *req = data->req;
  	struct inode *inode = data->inode;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct page *tmp_page;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1686
  	bool is_writeback;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1687
1688
1689
1690
1691
1692
1693
1694
  	int err;
  
  	if (!data->ff) {
  		err = -EIO;
  		data->ff = fuse_write_file_get(fc, get_fuse_inode(inode));
  		if (!data->ff)
  			goto out_unlock;
  	}
8b284dc47   Miklos Szeredi   fuse: writepages:...
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
  	/*
  	 * Being under writeback is unlikely but possible.  For example direct
  	 * read to an mmaped fuse file will set the page dirty twice; once when
  	 * the pages are faulted with get_user_pages(), and then after the read
  	 * completed.
  	 */
  	is_writeback = fuse_page_is_writeback(inode, page->index);
  
  	if (req && req->num_pages &&
  	    (is_writeback || req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1705
  	     (req->num_pages + 1) * PAGE_SIZE > fc->max_write ||
8b284dc47   Miklos Szeredi   fuse: writepages:...
1706
1707
1708
  	     data->orig_pages[req->num_pages - 1]->index + 1 != page->index)) {
  		fuse_writepages_send(data);
  		data->req = NULL;
26d614df1   Pavel Emelyanov   fuse: Implement w...
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
  	}
  	err = -ENOMEM;
  	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
  	if (!tmp_page)
  		goto out_unlock;
  
  	/*
  	 * The page must not be redirtied until the writeout is completed
  	 * (i.e. userspace has sent a reply to the write request).  Otherwise
  	 * there could be more than one temporary page instance for each real
  	 * page.
  	 *
  	 * This is ensured by holding the page lock in page_mkwrite() while
  	 * checking fuse_page_is_writeback().  We already hold the page lock
  	 * since clear_page_dirty_for_io() and keep it held until we add the
  	 * request to the fi->writepages list and increment req->num_pages.
  	 * After this fuse_page_is_writeback() will indicate that the page is
  	 * under writeback, so we can release the page lock.
  	 */
  	if (data->req == NULL) {
  		struct fuse_inode *fi = get_fuse_inode(inode);
  
  		err = -ENOMEM;
  		req = fuse_request_alloc_nofs(FUSE_MAX_PAGES_PER_REQ);
  		if (!req) {
  			__free_page(tmp_page);
  			goto out_unlock;
  		}
  
  		fuse_write_fill(req, data->ff, page_offset(page), 0);
  		req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
8b284dc47   Miklos Szeredi   fuse: writepages:...
1740
  		req->misc.write.next = NULL;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1741
  		req->in.argpages = 1;
825d6d339   Miklos Szeredi   fuse: req use bitops
1742
  		__set_bit(FR_BACKGROUND, &req->flags);
26d614df1   Pavel Emelyanov   fuse: Implement w...
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
  		req->num_pages = 0;
  		req->end = fuse_writepage_end;
  		req->inode = inode;
  
  		spin_lock(&fc->lock);
  		list_add(&req->writepages_entry, &fi->writepages);
  		spin_unlock(&fc->lock);
  
  		data->req = req;
  	}
  	set_page_writeback(page);
  
  	copy_highpage(tmp_page, page);
  	req->pages[req->num_pages] = tmp_page;
  	req->page_descs[req->num_pages].offset = 0;
  	req->page_descs[req->num_pages].length = PAGE_SIZE;
93f78d882   Tejun Heo   writeback: move b...
1759
  	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
11fb99898   Mel Gorman   mm: move most fil...
1760
  	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
8b284dc47   Miklos Szeredi   fuse: writepages:...
1761
1762
1763
1764
1765
1766
1767
  
  	err = 0;
  	if (is_writeback && fuse_writepage_in_flight(req, page)) {
  		end_page_writeback(page);
  		data->req = NULL;
  		goto out_unlock;
  	}
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1768
  	data->orig_pages[req->num_pages] = page;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1769
1770
1771
1772
1773
1774
1775
1776
  
  	/*
  	 * Protected by fc->lock against concurrent access by
  	 * fuse_page_is_writeback().
  	 */
  	spin_lock(&fc->lock);
  	req->num_pages++;
  	spin_unlock(&fc->lock);
26d614df1   Pavel Emelyanov   fuse: Implement w...
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  out_unlock:
  	unlock_page(page);
  
  	return err;
  }
  
  static int fuse_writepages(struct address_space *mapping,
  			   struct writeback_control *wbc)
  {
  	struct inode *inode = mapping->host;
  	struct fuse_fill_wb_data data;
  	int err;
  
  	err = -EIO;
  	if (is_bad_inode(inode))
  		goto out;
  
  	data.inode = inode;
  	data.req = NULL;
  	data.ff = NULL;
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1797
  	err = -ENOMEM;
f2b3455e4   Fabian Frederick   fuse: replace cou...
1798
1799
  	data.orig_pages = kcalloc(FUSE_MAX_PAGES_PER_REQ,
  				  sizeof(struct page *),
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1800
1801
1802
  				  GFP_NOFS);
  	if (!data.orig_pages)
  		goto out;
26d614df1   Pavel Emelyanov   fuse: Implement w...
1803
1804
1805
1806
1807
1808
1809
1810
1811
  	err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
  	if (data.req) {
  		/* Ignore errors if we can write at least one page */
  		BUG_ON(!data.req->num_pages);
  		fuse_writepages_send(&data);
  		err = 0;
  	}
  	if (data.ff)
  		fuse_file_put(data.ff, false);
2d033eaa0   Maxim Patlasov   fuse: fix race in...
1812
1813
  
  	kfree(data.orig_pages);
26d614df1   Pavel Emelyanov   fuse: Implement w...
1814
1815
1816
  out:
  	return err;
  }
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1817
1818
1819
1820
1821
1822
1823
1824
  /*
   * It's worthy to make sure that space is reserved on disk for the write,
   * but how to implement it without killing performance need more thinking.
   */
  static int fuse_write_begin(struct file *file, struct address_space *mapping,
  		loff_t pos, unsigned len, unsigned flags,
  		struct page **pagep, void **fsdata)
  {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1825
  	pgoff_t index = pos >> PAGE_SHIFT;
a455589f1   Al Viro   assorted conversi...
1826
  	struct fuse_conn *fc = get_fuse_conn(file_inode(file));
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  	struct page *page;
  	loff_t fsize;
  	int err = -ENOMEM;
  
  	WARN_ON(!fc->writeback_cache);
  
  	page = grab_cache_page_write_begin(mapping, index, flags);
  	if (!page)
  		goto error;
  
  	fuse_wait_on_page_writeback(mapping->host, page->index);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1838
  	if (PageUptodate(page) || len == PAGE_SIZE)
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1839
1840
1841
1842
1843
1844
  		goto success;
  	/*
  	 * Check if the start this page comes after the end of file, in which
  	 * case the readpage can be optimized away.
  	 */
  	fsize = i_size_read(mapping->host);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1845
1846
  	if (fsize <= (pos & PAGE_MASK)) {
  		size_t off = pos & ~PAGE_MASK;
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
  		if (off)
  			zero_user_segment(page, 0, off);
  		goto success;
  	}
  	err = fuse_do_readpage(file, page);
  	if (err)
  		goto cleanup;
  success:
  	*pagep = page;
  	return 0;
  
  cleanup:
  	unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1860
  	put_page(page);
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1861
1862
1863
1864
1865
1866
1867
1868
1869
  error:
  	return err;
  }
  
  static int fuse_write_end(struct file *file, struct address_space *mapping,
  		loff_t pos, unsigned len, unsigned copied,
  		struct page *page, void *fsdata)
  {
  	struct inode *inode = page->mapping->host;
59c3b76cc   Miklos Szeredi   fuse: fix fuse_wr...
1870
1871
1872
  	/* Haven't copied anything?  Skip zeroing, size extending, dirtying. */
  	if (!copied)
  		goto unlock;
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1873
1874
  	if (!PageUptodate(page)) {
  		/* Zero any unwritten bytes at the end of the page */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1875
  		size_t endoff = (pos + copied) & ~PAGE_MASK;
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1876
  		if (endoff)
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1877
  			zero_user_segment(page, endoff, PAGE_SIZE);
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1878
1879
1880
1881
1882
  		SetPageUptodate(page);
  	}
  
  	fuse_write_update_size(inode, pos + copied);
  	set_page_dirty(page);
59c3b76cc   Miklos Szeredi   fuse: fix fuse_wr...
1883
1884
  
  unlock:
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1885
  	unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1886
  	put_page(page);
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
1887
1888
1889
  
  	return copied;
  }
3be5a52b3   Miklos Szeredi   fuse: support wri...
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
  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
   */
11bac8000   Dave Jiang   mm, fs: reduce fa...
1926
  static int fuse_page_mkwrite(struct vm_fault *vmf)
3be5a52b3   Miklos Szeredi   fuse: support wri...
1927
  {
c2ec175c3   Nick Piggin   mm: page_mkwrite ...
1928
  	struct page *page = vmf->page;
11bac8000   Dave Jiang   mm, fs: reduce fa...
1929
  	struct inode *inode = file_inode(vmf->vma->vm_file);
cca243704   Miklos Szeredi   fuse: lock page i...
1930

11bac8000   Dave Jiang   mm, fs: reduce fa...
1931
  	file_update_time(vmf->vma->vm_file);
cca243704   Miklos Szeredi   fuse: lock page i...
1932
1933
1934
1935
1936
  	lock_page(page);
  	if (page->mapping != inode->i_mapping) {
  		unlock_page(page);
  		return VM_FAULT_NOPAGE;
  	}
3be5a52b3   Miklos Szeredi   fuse: support wri...
1937
1938
  
  	fuse_wait_on_page_writeback(inode, page->index);
cca243704   Miklos Szeredi   fuse: lock page i...
1939
  	return VM_FAULT_LOCKED;
3be5a52b3   Miklos Szeredi   fuse: support wri...
1940
  }
f0f37e2f7   Alexey Dobriyan   const: mark struc...
1941
  static const struct vm_operations_struct fuse_file_vm_ops = {
3be5a52b3   Miklos Szeredi   fuse: support wri...
1942
1943
  	.close		= fuse_vma_close,
  	.fault		= filemap_fault,
f1820361f   Kirill A. Shutemov   mm: implement ->m...
1944
  	.map_pages	= filemap_map_pages,
3be5a52b3   Miklos Szeredi   fuse: support wri...
1945
1946
1947
1948
1949
  	.page_mkwrite	= fuse_page_mkwrite,
  };
  
  static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
  {
650b22b94   Pavel Emelyanov   fuse: Linking fil...
1950
1951
  	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
  		fuse_link_write_file(file);
3be5a52b3   Miklos Szeredi   fuse: support wri...
1952
1953
  	file_accessed(file);
  	vma->vm_ops = &fuse_file_vm_ops;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
1954
1955
  	return 0;
  }
fc280c969   Miklos Szeredi   fuse: allow priva...
1956
1957
1958
1959
1960
  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...
1961
  	invalidate_inode_pages2(file->f_mapping);
fc280c969   Miklos Szeredi   fuse: allow priva...
1962
1963
  	return generic_file_mmap(file, vma);
  }
0b6e9ea04   Seth Forshee   fuse: Add support...
1964
1965
  static int convert_fuse_file_lock(struct fuse_conn *fc,
  				  const struct fuse_file_lock *ffl,
714212593   Miklos Szeredi   [PATCH] fuse: add...
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
  				  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;
0b6e9ea04   Seth Forshee   fuse: Add support...
1980
1981
  
  		/*
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
1982
1983
  		 * Convert pid into init's pid namespace.  The locks API will
  		 * translate it into the caller's pid namespace.
0b6e9ea04   Seth Forshee   fuse: Add support...
1984
1985
  		 */
  		rcu_read_lock();
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
1986
  		fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns);
0b6e9ea04   Seth Forshee   fuse: Add support...
1987
  		rcu_read_unlock();
714212593   Miklos Szeredi   [PATCH] fuse: add...
1988
1989
1990
1991
1992
1993
1994
1995
  		break;
  
  	default:
  		return -EIO;
  	}
  	fl->fl_type = ffl->type;
  	return 0;
  }
7078187a7   Miklos Szeredi   fuse: introduce f...
1996
  static void fuse_lk_fill(struct fuse_args *args, struct file *file,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
1997
  			 const struct file_lock *fl, int opcode, pid_t pid,
7078187a7   Miklos Szeredi   fuse: introduce f...
1998
  			 int flock, struct fuse_lk_in *inarg)
714212593   Miklos Szeredi   [PATCH] fuse: add...
1999
  {
6131ffaa1   Al Viro   more file_inode()...
2000
  	struct inode *inode = file_inode(file);
9c8ef5614   Miklos Szeredi   [PATCH] fuse: scr...
2001
  	struct fuse_conn *fc = get_fuse_conn(inode);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2002
  	struct fuse_file *ff = file->private_data;
7078187a7   Miklos Szeredi   fuse: introduce f...
2003
2004
2005
2006
2007
2008
2009
2010
  
  	memset(inarg, 0, sizeof(*inarg));
  	inarg->fh = ff->fh;
  	inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
  	inarg->lk.start = fl->fl_start;
  	inarg->lk.end = fl->fl_end;
  	inarg->lk.type = fl->fl_type;
  	inarg->lk.pid = pid;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2011
  	if (flock)
7078187a7   Miklos Szeredi   fuse: introduce f...
2012
2013
2014
2015
2016
2017
  		inarg->lk_flags |= FUSE_LK_FLOCK;
  	args->in.h.opcode = opcode;
  	args->in.h.nodeid = get_node_id(inode);
  	args->in.numargs = 1;
  	args->in.args[0].size = sizeof(*inarg);
  	args->in.args[0].value = inarg;
714212593   Miklos Szeredi   [PATCH] fuse: add...
2018
2019
2020
2021
  }
  
  static int fuse_getlk(struct file *file, struct file_lock *fl)
  {
6131ffaa1   Al Viro   more file_inode()...
2022
  	struct inode *inode = file_inode(file);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2023
  	struct fuse_conn *fc = get_fuse_conn(inode);
7078187a7   Miklos Szeredi   fuse: introduce f...
2024
2025
  	FUSE_ARGS(args);
  	struct fuse_lk_in inarg;
714212593   Miklos Szeredi   [PATCH] fuse: add...
2026
2027
  	struct fuse_lk_out outarg;
  	int err;
7078187a7   Miklos Szeredi   fuse: introduce f...
2028
2029
2030
2031
2032
  	fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg);
  	args.out.numargs = 1;
  	args.out.args[0].size = sizeof(outarg);
  	args.out.args[0].value = &outarg;
  	err = fuse_simple_request(fc, &args);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2033
  	if (!err)
0b6e9ea04   Seth Forshee   fuse: Add support...
2034
  		err = convert_fuse_file_lock(fc, &outarg.lk, fl);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2035
2036
2037
  
  	return err;
  }
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2038
  static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
714212593   Miklos Szeredi   [PATCH] fuse: add...
2039
  {
6131ffaa1   Al Viro   more file_inode()...
2040
  	struct inode *inode = file_inode(file);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2041
  	struct fuse_conn *fc = get_fuse_conn(inode);
7078187a7   Miklos Szeredi   fuse: introduce f...
2042
2043
  	FUSE_ARGS(args);
  	struct fuse_lk_in inarg;
714212593   Miklos Szeredi   [PATCH] fuse: add...
2044
  	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
0b6e9ea04   Seth Forshee   fuse: Add support...
2045
2046
  	struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
  	pid_t pid_nr = pid_nr_ns(pid, fc->pid_ns);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2047
  	int err;
8fb47a4fb   J. Bruce Fields   locks: rename loc...
2048
  	if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
48e90761b   Miklos Szeredi   fuse: lockd support
2049
2050
2051
  		/* NLM needs asynchronous locks, which we don't support yet */
  		return -ENOLCK;
  	}
714212593   Miklos Szeredi   [PATCH] fuse: add...
2052
  	/* Unlock on close is handled by the flush method */
50f2112cf   Benjamin Coddington   locks: Set FL_CLO...
2053
  	if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
714212593   Miklos Szeredi   [PATCH] fuse: add...
2054
  		return 0;
0b6e9ea04   Seth Forshee   fuse: Add support...
2055
  	fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
7078187a7   Miklos Szeredi   fuse: introduce f...
2056
  	err = fuse_simple_request(fc, &args);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2057

a4d27e75f   Miklos Szeredi   [PATCH] fuse: add...
2058
2059
2060
  	/* locking is restartable */
  	if (err == -EINTR)
  		err = -ERESTARTSYS;
7078187a7   Miklos Szeredi   fuse: introduce f...
2061

714212593   Miklos Szeredi   [PATCH] fuse: add...
2062
2063
2064
2065
2066
  	return err;
  }
  
  static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
  {
6131ffaa1   Al Viro   more file_inode()...
2067
  	struct inode *inode = file_inode(file);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2068
2069
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int err;
48e90761b   Miklos Szeredi   fuse: lockd support
2070
2071
2072
  	if (cmd == F_CANCELLK) {
  		err = 0;
  	} else if (cmd == F_GETLK) {
714212593   Miklos Szeredi   [PATCH] fuse: add...
2073
  		if (fc->no_lock) {
9d6a8c5c2   Marc Eshel   locks: give posix...
2074
  			posix_test_lock(file, fl);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2075
2076
2077
2078
2079
  			err = 0;
  		} else
  			err = fuse_getlk(file, fl);
  	} else {
  		if (fc->no_lock)
48e90761b   Miklos Szeredi   fuse: lockd support
2080
  			err = posix_lock_file(file, fl, NULL);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2081
  		else
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2082
  			err = fuse_setlk(file, fl, 0);
714212593   Miklos Szeredi   [PATCH] fuse: add...
2083
2084
2085
  	}
  	return err;
  }
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2086
2087
  static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
  {
6131ffaa1   Al Viro   more file_inode()...
2088
  	struct inode *inode = file_inode(file);
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2089
2090
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int err;
37fb3a30b   Miklos Szeredi   fuse: fix flock
2091
  	if (fc->no_flock) {
4f6563677   Benjamin Coddington   Move locks API us...
2092
  		err = locks_lock_file_wait(file, fl);
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2093
  	} else {
37fb3a30b   Miklos Szeredi   fuse: fix flock
2094
  		struct fuse_file *ff = file->private_data;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2095
  		/* emulate flock with POSIX locks */
37fb3a30b   Miklos Szeredi   fuse: fix flock
2096
  		ff->flock = true;
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2097
2098
2099
2100
2101
  		err = fuse_setlk(file, fl, 1);
  	}
  
  	return err;
  }
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2102
2103
2104
2105
  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);
7078187a7   Miklos Szeredi   fuse: introduce f...
2106
  	FUSE_ARGS(args);
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2107
2108
2109
2110
2111
2112
  	struct fuse_bmap_in inarg;
  	struct fuse_bmap_out outarg;
  	int err;
  
  	if (!inode->i_sb->s_bdev || fc->no_bmap)
  		return 0;
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2113
2114
2115
  	memset(&inarg, 0, sizeof(inarg));
  	inarg.block = block;
  	inarg.blocksize = inode->i_sb->s_blocksize;
7078187a7   Miklos Szeredi   fuse: introduce f...
2116
2117
2118
2119
2120
2121
2122
2123
2124
  	args.in.h.opcode = FUSE_BMAP;
  	args.in.h.nodeid = get_node_id(inode);
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	args.out.numargs = 1;
  	args.out.args[0].size = sizeof(outarg);
  	args.out.args[0].value = &outarg;
  	err = fuse_simple_request(fc, &args);
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2125
2126
2127
2128
2129
  	if (err == -ENOSYS)
  		fc->no_bmap = 1;
  
  	return err ? 0 : outarg.block;
  }
0b5da8db1   Ravishankar N   fuse: add support...
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
  static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
  {
  	struct inode *inode = file->f_mapping->host;
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	struct fuse_file *ff = file->private_data;
  	FUSE_ARGS(args);
  	struct fuse_lseek_in inarg = {
  		.fh = ff->fh,
  		.offset = offset,
  		.whence = whence
  	};
  	struct fuse_lseek_out outarg;
  	int err;
  
  	if (fc->no_lseek)
  		goto fallback;
  
  	args.in.h.opcode = FUSE_LSEEK;
  	args.in.h.nodeid = ff->nodeid;
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	args.out.numargs = 1;
  	args.out.args[0].size = sizeof(outarg);
  	args.out.args[0].value = &outarg;
  	err = fuse_simple_request(fc, &args);
  	if (err) {
  		if (err == -ENOSYS) {
  			fc->no_lseek = 1;
  			goto fallback;
  		}
  		return err;
  	}
  
  	return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes);
  
  fallback:
5b97eeacb   Miklos Szeredi   fuse: getattr cle...
2167
  	err = fuse_update_attributes(inode, file);
0b5da8db1   Ravishankar N   fuse: add support...
2168
2169
2170
2171
2172
  	if (!err)
  		return generic_file_llseek(file, offset, whence);
  	else
  		return err;
  }
965c8e59c   Andrew Morton   lseek: the "whenc...
2173
  static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
5559b8f4d   Miklos Szeredi   fuse: fix race in...
2174
2175
  {
  	loff_t retval;
6131ffaa1   Al Viro   more file_inode()...
2176
  	struct inode *inode = file_inode(file);
5559b8f4d   Miklos Szeredi   fuse: fix race in...
2177

0b5da8db1   Ravishankar N   fuse: add support...
2178
2179
2180
2181
  	switch (whence) {
  	case SEEK_SET:
  	case SEEK_CUR:
  		 /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
965c8e59c   Andrew Morton   lseek: the "whenc...
2182
  		retval = generic_file_llseek(file, offset, whence);
0b5da8db1   Ravishankar N   fuse: add support...
2183
2184
  		break;
  	case SEEK_END:
5955102c9   Al Viro   wrappers for ->i_...
2185
  		inode_lock(inode);
5b97eeacb   Miklos Szeredi   fuse: getattr cle...
2186
  		retval = fuse_update_attributes(inode, file);
0b5da8db1   Ravishankar N   fuse: add support...
2187
2188
  		if (!retval)
  			retval = generic_file_llseek(file, offset, whence);
5955102c9   Al Viro   wrappers for ->i_...
2189
  		inode_unlock(inode);
0b5da8db1   Ravishankar N   fuse: add support...
2190
2191
2192
  		break;
  	case SEEK_HOLE:
  	case SEEK_DATA:
5955102c9   Al Viro   wrappers for ->i_...
2193
  		inode_lock(inode);
0b5da8db1   Ravishankar N   fuse: add support...
2194
  		retval = fuse_lseek(file, offset, whence);
5955102c9   Al Viro   wrappers for ->i_...
2195
  		inode_unlock(inode);
0b5da8db1   Ravishankar N   fuse: add support...
2196
2197
2198
2199
  		break;
  	default:
  		retval = -EINVAL;
  	}
c07c3d193   Miklos Szeredi   fuse: llseek opti...
2200

5559b8f4d   Miklos Szeredi   fuse: fix race in...
2201
2202
  	return retval;
  }
59efec7b9   Tejun Heo   fuse: implement i...
2203
  /*
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
2204
2205
2206
2207
2208
   * 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
2209
2210
2211
  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...
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  {
  #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...
2240
2241
2242
2243
2244
  /* 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;
fb6ccff66   Zach Brown   fuse: verify all ...
2245
  	for (n = 0; n < count; n++, iov++) {
7572777ee   Miklos Szeredi   fuse: verify ioct...
2246
2247
2248
2249
2250
2251
  		if (iov->iov_len > (size_t) max)
  			return -ENOMEM;
  		max -= iov->iov_len;
  	}
  	return 0;
  }
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
  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...
2286
  /*
59efec7b9   Tejun Heo   fuse: implement i...
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
   * 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...
2332
2333
  long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
  		   unsigned int flags)
59efec7b9   Tejun Heo   fuse: implement i...
2334
  {
59efec7b9   Tejun Heo   fuse: implement i...
2335
  	struct fuse_file *ff = file->private_data;
d36f24871   Miklos Szeredi   fuse: don't use i...
2336
  	struct fuse_conn *fc = ff->fc;
59efec7b9   Tejun Heo   fuse: implement i...
2337
2338
2339
2340
2341
2342
2343
2344
2345
  	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
2346
  	struct iovec *iov_page = NULL;
59efec7b9   Tejun Heo   fuse: implement i...
2347
2348
  	struct iovec *in_iov = NULL, *out_iov = NULL;
  	unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages;
acbe5fda1   Miklos Szeredi   fuse: don't use f...
2349
2350
2351
  	size_t in_size, out_size, transferred, c;
  	int err, i;
  	struct iov_iter ii;
59efec7b9   Tejun Heo   fuse: implement i...
2352

1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
2353
2354
2355
2356
2357
2358
  #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...
2359
  	/* assume all the iovs returned by client always fits in a page */
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
2360
  	BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
59efec7b9   Tejun Heo   fuse: implement i...
2361

59efec7b9   Tejun Heo   fuse: implement i...
2362
  	err = -ENOMEM;
c411cc88d   Thomas Meyer   fuse: Use kcalloc...
2363
  	pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, sizeof(pages[0]), GFP_KERNEL);
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
2364
  	iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
59efec7b9   Tejun Heo   fuse: implement i...
2365
2366
2367
2368
2369
2370
2371
2372
  	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
2373
  		struct iovec *iov = iov_page;
59efec7b9   Tejun Heo   fuse: implement i...
2374

c9f0523d8   Miklos Szeredi   fuse: fix sparse ...
2375
  		iov->iov_base = (void __user *)arg;
59efec7b9   Tejun Heo   fuse: implement i...
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
  		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++;
  	}
54b966702   Maxim Patlasov   fuse: rework fuse...
2410
  	req = fuse_get_req(fc, num_pages);
59efec7b9   Tejun Heo   fuse: implement i...
2411
2412
2413
2414
2415
2416
2417
  	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;
7c190c8b9   Maxim Patlasov   fuse: optimize fu...
2418
  	fuse_page_descs_length_init(req, 0, req->num_pages);
59efec7b9   Tejun Heo   fuse: implement i...
2419
2420
2421
  
  	/* okay, let's send it to the client */
  	req->in.h.opcode = FUSE_IOCTL;
d36f24871   Miklos Szeredi   fuse: don't use i...
2422
  	req->in.h.nodeid = ff->nodeid;
59efec7b9   Tejun Heo   fuse: implement i...
2423
2424
2425
2426
2427
2428
2429
  	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;
acbe5fda1   Miklos Szeredi   fuse: don't use f...
2430
2431
2432
2433
2434
2435
2436
  		err = -EFAULT;
  		iov_iter_init(&ii, WRITE, in_iov, in_iovs, in_size);
  		for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= num_pages); i++) {
  			c = copy_page_from_iter(pages[i], 0, PAGE_SIZE, &ii);
  			if (c != PAGE_SIZE && iov_iter_count(&ii))
  				goto out;
  		}
59efec7b9   Tejun Heo   fuse: implement i...
2437
2438
2439
2440
2441
2442
2443
2444
  	}
  
  	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...
2445
  	fuse_request_send(fc, req);
59efec7b9   Tejun Heo   fuse: implement i...
2446
2447
2448
2449
2450
2451
2452
2453
2454
  	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
2455
  		void *vaddr;
59efec7b9   Tejun Heo   fuse: implement i...
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
  
  		/* 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;
2408f6ef6   Cong Wang   fuse: remove the ...
2474
  		vaddr = kmap_atomic(pages[0]);
1baa26b2b   Miklos Szeredi   fuse: fix ioctl ABI
2475
  		err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr,
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
2476
2477
  					    transferred, in_iovs + out_iovs,
  					    (flags & FUSE_IOCTL_COMPAT) != 0);
2408f6ef6   Cong Wang   fuse: remove the ...
2478
  		kunmap_atomic(vaddr);
d9d318d39   Miklos Szeredi   fuse: fix ioctl w...
2479
2480
  		if (err)
  			goto out;
59efec7b9   Tejun Heo   fuse: implement i...
2481

8ac835056   Miklos Szeredi   fuse: ioctl cleanup
2482
  		in_iov = iov_page;
59efec7b9   Tejun Heo   fuse: implement i...
2483
  		out_iov = in_iov + in_iovs;
7572777ee   Miklos Szeredi   fuse: verify ioct...
2484
2485
2486
2487
2488
2489
2490
  		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...
2491
2492
2493
2494
2495
2496
  		goto retry;
  	}
  
  	err = -EIO;
  	if (transferred > inarg.out_size)
  		goto out;
acbe5fda1   Miklos Szeredi   fuse: don't use f...
2497
2498
2499
2500
2501
2502
2503
2504
  	err = -EFAULT;
  	iov_iter_init(&ii, READ, out_iov, out_iovs, transferred);
  	for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= num_pages); i++) {
  		c = copy_page_to_iter(pages[i], 0, PAGE_SIZE, &ii);
  		if (c != PAGE_SIZE && iov_iter_count(&ii))
  			goto out;
  	}
  	err = 0;
59efec7b9   Tejun Heo   fuse: implement i...
2505
2506
2507
   out:
  	if (req)
  		fuse_put_request(fc, req);
8ac835056   Miklos Szeredi   fuse: ioctl cleanup
2508
  	free_page((unsigned long) iov_page);
59efec7b9   Tejun Heo   fuse: implement i...
2509
2510
2511
2512
2513
2514
  	while (num_pages)
  		__free_page(pages[--num_pages]);
  	kfree(pages);
  
  	return err ? err : outarg.result;
  }
08cbf542b   Tejun Heo   fuse: export symb...
2515
  EXPORT_SYMBOL_GPL(fuse_do_ioctl);
59efec7b9   Tejun Heo   fuse: implement i...
2516

b18da0c56   Miklos Szeredi   fuse: support ioc...
2517
2518
  long fuse_ioctl_common(struct file *file, unsigned int cmd,
  		       unsigned long arg, unsigned int flags)
d36f24871   Miklos Szeredi   fuse: don't use i...
2519
  {
6131ffaa1   Al Viro   more file_inode()...
2520
  	struct inode *inode = file_inode(file);
d36f24871   Miklos Szeredi   fuse: don't use i...
2521
  	struct fuse_conn *fc = get_fuse_conn(inode);
c2132c1bc   Anatol Pomozov   Do not use RCU fo...
2522
  	if (!fuse_allow_current_process(fc))
d36f24871   Miklos Szeredi   fuse: don't use i...
2523
2524
2525
2526
2527
2528
2529
  		return -EACCES;
  
  	if (is_bad_inode(inode))
  		return -EIO;
  
  	return fuse_do_ioctl(file, cmd, arg, flags);
  }
59efec7b9   Tejun Heo   fuse: implement i...
2530
2531
2532
  static long fuse_file_ioctl(struct file *file, unsigned int cmd,
  			    unsigned long arg)
  {
b18da0c56   Miklos Szeredi   fuse: support ioc...
2533
  	return fuse_ioctl_common(file, cmd, arg, 0);
59efec7b9   Tejun Heo   fuse: implement i...
2534
2535
2536
2537
2538
  }
  
  static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
  				   unsigned long arg)
  {
b18da0c56   Miklos Szeredi   fuse: support ioc...
2539
  	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
59efec7b9   Tejun Heo   fuse: implement i...
2540
  }
95668a69a   Tejun Heo   fuse: implement p...
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
  /*
   * 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)) {
f3846266f   Rajat Jain   fuse: fix "uninit...
2582
  		struct rb_node **link, *uninitialized_var(parent);
95668a69a   Tejun Heo   fuse: implement p...
2583
2584
2585
2586
2587
2588
2589
2590
  
  		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);
  }
076ccb76e   Al Viro   fs: annotate ->po...
2591
  __poll_t fuse_file_poll(struct file *file, poll_table *wait)
95668a69a   Tejun Heo   fuse: implement p...
2592
  {
95668a69a   Tejun Heo   fuse: implement p...
2593
  	struct fuse_file *ff = file->private_data;
797759aaf   Miklos Szeredi   fuse: don't use i...
2594
  	struct fuse_conn *fc = ff->fc;
95668a69a   Tejun Heo   fuse: implement p...
2595
2596
  	struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
  	struct fuse_poll_out outarg;
7078187a7   Miklos Szeredi   fuse: introduce f...
2597
  	FUSE_ARGS(args);
95668a69a   Tejun Heo   fuse: implement p...
2598
2599
2600
2601
2602
2603
  	int err;
  
  	if (fc->no_poll)
  		return DEFAULT_POLLMASK;
  
  	poll_wait(file, &ff->poll_wait, wait);
c71d227fc   Al Viro   make kernel-side ...
2604
  	inarg.events = mangle_poll(poll_requested_events(wait));
95668a69a   Tejun Heo   fuse: implement p...
2605
2606
2607
2608
2609
2610
2611
2612
2613
  
  	/*
  	 * 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);
  	}
7078187a7   Miklos Szeredi   fuse: introduce f...
2614
2615
2616
2617
2618
2619
2620
2621
2622
  	args.in.h.opcode = FUSE_POLL;
  	args.in.h.nodeid = ff->nodeid;
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	args.out.numargs = 1;
  	args.out.args[0].size = sizeof(outarg);
  	args.out.args[0].value = &outarg;
  	err = fuse_simple_request(fc, &args);
95668a69a   Tejun Heo   fuse: implement p...
2623
2624
  
  	if (!err)
c71d227fc   Al Viro   make kernel-side ...
2625
  		return demangle_poll(outarg.revents);
95668a69a   Tejun Heo   fuse: implement p...
2626
2627
2628
2629
  	if (err == -ENOSYS) {
  		fc->no_poll = 1;
  		return DEFAULT_POLLMASK;
  	}
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
2630
  	return EPOLLERR;
95668a69a   Tejun Heo   fuse: implement p...
2631
  }
08cbf542b   Tejun Heo   fuse: export symb...
2632
  EXPORT_SYMBOL_GPL(fuse_file_poll);
95668a69a   Tejun Heo   fuse: implement p...
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
  
  /*
   * 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;
  }
efb9fa9e9   Maxim Patlasov   fuse: truncate fi...
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
  static void fuse_do_truncate(struct file *file)
  {
  	struct inode *inode = file->f_mapping->host;
  	struct iattr attr;
  
  	attr.ia_valid = ATTR_SIZE;
  	attr.ia_size = i_size_read(inode);
  
  	attr.ia_file = file;
  	attr.ia_valid |= ATTR_FILE;
624903307   Jan Kara   fuse: Propagate d...
2667
  	fuse_do_setattr(file_dentry(file), &attr, file);
efb9fa9e9   Maxim Patlasov   fuse: truncate fi...
2668
  }
e5c5f05dc   Maxim Patlasov   fuse: fix alignme...
2669
2670
2671
2672
  static inline loff_t fuse_round_up(loff_t off)
  {
  	return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
  }
4273b793e   Anand Avati   fuse: O_DIRECT su...
2673
  static ssize_t
c8b8e32d7   Christoph Hellwig   direct-io: elimin...
2674
  fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4273b793e   Anand Avati   fuse: O_DIRECT su...
2675
  {
9d5722b77   Christoph Hellwig   fuse: handle sync...
2676
  	DECLARE_COMPLETION_ONSTACK(wait);
4273b793e   Anand Avati   fuse: O_DIRECT su...
2677
  	ssize_t ret = 0;
60b9df7a5   Miklos Szeredi   fuse: add flag to...
2678
2679
  	struct file *file = iocb->ki_filp;
  	struct fuse_file *ff = file->private_data;
e5c5f05dc   Maxim Patlasov   fuse: fix alignme...
2680
  	bool async_dio = ff->fc->async_dio;
4273b793e   Anand Avati   fuse: O_DIRECT su...
2681
  	loff_t pos = 0;
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2682
2683
  	struct inode *inode;
  	loff_t i_size;
a6cbcd4a4   Al Viro   get rid of pointl...
2684
  	size_t count = iov_iter_count(iter);
c8b8e32d7   Christoph Hellwig   direct-io: elimin...
2685
  	loff_t offset = iocb->ki_pos;
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
2686
  	struct fuse_io_priv *io;
4273b793e   Anand Avati   fuse: O_DIRECT su...
2687

4273b793e   Anand Avati   fuse: O_DIRECT su...
2688
  	pos = offset;
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2689
2690
  	inode = file->f_mapping->host;
  	i_size = i_size_read(inode);
4273b793e   Anand Avati   fuse: O_DIRECT su...
2691

6f6737631   Omar Sandoval   direct_IO: use io...
2692
  	if ((iov_iter_rw(iter) == READ) && (offset > i_size))
9fe55eea7   Steven Whitehouse   Fix race when che...
2693
  		return 0;
439ee5f0c   Maxim Patlasov   fuse: optimize sh...
2694
  	/* optimization for short read */
6f6737631   Omar Sandoval   direct_IO: use io...
2695
  	if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) {
439ee5f0c   Maxim Patlasov   fuse: optimize sh...
2696
2697
  		if (offset >= i_size)
  			return 0;
6b775b18e   Al Viro   fuse: ->direct_IO...
2698
2699
  		iov_iter_truncate(iter, fuse_round_up(i_size - offset));
  		count = iov_iter_count(iter);
439ee5f0c   Maxim Patlasov   fuse: optimize sh...
2700
  	}
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2701
  	io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
2702
2703
  	if (!io)
  		return -ENOMEM;
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2704
  	spin_lock_init(&io->lock);
744742d69   Seth Forshee   fuse: Add referen...
2705
  	kref_init(&io->refcnt);
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2706
2707
2708
2709
  	io->reqs = 1;
  	io->bytes = -1;
  	io->size = 0;
  	io->offset = offset;
6f6737631   Omar Sandoval   direct_IO: use io...
2710
  	io->write = (iov_iter_rw(iter) == WRITE);
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2711
  	io->err = 0;
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2712
2713
  	/*
  	 * By default, we want to optimize all I/Os with async request
60b9df7a5   Miklos Szeredi   fuse: add flag to...
2714
  	 * submission to the client filesystem if supported.
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2715
  	 */
e5c5f05dc   Maxim Patlasov   fuse: fix alignme...
2716
  	io->async = async_dio;
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2717
  	io->iocb = iocb;
7879c4e58   Ashish Sangwan   fuse: improve aio...
2718
  	io->blocking = is_sync_kiocb(iocb);
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2719
2720
  
  	/*
7879c4e58   Ashish Sangwan   fuse: improve aio...
2721
2722
  	 * We cannot asynchronously extend the size of a file.
  	 * In such case the aio will behave exactly like sync io.
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2723
  	 */
7879c4e58   Ashish Sangwan   fuse: improve aio...
2724
2725
  	if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE)
  		io->blocking = true;
4273b793e   Anand Avati   fuse: O_DIRECT su...
2726

7879c4e58   Ashish Sangwan   fuse: improve aio...
2727
  	if (io->async && io->blocking) {
744742d69   Seth Forshee   fuse: Add referen...
2728
2729
2730
2731
2732
  		/*
  		 * Additional reference to keep io around after
  		 * calling fuse_aio_complete()
  		 */
  		kref_get(&io->refcnt);
9d5722b77   Christoph Hellwig   fuse: handle sync...
2733
  		io->done = &wait;
744742d69   Seth Forshee   fuse: Add referen...
2734
  	}
9d5722b77   Christoph Hellwig   fuse: handle sync...
2735

6f6737631   Omar Sandoval   direct_IO: use io...
2736
  	if (iov_iter_rw(iter) == WRITE) {
6b775b18e   Al Viro   fuse: ->direct_IO...
2737
  		ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
812408fb5   Al Viro   expand __fuse_dir...
2738
2739
  		fuse_invalidate_attr(inode);
  	} else {
d22a943f4   Al Viro   fuse: pull iov_it...
2740
  		ret = __fuse_direct_read(io, iter, &pos);
812408fb5   Al Viro   expand __fuse_dir...
2741
  	}
36cf66ed9   Maxim Patlasov   fuse: make fuse_d...
2742

bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2743
2744
2745
2746
  	if (io->async) {
  		fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
  
  		/* we have a non-extending, async request, so return */
7879c4e58   Ashish Sangwan   fuse: improve aio...
2747
  		if (!io->blocking)
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2748
  			return -EIOCBQUEUED;
9d5722b77   Christoph Hellwig   fuse: handle sync...
2749
2750
  		wait_for_completion(&wait);
  		ret = fuse_get_res_by_io(io);
bcba24ccd   Maxim Patlasov   fuse: enable asyn...
2751
  	}
744742d69   Seth Forshee   fuse: Add referen...
2752
  	kref_put(&io->refcnt, fuse_io_release);
9d5722b77   Christoph Hellwig   fuse: handle sync...
2753

6f6737631   Omar Sandoval   direct_IO: use io...
2754
  	if (iov_iter_rw(iter) == WRITE) {
efb9fa9e9   Maxim Patlasov   fuse: truncate fi...
2755
2756
2757
2758
2759
  		if (ret > 0)
  			fuse_write_update_size(inode, pos);
  		else if (ret < 0 && offset + count > i_size)
  			fuse_do_truncate(file);
  	}
4273b793e   Anand Avati   fuse: O_DIRECT su...
2760
2761
2762
  
  	return ret;
  }
cdadb11ce   Miklos Szeredi   fuse: make fuse_f...
2763
2764
  static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
  				loff_t length)
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2765
2766
  {
  	struct fuse_file *ff = file->private_data;
1c68271cf   Miklos Szeredi   fuse: use file_in...
2767
  	struct inode *inode = file_inode(file);
0ab08f576   Maxim Patlasov   fuse: fix falloca...
2768
  	struct fuse_inode *fi = get_fuse_inode(inode);
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2769
  	struct fuse_conn *fc = ff->fc;
7078187a7   Miklos Szeredi   fuse: introduce f...
2770
  	FUSE_ARGS(args);
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2771
2772
2773
2774
2775
2776
2777
  	struct fuse_fallocate_in inarg = {
  		.fh = ff->fh,
  		.offset = offset,
  		.length = length,
  		.mode = mode
  	};
  	int err;
14c14414d   Maxim Patlasov   fuse: hold i_mute...
2778
2779
  	bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
  			   (mode & FALLOC_FL_PUNCH_HOLE);
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2780

4adb83029   Miklos Szeredi   fuse: check fallo...
2781
2782
  	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
  		return -EOPNOTSUPP;
519c6040c   Miklos Szeredi   fuse: optimize fa...
2783
2784
  	if (fc->no_fallocate)
  		return -EOPNOTSUPP;
14c14414d   Maxim Patlasov   fuse: hold i_mute...
2785
  	if (lock_inode) {
5955102c9   Al Viro   wrappers for ->i_...
2786
  		inode_lock(inode);
bde52788b   Maxim Patlasov   fuse: wait for wr...
2787
2788
2789
2790
2791
2792
2793
2794
2795
  		if (mode & FALLOC_FL_PUNCH_HOLE) {
  			loff_t endbyte = offset + length - 1;
  			err = filemap_write_and_wait_range(inode->i_mapping,
  							   offset, endbyte);
  			if (err)
  				goto out;
  
  			fuse_sync_writes(inode);
  		}
3634a6327   Brian Foster   fuse: truncate pa...
2796
  	}
0ab08f576   Maxim Patlasov   fuse: fix falloca...
2797
2798
  	if (!(mode & FALLOC_FL_KEEP_SIZE))
  		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
7078187a7   Miklos Szeredi   fuse: introduce f...
2799
2800
2801
2802
2803
2804
  	args.in.h.opcode = FUSE_FALLOCATE;
  	args.in.h.nodeid = ff->nodeid;
  	args.in.numargs = 1;
  	args.in.args[0].size = sizeof(inarg);
  	args.in.args[0].value = &inarg;
  	err = fuse_simple_request(fc, &args);
519c6040c   Miklos Szeredi   fuse: optimize fa...
2805
2806
2807
2808
  	if (err == -ENOSYS) {
  		fc->no_fallocate = 1;
  		err = -EOPNOTSUPP;
  	}
bee6c3078   Brian Foster   fuse: update inod...
2809
2810
2811
2812
  	if (err)
  		goto out;
  
  	/* we could have extended the file */
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
2813
2814
  	if (!(mode & FALLOC_FL_KEEP_SIZE)) {
  		bool changed = fuse_write_update_size(inode, offset + length);
93d2269d2   Miklos Szeredi   fuse: fuse: fallo...
2815
2816
  		if (changed && fc->writeback_cache)
  			file_update_time(file);
b0aa76065   Maxim Patlasov   fuse: Trust kerne...
2817
  	}
bee6c3078   Brian Foster   fuse: update inod...
2818
2819
2820
2821
2822
  
  	if (mode & FALLOC_FL_PUNCH_HOLE)
  		truncate_pagecache_range(inode, offset, offset + length - 1);
  
  	fuse_invalidate_attr(inode);
3634a6327   Brian Foster   fuse: truncate pa...
2823
  out:
0ab08f576   Maxim Patlasov   fuse: fix falloca...
2824
2825
  	if (!(mode & FALLOC_FL_KEEP_SIZE))
  		clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
bde52788b   Maxim Patlasov   fuse: wait for wr...
2826
  	if (lock_inode)
5955102c9   Al Viro   wrappers for ->i_...
2827
  		inode_unlock(inode);
3634a6327   Brian Foster   fuse: truncate pa...
2828

05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2829
2830
  	return err;
  }
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2831

4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
2832
  static const struct file_operations fuse_file_operations = {
5559b8f4d   Miklos Szeredi   fuse: fix race in...
2833
  	.llseek		= fuse_file_llseek,
37c20f16e   Al Viro   fuse_file_aio_rea...
2834
  	.read_iter	= fuse_file_read_iter,
84c3d55cc   Al Viro   fuse: switch to -...
2835
  	.write_iter	= fuse_file_write_iter,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2836
2837
2838
2839
2840
  	.mmap		= fuse_file_mmap,
  	.open		= fuse_open,
  	.flush		= fuse_flush,
  	.release	= fuse_release,
  	.fsync		= fuse_fsync,
714212593   Miklos Szeredi   [PATCH] fuse: add...
2841
  	.lock		= fuse_file_lock,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2842
  	.flock		= fuse_file_flock,
5ffc4ef45   Jens Axboe   sendfile: remove ...
2843
  	.splice_read	= generic_file_splice_read,
59efec7b9   Tejun Heo   fuse: implement i...
2844
2845
  	.unlocked_ioctl	= fuse_file_ioctl,
  	.compat_ioctl	= fuse_file_compat_ioctl,
95668a69a   Tejun Heo   fuse: implement p...
2846
  	.poll		= fuse_file_poll,
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2847
  	.fallocate	= fuse_file_fallocate,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2848
  };
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
2849
  static const struct file_operations fuse_direct_io_file_operations = {
5559b8f4d   Miklos Szeredi   fuse: fix race in...
2850
  	.llseek		= fuse_file_llseek,
153162636   Al Viro   fuse: switch fuse...
2851
  	.read_iter	= fuse_direct_read_iter,
153162636   Al Viro   fuse: switch fuse...
2852
  	.write_iter	= fuse_direct_write_iter,
fc280c969   Miklos Szeredi   fuse: allow priva...
2853
  	.mmap		= fuse_direct_mmap,
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
2854
2855
2856
2857
  	.open		= fuse_open,
  	.flush		= fuse_flush,
  	.release	= fuse_release,
  	.fsync		= fuse_fsync,
714212593   Miklos Szeredi   [PATCH] fuse: add...
2858
  	.lock		= fuse_file_lock,
a9ff4f870   Miklos Szeredi   fuse: support BSD...
2859
  	.flock		= fuse_file_flock,
59efec7b9   Tejun Heo   fuse: implement i...
2860
2861
  	.unlocked_ioctl	= fuse_file_ioctl,
  	.compat_ioctl	= fuse_file_compat_ioctl,
95668a69a   Tejun Heo   fuse: implement p...
2862
  	.poll		= fuse_file_poll,
05ba1f082   Anatol Pomozov   fuse: add FALLOCA...
2863
  	.fallocate	= fuse_file_fallocate,
fc280c969   Miklos Szeredi   fuse: allow priva...
2864
  	/* no splice_read */
413ef8cb3   Miklos Szeredi   [PATCH] FUSE - di...
2865
  };
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
2866
  static const struct address_space_operations fuse_file_aops  = {
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2867
  	.readpage	= fuse_readpage,
3be5a52b3   Miklos Szeredi   fuse: support wri...
2868
  	.writepage	= fuse_writepage,
26d614df1   Pavel Emelyanov   fuse: Implement w...
2869
  	.writepages	= fuse_writepages,
3be5a52b3   Miklos Szeredi   fuse: support wri...
2870
  	.launder_page	= fuse_launder_page,
db50b96c0   Miklos Szeredi   [PATCH] FUSE - re...
2871
  	.readpages	= fuse_readpages,
3be5a52b3   Miklos Szeredi   fuse: support wri...
2872
  	.set_page_dirty	= __set_page_dirty_nobuffers,
b2d2272fa   Miklos Szeredi   [PATCH] fuse: add...
2873
  	.bmap		= fuse_bmap,
4273b793e   Anand Avati   fuse: O_DIRECT su...
2874
  	.direct_IO	= fuse_direct_IO,
6b12c1b37   Pavel Emelyanov   fuse: Implement w...
2875
2876
  	.write_begin	= fuse_write_begin,
  	.write_end	= fuse_write_end,
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2877
2878
2879
2880
  };
  
  void fuse_init_file_inode(struct inode *inode)
  {
45323fb76   Miklos Szeredi   [PATCH] fuse: mor...
2881
2882
  	inode->i_fop = &fuse_file_operations;
  	inode->i_data.a_ops = &fuse_file_aops;
b6aeadeda   Miklos Szeredi   [PATCH] FUSE - fi...
2883
  }