Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4 * Copyright (c) 2013 Red Hat, Inc.
  5 * All Rights Reserved.
 
 
 
 
 
 
 
 
 
 
 
 
 
  6 */
  7#include "xfs.h"
  8#include "xfs_fs.h"
  9#include "xfs_shared.h"
 10#include "xfs_format.h"
 11#include "xfs_log_format.h"
 12#include "xfs_trans_resv.h"
 13#include "xfs_bit.h"
 14#include "xfs_mount.h"
 15#include "xfs_defer.h"
 16#include "xfs_da_format.h"
 17#include "xfs_da_btree.h"
 18#include "xfs_inode.h"
 
 19#include "xfs_trans.h"
 
 20#include "xfs_bmap.h"
 
 21#include "xfs_attr.h"
 
 22#include "xfs_attr_remote.h"
 
 23#include "xfs_trace.h"
 
 
 24#include "xfs_error.h"
 25
 26#define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
 27
 28/*
 29 * Remote Attribute Values
 30 * =======================
 31 *
 32 * Remote extended attribute values are conceptually simple -- they're written
 33 * to data blocks mapped by an inode's attribute fork, and they have an upper
 34 * size limit of 64k.  Setting a value does not involve the XFS log.
 35 *
 36 * However, on a v5 filesystem, maximally sized remote attr values require one
 37 * block more than 64k worth of space to hold both the remote attribute value
 38 * header (64 bytes).  On a 4k block filesystem this results in a 68k buffer;
 39 * on a 64k block filesystem, this would be a 128k buffer.  Note that the log
 40 * format can only handle a dirty buffer of XFS_MAX_BLOCKSIZE length (64k).
 41 * Therefore, we /must/ ensure that remote attribute value buffers never touch
 42 * the logging system and therefore never have a log item.
 43 */
 44
 45/*
 46 * Each contiguous block has a header, so it is not just a simple attribute
 47 * length to FSB conversion.
 48 */
 49int
 50xfs_attr3_rmt_blocks(
 51	struct xfs_mount *mp,
 52	int		attrlen)
 53{
 54	if (xfs_has_crc(mp)) {
 55		int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
 56		return (attrlen + buflen - 1) / buflen;
 57	}
 58	return XFS_B_TO_FSB(mp, attrlen);
 59}
 60
 61/*
 62 * Checking of the remote attribute header is split into two parts. The verifier
 63 * does CRC, location and bounds checking, the unpacking function checks the
 64 * attribute parameters and owner.
 65 */
 66static xfs_failaddr_t
 67xfs_attr3_rmt_hdr_ok(
 68	void			*ptr,
 69	xfs_ino_t		ino,
 70	uint32_t		offset,
 71	uint32_t		size,
 72	xfs_daddr_t		bno)
 73{
 74	struct xfs_attr3_rmt_hdr *rmt = ptr;
 75
 76	if (bno != be64_to_cpu(rmt->rm_blkno))
 77		return __this_address;
 78	if (offset != be32_to_cpu(rmt->rm_offset))
 79		return __this_address;
 80	if (size != be32_to_cpu(rmt->rm_bytes))
 81		return __this_address;
 82	if (ino != be64_to_cpu(rmt->rm_owner))
 83		return __this_address;
 84
 85	/* ok */
 86	return NULL;
 87}
 88
 89static xfs_failaddr_t
 90xfs_attr3_rmt_verify(
 91	struct xfs_mount	*mp,
 92	struct xfs_buf		*bp,
 93	void			*ptr,
 94	int			fsbsize,
 95	xfs_daddr_t		bno)
 96{
 97	struct xfs_attr3_rmt_hdr *rmt = ptr;
 98
 99	if (!xfs_verify_magic(bp, rmt->rm_magic))
100		return __this_address;
 
 
101	if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid))
102		return __this_address;
103	if (be64_to_cpu(rmt->rm_blkno) != bno)
104		return __this_address;
105	if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
106		return __this_address;
107	if (be32_to_cpu(rmt->rm_offset) +
108				be32_to_cpu(rmt->rm_bytes) > XFS_XATTR_SIZE_MAX)
109		return __this_address;
110	if (rmt->rm_owner == 0)
111		return __this_address;
112
113	return NULL;
114}
115
116static int
117__xfs_attr3_rmt_read_verify(
118	struct xfs_buf	*bp,
119	bool		check_crc,
120	xfs_failaddr_t	*failaddr)
121{
122	struct xfs_mount *mp = bp->b_mount;
123	char		*ptr;
124	int		len;
125	xfs_daddr_t	bno;
126	int		blksize = mp->m_attr_geo->blksize;
127
128	/* no verification of non-crc buffers */
129	if (!xfs_has_crc(mp))
130		return 0;
131
132	ptr = bp->b_addr;
133	bno = xfs_buf_daddr(bp);
134	len = BBTOB(bp->b_length);
135	ASSERT(len >= blksize);
136
137	while (len > 0) {
138		if (check_crc &&
139		    !xfs_verify_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF)) {
140			*failaddr = __this_address;
141			return -EFSBADCRC;
 
 
 
142		}
143		*failaddr = xfs_attr3_rmt_verify(mp, bp, ptr, blksize, bno);
144		if (*failaddr)
145			return -EFSCORRUPTED;
146		len -= blksize;
147		ptr += blksize;
148		bno += BTOBB(blksize);
149	}
150
151	if (len != 0) {
152		*failaddr = __this_address;
153		return -EFSCORRUPTED;
154	}
155
156	return 0;
157}
158
159static void
160xfs_attr3_rmt_read_verify(
161	struct xfs_buf	*bp)
162{
163	xfs_failaddr_t	fa;
164	int		error;
165
166	error = __xfs_attr3_rmt_read_verify(bp, true, &fa);
167	if (error)
168		xfs_verifier_error(bp, error, fa);
169}
170
171static xfs_failaddr_t
172xfs_attr3_rmt_verify_struct(
173	struct xfs_buf	*bp)
174{
175	xfs_failaddr_t	fa;
176	int		error;
177
178	error = __xfs_attr3_rmt_read_verify(bp, false, &fa);
179	return error ? fa : NULL;
180}
181
182static void
183xfs_attr3_rmt_write_verify(
184	struct xfs_buf	*bp)
185{
186	struct xfs_mount *mp = bp->b_mount;
187	xfs_failaddr_t	fa;
188	int		blksize = mp->m_attr_geo->blksize;
189	char		*ptr;
190	int		len;
191	xfs_daddr_t	bno;
192
193	/* no verification of non-crc buffers */
194	if (!xfs_has_crc(mp))
195		return;
196
197	ptr = bp->b_addr;
198	bno = xfs_buf_daddr(bp);
199	len = BBTOB(bp->b_length);
200	ASSERT(len >= blksize);
201
202	while (len > 0) {
203		struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr;
204
205		fa = xfs_attr3_rmt_verify(mp, bp, ptr, blksize, bno);
206		if (fa) {
207			xfs_verifier_error(bp, -EFSCORRUPTED, fa);
208			return;
209		}
210
211		/*
212		 * Ensure we aren't writing bogus LSNs to disk. See
213		 * xfs_attr3_rmt_hdr_set() for the explanation.
214		 */
215		if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) {
216			xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
 
217			return;
218		}
219		xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF);
220
221		len -= blksize;
222		ptr += blksize;
223		bno += BTOBB(blksize);
224	}
225
226	if (len != 0)
227		xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
228}
229
230const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
231	.name = "xfs_attr3_rmt",
232	.magic = { 0, cpu_to_be32(XFS_ATTR3_RMT_MAGIC) },
233	.verify_read = xfs_attr3_rmt_read_verify,
234	.verify_write = xfs_attr3_rmt_write_verify,
235	.verify_struct = xfs_attr3_rmt_verify_struct,
236};
237
238STATIC int
239xfs_attr3_rmt_hdr_set(
240	struct xfs_mount	*mp,
241	void			*ptr,
242	xfs_ino_t		ino,
243	uint32_t		offset,
244	uint32_t		size,
245	xfs_daddr_t		bno)
246{
247	struct xfs_attr3_rmt_hdr *rmt = ptr;
248
249	if (!xfs_has_crc(mp))
250		return 0;
251
252	rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC);
253	rmt->rm_offset = cpu_to_be32(offset);
254	rmt->rm_bytes = cpu_to_be32(size);
255	uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid);
256	rmt->rm_owner = cpu_to_be64(ino);
257	rmt->rm_blkno = cpu_to_be64(bno);
258
259	/*
260	 * Remote attribute blocks are written synchronously, so we don't
261	 * have an LSN that we can stamp in them that makes any sense to log
262	 * recovery. To ensure that log recovery handles overwrites of these
263	 * blocks sanely (i.e. once they've been freed and reallocated as some
264	 * other type of metadata) we need to ensure that the LSN has a value
265	 * that tells log recovery to ignore the LSN and overwrite the buffer
266	 * with whatever is in it's log. To do this, we use the magic
267	 * NULLCOMMITLSN to indicate that the LSN is invalid.
268	 */
269	rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN);
270
271	return sizeof(struct xfs_attr3_rmt_hdr);
272}
273
274/*
275 * Helper functions to copy attribute data in and out of the one disk extents
276 */
277STATIC int
278xfs_attr_rmtval_copyout(
279	struct xfs_mount *mp,
280	struct xfs_buf	*bp,
281	xfs_ino_t	ino,
282	int		*offset,
283	int		*valuelen,
284	uint8_t		**dst)
285{
286	char		*src = bp->b_addr;
287	xfs_daddr_t	bno = xfs_buf_daddr(bp);
288	int		len = BBTOB(bp->b_length);
289	int		blksize = mp->m_attr_geo->blksize;
290
291	ASSERT(len >= blksize);
292
293	while (len > 0 && *valuelen > 0) {
294		int hdr_size = 0;
295		int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
296
297		byte_cnt = min(*valuelen, byte_cnt);
298
299		if (xfs_has_crc(mp)) {
300			if (xfs_attr3_rmt_hdr_ok(src, ino, *offset,
301						  byte_cnt, bno)) {
302				xfs_alert(mp,
303"remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
304					bno, *offset, byte_cnt, ino);
305				return -EFSCORRUPTED;
306			}
307			hdr_size = sizeof(struct xfs_attr3_rmt_hdr);
308		}
309
310		memcpy(*dst, src + hdr_size, byte_cnt);
311
312		/* roll buffer forwards */
313		len -= blksize;
314		src += blksize;
315		bno += BTOBB(blksize);
316
317		/* roll attribute data forwards */
318		*valuelen -= byte_cnt;
319		*dst += byte_cnt;
320		*offset += byte_cnt;
321	}
322	return 0;
323}
324
325STATIC void
326xfs_attr_rmtval_copyin(
327	struct xfs_mount *mp,
328	struct xfs_buf	*bp,
329	xfs_ino_t	ino,
330	int		*offset,
331	int		*valuelen,
332	uint8_t		**src)
333{
334	char		*dst = bp->b_addr;
335	xfs_daddr_t	bno = xfs_buf_daddr(bp);
336	int		len = BBTOB(bp->b_length);
337	int		blksize = mp->m_attr_geo->blksize;
338
339	ASSERT(len >= blksize);
340
341	while (len > 0 && *valuelen > 0) {
342		int hdr_size;
343		int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
344
345		byte_cnt = min(*valuelen, byte_cnt);
346		hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
347						 byte_cnt, bno);
348
349		memcpy(dst + hdr_size, *src, byte_cnt);
350
351		/*
352		 * If this is the last block, zero the remainder of it.
353		 * Check that we are actually the last block, too.
354		 */
355		if (byte_cnt + hdr_size < blksize) {
356			ASSERT(*valuelen - byte_cnt == 0);
357			ASSERT(len == blksize);
358			memset(dst + hdr_size + byte_cnt, 0,
359					blksize - hdr_size - byte_cnt);
360		}
361
362		/* roll buffer forwards */
363		len -= blksize;
364		dst += blksize;
365		bno += BTOBB(blksize);
366
367		/* roll attribute data forwards */
368		*valuelen -= byte_cnt;
369		*src += byte_cnt;
370		*offset += byte_cnt;
371	}
372}
373
374/*
375 * Read the value associated with an attribute from the out-of-line buffer
376 * that we stored it in.
377 *
378 * Returns 0 on successful retrieval, otherwise an error.
379 */
380int
381xfs_attr_rmtval_get(
382	struct xfs_da_args	*args)
383{
384	struct xfs_bmbt_irec	map[ATTR_RMTVALUE_MAPSIZE];
385	struct xfs_mount	*mp = args->dp->i_mount;
386	struct xfs_buf		*bp;
387	xfs_dablk_t		lblkno = args->rmtblkno;
388	uint8_t			*dst = args->value;
389	int			valuelen;
390	int			nmap;
391	int			error;
392	int			blkcnt = args->rmtblkcnt;
393	int			i;
394	int			offset = 0;
395
396	trace_xfs_attr_rmtval_get(args);
397
398	ASSERT(args->valuelen != 0);
399	ASSERT(args->rmtvaluelen == args->valuelen);
400
401	valuelen = args->rmtvaluelen;
402	while (valuelen > 0) {
403		nmap = ATTR_RMTVALUE_MAPSIZE;
404		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
405				       blkcnt, map, &nmap,
406				       XFS_BMAPI_ATTRFORK);
407		if (error)
408			return error;
409		ASSERT(nmap >= 1);
410
411		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
412			xfs_daddr_t	dblkno;
413			int		dblkcnt;
414
415			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
416			       (map[i].br_startblock != HOLESTARTBLOCK));
417			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
418			dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
419			error = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt,
420					0, &bp, &xfs_attr3_rmt_buf_ops);
 
