[Cbe-oss-dev] [PATCH] libspe2 take 2: add assist calls for pread, pwrite, readv and writev
Patrick Mansfield
patmans at us.ibm.com
Sat Jun 23 02:02:01 EST 2007
Repost, added range check of the count argument, per Asayama-san's
review comment (thanks!).
Add assist calls for:
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
ssize_t readv(int fd, const struct iovec *vector, int count)
ssize_t writev(int fd, const struct iovec *vector, int count)
Signed-off-by: Patrick Mansfield <patmans at us.ibm.com>
Index: quilt-libspe2/spebase/default_posix1_handler.c
===================================================================
--- quilt-libspe2.orig/spebase/default_posix1_handler.c
+++ quilt-libspe2/spebase/default_posix1_handler.c
@@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <sys/timex.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <linux/limits.h>
@@ -156,6 +157,10 @@ enum {
SPE_POSIX1_UMASK,
SPE_POSIX1_UTIME,
SPE_POSIX1_UTIMES,
+ SPE_POSIX1_PREAD,
+ SPE_POSIX1_PWRITE,
+ SPE_POSIX1_READV,
+ SPE_POSIX1_WRITEV,
SPE_POSIX1_LAST_OPCODE,
};
#define SPE_POSIX1_NR_OPCODES \
@@ -264,6 +269,47 @@ static void spe_copy_dirent(struct spe_c
memcpy(spe_ent->d_name, ent->d_name, sizeof(spe_ent->d_name));
}
+/*
+ * Needs to be compiled with -D_XOPEN_SOURCE to get IOV_MAX, but that
+ * sounds bad: IOV_MAX is the maximum number of vectors for readv and
+ * writev calls.
+ */
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
+
+#define SPU_SSIZE_MAX 0x7fffffffL
+
+struct ls_iovec {
+ uint32_t iov_base;
+ uint32_t iov_len;
+};
+
+static int
+check_conv_spuvec(char *ls, struct iovec *vec, struct ls_iovec *lsvec, int
+ count)
+{
+ int i;
+ size_t sum;
+
+ if (count > IOV_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sum = 0;
+ for (i = 0; i < count; i++) {
+ vec[i].iov_base = GET_LS_PTR(lsvec[i].iov_base);
+ vec[i].iov_len = lsvec[i].iov_len;
+ if (sum + vec[i].iov_len > SPU_SSIZE_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ sum += vec[i].iov_len;
+ }
+ return 0;
+}
+
/**
* default_posix1_handler_stat
* @ls: base pointer to local store area.
@@ -2054,6 +2100,122 @@ int default_posix1_handler_utimes(char *
return 0;
}
+/**
+ * default_posix1_handler_pread
+ * @ls: base pointer to local store area.
+ * @opdata: POSIX.1 call opcode & data.
+ *
+ * Implement:
+ * ssize_t pread(int fd, void *buf, size_t count, off_t offset)
+ */
+int default_posix1_handler_pread(char *ls, unsigned long opdata)
+{
+ DECL_4_ARGS();
+ DECL_RET();
+ int fd;
+ void *buf;
+ size_t count;
+ off_t offset;
+ int rc;
+
+ DEBUG_PRINTF("%s\n", __func__);
+ fd = arg0->slot[0];
+ buf = GET_LS_PTR(arg1->slot[0]);
+ count = arg2->slot[0];
+ offset = arg3->slot[0];
+ rc = pread(fd, buf, count, offset);
+ PUT_LS_RC(rc, 0, 0, errno);
+ return 0;
+}
+
+/**
+ * default_posix1_handler_pwrite
+ * @ls: base pointer to local store area.
+ * @opdata: POSIX.1 call opcode & data.
+ *
+ * Implement:
+ * ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
+ */
+int default_posix1_handler_pwrite(char *ls, unsigned long opdata)
+{
+ DECL_4_ARGS();
+ DECL_RET();
+ int fd;
+ void *buf;
+ size_t count;
+ off_t offset;
+ ssize_t sz;
+ int rc;
+
+ DEBUG_PRINTF("%s\n", __func__);
+ fd = arg0->slot[0];
+ buf = GET_LS_PTR(arg1->slot[0]);
+ count = arg2->slot[0];
+ offset = arg3->slot[0];
+ sz = pwrite(fd, buf, count, offset);
+ rc = sz;
+ PUT_LS_RC(rc, 0, 0, errno);
+ return 0;
+}
+
+/**
+ * default_posix1_handler_readv
+ * @ls: base pointer to local store area.
+ * @opdata: POSIX.1 call opcode & data.
+ *
+ * Implement:
+ * ssize_t readv(int fd, const struct iovec *vec, int count)
+ */
+int default_posix1_handler_readv(char *ls, unsigned long opdata)
+{
+ DECL_3_ARGS();
+ DECL_RET();
+ int fd;
+ struct iovec vec[IOV_MAX];
+ struct ls_iovec *lsvec;
+ size_t count;
+ int rc;
+
+ DEBUG_PRINTF("%s\n", __func__);
+ fd = arg0->slot[0];
+ lsvec = GET_LS_PTR(arg1->slot[0]);
+ count = arg2->slot[0];
+ rc = check_conv_spuvec(ls, vec, lsvec, count);
+ if (!rc)
+ rc = readv(fd, vec, count);
+ PUT_LS_RC(rc, 0, 0, errno);
+ return 0;
+}
+
+/**
+ * default_posix1_handler_writev
+ * @ls: base pointer to local store area.
+ * @opdata: POSIX.1 call opcode & data.
+ *
+ * Implement:
+ * ssize_t writev(int fd, const struct iovec *vec, int count)
+ */
+int default_posix1_handler_writev(char *ls, unsigned long opdata)
+{
+ DECL_3_ARGS();
+ DECL_RET();
+ int fd;
+ struct iovec vec[IOV_MAX];
+ struct ls_iovec *lsvec;
+ size_t count;
+ int rc;
+
+ DEBUG_PRINTF("%s\n", __func__);
+ fd = arg0->slot[0];
+ lsvec = GET_LS_PTR(arg1->slot[0]);
+ count = arg2->slot[0];
+ rc = check_conv_spuvec(ls, vec, lsvec, count);
+ if (!rc)
+ rc = writev(fd, vec, count);
+ PUT_LS_RC(rc, 0, 0, errno);
+ return 0;
+}
+
int (*default_posix1_funcs[SPE_POSIX1_NR_OPCODES]) (char *, unsigned long) = {
[SPE_POSIX1_UNUSED] = NULL,
[SPE_POSIX1_ADJTIMEX] = default_posix1_handler_adjtimex,
@@ -2120,6 +2282,10 @@ int (*default_posix1_funcs[SPE_POSIX1_NR
[SPE_POSIX1_UMASK] = default_posix1_handler_umask,
[SPE_POSIX1_UTIME] = default_posix1_handler_utime,
[SPE_POSIX1_UTIMES] = default_posix1_handler_utimes,
+ [SPE_POSIX1_PREAD] = default_posix1_handler_pread,
+ [SPE_POSIX1_PWRITE] = default_posix1_handler_pwrite,
+ [SPE_POSIX1_READV] = default_posix1_handler_readv,
+ [SPE_POSIX1_WRITEV] = default_posix1_handler_writev,
};
/**
Index: quilt-libspe2/spebase/default_posix1_handler.h
===================================================================
--- quilt-libspe2.orig/spebase/default_posix1_handler.h
+++ quilt-libspe2/spebase/default_posix1_handler.h
@@ -87,5 +87,9 @@ extern int default_posix1_handler_sched_
extern int default_posix1_handler_umask(char *ls, unsigned long args);
extern int default_posix1_handler_utime(char *ls, unsigned long args);
extern int default_posix1_handler_utimes(char *ls, unsigned long args);
+extern int default_posix1_handler_pread(char *ls, unsigned long args);
+extern int default_posix1_handler_pwrite(char *ls, unsigned long args);
+extern int default_posix1_handler_readv(char *ls, unsigned long args);
+extern int default_posix1_handler_writev(char *ls, unsigned long args);
#endif /* __DEFAULT_POSIX1_HANDLER_H__ */
More information about the cbe-oss-dev
mailing list