View | Details | Raw Unified | Return to bug 238197
Collapse All | Expand All

(-)sys/fs/fuse/fuse_internal.c (-1 / +18 lines)
Lines 242-247 Link Here
242
	vp_cache_at->va_mtime.tv_nsec = attr->mtimensec;
242
	vp_cache_at->va_mtime.tv_nsec = attr->mtimensec;
243
	vp_cache_at->va_ctime.tv_sec  = attr->ctime;
243
	vp_cache_at->va_ctime.tv_sec  = attr->ctime;
244
	vp_cache_at->va_ctime.tv_nsec = attr->ctimensec;
244
	vp_cache_at->va_ctime.tv_nsec = attr->ctimensec;
245
	if (fuse_libabi_geq(data, 7, 9)) {
246
		vp_cache_at->va_birthtime.tv_sec  = attr->crtime;
247
		vp_cache_at->va_birthtime.tv_nsec = attr->crtimensec;
248
	} else {
249
		/* {-1, 0} means "no value" */
250
		vp_cache_at->va_birthtime.tv_sec  = -1;
251
		vp_cache_at->va_birthtime.tv_nsec = 0;
252
	}
245
	if (fuse_libabi_geq(data, 7, 9) && attr->blksize > 0)
253
	if (fuse_libabi_geq(data, 7, 9) && attr->blksize > 0)
246
		vp_cache_at->va_blocksize = attr->blksize;
254
		vp_cache_at->va_blocksize = attr->blksize;
247
	else
255
	else
Lines 855-861 Link Here
855
	data = fuse_get_mpdata(mp);
863
	data = fuse_get_mpdata(mp);
856
	dataflags = data->dataflags;
864
	dataflags = data->dataflags;
857
865
858
	fdisp_init(&fdi, sizeof(*fsai));
866
	if (fuse_libabi_geq(data, 7, 9))
867
		fdisp_init(&fdi, sizeof(*fsai));
868
	else
869
		fdisp_init(&fdi, FUSE_COMPAT_SETATTR_IN_SIZE);
859
	fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred);
870
	fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred);
860
	if (!cred) {
871
	if (!cred) {
861
		fdi.finh->uid = 0;
872
		fdi.finh->uid = 0;
Lines 902-907 Link Here
902
		if (vap->va_vaflags & VA_UTIMES_NULL)
913
		if (vap->va_vaflags & VA_UTIMES_NULL)
903
			fsai->valid |= FATTR_MTIME_NOW;
914
			fsai->valid |= FATTR_MTIME_NOW;
904
	}
915
	}
916
	if (fuse_libabi_geq(data, 7, 9) && vap->va_birthtime.tv_sec != VNOVAL) {
917
		fsai->crtime = vap->va_birthtime.tv_sec;
918
		fsai->crtimensec = vap->va_birthtime.tv_nsec;
919
		fsai->valid |= FATTR_CRTIME;
920
		/* birthtime can never be set to UTIME_NOW */
921
	}
905
	if (vap->va_mode != (mode_t)VNOVAL) {
922
	if (vap->va_mode != (mode_t)VNOVAL) {
906
		fsai->mode = vap->va_mode & ALLPERMS;
923
		fsai->mode = vap->va_mode & ALLPERMS;
907
		fsai->valid |= FATTR_MODE;
924
		fsai->valid |= FATTR_MODE;
(-)sys/fs/fuse/fuse_kernel.h (-2 / +54 lines)
Lines 45-50 Link Here
45
 *  - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
45
 *  - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
46
 *  - add blksize field to fuse_attr
46
 *  - add blksize field to fuse_attr
47
 *  - add file flags field to fuse_read_in and fuse_write_in
47
 *  - add file flags field to fuse_read_in and fuse_write_in
48
#if defined(__FreeBSD__)
49
 *  - add birthtime field fo fuse_attr (FreeBSD only)
50
#endif
48
 */
51
 */
49
52
50
#ifndef _FUSE_FUSE_KERNEL_H
53
#ifndef _FUSE_FUSE_KERNEL_H
Lines 85-98 Link Here
85
	__u64	atime;
88
	__u64	atime;
86
	__u64	mtime;
89
	__u64	mtime;
87
	__u64	ctime;
90
	__u64	ctime;
91
#ifdef __APPLE__
92
	__u64	crtime;
93
#endif
88
	__u32	atimensec;
94
	__u32	atimensec;
89
	__u32	mtimensec;
95
	__u32	mtimensec;
90
	__u32	ctimensec;
96
	__u32	ctimensec;
97
#ifdef __APPLE__
98
	__u32	crtimensec;
99
#endif
91
	__u32	mode;
100
	__u32	mode;
92
	__u32	nlink;
101
	__u32	nlink;
93
	__u32	uid;
102
	__u32	uid;
94
	__u32	gid;
103
	__u32	gid;
95
	__u32	rdev;
104
	__u32	rdev;
105
#if defined(__APPLE__) || defined(__FreeBSD__)
106
	__u32	flags;	/* file flags; see chflags(2) */
107
#endif
108
#ifdef __FreeBSD__
109
	__u64	crtime;
110
	__u32	crtimensec;
111
#endif
96
	__u32	blksize;
112
	__u32	blksize;
97
	__u32	padding;
113
	__u32	padding;
98
};
114
};
Lines 130-135 Link Here
130
#define FATTR_ATIME_NOW	(1 << 7)
146
#define FATTR_ATIME_NOW	(1 << 7)
131
#define FATTR_MTIME_NOW	(1 << 8)
147
#define FATTR_MTIME_NOW	(1 << 8)
132
#define FATTR_LOCKOWNER	(1 << 9)
148
#define FATTR_LOCKOWNER	(1 << 9)
149
#if defined(__APPLE__) || defined(__FreeBSD__)
150
#define FATTR_CRTIME	(1 << 28)
151
#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
152
#ifdef __APPLE__
153
#define FATTR_CHGTIME	(1 << 29)
154
#define FATTR_BKUPTIME	(1 << 30)
155
#endif /* __APPLE__ */
156
#if defined(__APPLE__) || defined(__FreeBSD__)
157
#define FATTR_FLAGS	(1 << 31)
158
#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
133
159
134
/**
160
/**
135
 * Flags returned by the OPEN request
161
 * Flags returned by the OPEN request
Lines 223-229 Link Here
223
/* The read buffer is required to be at least 8k, but may be much larger */
249
/* The read buffer is required to be at least 8k, but may be much larger */
224
#define FUSE_MIN_READ_BUFFER 8192
250
#define FUSE_MIN_READ_BUFFER 8192
225
251
226
#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
252
#ifdef __APPLE__
253
#  define FUSE_COMPAT_ENTRY_OUT_SIZE 136
254
#else
255
#  define FUSE_COMPAT_ENTRY_OUT_SIZE 120
256
#endif
227
257
228
struct fuse_entry_out {
258
struct fuse_entry_out {
229
	__u64	nodeid;		/* Inode ID */
259
	__u64	nodeid;		/* Inode ID */
Lines 246-252 Link Here
246
	__u64	fh;
276
	__u64	fh;
247
};
277
};
248
278
249
#define FUSE_COMPAT_ATTR_OUT_SIZE 96
279
#ifdef __APPLE__
280
#  define FUSE_COMPAT_ATTR_OUT_SIZE 112
281
#else
282
#  define FUSE_COMPAT_ATTR_OUT_SIZE 96
283
#endif
250
284
251
struct fuse_attr_out {
285
struct fuse_attr_out {
252
	__u64	attr_valid;	/* Cache timeout for the attributes */
286
	__u64	attr_valid;	/* Cache timeout for the attributes */
Lines 273-278 Link Here
273
	__u64	oldnodeid;
307
	__u64	oldnodeid;
274
};
308
};
275
309
310
/* size of fuse_setattr_in before the addition of crtime and flags in 7.9 */
311
#define FUSE_COMPAT_SETATTR_IN_SIZE 88
312
276
struct fuse_setattr_in {
313
struct fuse_setattr_in {
277
	__u32	valid;
314
	__u32	valid;
278
	__u32	padding;
315
	__u32	padding;
Lines 290-295 Link Here
290
	__u32	uid;
327
	__u32	uid;
291
	__u32	gid;
328
	__u32	gid;
292
	__u32	unused5;
329
	__u32	unused5;
330
#ifdef __APPLE__
331
	__u64	bkuptime;
332
	__u64	chgtime;
333
#endif /* __APPLE__ */
334
#if defined(__APPLE__) || defined(__FreeBSD__)
335
	__u64	crtime;
336
#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
337
#ifdef __APPLE__
338
	__u32	bkuptimensec;
339
	__u32	chgtimensec;
340
#endif /* __APPLE__ */
341
#if defined(__APPLE__) || defined(__FreeBSD__)
342
	__u32	crtimensec;
343
	__u32	flags; /* file flags; see chflags(2) */
344
#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
293
};
345
};
294
346
295
struct fuse_open_in {
347
struct fuse_open_in {
(-)sys/fs/fuse/fuse_vnops.c (-1 / +3 lines)
Lines 1700-1706 Link Here
1700
		}
1700
		}
