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

📄 xattr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return ERR_PTR(-ENOMEM);		xd->xid = xid;		xd->version = version;		if (xd->xid > c->highest_xid)			c->highest_xid = xd->xid;		list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);	}	return xd;}/* -------- xattr subsystem functions --------------- * xprefix_to_handler(xprefix) *   is used to translate xprefix into xattr_handler. * jffs2_listxattr(dentry, buffer, size) *   is an implementation of listxattr handler on jffs2. * do_jffs2_getxattr(inode, xprefix, xname, buffer, size) *   is an implementation of getxattr handler on jffs2. * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags) *   is an implementation of setxattr handler on jffs2. * -------------------------------------------------- */struct xattr_handler *jffs2_xattr_handlers[] = {	&jffs2_user_xattr_handler,#ifdef CONFIG_JFFS2_FS_SECURITY	&jffs2_security_xattr_handler,#endif#ifdef CONFIG_JFFS2_FS_POSIX_ACL	&jffs2_acl_access_xattr_handler,	&jffs2_acl_default_xattr_handler,#endif	&jffs2_trusted_xattr_handler,	NULL};static struct xattr_handler *xprefix_to_handler(int xprefix) {	struct xattr_handler *ret;	switch (xprefix) {	case JFFS2_XPREFIX_USER:		ret = &jffs2_user_xattr_handler;		break;#ifdef CONFIG_JFFS2_FS_SECURITY	case JFFS2_XPREFIX_SECURITY:		ret = &jffs2_security_xattr_handler;		break;#endif#ifdef CONFIG_JFFS2_FS_POSIX_ACL	case JFFS2_XPREFIX_ACL_ACCESS:		ret = &jffs2_acl_access_xattr_handler;		break;	case JFFS2_XPREFIX_ACL_DEFAULT:		ret = &jffs2_acl_default_xattr_handler;		break;#endif	case JFFS2_XPREFIX_TRUSTED:		ret = &jffs2_trusted_xattr_handler;		break;	default:		ret = NULL;		break;	}	return ret;}ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size){	struct inode *inode = dentry->d_inode;	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);	struct jffs2_inode_cache *ic = f->inocache;	struct jffs2_xattr_ref *ref, **pref;	struct jffs2_xattr_datum *xd;	struct xattr_handler *xhandle;	ssize_t len, rc;	int retry = 0;	rc = check_xattr_ref_inode(c, ic);	if (unlikely(rc))		return rc;	down_read(&c->xattr_sem); retry:	len = 0;	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {		BUG_ON(ref->ic != ic);		xd = ref->xd;		if (!xd->xname) {			/* xdatum is unchached */			if (!retry) {				retry = 1;				up_read(&c->xattr_sem);				down_write(&c->xattr_sem);				goto retry;			} else {				rc = load_xattr_datum(c, xd);				if (unlikely(rc > 0)) {					*pref = ref->next;					delete_xattr_ref(c, ref);					goto retry;				} else if (unlikely(rc < 0))					goto out;			}		}		xhandle = xprefix_to_handler(xd->xprefix);		if (!xhandle)			continue;		if (buffer) {			rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);		} else {			rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);		}		if (rc < 0)			goto out;		len += rc;	}	rc = len; out:	if (!retry) {		up_read(&c->xattr_sem);	} else {		up_write(&c->xattr_sem);	}	return rc;}int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,		      char *buffer, size_t size){	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);	struct jffs2_inode_cache *ic = f->inocache;	struct jffs2_xattr_datum *xd;	struct jffs2_xattr_ref *ref, **pref;	int rc, retry = 0;	rc = check_xattr_ref_inode(c, ic);	if (unlikely(rc))		return rc;	down_read(&c->xattr_sem); retry:	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {		BUG_ON(ref->ic!=ic);		xd = ref->xd;		if (xd->xprefix != xprefix)			continue;		if (!xd->xname) {			/* xdatum is unchached */			if (!retry) {				retry = 1;				up_read(&c->xattr_sem);				down_write(&c->xattr_sem);				goto retry;			} else {				rc = load_xattr_datum(c, xd);				if (unlikely(rc > 0)) {					*pref = ref->next;					delete_xattr_ref(c, ref);					goto retry;				} else if (unlikely(rc < 0)) {					goto out;				}			}		}		if (!strcmp(xname, xd->xname)) {			rc = xd->value_len;			if (buffer) {				if (size < rc) {					rc = -ERANGE;				} else {					memcpy(buffer, xd->xvalue, rc);				}			}			goto out;		}	}	rc = -ENODATA; out:	if (!retry) {		up_read(&c->xattr_sem);	} else {		up_write(&c->xattr_sem);	}	return rc;}int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,		      const char *buffer, size_t size, int flags){	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);	struct jffs2_inode_cache *ic = f->inocache;	struct jffs2_xattr_datum *xd;	struct jffs2_xattr_ref *ref, *newref, **pref;	uint32_t length, request;	int rc;	rc = check_xattr_ref_inode(c, ic);	if (unlikely(rc))		return rc;	request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);	rc = jffs2_reserve_space(c, request, &length,				 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);	if (rc) {		JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);		return rc;	}	/* Find existing xattr */	down_write(&c->xattr_sem); retry:	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {		xd = ref->xd;		if (xd->xprefix != xprefix)			continue;		if (!xd->xname) {			rc = load_xattr_datum(c, xd);			if (unlikely(rc > 0)) {				*pref = ref->next;				delete_xattr_ref(c, ref);				goto retry;			} else if (unlikely(rc < 0))				goto out;		}		if (!strcmp(xd->xname, xname)) {			if (flags & XATTR_CREATE) {				rc = -EEXIST;				goto out;			}			if (!buffer) {				ref->ino = ic->ino;				ref->xid = xd->xid;				ref->xseqno |= XREF_DELETE_MARKER;				rc = save_xattr_ref(c, ref);				if (!rc) {					*pref = ref->next;					spin_lock(&c->erase_completion_lock);					ref->next = c->xref_dead_list;					c->xref_dead_list = ref;					spin_unlock(&c->erase_completion_lock);					unrefer_xattr_datum(c, xd);				} else {					ref->ic = ic;					ref->xd = xd;					ref->xseqno &= ~XREF_DELETE_MARKER;				}				goto out;			}			goto found;		}	}	/* not found */	if (flags & XATTR_REPLACE) {		rc = -ENODATA;		goto out;	}	if (!buffer) {		rc = -ENODATA;		goto out;	} found:	xd = create_xattr_datum(c, xprefix, xname, buffer, size);	if (IS_ERR(xd)) {		rc = PTR_ERR(xd);		goto out;	}	up_write(&c->xattr_sem);	jffs2_complete_reservation(c);	/* create xattr_ref */	request = PAD(sizeof(struct jffs2_raw_xref));	rc = jffs2_reserve_space(c, request, &length,				 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);	down_write(&c->xattr_sem);	if (rc) {		JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);		unrefer_xattr_datum(c, xd);		up_write(&c->xattr_sem);		return rc;	}	if (ref)		*pref = ref->next;	newref = create_xattr_ref(c, ic, xd);	if (IS_ERR(newref)) {		if (ref) {			ref->next = ic->xref;			ic->xref = ref;		}		rc = PTR_ERR(newref);		unrefer_xattr_datum(c, xd);	} else if (ref) {		delete_xattr_ref(c, ref);	} out:	up_write(&c->xattr_sem);	jffs2_complete_reservation(c);	return rc;}/* -------- garbage collector functions ------------- * jffs2_garbage_collect_xattr_datum(c, xd, raw) *   is used to move xdatum into new node. * jffs2_garbage_collect_xattr_ref(c, ref, raw) *   is used to move xref into new node. * jffs2_verify_xattr(c) *   is used to call do_verify_xattr_datum() before garbage collecting. * jffs2_release_xattr_datum(c, xd) *   is used to release an in-memory object of xdatum. * jffs2_release_xattr_ref(c, ref) *   is used to release an in-memory object of xref. * -------------------------------------------------- */int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,				      struct jffs2_raw_node_ref *raw){	uint32_t totlen, length, old_ofs;	int rc = 0;	down_write(&c->xattr_sem);	if (xd->node != raw)		goto out;	if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))		goto out;	rc = load_xattr_datum(c, xd);	if (unlikely(rc)) {		rc = (rc > 0) ? 0 : rc;		goto out;	}	old_ofs = ref_offset(xd->node);	totlen = PAD(sizeof(struct jffs2_raw_xattr)			+ xd->name_len + 1 + xd->value_len);	rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);	if (rc) {		JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);		goto out;	}	rc = save_xattr_datum(c, xd);	if (!rc)		dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",			  xd->xid, xd->version, old_ofs, ref_offset(xd->node)); out:	if (!rc)		jffs2_mark_node_obsolete(c, raw);	up_write(&c->xattr_sem);	return rc;}int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,				    struct jffs2_raw_node_ref *raw){	uint32_t totlen, length, old_ofs;	int rc = 0;	down_write(&c->xattr_sem);	BUG_ON(!ref->node);	if (ref->node != raw)		goto out;	if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))		goto out;	old_ofs = ref_offset(ref->node);	totlen = ref_totlen(c, c->gcblock, ref->node);	rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);	if (rc) {		JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",			      __FUNCTION__, rc, totlen);		rc = rc ? rc : -EBADFD;		goto out;	}	rc = save_xattr_ref(c, ref);	if (!rc)		dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",			  ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); out:	if (!rc)		jffs2_mark_node_obsolete(c, raw);	up_write(&c->xattr_sem);	return rc;}int jffs2_verify_xattr(struct jffs2_sb_info *c){	struct jffs2_xattr_datum *xd, *_xd;	struct jffs2_eraseblock *jeb;	struct jffs2_raw_node_ref *raw;	uint32_t totlen;	int rc;	down_write(&c->xattr_sem);	list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {		rc = do_verify_xattr_datum(c, xd);		if (rc < 0)			continue;		list_del_init(&xd->xindex);		spin_lock(&c->erase_completion_lock);		for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {			if (ref_flags(raw) != REF_UNCHECKED)				continue;			jeb = &c->blocks[ref_offset(raw) / c->sector_size];			totlen = PAD(ref_totlen(c, jeb, raw));			c->unchecked_size -= totlen; c->used_size += totlen;			jeb->unchecked_size -= totlen; jeb->used_size += totlen;			raw->flash_offset = ref_offset(raw)				| ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);		}		if (xd->flags & JFFS2_XFLAGS_DEAD)			list_add(&xd->xindex, &c->xattr_dead_list);		spin_unlock(&c->erase_completion_lock);	}	up_write(&c->xattr_sem);	return list_empty(&c->xattr_unchecked) ? 1 : 0;}void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd){	/* must be called under spin_lock(&c->erase_completion_lock) */	if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)		return;	list_del(&xd->xindex);	jffs2_free_xattr_datum(xd);}void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref){	/* must be called under spin_lock(&c->erase_completion_lock) */	struct jffs2_xattr_ref *tmp, **ptmp;	if (ref->node != (void *)ref)		return;	for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {		if (ref == tmp) {			*ptmp = tmp->next;			break;		}	}	jffs2_free_xattr_ref(ref);}

⌨️ 快捷键说明

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