Blame view

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

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

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

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	inode->i_size = je32_to_cpu(latest_node.isize);
c4592b9c3   Arnd Bergmann   jffs2: use 64-bit...
274
275
276
  	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));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277

bfe868486   Miklos Szeredi   filesystems: add ...
278
  	set_nlink(inode, f->inocache->pino_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

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

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

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

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

ec10a24f1   David Howells   vfs: Convert jffs...
405
  	if (!(fc->sb_flags & SB_RDONLY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  		jffs2_start_garbage_collect_thread(c);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
407

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
431
432
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  
  	f = JFFS2_INODE_INFO(inode);
  	jffs2_init_inode_info(f);
ced220703   David Woodhouse   [JFFS2] semaphore...
433
  	mutex_lock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
  
  	memset(ri, 0, sizeof(*ri));
  	/* Set OS-specific defaults for new inodes */
0cfe53d3c   Eric W. Biederman   userns: Convert j...
437
  	ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  
  	if (dir_i->i_mode & S_ISGID) {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
440
  		ri->gid = cpu_to_je16(i_gid_read(dir_i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
  		if (S_ISDIR(mode))
  			mode |= S_ISGID;
  	} else {
0cfe53d3c   Eric W. Biederman   userns: Convert j...
444
  		ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  	}
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
446
447
448
  
  	/* 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...
449
450
  	ret = jffs2_init_acl_pre(dir_i, inode, &mode);
  	if (ret) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
451
452
453
454
  		mutex_unlock(&f->sem);
  		make_bad_inode(inode);
  		iput(inode);
  		return ERR_PTR(ret);
9ed437c50   David Woodhouse   [JFFS2] Fix ACL v...
455
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  	ret = jffs2_do_new_inode (c, f, mode, ri);
  	if (ret) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
458
  		mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
  		make_bad_inode(inode);
  		iput(inode);
  		return ERR_PTR(ret);
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
463
  	set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
  	inode->i_ino = je32_to_cpu(ri->ino);
  	inode->i_mode = jemode_to_cpu(ri->mode);
0cfe53d3c   Eric W. Biederman   userns: Convert j...
466
467
  	i_gid_write(inode, je16_to_cpu(ri->gid));
  	i_uid_write(inode, je16_to_cpu(ri->uid));
02027d42c   Deepa Dinamani   fs: Replace CURRE...
468
  	inode->i_atime = inode->i_ctime = inode->i_mtime = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
  	inode->i_blocks = 0;
  	inode->i_size = 0;
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
472
  	if (insert_inode_locked(inode) < 0) {
01887a3a2   Wang Guoli   jffs2: unlock f->...
473
  		mutex_unlock(&f->sem);
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
474
  		make_bad_inode(inode);
e72e6497e   David Woodhouse   jffs2: Fix NFS ra...
475
476
477
  		iput(inode);
  		return ERR_PTR(-EINVAL);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
  
  	return inode;
  }
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  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
500

ec10a24f1   David Howells   vfs: Convert jffs...
501
  int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
508
  {
  	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...
509
510
511
  	/* Do not support the MLC nand */
  	if (c->mtd->type == MTD_MLCNANDFLASH)
  		return -EINVAL;
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
512
  #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  	if (c->mtd->type == MTD_NANDFLASH) {
ec10a24f1   David Howells   vfs: Convert jffs...
514
  		errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  		return -EINVAL;
  	}
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
517
  	if (c->mtd->type == MTD_DATAFLASH) {
ec10a24f1   David Howells   vfs: Convert jffs...
518
  		errorf(fc, "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;
ec10a24f1   David Howells   vfs: Convert jffs...
532
533
  		infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB",
  		      c->flash_size / 1024);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  	if (c->flash_size < 5*c->sector_size) {
ec10a24f1   David Howells   vfs: Convert jffs...
536
  		errorf(fc, "Too few erase blocks (%d)",
da320f055   Joe Perches   jffs2: Convert pr...
537
  		       c->flash_size / c->sector_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
540
541
  		return -EINVAL;
  	}
  
  	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
544
545
546
  
  	/* NAND (or other bizarre) flash... do setup accordingly */
  	ret = jffs2_flash_setup(c);
  	if (ret)
  		return ret;
65e5a0e18   Daniel Drake   jffs2: Dynamicall...
547
548
  	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
549
550
551
552
  	if (!c->inocache_list) {
  		ret = -ENOMEM;
  		goto out_wbuf;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  	sb->s_maxbytes = 0xFFFFFFFF;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
574
575
  	sb->s_blocksize = PAGE_SIZE;
  	sb->s_blocksize_bits = PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	sb->s_magic = JFFS2_SUPER_MAGIC;
22b139691   Deepa Dinamani   fs: Fill in max a...
577
578
  	sb->s_time_min = 0;
  	sb->s_time_max = U32_MAX;
bc98a42c1   David Howells   VFS: Convert sb->...
579
  	if (!sb_rdonly(sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  		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);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  static int jffs2_flash_setup(struct jffs2_sb_info *c) {
  	int ret = 0;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
669

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
672
673
674
675
  	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...
676
677
678
679
680
681
  	/* and Dataflash */
  	if (jffs2_dataflash(c)) {
  		ret = jffs2_dataflash_setup(c);
  		if (ret)
  			return ret;
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
682
683
684
685
686
687
688
  
  	/* 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...
689
690
691
692
693
694
  	/* 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
695
696
697
698
699
700
701
702
  	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...
703
704
705
706
  	/* and DataFlash */
  	if (jffs2_dataflash(c)) {
  		jffs2_dataflash_cleanup(c);
  	}
59da721a2   Nicolas Pitre   [JFFS2] Teach JFF...
707
708
709
710
711
  
  	/* and Intel "Sibley" flash */
  	if (jffs2_nor_wbuf_flash(c)) {
  		jffs2_nor_wbuf_flash_cleanup(c);
  	}
0029da3bf   Artem Bityutskiy   JFFS2: add UBI su...
712
713
714
715
716
  
  	/* and an UBI volume */
  	if (jffs2_ubivol(c)) {
  		jffs2_ubivol_cleanup(c);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  }