#include <errno.h>
#include <assert.h>
#include <syscall.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include "xtio.h"
#include "sysio.h"
+#include "native.h"
#include "fs.h"
#include "mount.h"
#include "inode.h"
#include <sys/uio.h>
#endif
-#if defined(SYS_getdirentries)
+#if defined(SYSIO_SYS_getdirentries)
#define DIR_STREAMED 0
#define DIR_CVT_64 0
-#elif defined(SYS_getdents64)
+#elif defined(SYSIO_SYS_getdents64)
#define DIR_STREAMED 1
#define DIR_CVT_64 0
-#elif defined(SYS_getdents)
+#elif defined(SYSIO_SYS_getdents)
#define DIR_STREAMED 1
#if defined(_LARGEFILE64_SOURCE)
#define DIR_CVT_64 1
#endif
/*
- * Local host file system driver.
+ * Native file system information we keep per FS.
*/
-
-#if defined(ALPHA_LINUX)
-
-/* stat struct from asm/stat.h, as returned
- * by alpha linux kernel
- */
-struct __native_stat {
- unsigned int st_dev;
- unsigned int st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int st_rdev;
- long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
- unsigned int st_blksize;
- int st_blocks;
- unsigned int st_flags;
- unsigned int st_gen;
+struct native_filesystem {
+ time_t nfs_atimo; /* attr timeout (sec) */
};
-#define COPY_STAT(src, dest) \
-do { \
- memset((dest), 0, sizeof((*dest))); \
- (dest)->st_dev = (src)->st_dev; \
- (dest)->st_ino = (src)->st_ino; \
- (dest)->st_mode = (src)->st_mode; \
- (dest)->st_nlink = (src)->st_nlink; \
- (dest)->st_uid = (src)->st_uid; \
- (dest)->st_gid = (src)->st_gid; \
- (dest)->st_rdev = (src)->st_rdev; \
- (dest)->st_size = (src)->st_size; \
- (dest)->st_atime = (src)->st_atime; \
- (dest)->st_mtime = (src)->st_mtime; \
- (dest)->st_ctime = (src)->st_ctime; \
- (dest)->st_blksize = (src)->st_blksize; \
- (dest)->st_blocks = (src)->st_blocks; \
- (dest)->st_flags = (src)->st_flags; \
- (dest)->st_gen = (src)->st_gen; \
-} while (0);
-
-#else
-#define __native_stat intnl_stat
-#define COPY_STAT(src, dest) *(dest) = *(src)
-#endif
-
-#if defined(USE_NATIVE_STAT)
-#define __SYS_STAT SYS_lstat
-#define __SYS_FSTAT SYS_fstat
-#define __SYS_TRUNCATE SYS_truncate
-#define __SYS_FTRUNCATE SYS_ftruncate
-#else
-#define __SYS_STAT SYS_lstat64
-#define __SYS_FSTAT SYS_fstat64
-#define __SYS_TRUNCATE SYS_truncate64
-#define __SYS_FTRUNCATE SYS_ftruncate64
-#endif
-
-#if defined(USE_NATIVE_FDATASYNC)
-#define __SYS_FDATASYNC SYS_osf_fdatasync
-#else
-#define __SYS_FDATASYNC SYS_fdatasync
-#endif
-
-#if defined(USE_NATIVE_UTIME)
-#define __SYS_UTIME SYS_utimes
-#else
-#define __SYS_UTIME SYS_utime
-#endif
+/*
+ * Given fs, return driver private part.
+ */
+#define FS2NFS(fs) \
+ ((struct native_filesystem *)(fs)->fs_private)
/*
* Native file identifiers format.
*/
struct native_inode {
unsigned
- ni_seekok : 1; /* can seek? */
+ ni_seekok : 1, /* can seek? */
+ ni_attrvalid : 1; /* cached attrs ok? */
struct native_inode_identifier ni_ident; /* unique identifier */
struct file_identifier ni_fileid; /* ditto */
int ni_fd; /* host fildes */
int ni_oflags; /* flags, from open */
unsigned ni_nopens; /* soft ref count */
_SYSIO_OFF_T ni_fpos; /* current pos */
- struct intnl_stat ni_stat; /* cached attrs */
+ time_t ni_attrtim; /* attrs expire time */
};
/*
+ * Cached attributes usable?
+ */
+#define NATIVE_ATTRS_VALID(nino, t) \
+ ((nino)->ni_attrtim && (t) < (nino)->ni_attrtim)
+
+/*
* Native IO path arguments.
*/
struct native_io {
* stat -- by path.
*/
static int
-native_stat(const char *path, struct native_inode *nino, struct intnl_stat *buf)
+native_stat(const char *path,
+ struct inode *ino,
+ time_t t,
+ struct intnl_stat *buf)
{
+ struct native_inode *nino;
int err;
- struct __native_stat stbuf;
-
- err = syscall(__SYS_STAT, path, &stbuf);
- if (err) {
- err = -errno;
- goto out;
- }
- if (!nino) {
- COPY_STAT(&stbuf, buf);
- goto out;
- }
- COPY_STAT(&stbuf, &nino->ni_stat);
- if (&nino->ni_stat != buf)
- (void )memcpy(buf, &nino->ni_stat, sizeof(struct intnl_stat));
-
-out:
- return err;
-}
+ struct _sysio_native_stat stbuf;
-/*
- * stat -- by fildes
- */
-static int
-native_fstat(int fd, struct native_inode *nino, struct intnl_stat *buf)
-{
- int err;
- struct __native_stat stbuf;
+ nino = ino ? I2NI(ino) : NULL;
- err = syscall(__SYS_FSTAT, fd, &stbuf);
+ if (path)
+ err = syscall(SYSIO_SYS_stat, path, &stbuf);
+ else if (nino && nino->ni_fd >= 0)
+ err = syscall(SYSIO_SYS_fstat, nino->ni_fd, &stbuf);
+ else
+ abort();
if (err) {
- err = -errno;
- goto out;
+ if (nino)
+ nino->ni_attrtim = 0;
+ return -errno;
}
- if (!nino) {
- COPY_STAT(&stbuf, buf);
- goto out;
+ if (nino) {
+ nino->ni_attrtim = t;
+ SYSIO_COPY_STAT(&stbuf, &ino->i_stbuf);
+ if (buf)
+ *buf = ino->i_stbuf;
+ return 0;
}
- COPY_STAT(&stbuf, &nino->ni_stat);
- if (&nino->ni_stat != buf)
- (void )memcpy(buf, &nino->ni_stat, sizeof(struct intnl_stat));
-
-out:
- return err;
+ if (!buf)
+ return 0;
+ SYSIO_COPY_STAT(&stbuf, buf);
+ return 0;
}
/*
* Introduce an i-node to the system.
*/
static struct inode *
-native_i_new(struct filesys *fs, struct intnl_stat *buf)
+native_i_new(struct filesys *fs, time_t expiration, struct intnl_stat *buf)
{
struct native_inode *nino;
struct inode *ino;
if (!nino)
return NULL;
bzero(&nino->ni_ident, sizeof(nino->ni_ident));
+ nino->ni_seekok = 0;
nino->ni_ident.dev = buf->st_dev;
nino->ni_ident.ino = buf->st_ino;
#ifdef HAVE_GENERATION
nino->ni_oflags = 0;
nino->ni_nopens = 0;
nino->ni_fpos = 0;
- (void )memcpy(&nino->ni_stat, buf, sizeof(struct intnl_stat));
+ nino->ni_attrtim = expiration;
ino =
_sysio_i_new(fs,
&nino->ni_fileid,
-#ifndef AUTOMOUNT_FILE_NAME
- buf->st_mode & S_IFMT,
-#else
- buf->st_mode, /* all of the bits! */
-#endif
- buf->st_rdev,
+ buf,
0,
&native_i_ops,
nino);
* zero. All permission bits to open/creat/setattr are absolute --
* They've already had a umask applied, when appropriate.
*/
- _sysio_umask = syscall(SYS_umask, 0);
+ _sysio_umask = syscall(SYSIO_SYS_umask, 0);
return _sysio_fssw_register("native", &native_fssw_ops);
}
* Create private, internal, view of the hosts name space.
*/
static int
-create_internal_namespace()
+create_internal_namespace(const void *data)
{
+ char *opts;
+ ssize_t len;
+ char *cp;
+ struct native_filesystem *nfs;
int err;
struct mount *mnt;
struct inode *rootino;
struct pnode_base *rootpb;
static struct qstr noname = { NULL, 0, 0 };
struct filesys *fs;
+ time_t t;
struct intnl_stat stbuf;
+ unsigned long ul;
+ static struct option_value_info v[] = {
+ { "atimo", "30" },
+ { NULL, NULL }
+ };
if (native_internal_mount) {
/*
}
/*
+ * Get mount options.
+ */
+ opts = NULL;
+ if (data && (len = strlen((char *)data))) {
+ opts = malloc(len + 1);
+ if (!opts)
+ return -ENOMEM;
+ (void )strcpy(opts, data);
+ if (_sysio_get_args(opts, v) - opts != (ssize_t )len)
+ return -EINVAL;
+ }
+ ul = strtoul(v[0].ovi_value, &cp, 0);
+ if (*cp != '\0' || ul >= UINT_MAX)
+ return -EINVAL;
+ if (opts) {
+ free(opts);
+ opts = NULL;
+ }
+
+ /*
* We maintain an artificial, internal, name space in order to
* have access to fully qualified path names in the various routines.
* Initialize that name space now.
*/
+ fs = NULL;
mnt = NULL;
rootino = NULL;
rootpb = NULL;
- fs = _sysio_fs_new(&native_inodesys_ops, 0, NULL);
+ /*
+ * This really should be per-mount. Hmm, but that's best done
+ * as proper sub-mounts in the core and not this driver. We reconcile
+ * now, here, by putting the mount options on the file system. That
+ * means they are global and only can be passed at the initial mount.
+ *
+ * Maybe do it right some day?
+ */
+ nfs = malloc(sizeof(struct native_filesystem));
+ if (!nfs) {
+ err = -ENOMEM;
+ goto error;
+ }
+ nfs->nfs_atimo = ul;
+ if ((unsigned long)nfs->nfs_atimo != ul) {
+ err = -EINVAL;
+ goto error;
+ }
+ fs = _sysio_fs_new(&native_inodesys_ops, 0, nfs);
if (!fs) {
err = -ENOMEM;
goto error;
/*
* Get root i-node.
*/
- err = native_stat("/", NULL, &stbuf);
+ t = _SYSIO_LOCAL_TIME();
+ err = native_stat("/", NULL, 0, &stbuf);
if (err)
goto error;
- rootino = native_i_new(fs, &stbuf);
+ rootino = native_i_new(fs, t + FS2NFS(fs)->nfs_atimo, &stbuf);
if (!rootino) {
err = -ENOMEM;
goto error;
if (mnt) {
if (_sysio_do_unmount(mnt) != 0)
abort();
+ nfs = NULL;
fs = NULL;
rootpb = NULL;
rootino = NULL;
if (fs) {
FS_RELE(fs);
_sysio_fs_gone(fs);
+ nfs = NULL;
}
+ if (nfs)
+ free(nfs);
+ if (opts)
+ free(opts);
return err;
}
static int
native_fsswop_mount(const char *source,
unsigned flags,
- const void *data __IS_UNUSED,
+ const void *data,
struct pnode *tocover,
struct mount **mntp)
{
return -ENOENT;
if (!native_internal_mount) {
- err = create_internal_namespace();
+ err = create_internal_namespace(data);
if (err)
return err;
- }
+ } else if (data && *(char *)data)
+ return -EINVAL;
/*
* Lookup the source in the internally maintained name space.
}
static int
-native_i_invalid(struct inode *inop, struct intnl_stat stbuf)
+native_i_invalid(struct inode *inop, struct intnl_stat *stat)
{
+ struct native_inode *nino;
+
/*
* Validate passed in inode against stat struct info
*/
- struct native_inode *nino = I2NI(inop);
+ nino = I2NI(inop);
- if ((nino->ni_ident.dev != stbuf.st_dev ||
- nino->ni_ident.ino != stbuf.st_ino ||
+ if (!nino->ni_attrtim ||
+ (nino->ni_ident.dev != stat->st_dev ||
+ nino->ni_ident.ino != stat->st_ino ||
#ifdef HAVE_GENERATION
- nino->ni_ident.gen != stbuf.st_gen ||
+ nino->ni_ident.gen != stat->st_gen ||
#endif
- ((inop)->i_mode & S_IFMT) != (stbuf.st_mode & S_IFMT)) ||
- (((inop)->i_rdev != stbuf.st_rdev) &&
- (S_ISCHR((inop)->i_mode) || S_ISBLK((inop)->i_mode))))
+ ((inop)->i_stbuf.st_mode & S_IFMT) != (stat->st_mode & S_IFMT)) ||
+ (((inop)->i_stbuf.st_rdev != stat->st_rdev) &&
+ (S_ISCHR((inop)->i_stbuf.st_mode) ||
+ S_ISBLK((inop)->i_stbuf.st_mode)))) {
+ nino->ni_attrtim = 0; /* invalidate attrs */
return 1;
-
+ }
return 0;
}
+static struct inode *
+native_iget(struct filesys *fs, time_t expire, struct intnl_stat *stbp)
+{
+ struct inode *ino;
+ struct native_inode_identifier ident;
+ struct file_identifier fileid;
+
+ bzero(&ident, sizeof(ident));
+ ident.dev = stbp->st_dev;
+ ident.ino = stbp->st_ino;
+#ifdef HAVE_GENERATION
+ ident.gen = stbp->st_gen;
+#endif
+ fileid.fid_data = &ident;
+ fileid.fid_len = sizeof(ident);
+ ino = _sysio_i_find(fs, &fileid);
+ if (ino) {
+ ino->i_stbuf = *stbp;
+ I2NI(ino)->ni_attrtim = expire;
+ return ino;
+ }
+ return native_i_new(fs, expire, stbp);
+}
+
/*
* Find, and validate, or create i-node by host-relative path. Returned i-node
* is referenced.
*/
static int
-native_iget(struct filesys *fs,
- const char *path,
- struct inode **inop,
- int forced)
+native_ibind(struct filesys *fs,
+ char *path,
+ time_t t,
+ struct inode **inop)
{
+ struct intnl_stat ostbuf, stbuf;
int err;
struct inode *ino;
- struct intnl_stat stbuf;
- struct native_inode_identifier ident;
- struct file_identifier fileid;
- /*
- * Get file status.
- */
- err = native_stat(path, *inop ? I2NI(*inop) : NULL, &stbuf);
- if (err) {
- *inop = NULL;
+ if (*inop)
+ ostbuf = (*inop)->i_stbuf;
+
+ err = native_stat(path, *inop, t, &stbuf);
+ if (err)
return err;
- }
/*
* Validate?
*/
if (*inop) {
- if (!native_i_invalid(*inop, stbuf))
+ if (!native_i_invalid(*inop, &ostbuf))
return 0;
/*
* Invalidate.
*/
+ _sysio_i_undead(*inop);
*inop = NULL;
}
- /*
- * I-node is not already known. Find or create it.
- */
- bzero(&ident, sizeof(ident));
- ident.dev = stbuf.st_dev;
- ident.ino = stbuf.st_ino;
-#ifdef HAVE_GENERATION
- ident.gen = stbuf.st_gen;
-#endif
- fileid.fid_data = &ident;
- fileid.fid_len = sizeof(ident);
- ino = _sysio_i_find(fs, &fileid);
- if (ino &&
- (forced || (ino->i_mode & S_IFMT) != (stbuf.st_mode & S_IFMT))) {
- /*
- * Insertion was forced or dup inum but it's already present!
- */
- if (native_i_invalid(ino, stbuf)) {
- /*
- * Cached inode has stale attrs
- * make way for the new one
- */
- I_GONE(ino);
- ino = NULL;
- } else
- /*
- * OK to reuse cached inode
- */
- goto out;
- }
-
- if (!ino) {
- ino = native_i_new(fs, &stbuf);
- if (!ino)
- err = -ENOMEM;
- }
-out:
- if (!err)
- *inop = ino;
- return err;
-}
-
-/*
- * Look up named object in host's name space by path.
- */
-static int
-native_path_lookup(struct filesys *fs, const char *path, struct inode **inop)
-{
-
- return native_iget(fs, path, inop, 0);
-}
-
-/*
- * Look up object by it's path node.
- */
-static int
-native_i_lookup(struct filesys *fs, struct pnode_base *pb, struct inode **inop)
-{
- int err;
- char *path;
-
- path = _sysio_pb_path(pb, '/');
- if (!path)
+ if (!(ino = native_iget(fs, t + FS2NFS(fs)->nfs_atimo, &stbuf)))
return -ENOMEM;
- err = native_path_lookup(fs, path, inop);
- free(path);
- return err;
+
+ *inop = ino;
+ return 0;
}
static int
struct intent *intnt __IS_UNUSED,
const char *path __IS_UNUSED)
{
+ time_t t;
+ char *fqpath;
+ struct filesys *fs;
int err;
*inop = pno->p_base->pb_ino;
/*
+ * Try to use the cached attributes unless the intent
+ * indicates we are looking up the last component and
+ * caller wants attributes. In that case, force a refresh.
+ */
+ t = _SYSIO_LOCAL_TIME();
+ if (*inop &&
+ (path || !intnt || (intnt->int_opmask & INT_GETATTR) == 0) &&
+ NATIVE_ATTRS_VALID(I2NI(*inop), t))
+ return 0;
+
+ /*
* Don't have an inode yet. Because we translate everything back to
* a single name space for the host, we will assume the object the
* caller is looking for has no existing alias in our internal
* The file identifier *will* be unique. It's got to have a different
* dev.
*/
- err = native_i_lookup(pno->p_mount->mnt_fs, pno->p_base, inop);
+ fqpath = _sysio_pb_path(pno->p_base, '/');
+ if (!fqpath)
+ return -ENOMEM;
+ fs = pno->p_mount->mnt_fs;
+ err = native_ibind(fs, fqpath, t + FS2NFS(fs)->nfs_atimo, inop);
+ free(fqpath);
if (err)
*inop = NULL;
return err;
static int
native_inop_getattr(struct pnode *pno,
struct inode *ino,
- struct intnl_stat *stbuf)
+ struct intnl_stat *stat)
{
- char *path;
struct native_inode *nino;
int err;
- nino = ino ? I2NI(ino) : NULL;
+ /*
+ * We just cannot use the cached attributes when getattr is
+ * called. Had the caller felt those were sufficient then
+ * they could have (would have?) simply used what was cached
+ * after revalidating. In this case, there's a good chance the
+ * caller is looking for the current time stamps and/or size. Something
+ * pretty volatile anyway.
+ */
err = 0; /* compiler cookie */
- if (!ino) {
+ if (pno) {
+ char *path;
+ struct filesys *fs;
+ time_t t;
+
path = _sysio_pb_path(pno->p_base, '/');
if (!path)
return -ENOMEM;
- err = native_stat(path, nino, stbuf);
+ fs = pno->p_mount->mnt_fs;
+ t = _SYSIO_LOCAL_TIME();
+ err = native_stat(path, ino, t + FS2NFS(fs)->nfs_atimo, stat);
free(path);
- } else if (nino->ni_fd >= 0)
- err = native_fstat(nino->ni_fd, nino, stbuf);
+ } else if ((nino = I2NI(ino))->ni_fd >= 0)
+ /*
+ * Don't have access to the fs record anymore. Just
+ * refresh but keep the current timeout.
+ */
+ err = native_stat(NULL, ino, nino->ni_attrtim, stat);
else {
/*
* Dev inodes don't open in this driver. We won't have
* a file descriptor with which to do the deed then. Satisfy
* the request from the cached copy of the attributes.
*/
- (void )memcpy(stbuf,
- &nino->ni_stat,
+ (void )memcpy(stat,
+ &ino->i_stbuf,
sizeof(struct intnl_stat));
err = 0;
}
return err;
}
+#ifdef SYSIO_SYS_utime
+static int
+_ut(const char *path, time_t actime, time_t modtime)
+{
+ struct utimbuf ut;
+
+ ut.actime = actime;
+ ut.modtime = modtime;
+ return syscall(SYSIO_SYS_utime, path, &ut);
+}
+#else
+static int
+_ut(const char *path, time_t actime, time_t modtime)
+{
+ struct timeval tv[2];
+
+ tv[0].tv_sec = actime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = modtime;
+ tv[1].tv_usec = 0;
+ return syscall(SYSIO_SYS_utimes, path, &tv);
+}
+#endif
+
static int
native_inop_setattr(struct pnode *pno,
struct inode *ino,
unsigned mask,
- struct intnl_stat *stbuf)
+ struct intnl_stat *stat)
{
char *path;
struct native_inode *nino;
int fd;
- struct intnl_stat *stbp, _stbuf;
int err;
path = NULL;
nino = ino ? I2NI(ino) : NULL;
fd = -1;
- stbp = &_stbuf;
- if (nino) {
+ if (nino)
fd = nino->ni_fd;
- stbp = &nino->ni_stat;
- }
if (fd < 0 || mask & (SETATTR_MTIME|SETATTR_ATIME)) {
if (!pno)
return -EEXIST;
/*
* Get current status for undo.
*/
- err =
- fd < 0
- ? native_stat(path, nino, stbp)
- : native_fstat(fd, nino, stbp);
+ err = native_stat(path, ino, 0, NULL);
if (err)
goto out;
/*
* Alter permissions attribute.
*/
- mode = stbuf->st_mode & 07777;
+ mode = stat->st_mode & 07777;
err =
fd < 0
- ? syscall(SYS_chmod, path, mode)
- : syscall(SYS_fchmod, fd, mode);
+ ? syscall(SYSIO_SYS_chmod, path, mode)
+ : syscall(SYSIO_SYS_fchmod, fd, mode);
if (err)
err = -errno;
}
if (err)
mask &= ~SETATTR_MODE;
else if (mask & (SETATTR_MTIME|SETATTR_ATIME)) {
- struct utimbuf ut;
+ time_t actime, modtime;
/*
* Alter access and/or modify time attributes.
*/
- ut.actime = stbuf->st_atime;
- ut.modtime = stbuf->st_mtime;
- if (mask & SETATTR_MTIME)
- ut.modtime = stbuf->st_mtime;
+ actime = ino->i_stbuf.st_atime;
+ modtime = ino->i_stbuf.st_mtime;
if (mask & SETATTR_ATIME)
- ut.actime = stbuf->st_atime;
- err = syscall(__SYS_UTIME, path, &ut);
- if (err)
- err = -errno;
+ actime = stat->st_atime;
+ if (mask & SETATTR_MTIME)
+ modtime = stat->st_mtime;
+ if (_ut(path, actime, modtime) != 0)
+ return -errno;
}
if (err)
mask &= ~(SETATTR_MTIME|SETATTR_ATIME);
*/
err =
fd < 0
- ? syscall(SYS_chown,
+ ? syscall(SYSIO_SYS_chown,
path,
mask & SETATTR_UID
- ? stbuf->st_uid
+ ? stat->st_uid
: (uid_t )-1,
mask & SETATTR_GID
- ? stbuf->st_gid
+ ? stat->st_gid
: (gid_t )-1)
- : syscall(SYS_fchown,
+ : syscall(SYSIO_SYS_fchown,
fd,
mask & SETATTR_UID
- ? stbuf->st_uid
+ ? stat->st_uid
: (uid_t )-1,
mask & SETATTR_GID
- ? stbuf->st_gid
+ ? stat->st_gid
: (gid_t )-1);
if (err)
err = -errno;
* Do the truncate last. It can't be undone.
*/
(void )(fd < 0
- ? syscall(__SYS_TRUNCATE, path, stbuf->st_size)
- : syscall(__SYS_FTRUNCATE, fd, stbuf->st_size));
+ ? syscall(SYSIO_SYS_truncate, path, stat->st_size)
+ : syscall(SYSIO_SYS_ftruncate, fd, stat->st_size));
}
if (!err)
goto out;
*/
if (mask & (SETATTR_UID|SETATTR_GID)) {
(void )(fd < 0
- ? syscall(SYS_chown,
+ ? syscall(SYSIO_SYS_chown,
path,
mask & SETATTR_UID
- ? stbp->st_uid
+ ? ino->i_stbuf.st_uid
: (uid_t )-1,
mask & SETATTR_GID
- ? stbp->st_gid
+ ? ino->i_stbuf.st_gid
: (gid_t )-1)
- : syscall(SYS_fchown,
+ : syscall(SYSIO_SYS_fchown,
fd,
mask & SETATTR_UID
- ? stbp->st_uid
+ ? ino->i_stbuf.st_uid
: (uid_t )-1,
mask & SETATTR_GID
- ? stbp->st_gid
+ ? ino->i_stbuf.st_gid
: (gid_t )-1));
}
- if (mask & (SETATTR_MTIME|SETATTR_ATIME)) {
- struct utimbuf ut;
-
- ut.actime = stbp->st_atime;
- ut.modtime = stbp->st_mtime;
- (void )syscall(__SYS_UTIME, path, &ut);
- }
+ if (mask & (SETATTR_MTIME|SETATTR_ATIME))
+ (void )_ut(path, ino->i_stbuf.st_atime, ino->i_stbuf.st_mtime);
if (mask & SETATTR_MODE) {
fd < 0
- ? syscall(SYS_chmod, path, stbp->st_mode & 07777)
- : syscall(SYS_fchmod, stbp->st_mode & 07777);
+ ? syscall(SYSIO_SYS_chmod, path, ino->i_stbuf.st_mode & 07777)
+ : syscall(SYSIO_SYS_fchmod, ino->i_stbuf.st_mode & 07777);
}
out:
/*
- * We must refresh the cached attributes on success.
+ * We must refresh the cached attributes.
*/
- if (!err && (fd < 0
- ? native_stat(path, nino, stbp)
- : native_fstat(fd, nino, stbp)) != 0)
+ if (!err && native_stat(path, ino, _SYSIO_LOCAL_TIME(), NULL) != 0)
abort();
if (path)
free(path);
assert(*offset >= 0);
off = *offset;
-#if _LARGEFILE64_SOURCE && defined(SYS__llseek)
+#if _LARGEFILE64_SOURCE && defined(SYSIO_SYS__llseek)
{
int err;
err =
- syscall(SYS__llseek,
+ syscall(SYSIO_SYS__llseek,
(unsigned int)fd,
(unsigned int)(off >> 32),
(unsigned int)off,
}
#else
off =
- syscall(SYS_lseek,
+ syscall(SYSIO_SYS_lseek,
fd,
off,
whence);
nino->ni_fpos = *basep;
cc =
-#if defined(SYS_getdirentries)
- syscall(SYS_getdirentries,
+#if defined(SYSIO_SYS_getdirentries)
+ syscall(SYSIO_SYS_getdirentries,
nino->ni_fd,
buf,
nbytes,
basep);
-#elif defined(SYS_getdents64)
- syscall(SYS_getdents64, nino->ni_fd, buf, nbytes);
-#elif defined(SYS_getdents)
- syscall(SYS_getdents, nino->ni_fd, buf, nbytes);
+#elif defined(SYSIO_SYS_getdents64)
+ syscall(SYSIO_SYS_getdents64, nino->ni_fd, buf, nbytes);
+#elif defined(SYSIO_SYS_getdents)
+ syscall(SYSIO_SYS_getdents, nino->ni_fd, buf, nbytes);
#endif
if (cc < 0)
struct dirent64 *d64p;
size_t namlen;
size_t reclen;
+ /*
+ * Work-around for broken 64 bit basep update
+ * Get value of basep to return from last directory
+ * entry d_off value
+ */
+ _SYSIO_OFF_T last_offset = *basep;
#else
#define bp buf
#define count nbytes
cc -= ldp->ld_reclen;
ldp = (struct linux_dirent *)((char *)ldp + ldp->ld_reclen);
nbytes -= d64p->d_reclen;
+ last_offset = d64p->d_off;
d64p = (struct dirent64 *)((char *)d64p + d64p->d_reclen);
}
+ nino->ni_fpos = *basep = last_offset;
free(bp);
- if (d64p == (struct dirent64 *)buf && cc)
- cc = -EINVAL; /* buf too small */
- cc = (char *)d64p - buf;
+ cc =
+ (d64p == (struct dirent64 *)buf && cc)
+ ? -EINVAL
+ : (char *)d64p - buf;
#else
#undef bp
#undef count
if (!path)
return -ENOMEM;
- err = syscall(SYS_mkdir, path, mode);
+ err = syscall(SYSIO_SYS_mkdir, path, mode);
if (err != 0)
err = -errno;
free(path);
if (!path)
return -ENOMEM;
- err = syscall(SYS_rmdir, path);
+ err = syscall(SYSIO_SYS_rmdir, path);
if (err != 0)
err = -errno;
free(path);
if (!path)
return -ENOMEM;
- err = syscall(SYS_symlink, data, path);
+ err = syscall(SYSIO_SYS_symlink, data, path);
if (err != 0)
err = -errno;
free(path);
path = _sysio_pb_path(pno->p_base, '/');
if (!path)
return -ENOMEM;
- i = syscall(SYS_readlink, path, buf, bufsiz);
+ i = syscall(SYSIO_SYS_readlink, path, buf, bufsiz);
if (i < 0)
i = -errno;
free(path);
#ifdef O_LARGEFILE
flags |= O_LARGEFILE;
#endif
- fd = syscall(SYS_open, path, flags, mode);
+ fd = syscall(SYSIO_SYS_open, path, flags, mode);
if (!pno->p_base->pb_ino && fd >= 0) {
+ struct filesys *fs;
int err;
/*
* Success but we need to return an i-node.
*/
+ fs = pno->p_mount->mnt_fs;
err =
- native_iget(pno->p_mount->mnt_fs,
- path,
- &pno->p_base->pb_ino,
- 1);
+ native_ibind(fs,
+ path,
+ _SYSIO_LOCAL_TIME() + FS2NFS(fs)->nfs_atimo,
+ &pno->p_base->pb_ino);
if (err) {
- (void )syscall(SYS_close, fd);
+ (void )syscall(SYSIO_SYS_close, fd);
if (err == -EEXIST)
abort();
fd = err;
/*
* Keep existing.
*/
- (void )syscall(SYS_close, fd);
+ (void )syscall(SYSIO_SYS_close, fd);
return 0;
}
- (void )syscall(SYS_close, nino->ni_fd);
+ (void )syscall(SYSIO_SYS_close, nino->ni_fd);
}
/*
* Invariant; First open. Must init.
return 0;
}
- err = syscall(SYS_close, nino->ni_fd);
+ err = syscall(SYSIO_SYS_close, nino->ni_fd);
if (err)
return -errno;
goto out;
}
- err = syscall(SYS_link, opath, npath);
+ err = syscall(SYSIO_SYS_link, opath, npath);
if (err != 0)
err = -errno;
free(opath);
if (npath)
free(npath);
-
return err;
}
* (usually .NFSXXXXXX, where the X's are replaced by the PID and some
* unique characters) in order to simulate the proper semantic.
*/
- if (syscall(SYS_unlink, path) != 0)
+ if (syscall(SYSIO_SYS_unlink, path) != 0)
err = -errno;
free(path);
return err;
goto out;
}
- err = syscall(SYS_rename, opath, npath);
+ err = syscall(SYSIO_SYS_rename, opath, npath);
if (err != 0)
err = -errno;
free(opath);
if (npath)
free(npath);
-
return err;
}
static ssize_t
dopio(void *buf, size_t count, _SYSIO_OFF_T off, struct native_io *nio)
{
-#if defined(_LARGEFILE64_SOURCE) && \
- defined(SYS_pread64) && \
- defined(SYS_pwrite64)
-#define _NATIVE_SYSCALL_PREAD SYS_pread64
-#define _NATIVE_SYSCALL_PWRITE SYS_pwrite64
-#else
-#define _NATIVE_SYSCALL_PREAD SYS_pread
-#define _NATIVE_SYSCALL_PWRITE SYS_pwrite
-#endif
ssize_t cc;
if (!(off == nio->nio_nino->ni_fpos || nio->nio_nino->ni_seekok))
return -1;
}
cc =
- syscall(nio->nio_op == 'r' ? SYS_read : SYS_write,
+ syscall(nio->nio_op == 'r'
+ ? SYSIO_SYS_read
+ : SYSIO_SYS_write,
nio->nio_nino->ni_fd,
buf,
count);
} else
cc =
syscall((nio->nio_op == 'r'
- ? _NATIVE_SYSCALL_PREAD
- : _NATIVE_SYSCALL_PWRITE),
+ ? SYSIO_SYS_pread
+ : SYSIO_SYS_pwrite),
nio->nio_nino->ni_fd,
buf,
count,
off);
return cc;
-#undef _NATIVE_SYSCALL_PREAD
-#undef _NATIVE_SYSCALL_PWRITE
}
static ssize_t
ssize_t cc;
#if !(defined(REDSTORM) || defined(MAX_IOVEC))
-#define MAX_IOVEC INT_MAX
+#define MAX_IOVEC INT_MAX
#endif
+
if (count <= 0)
return -EINVAL;
cc =
#ifndef REDSTORM
count <= MAX_IOVEC
- ? syscall(nio->nio_op == 'r' ? SYS_readv : SYS_writev,
+ ? syscall(nio->nio_op == 'r' ? SYSIO_SYS_readv : SYSIO_SYS_writev,
nio->nio_nino->ni_fd,
iov,
count)
flock.l_len = xtv->xtv_len;
xtv++;
err =
- syscall(
-#if !_LARGEFILE64_SOURCE
- SYS_fcntl64
-#else
- SYS_fcntl
-#endif
- ,
+ syscall(SYSIO_SYS_fcntl,
nino->ni_fd,
F_SETLK,
&flock);
#ifdef F_GETOWN
case F_GETOWN:
#endif
- *rtn = syscall(SYS_fcntl, nino->ni_fd, cmd);
+ *rtn = syscall(SYSIO_SYS_fcntl, nino->ni_fd, cmd);
if (*rtn == -1)
err = -errno;
break;
case F_SETOWN:
#endif
arg = va_arg(ap, long);
- *rtn = syscall(SYS_fcntl, nino->ni_fd, cmd, arg);
+ *rtn = syscall(SYSIO_SYS_fcntl, nino->ni_fd, cmd, arg);
if (*rtn == -1)
err = -errno;
break;
}
/*
- * The syscall interface does not support SYS_fstatvfs.
+ * The syscall interface does not support SYSIO_SYS_fstatvfs.
* Should possibly return ENOSYS, but thought it
- * better to use SYS_fstatfs and fill in as much of
+ * better to use SYSIO_SYS_fstatfs and fill in as much of
* the statvfs structure as possible. This allows
* for more of a test of the sysio user interface.
*/
rc =
path
- ? syscall(SYS_statfs, path, &fs)
- : syscall(SYS_fstatfs, I2NI(ino)->ni_fd, &fs);
+ ? syscall(SYSIO_SYS_statfs, path, &fs)
+ : syscall(SYSIO_SYS_fstatfs, I2NI(ino)->ni_fd, &fs);
if (path)
free(path);
if (rc < 0)
assert(I2NI(ino)->ni_fd >= 0);
- err = syscall(SYS_fsync, I2NI(ino)->ni_fd);
+ err = syscall(SYSIO_SYS_fsync, I2NI(ino)->ni_fd);
if (err)
err = -errno;
return err;
static int
native_inop_datasync(struct inode *ino)
{
+ struct native_inode *nino;
int err;
- assert(I2NI(ino)->ni_fd >= 0);
+ nino = I2NI(ino);
+ assert(nino->ni_fd >= 0);
-#ifdef NATIVE_FDATASYNC
- err = syscall(NATIVE_FDATASYNC, I2NI(ino)->ni_fd);
+#ifdef SYSIO_SYS_fdatasync
+ err = syscall(SYSIO_SYS_fdatasync, I2NI(ino)->ni_fd);
#else
#if 0
#warning No fdatasync system call -- Using fsync instead!
#endif
- err = syscall(SYS_fsync, I2NI(ino)->ni_fd);
+ err = syscall(SYSIO_SYS_fsync, I2NI(ino)->ni_fd);
#endif
if (err)
err = -errno;
unsigned long int request,
va_list ap)
{
+ struct native_inode *nino;
long arg1, arg2, arg3, arg4;
- assert(I2NI(ino)->ni_fd >= 0);
-
+ nino = I2NI(ino);
+ assert(nino->ni_fd >= 0);
arg1 = va_arg(ap, long);
arg2 = va_arg(ap, long);
arg3 = va_arg(ap, long);
arg4 = va_arg(ap, long);
- return syscall(SYS_ioctl, I2NI(ino)->ni_fd, request,
+ return syscall(SYSIO_SYS_ioctl, I2NI(ino)->ni_fd, request,
arg1, arg2, arg3, arg4);
}
#else
struct native_inode *nino = I2NI(ino);
if (nino->ni_fd >= 0)
- (void )syscall(SYS_close, nino->ni_fd);
+ (void )syscall(SYSIO_SYS_close, nino->ni_fd);
free(ino->i_private);
}
native_fsop_gone(struct filesys *fs __IS_UNUSED)
{
+ free(fs->fs_private);
/*
* Do nothing. There is no private part maintained for the
* native file interface.