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
  #include <linux/kernel.h>
  #include <linux/sched.h>
5b825c3af   Ingo Molnar   sched/headers: Pr...
16
  #include <linux/cred.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
  #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...
28
  int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
  {
  	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...
34
  	union jffs2_device_node dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
  	unsigned char *mdata = NULL;
  	int mdatalen = 0;
  	unsigned int ivalid;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
38
  	uint32_t alloclen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  	int ret;
dd919660a   David Woodhouse   [JFFS2] Use ALLOC...
40
  	int alloc_type = ALLOC_NORMAL;
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
41

9c261b33a   Joe Perches   jffs2: Convert mo...
42
43
  	jffs2_dbg(1, "%s(): ino #%lu
  ", __func__, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
  
  	/* 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...
52
  		mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  		mdata = (char *)&dev;
9c261b33a   Joe Perches   jffs2: Convert mo...
54
55
56
  		jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t
  ",
  			  __func__, mdatalen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  	} else if (S_ISLNK(inode->i_mode)) {
ced220703   David Woodhouse   [JFFS2] semaphore...
58
  		mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
  		mdatalen = f->metadata->size;
  		mdata = kmalloc(f->metadata->size, GFP_USER);
422138dd6   Dmitry Bazhenov   [JFFS2] Fix race ...
61
  		if (!mdata) {
ced220703   David Woodhouse   [JFFS2] semaphore...
62
  			mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  			return -ENOMEM;
422138dd6   Dmitry Bazhenov   [JFFS2] Fix race ...
64
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  		ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
  		if (ret) {
ced220703   David Woodhouse   [JFFS2] semaphore...
67
  			mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  			kfree(mdata);
  			return ret;
  		}
ced220703   David Woodhouse   [JFFS2] semaphore...
71
  		mutex_unlock(&f->sem);
9c261b33a   Joe Perches   jffs2: Convert mo...
72
73
74
  		jffs2_dbg(1, "%s(): Writing %d bytes of symlink target
  ",
  			  __func__, mdatalen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
81
82
  	}
  
  	ri = jffs2_alloc_raw_inode();
  	if (!ri) {
  		if (S_ISLNK(inode->i_mode))
  			kfree(mdata);
  		return -ENOMEM;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
83

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
  	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...
102
103
104
105
  	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
106
107
  
  	if (ivalid & ATTR_MODE)
857013b87   David Woodhouse   [JFFS2] Don't str...
108
  		ri->mode = cpu_to_jemode(iattr->ia_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	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...
126
127
128
129
  	} 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
130
131
132
133
134
135
  	}
  	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...
136
  	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  	if (S_ISLNK(inode->i_mode))
  		kfree(mdata);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
139

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
  	if (IS_ERR(new_metadata)) {
  		jffs2_complete_reservation(c);
  		jffs2_free_raw_inode(ri);
ced220703   David Woodhouse   [JFFS2] semaphore...
143
  		mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
  		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...
151
152
  	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
153
154
155
156
157
  
  
  	old_metadata = f->metadata;
  
  	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
f302cd028   Artem B. Bityutskiy   [JFFS2] Namespace...
158
  		jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
  
  	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...
163
  		inode->i_blocks = (inode->i_size + 511) >> 9;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
171
172
  		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...
173
  	mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  	jffs2_complete_reservation(c);
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
175
  	/* We have to do the truncate_setsize() without f->sem held, since
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
176
  	   some pages may be locked and waiting for it in readpage().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
  	   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...
180
  	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
181
  		truncate_setsize(inode, iattr->ia_size);
b28ba9fa0   David Woodhouse   [JFFS2] Set i_blo...
182
183
  		inode->i_blocks = (inode->i_size + 511) >> 9;
  	}	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
  
  	return 0;
  }
  
  int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
  {
2b0143b5c   David Howells   VFS: normal files...
190
  	struct inode *inode = d_inode(dentry);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
191
  	int rc;
31051c85b   Jan Kara   fs: Give dentry t...
192
  	rc = setattr_prepare(dentry, iattr);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
193
194
  	if (rc)
  		return rc;
f2963d455   Christoph Hellwig   jffs2: use generi...
195
  	rc = jffs2_do_setattr(inode, iattr);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
196
  	if (!rc && (iattr->ia_valid & ATTR_MODE))
f2963d455   Christoph Hellwig   jffs2: use generi...
197
  		rc = posix_acl_chmod(inode, inode->i_mode);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
198

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  	switch (inode->i_mode & S_IFMT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
  
  	case S_IFLNK:
  		inode->i_op = &jffs2_symlink_inode_operations;
a8db149fc   Al Viro   jffs2: switch to ...
284
  		inode->i_link = f->target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  		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
  	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
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
bc98a42c1   David Howells   VFS: Convert sb->...
388
  	if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
391
392
393
394
  		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 */
bc98a42c1   David Howells   VFS: Convert sb->...
395
  	if (!sb_rdonly(sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  		jffs2_stop_garbage_collect_thread(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
397
  		mutex_lock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  		jffs2_flush_wbuf_pad(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
399
  		mutex_unlock(&c->alloc_sem);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
400
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
  
  	if (!(*flags & MS_RDONLY))
  		jffs2_start_garbage_collect_thread(c);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
404

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

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

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

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

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

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

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