421			if (error)
422				return error;
423
424			error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
425							&offset, &valuelen,
426							&dst);
427			xfs_buf_relse(bp);
428			if (error)
429				return error;
430
431			/* roll attribute extent map forwards */
432			lblkno += map[i].br_blockcount;
433			blkcnt -= map[i].br_blockcount;
434		}
435	}
436	ASSERT(valuelen == 0);
437	return 0;
438}
439
440/*
441 * Find a "hole" in the attribute address space large enough for us to drop the
442 * new attributes value into
443 */
444int
445xfs_attr_rmt_find_hole(
446	struct xfs_da_args	*args)
447{
448	struct xfs_inode	*dp = args->dp;
449	struct xfs_mount	*mp = dp->i_mount;
450	int			error;
451	int			blkcnt;
452	xfs_fileoff_t		lfileoff = 0;
 
 
 
 
 
 
 
 
453
454	/*
455	 * Because CRC enable attributes have headers, we can't just do a
456	 * straight byte to FSB conversion and have to take the header space
457	 * into account.
 
458	 */
459	blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen);
460	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
461						   XFS_ATTR_FORK);
462	if (error)
463		return error;
464
465	args->rmtblkno = (xfs_dablk_t)lfileoff;
466	args->rmtblkcnt = blkcnt;
467
468	return 0;
469}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
471int
472xfs_attr_rmtval_set_value(
473	struct xfs_da_args	*args)
474{
475	struct xfs_inode	*dp = args->dp;
476	struct xfs_mount	*mp = dp->i_mount;
477	struct xfs_bmbt_irec	map;
478	xfs_dablk_t		lblkno;
479	uint8_t			*src = args->value;
480	int			blkcnt;
481	int			valuelen;
482	int			nmap;
483	int			error;
484	int			offset = 0;
485
486	/*
487	 * Roll through the "value", copying the attribute value to the
488	 * already-allocated blocks.  Blocks are written synchronously
489	 * so that we can know they are all on disk before we turn off
490	 * the INCOMPLETE flag.
491	 */
492	lblkno = args->rmtblkno;
493	blkcnt = args->rmtblkcnt;
494	valuelen = args->rmtvaluelen;
495	while (valuelen > 0) {
496		struct xfs_buf	*bp;
497		xfs_daddr_t	dblkno;
498		int		dblkcnt;
499
500		ASSERT(blkcnt > 0);
501
 
502		nmap = 1;
503		error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
504				       blkcnt, &map, &nmap,
505				       XFS_BMAPI_ATTRFORK);
506		if (error)
507			return error;
508		ASSERT(nmap == 1);
509		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
510		       (map.br_startblock != HOLESTARTBLOCK));
511
512		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
513		dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
514
515		error = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, &bp);
516		if (error)
517			return error;
518		bp->b_ops = &xfs_attr3_rmt_buf_ops;
519
520		xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
521				       &valuelen, &src);
522
523		error = xfs_bwrite(bp);	/* GROT: NOTE: synchronous write */
524		xfs_buf_relse(bp);
525		if (error)
526			return error;
527
528
529		/* roll attribute extent map forwards */
530		lblkno += map.br_blockcount;
531		blkcnt -= map.br_blockcount;
532	}
533	ASSERT(valuelen == 0);
534	return 0;
535}
536
537/* Mark stale any incore buffers for the remote value. */
538int
539xfs_attr_rmtval_stale(
540	struct xfs_inode	*ip,
541	struct xfs_bmbt_irec	*map,
542	xfs_buf_flags_t		incore_flags)
543{
544	struct xfs_mount	*mp = ip->i_mount;
545	struct xfs_buf		*bp;
546	int			error;
547
548	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
549
550	if (XFS_IS_CORRUPT(mp, map->br_startblock == DELAYSTARTBLOCK) ||
551	    XFS_IS_CORRUPT(mp, map->br_startblock == HOLESTARTBLOCK))
552		return -EFSCORRUPTED;
553
554	error = xfs_buf_incore(mp->m_ddev_targp,
555			XFS_FSB_TO_DADDR(mp, map->br_startblock),
556			XFS_FSB_TO_BB(mp, map->br_blockcount),
557			incore_flags, &bp);
558	if (error) {
559		if (error == -ENOENT)
560			return 0;
561		return error;
562	}
563
564	xfs_buf_stale(bp);
565	xfs_buf_relse(bp);
566	return 0;
567}
568
569/*
570 * Find a hole for the attr and store it in the delayed attr context.  This
571 * initializes the context to roll through allocating an attr extent for a
572 * delayed attr operation
573 */
574int
575xfs_attr_rmtval_find_space(
576	struct xfs_attr_intent		*attr)
577{
578	struct xfs_da_args		*args = attr->xattri_da_args;
579	struct xfs_bmbt_irec		*map = &attr->xattri_map;
580	int				error;
581
582	attr->xattri_lblkno = 0;
583	attr->xattri_blkcnt = 0;
584	args->rmtblkcnt = 0;
585	args->rmtblkno = 0;
586	memset(map, 0, sizeof(struct xfs_bmbt_irec));
587
588	error = xfs_attr_rmt_find_hole(args);
589	if (error)
590		return error;
591
592	attr->xattri_blkcnt = args->rmtblkcnt;
593	attr->xattri_lblkno = args->rmtblkno;
594
595	return 0;
596}
597
598/*
599 * Write one block of the value associated with an attribute into the
600 * out-of-line buffer that we have defined for it. This is similar to a subset
601 * of xfs_attr_rmtval_set, but records the current block to the delayed attr
602 * context, and leaves transaction handling to the caller.
603 */
604int
605xfs_attr_rmtval_set_blk(
606	struct xfs_attr_intent		*attr)
607{
608	struct xfs_da_args		*args = attr->xattri_da_args;
609	struct xfs_inode		*dp = args->dp;
610	struct xfs_bmbt_irec		*map = &attr->xattri_map;
611	int nmap;
612	int error;
613
614	nmap = 1;
615	error = xfs_bmapi_write(args->trans, dp,
616			(xfs_fileoff_t)attr->xattri_lblkno,
617			attr->xattri_blkcnt, XFS_BMAPI_ATTRFORK, args->total,
618			map, &nmap);
619	if (error)
620		return error;
621
622	ASSERT(nmap == 1);
623	ASSERT((map->br_startblock != DELAYSTARTBLOCK) &&
624	       (map->br_startblock != HOLESTARTBLOCK));
625
626	/* roll attribute extent map forwards */
627	attr->xattri_lblkno += map->br_blockcount;
628	attr->xattri_blkcnt -= map->br_blockcount;
629
630	return 0;
631}
632
633/*
634 * Remove the value associated with an attribute by deleting the
635 * out-of-line buffer that it is stored on.
636 */
637int
638xfs_attr_rmtval_invalidate(
639	struct xfs_da_args	*args)
640{
 
641	xfs_dablk_t		lblkno;
642	int			blkcnt;
643	int			error;
 
 
 
644
645	/*
646	 * Roll through the "value", invalidating the attribute value's blocks.
647	 */
648	lblkno = args->rmtblkno;
649	blkcnt = args->rmtblkcnt;
650	while (blkcnt > 0) {
651		struct xfs_bmbt_irec	map;
 
 
 
652		int			nmap;
653
654		/*
655		 * Try to remember where we decided to put the value.
656		 */
657		nmap = 1;
658		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
659				       blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
660		if (error)
661			return error;
662		if (XFS_IS_CORRUPT(args->dp->i_mount, nmap != 1))
663			return -EFSCORRUPTED;
664		error = xfs_attr_rmtval_stale(args->dp, &map, XBF_TRYLOCK);
665		if (error)
666			return error;
 
 
 
 
 
 
 
 
 
 
 
667
668		lblkno += map.br_blockcount;
669		blkcnt -= map.br_blockcount;
670	}
671	return 0;
672}
673
674/*
675 * Remove the value associated with an attribute by deleting the out-of-line
676 * buffer that it is stored on. Returns -EAGAIN for the caller to refresh the
677 * transaction and re-call the function.  Callers should keep calling this
678 * routine until it returns something other than -EAGAIN.
679 */
680int
681xfs_attr_rmtval_remove(
682	struct xfs_attr_intent		*attr)
683{
684	struct xfs_da_args		*args = attr->xattri_da_args;
685	int				error, done;
686
687	/*
688	 * Unmap value blocks for this attr.
689	 */
690	error = xfs_bunmapi(args->trans, args->dp, args->rmtblkno,
691			    args->rmtblkcnt, XFS_BMAPI_ATTRFORK, 1, &done);
692	if (error)
693		return error;
 
 
 
 
 
 
 
 
 
 
 
 
694
695	/*
696	 * We don't need an explicit state here to pick up where we left off. We
697	 * can figure it out using the !done return code. The actual value of
698	 * attr->xattri_dela_state may be some value reminiscent of the calling
699	 * function, but it's value is irrelevant with in the context of this
700	 * function. Once we are done here, the next state is set as needed by
701	 * the parent
702	 */
703	if (!done) {
704		trace_xfs_attr_rmtval_remove_return(attr->xattri_dela_state,
705						    args->dp);
706		return -EAGAIN;
707	}
708
709	args->rmtblkno = 0;
710	args->rmtblkcnt = 0;
711	return 0;
712}
v4.10.11
 
  1/*
  2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  3 * Copyright (c) 2013 Red Hat, Inc.
  4 * All Rights Reserved.
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License as
  8 * published by the Free Software Foundation.
  9 *
 10 * This program is distributed in the hope that it would be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU General Public License
 16 * along with this program; if not, write the Free Software Foundation,
 17 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18 */
 19#include "xfs.h"
 20#include "xfs_fs.h"
 21#include "xfs_shared.h"
 22#include "xfs_format.h"
 23#include "xfs_log_format.h"
 24#include "xfs_trans_resv.h"
 25#include "xfs_bit.h"
 26#include "xfs_mount.h"
 27#include "xfs_defer.h"
 28#include "xfs_da_format.h"
 29#include "xfs_da_btree.h"
 30#include "xfs_inode.h"
 31#include "xfs_alloc.h"
 32#include "xfs_trans.h"
 33#include "xfs_inode_item.h"
 34#include "xfs_bmap.h"
 35#include "xfs_bmap_util.h"
 36#include "xfs_attr.h"
 37#include "xfs_attr_leaf.h"
 38#include "xfs_attr_remote.h"
 39#include "xfs_trans_space.h"
 40#include "xfs_trace.h"
 41#include "xfs_cksum.h"
 42#include "xfs_buf_item.h"
 43#include "xfs_error.h"
 44
 45#define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
 46
 47/*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 48 * Each contiguous block has a header, so it is not just a simple attribute
 49 * length to FSB conversion.
 50 */
 51int
 52xfs_attr3_rmt_blocks(
 53	struct xfs_mount *mp,
 54	int		attrlen)
 55{
 56	if (xfs_sb_version_hascrc(&mp->m_sb)) {
 57		int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
 58		return (attrlen + buflen - 1) / buflen;
 59	}
 60	return XFS_B_TO_FSB(mp, attrlen);
 61}
 62
 63/*
 64 * Checking of the remote attribute header is split into two parts. The verifier
 65 * does CRC, location and bounds checking, the unpacking function checks the
 66 * attribute parameters and owner.
 67 */
 68static bool
 69xfs_attr3_rmt_hdr_ok(
 70	void			*ptr,
 71	xfs_ino_t		ino,
 72	uint32_t		offset,
 73	uint32_t		size,
 74	xfs_daddr_t		bno)
 75{
 76	struct xfs_attr3_rmt_hdr *rmt = ptr;
 77
 78	if (bno != be64_to_cpu(rmt->rm_blkno))
 79		return false;
 80	if (offset != be32_to_cpu(rmt->rm_offset))
 81		return false;
 82	if (size != be32_to_cpu(rmt->rm_bytes))
 83		return false;
 84	if (ino != be64_to_cpu(rmt->rm_owner))
 85		return false;
 86
 87	/* ok */
 88	return true;
 89}
 90
 91static bool
 92xfs_attr3_rmt_verify(
 93	struct xfs_mount	*mp,
 
 94	void			*ptr,
 95	int			fsbsize,
 96	xfs_daddr_t		bno)
 97{
 98	struct xfs_attr3_rmt_hdr *rmt = ptr;
 99
100	if (!xfs_sb_version_hascrc(&mp->m_sb))
101		return false;
102	if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC))
103		return false;
104	if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid))
105		return false;
106	if (be64_to_cpu(rmt->rm_blkno) != bno)
107		return false;
108	if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
109		return false;
110	if (be32_to_cpu(rmt->rm_offset) +
111				be32_to_cpu(rmt->rm_bytes) > XFS_XATTR_SIZE_MAX)
112		return false;
113	if (rmt->rm_owner == 0)
114		return false;
115
116	return true;
117}
118
119static void
120xfs_attr3_rmt_read_verify(
121	struct xfs_buf	*bp)
 
 
122{
123	struct xfs_mount *mp = bp->b_target->bt_mount;
124	char		*ptr;
125	int		len;
126	xfs_daddr_t	bno;
127	int		blksize = mp->m_attr_geo->blksize;
128
129	/* no verification of non-crc buffers */
130	if (!xfs_sb_version_hascrc(&mp->m_sb))
131		return;
132
133	ptr = bp->b_addr;
134	bno = bp->b_bn;
135	len = BBTOB(bp->b_length);
136	ASSERT(len >= blksize);
137
138	while (len > 0) {
139		if (!xfs_verify_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF)) {
140			xfs_buf_ioerror(bp, -EFSBADCRC);
141			break;
142		}
143		if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) {
144			xfs_buf_ioerror(bp, -EFSCORRUPTED);
145			break;
146		}
 
 
 
