]> Zhao Yanbai Git Server - minix.git/commitdiff
Subsecond timestamps support for FS
authorAntoine Leca <Antoine.Leca.1@gmail.com>
Wed, 21 Dec 2011 22:29:29 +0000 (23:29 +0100)
committerCharlie Root <root@hppc359.few.vu.nl>
Fri, 12 Apr 2013 09:11:59 +0000 (11:11 +0200)
Expand REQ_UTIME to include tv_nsec members
(as in struct timespec) in addition to tv_sec==time_t

Designed with help from David van Moolenbroek

include/minix/vfsif.h
lib/libsffs/stat.c
servers/ext2/time.c
servers/mfs/time.c
servers/vfs/proto.h
servers/vfs/request.c
servers/vfs/time.c
servers/vfs/utility.c

index f4aac02ccb1552a8aa4c3df3604f0ce0f620912e..35fc94e7d8509b5af845fefc3c2709ead19fac89 100644 (file)
@@ -6,6 +6,7 @@
 
 /* VFS/FS request fields */
 #define REQ_ACTIME             m9_l2
+#define REQ_ACNSEC             m9_l4
 #define REQ_COUNT              m9_l2
 #define REQ_DEV                        m9_l5
 #define REQ_DEV2               m9_l1
@@ -19,6 +20,7 @@
 #define REQ_MEM_SIZE           m9_l5
 #define REQ_MODE               m9_s3
 #define REQ_MODTIME            m9_l3
+#define REQ_MODNSEC            m9_l5
 #define REQ_NBYTES             m9_l5
 #define REQ_PATH_LEN           m9_s2
 #define REQ_PATH_SIZE          m9_l5
index dbac8086743306b434881f88ea3d75098b5b13c6..b0aa4550f7dc4c32cc5756a2a9e13ce0f8eb3434 100644 (file)
@@ -158,11 +158,39 @@ int do_utime()
   if ((r = verify_inode(ino, path, NULL)) != OK)
        return r;
 
-  attr.a_mask = SFFS_ATTR_ATIME | SFFS_ATTR_MTIME;
-  attr.a_atime.tv_sec = m_in.REQ_ACTIME;
-  attr.a_atime.tv_nsec = 0;
-  attr.a_mtime.tv_sec = m_in.REQ_MODTIME;
-  attr.a_mtime.tv_nsec = 0;
-
+  attr.a_mask = 0;
+
+  switch(m_in.REQ_ACNSEC) {
+  case UTIME_OMIT: /* do not touch */
+       break;
+  case UTIME_NOW:
+       /* XXX VFS should have time() into ACTIME, for compat; we trust it! */
+       m_in.REQ_ACNSEC = 0;
+       /*FALLTHROUGH*/
+  default:
+       /* cases m_in.REQ_ACNSEC < 0 || m_in.REQ_ACNSEC >= 1E9
+        * are caught by VFS to cooperate with old instances of EXT2
+        */
+       attr.a_atime.tv_sec = m_in.REQ_ACTIME;
+       attr.a_atime.tv_nsec = m_in.REQ_ACNSEC;
+       attr.a_mask |= SFFS_ATTR_ATIME;
+       break;
+  }
+  switch(m_in.REQ_MODNSEC) {
+  case UTIME_OMIT: /* do not touch */
+       break;
+  case UTIME_NOW:
+       /* XXX VFS should have time() into MODTIME, for compat; we trust it! */
+       m_in.REQ_MODNSEC = 0;
+       /*FALLTHROUGH*/
+  default:
+       /* cases m_in.REQ_MODNSEC < 0 || m_in.REQ_MODNSEC >= 1E9
+        * are caught by VFS to cooperate with old instances
+        */
+       attr.a_mtime.tv_sec = m_in.REQ_MODTIME;
+       attr.a_mtime.tv_nsec = m_in.REQ_MODNSEC;
+       attr.a_mask |= SFFS_ATTR_MTIME;
+       break;
+  }
   return sffs_table->t_setattr(path, &attr);
 }
