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

📄 xfs_attr_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
xfs_attr_shortform_getvalue(xfs_da_args_t *args){	xfs_attr_shortform_t *sf;	xfs_attr_sf_entry_t *sfe;	int i;	ASSERT(args->dp->i_d.di_aformat == XFS_IFINLINE);	sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data;	sfe = &sf->list[0];	for (i = 0; i < sf->hdr.count;				sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {		if (sfe->namelen != args->namelen)			continue;		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)			continue;		if (!xfs_attr_namesp_match(args->flags, sfe->flags))			continue;		if (args->flags & ATTR_KERNOVAL) {			args->valuelen = sfe->valuelen;			return(XFS_ERROR(EEXIST));		}		if (args->valuelen < sfe->valuelen) {			args->valuelen = sfe->valuelen;			return(XFS_ERROR(ERANGE));		}		args->valuelen = sfe->valuelen;		memcpy(args->value, &sfe->nameval[args->namelen],						    args->valuelen);		return(XFS_ERROR(EEXIST));	}	return(XFS_ERROR(ENOATTR));}/* * Convert from using the shortform to the leaf. */intxfs_attr_shortform_to_leaf(xfs_da_args_t *args){	xfs_inode_t *dp;	xfs_attr_shortform_t *sf;	xfs_attr_sf_entry_t *sfe;	xfs_da_args_t nargs;	char *tmpbuffer;	int error, i, size;	xfs_dablk_t blkno;	xfs_dabuf_t *bp;	xfs_ifork_t *ifp;	dp = args->dp;	ifp = dp->i_afp;	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;	size = be16_to_cpu(sf->hdr.totsize);	tmpbuffer = kmem_alloc(size, KM_SLEEP);	ASSERT(tmpbuffer != NULL);	memcpy(tmpbuffer, ifp->if_u1.if_data, size);	sf = (xfs_attr_shortform_t *)tmpbuffer;	xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);	bp = NULL;	error = xfs_da_grow_inode(args, &blkno);	if (error) {		/*		 * If we hit an IO error middle of the transaction inside		 * grow_inode(), we may have inconsistent data. Bail out.		 */		if (error == EIO)			goto out;		xfs_idata_realloc(dp, size, XFS_ATTR_FORK);	/* try to put */		memcpy(ifp->if_u1.if_data, tmpbuffer, size);	/* it back */		goto out;	}	ASSERT(blkno == 0);	error = xfs_attr_leaf_create(args, blkno, &bp);	if (error) {		error = xfs_da_shrink_inode(args, 0, bp);		bp = NULL;		if (error)			goto out;		xfs_idata_realloc(dp, size, XFS_ATTR_FORK);	/* try to put */		memcpy(ifp->if_u1.if_data, tmpbuffer, size);	/* it back */		goto out;	}	memset((char *)&nargs, 0, sizeof(nargs));	nargs.dp = dp;	nargs.firstblock = args->firstblock;	nargs.flist = args->flist;	nargs.total = args->total;	nargs.whichfork = XFS_ATTR_FORK;	nargs.trans = args->trans;	nargs.oknoent = 1;	sfe = &sf->list[0];	for (i = 0; i < sf->hdr.count; i++) {		nargs.name = (char *)sfe->nameval;		nargs.namelen = sfe->namelen;		nargs.value = (char *)&sfe->nameval[nargs.namelen];		nargs.valuelen = sfe->valuelen;		nargs.hashval = xfs_da_hashname((char *)sfe->nameval,						sfe->namelen);		nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags);		error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */		ASSERT(error == ENOATTR);		error = xfs_attr_leaf_add(bp, &nargs);		ASSERT(error != ENOSPC);		if (error)			goto out;		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);	}	error = 0;out:	if(bp)		xfs_da_buf_done(bp);	kmem_free(tmpbuffer, size);	return(error);}STATIC intxfs_attr_shortform_compare(const void *a, const void *b){	xfs_attr_sf_sort_t *sa, *sb;	sa = (xfs_attr_sf_sort_t *)a;	sb = (xfs_attr_sf_sort_t *)b;	if (sa->hash < sb->hash) {		return(-1);	} else if (sa->hash > sb->hash) {		return(1);	} else {		return(sa->entno - sb->entno);	}}#define XFS_ISRESET_CURSOR(cursor) \	(!((cursor)->initted) && !((cursor)->hashval) && \	 !((cursor)->blkno) && !((cursor)->offset))/* * Copy out entries of shortform attribute lists for attr_list(). * Shortform attribute lists are not stored in hashval sorted order. * If the output buffer is not large enough to hold them all, then we * we have to calculate each entries' hashvalue and sort them before * we can begin returning them to the user. *//*ARGSUSED*/intxfs_attr_shortform_list(xfs_attr_list_context_t *context){	attrlist_cursor_kern_t *cursor;	xfs_attr_sf_sort_t *sbuf, *sbp;	xfs_attr_shortform_t *sf;	xfs_attr_sf_entry_t *sfe;	xfs_inode_t *dp;	int sbsize, nsbuf, count, i;	int error;	ASSERT(context != NULL);	dp = context->dp;	ASSERT(dp != NULL);	ASSERT(dp->i_afp != NULL);	sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;	ASSERT(sf != NULL);	if (!sf->hdr.count)		return(0);	cursor = context->cursor;	ASSERT(cursor != NULL);	xfs_attr_trace_l_c("sf start", context);	/*	 * If the buffer is large enough and the cursor is at the start,	 * do not bother with sorting since we will return everything in	 * one buffer and another call using the cursor won't need to be	 * made.	 * Note the generous fudge factor of 16 overhead bytes per entry.	 * If bufsize is zero then put_listent must be a search function	 * and can just scan through what we have.	 */	if (context->bufsize == 0 ||	    (XFS_ISRESET_CURSOR(cursor) &&             (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {		for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {			attrnames_t	*namesp;			if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);				continue;			}			namesp = xfs_attr_flags_namesp(sfe->flags);			error = context->put_listent(context,					   namesp,					   (char *)sfe->nameval,					   (int)sfe->namelen,					   (int)sfe->valuelen,					   (char*)&sfe->nameval[sfe->namelen]);			/*			 * Either search callback finished early or			 * didn't fit it all in the buffer after all.			 */			if (context->seen_enough)				break;			if (error)				return error;			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);		}		xfs_attr_trace_l_c("sf big-gulp", context);		return(0);	}	/* do no more for a search callback */	if (context->bufsize == 0)		return 0;	/*	 * It didn't all fit, so we have to sort everything on hashval.	 */	sbsize = sf->hdr.count * sizeof(*sbuf);	sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);	/*	 * Scan the attribute list for the rest of the entries, storing	 * the relevant info from only those that match into a buffer.	 */	nsbuf = 0;	for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {		if (unlikely(		    ((char *)sfe < (char *)sf) ||		    ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {			XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",					     XFS_ERRLEVEL_LOW,					     context->dp->i_mount, sfe);			xfs_attr_trace_l_c("sf corrupted", context);			kmem_free(sbuf, sbsize);			return XFS_ERROR(EFSCORRUPTED);		}		if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);			continue;		}		sbp->entno = i;		sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen);		sbp->name = (char *)sfe->nameval;		sbp->namelen = sfe->namelen;		/* These are bytes, and both on-disk, don't endian-flip */		sbp->valuelen = sfe->valuelen;		sbp->flags = sfe->flags;		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);		sbp++;		nsbuf++;	}	/*	 * Sort the entries on hash then entno.	 */	xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);	/*	 * Re-find our place IN THE SORTED LIST.	 */	count = 0;	cursor->initted = 1;	cursor->blkno = 0;	for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {		if (sbp->hash == cursor->hashval) {			if (cursor->offset == count) {				break;			}			count++;		} else if (sbp->hash > cursor->hashval) {			break;		}	}	if (i == nsbuf) {		kmem_free(sbuf, sbsize);		xfs_attr_trace_l_c("blk end", context);		return(0);	}	/*	 * Loop putting entries into the user buffer.	 */	for ( ; i < nsbuf; i++, sbp++) {		attrnames_t	*namesp;		namesp = xfs_attr_flags_namesp(sbp->flags);		if (cursor->hashval != sbp->hash) {			cursor->hashval = sbp->hash;			cursor->offset = 0;		}		error = context->put_listent(context,					namesp,					sbp->name,					sbp->namelen,					sbp->valuelen,					&sbp->name[sbp->namelen]);		if (error)			return error;		if (context->seen_enough)			break;		cursor->offset++;	}	kmem_free(sbuf, sbsize);	xfs_attr_trace_l_c("sf E-O-F", context);	return(0);}/* * Check a leaf attribute block to see if all the entries would fit into * a shortform attribute list. */intxfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_entry_t *entry;	xfs_attr_leaf_name_local_t *name_loc;	int bytes, i;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	entry = &leaf->entries[0];	bytes = sizeof(struct xfs_attr_sf_hdr);	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {		if (entry->flags & XFS_ATTR_INCOMPLETE)			continue;		/* don't copy partial entries */		if (!(entry->flags & XFS_ATTR_LOCAL))			return(0);		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);		if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX)			return(0);		if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX)			return(0);		bytes += sizeof(struct xfs_attr_sf_entry)-1				+ name_loc->namelen				+ be16_to_cpu(name_loc->valuelen);	}	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&	    (bytes == sizeof(struct xfs_attr_sf_hdr)))		return(-1);	return(xfs_attr_shortform_bytesfit(dp, bytes));}/* * Convert a leaf attribute list to shortform attribute list */intxfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_entry_t *entry;	xfs_attr_leaf_name_local_t *name_loc;	xfs_da_args_t nargs;	xfs_inode_t *dp;	char *tmpbuffer;	int error, i;	dp = args->dp;	tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);	ASSERT(tmpbuffer != NULL);	ASSERT(bp != NULL);	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));	leaf = (xfs_attr_leafblock_t *)tmpbuffer;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));	/*	 * Clean out the prior contents of the attribute list.	 */	error = xfs_da_shrink_inode(args, 0, bp);	if (error)		goto out;	if (forkoff == -1) {		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);		/*		 * Last attribute was removed, revert to original		 * inode format making all literal area available		 * to the data fork once more.		 */		xfs_idestroy_fork(dp, XFS_ATTR_FORK);		dp->i_d.di_forkoff = 0;		dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;		ASSERT(dp->i_d.di_anextents == 0);		ASSERT(dp->i_afp == NULL);		dp->i_df.if_ext_max =			XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);		goto out;	}	xfs_attr_shortform_create(args);	/*	 * Copy the attributes	 */	memset((char *)&nargs, 0, sizeof(nargs));	nargs.dp = dp;	nargs.firstblock = args->firstblock;	nargs.flist = args->flist;	nargs.total = args->total;	nargs.whichfork = XFS_ATTR_FORK;	nargs.trans = args->trans;	nargs.oknoent = 1;	entry = &leaf->entries[0];	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {		if (entry->flags & XFS_ATTR_INCOMPLETE)			continue;	/* don't copy partial entries */		if (!entry->nameidx)			continue;		ASSERT(entry->flags & XFS_ATTR_LOCAL);		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);		nargs.name = (char *)name_loc->nameval;		nargs.namelen = name_loc->namelen;		nargs.value = (char *)&name_loc->nameval[nargs.namelen];		nargs.valuelen = be16_to_cpu(name_loc->valuelen);		nargs.hashval = be32_to_cpu(entry->hashval);		nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);		xfs_attr_shortform_add(&nargs, forkoff);	}	error = 0;out:	kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));	return(error);}/* * Convert from using a single leaf to a root node and a leaf. */intxfs_attr_leaf_to_node(xfs_da_args_t *args)

⌨️ 快捷键说明

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