147		len -= blksize;
148		ptr += blksize;
149		bno += BTOBB(blksize);
150	}
151
152	if (bp->b_error)
153		xfs_verifier_error(bp);
154	else
155		ASSERT(len == 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156}
157
158static void
159xfs_attr3_rmt_write_verify(
160	struct xfs_buf	*bp)
161{
162	struct xfs_mount *mp = bp->b_target->bt_mount;
 
163	int		blksize = mp->m_attr_geo->blksize;
164	char		*ptr;
165	int		len;
166	xfs_daddr_t	bno;
167
168	/* no verification of non-crc buffers */
169	if (!xfs_sb_version_hascrc(&mp->m_sb))
170		return;
171
172	ptr = bp->b_addr;
173	bno = bp->b_bn;
174	len = BBTOB(bp->b_length);
175	ASSERT(len >= blksize);
176
177	while (len > 0) {
178		struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr;
179
180		if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) {
181			xfs_buf_ioerror(bp, -EFSCORRUPTED);
182			xfs_verifier_error(bp);
183			return;
184		}
185
186		/*
187		 * Ensure we aren't writing bogus LSNs to disk. See
188		 * xfs_attr3_rmt_hdr_set() for the explanation.
189		 */
190		if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) {
191			xfs_buf_ioerror(bp, -EFSCORRUPTED);
192			xfs_verifier_error(bp);
193			return;
194		}
195		xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF);
196
197		len -= blksize;
198		ptr += blksize;
199		bno += BTOBB(blksize);
200	}
201	ASSERT(len == 0);
 
 
202}
203
204const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
205	.name = "xfs_attr3_rmt",
 
