Commit 7a932516 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-timespec64' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground

Pull inode timestamps conversion to timespec64 from Arnd Bergmann:
 "This is a late set of changes from Deepa Dinamani doing an automated
  treewide conversion of the inode and iattr structures from 'timespec'
  to 'timespec64', to push the conversion from the VFS layer into the
  individual file systems.

  As Deepa writes:

   'The series aims to switch vfs timestamps to use struct timespec64.
    Currently vfs uses struct timespec, which is not y2038 safe.

    The series involves the following:
    1. Add vfs helper functions for supporting struct timepec64
       timestamps.
    2. Cast prints of vfs timestamps to avoid warnings after the switch.
    3. Simplify code using vfs timestamps so that the actual replacement
       becomes easy.
    4. Convert vfs timestamps to use struct timespec64 using a script.
       This is a flag day patch.

    Next steps:
    1. Convert APIs that can handle timespec64, instead of converting
       timestamps at the boundaries.
    2. Update internal data structures to avoid timestamp conversions'

  Thomas Gleixner adds:

   'I think there is no point to drag that out for the next merge
    window. The whole thing needs to be done in one go for the core
    changes which means that you're going to play that catchup game
    forever. Let's get over with it towards the end of the merge window'"

* tag 'vfs-timespec64' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground:
  pstore: Remove bogus format string definition
  vfs: change inode times to use struct timespec64
  pstore: Convert internal records to timespec64
  udf: Simplify calls to udf_disk_stamp_to_time
  fs: nfs: get rid of memcpys for inode times
  ceph: make inode time prints to be long long
  lustre: Use long long type to print inode time
  fs: add timespec64_truncate()