1701
		/* Don't set accmode.  Permission to trunc is checked upstack */
1701
		/* Don't set accmode.  Permission to trunc is checked upstack */
1702
	}
1702
	}
1703
	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1703
	if (vap->va_atime.tv_sec != VNOVAL ||
1704
	    vap->va_mtime.tv_sec != VNOVAL ||
1705
	    vap->va_birthtime.tv_sec != VNOVAL) {
1704
		if (vap->va_vaflags & VA_UTIMES_NULL)
1706
		if (vap->va_vaflags & VA_UTIMES_NULL)
1705
			accmode |= VWRITE;
1707
			accmode |= VWRITE;
1706
		else
1708
		else
(-)tests/sys/fs/fusefs/getattr.cc (-10 / +7 lines)
Lines 212-217 Link Here
212
		out.body.attr.attr.uid = 10;
212
		out.body.attr.attr.uid = 10;
213
		out.body.attr.attr.gid = 11;
213
		out.body.attr.attr.gid = 11;
214
		out.body.attr.attr.rdev = 12;
214
		out.body.attr.attr.rdev = 12;
215
		out.body.attr.attr.crtime = 13;
216
		out.body.attr.attr.crtimensec = 14;
215
		out.body.attr.attr.blksize = 12345;
217
		out.body.attr.attr.blksize = 12345;
216
	})));
218
	})));
217
219
Lines 228-243 Link Here
228
	EXPECT_EQ(10ul, sb.st_uid);
230
	EXPECT_EQ(10ul, sb.st_uid);
229
	EXPECT_EQ(11ul, sb.st_gid);
231
	EXPECT_EQ(11ul, sb.st_gid);
230
	EXPECT_EQ(12ul, sb.st_rdev);
232
	EXPECT_EQ(12ul, sb.st_rdev);
233
	EXPECT_EQ(13, sb.st_birthtim.tv_sec);
234
	EXPECT_EQ(14, sb.st_birthtim.tv_nsec);
231
	EXPECT_EQ((blksize_t)12345, sb.st_blksize);
235
	EXPECT_EQ((blksize_t)12345, sb.st_blksize);
232
	EXPECT_EQ(ino, sb.st_ino);
236
	EXPECT_EQ(ino, sb.st_ino);
233
	EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
237
	EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
234
235
	//st_birthtim and st_flags are not supported by protocol 7.8.  They're
236
	//only supported as OS-specific extensions to OSX.
237
	//EXPECT_EQ(, sb.st_birthtim);
238
	//EXPECT_EQ(, sb.st_flags);
239
	
240
	//FUSE can't set st_blksize until protocol 7.9
241
}
238
}
242
239
243
TEST_F(Getattr_7_8, ok)
240
TEST_F(Getattr_7_8, ok)
Lines 292-300 Link Here
292
	EXPECT_EQ(10ul, sb.st_uid);
289
	EXPECT_EQ(10ul, sb.st_uid);
293
	EXPECT_EQ(11ul, sb.st_gid);
290
	EXPECT_EQ(11ul, sb.st_gid);
294
	EXPECT_EQ(12ul, sb.st_rdev);
291
	EXPECT_EQ(12ul, sb.st_rdev);
292
	/* fusefs should leave birthtime uninitialized */
293
	EXPECT_EQ(-1, sb.st_birthtim.tv_sec);
294
	EXPECT_EQ(0, sb.st_birthtim.tv_nsec);
295
	EXPECT_EQ(ino, sb.st_ino);
295
	EXPECT_EQ(ino, sb.st_ino);
296
	EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
296
	EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
297
298
	//st_birthtim and st_flags are not supported by protocol 7.8.  They're
299
	//only supported as OS-specific extensions to OSX.
300
}
297
}
(-)tests/sys/fs/fusefs/mockfs.cc (+4 lines)
Lines 253-258 Link Here
253
				printf(" mtime=%" PRIu64 ".%u",
253
				printf(" mtime=%" PRIu64 ".%u",
254
					in.body.setattr.mtime,
254
					in.body.setattr.mtime,
255
					in.body.setattr.mtimensec);
255
					in.body.setattr.mtimensec);
