Blame view

fs/jffs2/fs.c 19.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2001-2007 Red Hat, Inc.
6088c0587   David Woodhouse   jffs2: Update cop...
5
   * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
   *
   * Created by David Woodhouse <dwmw2@infradead.org>
   *
   * For licensing information, see the file 'LICENCE' in this directory.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
12
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
13
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
20
21
22
23
24
25
26
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/fs.h>
  #include <linux/list.h>
  #include <linux/mtd/mtd.h>
  #include <linux/pagemap.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
  #include <linux/vfs.h>
  #include <linux/crc32.h>
  #include "nodelist.h"
  
  static int jffs2_flash_setup(struct jffs2_sb_info *c);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
27
  int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
32
  {
  	struct jffs2_full_dnode *old_metadata, *new_metadata;
  	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
  	struct jffs2_raw_inode *ri;
aef9ab478   David Woodhouse   [JFFS2] Support n...
33
  	union jffs2_device_node dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  	unsigned char *mdata = NULL;
  	int mdatalen = 0;
  	unsigned int ivalid;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
37
  	uint32_t alloclen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  	int ret;
dd919660a   David Woodhouse   [JFFS2] Use ALLOC...
39
  	int alloc_type = ALLOC_NORMAL;
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
40

9c261b33a   Joe Perches   jffs2: Convert mo...
41
42
  	jffs2_dbg(1, "%s(): ino #%lu
  ", __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
49
50
  
  	/* Special cases - we don't want more than one data node
  	   for these types on the medium at any time. So setattr
  	   must read the original data associated with the node
  	   (i.e. the device numbers or the target name) and write
  	   it out again with the appropriate data attached */
  	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
  		/* For these, we don't actually need to read the old node */
aef9ab478   David Woodhouse   [JFFS2] Support n...
51
  		mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  		mdata = (char *)&dev;
9c261b33a   Joe Perches   jffs2: Convert mo...
53
54
55
  		jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t
  ",
  			  __func__, mdatalen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	} else if (S_ISLNK(inode->i_mode)) {
ced220703   David Woodhouse   [JFFS2] semaphore...
57
  		mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  		mdatalen = f->metadata->size;
  		mdata = kmalloc(f->metadata->size, GFP_USER);
422138dd6   Dmitry Bazhenov   [JFFS2] Fix race ...
60
  		if (!mdata) {
ced220703   David Woodhouse   [JFFS2] semaphore...
61
  			mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  			return -ENOMEM;
422138dd6   Dmitry Bazhenov   [JFFS2] Fix race ...
63
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
  		ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
  		if (ret) {
ced220703   David Woodhouse   [JFFS2] semaphore...
66
  			mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
  			kfree(mdata);
  			return ret;
  		}
ced220703   David Woodhouse   [JFFS2] semaphore...
70
  		mutex_unlock(&f->sem);
9c261b33a   Joe Perches   jffs2: Convert mo...
71
72
73
  		jffs2_dbg(1, "%s(): Writing %d bytes of symlink target
  ",
  			  __func__, mdatalen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
  	}
  
  	ri = jffs2_alloc_raw_inode();
  	if (!ri) {
  		if (S_ISLNK(inode->i_mode))
  			kfree(mdata);
  		return -ENOMEM;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
82

9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
83
84
  	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
  				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  	if (ret) {
  		jffs2_free_raw_inode(ri);
61effb519   Al Viro   jffs2: S_ISLNK(mo...
87
  		if (S_ISLNK(inode->i_mode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  			 kfree(mdata);
  		return ret;
  	}
ced220703   David Woodhouse   [JFFS2] semaphore...
91
  	mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	ivalid = iattr->ia_valid;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
93

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
  	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
  	ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
  	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
  
  	ri->ino = cpu_to_je32(inode->i_ino);
  	ri->version = cpu_to_je32(++f->highest_version);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
101
102
103
104
  	ri->uid = cpu_to_je16((ivalid & ATTR_UID)?
  		from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode));
  	ri->gid = cpu_to_je16((ivalid & ATTR_GID)?
  		from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  
  	if (ivalid & ATTR_MODE)
857013b87   David Woodhouse   [JFFS2] Don't str...
107
  		ri->mode = cpu_to_jemode(iattr->ia_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  	else
  		ri->mode = cpu_to_jemode(inode->i_mode);
  
  
  	ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);
  	ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime));
  	ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime));
  	ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime));
  
  	ri->offset = cpu_to_je32(0);
  	ri->csize = ri->dsize = cpu_to_je32(mdatalen);
  	ri->compr = JFFS2_COMPR_NONE;
  	if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
  		/* It's an extension. Make it a hole node */
  		ri->compr = JFFS2_COMPR_ZERO;
  		ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
  		ri->offset = cpu_to_je32(inode->i_size);
dd919660a   David Woodhouse   [JFFS2] Use ALLOC...
125
126
127
128
  	} else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
  		/* For truncate-to-zero, treat it as deletion because
  		   it'll always be obsoleting all previous nodes */
  		alloc_type = ALLOC_DELETION;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
  	}
  	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
  	if (mdatalen)
  		ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
  	else
  		ri->data_crc = cpu_to_je32(0);
