Blame view

fs/libfs.c 25.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   *	fs/libfs.c
   *	Library for filesystems writers.
   */
  
  #include <linux/module.h>
  #include <linux/pagemap.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/mount.h>
  #include <linux/vfs.h>
7bb46a673   npiggin@suse.de   fs: introduce new...
11
  #include <linux/quotaops.h>
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
12
  #include <linux/mutex.h>
2596110a3   Christoph Hellwig   exportfs: add new...
13
  #include <linux/exportfs.h>
d5aacad54   Al Viro   New helper - simp...
14
  #include <linux/writeback.h>
ff01bb483   Al Viro   fs: move code out...
15
  #include <linux/buffer_head.h> /* sync_mapping_buffers */
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
16

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <asm/uaccess.h>
a4464dbc0   Al Viro   Make ->d_sb assig...
18
  #include "internal.h"
da5029563   Nick Piggin   fs: dcache scale ...
19
20
21
22
  static inline int simple_positive(struct dentry *dentry)
  {
  	return dentry->d_inode && !d_unhashed(dentry);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
30
  int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
  		   struct kstat *stat)
  {
  	struct inode *inode = dentry->d_inode;
  	generic_fillattr(inode, stat);
  	stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
  	return 0;
  }
726c33422   David Howells   [PATCH] VFS: Perm...
31
  int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  {
726c33422   David Howells   [PATCH] VFS: Perm...
33
  	buf->f_type = dentry->d_sb->s_magic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
42
  	buf->f_bsize = PAGE_CACHE_SIZE;
  	buf->f_namelen = NAME_MAX;
  	return 0;
  }
  
  /*
   * Retaining negative dentries for an in-memory filesystem just wastes
   * memory and lookup time: arrange for them to be deleted immediately.
   */