256
			if (in.body.setattr.valid & FATTR_CRTIME)
257
				printf(" crtime=%" PRIu64 ".%u",
258
					in.body.setattr.crtime,
259
					in.body.setattr.crtimensec);
256
			if (in.body.setattr.valid & FATTR_FH)
260
			if (in.body.setattr.valid & FATTR_FH)
257
				printf(" fh=%" PRIu64 "", in.body.setattr.fh);
261
				printf(" fh=%" PRIu64 "", in.body.setattr.fh);
258
			break;
262
			break;
(-)tests/sys/fs/fusefs/setattr.cc (-6 / +32 lines)
Lines 565-577 Link Here
565
	const char FULLPATH[] = "mountpoint/some_file.txt";
565
	const char FULLPATH[] = "mountpoint/some_file.txt";
566
	const char RELPATH[] = "some_file.txt";
566
	const char RELPATH[] = "some_file.txt";
567
	const uint64_t ino = 42;
567
	const uint64_t ino = 42;
568
	const timespec oldtimes[2] = {
568
	const timespec newtimes[2] = {
569
		{.tv_sec = 1, .tv_nsec = 2},
569
		{.tv_sec = 1, .tv_nsec = 2},
570
		{.tv_sec = 3, .tv_nsec = 4},
570
		{.tv_sec = 3, .tv_nsec = 4},
571
	};
571
	};
572
	const timespec newtimes[2] = {
572
	const timespec oldtimes[3] = {
573
		{.tv_sec = 5, .tv_nsec = 6},
573
		{.tv_sec = 5, .tv_nsec = 6},
574
		{.tv_sec = 7, .tv_nsec = 8},
574
		{.tv_sec = 7, .tv_nsec = 8},
575
		{.tv_sec = 9, .tv_nsec = 10},
575
	};
576
	};
576
577
577
	EXPECT_LOOKUP(1, RELPATH)
578
	EXPECT_LOOKUP(1, RELPATH)
Lines 584-595 Link Here
584
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
585
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
585
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
586
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
586
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
587
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
588
		out.body.entry.attr.crtime = oldtimes[2].tv_sec;
589
		out.body.entry.attr.crtimensec = oldtimes[2].tv_nsec;
587
	})));
590
	})));
588
591
589
	EXPECT_CALL(*m_mock, process(
592
	EXPECT_CALL(*m_mock, process(
590
		ResultOf([=](auto in) {
593
		ResultOf([=](auto in) {
591
			/* In protocol 7.23, ctime will be changed too */
594
			/* In protocol 7.23, ctime will be changed too */
592
			uint32_t valid = FATTR_ATIME | FATTR_MTIME;
595
			uint32_t valid = FATTR_ATIME | FATTR_MTIME |
596
				FATTR_CRTIME;
593
			return (in.header.opcode == FUSE_SETATTR &&
597
			return (in.header.opcode == FUSE_SETATTR &&
594
				in.header.nodeid == ino &&
598
				in.header.nodeid == ino &&
595
				in.body.setattr.valid == valid &&
599
				in.body.setattr.valid == valid &&
Lines 598-603 Link Here
598
					newtimes[0].tv_nsec &&
602
					newtimes[0].tv_nsec &&
599
				in.body.setattr.mtime == newtimes[1].tv_sec &&
603
				in.body.setattr.mtime == newtimes[1].tv_sec &&
600
				in.body.setattr.mtimensec ==
604
				in.body.setattr.mtimensec ==
605
					newtimes[1].tv_nsec &&
606
				/* 
607
				 * birthtime can't be set directly.  Instead,
608
				 * it's set to the older of the old birthtime
609
				 * and the new mtime
610
				 */
611
				in.body.setattr.crtime == newtimes[1].tv_sec &&
612
				in.body.setattr.crtimensec ==
601
					newtimes[1].tv_nsec);
613
					newtimes[1].tv_nsec);
602
		}, Eq(true)),
614
		}, Eq(true)),
603
		_)
615
		_)
Lines 609-627 Link Here
609
		out.body.attr.attr.atimensec = newtimes[0].tv_nsec;
621
		out.body.attr.attr.atimensec = newtimes[0].tv_nsec;
610
		out.body.attr.attr.mtime = newtimes[1].tv_sec;
622
		out.body.attr.attr.mtime = newtimes[1].tv_sec;
611
		out.body.attr.attr.mtimensec = newtimes[1].tv_nsec;
623
		out.body.attr.attr.mtimensec = newtimes[1].tv_nsec;
624
		out.body.attr.attr.crtime = newtimes[1].tv_sec;
625
		out.body.attr.attr.crtimensec = newtimes[1].tv_nsec;
612
	})));
