⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xattr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	int rc;	spin_lock(&c->erase_completion_lock);	if (ref_flags(ref->node) != REF_UNCHECKED)		goto complete;	offset = ref_offset(ref->node);	spin_unlock(&c->erase_completion_lock);	rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);	if (rc || sizeof(rr) != readlen) {		JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",			      rc, sizeof(rr), readlen, offset);		return rc ? rc : -EIO;	}	/* obsolete node */	crc = crc32(0, &rr, sizeof(rr) - 4);	if (crc != je32_to_cpu(rr.node_crc)) {		JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",			    offset, je32_to_cpu(rr.node_crc), crc);		return EIO;	}	if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK	    || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF	    || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {		JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "			    "nodetype=%#04x/%#04x, totlen=%u/%zu\n",			    offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,			    je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,			    je32_to_cpu(rr.totlen), PAD(sizeof(rr)));		return EIO;	}	ref->ino = je32_to_cpu(rr.ino);	ref->xid = je32_to_cpu(rr.xid);	ref->xseqno = je32_to_cpu(rr.xseqno);	if (ref->xseqno > c->highest_xseqno)		c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);	spin_lock(&c->erase_completion_lock); complete:	for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {		jeb = &c->blocks[ref_offset(raw) / c->sector_size];		totlen = PAD(ref_totlen(c, jeb, raw));		if (ref_flags(raw) == REF_UNCHECKED) {			c->unchecked_size -= totlen; c->used_size += totlen;			jeb->unchecked_size -= totlen; jeb->used_size += totlen;		}		raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);	}	spin_unlock(&c->erase_completion_lock);	dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",		  ref->ino, ref->xid, ref_offset(ref->node));	return 0;}static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref){	/* must be called under down_write(xattr_sem) */	struct jffs2_raw_xref rr;	size_t length;	uint32_t xseqno, phys_ofs = write_ofs(c);	int ret;	rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);	rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);	rr.totlen = cpu_to_je32(PAD(sizeof(rr)));	rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));	xseqno = (c->highest_xseqno += 2);	if (is_xattr_ref_dead(ref)) {		xseqno |= XREF_DELETE_MARKER;		rr.ino = cpu_to_je32(ref->ino);		rr.xid = cpu_to_je32(ref->xid);	} else {		rr.ino = cpu_to_je32(ref->ic->ino);		rr.xid = cpu_to_je32(ref->xd->xid);	}	rr.xseqno = cpu_to_je32(xseqno);	rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));	ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);	if (ret || sizeof(rr) != length) {		JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",			      ret, sizeof(rr), length, phys_ofs);		ret = ret ? ret : -EIO;		if (length)			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);		return ret;	}	/* success */	ref->xseqno = xseqno;	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);	dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);	return 0;}static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,						struct jffs2_xattr_datum *xd){	/* must be called under down_write(xattr_sem) */	struct jffs2_xattr_ref *ref;	int ret;	ref = jffs2_alloc_xattr_ref();	if (!ref)		return ERR_PTR(-ENOMEM);	ref->ic = ic;	ref->xd = xd;	ret = save_xattr_ref(c, ref);	if (ret) {		jffs2_free_xattr_ref(ref);		return ERR_PTR(ret);	}	/* Chain to inode */	ref->next = ic->xref;	ic->xref = ref;	return ref; /* success */}static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref){	/* must be called under down_write(xattr_sem) */	struct jffs2_xattr_datum *xd;	xd = ref->xd;	ref->xseqno |= XREF_DELETE_MARKER;	ref->ino = ref->ic->ino;	ref->xid = ref->xd->xid;	spin_lock(&c->erase_completion_lock);	ref->next = c->xref_dead_list;	c->xref_dead_list = ref;	spin_unlock(&c->erase_completion_lock);	dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",		  ref->ino, ref->xid, ref->xseqno);	unrefer_xattr_datum(c, xd);}void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic){	/* It's called from jffs2_clear_inode() on inode removing.	   When an inode with XATTR is removed, those XATTRs must be removed. */	struct jffs2_xattr_ref *ref, *_ref;	if (!ic || ic->nlink > 0)		return;	down_write(&c->xattr_sem);	for (ref = ic->xref; ref; ref = _ref) {		_ref = ref->next;		delete_xattr_ref(c, ref);	}	ic->xref = NULL;	up_write(&c->xattr_sem);}void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic){	/* It's called from jffs2_free_ino_caches() until unmounting FS. */	struct jffs2_xattr_datum *xd;	struct jffs2_xattr_ref *ref, *_ref;	down_write(&c->xattr_sem);	for (ref = ic->xref; ref; ref = _ref) {		_ref = ref->next;		xd = ref->xd;		if (atomic_dec_and_test(&xd->refcnt)) {			unload_xattr_datum(c, xd);			jffs2_free_xattr_datum(xd);		}		jffs2_free_xattr_ref(ref);	}	ic->xref = NULL;	up_write(&c->xattr_sem);}static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic){	/* success of check_xattr_ref_inode() means taht inode (ic) dose not have	 * duplicate name/value pairs. If duplicate name/value pair would be found,	 * one will be removed.	 */	struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;	int rc = 0;	if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))		return 0;	down_write(&c->xattr_sem); retry:	rc = 0;	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {		if (!ref->xd->xname) {			rc = load_xattr_datum(c, ref->xd);			if (unlikely(rc > 0)) {				*pref = ref->next;				delete_xattr_ref(c, ref);				goto retry;			} else if (unlikely(rc < 0))				goto out;		}		for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {			if (!cmp->xd->xname) {				ref->xd->flags |= JFFS2_XFLAGS_BIND;				rc = load_xattr_datum(c, cmp->xd);				ref->xd->flags &= ~JFFS2_XFLAGS_BIND;				if (unlikely(rc > 0)) {					*pcmp = cmp->next;					delete_xattr_ref(c, cmp);					goto retry;				} else if (unlikely(rc < 0))					goto out;			}			if (ref->xd->xprefix == cmp->xd->xprefix			    && !strcmp(ref->xd->xname, cmp->xd->xname)) {				if (ref->xseqno > cmp->xseqno) {					*pcmp = cmp->next;					delete_xattr_ref(c, cmp);				} else {					*pref = ref->next;					delete_xattr_ref(c, ref);				}				goto retry;			}		}	}	ic->flags |= INO_FLAGS_XATTR_CHECKED; out:	up_write(&c->xattr_sem);	return rc;}/* -------- xattr subsystem functions --------------- * jffs2_init_xattr_subsystem(c) *   is used to initialize semaphore and list_head, and some variables. * jffs2_find_xattr_datum(c, xid) *   is used to lookup xdatum while scanning process. * jffs2_clear_xattr_subsystem(c) *   is used to release any xattr related objects. * jffs2_build_xattr_subsystem(c) *   is used to associate xdatum and xref while super block building process. * jffs2_setup_xattr_datum(c, xid, version) *   is used to insert xdatum while scanning process. * -------------------------------------------------- */void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c){	int i;	for (i=0; i < XATTRINDEX_HASHSIZE; i++)		INIT_LIST_HEAD(&c->xattrindex[i]);	INIT_LIST_HEAD(&c->xattr_unchecked);	INIT_LIST_HEAD(&c->xattr_dead_list);	c->xref_dead_list = NULL;	c->xref_temp = NULL;	init_rwsem(&c->xattr_sem);	c->highest_xid = 0;	c->highest_xseqno = 0;	c->xdatum_mem_usage = 0;	c->xdatum_mem_threshold = 32 * 1024;	/* Default 32KB */}static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid){	struct jffs2_xattr_datum *xd;	int i = xid % XATTRINDEX_HASHSIZE;	/* It's only used in scanning/building process. */	BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));	list_for_each_entry(xd, &c->xattrindex[i], xindex) {		if (xd->xid==xid)			return xd;	}	return NULL;}void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c){	struct jffs2_xattr_datum *xd, *_xd;	struct jffs2_xattr_ref *ref, *_ref;	int i;	for (ref=c->xref_temp; ref; ref = _ref) {		_ref = ref->next;		jffs2_free_xattr_ref(ref);	}	for (ref=c->xref_dead_list; ref; ref = _ref) {		_ref = ref->next;		jffs2_free_xattr_ref(ref);	}	for (i=0; i < XATTRINDEX_HASHSIZE; i++) {		list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {			list_del(&xd->xindex);			if (xd->xname)				kfree(xd->xname);			jffs2_free_xattr_datum(xd);		}	}	list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {		list_del(&xd->xindex);		jffs2_free_xattr_datum(xd);	}	list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {		list_del(&xd->xindex);		jffs2_free_xattr_datum(xd);	}}#define XREF_TMPHASH_SIZE	(128)void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c){	struct jffs2_xattr_ref *ref, *_ref;	struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];	struct jffs2_xattr_datum *xd, *_xd;	struct jffs2_inode_cache *ic;	struct jffs2_raw_node_ref *raw;	int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;	int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;	BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));	/* Phase.1 : Merge same xref */	for (i=0; i < XREF_TMPHASH_SIZE; i++)		xref_tmphash[i] = NULL;	for (ref=c->xref_temp; ref; ref=_ref) {		struct jffs2_xattr_ref *tmp;		_ref = ref->next;		if (ref_flags(ref->node) != REF_PRISTINE) {			if (verify_xattr_ref(c, ref)) {				BUG_ON(ref->node->next_in_ino != (void *)ref);				ref->node->next_in_ino = NULL;				jffs2_mark_node_obsolete(c, ref->node);				jffs2_free_xattr_ref(ref);				continue;			}		}		i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;		for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {			if (tmp->ino == ref->ino && tmp->xid == ref->xid)				break;		}		if (tmp) {			raw = ref->node;			if (ref->xseqno > tmp->xseqno) {				tmp->xseqno = ref->xseqno;				raw->next_in_ino = tmp->node;				tmp->node = raw;			} else {				raw->next_in_ino = tmp->node->next_in_ino;				tmp->node->next_in_ino = raw;			}			jffs2_free_xattr_ref(ref);			continue;		} else {			ref->next = xref_tmphash[i];			xref_tmphash[i] = ref;		}	}	c->xref_temp = NULL;	/* Phase.2 : Bind xref with inode_cache and xattr_datum */	for (i=0; i < XREF_TMPHASH_SIZE; i++) {		for (ref=xref_tmphash[i]; ref; ref=_ref) {			xref_count++;			_ref = ref->next;			if (is_xattr_ref_dead(ref)) {				ref->next = c->xref_dead_list;				c->xref_dead_list = ref;				xref_dead_count++;				continue;			}			/* At this point, ref->xid and ref->ino contain XID and inode number.			   ref->xd and ref->ic are not valid yet. */			xd = jffs2_find_xattr_datum(c, ref->xid);			ic = jffs2_get_ino_cache(c, ref->ino);			if (!xd || !ic || !ic->nlink) {				dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",					  ref->ino, ref->xid, ref->xseqno);				ref->xseqno |= XREF_DELETE_MARKER;				ref->next = c->xref_dead_list;				c->xref_dead_list = ref;				xref_orphan_count++;				continue;			}			ref->xd = xd;			ref->ic = ic;			atomic_inc(&xd->refcnt);			ref->next = ic->xref;			ic->xref = ref;		}	}	/* Phase.3 : Link unchecked xdatum to xattr_unchecked list */	for (i=0; i < XATTRINDEX_HASHSIZE; i++) {		list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {			xdatum_count++;			list_del_init(&xd->xindex);			if (!atomic_read(&xd->refcnt)) {				dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",					  xd->xid, xd->version);				xd->flags |= JFFS2_XFLAGS_DEAD;				list_add(&xd->xindex, &c->xattr_unchecked);				xdatum_orphan_count++;				continue;			}			if (is_xattr_datum_unchecked(c, xd)) {				dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",					  xd->xid, xd->version);				list_add(&xd->xindex, &c->xattr_unchecked);				xdatum_unchecked_count++;			}		}	}	/* build complete */	JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"		     " (%u unchecked, %u orphan) and "		     "%u of xref (%u dead, %u orphan) found.\n",		     xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,		     xref_count, xref_dead_count, xref_orphan_count);}struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,						  uint32_t xid, uint32_t version){	struct jffs2_xattr_datum *xd;	xd = jffs2_find_xattr_datum(c, xid);	if (!xd) {		xd = jffs2_alloc_xattr_datum();		if (!xd)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -