95582b0083
struct timespec is not y2038 safe. Transition vfs to use y2038 safe struct timespec64 instead. The change was made with the help of the following cocinelle script. This catches about 80% of the changes. All the header file and logic changes are included in the first 5 rules. The rest are trivial substitutions. I avoid changing any of the function signatures or any other filesystem specific data structures to keep the patch simple for review. The script can be a little shorter by combining different cases. But, this version was sufficient for my usecase. virtual patch @ depends on patch @ identifier now; @@ - struct timespec + struct timespec64 current_time ( ... ) { - struct timespec now = current_kernel_time(); + struct timespec64 now = current_kernel_time64(); ... - return timespec_trunc( + return timespec64_trunc( ... ); } @ depends on patch @ identifier xtime; @@ struct \( iattr \| inode \| kstat \) { ... - struct timespec xtime; + struct timespec64 xtime; ... } @ depends on patch @ identifier t; @@ struct inode_operations { ... int (*update_time) (..., - struct timespec t, + struct timespec64 t, ...); ... } @ depends on patch @ identifier t; identifier fn_update_time =~ "update_time$"; @@ fn_update_time (..., - struct timespec *t, + struct timespec64 *t, ...) { ... } @ depends on patch @ identifier t; @@ lease_get_mtime( ... , - struct timespec *t + struct timespec64 *t ) { ... } @te depends on patch forall@ identifier ts; local idexpression struct inode *inode_node; identifier i_xtime =~ "^i_[acm]time$"; identifier ia_xtime =~ "^ia_[acm]time$"; identifier fn_update_time =~ "update_time$"; identifier fn; expression e, E3; local idexpression struct inode *node1; local idexpression struct inode *node2; local idexpression struct iattr *attr1; local idexpression struct iattr *attr2; local idexpression struct iattr attr; identifier i_xtime1 =~ "^i_[acm]time$"; identifier i_xtime2 =~ "^i_[acm]time$"; identifier ia_xtime1 =~ "^ia_[acm]time$"; identifier ia_xtime2 =~ "^ia_[acm]time$"; @@ ( ( - struct timespec ts; + struct timespec64 ts; | - struct timespec ts = current_time(inode_node); + struct timespec64 ts = current_time(inode_node); ) <+... when != ts ( - timespec_equal(&inode_node->i_xtime, &ts) + timespec64_equal(&inode_node->i_xtime, &ts) | - timespec_equal(&ts, &inode_node->i_xtime) + timespec64_equal(&ts, &inode_node->i_xtime) | - timespec_compare(&inode_node->i_xtime, &ts) + timespec64_compare(&inode_node->i_xtime, &ts) | - timespec_compare(&ts, &inode_node->i_xtime) + timespec64_compare(&ts, &inode_node->i_xtime) | ts = current_time(e) | fn_update_time(..., &ts,...) | inode_node->i_xtime = ts | node1->i_xtime = ts | ts = inode_node->i_xtime | <+... attr1->ia_xtime ...+> = ts | ts = attr1->ia_xtime | ts.tv_sec | ts.tv_nsec | btrfs_set_stack_timespec_sec(..., ts.tv_sec) | btrfs_set_stack_timespec_nsec(..., ts.tv_nsec) | - ts = timespec64_to_timespec( + ts = ... -) | - ts = ktime_to_timespec( + ts = ktime_to_timespec64( ...) | - ts = E3 + ts = timespec_to_timespec64(E3) | - ktime_get_real_ts(&ts) + ktime_get_real_ts64(&ts) | fn(..., - ts + timespec64_to_timespec(ts) ,...) ) ...+> ( <... when != ts - return ts; + return timespec64_to_timespec(ts); ...> ) | - timespec_equal(&node1->i_xtime1, &node2->i_xtime2) + timespec64_equal(&node1->i_xtime2, &node2->i_xtime2) | - timespec_equal(&node1->i_xtime1, &attr2->ia_xtime2) + timespec64_equal(&node1->i_xtime2, &attr2->ia_xtime2) | - timespec_compare(&node1->i_xtime1, &node2->i_xtime2) + timespec64_compare(&node1->i_xtime1, &node2->i_xtime2) | node1->i_xtime1 = - timespec_trunc(attr1->ia_xtime1, + timespec64_trunc(attr1->ia_xtime1, ...) | - attr1->ia_xtime1 = timespec_trunc(attr2->ia_xtime2, + attr1->ia_xtime1 = timespec64_trunc(attr2->ia_xtime2, ...) | - ktime_get_real_ts(&attr1->ia_xtime1) + ktime_get_real_ts64(&attr1->ia_xtime1) | - ktime_get_real_ts(&attr.ia_xtime1) + ktime_get_real_ts64(&attr.ia_xtime1) ) @ depends on patch @ struct inode *node; struct iattr *attr; identifier fn; identifier i_xtime =~ "^i_[acm]time$"; identifier ia_xtime =~ "^ia_[acm]time$"; expression e; @@ ( - fn(node->i_xtime); + fn(timespec64_to_timespec(node->i_xtime)); | fn(..., - node->i_xtime); + timespec64_to_timespec(node->i_xtime)); | - e = fn(attr->ia_xtime); + e = fn(timespec64_to_timespec(attr->ia_xtime)); ) @ depends on patch forall @ struct inode *node; struct iattr *attr; identifier i_xtime =~ "^i_[acm]time$"; identifier ia_xtime =~ "^ia_[acm]time$"; identifier fn; @@ { + struct timespec ts; <+... ( + ts = timespec64_to_timespec(node->i_xtime); fn (..., - &node->i_xtime, + &ts, ...); | + ts = timespec64_to_timespec(attr->ia_xtime); fn (..., - &attr->ia_xtime, + &ts, ...); ) ...+> } @ depends on patch forall @ struct inode *node; struct iattr *attr; struct kstat *stat; identifier ia_xtime =~ "^ia_[acm]time$"; identifier i_xtime =~ "^i_[acm]time$"; identifier xtime =~ "^[acm]time$"; identifier fn, ret; @@ { + struct timespec ts; <+... ( + ts = timespec64_to_timespec(node->i_xtime); ret = fn (..., - &node->i_xtime, + &ts, ...); | + ts = timespec64_to_timespec(node->i_xtime); ret = fn (..., - &node->i_xtime); + &ts); | + ts = timespec64_to_timespec(attr->ia_xtime); ret = fn (..., - &attr->ia_xtime, + &ts, ...); | + ts = timespec64_to_timespec(attr->ia_xtime); ret = fn (..., - &attr->ia_xtime); + &ts); | + ts = timespec64_to_timespec(stat->xtime); ret = fn (..., - &stat->xtime); + &ts); ) ...+> } @ depends on patch @ struct inode *node; struct inode *node2; identifier i_xtime1 =~ "^i_[acm]time$"; identifier i_xtime2 =~ "^i_[acm]time$"; identifier i_xtime3 =~ "^i_[acm]time$"; struct iattr *attrp; struct iattr *attrp2; struct iattr attr ; identifier ia_xtime1 =~ "^ia_[acm]time$"; identifier ia_xtime2 =~ "^ia_[acm]time$"; struct kstat *stat; struct kstat stat1; struct timespec64 ts; identifier xtime =~ "^[acmb]time$"; expression e; @@ ( ( node->i_xtime2 \| attrp->ia_xtime2 \| attr.ia_xtime2 \) = node->i_xtime1 ; | node->i_xtime2 = \( node2->i_xtime1 \| timespec64_trunc(...) \); | node->i_xtime2 = node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \); | node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \); | stat->xtime = node2->i_xtime1; | stat1.xtime = node2->i_xtime1; | ( node->i_xtime2 \| attrp->ia_xtime2 \) = attrp->ia_xtime1 ; | ( attrp->ia_xtime1 \| attr.ia_xtime1 \) = attrp2->ia_xtime2; | - e = node->i_xtime1; + e = timespec64_to_timespec( node->i_xtime1 ); | - e = attrp->ia_xtime1; + e = timespec64_to_timespec( attrp->ia_xtime1 ); | node->i_xtime1 = current_time(...); | node->i_xtime2 = node->i_xtime1 = node->i_xtime3 = - e; + timespec_to_timespec64(e); | node->i_xtime1 = node->i_xtime3 = - e; + timespec_to_timespec64(e); | - node->i_xtime1 = e; + node->i_xtime1 = timespec_to_timespec64(e); ) Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com> Cc: <anton@tuxera.com> Cc: <balbi@kernel.org> Cc: <bfields@fieldses.org> Cc: <darrick.wong@oracle.com> Cc: <dhowells@redhat.com> Cc: <dsterba@suse.com> Cc: <dwmw2@infradead.org> Cc: <hch@lst.de> Cc: <hirofumi@mail.parknet.co.jp> Cc: <hubcap@omnibond.com> Cc: <jack@suse.com> Cc: <jaegeuk@kernel.org> Cc: <jaharkes@cs.cmu.edu> Cc: <jslaby@suse.com> Cc: <keescook@chromium.org> Cc: <mark@fasheh.com> Cc: <miklos@szeredi.hu> Cc: <nico@linaro.org> Cc: <reiserfs-devel@vger.kernel.org> Cc: <richard@nod.at> Cc: <sage@redhat.com> Cc: <sfrench@samba.org> Cc: <swhiteho@redhat.com> Cc: <tj@kernel.org> Cc: <trond.myklebust@primarydata.com> Cc: <tytso@mit.edu> Cc: <viro@zeniv.linux.org.uk>
187 lines
5.1 KiB
C
187 lines
5.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Inode operations for Coda filesystem
|
|
* Original version: (C) 1996 P. Braam and M. Callahan
|
|
* Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
|
|
*
|
|
* Carnegie Mellon encourages users to contribute improvements to
|
|
* the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/time.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/coda.h>
|
|
#include <linux/coda_psdev.h>
|
|
#include "coda_linux.h"
|
|
|
|
/* initialize the debugging variables */
|
|
int coda_fake_statfs;
|
|
|
|
/* print a fid */
|
|
char * coda_f2s(struct CodaFid *f)
|
|
{
|
|
static char s[60];
|
|
|
|
sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
|
|
|
|
return s;
|
|
}
|
|
|
|
/* recognize special .CONTROL name */
|
|
int coda_iscontrol(const char *name, size_t length)
|
|
{
|
|
return ((CODA_CONTROLLEN == length) &&
|
|
(strncmp(name, CODA_CONTROL, CODA_CONTROLLEN) == 0));
|
|
}
|
|
|
|
unsigned short coda_flags_to_cflags(unsigned short flags)
|
|
{
|
|
unsigned short coda_flags = 0;
|
|
|
|
if ((flags & O_ACCMODE) == O_RDONLY)
|
|
coda_flags |= C_O_READ;
|
|
|
|
if ((flags & O_ACCMODE) == O_RDWR)
|
|
coda_flags |= C_O_READ | C_O_WRITE;
|
|
|
|
if ((flags & O_ACCMODE) == O_WRONLY)
|
|
coda_flags |= C_O_WRITE;
|
|
|
|
if (flags & O_TRUNC)
|
|
coda_flags |= C_O_TRUNC;
|
|
|
|
if (flags & O_CREAT)
|
|
coda_flags |= C_O_CREAT;
|
|
|
|
if (flags & O_EXCL)
|
|
coda_flags |= C_O_EXCL;
|
|
|
|
return coda_flags;
|
|
}
|
|
|
|
|
|
/* utility functions below */
|
|
void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
|
|
{
|
|
int inode_type;
|
|
/* inode's i_flags, i_ino are set by iget
|
|
XXX: is this all we need ??
|
|
*/
|
|
switch (attr->va_type) {
|
|
case C_VNON:
|
|
inode_type = 0;
|
|
break;
|
|
case C_VREG:
|
|
inode_type = S_IFREG;
|
|
break;
|
|
case C_VDIR:
|
|
inode_type = S_IFDIR;
|
|
break;
|
|
case C_VLNK:
|
|
inode_type = S_IFLNK;
|
|
break;
|
|
default:
|
|
inode_type = 0;
|
|
}
|
|
inode->i_mode |= inode_type;
|
|
|
|
if (attr->va_mode != (u_short) -1)
|
|
inode->i_mode = attr->va_mode | inode_type;
|
|
if (attr->va_uid != -1)
|
|
inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid);
|
|
if (attr->va_gid != -1)
|
|
inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid);
|
|
if (attr->va_nlink != -1)
|
|
set_nlink(inode, attr->va_nlink);
|
|
if (attr->va_size != -1)
|
|
inode->i_size = attr->va_size;
|
|
if (attr->va_size != -1)
|
|
inode->i_blocks = (attr->va_size + 511) >> 9;
|
|
if (attr->va_atime.tv_sec != -1)
|
|
inode->i_atime = timespec_to_timespec64(attr->va_atime);
|
|
if (attr->va_mtime.tv_sec != -1)
|
|
inode->i_mtime = timespec_to_timespec64(attr->va_mtime);
|
|
if (attr->va_ctime.tv_sec != -1)
|
|
inode->i_ctime = timespec_to_timespec64(attr->va_ctime);
|
|
}
|
|
|
|
|
|
/*
|
|
* BSD sets attributes that need not be modified to -1.
|
|
* Linux uses the valid field to indicate what should be
|
|
* looked at. The BSD type field needs to be deduced from linux
|
|
* mode.
|
|
* So we have to do some translations here.
|
|
*/
|
|
|
|
void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
|
|
{
|
|
unsigned int valid;
|
|
|
|
/* clean out */
|
|
vattr->va_mode = -1;
|
|
vattr->va_uid = (vuid_t) -1;
|
|
vattr->va_gid = (vgid_t) -1;
|
|
vattr->va_size = (off_t) -1;
|
|
vattr->va_atime.tv_sec = (time_t) -1;
|
|
vattr->va_atime.tv_nsec = (time_t) -1;
|
|
vattr->va_mtime.tv_sec = (time_t) -1;
|
|
vattr->va_mtime.tv_nsec = (time_t) -1;
|
|
vattr->va_ctime.tv_sec = (time_t) -1;
|
|
vattr->va_ctime.tv_nsec = (time_t) -1;
|
|
vattr->va_type = C_VNON;
|
|
vattr->va_fileid = -1;
|
|
vattr->va_gen = -1;
|
|
vattr->va_bytes = -1;
|
|
vattr->va_nlink = -1;
|
|
vattr->va_blocksize = -1;
|
|
vattr->va_rdev = -1;
|
|
vattr->va_flags = 0;
|
|
|
|
/* determine the type */
|
|
#if 0
|
|
mode = iattr->ia_mode;
|
|
if ( S_ISDIR(mode) ) {
|
|
vattr->va_type = C_VDIR;
|
|
} else if ( S_ISREG(mode) ) {
|
|
vattr->va_type = C_VREG;
|
|
} else if ( S_ISLNK(mode) ) {
|
|
vattr->va_type = C_VLNK;
|
|
} else {
|
|
/* don't do others */
|
|
vattr->va_type = C_VNON;
|
|
}
|
|
#endif
|
|
|
|
/* set those vattrs that need change */
|
|
valid = iattr->ia_valid;
|
|
if ( valid & ATTR_MODE ) {
|
|
vattr->va_mode = iattr->ia_mode;
|
|
}
|
|
if ( valid & ATTR_UID ) {
|
|
vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
|
|
}
|
|
if ( valid & ATTR_GID ) {
|
|
vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
|
|
}
|
|
if ( valid & ATTR_SIZE ) {
|
|
vattr->va_size = iattr->ia_size;
|
|
}
|
|
if ( valid & ATTR_ATIME ) {
|
|
vattr->va_atime = timespec64_to_timespec(iattr->ia_atime);
|
|
}
|
|
if ( valid & ATTR_MTIME ) {
|
|
vattr->va_mtime = timespec64_to_timespec(iattr->ia_mtime);
|
|
}
|
|
if ( valid & ATTR_CTIME ) {
|
|
vattr->va_ctime = timespec64_to_timespec(iattr->ia_ctime);
|
|
}
|
|
}
|
|
|