index 2db6dcd794f4a42130fc42bada3b7dc654421723..a7b6e948c345cabe7c2c7415a86a737c9eeca329 100644 (file)
@@ -6,6 +6,7 @@
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include "inode.h"
+#include <sys/stat.h>
 #include <minix/vfsif.h>
 
 
@@ -21,14 +22,54 @@ int fs_utime()
   if( (rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
         return(EINVAL);
 
-  /* Only the owner of a file or the super_user can change its time. */
+  /*
+   * Only the owner of a file or the super_user can change the timestamps.
+   * Here we assume VFS did that check before.
+   */
+
   r = OK;
   if(read_only(rip) != OK) r = EROFS;  /* not even su can touch if R/O */
   if(r == OK) {
-         rip->i_atime = fs_m_in.REQ_ACTIME;
-         rip->i_mtime = fs_m_in.REQ_MODTIME;
-         rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */
-         rip->i_dirt = IN_DIRTY;
+       rip->i_update = CTIME;  /* discard any stale ATIME and MTIME flags */
+       switch(fs_m_in.REQ_ACNSEC) {
+       case UTIME_NOW:
+               rip->i_update |= ATIME;
+               break;
+       case UTIME_OMIT: /* do not touch */
+               break;
+       default:
+               /*
+                * cases fs_m_in.REQ_ACNSEC < 0 || fs_m_in.REQ_ACNSEC >= 1E9
+                * are caught by VFS to cooperate with old instances of EXT2
+                */
+               rip->i_atime = fs_m_in.REQ_ACTIME;
+               /*
+                * Ext2FS does not support better than second resolution,
+                * so we discard REQ_ACNSEC to round down
+                */
+               break;
+       }
+
+       switch(fs_m_in.REQ_MODNSEC) {
+       case UTIME_NOW:
+               rip->i_update |= MTIME;
+               break;
+       case UTIME_OMIT: /* do not touch */
+               break;
+       default:
+               /*
+                * cases fs_m_in.REQ_MODNSEC < 0 || fs_m_in.REQ_MODNSEC >= 1E9
+                * are caught by VFS to cooperate with old instances of EXT2
+                */
+               rip->i_mtime = fs_m_in.REQ_MODTIME;
+               /*
+                * Ext2FS does not support better than second resolution,
+                * so we discard REQ_MODNSEC to round down
+                */
+               break;
+       }
+
+       rip->i_dirt = IN_DIRTY;
   }
 
   put_inode(rip);
index 48af75d03061b593790119baff61464aa3fab000..245c1d926354b1e3d81d7ee4e99d3b5d1e72f047 100644 (file)
@@ -1,5 +1,6 @@
 #include "fs.h"
 #include "inode.h"
+#include <sys/stat.h>
 #include <minix/vfsif.h>
 
 
@@ -10,19 +11,59 @@ int fs_utime()
 {
   register struct inode *rip;
   register int r;
-  
+
   /* Temporarily open the file. */
   if( (rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
         return(EINVAL);
 
-  /* Only the owner of a file or the super_user can change its time. */
+  /*
+   * Only the owner of a file or the super_user can change the timestamps.
+   * Here we assume VFS did that check before.
+   */
+
   r = OK;
   if(read_only(rip) != OK) r = EROFS;  /* not even su can touch if R/O */
   if(r == OK) {
-         rip->i_atime = fs_m_in.REQ_ACTIME;
-         rip->i_mtime = fs_m_in.REQ_MODTIME;
-         rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */
-         IN_MARKDIRTY(rip);
+       rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */
+       switch(fs_m_in.REQ_ACNSEC) {
+       case UTIME_NOW:
+               rip->i_update |= ATIME;
+               break;
+       case UTIME_OMIT: /* do not touch */
+               break;
+       default:
+               /*
+                * cases fs_m_in.REQ_ACNSEC < 0 || fs_m_in.REQ_ACNSEC >= 1E9
+                * are caught by VFS to cooperate with old instances of MFS
+                */
+               rip->i_atime = fs_m_in.REQ_ACTIME;
+               /*
+                * MFS does not support better than second resolution,
+                * so we discard REQ_ACNSEC to round down
+                */
+               break;
+       }
+
+       switch(fs_m_in.REQ_MODNSEC) {
+       case UTIME_NOW:
+               rip->i_update |= MTIME;
+               break;
+       case UTIME_OMIT: /* do not touch */
+               break;
+       default:
+               /*
+                * cases fs_m_in.REQ_MODNSEC < 0 || fs_m_in.REQ_MODNSEC >= 1E9
+                * are caught by VFS to cooperate with old instances of MFS
+                */
+               rip->i_mtime = fs_m_in.REQ_MODTIME;
+               /*
+                * MFS does not support better than second resolution,
+                * so we discard REQ_MODNSEC to round down
+                */
+               break;
+       }
+
+       IN_MARKDIRTY(rip);
   }
 
   put_inode(rip);
index 7bfff497adee85d8bb7027a6ef3f30eea40aa3e6..36c3ef0e83fee6bed6f151146cf3a86eb71e6768 100644 (file)
@@ -12,6 +12,7 @@
 /* Structs used in prototypes must be declared as such first. */
 struct filp;
 struct fproc;
+struct timespec;
 struct vmnt;
 struct vnode;
 struct lookup;
@@ -261,7 +262,8 @@ int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf);
 int req_sync(endpoint_t fs_e);
 int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc);
 int req_unmount(endpoint_t fs_e);
-int req_utime(endpoint_t fs_e, ino_t inode_nr, time_t actime, time_t modtime);
+int req_utime(endpoint_t fs_e, ino_t inode_nr, struct timespec * actv,
+       struct timespec * modtv);
 int req_newdriver(endpoint_t fs_e, dev_t dev, char *label);
 
 /* stadir.c */
@@ -291,7 +293,7 @@ int tll_unlock(tll_t *tllp);
 void tll_upgrade(tll_t *tllp);
 
 /* utility.c */
-time_t clock_time(void);
+struct timespec clock_timespec(void);
 unsigned conv2(int norm, int w);
 long conv4(int norm, long x);
 int copy_name(size_t len, char *dest);
index 443ba69053e0fc38b802de83c79b2d75dc1b0530..4eab2791e13931a9e61673afe8303bb90b95c167 100644 (file)
@@ -17,7 +17,7 @@
 #include <minix/endpoint.h>
 #include <minix/u64.h>
 #include <unistd.h>
-#include <minix/vfsif.h>
+#include <time.h>
 #include "fproc.h"
 #include "vmnt.h"
 #include "vnode.h"
@@ -1038,19 +1038,21 @@ endpoint_t fs_e;
 /*===========================================================================*
  *                             req_utime                                    *
  *===========================================================================*/
-int req_utime(fs_e, inode_nr, actime, modtime)
-endpoint_t fs_e;
-ino_t inode_nr;
-time_t actime;
-time_t modtime;
+int req_utime(endpoint_t fs_e, ino_t inode_nr, struct timespec * actimespec,
+       struct timespec * modtimespec)
 {
   message m;
 
+  assert(actimespec != NULL);
+  assert(modtimespec != NULL);
+
   /* Fill in request message */
   m.m_type = REQ_UTIME;
   m.REQ_INODE_NR = inode_nr;
-  m.REQ_ACTIME = actime;
-  m.REQ_MODTIME = modtime;
+  m.REQ_ACTIME = actimespec->tv_sec;
+  m.REQ_MODTIME = modtimespec->tv_sec;
+  m.REQ_ACNSEC = actimespec->tv_nsec;
+  m.REQ_MODNSEC = modtimespec->tv_nsec;
 
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
index 54d71f2e8c696606c1afed7ce970256364cda9ae..2695dc8377040cf8d86a13db6e0a85e778e833b5 100644 (file)
@@ -7,6 +7,7 @@
 #include "fs.h"
 #include <minix/callnr.h>
 #include <minix/com.h>
+#include <time.h>
 #include "file.h"
 #include "fproc.h"
 #include "path.h"
@@ -22,7 +23,7 @@ int do_utime()
 {
 /* Perform the utime(name, timep) system call. */
   int r;
-  time_t actime, modtime, newactime, newmodtime;
+  struct timespec actim, modtim, newactim, newmodtim;
   struct vnode *vp;
   struct vmnt *vmp;
   char fullpath[PATH_MAX];
@@ -32,8 +33,9 @@ int do_utime()
 
   vname = (vir_bytes) job_m_in.utime_file;
   vname_length = (size_t) job_m_in.utime_length;
-  actime = job_m_in.utime_actime;
-  modtime = job_m_in.utime_modtime;
+  actim.tv_sec = job_m_in.utime_actime;
+  modtim.tv_sec = job_m_in.utime_modtime;
+  actim.tv_nsec = modtim.tv_nsec = 0;
 
   /* Adjust for case of 'timep' being NULL;
    * utime_strlen then holds the actual size: strlen(name)+1 */
@@ -48,7 +50,7 @@ int do_utime()
   if (fetch_name(vname, len, fullpath) != OK) return(err_code);
   if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
 
-  /* Only the owner of a file or the super user can change its name. */
+  /* Only the owner of a file or the super user can change timestamps. */
   r = OK;
   if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
   if (vname_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
@@ -56,12 +58,12 @@ int do_utime()
   if (r == OK) {
        /* Issue request */
        if (vname_length == 0) {
-               newactime = newmodtime = clock_time();
+               newactim = newmodtim = clock_timespec();
        } else {
-               newactime = actime;
-               newmodtime = modtime;
+               newactim = actim;
+               newmodtim = modtim;
        }
-       r = req_utime(vp->v_fs_e, vp->v_inode_nr, newactime, newmodtime);
+       r = req_utime(vp->v_fs_e, vp->v_inode_nr, &newactim, &newmodtim);
   }
 
   unlock_vnode(vp);
index f4476f679a768023540ffce17478cf7d13b5b55d..1af39f7e6be5d62da4be0fd3debee6aecaec79ca 100644 (file)
@@ -1,7 +1,7 @@
 /* This file contains a few general purpose utility routines.
  *
  * The entry points into this file are
- *   clock_time ask the clock task for the real time
+ *   clock_timespec: ask the clock task for the real time
  *   copy:       copy a block of data
  *   fetch_name:  go get a path name from user space
  *   no_sys:      reject a system call that FS does not handle
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <time.h>
 #include "file.h"
 #include "fproc.h"
 #include "param.h"
@@ -141,9 +142,9 @@ int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc,
 
 
 /*===========================================================================*
- *                             clock_time                                   *
+ *                             clock_timespec                               *
  *===========================================================================*/
-time_t clock_time()
+struct timespec clock_timespec(void)
 {
 /* This routine returns the time in seconds since 1.1.1970.  MINIX is an
  * astrophysically naive system that assumes the earth rotates at a constant
@@ -151,15 +152,20 @@ time_t clock_time()
  */
 
   register int r;
+  struct timespec tv;
   clock_t uptime;
   clock_t realtime;
   time_t boottime;
 
   r = getuptime(&uptime, &realtime, &boottime);
   if (r != OK)
-       panic("clock_time err: %d", r);
+       panic("clock_timespec err: %d", r);
 
-  return( (time_t) (boottime + (realtime/system_hz)));
+  tv.tv_sec = (time_t) (boottime + (realtime/system_hz));
+  /* We do not want to overflow, and system_hz can be as high as 50kHz */
+  assert(system_hz < LONG_MAX/40000);
+  tv.tv_nsec = (realtime%system_hz) * 40000 / system_hz * 25000;
+  return tv;
 }
 
 /*===========================================================================*