[LU-5933] FIEMAP: FIEMAP_EXTENT_LAST is not always set Created: 19/Nov/14  Updated: 25/Aug/15  Resolved: 05/Dec/14

Status: Resolved
Project: Lustre
Component/s: None
Affects Version/s: Lustre 2.7.0
Fix Version/s: Lustre 2.7.0

Type: Bug Priority: Major
Reporter: Frank Zago (Inactive) Assignee: Zhenyu Xu
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Related
is related to LU-6007 FIEMAP fails xfstests's fiemap-tester Open
Severity: 3
Rank (Obsolete): 16568

 Description   

With the FS_IOC_FIEMAP ioctl, when the exact number of required extent is used, and the file ends with a hole, FIEMAP_EXTENT_LAST is not set like it should.

Reproducer:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <linux/fiemap.h>
#include <sys/ioctl.h>

int main(int argc, char *argv[])
{
	struct fiemap *fiemap = NULL;
	struct fiemap fiemap_init;
	int fd;
	size_t extents_count;

	fd = open(argv[1], O_RDONLY);

	/* Query to get the number of extents. */
	memset(&fiemap_init, 0, sizeof(fiemap_init));
	fiemap_init.fm_length = ~0;		/* all of it */
	fiemap_init.fm_flags = FIEMAP_FLAG_SYNC; /* sync file */

	if (ioctl(fd, FS_IOC_FIEMAP, &fiemap_init) < 0) {
		perror("fiemap 1 failed");
		return 1;
	}

	extents_count = fiemap_init.fm_mapped_extents;
	fprintf(stderr, "(1st) file has %zd extent(s)\n", extents_count);

	if (extents_count == 0) {
		return 1;
	}

	/* Workaround for Lustre */
	//extents_count++;

	fiemap = calloc(1, sizeof(struct fiemap) +
					sizeof(struct fiemap_extent) * extents_count);
	if (fiemap == NULL) {
		perror("calloc failed");
		return 1;
	}

	/* Get the extents. */
	fiemap->fm_length = ~0;		/* the whole file */
	fiemap->fm_flags = FIEMAP_FLAG_SYNC; /* sync file */
	fiemap->fm_extent_count = extents_count;

	if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) {
		perror("fiemap 2 failed");
		return 1;
	}

	fprintf(stderr, "(2nd) file has %zd extent(s)\n", extents_count);

	if (fiemap->fm_extents[fiemap->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST)
		printf("Good\n");
	else
		printf("Bad\n");

	return 0;
}

On ext4:

# echo sdfghjk > tfile
# ~/tsparse tfile 
file has 1 extent(s)
Good
# truncate -s 10000 tfile 
# ~/tsparse tfile 
(1st) file has 1 extent(s)
(2nd) file has 1 extent(s)
Good

On Lustre head of tree:

# echo sdfghjk > tfile
# ~/tsparse tfile 
(1st) file has 1 extent(s)
(2nd) file has 1 extent(s)
Good
# truncate -s 1000000 tfile 
# ~/tsparse tfile 
file has 1 extent(s)
Bad

If I uncomment the "hack" in the test code, allocating one extra extent, then it works, although only 1 extent is actually used.

This is likely to break programs that rely on that flag to check the integrity of the returned mapping.

I don't have a fix at this time.



 Comments   
Comment by Gerrit Updater [ 05/Dec/14 ]

Oleg Drokin (oleg.drokin@intel.com) merged in patch http://review.whamcloud.com/12781/
Subject: LU-5933 fiemap: set FIEMAP_EXTENT_LAST correctly
Project: fs/lustre-release
Branch: master
Current Patch Set:
Commit: 5c2e692d2ae971f1ba0811487c37b3510ccde8be

Comment by Peter Jones [ 05/Dec/14 ]

Landed for 2.7

Generated at Sat Feb 10 01:55:46 UTC 2024 using Jira 9.4.14#940014-sha1:734e6822bbf0d45eff9af51f82432957f73aa32c.