fe15ce446   Nick Piggin   fs: change d_dele...
43
  static int simple_delete_dentry(const struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
52
53
  {
  	return 1;
  }
  
  /*
   * Lookup the data. This is trivial - if the dentry didn't already
   * exist, we know it is negative.  Set d_op to delete negative dentries.
   */
  struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  {
3ba13d179   Al Viro   constify dentry_o...
54
  	static const struct dentry_operations simple_dentry_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
  		.d_delete = simple_delete_dentry,
  	};
  
  	if (dentry->d_name.len > NAME_MAX)
  		return ERR_PTR(-ENAMETOOLONG);
fb045adb9   Nick Piggin   fs: dcache reduce...
60
  	d_set_d_op(dentry, &simple_dentry_operations);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
  	d_add(dentry, NULL);
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
  int dcache_dir_open(struct inode *inode, struct file *file)
  {
  	static struct qstr cursor_name = {.len = 1, .name = "."};
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
67
  	file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
73
74
75
76
77
78
79
  
  	return file->private_data ? 0 : -ENOMEM;
  }
  
  int dcache_dir_close(struct inode *inode, struct file *file)
  {
  	dput(file->private_data);
  	return 0;
  }
  
  loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
  {
2fd6b7f50   Nick Piggin   fs: dcache scale ...
80
81
  	struct dentry *dentry = file->f_path.dentry;
  	mutex_lock(&dentry->d_inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
85
86
87
88
  	switch (origin) {
  		case 1:
  			offset += file->f_pos;
  		case 0:
  			if (offset >= 0)
  				break;
  		default:
2fd6b7f50   Nick Piggin   fs: dcache scale ...
89
  			mutex_unlock(&dentry->d_inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
97
  			return -EINVAL;
  	}
  	if (offset != file->f_pos) {
  		file->f_pos = offset;
  		if (file->f_pos >= 2) {
  			struct list_head *p;
  			struct dentry *cursor = file->private_data;
  			loff_t n = file->f_pos - 2;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
98
99
  			spin_lock(&dentry->d_lock);
  			/* d_lock not required for cursor */
5160ee6fc   Eric Dumazet   [PATCH] shrink de...
100
  			list_del(&cursor->d_u.d_child);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
101
102
  			p = dentry->d_subdirs.next;
  			while (n && p != &dentry->d_subdirs) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  				struct dentry *next;
5160ee6fc   Eric Dumazet   [PATCH] shrink de...
104
  				next = list_entry(p, struct dentry, d_u.d_child);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
105
  				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
da5029563   Nick Piggin   fs: dcache scale ...
106
  				if (simple_positive(next))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  					n--;
da5029563   Nick Piggin   fs: dcache scale ...
108
  				spin_unlock(&next->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
  				p = p->next;
  			}
5160ee6fc   Eric Dumazet   [PATCH] shrink de...
111
  			list_add_tail(&cursor->d_u.d_child, p);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
112
  			spin_unlock(&dentry->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
  		}
  	}
2fd6b7f50   Nick Piggin   fs: dcache scale ...
115
  	mutex_unlock(&dentry->d_inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  	return offset;
  }
  
  /* Relationship between i_mode and the DT_xxx types */
  static inline unsigned char dt_type(struct inode *inode)
  {
  	return (inode->i_mode >> 12) & 15;
  }
  
  /*
   * Directory is locked and all positive dentries in it are safe, since
   * for ramfs-type trees they can't go away without unlink() or rmdir(),
   * both impossible due to the lock on directory.
   */
  
  int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
  {
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
133
  	struct dentry *dentry = filp->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  	struct dentry *cursor = filp->private_data;
5160ee6fc   Eric Dumazet   [PATCH] shrink de...
135
  	struct list_head *p, *q = &cursor->d_u.d_child;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  	ino_t ino;
  	int i = filp->f_pos;
  
  	switch (i) {
  		case 0:
  			ino = dentry->d_inode->i_ino;
  			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
  				break;
  			filp->f_pos++;
  			i++;
  			/* fallthrough */
  		case 1:
  			ino = parent_ino(dentry);
  			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
  				break;
  			filp->f_pos++;
  			i++;
  			/* fallthrough */
  		default:
2fd6b7f50   Nick Piggin   fs: dcache scale ...
155
  			spin_lock(&dentry->d_lock);
1bfba4e8e   Akinobu Mita   [PATCH] core: use...
156
157
  			if (filp->f_pos == 2)
  				list_move(q, &dentry->d_subdirs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
  				struct dentry *next;
5160ee6fc   Eric Dumazet   [PATCH] shrink de...
160
  				next = list_entry(p, struct dentry, d_u.d_child);
da5029563   Nick Piggin   fs: dcache scale ...
161
162
163
  				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
  				if (!simple_positive(next)) {
  					spin_unlock(&next->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  					continue;
da5029563   Nick Piggin   fs: dcache scale ...
165
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166

da5029563   Nick Piggin   fs: dcache scale ...
167
  				spin_unlock(&next->d_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
168
  				spin_unlock(&dentry->d_lock);
0f8952c2f   Ronni Nielsen   fs/libfs.c: >80 c...
169
170
171
172
  				if (filldir(dirent, next->d_name.name, 
  					    next->d_name.len, filp->f_pos, 
  					    next->d_inode->i_ino, 
  					    dt_type(next->d_inode)) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  					return 0;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
174
175
  				spin_lock(&dentry->d_lock);
  				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  				/* next is still alive */
1bfba4e8e   Akinobu Mita   [PATCH] core: use...
177
  				list_move(q, p);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
178
  				spin_unlock(&next->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
  				p = q;
  				filp->f_pos++;
  			}
2fd6b7f50   Nick Piggin   fs: dcache scale ...
182
  			spin_unlock(&dentry->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
190
  	}
  	return 0;
  }
  
  ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
  {
  	return -EISDIR;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
191
  const struct file_operations simple_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
  	.open		= dcache_dir_open,
  	.release	= dcache_dir_close,
  	.llseek		= dcache_dir_lseek,
  	.read		= generic_read_dir,
  	.readdir	= dcache_readdir,
1b061d924   Christoph Hellwig   rename the generi...
197
  	.fsync		= noop_fsync,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
199
  const struct inode_operations simple_dir_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
  	.lookup		= simple_lookup,
  };
759b9775c   Hugh Dickins   [PATCH] shmem and...
202
203
204
  static const struct super_operations simple_super_operations = {
  	.statfs		= simple_statfs,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
208
  /*
   * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
   * will never be mountable)
   */
51139adac   Al Viro   convert get_sb_ps...
209
  struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
c74a1cbb3   Al Viro   pass default dent...
210
211
  	const struct super_operations *ops,
  	const struct dentry_operations *dops, unsigned long magic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  {
  	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
  	struct dentry *dentry;
  	struct inode *root;
  	struct qstr d_name = {.name = name, .len = strlen(name)};
  
  	if (IS_ERR(s))
51139adac   Al Viro   convert get_sb_ps...
219
  		return ERR_CAST(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  
  	s->s_flags = MS_NOUSER;
89a4eb4b6   Jeff Layton   vfs: make get_sb_...
222
  	s->s_maxbytes = MAX_LFS_FILESIZE;
3971e1a91   Alex Nixon   VFS: increase pse...
223
224
  	s->s_blocksize = PAGE_SIZE;
  	s->s_blocksize_bits = PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  	s->s_magic = magic;
759b9775c   Hugh Dickins   [PATCH] shmem and...
226
  	s->s_op = ops ? ops : &simple_super_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
  	s->s_time_gran = 1;
  	root = new_inode(s);
  	if (!root)
  		goto Enomem;
1a1c9bb43   Jeff Layton   inode numbering: ...
231
232
233
234
235
236
  	/*
  	 * since this is the first inode, make it number 1. New inodes created
  	 * after this must take care not to collide with it (by passing
  	 * max_reserved of 1 to iunique).
  	 */
  	root->i_ino = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
a4464dbc0   Al Viro   Make ->d_sb assig...
239
  	dentry = __d_alloc(s, &d_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
  	if (!dentry) {
  		iput(root);
  		goto Enomem;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
  	d_instantiate(dentry, root);
  	s->s_root = dentry;
c74a1cbb3   Al Viro   pass default dent...
246
  	s->s_d_op = dops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	s->s_flags |= MS_ACTIVE;
51139adac   Al Viro   convert get_sb_ps...
248
  	return dget(s->s_root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
  
  Enomem:
6f5bbff9a   Al Viro   Convert obvious p...
251
  	deactivate_locked_super(s);
51139adac   Al Viro   convert get_sb_ps...
252
  	return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
258
259
  }
  
  int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
  {
  	struct inode *inode = old_dentry->d_inode;
  
  	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
260
  	inc_nlink(inode);
7de9c6ee3   Al Viro   new helper: ihold()
261
  	ihold(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
  	dget(dentry);
  	d_instantiate(dentry, inode);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
269
  int simple_empty(struct dentry *dentry)
  {
  	struct dentry *child;
  	int ret = 0;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
270
  	spin_lock(&dentry->d_lock);
da5029563   Nick Piggin   fs: dcache scale ...
271
272
273
274
  	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
  		spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
  		if (simple_positive(child)) {
  			spin_unlock(&child->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  			goto out;
da5029563   Nick Piggin   fs: dcache scale ...
276
277
278
  		}
  		spin_unlock(&child->d_lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	ret = 1;
  out:
2fd6b7f50   Nick Piggin   fs: dcache scale ...
281
  	spin_unlock(&dentry->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
287
288
289
  	return ret;
  }
  
  int simple_unlink(struct inode *dir, struct dentry *dentry)
  {
  	struct inode *inode = dentry->d_inode;
  
  	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
290
  	drop_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
295
296
297
298
  	dput(dentry);
  	return 0;
  }
  
  int simple_rmdir(struct inode *dir, struct dentry *dentry)
  {
  	if (!simple_empty(dentry))
  		return -ENOTEMPTY;
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
299
  	drop_nlink(dentry->d_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  	simple_unlink(dir, dentry);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
301
  	drop_nlink(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  	return 0;
  }
  
  int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
  		struct inode *new_dir, struct dentry *new_dentry)
  {
  	struct inode *inode = old_dentry->d_inode;
  	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
  
  	if (!simple_empty(new_dentry))
  		return -ENOTEMPTY;
  
  	if (new_dentry->d_inode) {
  		simple_unlink(new_dir, new_dentry);
841590ce1   Al Viro   fix IN_DELETE_SEL...
316
317
  		if (they_are_dirs) {
  			drop_nlink(new_dentry->d_inode);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
318
  			drop_nlink(old_dir);
841590ce1   Al Viro   fix IN_DELETE_SEL...
319
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	} else if (they_are_dirs) {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
321
  		drop_nlink(old_dir);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
322
  		inc_nlink(new_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
328
329
  	}
  
  	old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
  		new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
  
  	return 0;
  }
7bb46a673   npiggin@suse.de   fs: introduce new...
330
  /**
eef2380c1   Christoph Hellwig   default to simple...
331
   * simple_setattr - setattr for simple filesystem
7bb46a673   npiggin@suse.de   fs: introduce new...
332
333
334
335
336
   * @dentry: dentry
   * @iattr: iattr structure
   *
   * Returns 0 on success, -error on failure.
   *
eef2380c1   Christoph Hellwig   default to simple...
337
338
339
340
341
342
   * simple_setattr is a simple ->setattr implementation without a proper
   * implementation of size changes.
   *
   * It can either be used for in-memory filesystems or special files
   * on simple regular filesystems.  Anything that needs to change on-disk
   * or wire state on size changes needs its own setattr method.
7bb46a673   npiggin@suse.de   fs: introduce new...
343
344
345
346
347
   */
  int simple_setattr(struct dentry *dentry, struct iattr *iattr)
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
eef2380c1   Christoph Hellwig   default to simple...
348
  	WARN_ON_ONCE(inode->i_op->truncate);
7bb46a673   npiggin@suse.de   fs: introduce new...
349
350
351
  	error = inode_change_ok(inode, iattr);
  	if (error)
  		return error;
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
352
353
  	if (iattr->ia_valid & ATTR_SIZE)
  		truncate_setsize(inode, iattr->ia_size);
6a1a90ad1   Christoph Hellwig   rename generic_se...
354
  	setattr_copy(inode, iattr);
eef2380c1   Christoph Hellwig   default to simple...
355
356
  	mark_inode_dirty(inode);
  	return 0;
7bb46a673   npiggin@suse.de   fs: introduce new...
357
358
  }
  EXPORT_SYMBOL(simple_setattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
  int simple_readpage(struct file *file, struct page *page)
  {
c0d92cbc5   Pekka J Enberg   [PATCH] libfs: re...
361
  	clear_highpage(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
  	flush_dcache_page(page);
  	SetPageUptodate(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
  	unlock_page(page);
  	return 0;
  }
afddba49d   Nick Piggin   fs: introduce wri...
367
368
369
370
371
372
  int simple_write_begin(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
  {
  	struct page *page;
  	pgoff_t index;
afddba49d   Nick Piggin   fs: introduce wri...
373
374
  
  	index = pos >> PAGE_CACHE_SHIFT;
afddba49d   Nick Piggin   fs: introduce wri...
375

54566b2c1   Nick Piggin   fs: symlink write...
376
  	page = grab_cache_page_write_begin(mapping, index, flags);
afddba49d   Nick Piggin   fs: introduce wri...
377
378
379
380
  	if (!page)
  		return -ENOMEM;
  
  	*pagep = page;
193cf4b99   Boaz Harrosh   libfs: Unexport a...
381
382
383
384
385
386
  	if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) {
  		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
  
  		zero_user_segments(page, 0, from, from + len, PAGE_CACHE_SIZE);
  	}
  	return 0;
afddba49d   Nick Piggin   fs: introduce wri...
387
  }
ad2a722f1   Boaz Harrosh   libfs: Open code ...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  /**
   * simple_write_end - .write_end helper for non-block-device FSes
   * @available: See .write_end of address_space_operations
   * @file: 		"
   * @mapping: 		"
   * @pos: 		"
   * @len: 		"
   * @copied: 		"
   * @page: 		"
   * @fsdata: 		"
   *
   * simple_write_end does the minimum needed for updating a page after writing is
   * done. It has the same API signature as the .write_end of
   * address_space_operations vector. So it can just be set onto .write_end for
   * FSes that don't need any other processing. i_mutex is assumed to be held.
   * Block based filesystems should use generic_write_end().
   * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
   * is not called, so a filesystem that actually does store data in .write_inode
   * should extend on what's done here with a call to mark_inode_dirty() in the
   * case that i_size has changed.
   */
afddba49d   Nick Piggin   fs: introduce wri...
409
410
411
412
  int simple_write_end(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned copied,
  			struct page *page, void *fsdata)
  {
ad2a722f1   Boaz Harrosh   libfs: Open code ...
413
414
  	struct inode *inode = page->mapping->host;
  	loff_t last_pos = pos + copied;
afddba49d   Nick Piggin   fs: introduce wri...
415
416
417
  
  	/* zero the stale part of the page if we did a short copy */
  	if (copied < len) {
ad2a722f1   Boaz Harrosh   libfs: Open code ...
418
419
420
  		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
  
  		zero_user(page, from + copied, len - copied);
afddba49d   Nick Piggin   fs: introduce wri...
421
  	}
ad2a722f1   Boaz Harrosh   libfs: Open code ...
422
423
424
425
426
427
428
429
  	if (!PageUptodate(page))
  		SetPageUptodate(page);
  	/*
  	 * No need to use i_size_read() here, the i_size
  	 * cannot change under us because we hold the i_mutex.
  	 */
  	if (last_pos > inode->i_size)
  		i_size_write(inode, last_pos);
afddba49d   Nick Piggin   fs: introduce wri...
430

ad2a722f1   Boaz Harrosh   libfs: Open code ...
431
  	set_page_dirty(page);
afddba49d   Nick Piggin   fs: introduce wri...
432
433
434
435
436
  	unlock_page(page);
  	page_cache_release(page);
  
  	return copied;
  }
1a1c9bb43   Jeff Layton   inode numbering: ...
437
438
439
440
441
  /*
   * the inodes created here are not hashed. If you use iunique to generate
   * unique inode values later for this filesystem, then you must take care
   * to pass it an appropriate max_reserved value to avoid collisions.
   */
7d683a099   Roberto Sassu   wrong type for 'm...
442
443
  int simple_fill_super(struct super_block *s, unsigned long magic,
  		      struct tree_descr *files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
447
448
449
450
451
452
  	struct inode *inode;
  	struct dentry *root;
  	struct dentry *dentry;
  	int i;
  
  	s->s_blocksize = PAGE_CACHE_SIZE;
  	s->s_blocksize_bits = PAGE_CACHE_SHIFT;
  	s->s_magic = magic;
759b9775c   Hugh Dickins   [PATCH] shmem and...
453
  	s->s_op = &simple_super_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
  	s->s_time_gran = 1;
  
  	inode = new_inode(s);
  	if (!inode)
  		return -ENOMEM;
1a1c9bb43   Jeff Layton   inode numbering: ...
459
460
461
462
463
  	/*
  	 * because the root inode is 1, the files array must not contain an
  	 * entry at index 1
  	 */
  	inode->i_ino = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  	inode->i_mode = S_IFDIR | 0755;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
bfe868486   Miklos Szeredi   filesystems: add ...
468
  	set_nlink(inode, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
475
476
  	root = d_alloc_root(inode);
  	if (!root) {
  		iput(inode);
  		return -ENOMEM;
  	}
  	for (i = 0; !files->name || files->name[0]; i++, files++) {
  		if (!files->name)
  			continue;
1a1c9bb43   Jeff Layton   inode numbering: ...
477
478
479
480
481
482
483
  
  		/* warn if it tries to conflict with the root inode */
  		if (unlikely(i == 1))
  			printk(KERN_WARNING "%s: %s passed in a files array"
  				"with an index of 1!
  ", __func__,
  				s->s_type->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
487
  		dentry = d_alloc_name(root, files->name);
  		if (!dentry)
  			goto out;
  		inode = new_inode(s);
32096ea1a   Konstantin Khlebnikov   vfs: fix dentry l...
488
489
  		if (!inode) {
  			dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  			goto out;
32096ea1a   Konstantin Khlebnikov   vfs: fix dentry l...
491
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  		inode->i_mode = S_IFREG | files->mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  		inode->i_fop = files->ops;
  		inode->i_ino = i;
  		d_add(dentry, inode);
  	}
  	s->s_root = root;
  	return 0;
  out:
  	d_genocide(root);
  	dput(root);
  	return -ENOMEM;
  }
  
  static DEFINE_SPINLOCK(pin_fs_lock);
1f5ce9e93   Trond Myklebust   VFS: Unexport do_...
507
  int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
512
  {
  	struct vfsmount *mnt = NULL;
  	spin_lock(&pin_fs_lock);
  	if (unlikely(!*mount)) {
  		spin_unlock(&pin_fs_lock);
1f5ce9e93   Trond Myklebust   VFS: Unexport do_...
513
  		mnt = vfs_kern_mount(type, 0, type->name, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  		if (IS_ERR(mnt))
  			return PTR_ERR(mnt);
  		spin_lock(&pin_fs_lock);
  		if (!*mount)
  			*mount = mnt;
  	}
  	mntget(*mount);
  	++*count;
  	spin_unlock(&pin_fs_lock);
  	mntput(mnt);
  	return 0;
  }
  
  void simple_release_fs(struct vfsmount **mount, int *count)
  {
  	struct vfsmount *mnt;
  	spin_lock(&pin_fs_lock);
  	mnt = *mount;
  	if (!--*count)
  		*mount = NULL;
  	spin_unlock(&pin_fs_lock);
  	mntput(mnt);
  }
6d1029b56   Akinobu Mita   add kernel-doc fo...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  /**
   * simple_read_from_buffer - copy data from the buffer to user space
   * @to: the user space buffer to read to
   * @count: the maximum number of bytes to read
   * @ppos: the current position in the buffer
   * @from: the buffer to read from
   * @available: the size of the buffer
   *
   * The simple_read_from_buffer() function reads up to @count bytes from the
   * buffer @from at offset @ppos into the user space address starting at @to.
   *
   * On success, the number of bytes read is returned and the offset @ppos is
   * advanced by this number, or negative value is returned on error.
   **/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
  ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
  				const void *from, size_t available)
  {
  	loff_t pos = *ppos;
14be27460   Steven Rostedt   libfs: make simpl...
555
  	size_t ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
  	if (pos < 0)
  		return -EINVAL;
14be27460   Steven Rostedt   libfs: make simpl...
558
  	if (pos >= available || !count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
  		return 0;
  	if (count > available - pos)
  		count = available - pos;
14be27460   Steven Rostedt   libfs: make simpl...
562
563
  	ret = copy_to_user(to, from + pos, count);
  	if (ret == count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  		return -EFAULT;
14be27460   Steven Rostedt   libfs: make simpl...
565
  	count -= ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
  	*ppos = pos + count;
  	return count;
  }
6d1029b56   Akinobu Mita   add kernel-doc fo...
569
  /**
6a727b43b   Jiri Slaby   FS / libfs: Imple...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
   * simple_write_to_buffer - copy data from user space to the buffer
   * @to: the buffer to write to
   * @available: the size of the buffer
   * @ppos: the current position in the buffer
   * @from: the user space buffer to read from
   * @count: the maximum number of bytes to read
   *
   * The simple_write_to_buffer() function reads up to @count bytes from the user
   * space address starting at @from into the buffer @to at offset @ppos.
   *
   * On success, the number of bytes written is returned and the offset @ppos is
   * advanced by this number, or negative value is returned on error.
   **/
  ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
  		const void __user *from, size_t count)
  {
  	loff_t pos = *ppos;
  	size_t res;
  
  	if (pos < 0)
  		return -EINVAL;
  	if (pos >= available || !count)
  		return 0;
  	if (count > available - pos)
  		count = available - pos;
  	res = copy_from_user(to + pos, from, count);
  	if (res == count)
  		return -EFAULT;
  	count -= res;
  	*ppos = pos + count;
  	return count;
  }
  
  /**
6d1029b56   Akinobu Mita   add kernel-doc fo...
604
605
606
607
608
609
610
611
612
613
614
615
616
   * memory_read_from_buffer - copy data from the buffer
   * @to: the kernel space buffer to read to
   * @count: the maximum number of bytes to read
   * @ppos: the current position in the buffer
   * @from: the buffer to read from
   * @available: the size of the buffer
   *
   * The memory_read_from_buffer() function reads up to @count bytes from the
   * buffer @from at offset @ppos into the kernel space address starting at @to.
   *
   * On success, the number of bytes read is returned and the offset @ppos is
   * advanced by this number, or negative value is returned on error.
   **/
93b071139   Akinobu Mita   introduce memory_...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
  ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
  				const void *from, size_t available)
  {
  	loff_t pos = *ppos;
  
  	if (pos < 0)
  		return -EINVAL;
  	if (pos >= available)
  		return 0;
  	if (count > available - pos)
  		count = available - pos;
  	memcpy(to, from + pos, count);
  	*ppos = pos + count;
  
  	return count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
637
638
  /*
   * Transaction based IO.
   * The file expects a single write which triggers the transaction, and then
   * possibly a read which collects the result - which is stored in a
   * file-local buffer.
   */
76791ab2d   Ingo Molnar   kmemtrace, fs: un...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  
  void simple_transaction_set(struct file *file, size_t n)
  {
  	struct simple_transaction_argresp *ar = file->private_data;
  
  	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
  
  	/*
  	 * The barrier ensures that ar->size will really remain zero until
  	 * ar->data is ready for reading.
  	 */
  	smp_mb();
  	ar->size = n;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
  {
  	struct simple_transaction_argresp *ar;
  	static DEFINE_SPINLOCK(simple_transaction_lock);
  
  	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
  		return ERR_PTR(-EFBIG);
  
  	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
  	if (!ar)
  		return ERR_PTR(-ENOMEM);
  
  	spin_lock(&simple_transaction_lock);
  
  	/* only one write allowed per open */
  	if (file->private_data) {
  		spin_unlock(&simple_transaction_lock);
  		free_page((unsigned long)ar);
  		return ERR_PTR(-EBUSY);
  	}
  
  	file->private_data = ar;
  
  	spin_unlock(&simple_transaction_lock);
  
  	if (copy_from_user(ar->data, buf, size))
  		return ERR_PTR(-EFAULT);
  
  	return ar->data;
  }
  
  ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
  {
  	struct simple_transaction_argresp *ar = file->private_data;
  
  	if (!ar)
  		return 0;
  	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
  }
  
  int simple_transaction_release(struct inode *inode, struct file *file)
  {
  	free_page((unsigned long)file->private_data);
  	return 0;
  }
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
698
699
700
  /* Simple attribute files */
  
  struct simple_attr {
8b88b0998   Christoph Hellwig   libfs: allow erro...
701
702
  	int (*get)(void *, u64 *);
  	int (*set)(void *, u64);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
703
704
705
706
707
  	char get_buf[24];	/* enough to store a u64 and "
  \0" */
  	char set_buf[24];
  	void *data;
  	const char *fmt;	/* format for read operation */
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
708
  	struct mutex mutex;	/* protects access to these buffers */
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
709
710
711
712
713
  };
  
  /* simple_attr_open is called by an actual attribute open file operation
   * to set the attribute specific access operations. */
  int simple_attr_open(struct inode *inode, struct file *file,
8b88b0998   Christoph Hellwig   libfs: allow erro...
714
  		     int (*get)(void *, u64 *), int (*set)(void *, u64),
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
715
716
717
718
719
720
721
722
723
724
  		     const char *fmt)
  {
  	struct simple_attr *attr;
  
  	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
  	if (!attr)
  		return -ENOMEM;
  
  	attr->get = get;
  	attr->set = set;
8e18e2941   Theodore Ts'o   [PATCH] inode_die...
725
  	attr->data = inode->i_private;
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
726
  	attr->fmt = fmt;
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
727
  	mutex_init(&attr->mutex);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
728
729
730
731
732
  
  	file->private_data = attr;
  
  	return nonseekable_open(inode, file);
  }
74bedc4d5   Christoph Hellwig   libfs: rename sim...
733
  int simple_attr_release(struct inode *inode, struct file *file)
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
  {
  	kfree(file->private_data);
  	return 0;
  }
  
  /* read from the buffer that is filled with the get function */
  ssize_t simple_attr_read(struct file *file, char __user *buf,
  			 size_t len, loff_t *ppos)
  {
  	struct simple_attr *attr;
  	size_t size;
  	ssize_t ret;
  
  	attr = file->private_data;
  
  	if (!attr->get)
  		return -EACCES;
9261303ab   Christoph Hellwig   libfs: make simpl...
751
752
753
  	ret = mutex_lock_interruptible(&attr->mutex);
  	if (ret)
  		return ret;
8b88b0998   Christoph Hellwig   libfs: allow erro...
754
  	if (*ppos) {		/* continued read */
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
755
  		size = strlen(attr->get_buf);
8b88b0998   Christoph Hellwig   libfs: allow erro...
756
757
758
759
760
  	} else {		/* first read */
  		u64 val;
  		ret = attr->get(attr->data, &val);
  		if (ret)
  			goto out;
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
761
  		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
8b88b0998   Christoph Hellwig   libfs: allow erro...
762
763
  				 attr->fmt, (unsigned long long)val);
  	}
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
764
765
  
  	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
8b88b0998   Christoph Hellwig   libfs: allow erro...
766
  out:
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
767
  	mutex_unlock(&attr->mutex);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
768
769
770
771
772
773
774
775
776
777
778
779
780
  	return ret;
  }
  
  /* interpret the buffer as a number to call the set function with */
  ssize_t simple_attr_write(struct file *file, const char __user *buf,
  			  size_t len, loff_t *ppos)
  {
  	struct simple_attr *attr;
  	u64 val;
  	size_t size;
  	ssize_t ret;
  
  	attr = file->private_data;
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
781
782
  	if (!attr->set)
  		return -EACCES;
9261303ab   Christoph Hellwig   libfs: make simpl...
783
784
785
  	ret = mutex_lock_interruptible(&attr->mutex);
  	if (ret)
  		return ret;
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
786
787
788
789
  	ret = -EFAULT;
  	size = min(sizeof(attr->set_buf) - 1, len);
  	if (copy_from_user(attr->set_buf, buf, size))
  		goto out;
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
790
  	attr->set_buf[size] = '\0';
f7b88631a   Akinobu Mita   fs/libfs.c: fix s...
791
  	val = simple_strtoll(attr->set_buf, NULL, 0);
05cc0cee6   Wu Fengguang   libfs: return err...
792
793
794
  	ret = attr->set(attr->data, val);
  	if (ret == 0)
  		ret = len; /* on success, claim we got the whole input */
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
795
  out:
7cf34c761   Ingo Molnar   [PATCH] sem2mutex...
796
  	mutex_unlock(&attr->mutex);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
797
798
  	return ret;
  }
2596110a3   Christoph Hellwig   exportfs: add new...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  /**
   * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
   * @sb:		filesystem to do the file handle conversion on
   * @fid:	file handle to convert
   * @fh_len:	length of the file handle in bytes
   * @fh_type:	type of file handle
   * @get_inode:	filesystem callback to retrieve inode
   *
   * This function decodes @fid as long as it has one of the well-known
   * Linux filehandle types and calls @get_inode on it to retrieve the
   * inode for the object specified in the file handle.
   */
  struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type, struct inode *(*get_inode)
  			(struct super_block *sb, u64 ino, u32 gen))
  {
  	struct inode *inode = NULL;
  
  	if (fh_len < 2)
  		return NULL;
  
  	switch (fh_type) {
  	case FILEID_INO32_GEN:
  	case FILEID_INO32_GEN_PARENT:
  		inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
  		break;
  	}
4ea3ada29   Christoph Hellwig   [PATCH] new helpe...
826
  	return d_obtain_alias(inode);
2596110a3   Christoph Hellwig   exportfs: add new...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  }
  EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
  
  /**
   * generic_fh_to_dentry - generic helper for the fh_to_parent export operation
   * @sb:		filesystem to do the file handle conversion on
   * @fid:	file handle to convert
   * @fh_len:	length of the file handle in bytes
   * @fh_type:	type of file handle
   * @get_inode:	filesystem callback to retrieve inode
   *
   * This function decodes @fid as long as it has one of the well-known
   * Linux filehandle types and calls @get_inode on it to retrieve the
   * inode for the _parent_ object specified in the file handle if it
   * is specified in the file handle, or NULL otherwise.
   */
  struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type, struct inode *(*get_inode)
  			(struct super_block *sb, u64 ino, u32 gen))
  {
  	struct inode *inode = NULL;
  
  	if (fh_len <= 2)
  		return NULL;
  
  	switch (fh_type) {
  	case FILEID_INO32_GEN_PARENT:
  		inode = get_inode(sb, fid->i32.parent_ino,
  				  (fh_len > 3 ? fid->i32.parent_gen : 0));
  		break;
  	}
4ea3ada29   Christoph Hellwig   [PATCH] new helpe...
858
  	return d_obtain_alias(inode);
2596110a3   Christoph Hellwig   exportfs: add new...
859
860
  }
  EXPORT_SYMBOL_GPL(generic_fh_to_parent);
1b061d924   Christoph Hellwig   rename the generi...
861
862
863
864
865
866
867
868
869
  /**
   * generic_file_fsync - generic fsync implementation for simple filesystems
   * @file:	file to synchronize
   * @datasync:	only synchronize essential metadata if true
   *
   * This is a generic implementation of the fsync method for simple
   * filesystems which track all non-inode metadata in the buffers list
   * hanging off the address_space structure.
   */
02c24a821   Josef Bacik   fs: push i_mutex ...
870
871
  int generic_file_fsync(struct file *file, loff_t start, loff_t end,
  		       int datasync)
d5aacad54   Al Viro   New helper - simp...
872
  {
7ea808591   Christoph Hellwig   drop unused dentr...
873
  	struct inode *inode = file->f_mapping->host;
d5aacad54   Al Viro   New helper - simp...
874
875
  	int err;
  	int ret;
02c24a821   Josef Bacik   fs: push i_mutex ...
876
877
878
879
880
  	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
  	if (err)
  		return err;
  
  	mutex_lock(&inode->i_mutex);
d5aacad54   Al Viro   New helper - simp...
881
882
  	ret = sync_mapping_buffers(inode->i_mapping);
  	if (!(inode->i_state & I_DIRTY))
02c24a821   Josef Bacik   fs: push i_mutex ...
883
  		goto out;
d5aacad54   Al Viro   New helper - simp...
884
  	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
02c24a821   Josef Bacik   fs: push i_mutex ...
885
  		goto out;
d5aacad54   Al Viro   New helper - simp...
886

c37650161   Christoph Hellwig   fs: add sync_inod...
887
  	err = sync_inode_metadata(inode, 1);
d5aacad54   Al Viro   New helper - simp...
888
889
  	if (ret == 0)
  		ret = err;
02c24a821   Josef Bacik   fs: push i_mutex ...
890
891
  out:
  	mutex_unlock(&inode->i_mutex);
d5aacad54   Al Viro   New helper - simp...
892
893
  	return ret;
  }
1b061d924   Christoph Hellwig   rename the generi...
894
  EXPORT_SYMBOL(generic_file_fsync);
30ca22c70   Patrick J. LoPresti   ext3/ext4: Factor...
895
896
897
898
899
900
901
902
903
904
905
906
  /**
   * generic_check_addressable - Check addressability of file system
   * @blocksize_bits:	log of file system block size
   * @num_blocks:		number of blocks in file system
   *
   * Determine whether a file system with @num_blocks blocks (and a
   * block size of 2**@blocksize_bits) is addressable by the sector_t
   * and page cache of the system.  Return 0 if so and -EFBIG otherwise.
   */
  int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
  {
  	u64 last_fs_block = num_blocks - 1;
a33f13efe   Joel Becker   libfs: Fix shift ...
907
908
  	u64 last_fs_page =
  		last_fs_block >> (PAGE_CACHE_SHIFT - blocksize_bits);
30ca22c70   Patrick J. LoPresti   ext3/ext4: Factor...
909
910
911
912
913
914
  
  	if (unlikely(num_blocks == 0))
  		return 0;
  
  	if ((blocksize_bits < 9) || (blocksize_bits > PAGE_CACHE_SHIFT))
  		return -EINVAL;
a33f13efe   Joel Becker   libfs: Fix shift ...
915
916
  	if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
  	    (last_fs_page > (pgoff_t)(~0ULL))) {
30ca22c70   Patrick J. LoPresti   ext3/ext4: Factor...
917
918
919
920
921
  		return -EFBIG;
  	}
  	return 0;
  }
  EXPORT_SYMBOL(generic_check_addressable);
1b061d924   Christoph Hellwig   rename the generi...
922
923
924
  /*
   * No-op implementation of ->fsync for in-memory filesystems.
   */
02c24a821   Josef Bacik   fs: push i_mutex ...
925
  int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
1b061d924   Christoph Hellwig   rename the generi...
926
927
928
  {
  	return 0;
  }
d5aacad54   Al Viro   New helper - simp...
929

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
  EXPORT_SYMBOL(dcache_dir_close);
  EXPORT_SYMBOL(dcache_dir_lseek);
  EXPORT_SYMBOL(dcache_dir_open);
  EXPORT_SYMBOL(dcache_readdir);
  EXPORT_SYMBOL(generic_read_dir);
51139adac   Al Viro   convert get_sb_ps...
935
  EXPORT_SYMBOL(mount_pseudo);
afddba49d   Nick Piggin   fs: introduce wri...
936
937
  EXPORT_SYMBOL(simple_write_begin);
  EXPORT_SYMBOL(simple_write_end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
  EXPORT_SYMBOL(simple_dir_inode_operations);
  EXPORT_SYMBOL(simple_dir_operations);
  EXPORT_SYMBOL(simple_empty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
945
  EXPORT_SYMBOL(simple_fill_super);
  EXPORT_SYMBOL(simple_getattr);
  EXPORT_SYMBOL(simple_link);
  EXPORT_SYMBOL(simple_lookup);
  EXPORT_SYMBOL(simple_pin_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
947
948
949
950
  EXPORT_SYMBOL(simple_readpage);
  EXPORT_SYMBOL(simple_release_fs);
  EXPORT_SYMBOL(simple_rename);
  EXPORT_SYMBOL(simple_rmdir);
  EXPORT_SYMBOL(simple_statfs);
1b061d924   Christoph Hellwig   rename the generi...
951
  EXPORT_SYMBOL(noop_fsync);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  EXPORT_SYMBOL(simple_unlink);
  EXPORT_SYMBOL(simple_read_from_buffer);
6a727b43b   Jiri Slaby   FS / libfs: Imple...
954
  EXPORT_SYMBOL(simple_write_to_buffer);
93b071139   Akinobu Mita   introduce memory_...
955
  EXPORT_SYMBOL(memory_read_from_buffer);
76791ab2d   Ingo Molnar   kmemtrace, fs: un...
956
  EXPORT_SYMBOL(simple_transaction_set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
959
  EXPORT_SYMBOL(simple_transaction_get);
  EXPORT_SYMBOL(simple_transaction_read);
  EXPORT_SYMBOL(simple_transaction_release);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
960
  EXPORT_SYMBOL_GPL(simple_attr_open);
74bedc4d5   Christoph Hellwig   libfs: rename sim...
961
  EXPORT_SYMBOL_GPL(simple_attr_release);
acaefc25d   Arnd Bergmann   [PATCH] libfs: ad...
962
963
  EXPORT_SYMBOL_GPL(simple_attr_read);
  EXPORT_SYMBOL_GPL(simple_attr_write);