parents dc594c39 e264abea
......@@ -28,10 +28,9 @@ static int efi_pstore_close(struct pstore_info *psi)
return 0;
}
static inline u64 generic_id(unsigned long timestamp,
unsigned int part, int count)
static inline u64 generic_id(u64 timestamp, unsigned int part, int count)
{
return ((u64) timestamp * 100 + part) * 1000 + count;
return (timestamp * 100 + part) * 1000 + count;
}
static int efi_pstore_read_func(struct efivar_entry *entry,
......@@ -42,7 +41,8 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
int i;
int cnt;
unsigned int part;
unsigned long time, size;
unsigned long size;
u64 time;
if (efi_guidcmp(entry->var.VendorGuid, vendor))
return 0;
......@@ -50,7 +50,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
for (i = 0; i < DUMP_NAME_LEN; i++)
name[i] = entry->var.VariableName[i];
if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
if (sscanf(name, "dump-type%u-%u-%d-%llu-%c",
&record->type, &part, &cnt, &time, &data_type) == 5) {
record->id = generic_id(time, part, cnt);
record->part = part;
......@@ -62,7 +62,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
else
record->compressed = false;
record->ecc_notice_size = 0;
} else if (sscanf(name, "dump-type%u-%u-%d-%lu",
} else if (sscanf(name, "dump-type%u-%u-%d-%llu",
&record->type, &part, &cnt, &time) == 4) {
record->id = generic_id(time, part, cnt);
record->part = part;
......@@ -71,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
record->time.tv_nsec = 0;
record->compressed = false;
record->ecc_notice_size = 0;
} else if (sscanf(name, "dump-type%u-%u-%lu",
} else if (sscanf(name, "dump-type%u-%u-%llu",
&record->type, &part, &time) == 3) {
/*
* Check if an old format,
......@@ -250,9 +250,10 @@ static int efi_pstore_write(struct pstore_record *record)
/* Since we copy the entire length of name, make sure it is wiped. */
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c",
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c",
record->type, record->part, record->count,
record->time.tv_sec, record->compressed ? 'C' : 'D');
(long long)record->time.tv_sec,
record->compressed ? 'C' : 'D');
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
......@@ -327,15 +328,15 @@ static int efi_pstore_erase(struct pstore_record *record)
char name[DUMP_NAME_LEN];
int ret;
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu",
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld",
record->type, record->part, record->count,
record->time.tv_sec);
(long long)record->time.tv_sec);
ret = efi_pstore_erase_name(name);
if (ret != -ENOENT)
return ret;
snprintf(name, sizeof(name), "dump-type%u-%u-%lu",
record->type, record->part, record->time.tv_sec);
snprintf(name, sizeof(name), "dump-type%u-%u-%lld",
record->type, record->part, (long long)record->time.tv_sec);
ret = efi_pstore_erase_name(name);
return ret;
......
......@@ -867,8 +867,13 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
i = -EIO;
tty_ldisc_deref(ld);
if (i > 0)
tty_update_time(&inode->i_atime);
if (i > 0) {
struct timespec ts;
ts = timespec64_to_timespec(inode->i_atime);
tty_update_time(&ts);
inode->i_atime = timespec_to_timespec64(ts);
}
return i;
}
......@@ -969,7 +974,11 @@ static inline ssize_t do_tty_write(
cond_resched();
}
if (written) {
tty_update_time(&file_inode(file)->i_mtime);
struct timespec ts;
ts = timespec64_to_timespec(file_inode(file)->i_mtime);
tty_update_time(&ts);
file_inode(file)->i_mtime = timespec_to_timespec64(ts);
ret = written;
}
out:
......
......@@ -1308,7 +1308,7 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
inode = new_inode(sb);
if (likely(inode)) {
struct timespec ts = current_time(inode);
struct timespec64 ts = current_time(inode);
inode->i_ino = get_next_ino();
inode->i_mode = perms->mode;
......
......@@ -199,7 +199,7 @@ adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
return;
cur_time:
*tv = current_time(inode);
*tv = timespec64_to_timespec(current_time(inode));
return;
too_early:
......@@ -242,6 +242,7 @@ adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
struct inode *
adfs_iget(struct super_block *sb, struct object_info *obj)
{
struct timespec ts;
struct inode *inode;
inode = new_inode(sb);
......@@ -270,7 +271,9 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
inode->i_mode = adfs_atts2mode(sb, inode);
adfs_adfs2unix_time(&inode->i_mtime, inode);
ts = timespec64_to_timespec(inode->i_mtime);
adfs_adfs2unix_time(&ts, inode);
inode->i_mtime = timespec_to_timespec64(ts);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
......
......@@ -72,7 +72,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode,
const afs_dataversion_t *expected_version,
u8 flags)
{
struct timespec t;
struct timespec64 t;
umode_t mode;
t.tv_sec = status->mtime_client;
......
......@@ -183,14 +183,14 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
inode->i_atime = timespec_trunc(attr->ia_atime,
inode->i_sb->s_time_gran);
inode->i_atime = timespec64_trunc(attr->ia_atime,
inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
inode->i_mtime = timespec_trunc(attr->ia_mtime,
inode->i_sb->s_time_gran);
inode->i_mtime = timespec64_trunc(attr->ia_mtime,
inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
inode->i_ctime = timespec_trunc(attr->ia_ctime,
inode->i_sb->s_time_gran);
inode->i_ctime = timespec64_trunc(attr->ia_ctime,
inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
......@@ -227,7 +227,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
int error;
struct timespec now;
struct timespec64 now;
unsigned int ia_valid = attr->ia_valid;
WARN_ON_ONCE(!inode_is_locked(inode));
......
......@@ -126,7 +126,7 @@ static int bad_inode_fiemap(struct inode *inode,
return -EIO;
}
static int bad_inode_update_time(struct inode *inode, struct timespec *time,
static int bad_inode_update_time(struct inode *inode, struct timespec64 *time,
int flags)
{
return -EIO;
......
......@@ -1842,16 +1842,16 @@ out:
static void update_time_for_write(struct inode *inode)
{
struct timespec now;
struct timespec64 now;
if (IS_NOCMTIME(inode))
return;
now = current_time(inode);
if (!timespec_equal(&inode->i_mtime, &now))
if (!timespec64_equal(&inode->i_mtime, &now))
inode->i_mtime = now;
if (!timespec_equal(&inode->i_ctime, &now))
if (!timespec64_equal(&inode->i_ctime, &now))
inode->i_ctime = now;
if (IS_I_VERSION(inode))
......
......@@ -5745,7 +5745,7 @@ static struct inode *new_simple_dir(struct super_block *s,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
BTRFS_I(inode)->i_otime = inode->i_mtime;
BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
return inode;
}
......@@ -6094,7 +6094,7 @@ static int btrfs_dirty_inode(struct inode *inode)
* This is a copy of file_update_time. We need this so we can return error on
* ENOSPC for updating the inode in the case of file write and mmap writes.
*/
static int btrfs_update_time(struct inode *inode, struct timespec *now,
static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
int flags)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
......@@ -6349,7 +6349,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
BTRFS_I(inode)->i_otime = inode->i_mtime;
BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_inode_item);
......@@ -9435,7 +9435,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
struct btrfs_root *dest = BTRFS_I(new_dir)->root;
struct inode *new_inode = new_dentry->d_inode;
struct inode *old_inode = old_dentry->d_inode;
struct timespec ctime = current_time(old_inode);
struct timespec64 ctime = current_time(old_inode);
struct dentry *parent;
u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
......
......@@ -562,7 +562,7 @@ static noinline int create_subvol(struct inode *dir,
struct btrfs_root *root = BTRFS_I(dir)->root;
struct btrfs_root *new_root;
struct btrfs_block_rsv block_rsv;
struct timespec cur_time = current_time(dir);
struct timespec64 cur_time = current_time(dir);
struct inode *inode;
int ret;
int err;
......@@ -5395,7 +5395,7 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_root_item *root_item = &root->root_item;
struct btrfs_trans_handle *trans;
struct timespec ct = current_time(inode);
struct timespec64 ct = current_time(inode);
int ret = 0;
int received_uuid_changed;
......
......@@ -485,9 +485,9 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_root_item *item = &root->root_item;
struct timespec ct;
struct timespec64 ct;
ktime_get_real_ts(&ct);
ktime_get_real_ts64(&ct);
spin_lock(&root->root_item_lock);
btrfs_set_root_ctransid(item, trans->transid);
btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
......
......@@ -1422,7 +1422,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
struct dentry *dentry;
struct extent_buffer *tmp;
struct extent_buffer *old;
struct timespec cur_time;
struct timespec64 cur_time;
int ret = 0;
u64 to_reserve = 0;
u64 index = 0;
......
......@@ -574,6 +574,7 @@ static u64 get_writepages_data_length(struct inode *inode,
*/
static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
{
struct timespec ts;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_fs_client *fsc;
......@@ -624,11 +625,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC);
set_page_writeback(page);
ts = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_writepages(&fsc->client->osdc, ceph_vino(inode),
&ci->i_layout, snapc, page_off, len,
ceph_wbc.truncate_seq,
ceph_wbc.truncate_size,
&inode->i_mtime, &page, 1);
&ts, &page, 1);
if (err < 0) {
struct writeback_control tmp_wbc;
if (!wbc)
......@@ -1132,7 +1134,7 @@ new_request:
pages = NULL;
}
req->r_mtime = inode->i_mtime;
req->r_mtime = timespec64_to_timespec(inode->i_mtime);
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
BUG_ON(rc);
req = NULL;
......@@ -1732,7 +1734,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out;
}
req->r_mtime = inode->i_mtime;
req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
......@@ -1774,7 +1776,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out_put;
}
req->r_mtime = inode->i_mtime;
req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
......@@ -1935,7 +1937,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
0, false, true);
err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
wr_req->r_mtime = ci->vfs_inode.i_mtime;
wr_req->r_mtime = timespec64_to_timespec(ci->vfs_inode.i_mtime);
err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
if (!err)
......
......@@ -130,7 +130,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
aux.mtime = inode->i_mtime;
aux.mtime = timespec64_to_timespec(inode->i_mtime);
if (memcmp(data, &aux, sizeof(aux)) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
......@@ -163,7 +163,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
if (!ci->fscache) {
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
aux.mtime = inode->i_mtime;
aux.mtime = timespec64_to_timespec(inode->i_mtime);
ci->fscache = fscache_acquire_cookie(fsc->fscache,
&ceph_fscache_inode_object_def,
&ci->i_vino, sizeof(ci->i_vino),
......
......@@ -1360,9 +1360,9 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
arg.xattr_buf = NULL;
}
arg.mtime = inode->i_mtime;
arg.atime = inode->i_atime;
arg.ctime = inode->i_ctime;
arg.mtime = timespec64_to_timespec(inode->i_mtime);
arg.atime = timespec64_to_timespec(inode->i_atime);
arg.ctime = timespec64_to_timespec(inode->i_ctime);
arg.op = op;
arg.caps = cap->implemented;
......
......@@ -923,7 +923,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int num_pages = 0;
int flags;
int ret;
struct timespec mtime = current_time(inode);
struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(iter);
loff_t pos = iocb->ki_pos;
bool write = iov_iter_rw(iter) == WRITE;
......@@ -1131,7 +1131,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
int flags;
int ret;
bool check_caps = false;
struct timespec mtime = current_time(inode);
struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(from);
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
......@@ -1663,7 +1663,7 @@ static int ceph_zero_partial_object(struct inode *inode,
goto out;
}
req->r_mtime = inode->i_mtime;
req->r_mtime = timespec64_to_timespec(inode->i_mtime);
ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!ret) {
ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
......
......@@ -662,6 +662,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
struct timespec *mtime, struct timespec *atime)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct timespec64 ctime64 = timespec_to_timespec64(*ctime);
struct timespec64 mtime64 = timespec_to_timespec64(*mtime);
struct timespec64 atime64 = timespec_to_timespec64(*atime);
int warn = 0;
if (issued & (CEPH_CAP_FILE_EXCL|
......@@ -670,39 +673,39 @@ void ceph_fill_file_time(struct inode *inode, int issued,
CEPH_CAP_AUTH_EXCL|
CEPH_CAP_XATTR_EXCL)) {
if (ci->i_version == 0 ||
timespec_compare(ctime, &inode->i_ctime) > 0) {
dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
ctime->tv_sec, ctime->tv_nsec);
inode->i_ctime = *ctime;
timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
(long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
(long long)ctime->tv_sec, ctime->tv_nsec);
inode->i_ctime = ctime64;
}
if (ci->i_version == 0 ||
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
dout("mtime %ld.%09ld -> %ld.%09ld "
dout("mtime %lld.%09ld -> %lld.%09ld "
"tw %d -> %d\n",
inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
mtime->tv_sec, mtime->tv_nsec,
(long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
(long long)mtime->tv_sec, mtime->tv_nsec,
ci->i_time_warp_seq, (int)time_warp_seq);
inode->i_mtime = *mtime;
inode->i_atime = *atime;
inode->i_mtime = mtime64;
inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else if (time_warp_seq == ci->i_time_warp_seq) {
/* nobody did utimes(); take the max */
if (timespec_compare(mtime, &inode->i_mtime) > 0) {
dout("mtime %ld.%09ld -> %ld.%09ld inc\n",
inode->i_mtime.tv_sec,
if (timespec64_compare(&mtime64, &inode->i_mtime) > 0) {
dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
(long long)inode->i_mtime.tv_sec,
inode->i_mtime.tv_nsec,
mtime->tv_sec, mtime->tv_nsec);
inode->i_mtime = *mtime;
(long long)mtime->tv_sec, mtime->tv_nsec);
inode->i_mtime = mtime64;
}
if (timespec_compare(atime, &inode->i_atime) > 0) {
dout("atime %ld.%09ld -> %ld.%09ld inc\n",
inode->i_atime.tv_sec,
if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
dout("atime %lld.%09ld -> %lld.%09ld inc\n",
(long long)inode->i_atime.tv_sec,
inode->i_atime.tv_nsec,
atime->tv_sec, atime->tv_nsec);
inode->i_atime = *atime;
(long long)atime->tv_sec, atime->tv_nsec);
inode->i_atime = atime64;
}
} else if (issued & CEPH_CAP_FILE_EXCL) {
/* we did a utimes(); ignore mds values */
......@@ -712,9 +715,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
} else {
/* we have no write|excl caps; whatever the MDS says is true */
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
inode->i_ctime = *ctime;
inode->i_mtime = *mtime;
inode->i_atime = *atime;
inode->i_ctime = ctime64;
inode->i_mtime = mtime64;
inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else {
warn = 1;
......@@ -1950,6 +1953,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
int err = 0;
int inode_dirty_flags = 0;
bool lock_snap_rwsem = false;
struct timespec ts;
prealloc_cf = ceph_alloc_cap_flush();
if (!prealloc_cf)
......@@ -2024,44 +2028,44 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
}
if (ia_valid & ATTR_ATIME) {
dout("setattr %p atime %ld.%ld -> %ld.%ld\n", inode,
inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
(long long)inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
(long long)attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
timespec_compare(&inode->i_atime,
timespec64_compare(&inode->i_atime,
&attr->ia_atime) < 0) {
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
!timespec_equal(&inode->i_atime, &attr->ia_atime)) {
ceph_encode_timespec(&req->r_args.setattr.atime,
&attr->ia_atime);
!timespec64_equal(&inode->i_atime, &attr->ia_atime)) {
ts = timespec64_to_timespec(attr->ia_atime);
ceph_encode_timespec(&req->r_args.setattr.atime, &ts);
mask |= CEPH_SETATTR_ATIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
}
}
if (ia_valid & ATTR_MTIME) {
dout("setattr %p mtime %ld.%ld -> %ld.%ld\n", inode,
inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
(long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
(long long)attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
timespec_compare(&inode->i_mtime,
timespec64_compare(&inode->i_mtime,
&attr->ia_mtime) < 0) {
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
!timespec_equal(&inode->i_mtime, &attr->ia_mtime)) {
ceph_encode_timespec(&req->r_args.setattr.mtime,
&attr->ia_mtime);
!timespec64_equal(&inode->i_mtime, &attr->ia_mtime)) {
ts = timespec64_to_timespec(attr->ia_mtime);
ceph_encode_timespec(&req->r_args.setattr.mtime, &ts);
mask |= CEPH_SETATTR_MTIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
......@@ -2091,9 +2095,9 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
if (ia_valid & ATTR_CTIME) {
bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
dout("setattr %p ctime %ld.%ld -> %ld.%ld (%s)\n", inode,
inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
(long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
(long long)attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
only ? "ctime only" : "ignored");
if (only) {
/*
......@@ -2135,7 +2139,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
req->r_inode_drop = release;
req->r_args.setattr.mask = cpu_to_le32(mask);
req->r_num_caps = 1;
req->r_stamp = attr->ia_ctime;
req->r_stamp = timespec64_to_timespec(attr->ia_ctime);
err = ceph_mdsc_do_request(mdsc, NULL, req);
}
dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
......
......@@ -2958,12 +2958,15 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
rec.v2.flock_len = (__force __le32)
((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
} else {
struct timespec ts;
rec.v1.cap_id = cpu_to_le64(cap->cap_id);
rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
rec.v1.issued = cpu_to_le32(cap->issued);
rec.v1.size = cpu_to_le64(inode->i_size);