206	.verify_read = xfs_attr3_rmt_read_verify,
207	.verify_write = xfs_attr3_rmt_write_verify,
 
208};
209
210STATIC int
211xfs_attr3_rmt_hdr_set(
212	struct xfs_mount	*mp,
213	void			*ptr,
214	xfs_ino_t		ino,
215	uint32_t		offset,
216	uint32_t		size,
217	xfs_daddr_t		bno)
218{
219	struct xfs_attr3_rmt_hdr *rmt = ptr;
220
221	if (!xfs_sb_version_hascrc(&mp->m_sb))
222		return 0;
223
224	rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC);
225	rmt->rm_offset = cpu_to_be32(offset);
226	rmt->rm_bytes = cpu_to_be32(size);
227	uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid);
228	rmt->rm_owner = cpu_to_be64(ino);
229	rmt->rm_blkno = cpu_to_be64(bno);
230
231	/*
232	 * Remote attribute blocks are written synchronously, so we don't
233	 * have an LSN that we can stamp in them that makes any sense to log
234	 * recovery. To ensure that log recovery handles overwrites of these
235	 * blocks sanely (i.e. once they've been freed and reallocated as some
236	 * other type of metadata) we need to ensure that the LSN has a value
237	 * that tells log recovery to ignore the LSN and overwrite the buffer
238	 * with whatever is in it's log. To do this, we use the magic
239	 * NULLCOMMITLSN to indicate that the LSN is invalid.
240	 */
241	rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN);
242
243	return sizeof(struct xfs_attr3_rmt_hdr);
244}
245
246/*
247 * Helper functions to copy attribute data in and out of the one disk extents
248 */
249STATIC int
250xfs_attr_rmtval_copyout(
251	struct xfs_mount *mp,
252	struct xfs_buf	*bp,
253	xfs_ino_t	ino,
254	int		*offset,
255	int		*valuelen,
256	__uint8_t	**dst)
257{
258	char		*src = bp->b_addr;
259	xfs_daddr_t	bno = bp->b_bn;
260	int		len = BBTOB(bp->b_length);
261	int		blksize = mp->m_attr_geo->blksize;
262
263	ASSERT(len >= blksize);
264
265	while (len > 0 && *valuelen > 0) {
266		int hdr_size = 0;
267		int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
268
269		byte_cnt = min(*valuelen, byte_cnt);
270
271		if (xfs_sb_version_hascrc(&mp->m_sb)) {
272			if (!xfs_attr3_rmt_hdr_ok(src, ino, *offset,
273						  byte_cnt, bno)) {
274				xfs_alert(mp,
275"remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
276					bno, *offset, byte_cnt, ino);
277				return -EFSCORRUPTED;
278			}
279			hdr_size = sizeof(struct xfs_attr3_rmt_hdr);
280		}
281
282		memcpy(*dst, src + hdr_size, byte_cnt);
283
284		/* roll buffer forwards */
285		len -= blksize;
286		src += blksize;
287		bno += BTOBB(blksize);
288
289		/* roll attribute data forwards */
290		*valuelen -= byte_cnt;
291		*dst += byte_cnt;
292		*offset += byte_cnt;
293	}
294	return 0;
295}
296
297STATIC void
298xfs_attr_rmtval_copyin(
299	struct xfs_mount *mp,
300	struct xfs_buf	*bp,
301	xfs_ino_t	ino,
302	int		*offset,
303	int		*valuelen,
304	__uint8_t	**src)
305{
306	char		*dst = bp->b_addr;
307	xfs_daddr_t	bno = bp->b_bn;
308	int		len = BBTOB(bp->b_length);
309	int		blksize = mp->m_attr_geo->blksize;
310
311	ASSERT(len >= blksize);
312
313	while (len > 0 && *valuelen > 0) {
314		int hdr_size;
315		int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize);
316
317		byte_cnt = min(*valuelen, byte_cnt);
318		hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
319						 byte_cnt, bno);
320
321		memcpy(dst + hdr_size, *src, byte_cnt);
322
323		/*
324		 * If this is the last block, zero the remainder of it.
325		 * Check that we are actually the last block, too.
326		 */
327		if (byte_cnt + hdr_size < blksize) {
328			ASSERT(*valuelen - byte_cnt == 0);
329			ASSERT(len == blksize);
330			memset(dst + hdr_size + byte_cnt, 0,
331					blksize - hdr_size - byte_cnt);
332		}
333
334		/* roll buffer forwards */
335		len -= blksize;
336		dst += blksize;
337		bno += BTOBB(blksize);
338
339		/* roll attribute data forwards */
340		*valuelen -= byte_cnt;
341		*src += byte_cnt;
342		*offset += byte_cnt;
343	}
344}
345
346/*
347 * Read the value associated with an attribute from the out-of-line buffer
348 * that we stored it in.
 
 
349 */
350int
351xfs_attr_rmtval_get(
352	struct xfs_da_args	*args)
353{
354	struct xfs_bmbt_irec	map[ATTR_RMTVALUE_MAPSIZE];
355	struct xfs_mount	*mp = args->dp->i_mount;
356	struct xfs_buf		*bp;
357	xfs_dablk_t		lblkno = args->rmtblkno;
358	__uint8_t		*dst = args->value;
359	int			valuelen;
360	int			nmap;
361	int			error;
362	int			blkcnt = args->rmtblkcnt;
363	int			i;
364	int			offset = 0;
365
366	trace_xfs_attr_rmtval_get(args);
367
368	ASSERT(!(args->flags & ATTR_KERNOVAL));
369	ASSERT(args->rmtvaluelen == args->valuelen);
370
371	valuelen = args->rmtvaluelen;
372	while (valuelen > 0) {
373		nmap = ATTR_RMTVALUE_MAPSIZE;
374		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
375				       blkcnt, map, &nmap,
376				       XFS_BMAPI_ATTRFORK);
377		if (error)
378			return error;
379		ASSERT(nmap >= 1);
380
381		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
382			xfs_daddr_t	dblkno;
383			int		dblkcnt;
384
385			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
386			       (map[i].br_startblock != HOLESTARTBLOCK));
387			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
388			dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
389			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
390						   dblkno, dblkcnt, 0, &bp,
391						   &xfs_attr3_rmt_buf_ops);
392			if (error)
393				return error;
394
395			error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
396							&offset, &valuelen,
397							&dst);
398			xfs_buf_relse(bp);
399			if (error)
400				return error;
401
402			/* roll attribute extent map forwards */
403			lblkno += map[i].br_blockcount;
404			blkcnt -= map[i].br_blockcount;
405		}
406	}
407	ASSERT(valuelen == 0);
408	return 0;
409}
410
411/*
412 * Write the value associated with an attribute into the out-of-line buffer
413 * that we have defined for it.
414 */
415int
416xfs_attr_rmtval_set(
417	struct xfs_da_args	*args)
418{
419	struct xfs_inode	*dp = args->dp;
420	struct xfs_mount	*mp = dp->i_mount;
421	struct xfs_bmbt_irec	map;
422	xfs_dablk_t		lblkno;
423	xfs_fileoff_t		lfileoff = 0;
424	__uint8_t		*src = args->value;
425	int			blkcnt;
426	int			valuelen;
427	int			nmap;
428	int			error;
429	int			offset = 0;
430
431	trace_xfs_attr_rmtval_set(args);
432
433	/*
434	 * Find a "hole" in the attribute address space large enough for
435	 * us to drop the new attribute's value into. Because CRC enable
436	 * attributes have headers, we can't just do a straight byte to FSB
437	 * conversion and have to take the header space into account.
438	 */
439	blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen);
440	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
441						   XFS_ATTR_FORK);
442	if (error)
443		return error;
444
445	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
446	args->rmtblkcnt = blkcnt;
447
448	/*
449	 * Roll through the "value", allocating blocks on disk as required.
450	 */
451	while (blkcnt > 0) {
452		/*
453		 * Allocate a single extent, up to the size of the value.
454		 *
455		 * Note that we have to consider this a data allocation as we
456		 * write the remote attribute without logging the contents.
457		 * Hence we must ensure that we aren't using blocks that are on
458		 * the busy list so that we don't overwrite blocks which have
459		 * recently been freed but their transactions are not yet
460		 * committed to disk. If we overwrite the contents of a busy
461		 * extent and then crash then the block may not contain the
462		 * correct metadata after log recovery occurs.
463		 */
464		xfs_defer_init(args->dfops, args->firstblock);
465		nmap = 1;
466		error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
467				  blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock,
468				  args->total, &map, &nmap, args->dfops);
469		if (!error)
470			error = xfs_defer_finish(&args->trans, args->dfops, dp);
471		if (error) {
472			args->trans = NULL;
473			xfs_defer_cancel(args->dfops);
474			return error;
475		}
476
477		ASSERT(nmap == 1);
478		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
479		       (map.br_startblock != HOLESTARTBLOCK));
480		lblkno += map.br_blockcount;
481		blkcnt -= map.br_blockcount;
482
483		/*
484		 * Start the next trans in the chain.
485		 */
486		error = xfs_trans_roll(&args->trans, dp);
487		if (error)
488			return error;
489	}
 