626
	})));
627
628
	//struct stat sb;
629
	//EXPECT_EQ(0, stat(FULLPATH, &sb));
630
	//printf("atime=%ld.%ld\t", sb.st_atim.tv_sec, sb.st_atim.tv_nsec);
631
	//printf("mtime=%ld.%ld\t", sb.st_mtim.tv_sec, sb.st_mtim.tv_nsec);
632
	//printf("birthtime=%ld.%ld\n", sb.st_birthtim.tv_sec, sb.st_birthtim.tv_nsec);
613
	EXPECT_EQ(0, utimensat(AT_FDCWD, FULLPATH, &newtimes[0], 0))
633
	EXPECT_EQ(0, utimensat(AT_FDCWD, FULLPATH, &newtimes[0], 0))
614
		<< strerror(errno);
634
		<< strerror(errno);
615
}
635
}
616
636
617
/* Change a file mtime but not its atime */
637
/* Change a file's mtime but not its atime */
618
TEST_F(Setattr, utimensat_mtime_only) {
638
TEST_F(Setattr, utimensat_mtime_only) {
619
	const char FULLPATH[] = "mountpoint/some_file.txt";
639
	const char FULLPATH[] = "mountpoint/some_file.txt";
620
	const char RELPATH[] = "some_file.txt";
640
	const char RELPATH[] = "some_file.txt";
621
	const uint64_t ino = 42;
641
	const uint64_t ino = 42;
622
	const timespec oldtimes[2] = {
642
	const timespec oldtimes[3] = {
623
		{.tv_sec = 1, .tv_nsec = 2},
643
		{.tv_sec = 1, .tv_nsec = 2},
624
		{.tv_sec = 3, .tv_nsec = 4},
644
		{.tv_sec = 3, .tv_nsec = 4},
645
		{.tv_sec = 1, .tv_nsec = 1},
625
	};
646
	};
626
	const timespec newtimes[2] = {
647
	const timespec newtimes[2] = {
627
		{.tv_sec = 5, .tv_nsec = UTIME_OMIT},
648
		{.tv_sec = 5, .tv_nsec = UTIME_OMIT},
Lines 638-643 Link Here
638
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
659
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
639
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
660
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
640
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
661
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
662
		out.body.entry.attr.crtime = oldtimes[2].tv_sec;
663
		out.body.entry.attr.crtimensec = oldtimes[2].tv_nsec;
641
	})));
664
	})));
642
665
643
	EXPECT_CALL(*m_mock, process(
666
	EXPECT_CALL(*m_mock, process(
Lines 675-683 Link Here
675
	const char FULLPATH[] = "mountpoint/some_file.txt";
698
	const char FULLPATH[] = "mountpoint/some_file.txt";
676
	const char RELPATH[] = "some_file.txt";
699
	const char RELPATH[] = "some_file.txt";
677
	const uint64_t ino = 42;
700
	const uint64_t ino = 42;
678
	const timespec oldtimes[2] = {
701
	const timespec oldtimes[3] = {
679
		{.tv_sec = 1, .tv_nsec = 2},
702
		{.tv_sec = 1, .tv_nsec = 2},
680
		{.tv_sec = 3, .tv_nsec = 4},
703
		{.tv_sec = 3, .tv_nsec = 4},
704
		{.tv_sec = 5, .tv_nsec = 6},
681
	};
705
	};
682
	const timespec newtimes[2] = {
706
	const timespec newtimes[2] = {
683
		{.tv_sec = 0, .tv_nsec = UTIME_NOW},
707
		{.tv_sec = 0, .tv_nsec = UTIME_NOW},
Lines 701-706 Link Here
701
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
725
		out.body.entry.attr.atimensec = oldtimes[0].tv_nsec;
702
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
726
		out.body.entry.attr.mtime = oldtimes[1].tv_sec;
703
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
727
		out.body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
728
		out.body.entry.attr.crtime = oldtimes[2].tv_sec;
729
		out.body.entry.attr.crtimensec = oldtimes[2].tv_nsec;
704
	})));
730
	})));
705
731
706
	EXPECT_CALL(*m_mock, process(
732
	EXPECT_CALL(*m_mock, process(

Return to bug 238197