From: Andreas Dilger Date: Fri, 27 Jan 2012 21:12:06 +0000 (-0700) Subject: LU-1042 obdfilter: initialize new object timestamp X-Git-Tag: 2.1.56~23 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=f1deb50672b37a1c87ef5ec93f14ef805e456b2b LU-1042 obdfilter: initialize new object timestamp Initialize newly-created objects with a/m/ctime = 0, so that however clients modify the timestamp it will be updated the first time. The fsfilt_ext3_setattr() code will special case ctime = 0 for new files and reset them to the ext4 s_mkfs_time stored in the superblock. In LU-221 (commit 414251797ed178eec5d431e1f5aa4a889d2b159f) the timestamps were initialized to (INT_MIN + 24 * 3600) (1901-12-14), but the use of unsigned on-disk timestamps caused these negative numbers to be transformed into large positive numbers (debugfs reports them to be "Tue Jan 19 20:14:08 2038"). Add a fix so that files with this exact timestamp have the timestamp reset to 0. Signed-off-by: Andreas Dilger Change-Id: I22f2cd443402c0c524bafaf37c80cad7b6d00c1e Reviewed-on: http://review.whamcloud.com/2036 Reviewed-by: Johann Lombardi Tested-by: Hudson Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre_fsfilt.h b/lustre/include/lustre_fsfilt.h index 48b2bc0..ea7af30 100644 --- a/lustre/include/lustre_fsfilt.h +++ b/lustre/include/lustre_fsfilt.h @@ -51,4 +51,6 @@ #error Unsupported operating system. #endif +#define LU221_BAD_TIME (0x80000000U + 24 * 3600) + #endif diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index 30eed7c..5fbed73 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -581,6 +581,41 @@ static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle, struct inode *inode = dentry->d_inode; int rc = 0; +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0) + /* Try to correct for a bug in 2.1.0 (LU-221) that caused negative + * timestamps to appear to be in the far future, due old timestamp + * being stored on disk as an unsigned value. This fixes up any + * bad values held by the client before storing them on disk, + * and ensures any timestamp updates are correct. LU-1042 */ + if (unlikely(LTIME_S(inode->i_atime) == LU221_BAD_TIME && + !(iattr->ia_valid & ATTR_ATIME))) { + iattr->ia_valid |= ATTR_ATIME; + LTIME_S(iattr->ia_atime) = 0; + } + if (unlikely(LTIME_S(inode->i_mtime) == LU221_BAD_TIME && + !(iattr->ia_valid & ATTR_MTIME))) { + iattr->ia_valid |= ATTR_MTIME; + LTIME_S(iattr->ia_mtime) = 0; + } + if (unlikely((LTIME_S(inode->i_ctime) == LU221_BAD_TIME || + LTIME_S(inode->i_ctime) == 0) && + !(iattr->ia_valid & ATTR_CTIME))) { + iattr->ia_valid |= ATTR_CTIME; + LTIME_S(iattr->ia_ctime) = 0; + } +#else +#warning "remove old LU-221/LU-1042 workaround code" +#endif + + /* When initializating timestamps for new inodes, use the filesystem + * mkfs time for ctime to avoid e2fsck ibadness incorrectly thinking + * that this is potentially an invalid inode. Files with an old ctime + * migrated to a newly-formatted OST with a newer s_mkfs_time will not + * hit this check, since it is only for ctime == 0. LU-1010/LU-1042 */ + if ((iattr->ia_valid & ATTR_CTIME) && LTIME_S(iattr->ia_ctime) == 0) + LTIME_S(iattr->ia_ctime) = + EXT4_SB(inode->i_sb)->s_es->s_mkfs_time; + /* Avoid marking the inode dirty on the superblock list unnecessarily. * We are already writing the inode to disk as part of this * transaction and want to avoid a lot of extra inode writeout diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index f61d613..afbab0b 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -3136,6 +3136,22 @@ struct dentry *__filter_oa2dentry(struct obd_device *obd, struct ost_id *ostid, RETURN(ERR_PTR(-ENOENT)); } +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0) + /* Try to correct for a bug in 2.1.0 (LU-221) that caused negative + * timestamps to appear to be in the far future, due old timestamp + * being stored on disk as an unsigned value. This fixes up any + * bad values stored on disk before returning them to the client, + * and ensures any timestamp updates are correct. LU-1042 */ + if (unlikely(LTIME_S(dchild->d_inode->i_atime) == LU221_BAD_TIME)) + LTIME_S(dchild->d_inode->i_atime) = 0; + if (unlikely(LTIME_S(dchild->d_inode->i_mtime) == LU221_BAD_TIME)) + LTIME_S(dchild->d_inode->i_mtime) = 0; + if (unlikely(LTIME_S(dchild->d_inode->i_ctime) == LU221_BAD_TIME)) + LTIME_S(dchild->d_inode->i_ctime) = 0; +#else +#warning "remove old LU-221/LU-1042 workaround code" +#endif + return dchild; } @@ -3942,23 +3958,23 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa, rc = ll_vfs_create(dparent->d_inode, dchild, S_IFREG | S_ISUID | S_ISGID | 0666, NULL); if (rc) { - CERROR("create failed rc = %d\n", rc); + CWARN("%s: create failed: rc = %d\n", obd->obd_name,rc); if (rc == -ENOSPC) { os_ffree = filter_calc_free_inodes(obd); - if (os_ffree == -1) + if (os_ffree == -1) GOTO(cleanup, rc); if (obd->obd_osfs.os_bavail < (obd->obd_osfs.os_blocks >> 10)) { - if (oa->o_valid & OBD_MD_FLFLAGS) + if (oa->o_valid & OBD_MD_FLFLAGS) { oa->o_flags |= OBD_FL_NOSPC_BLK; - else { + } else { oa->o_valid |= OBD_MD_FLFLAGS; oa->o_flags = OBD_FL_NOSPC_BLK; } - CERROR("%s: free inode "LPU64"\n", - obd->obd_name, os_ffree); + CWARN("%s: free inode "LPU64"\n", + obd->obd_name, os_ffree); } } GOTO(cleanup, rc); @@ -3969,25 +3985,27 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa, dchild->d_inode->i_ino); set_last_id: - /* Set a/c/m time to a insane large negative value at creation - * time so that any timestamp arriving from the client will - * always be newer and update the inode. - * See LU-221 for details */ + /* Initialize a/c/m time so any client timestamp will always + * be newer and update the inode. ctime = 0 is also handled + * specially in fsfilt_ext3_setattr(). See LU-221, LU-1042 */ iattr.ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_CTIME; - LTIME_S(iattr.ia_atime) = INT_MIN + 24 * 3600; - LTIME_S(iattr.ia_mtime) = INT_MIN + 24 * 3600; - LTIME_S(iattr.ia_ctime) = INT_MIN + 24 * 3600; + LTIME_S(iattr.ia_atime) = 0; + LTIME_S(iattr.ia_mtime) = 0; + LTIME_S(iattr.ia_ctime) = 0; err = fsfilt_setattr(obd, dchild, handle, &iattr, 0); - if (err) - CERROR("unable to initialize a/c/m time of newly" - "created inode\n"); + if (err) + CWARN("%s: unable to initialize a/c/m time of newly " + "created object %.*s: rc = %d\n", + obd->obd_name, dchild->d_name.len, + dchild->d_name.name, err); if (!recreate_obj) { filter_set_last_id(filter, next_id, group); err = filter_update_last_objid(obd, group, 0); if (err) - CERROR("unable to write lastobjid " - "but file created\n"); + CERROR("%s: unable to write lastobjid " + "but file created: rc = %d\n", + obd->obd_name, err); } cleanup: