• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright © 2001-2007 Red Hat, Inc.
5  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
6  *
7  * Created by David Woodhouse <dwmw2@infradead.org>
8  *
9  * For licensing information, see the file 'LICENCE' in this directory.
10  *
11  */
12 
13 #include <linux/delay.h>
14 #include "nodelist.h"
15 #include "os-linux.h"
16 #include "los_crc32.h"
17 #include "jffs2_hash.h"
18 #include "capability_type.h"
19 #include "capability_api.h"
20 
jffs2_setattr(struct jffs2_inode * inode,struct IATTR * attr)21 int jffs2_setattr (struct jffs2_inode *inode, struct IATTR *attr)
22 {
23 	struct jffs2_full_dnode *old_metadata, *new_metadata;
24 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
25 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
26 	struct jffs2_raw_inode *ri;
27 	unsigned int ivalid;
28 	mode_t tmp_mode;
29 	uint c_uid = OsCurrUserGet()->effUserID;
30 	uint c_gid = OsCurrUserGet()->effGid;
31 	uint32_t alloclen;
32 	int ret;
33 	int alloc_type = ALLOC_NORMAL;
34 
35 	jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino);
36 	ri = jffs2_alloc_raw_inode();
37 	if (!ri) {
38 		return -ENOMEM;
39 	}
40 
41 	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
42 
43 	if (ret) {
44 		jffs2_free_raw_inode(ri);
45 		return ret;
46 	}
47 	mutex_lock(&f->sem);
48 	ivalid = attr->attr_chg_valid;
49 	tmp_mode = inode->i_mode;
50 
51 	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
52 	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
53 	ri->totlen = cpu_to_je32(sizeof(*ri));
54 	ri->hdr_crc = cpu_to_je32(crc32(0, ri, (sizeof(struct jffs2_unknown_node)-4)));
55 
56 	ri->ino = cpu_to_je32(inode->i_ino);
57 	ri->version = cpu_to_je32(++f->highest_version);
58 	ri->uid = cpu_to_je16(inode->i_uid);
59 	ri->gid = cpu_to_je16(inode->i_gid);
60 
61 	if (ivalid & CHG_UID) {
62 		if (((c_uid != inode->i_uid) || (attr->attr_chg_uid != inode->i_uid)) && (!IsCapPermit(CAP_CHOWN))) {
63 			jffs2_complete_reservation(c);
64 			jffs2_free_raw_inode(ri);
65 			mutex_unlock(&f->sem);
66 			return -EPERM;
67 		} else {
68 			ri->uid = cpu_to_je16(attr->attr_chg_uid);
69 		}
70 	}
71 
72 	if (ivalid & CHG_GID) {
73 		if (((c_gid != inode->i_gid) || (attr->attr_chg_gid != inode->i_gid)) && (!IsCapPermit(CAP_CHOWN))) {
74 			jffs2_complete_reservation(c);
75 			jffs2_free_raw_inode(ri);
76 			mutex_unlock(&f->sem);
77 			return -EPERM;
78 		} else {
79 			ri->gid = cpu_to_je16(attr->attr_chg_gid);
80 		}
81 	}
82 
83 	if (ivalid & CHG_MODE) {
84 		if (!IsCapPermit(CAP_FOWNER) && (c_uid != inode->i_uid)) {
85 			jffs2_complete_reservation(c);
86 			jffs2_free_raw_inode(ri);
87 			mutex_unlock(&f->sem);
88 			return -EPERM;
89 		} else {
90 			attr->attr_chg_mode  &= ~S_IFMT; // delete file type
91 			tmp_mode &= S_IFMT;
92 			tmp_mode = attr->attr_chg_mode | tmp_mode; // add old file type
93 		}
94 	}
95 
96 	if (ivalid & CHG_ATIME) {
97 		if ((c_uid != inode->i_uid) || (attr->attr_chg_uid != inode->i_uid)) {
98 			return -EPERM;
99 		} else {
100 			ri->atime = cpu_to_je32(attr->attr_chg_atime);
101 		}
102 	} else {
103 		ri->atime = cpu_to_je32(inode->i_atime);
104 	}
105 
106 	if (ivalid & CHG_MTIME) {
107 		if ((c_uid != inode->i_uid) || (attr->attr_chg_uid != inode->i_uid)) {
108 			return -EPERM;
109 		} else {
110 			ri->mtime = cpu_to_je32(attr->attr_chg_mtime);
111 		}
112 	} else {
113 		ri->mtime = cpu_to_je32(Jffs2CurSec());
114 	}
115 	ri->mode = cpu_to_jemode(tmp_mode);
116 
117 	ri->isize = cpu_to_je32((ivalid & CHG_SIZE) ? attr->attr_chg_size : inode->i_size);
118 	ri->ctime = cpu_to_je32(Jffs2CurSec());
119 
120 	ri->offset = cpu_to_je32(0);
121 	ri->csize = ri->dsize = cpu_to_je32(0);
122 	ri->compr = JFFS2_COMPR_NONE;
123 	if (ivalid & CHG_SIZE && inode->i_size < attr->attr_chg_size) {
124 		/* It's an extension. Make it a hole node */
125 		ri->compr = JFFS2_COMPR_ZERO;
126 		ri->dsize = cpu_to_je32(attr->attr_chg_size - inode->i_size);
127 		ri->offset = cpu_to_je32(inode->i_size);
128 	} else if (ivalid & CHG_SIZE && !attr->attr_chg_size) {
129 		/* For truncate-to-zero, treat it as deletion because
130 		   it'll always be obsoleting all previous nodes */
131 		alloc_type = ALLOC_DELETION;
132 	}
133 	ri->node_crc = cpu_to_je32(crc32(0, ri, (sizeof(*ri)-8)));
134 	ri->data_crc = cpu_to_je32(0);
135 	new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, alloc_type);
136 	if (IS_ERR(new_metadata)) {
137 		jffs2_complete_reservation(c);
138 		jffs2_free_raw_inode(ri);
139 		mutex_unlock(&f->sem);
140 		return PTR_ERR(new_metadata);
141 	}
142 	/* It worked. Update the inode */
143 	inode->i_atime = je32_to_cpu(ri->atime);
144 	inode->i_ctime = je32_to_cpu(ri->ctime);
145 	inode->i_mtime = je32_to_cpu(ri->mtime);
146 	inode->i_mode = jemode_to_cpu(ri->mode);
147 	inode->i_uid = je16_to_cpu(ri->uid);
148 	inode->i_gid = je16_to_cpu(ri->gid);
149 
150 	old_metadata = f->metadata;
151 	if (ivalid & CHG_SIZE && inode->i_size > attr->attr_chg_size)
152 		jffs2_truncate_fragtree (c, &f->fragtree, attr->attr_chg_size);
153 
154 	if (ivalid & CHG_SIZE && inode->i_size < attr->attr_chg_size) {
155 		jffs2_add_full_dnode_to_inode(c, f, new_metadata);
156 		inode->i_size = attr->attr_chg_size;
157 		f->metadata = NULL;
158 	} else {
159 		f->metadata = new_metadata;
160 	}
161 	if (old_metadata) {
162 		jffs2_mark_node_obsolete(c, old_metadata->raw);
163 		jffs2_free_full_dnode(old_metadata);
164 	}
165 	jffs2_free_raw_inode(ri);
166 
167 	mutex_unlock(&f->sem);
168 	jffs2_complete_reservation(c);
169 
170 	/* We have to do the truncate_setsize() without f->sem held, since
171 	   some pages may be locked and waiting for it in readpage().
172 	   We are protected from a simultaneous write() extending i_size
173 	   back past iattr->ia_size, because do_truncate() holds the
174 	   generic inode semaphore. */
175 	if (ivalid & CHG_SIZE && inode->i_size > attr->attr_chg_size) {
176 		inode->i_size = attr->attr_chg_size; // truncate_setsize
177 	}
178 
179 	return 0;
180 }
181 
jffs2_clear_inode(struct jffs2_inode * inode)182 static void jffs2_clear_inode (struct jffs2_inode *inode)
183 {
184 	/* We can forget about this inode for now - drop all
185 	 *  the nodelists associated with it, etc.
186 	 */
187 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
188 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
189 
190 	jffs2_do_clear_inode(c, f);
191 }
192 
ilookup(struct super_block * sb,uint32_t ino)193 static struct jffs2_inode *ilookup(struct super_block *sb, uint32_t ino)
194 {
195 	struct jffs2_inode *node = NULL;
196 
197 	if (sb->s_root == NULL) {
198 		return NULL;
199 	}
200 
201 	// Check for this inode in the cache
202 	Jffs2NodeLock();
203 	(void)Jffs2HashGet(&sb->s_node_hash_lock, &sb->s_node_hash[0], sb, ino, &node);
204 	Jffs2NodeUnlock();
205 	return node;
206 }
207 
new_inode(struct super_block * sb)208 struct jffs2_inode *new_inode(struct super_block *sb)
209 {
210 	struct jffs2_inode *inode = NULL;
211 
212 	inode = zalloc(sizeof (struct jffs2_inode));
213 	if (inode == NULL)
214 		return 0;
215 
216 	D2(PRINTK("malloc new_inode %x ####################################\n",
217 		inode));
218 
219 	inode->i_sb = sb;
220 	inode->i_ino = 1;
221 	inode->i_nlink = 1;    // Let JFFS2 manage the link count
222 	inode->i_size = 0;
223 	LOS_ListInit((&(inode->i_hashlist)));
224 
225 	return inode;
226 }
227 
jffs2_iget(struct super_block * sb,uint32_t ino)228 struct jffs2_inode *jffs2_iget(struct super_block *sb, uint32_t ino)
229 {
230 	struct jffs2_inode_info *f;
231 	struct jffs2_sb_info *c;
232 	struct jffs2_raw_inode latest_node;
233 	struct jffs2_inode *inode;
234 	int ret;
235 
236 	Jffs2NodeLock();
237 	inode = ilookup(sb, ino);
238 	if (inode) {
239 		Jffs2NodeUnlock();
240 		return inode;
241 	}
242 	inode = new_inode(sb);
243 	if (inode == NULL) {
244 		Jffs2NodeUnlock();
245 		return (struct jffs2_inode *)-ENOMEM;
246 	}
247 
248 	inode->i_ino = ino;
249 	f = JFFS2_INODE_INFO(inode);
250 	c = JFFS2_SB_INFO(inode->i_sb);
251 
252 	(void)mutex_init(&f->sem);
253 	(void)mutex_lock(&f->sem);
254 
255 	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
256 	if (ret) {
257 		(void)mutex_unlock(&f->sem);
258         inode->i_nlink = 0;
259         free(inode);
260 		Jffs2NodeUnlock();
261 		return (struct jffs2_inode *)ret;
262 	}
263 
264 	inode->i_mode = jemode_to_cpu(latest_node.mode);
265 	inode->i_uid = je16_to_cpu(latest_node.uid);
266 	inode->i_gid = je16_to_cpu(latest_node.gid);
267 	inode->i_size = je32_to_cpu(latest_node.isize);
268 	inode->i_atime = je32_to_cpu(latest_node.atime);
269 	inode->i_mtime = je32_to_cpu(latest_node.mtime);
270 	inode->i_ctime = je32_to_cpu(latest_node.ctime);
271 	inode->i_nlink = f->inocache->pino_nlink;
272 
273 	(void)mutex_unlock(&f->sem);
274 
275 	(void)Jffs2HashInsert(&sb->s_node_hash_lock, &sb->s_node_hash[0], inode, ino);
276 
277 	jffs2_dbg(1, "jffs2_read_inode() returning\n");
278 	Jffs2NodeUnlock();
279 
280 	return inode;
281 }
282 
283 
284 // -------------------------------------------------------------------------
285 // Decrement the reference count on an inode. If this makes the ref count
286 // zero, then this inode can be freed.
287 
jffs2_iput(struct jffs2_inode * i)288 int jffs2_iput(struct jffs2_inode *i)
289 {
290 	// Called in jffs2_find
291 	// (and jffs2_open and jffs2_ops_mkdir?)
292 	// super.c jffs2_fill_super,
293 	// and gc.c jffs2_garbage_collect_pass
294 	struct jffs2_inode_info *f = NULL;
295 
296 	Jffs2NodeLock();
297 	if (!i || i->i_nlink) {
298 		// and let it fault...
299 		Jffs2NodeUnlock();
300 		return -EBUSY;
301 	}
302 
303 	jffs2_clear_inode(i);
304 	f = JFFS2_INODE_INFO(i);
305 	(void)mutex_destroy(&(f->sem));
306 	(void)Jffs2HashRemove(&i->i_sb->s_node_hash_lock, i);
307 	(void)memset_s(i, sizeof(*i), 0x5a, sizeof(*i));
308 	free(i);
309 	Jffs2NodeUnlock();
310 
311 	return 0;
312 }
313 
314 
315 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
316    fill in the raw_inode while you're at it. */
jffs2_new_inode(struct jffs2_inode * dir_i,int mode,struct jffs2_raw_inode * ri)317 struct jffs2_inode *jffs2_new_inode (struct jffs2_inode *dir_i, int mode, struct jffs2_raw_inode *ri)
318 {
319 	struct jffs2_inode *inode;
320 	struct super_block *sb = dir_i->i_sb;
321 	struct jffs2_sb_info *c;
322 	struct jffs2_inode_info *f;
323 	int ret;
324 
325 	c = JFFS2_SB_INFO(sb);
326 
327 	Jffs2NodeLock();
328 	inode = new_inode(sb);
329 
330 	if (!inode)
331 		return (struct jffs2_inode *)-ENOMEM;
332 
333 	f = JFFS2_INODE_INFO(inode);
334 	(void)mutex_init(&f->sem);
335 	(void)mutex_lock(&f->sem);;
336 
337 	memset(ri, 0, sizeof(*ri));
338 	/* Set OS-specific defaults for new inodes */
339 	ri->uid = cpu_to_je16(OsCurrUserGet()->effUserID);
340 	ri->gid = cpu_to_je16(OsCurrUserGet()->effGid);
341 
342 	ret = jffs2_do_new_inode (c, f, mode, ri);
343 	if (ret) {
344 		mutex_unlock(&(f->sem));
345 		jffs2_clear_inode(inode);
346 		(void)mutex_destroy(&(f->sem));
347 		(void)memset_s(inode, sizeof(*inode), 0x6a, sizeof(*inode));
348 		free(inode);
349 		Jffs2NodeUnlock();
350 		return (struct jffs2_inode *)ret;
351 
352 	}
353 	inode->i_nlink = 1;
354 	inode->i_ino = je32_to_cpu(ri->ino);
355 	inode->i_mode = jemode_to_cpu(ri->mode);
356 	inode->i_gid = je16_to_cpu(ri->gid);
357 	inode->i_uid = je16_to_cpu(ri->uid);
358 	inode->i_atime = inode->i_ctime = inode->i_mtime = Jffs2CurSec();
359 	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
360 
361 	inode->i_size = 0;
362 
363 	(void)Jffs2HashInsert(&sb->s_node_hash_lock, &sb->s_node_hash[0], inode, inode->i_ino);
364 	Jffs2NodeUnlock();
365 
366 	return inode;
367 }
368 
calculate_inocache_hashsize(uint32_t flash_size)369 int calculate_inocache_hashsize(uint32_t flash_size)
370 {
371 	/*
372 	 * Pick a inocache hash size based on the size of the medium.
373 	 * Count how many megabytes we're dealing with, apply a hashsize twice
374 	 * that size, but rounding down to the usual big powers of 2. And keep
375 	 * to sensible bounds.
376 	 */
377 
378 	int size_mb = flash_size / 1024 / 1024;
379 	int hashsize = (size_mb * 2) & ~0x3f;
380 
381 	if (hashsize < INOCACHE_HASHSIZE_MIN)
382 		return INOCACHE_HASHSIZE_MIN;
383 	if (hashsize > INOCACHE_HASHSIZE_MAX)
384 		return INOCACHE_HASHSIZE_MAX;
385 
386 	return hashsize;
387 }
388 
jffs2_gc_release_inode(struct jffs2_sb_info * c,struct jffs2_inode_info * f)389 void jffs2_gc_release_inode(struct jffs2_sb_info *c,
390 		   	    struct jffs2_inode_info *f)
391 {
392 	struct jffs2_inode *node = OFNI_EDONI_2SFFJ(f);
393 	jffs2_iput(node);
394 }
395 
jffs2_gc_fetch_inode(struct jffs2_sb_info * c,int inum,int unlinked)396 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
397 					      int inum, int unlinked)
398 {
399 	struct jffs2_inode *inode;
400 	struct jffs2_inode_cache *ic;
401 
402 	if (unlinked) {
403 		/* The inode has zero nlink but its nodes weren't yet marked
404 		   obsolete. This has to be because we're still waiting for
405 		   the final (close() and) iput() to happen.
406 
407 		   There's a possibility that the final iput() could have
408 		   happened while we were contemplating. In order to ensure
409 		   that we don't cause a new read_inode() (which would fail)
410 		   for the inode in question, we use ilookup() in this case
411 		   instead of iget().
412 
413 		   The nlink can't _become_ zero at this point because we're
414 		   holding the alloc_sem, and jffs2_do_unlink() would also
415 		   need that while decrementing nlink on any inode.
416 		*/
417 		inode = ilookup(OFNI_BS_2SFFJ(c), inum);
418 		if (!inode) {
419 			jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
420 				  inum);
421 
422 			spin_lock(&c->inocache_lock);
423 			ic = jffs2_get_ino_cache(c, inum);
424 			if (!ic) {
425 				jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
426 					  inum);
427 				spin_unlock(&c->inocache_lock);
428 				return NULL;
429 			}
430 			if (ic->state != INO_STATE_CHECKEDABSENT) {
431 				/* Wait for progress. Don't just loop */
432 				jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
433 					  ic->ino, ic->state);
434 				sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
435 			} else {
436 				spin_unlock(&c->inocache_lock);
437 			}
438 
439 			return NULL;
440 		}
441 	} else {
442 		/* Inode has links to it still; they're not going away because
443 		   jffs2_do_unlink() would need the alloc_sem and we have it.
444 		   Just iget() it, and if read_inode() is necessary that's OK.
445 		*/
446 		inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
447 		if (inode <= 0)
448 			return (struct jffs2_inode_info *)inode;
449 	}
450 
451 	return JFFS2_INODE_INFO(inode);
452 }
453