Bug 1739437 - nfs client gets bad ctime for copied file which is on glusterfs disperse volume with ctime on
Summary: nfs client gets bad ctime for copied file which is on glusterfs disperse volu...
Keywords:
Status: CLOSED NEXTRELEASE
Alias: None
Product: GlusterFS
Classification: Community
Component: ctime
Version: 7
Hardware: Unspecified
OS: Unspecified
medium
high
Target Milestone: ---
Assignee: Kotresh HR
QA Contact:
URL:
Whiteboard:
Depends On: 1737288
Blocks: 1737705 1737746
TreeView+ depends on / blocked
 
Reported: 2019-08-09 10:16 UTC by Kotresh HR
Modified: 2019-08-19 11:28 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of: 1737288
Environment:
Last Closed: 2019-08-19 11:28:08 UTC
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:


Attachments (Terms of Use)


Links
System ID Priority Status Summary Last Updated
Gluster.org Gerrit 23196 None Merged features/utime: always update ctime at setattr 2019-08-19 11:28:07 UTC

Description Kotresh HR 2019-08-09 10:16:56 UTC
+++ This bug was initially created as a clone of Bug #1737288 +++

Description of problem:

I have a 4+2 disperse volume with ctime on, and export a dir from nfs-ganesha,

storage.ctime: on
features.utime: on

When I copy a local file to nfs client, stat shows bad ctime for the file.

# stat /mnt/nfs/test*
  File: ‘/mnt/nfs/test1.sh’
  Size: 166             Blocks: 4          IO Block: 1048576 regular file
Device: 27h/39d Inode: 10744358902712050257  Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-08-05 09:49:00.000000000 +0800
Modify: 2019-08-05 09:49:00.000000000 +0800
Change: 2061-07-23 21:54:08.000000000 +0800
 Birth: -
  File: ‘/mnt/nfs/test2.sh’
  Size: 214             Blocks: 4          IO Block: 1048576 regular file
Device: 27h/39d Inode: 12073556847735387788  Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-08-05 09:49:00.000000000 +0800
Modify: 2019-08-05 09:49:00.000000000 +0800
Change: 2061-07-23 21:54:08.000000000 +0800
 Birth: -

# ps a
342188 pts/0    D+     0:00 cp -i test1.sh test2.sh /mnt/nfs/

# gdb glusterfsd
(gdb) p *stbuf
$1 = {ia_flags = 0, ia_ino = 0, ia_dev = 0, ia_rdev = 0, ia_size = 0,
  ia_nlink = 0, ia_uid = 0, ia_gid = 0, ia_blksize = 0, ia_blocks = 0,
  ia_atime = 174138658, ia_mtime = 2889352448, ia_ctime = 0, ia_btime = 0,
  ia_atime_nsec = 0, ia_mtime_nsec = 0, ia_ctime_nsec = 0, ia_btime_nsec = 0,
  ia_attributes = 0, ia_attributes_mask = 0,
  ia_gfid = '\000' <repeats 15 times>, ia_type = IA_INVAL, ia_prot = {
    suid = 0 '\000', sgid = 0 '\000', sticky = 0 '\000', owner = {
      read = 0 '\000', write = 0 '\000', exec = 0 '\000'}, group = {
      read = 0 '\000', write = 0 '\000', exec = 0 '\000'}, other = {
      read = 0 '\000', write = 0 '\000', exec = 0 '\000'}}}

It is caused by nfs client create the copied file as EXCLUSIVE mode which
set a verifier, the verifier is set to file's atime and mtime.

nfs client set the verifier as, 

        if (flags & O_EXCL) {
                data->arg.create.createmode  = NFS3_CREATE_EXCLUSIVE;
                data->arg.create.verifier[0] = cpu_to_be32(jiffies);
                data->arg.create.verifier[1] = cpu_to_be32(current->pid);
        }
the verifier[0] is set to file's atime, and verifier[1] is set to mtime.

But utime at storage/posix set the mtime to ctime too at setattr and set ctime to a earlier time is not allowed. 

        /* Earlier, mdata was updated only if the existing time is less
         * than the time to be updated. This would fail the scenarios
         * where mtime can be set to any time using the syscall. Hence
         * just updating without comparison. But the ctime is not
         * allowed to changed to older date.
         */

The following codes is used to find those PIDs which may cause a bad ctime for a copied file.

==========================================================================
#include <stdio.h>
#include <stdlib.h>

int swap_endian(int val){
        val = ((val << 8)&0xFF00FF00) | ((val >> 8)&0x00FF00FF);
        return (val << 16)|(val >> 16);
}

// time of 2020/01/01 0:0:0
#define TO2020 1577808000

int main(int argc, char **argv)
{
        unsigned int i = 0, val = 0;
        for (i = 0; i < 500000; i++) {
                val = swap_endian(i);
                if (val > TO2020)
                        printf("%u %u\n", i, val);
        }
        return 0;
}

--- Additional comment from Worker Ant on 2019-08-05 03:18:00 UTC ---

REVIEW: https://review.gluster.org/23154 (features/utime: always update ctime at setattr) posted (#1) for review on master by Kinglong Mee

--- Additional comment from Worker Ant on 2019-08-06 06:06:15 UTC ---

REVIEW: https://review.gluster.org/23154 (features/utime: always update ctime at setattr) merged (#2) on master by Kotresh HR

Comment 1 Worker Ant 2019-08-09 10:22:28 UTC
REVIEW: https://review.gluster.org/23196 (features/utime: always update ctime at setattr) posted (#1) for review on release-7 by Kotresh HR

Comment 2 Worker Ant 2019-08-19 11:28:08 UTC
REVIEW: https://review.gluster.org/23196 (features/utime: always update ctime at setattr) merged (#2) on release-7 by Rinku Kothiya


Note You need to log in before you can comment on or make changes to this bug.