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)
  {
2b0143b5c   David Howells   VFS: normal files...
189
  	struct inode *inode = d_inode(dentry);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
190
  	int rc;
f2963d455   Christoph Hellwig   jffs2: use generi...
191
  	rc = inode_change_ok(inode, iattr);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
192
193
  	if (rc)
  		return rc;
f2963d455   Christoph Hellwig   jffs2: use generi...
194
  	rc = jffs2_do_setattr(inode, iattr);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
195
  	if (!rc && (iattr->ia_valid & ATTR_MODE))
f2963d455   Christoph Hellwig   jffs2: use generi...
196
  		rc = posix_acl_chmod(inode, inode->i_mode);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
197

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
198
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  }
726c33422   David Howells   [PATCH] VFS: Perm...
200
  int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  {
726c33422   David Howells   [PATCH] VFS: Perm...
202
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
206
207
208
209
210
  	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...
211
212
  	buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC;
  	buf->f_fsid.val[1] = c->mtd->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  
  	spin_lock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
  	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...
220
  	spin_unlock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  
  	buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
  	return 0;
  }
b57922d97   Al Viro   convert remaining...
225
  void jffs2_evict_inode (struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
227
  	/* We can forget about this inode for now - drop all
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
  	 *  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 ...
232

9c261b33a   Joe Perches   jffs2: Convert mo...
233
234
235
  	jffs2_dbg(1, "%s(): ino #%lu mode %o
  ",
  		  __func__, inode->i_ino, inode->i_mode);
91b0abe36   Johannes Weiner   mm + fs: store sh...
236
  	truncate_inode_pages_final(&inode->i_data);
dbd5768f8   Jan Kara   vfs: Rename end_w...
237
  	clear_inode(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  	jffs2_do_clear_inode(c, f);
  }
5451f79f5   David Howells   iget: stop JFFS2 ...
240
  struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
243
244
  {
  	struct jffs2_inode_info *f;
  	struct jffs2_sb_info *c;
  	struct jffs2_raw_inode latest_node;
aef9ab478   David Woodhouse   [JFFS2] Support n...
245
  	union jffs2_device_node jdev;
5451f79f5   David Howells   iget: stop JFFS2 ...
246
  	struct inode *inode;
aef9ab478   David Woodhouse   [JFFS2] Support n...
247
  	dev_t rdev = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  	int ret;
9c261b33a   Joe Perches   jffs2: Convert mo...
249
250
  	jffs2_dbg(1, "%s(): ino == %lu
  ", __func__, ino);
5451f79f5   David Howells   iget: stop JFFS2 ...
251
252
253
254
255
256
  
  	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
257
258
259
260
261
  
  	f = JFFS2_INODE_INFO(inode);
  	c = JFFS2_SB_INFO(inode->i_sb);
  
  	jffs2_init_inode_info(f);
ced220703   David Woodhouse   [JFFS2] semaphore...
262
  	mutex_lock(&f->sem);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
263

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
7aaea7605   Brian Norris   jffs2: fix unbala...
265
266
  	if (ret)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  	inode->i_mode = jemode_to_cpu(latest_node.mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
269
270
  	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
271
272
273
274
  	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 ...
275
  	set_nlink(inode, f->inocache->pino_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  	switch (inode->i_mode & S_IFMT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
  
  	case S_IFLNK:
  		inode->i_op = &jffs2_symlink_inode_operations;
a8db149fc   Al Viro   jffs2: switch to ...
283
  		inode->i_link = f->target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  		break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
285

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

9c261b33a   Joe Perches   jffs2: Convert mo...
348
349
  	jffs2_dbg(1, "jffs2_read_inode() returning
  ");
5451f79f5   David Howells   iget: stop JFFS2 ...
350
351
352
353
354
355
  	unlock_new_inode(inode);
  	return inode;
  
  error_io:
  	ret = -EIO;
  error:
ced220703   David Woodhouse   [JFFS2] semaphore...
356
  	mutex_unlock(&f->sem);
5451f79f5   David Howells   iget: stop JFFS2 ...
357
358
359
  	jffs2_do_clear_inode(c, f);
  	iget_failed(inode);
  	return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  }
aa3857295   Christoph Hellwig   fs: pass exact ty...
361
  void jffs2_dirty_inode(struct inode *inode, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
  {
  	struct iattr iattr;
  
  	if (!(inode->i_state & I_DIRTY_DATASYNC)) {
9c261b33a   Joe Perches   jffs2: Convert mo...
366
367
368
  		jffs2_dbg(2, "%s(): not calling setattr() for ino #%lu
  ",
  			  __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  		return;
  	}
9c261b33a   Joe Perches   jffs2: Convert mo...
371
372
373
  	jffs2_dbg(1, "%s(): calling setattr() for ino #%lu
  ",
  		  __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
377
378
379
380
381
382
383
384
  
  	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 ...
385
  int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
391
392
393
394
395
396
397
  {
  	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...
398
  		mutex_lock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  		jffs2_flush_wbuf_pad(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
400
  		mutex_unlock(&c->alloc_sem);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
401
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
  
  	if (!(*flags & MS_RDONLY))
  		jffs2_start_garbage_collect_thread(c);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
405

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	*flags |= MS_NOATIME;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
  /* 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_...
411
  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
412
413
414
415
416
417
  {
  	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...
418
419
420
  	jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x
  ",
  		  __func__, dir_i->i_ino, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
  
  	c = JFFS2_SB_INFO(sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
423

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
429
430
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  
  	f = JFFS2_INODE_INFO(inode);
  	jffs2_init_inode_info(f);
ced220703   David Woodhouse   [JFFS2] semaphore...
431
  	mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
  
  	memset(ri, 0, sizeof(*ri));
  	/* Set OS-specific defaults for new inodes */
0cfe53d3c   Eric W. Biederman   userns: Convert j...
435
  	ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
  
  	if (dir_i->i_mode & S_ISGID) {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
438
  		ri->gid = cpu_to_je16(i_gid_read(dir_i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
  		if (S_ISDIR(mode))
  			mode |= S_ISGID;
  	} else {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
442
  		ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  	}
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
444
445
446
  
  	/* 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...
447
448
  	ret = jffs2_init_acl_pre(dir_i, inode, &mode);
  	if (ret) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
449
450
451
452
  		mutex_unlock(&f->sem);
  		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
  	ret = jffs2_do_new_inode (c, f, mode, ri);
  	if (ret) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
456
  		mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
  		make_bad_inode(inode);
  		iput(inode);
  		return ERR_PTR(ret);
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
461
  	set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
  	inode->i_ino = je32_to_cpu(ri->ino);
  	inode->i_mode = jemode_to_cpu(ri->mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
464
465
  	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
466
467
  	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
468
469
  	inode->i_blocks = 0;
  	inode->i_size = 0;
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
470
  	if (insert_inode_locked(inode) < 0) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
471
  		mutex_unlock(&f->sem);
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
472
  		make_bad_inode(inode);
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
473
474
475
  		iput(inode);
  		return ERR_PTR(-EINVAL);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
  
  	return inode;
  }
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  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
498
499
500
501
502
503
504
505
506
  
  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);
e104f1e9d   Huang Shijie   jffs2: do not sup...
507
508
509
  	/* Do not support the MLC nand */
  	if (c->mtd->type == MTD_MLCNANDFLASH)
  		return -EINVAL;
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
510
  #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	if (c->mtd->type == MTD_NANDFLASH) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
512
513
  		pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  		return -EINVAL;
  	}
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
516
  	if (c->mtd->type == MTD_DATAFLASH) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
517
518
  		pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in
  ");
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
519
520
521
  		return -EINVAL;
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
  
  	c->flash_size = c->mtd->size;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
524
  	c->sector_size = c->mtd->erasesize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  	blocks = c->flash_size / c->sector_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
530
  
  	/*
  	 * Size alignment check
  	 */
  	if ((c->sector_size * blocks) != c->flash_size) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
531
  		c->flash_size = c->sector_size * blocks;
5a528957e   Joe Perches   jffs2: Use pr_fmt...
532
533
  		pr_info("Flash size not aligned to erasesize, reducing to %dKiB
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
  			c->flash_size / 1024);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  	if (c->flash_size < 5*c->sector_size) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
537
538
  		pr_err("Too few erase blocks (%d)
  ",
da320f055   Joe Perches   jffs2: Convert pr...
539
  		       c->flash_size / c->sector_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
  		return -EINVAL;
  	}
  
  	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
546
547
548
  
  	/* NAND (or other bizarre) flash... do setup accordingly */
  	ret = jffs2_flash_setup(c);
  	if (ret)
  		return ret;
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
549
550
  	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
551
552
553
554
  	if (!c->inocache_list) {
  		ret = -ENOMEM;
  		goto out_wbuf;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  	sb->s_maxbytes = 0xFFFFFFFF;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
576
577
  	sb->s_blocksize = PAGE_SIZE;
  	sb->s_blocksize_bits = PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
581
  	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 ...
582
  out_root:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
  	jffs2_free_ino_caches(c);
  	jffs2_free_raw_node_refs(c);
1d5cfdb07   Tetsuo Handa   tree wide: use kv...
585
  	kvfree(c->blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
   out_inohash:
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
587
  	jffs2_clear_xattr_subsystem(c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  	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...
602
  					      int inum, int unlinked)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
  {
  	struct inode *inode;
  	struct jffs2_inode_cache *ic;
1b690b487   David Woodhouse   [JFFS2] Invert la...
606
607
  
  	if (unlinked) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  		/* The inode has zero nlink but its nodes weren't yet marked
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
609
  		   obsolete. This has to be because we're still waiting for
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
  		   the final (close() and) iput() to happen.
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
611
  		   There's a possibility that the final iput() could have
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
615
  		   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 ...
616
  		   The nlink can't _become_ zero at this point because we're
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
621
  		   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...
622
623
624
  			jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.
  ",
  				  inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
628
  
  			spin_lock(&c->inocache_lock);
  			ic = jffs2_get_ino_cache(c, inum);
  			if (!ic) {
9c261b33a   Joe Perches   jffs2: Convert mo...
629
630
631
  				jffs2_dbg(1, "Inode cache for ino #%u is gone
  ",
  					  inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
  				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...
637
638
639
  				jffs2_dbg(1, "Waiting for ino #%u in state %d
  ",
  					  ic->ino, ic->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
643
644
645
646
647
648
649
650
651
  				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 ...
652
653
654
  		inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
  		if (IS_ERR(inode))
  			return ERR_CAST(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
  	}
  	if (is_bad_inode(inode)) {
da320f055   Joe Perches   jffs2: Convert pr...
657
658
659
  		pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d
  ",
  			  inum, unlinked);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
662
663
664
665
666
  		/* 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 ...
667
668
  unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
  				   struct jffs2_inode_info *f,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
673
  				   unsigned long offset,
  				   unsigned long *priv)
  {
  	struct inode *inode = OFNI_EDONI_2SFFJ(f);
  	struct page *pg;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
674
  	pg = read_cache_page(inode->i_mapping, offset >> PAGE_SHIFT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
  			     (void *)jffs2_do_readpage_unlock, inode);
  	if (IS_ERR(pg))
  		return (void *)pg;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
678

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
684
685
686
687
688
689
  	*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);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
690
  	put_page(pg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
  }
  
  static int jffs2_flash_setup(struct jffs2_sb_info *c) {
  	int ret = 0;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
695

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
  	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...
702
703
704
705
706
707
  	/* and Dataflash */
  	if (jffs2_dataflash(c)) {
  		ret = jffs2_dataflash_setup(c);
  		if (ret)
  			return ret;
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
708
709
710
711
712
713
714
  
  	/* 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...
715
716
717
718
719
720
  	/* 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
721
722
723
724
725
726
727
728
  	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...
729
730
731
732
  	/* and DataFlash */
  	if (jffs2_dataflash(c)) {
  		jffs2_dataflash_cleanup(c);
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
733
734
735
736
737
  
  	/* and Intel "Sibley" flash */
  	if (jffs2_nor_wbuf_flash(c)) {
  		jffs2_nor_wbuf_flash_cleanup(c);
  	}
0029da3bf   Artem Bityutskiy   JFFS2: add UBI su...
738
739
740
741
742
  
  	/* and an UBI volume */
  	if (jffs2_ubivol(c)) {
  		jffs2_ubivol_cleanup(c);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
  }