dd919660a   David Woodhouse   [JFFS2] Use ALLOC...
135
  	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  	if (S_ISLNK(inode->i_mode))
  		kfree(mdata);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
138

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  	if (IS_ERR(new_metadata)) {
  		jffs2_complete_reservation(c);
  		jffs2_free_raw_inode(ri);
ced220703   David Woodhouse   [JFFS2] semaphore...
142
  		mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
149
  		return PTR_ERR(new_metadata);
  	}
  	/* It worked. Update the inode */
  	inode->i_atime = ITIME(je32_to_cpu(ri->atime));
  	inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));
  	inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
  	inode->i_mode = jemode_to_cpu(ri->mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
150
151
  	i_uid_write(inode, je16_to_cpu(ri->uid));
  	i_gid_write(inode, je16_to_cpu(ri->gid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
  
  
  	old_metadata = f->metadata;
  
  	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
f302cd028   Artem B. Bityutskiy   [JFFS2] Namespace...
157
  		jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
  
  	if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
  		jffs2_add_full_dnode_to_inode(c, f, new_metadata);
  		inode->i_size = iattr->ia_size;
b28ba9fa0   David Woodhouse   [JFFS2] Set i_blo...
162
  		inode->i_blocks = (inode->i_size + 511) >> 9;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
170
171
  		f->metadata = NULL;
  	} else {
  		f->metadata = new_metadata;
  	}
  	if (old_metadata) {
  		jffs2_mark_node_obsolete(c, old_metadata->raw);
  		jffs2_free_full_dnode(old_metadata);
  	}
  	jffs2_free_raw_inode(ri);
ced220703   David Woodhouse   [JFFS2] semaphore...
172
  	mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  	jffs2_complete_reservation(c);
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
174
  	/* We have to do the truncate_setsize() without f->sem held, since
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
175
  	   some pages may be locked and waiting for it in readpage().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
  	   We are protected from a simultaneous write() extending i_size
  	   back past iattr->ia_size, because do_truncate() holds the
  	   generic inode semaphore. */
b28ba9fa0   David Woodhouse   [JFFS2] Set i_blo...
179
  	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
180
  		truncate_setsize(inode, iattr->ia_size);
b28ba9fa0   David Woodhouse   [JFFS2] Set i_blo...
181
182
  		inode->i_blocks = (inode->i_size + 511) >> 9;
  	}	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
  
  	return 0;
  }
  
  int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
  {
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
189
  	int rc;
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
190
191
192
  	rc = inode_change_ok(dentry->d_inode, iattr);
  	if (rc)
  		return rc;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
193
194
195
  	rc = jffs2_do_setattr(dentry->d_inode, iattr);
  	if (!rc && (iattr->ia_valid & ATTR_MODE))
  		rc = jffs2_acl_chmod(dentry->d_inode);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
196

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
197
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  }
726c33422   David Howells   [PATCH] VFS: Perm...
199
  int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  {
726c33422   David Howells   [PATCH] VFS: Perm...
201
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
  	unsigned long avail;
  
  	buf->f_type = JFFS2_SUPER_MAGIC;
  	buf->f_bsize = 1 << PAGE_SHIFT;
  	buf->f_blocks = c->flash_size >> PAGE_SHIFT;
  	buf->f_files = 0;
  	buf->f_ffree = 0;
  	buf->f_namelen = JFFS2_MAX_NAME_LEN;
75caf6b5a   David Woodhouse   [JFFS2] Fill in f...
210
211
  	buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC;
  	buf->f_fsid.val[1] = c->mtd->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  
  	spin_lock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
  	avail = c->dirty_size + c->free_size;
  	if (avail > c->sector_size * c->resv_blocks_write)
  		avail -= c->sector_size * c->resv_blocks_write;
  	else
  		avail = 0;
e0c8e42f8   Artem B. Bityutskiy   [JFFS2] Debug cod...
219
  	spin_unlock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  
  	buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  	return 0;
  }
b57922d97   Al Viro   convert remaining...
224
  void jffs2_evict_inode (struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
226
  	/* We can forget about this inode for now - drop all
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
  	 *  the nodelists associated with it, etc.
  	 */
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
  	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
231

9c261b33a   Joe Perches   jffs2: Convert mo...
232
233
234
  	jffs2_dbg(1, "%s(): ino #%lu mode %o
  ",
  		  __func__, inode->i_ino, inode->i_mode);
b57922d97   Al Viro   convert remaining...
235
  	truncate_inode_pages(&inode->i_data, 0);
dbd5768f8   Jan Kara   vfs: Rename end_w...
236
  	clear_inode(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
  	jffs2_do_clear_inode(c, f);
  }
5451f79f5   David Howells   iget: stop JFFS2 ...
239
  struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
  {
  	struct jffs2_inode_info *f;
  	struct jffs2_sb_info *c;
  	struct jffs2_raw_inode latest_node;
aef9ab478   David Woodhouse   [JFFS2] Support n...
244
  	union jffs2_device_node jdev;
5451f79f5   David Howells   iget: stop JFFS2 ...
245
  	struct inode *inode;
aef9ab478   David Woodhouse   [JFFS2] Support n...
246
  	dev_t rdev = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	int ret;
9c261b33a   Joe Perches   jffs2: Convert mo...
248
249
  	jffs2_dbg(1, "%s(): ino == %lu
  ", __func__, ino);
5451f79f5   David Howells   iget: stop JFFS2 ...
250
251
252
253
254
255
  
  	inode = iget_locked(sb, ino);
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  	if (!(inode->i_state & I_NEW))
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
260
  
  	f = JFFS2_INODE_INFO(inode);
  	c = JFFS2_SB_INFO(inode->i_sb);
  
  	jffs2_init_inode_info(f);
ced220703   David Woodhouse   [JFFS2] semaphore...
261
  	mutex_lock(&f->sem);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
262

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
  	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
  
  	if (ret) {
ced220703   David Woodhouse   [JFFS2] semaphore...
266
  		mutex_unlock(&f->sem);
5451f79f5   David Howells   iget: stop JFFS2 ...
267
268
  		iget_failed(inode);
  		return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	}
  	inode->i_mode = jemode_to_cpu(latest_node.mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
271
272
  	i_uid_write(inode, je16_to_cpu(latest_node.uid));
  	i_gid_write(inode, je16_to_cpu(latest_node.gid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
  	inode->i_size = je32_to_cpu(latest_node.isize);
  	inode->i_atime = ITIME(je32_to_cpu(latest_node.atime));
  	inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
  	inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
bfe868486   Miklos Szeredi   filesystems: add ...
277
  	set_nlink(inode, f->inocache->pino_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  	inode->i_blocks = (inode->i_size + 511) >> 9;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
280

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	switch (inode->i_mode & S_IFMT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
  
  	case S_IFLNK:
  		inode->i_op = &jffs2_symlink_inode_operations;
  		break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
286

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
  	case S_IFDIR:
  	{
  		struct jffs2_full_dirent *fd;
bfe868486   Miklos Szeredi   filesystems: add ...
290
  		set_nlink(inode, 2); /* parent and '.' */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
  
  		for (fd=f->dents; fd; fd = fd->next) {
  			if (fd->type == DT_DIR && fd->ino)
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
294
  				inc_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
  		/* Root dir gets i_nlink 3 for some reason */
  		if (inode->i_ino == 1)
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
298
  			inc_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  
  		inode->i_op = &jffs2_dir_inode_operations;
  		inode->i_fop = &jffs2_dir_operations;
  		break;
  	}
  	case S_IFREG:
  		inode->i_op = &jffs2_file_inode_operations;
  		inode->i_fop = &jffs2_file_operations;
  		inode->i_mapping->a_ops = &jffs2_file_address_operations;
  		inode->i_mapping->nrpages = 0;
  		break;
  
  	case S_IFBLK:
  	case S_IFCHR:
  		/* Read the device numbers from the media */
91f802660   Andrew Morton   JFFS2: avoid usin...
314
315
  		if (f->metadata->size != sizeof(jdev.old_id) &&
  		    f->metadata->size != sizeof(jdev.new_id)) {
da320f055   Joe Perches   jffs2: Convert pr...
316
317
318
  			pr_notice("Device node has strange size %d
  ",
  				  f->metadata->size);
5451f79f5   David Howells   iget: stop JFFS2 ...
319
  			goto error_io;
aef9ab478   David Woodhouse   [JFFS2] Support n...
320
  		}
9c261b33a   Joe Perches   jffs2: Convert mo...
321
322
  		jffs2_dbg(1, "Reading device numbers from flash
  ");
5451f79f5   David Howells   iget: stop JFFS2 ...
323
324
  		ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size);
  		if (ret < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  			/* Eep */
da320f055   Joe Perches   jffs2: Convert pr...
326
327
328
  			pr_notice("Read device numbers for inode %lu failed
  ",
  				  (unsigned long)inode->i_ino);
5451f79f5   David Howells   iget: stop JFFS2 ...
329
  			goto error;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
330
  		}
91f802660   Andrew Morton   JFFS2: avoid usin...
331
332
  		if (f->metadata->size == sizeof(jdev.old_id))
  			rdev = old_decode_dev(je16_to_cpu(jdev.old_id));
aef9ab478   David Woodhouse   [JFFS2] Support n...
333
  		else
91f802660   Andrew Morton   JFFS2: avoid usin...
334
  			rdev = new_decode_dev(je32_to_cpu(jdev.new_id));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
  
  	case S_IFSOCK:
  	case S_IFIFO:
  		inode->i_op = &jffs2_file_inode_operations;
aef9ab478   David Woodhouse   [JFFS2] Support n...
339
  		init_special_inode(inode, inode->i_mode, rdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
  		break;
  
  	default:
da320f055   Joe Perches   jffs2: Convert pr...
343
344
345
  		pr_warn("%s(): Bogus i_mode %o for ino %lu
  ",
  			__func__, inode->i_mode, (unsigned long)inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  	}
ced220703   David Woodhouse   [JFFS2] semaphore...
347
  	mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348

9c261b33a   Joe Perches   jffs2: Convert mo...
349
350
  	jffs2_dbg(1, "jffs2_read_inode() returning
  ");
5451f79f5   David Howells   iget: stop JFFS2 ...
351
352
353
354
355
356
  	unlock_new_inode(inode);
  	return inode;
  
  error_io:
  	ret = -EIO;
  error:
ced220703   David Woodhouse   [JFFS2] semaphore...
357
  	mutex_unlock(&f->sem);
5451f79f5   David Howells   iget: stop JFFS2 ...
358
359
360
  	jffs2_do_clear_inode(c, f);
  	iget_failed(inode);
  	return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  }
aa3857295   Christoph Hellwig   fs: pass exact ty...
362
  void jffs2_dirty_inode(struct inode *inode, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
  {
  	struct iattr iattr;
  
  	if (!(inode->i_state & I_DIRTY_DATASYNC)) {
9c261b33a   Joe Perches   jffs2: Convert mo...
367
368
369
  		jffs2_dbg(2, "%s(): not calling setattr() for ino #%lu
  ",
  			  __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  		return;
  	}
9c261b33a   Joe Perches   jffs2: Convert mo...
372
373
374
  	jffs2_dbg(1, "%s(): calling setattr() for ino #%lu
  ",
  		  __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
383
384
385
  
  	iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME;
  	iattr.ia_mode = inode->i_mode;
  	iattr.ia_uid = inode->i_uid;
  	iattr.ia_gid = inode->i_gid;
  	iattr.ia_atime = inode->i_atime;
  	iattr.ia_mtime = inode->i_mtime;
  	iattr.ia_ctime = inode->i_ctime;
  
  	jffs2_do_setattr(inode, &iattr);
  }
92abc475d   Andres Salomon   jffs2: implement ...
386
  int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
395
396
397
398
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
  
  	if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY))
  		return -EROFS;
  
  	/* We stop if it was running, then restart if it needs to.
  	   This also catches the case where it was stopped and this
  	   is just a remount to restart it.
  	   Flush the writebuffer, if neccecary, else we loose it */
  	if (!(sb->s_flags & MS_RDONLY)) {
  		jffs2_stop_garbage_collect_thread(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
399
  		mutex_lock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
  		jffs2_flush_wbuf_pad(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
401
  		mutex_unlock(&c->alloc_sem);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
402
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  
  	if (!(*flags & MS_RDONLY))
  		jffs2_start_garbage_collect_thread(c);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
406

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  	*flags |= MS_NOATIME;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
     fill in the raw_inode while you're at it. */
d3fb61207   Al Viro   switch posix_acl_...
412
  struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
  {
  	struct inode *inode;
  	struct super_block *sb = dir_i->i_sb;
  	struct jffs2_sb_info *c;
  	struct jffs2_inode_info *f;
  	int ret;
9c261b33a   Joe Perches   jffs2: Convert mo...
419
420
421
  	jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x
  ",
  		  __func__, dir_i->i_ino, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
  
  	c = JFFS2_SB_INFO(sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
424

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  	inode = new_inode(sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
426

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  
  	f = JFFS2_INODE_INFO(inode);
  	jffs2_init_inode_info(f);
ced220703   David Woodhouse   [JFFS2] semaphore...
432
  	mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
  
  	memset(ri, 0, sizeof(*ri));
  	/* Set OS-specific defaults for new inodes */
0cfe53d3c   Eric W. Biederman   userns: Convert j...
436
  	ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  
  	if (dir_i->i_mode & S_ISGID) {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
439
  		ri->gid = cpu_to_je16(i_gid_read(dir_i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
  		if (S_ISDIR(mode))
  			mode |= S_ISGID;
  	} else {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
443
  		ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	}
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
445
446
447
  
  	/* POSIX ACLs have to be processed now, at least partly.
  	   The umask is only applied if there's no default ACL */
cfc8dc6f6   KaiGai Kohei   [JFFS2] Tidy up f...
448
449
450
451
452
  	ret = jffs2_init_acl_pre(dir_i, inode, &mode);
  	if (ret) {
  	    make_bad_inode(inode);
  	    iput(inode);
  	    return ERR_PTR(ret);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
453
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
459
  	ret = jffs2_do_new_inode (c, f, mode, ri);
  	if (ret) {
  		make_bad_inode(inode);
  		iput(inode);
  		return ERR_PTR(ret);
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
460
  	set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
  	inode->i_ino = je32_to_cpu(ri->ino);
  	inode->i_mode = jemode_to_cpu(ri->mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
463
464
  	i_gid_write(inode, je16_to_cpu(ri->gid));
  	i_uid_write(inode, je16_to_cpu(ri->uid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  	inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
  	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
  	inode->i_blocks = 0;
  	inode->i_size = 0;
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
469
470
  	if (insert_inode_locked(inode) < 0) {
  		make_bad_inode(inode);
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
471
472
473
  		iput(inode);
  		return ERR_PTR(-EINVAL);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
  
  	return inode;
  }
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  static int calculate_inocache_hashsize(uint32_t flash_size)
  {
  	/*
  	 * Pick a inocache hash size based on the size of the medium.
  	 * Count how many megabytes we're dealing with, apply a hashsize twice
  	 * that size, but rounding down to the usual big powers of 2. And keep
  	 * to sensible bounds.
  	 */
  
  	int size_mb = flash_size / 1024 / 1024;
  	int hashsize = (size_mb * 2) & ~0x3f;
  
  	if (hashsize < INOCACHE_HASHSIZE_MIN)
  		return INOCACHE_HASHSIZE_MIN;
  	if (hashsize > INOCACHE_HASHSIZE_MAX)
  		return INOCACHE_HASHSIZE_MAX;
  
  	return hashsize;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
500
501
502
503
504
  
  int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct jffs2_sb_info *c;
  	struct inode *root_i;
  	int ret;
  	size_t blocks;
  
  	c = JFFS2_SB_INFO(sb);
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
505
  #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  	if (c->mtd->type == MTD_NANDFLASH) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
507
508
  		pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
  		return -EINVAL;
  	}
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
511
  	if (c->mtd->type == MTD_DATAFLASH) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
512
513
  		pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in
  ");
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
514
515
516
  		return -EINVAL;
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
  
  	c->flash_size = c->mtd->size;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
519
  	c->sector_size = c->mtd->erasesize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  	blocks = c->flash_size / c->sector_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
  
  	/*
  	 * Size alignment check
  	 */
  	if ((c->sector_size * blocks) != c->flash_size) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
526
  		c->flash_size = c->sector_size * blocks;
5a528957e   Joe Perches   jffs2: Use pr_fmt...
527
528
  		pr_info("Flash size not aligned to erasesize, reducing to %dKiB
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
  			c->flash_size / 1024);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  	if (c->flash_size < 5*c->sector_size) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
532
533
  		pr_err("Too few erase blocks (%d)
  ",
da320f055   Joe Perches   jffs2: Convert pr...
534
  		       c->flash_size / c->sector_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
  		return -EINVAL;
  	}
  
  	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
542
543
  
  	/* NAND (or other bizarre) flash... do setup accordingly */
  	ret = jffs2_flash_setup(c);
  	if (ret)
  		return ret;
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
544
545
  	c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
  	c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
  	if (!c->inocache_list) {
  		ret = -ENOMEM;
  		goto out_wbuf;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
551
  	jffs2_init_xattr_subsystem(c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
  	if ((ret = jffs2_do_mount_fs(c)))
  		goto out_inohash;
9c261b33a   Joe Perches   jffs2: Convert mo...
554
555
  	jffs2_dbg(1, "%s(): Getting root inode
  ", __func__);
5451f79f5   David Howells   iget: stop JFFS2 ...
556
557
  	root_i = jffs2_iget(sb, 1);
  	if (IS_ERR(root_i)) {
9c261b33a   Joe Perches   jffs2: Convert mo...
558
559
  		jffs2_dbg(1, "get root inode failed
  ");
5451f79f5   David Howells   iget: stop JFFS2 ...
560
561
  		ret = PTR_ERR(root_i);
  		goto out_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  	}
5451f79f5   David Howells   iget: stop JFFS2 ...
563
  	ret = -ENOMEM;
623ff7739   Linus Torvalds   Merge tag 'for-li...
564
565
  	jffs2_dbg(1, "%s(): d_make_root()
  ", __func__);
48fde701a   Al Viro   switch open-coded...
566
  	sb->s_root = d_make_root(root_i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  	if (!sb->s_root)
48fde701a   Al Viro   switch open-coded...
568
  		goto out_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
  	sb->s_maxbytes = 0xFFFFFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
  	sb->s_blocksize = PAGE_CACHE_SIZE;
  	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
  	sb->s_magic = JFFS2_SUPER_MAGIC;
  	if (!(sb->s_flags & MS_RDONLY))
  		jffs2_start_garbage_collect_thread(c);
  	return 0;
5451f79f5   David Howells   iget: stop JFFS2 ...
577
  out_root:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
  	jffs2_free_ino_caches(c);
  	jffs2_free_raw_node_refs(c);
4ce1f5621   Ferenc Havasi   [JFFS2] Remove su...
580
  	if (jffs2_blocks_use_vmalloc(c))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
584
  		vfree(c->blocks);
  	else
  		kfree(c->blocks);
   out_inohash:
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
585
  	jffs2_clear_xattr_subsystem(c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  	kfree(c->inocache_list);
   out_wbuf:
  	jffs2_flash_cleanup(c);
  
  	return ret;
  }
  
  void jffs2_gc_release_inode(struct jffs2_sb_info *c,
  				   struct jffs2_inode_info *f)
  {
  	iput(OFNI_EDONI_2SFFJ(f));
  }
  
  struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
1b690b487   David Woodhouse   [JFFS2] Invert la...
600
  					      int inum, int unlinked)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
  {
  	struct inode *inode;
  	struct jffs2_inode_cache *ic;
1b690b487   David Woodhouse   [JFFS2] Invert la...
604
605
  
  	if (unlinked) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  		/* The inode has zero nlink but its nodes weren't yet marked
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
607
  		   obsolete. This has to be because we're still waiting for
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  		   the final (close() and) iput() to happen.
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
609
  		   There's a possibility that the final iput() could have
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
  		   happened while we were contemplating. In order to ensure
  		   that we don't cause a new read_inode() (which would fail)
  		   for the inode in question, we use ilookup() in this case
  		   instead of iget().
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
614
  		   The nlink can't _become_ zero at this point because we're
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
618
619
  		   holding the alloc_sem, and jffs2_do_unlink() would also
  		   need that while decrementing nlink on any inode.
  		*/
  		inode = ilookup(OFNI_BS_2SFFJ(c), inum);
  		if (!inode) {
9c261b33a   Joe Perches   jffs2: Convert mo...
620
621
622
  			jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.
  ",
  				  inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
626
  
  			spin_lock(&c->inocache_lock);
  			ic = jffs2_get_ino_cache(c, inum);
  			if (!ic) {
9c261b33a   Joe Perches   jffs2: Convert mo...
627
628
629
  				jffs2_dbg(1, "Inode cache for ino #%u is gone
  ",
  					  inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
632
633
634
  				spin_unlock(&c->inocache_lock);
  				return NULL;
  			}
  			if (ic->state != INO_STATE_CHECKEDABSENT) {
  				/* Wait for progress. Don't just loop */
9c261b33a   Joe Perches   jffs2: Convert mo...
635
636
637
  				jffs2_dbg(1, "Waiting for ino #%u in state %d
  ",
  					  ic->ino, ic->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
644
645
646
647
648
649
  				sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
  			} else {
  				spin_unlock(&c->inocache_lock);
  			}
  
  			return NULL;
  		}
  	} else {
  		/* Inode has links to it still; they're not going away because
  		   jffs2_do_unlink() would need the alloc_sem and we have it.
  		   Just iget() it, and if read_inode() is necessary that's OK.
  		*/
5451f79f5   David Howells   iget: stop JFFS2 ...
650
651
652
  		inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
  		if (IS_ERR(inode))
  			return ERR_CAST(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
  	}
  	if (is_bad_inode(inode)) {
da320f055   Joe Perches   jffs2: Convert pr...
655
656
657
  		pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d
  ",
  			  inum, unlinked);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
  		/* NB. This will happen again. We need to do something appropriate here. */
  		iput(inode);
  		return ERR_PTR(-EIO);
  	}
  
  	return JFFS2_INODE_INFO(inode);
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
665
666
  unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
  				   struct jffs2_inode_info *f,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
671
  				   unsigned long offset,
  				   unsigned long *priv)
  {
  	struct inode *inode = OFNI_EDONI_2SFFJ(f);
  	struct page *pg;
fc0e01974   Jason Lunz   [JFFS2] fix write...
672
  	pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
  			     (void *)jffs2_do_readpage_unlock, inode);
  	if (IS_ERR(pg))
  		return (void *)pg;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
676

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  	*priv = (unsigned long)pg;
  	return kmap(pg);
  }
  
  void jffs2_gc_release_page(struct jffs2_sb_info *c,
  			   unsigned char *ptr,
  			   unsigned long *priv)
  {
  	struct page *pg = (void *)*priv;
  
  	kunmap(pg);
  	page_cache_release(pg);
  }
  
  static int jffs2_flash_setup(struct jffs2_sb_info *c) {
  	int ret = 0;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
693

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
699
  	if (jffs2_cleanmarker_oob(c)) {
  		/* NAND flash... do setup accordingly */
  		ret = jffs2_nand_flash_setup(c);
  		if (ret)
  			return ret;
  	}
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
700
701
702
703
704
705
  	/* and Dataflash */
  	if (jffs2_dataflash(c)) {
  		ret = jffs2_dataflash_setup(c);
  		if (ret)
  			return ret;
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
706
707
708
709
710
711
712
  
  	/* and Intel "Sibley" flash */
  	if (jffs2_nor_wbuf_flash(c)) {
  		ret = jffs2_nor_wbuf_flash_setup(c);
  		if (ret)
  			return ret;
  	}
0029da3bf   Artem Bityutskiy   JFFS2: add UBI su...
713
714
715
716
717
718
  	/* and an UBI volume */
  	if (jffs2_ubivol(c)) {
  		ret = jffs2_ubivol_setup(c);
  		if (ret)
  			return ret;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
723
724
725
726
  	return ret;
  }
  
  void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
  
  	if (jffs2_cleanmarker_oob(c)) {
  		jffs2_nand_flash_cleanup(c);
  	}
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
727
728
729
730
  	/* and DataFlash */
  	if (jffs2_dataflash(c)) {
  		jffs2_dataflash_cleanup(c);
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
731
732
733
734
735
  
  	/* and Intel "Sibley" flash */
  	if (jffs2_nor_wbuf_flash(c)) {
  		jffs2_nor_wbuf_flash_cleanup(c);
  	}
0029da3bf   Artem Bityutskiy   JFFS2: add UBI su...
736
737
738
739
740
  
  	/* and an UBI volume */
  	if (jffs2_ubivol(c)) {
  		jffs2_ubivol_cleanup(c);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  }