📄 fs_native.c
字号:
fd = err; } } free(path); if (fd < 0) return -errno; /* * Remember this new open. */ nino = I2NI(pno->p_base->pb_ino); nino->ni_nopens++; assert(nino->ni_nopens); if (nino->ni_fd >= 0) { if ((nino->ni_oflags & O_RDWR) || (flags & (O_RDONLY|O_WRONLY|O_RDWR)) == O_RDONLY) { /* * Keep existing. */ (void )syscall(SYSIO_SYS_close, fd); return 0; } (void )syscall(SYSIO_SYS_close, nino->ni_fd); } /* * Invariant; First open. Must init. */ nino->ni_resetfpos = 0; nino->ni_fpos = 0; nino->ni_fd = fd; /* * Need to know whether we can seek on this * descriptor. */ nino->ni_seekok = native_pos(nino->ni_fd, &nino->ni_fpos, SEEK_CUR) != 0 ? 0 : 1; return 0;}static intnative_inop_close(struct inode *ino){ struct native_inode *nino = I2NI(ino); int err; if (nino->ni_fd < 0) abort(); assert(nino->ni_nopens); if (--nino->ni_nopens) { /* * Hmmm. We really don't need anything else. However, some * filesystems try to implement a sync-on-close semantic. * As this appears now, that is lost. Might want to change * it somehow in the future? */ return 0; } err = syscall(SYSIO_SYS_close, nino->ni_fd); if (err) return -errno; nino->ni_fd = -1; nino->ni_resetfpos = 0; nino->ni_fpos = 0; return 0;}static intnative_inop_link(struct pnode *old, struct pnode *new){ int err; char *opath, *npath; err = 0; opath = _sysio_pb_path(old->p_base, '/'); npath = _sysio_pb_path(new->p_base, '/'); if (!(opath && npath)) { err = -ENOMEM; goto out; } err = syscall(SYSIO_SYS_link, opath, npath); if (err != 0) err = -errno;out: if (opath) free(opath); if (npath) free(npath); return err;}static intnative_inop_unlink(struct pnode *pno){ char *path; int err = 0; path = _sysio_pb_path(pno->p_base, '/'); if (!path) return -ENOMEM; /* * For this driver, unlink is easy with open files. Since the * file remains open to the system, too, the descriptors are still * valid. * * Other drivers will have some difficulty here as the entry in the * file system name space must be removed without sacrificing access * to the file itself. In NFS this is done with a mechanism referred * to as a `silly delete'. The file is moved to a temporary name * (usually .NFSXXXXXX, where the X's are replaced by the PID and some * unique characters) in order to simulate the proper semantic. */ if (syscall(SYSIO_SYS_unlink, path) != 0) err = -errno; free(path); return err;}static intnative_inop_rename(struct pnode *old, struct pnode *new){ int err; char *opath, *npath; opath = _sysio_pb_path(old->p_base, '/'); npath = _sysio_pb_path(new->p_base, '/'); if (!(opath && npath)) { err = -ENOMEM; goto out; } err = syscall(SYSIO_SYS_rename, opath, npath); if (err != 0) err = -errno;out: if (opath) free(opath); if (npath) free(npath); return err;}static ssize_tdopio(void *buf, size_t count, _SYSIO_OFF_T off, struct native_io *nio){ ssize_t cc; if (!nio->nio_nino->ni_seekok) { if (off != nio->nio_nino->ni_fpos) { /* * They're trying to reposition. Can't * seek on this descriptor so we err out now. */ errno = ESPIPE; return -1; } cc = syscall(nio->nio_op == 'r' ? SYSIO_SYS_read : SYSIO_SYS_write, nio->nio_nino->ni_fd, buf, count); if (cc > 0) nio->nio_nino->ni_fpos += cc; } else cc = syscall((nio->nio_op == 'r' ? SYSIO_SYS_pread : SYSIO_SYS_pwrite), nio->nio_nino->ni_fd, buf, count, off); return cc;}static ssize_tdoiov(const struct iovec *iov, int count, _SYSIO_OFF_T off, ssize_t limit, struct native_io *nio){ ssize_t cc;#if !(defined(REDSTORM) || defined(MAX_IOVEC))#define MAX_IOVEC INT_MAX#endif if (count <= 0) return -EINVAL; /* * Avoid the reposition call if we're already at the right place. * Allows us to access pipes and fifos. */ if (off != nio->nio_nino->ni_fpos) { int err; err = native_pos(nio->nio_nino->ni_fd, &off, SEEK_SET); if (err) { nio->nio_nino->ni_resetfpos = 1; return err; } nio->nio_nino->ni_resetfpos = 0; nio->nio_nino->ni_fpos = off; } /* * The {read,write}v is safe as this routine is only ever called * by _sysio_enumerate_extents() and that routine is exact. It never * passes iovectors including tails. */ cc =#ifndef REDSTORM count <= MAX_IOVEC ? syscall(nio->nio_op == 'r' ? SYSIO_SYS_readv : SYSIO_SYS_writev, nio->nio_nino->ni_fd, iov, count) :#endif _sysio_enumerate_iovec(iov, count, off, limit, (ssize_t (*)(void *, size_t, _SYSIO_OFF_T, void *))dopio, nio); if (cc < 0) cc = -errno; else nio->nio_nino->ni_fpos += cc; return cc;#if !(defined(REDSTORM) || defined(MAX_IOVEC))#undef MAX_IOVEC#endif}#if 0static intlockop_all(struct native_inode *nino, struct intnl_xtvec *xtv, size_t count, short op){ struct flock flock; int err; if (!count) return -EINVAL; flock.l_type = op; flock.l_whence = SEEK_SET; while (count--) { flock.l_start = xtv->xtv_off; flock.l_len = xtv->xtv_len; xtv++; err = syscall(SYSIO_SYS_fcntl, nino->ni_fd, F_SETLK, &flock); if (err != 0) return -errno; } return 0;}static intorder_xtv(const struct intnl_xtvec *xtv1, const struct intnl_xtvec *xtv2){ if (xtv1->xtv_off < xtv2->xtv_off) return -1; if (xtv1->xtv_off > xtv2->xtv_off) return 1; return 0;}#endifstatic intdoio(char op, struct ioctx *ioctx){ struct native_inode *nino;#if 0 int dolocks; struct intnl_xtvec *oxtv; int err;#endif struct native_io arguments; ssize_t cc;#if 0 struct intnl_xtvec *front, *rear, tmp;#endif nino = I2NI(ioctx->ioctx_ino);#if 0 dolocks = ioctx->ioctx_xtvlen > 1 && nino->ni_seekok; if (dolocks) { /* * Must lock the regions (in order!) since we can't do * strided-IO as a single atomic operation. */ oxtv = malloc(ioctx->ioctx_xtvlen * sizeof(struct intnl_xtvec)); if (!oxtv) return -ENOMEM; (void )memcpy(oxtv, ioctx->ioctx_xtv, ioctx->ioctx_xtvlen * sizeof(struct intnl_xtvec)); qsort(oxtv, ioctx->ioctx_xtvlen, sizeof(struct intnl_xtvec), (int (*)(const void *, const void *))order_xtv); err = lockop_all(nino, oxtv, ioctx->ioctx_xtvlen, op == 'r' ? F_RDLCK : F_WRLCK); if (err) { free(oxtv); return err; } }#endif arguments.nio_op = op; arguments.nio_nino = nino; cc = _sysio_enumerate_extents(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen, ioctx->ioctx_iov, ioctx->ioctx_iovlen, (ssize_t (*)(const struct iovec *, int, _SYSIO_OFF_T, ssize_t, void *))doiov, &arguments);#if 0 if (dolocks) { /* * Must unlock in reverse order. */ front = oxtv; rear = front + ioctx->ioctx_xtvlen - 1; while (front < rear) { tmp = *front; *front++ = *rear; *rear-- = tmp; } if (lockop_all(nino, oxtv, ioctx->ioctx_xtvlen, F_UNLCK) != 0) abort(); free(oxtv); }#endif if ((ioctx->ioctx_cc = cc) < 0) { ioctx->ioctx_errno = -ioctx->ioctx_cc; ioctx->ioctx_cc = -1; } return 0;}static intnative_inop_read(struct inode *ino __IS_UNUSED, struct ioctx *ioctx){ return doio('r', ioctx);}static intnative_inop_write(struct inode *ino __IS_UNUSED, struct ioctx *ioctx){ return doio('w', ioctx);}static _SYSIO_OFF_Tnative_inop_pos(struct inode *ino, _SYSIO_OFF_T off){ struct native_inode *nino = I2NI(ino); int err; err = native_pos(nino->ni_fd, &off, SEEK_SET); return err < 0 ? err : off;}static intnative_inop_iodone(struct ioctx *ioctxp __IS_UNUSED){ /* * It's always done in this driver. It completed when posted. */ return 1;}static intnative_inop_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn){ struct native_inode *nino = I2NI(ino); long arg; int err; if (nino->ni_fd < 0) abort(); err = 0; switch (cmd) { case F_GETFD: case F_GETFL:#ifdef F_GETOWN case F_GETOWN:#endif *rtn = syscall(SYSIO_SYS_fcntl, nino->ni_fd, cmd); if (*rtn == -1) err = -errno; break; case F_DUPFD: case F_SETFD: case F_SETFL: case F_GETLK: case F_SETLK: case F_SETLKW:#ifdef F_SETOWN case F_SETOWN:#endif arg = va_arg(ap, long); *rtn = syscall(SYSIO_SYS_fcntl, nino->ni_fd, cmd, arg); if (*rtn == -1) err = -errno; break; default: *rtn = -1; err = -EINVAL; } return err;}static intnative_inop_mknod(struct pnode *pno __IS_UNUSED, mode_t mode __IS_UNUSED, dev_t dev __IS_UNUSED){ return -ENOSYS;}#ifdef _HAVE_STATVFSstatic intnative_inop_statvfs(struct pnode *pno, struct inode *ino, struct intnl_statvfs *buf){ char *path; int rc; struct statfs fs; path = NULL; if (!ino || I2NI(ino)->ni_fd < 0) { path = _sysio_pb_path(pno->p_base, '/'); if (!path) return -ENOMEM; } /* * The syscall interface does not support SYSIO_SYS_fstatvfs. * Should possibly return ENOSYS, but thought it * 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(SYSIO_SYS_statfs, path, &fs) : syscall(SYSIO_SYS_fstatfs, I2NI(ino)->ni_fd, &fs); if (path) free(path); if (rc < 0) return -errno; buf->f_bsize = fs.f_bsize; /* file system block size */ buf->f_frsize = fs.f_bsize; /* file system fundamental block size */ buf->f_blocks = fs.f_blocks; buf->f_bfree = fs.f_bfree; buf->f_bavail = fs.f_bavail; buf->f_files = fs.f_files; /* Total number serial numbers */ buf->f_ffree = fs.f_ffree; /* Number free serial numbers */ buf->f_favail = fs.f_ffree; /* Number free ser num for non-privileged*/ buf->f_fsid = fs.f_fsid.__val[1]; buf->f_flag = 0; /* No equiv in statfs; maybe use type? */ buf->f_namemax = fs.f_namelen; return 0;}#endifstatic intnative_inop_sync(struct inode *ino){ int err; assert(I2NI(ino)->ni_fd >= 0); err = syscall(SYSIO_SYS_fsync, I2NI(ino)->ni_fd); if (err) err = -errno; return err;}static intnative_inop_datasync(struct inode *ino){ struct native_inode *nino; int err; nino = I2NI(ino); assert(nino->ni_fd >= 0);#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(SYSIO_SYS_fsync, I2NI(ino)->ni_fd);#endif if (err) err = -errno; return err;}#ifdef HAVE_LUSTRE_HACKstatic intnative_inop_ioctl(struct inode *ino, unsigned long int request, va_list ap){ struct native_inode *nino; long arg1, arg2, arg3, arg4; int rtn; 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); rtn = syscall(SYSIO_SYS_ioctl, I2NI(ino)->ni_fd, request, arg1, arg2, arg3, arg4); if (rtn < 0) rtn = -errno; return rtn;}#elsestatic intnative_inop_ioctl(struct inode *ino __IS_UNUSED, unsigned long int request __IS_UNUSED, va_list ap __IS_UNUSED){ /* * I'm lazy. Maybe implemented later. */ return -ENOTTY;}#endifstatic voidnative_inop_gone(struct inode *ino){ struct native_inode *nino = I2NI(ino); if (nino->ni_fd >= 0) (void )syscall(SYSIO_SYS_close, nino->ni_fd); free(ino->i_private);}static voidnative_fsop_gone(struct filesys *fs __IS_UNUSED){ free(fs->fs_private); /* * Do nothing. There is no private part maintained for the * native file interface. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -