Hide Forgot
Additional info: 1 creat("test", 0644) = 3 2 chown("test", 65534, 65533) = 0 3 chmod("test", 06555) = 0 4 setgroups(3, [65533, 65532, 65531]) = 0 5 setuid(65534) = 0 6 chown("test", 65534, 65532) = 0 7 stat("test", {st_dev=makedev(0, 24), st_ino=341999833, st_mode=S_IFREG|0555, st_nlink=1, st_uid=65534, st_gid=65533, st_blksize=4096, st_blocks=8, st_size=0, st_atime=2009/07/15-03:30:00, st_mtime=2009/07/15-03:30:00, st_ctime=2009/07/15-06:38:31}) = 0 8 chown("test", 65534, 65532) = 0 9 stat("test", {st_dev=makedev(0, 24), st_ino=341999833, st_mode=S_IFREG|0555, st_nlink=1, st_uid=65534, st_gid=65532, st_blksize=4096, st_blocks=8, st_size=0, st_atime=2009/07/15-03:30:00, st_mtime=2009/07/15-03:30:00, st_ctime=2009/07/15-06:38:31}) = 0 As you can see, call #6 supposedly succeeded but call #7 still shows gid=65533. Additionally, call #6 does not hit a fuse_setattr breakpoint, but call #8 does.
Following sequence of system calls generated by a C program on a simple-afr mountpoint: 1 creat("test", 0644) = 3 2 chown("test", 65534, 65533) = 0 3 chmod("test", 06555) = 0 4 setgroups(3, [65533, 65532, 65531]) = 0 5 setuid(65534) = 0 6 chown("test", 65534, 65532) = 0 7 chown("test", 65534, 65532) = 0 The mystery is that call #6 never reaches FUSE, whereas call #7 reaches FUSE and completes successfully. C program to generate: #include <unistd.h> #include <sys/types.h> #include <fcntl.h> int main () { char *n0 = "test"; gid_t list[3] = {65533, 65532, 65531}; creat (n0, 0644); chown (n0, 65534, 65533); chmod (n0, 06555); setgroups (3, &list); setuid(65534); chown (n0, 65534, 65532); chown (n0, 65534, 65532); return 0; }
This issue is seen on a simple posix volume setup also.
mysteriously "lost" chown was found to be thrown away by fuse-bridge. reason: assumption in fuse-bridge that fuse_setattr() call that fuse kernel module sends only one of the four attribute setting calls among the following: 1. ownership change - (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID) (chown) 2. mode change - FUSE_SET_ATTR_MODE (chmod) 3. size change - FUSE_SET_ATTR_SIZE (truncate) 4. time change - FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME (utimes) but fuse kernel module can group the modifications to the attribute and send them in one setattr() call to the filesystem (glusterfs, in this case). fix is on the way.
Fix will be by adding setattr() fop to glusterfs. Since fuse kernel module sends a single setattr() for changing file mode as well as ownership (and might also send modifications for times, size in a single setattr call), glusterfs should complete all the ops (chmod, chown, utimes, truncate) before doing fuse_reply() to any of the single call. In glusterfs's model, it take 4 different network calls for a single setattr() sent by fuse kernel module. It can be completed in a single network call, if we implement setattr(), in the same way as all the filesystems (in kernel) implement.
(In reply to comment #4) > Fix will be by adding setattr() fop to glusterfs. > > Since fuse kernel module sends a single setattr() for changing file mode as > well as ownership (and might also send modifications for times, size in a > single setattr call), glusterfs should complete all the ops (chmod, chown, > utimes, truncate) before doing fuse_reply() to any of the single call. > > In glusterfs's model, it take 4 different network calls for a single setattr() > sent by fuse kernel module. It can be completed in a single network call, if we > implement setattr(), in the same way as all the filesystems (in kernel) > implement. Avati suggested that setattr cover only chown, chmod, and utimes, with truncate being a separate call as it is now. This is because: - unify needs to handle truncate separately, in that it shouldn't truncate on the namespace volume. - afr needs to lock different regions of the file for chown/chmod/utimes v/s truncate.
int32_t fop_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct stat *stbuf, int32_t valid); valid can assume one of the following values: GF_SET_ATTR_MODE - stbuf->st_mode is valid and needs to be set on backend GF_SET_ATTR_UID - stbuf->st_uid is valid and needs to be set on backend GF_SET_ATTR_GID - stbuf->st_gid is valid and needs to be set on backend GF_SET_ATTR_SIZE - stbuf->st_size is valid and needs to be set on backend GF_SET_ATTR_ATIME - stbuf->st_atime is valid and needs to be set on backend GF_SET_ATTR_MTIME - stbuf->st_mtime is valid and needs to be set on backend truncate() corresponds to an fop_setattr() call with GF_SET_ATTR_SIZE bit set in 'valid' flag. by checking for the flags in 'valid', any translator can do the specific tasks. for example, cluster/unify can internally call its unify_truncate() when GF_SET_ATTR_SIZE flag is set in 'valid'.