490
491	/*
492	 * Roll through the "value", copying the attribute value to the
493	 * already-allocated blocks.  Blocks are written synchronously
494	 * so that we can know they are all on disk before we turn off
495	 * the INCOMPLETE flag.
496	 */
497	lblkno = args->rmtblkno;
498	blkcnt = args->rmtblkcnt;
499	valuelen = args->rmtvaluelen;
500	while (valuelen > 0) {
501		struct xfs_buf	*bp;
502		xfs_daddr_t	dblkno;
503		int		dblkcnt;
504
505		ASSERT(blkcnt > 0);
506
507		xfs_defer_init(args->dfops, args->firstblock);
508		nmap = 1;
509		error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
510				       blkcnt, &map, &nmap,
511				       XFS_BMAPI_ATTRFORK);
512		if (error)
513			return error;
514		ASSERT(nmap == 1);
515		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
516		       (map.br_startblock != HOLESTARTBLOCK));
517
518		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
519		dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
520
521		bp = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, 0);
522		if (!bp)
523			return -ENOMEM;
524		bp->b_ops = &xfs_attr3_rmt_buf_ops;
525
526		xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
527				       &valuelen, &src);
528
529		error = xfs_bwrite(bp);	/* GROT: NOTE: synchronous write */
530		xfs_buf_relse(bp);
531		if (error)
532			return error;
533
534
535		/* roll attribute extent map forwards */
536		lblkno += map.br_blockcount;
537		blkcnt -= map.br_blockcount;
538	}
539	ASSERT(valuelen == 0);
540	return 0;
541}
542
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543/*
544 * Remove the value associated with an attribute by deleting the
545 * out-of-line buffer that it is stored on.
546 */
547int
548xfs_attr_rmtval_remove(
549	struct xfs_da_args	*args)
550{
551	struct xfs_mount	*mp = args->dp->i_mount;
552	xfs_dablk_t		lblkno;
553	int			blkcnt;
554	int			error;
555	int			done;
556
557	trace_xfs_attr_rmtval_remove(args);
558
559	/*
560	 * Roll through the "value", invalidating the attribute value's blocks.
561	 */
562	lblkno = args->rmtblkno;
563	blkcnt = args->rmtblkcnt;
564	while (blkcnt > 0) {
565		struct xfs_bmbt_irec	map;
566		struct xfs_buf		*bp;
567		xfs_daddr_t		dblkno;
568		int			dblkcnt;
569		int			nmap;
570
571		/*
572		 * Try to remember where we decided to put the value.
573		 */
574		nmap = 1;
575		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
576				       blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
577		if (error)
578			return error;
579		ASSERT(nmap == 1);
580		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
581		       (map.br_startblock != HOLESTARTBLOCK));
582
583		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
584		dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
585
586		/*
587		 * If the "remote" value is in the cache, remove it.
588		 */
589		bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
590		if (bp) {
591			xfs_buf_stale(bp);
592			xfs_buf_relse(bp);
593			bp = NULL;
594		}
595
596		lblkno += map.br_blockcount;
597		blkcnt -= map.br_blockcount;
598	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
600	/*
601	 * Keep de-allocating extents until the remote-value region is gone.
602	 */
603	lblkno = args->rmtblkno;
604	blkcnt = args->rmtblkcnt;
605	done = 0;
606	while (!done) {
607		xfs_defer_init(args->dfops, args->firstblock);
608		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
609				    XFS_BMAPI_ATTRFORK, 1, args->firstblock,
610				    args->dfops, &done);
611		if (!error)
612			error = xfs_defer_finish(&args->trans, args->dfops,
613						args->dp);
614		if (error) {
615			args->trans = NULL;
616			xfs_defer_cancel(args->dfops);
617			return error;
618		}
619
620		/*
621		 * Close out trans and start the next one in the chain.
622		 */
623		error = xfs_trans_roll(&args->trans, args->dp);
624		if (error)
625			return error;
 
 
 
 
 
 
626	}
 
 
 
627	return 0;
628}