From 0d44747df99f2168a063feedad5039f222746f61 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Jan 2004 01:22:14 +0000 Subject: Patch based on work from James Peach to convert over to using pread/pwrite. Modified a little to ensure fsp->pos is correct. Fix for #889. Jeremy. (This used to be commit 019aaaf0df091c3f67048f591e70d4353a02bb9b) --- examples/VFS/skel_opaque.c | 12 ++ examples/VFS/skel_transparent.c | 10 ++ source3/include/smbprofile.h | 8 +- source3/include/vfs.h | 9 +- source3/include/vfs_macros.h | 6 + source3/lib/system.c | 41 +++++ source3/smbd/fileio.c | 23 +-- source3/smbd/vfs-wrap.c | 320 +++++++++++++++++++++++++--------------- source3/smbd/vfs.c | 43 ++++++ source3/utils/status.c | 6 + 10 files changed, 345 insertions(+), 133 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index de82801d85..310d305cee 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -111,11 +111,21 @@ static ssize_t skel_read(vfs_handle_struct *handle, files_struct *fsp, int fd, v return vfswrap_read(NULL, fsp, fd, data, n); } +static ssize_t skel_pread(vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset) +{ + return vfswrap_pread(NULL, fsp, fd, data, n, offset); +} + static ssize_t skel_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { return vfswrap_write(NULL, fsp, fd, data, n); } +ssize_t skel_pwrite(vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset) +{ + return vfswrap_pwrite(NULL, fsp, fd, data, n, offset); +} + static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { return vfswrap_lseek(NULL, fsp, filedes, offset, whence); @@ -488,7 +498,9 @@ static vfs_op_tuple skel_op_tuples[] = { {SMB_VFS_OP(skel_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_read), SMB_VFS_OP_READ, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(skel_pread), SMB_VFS_OP_PREAD, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_write), SMB_VFS_OP_WRITE, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(skel_pwrite), SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_lseek), SMB_VFS_OP_LSEEK, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_fsync), SMB_VFS_OP_FSYNC, SMB_VFS_LAYER_OPAQUE}, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 7a326741c5..448390e72f 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -110,11 +110,21 @@ static ssize_t skel_read(vfs_handle_struct *handle, files_struct *fsp, int fd, v return SMB_VFS_NEXT_READ(handle, fsp, fd, data, n); } +static ssize_t skel_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset) +{ + return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, offset); +} + static ssize_t skel_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { return SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n); } +static ssize_t skel_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset) +{ + return SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, offset); +} + static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { return SMB_VFS_NEXT_LSEEK(handle, fsp, filedes, offset, whence); diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index a64c2ce69e..c29a630fe5 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -34,7 +34,7 @@ enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH, #define PROF_SHMEM_KEY ((key_t)0x07021999) #define PROF_SHM_MAGIC 0x6349985 -#define PROF_SHM_VERSION 7 +#define PROF_SHM_VERSION 8 /* time values in the following structure are in microseconds */ @@ -60,9 +60,15 @@ struct profile_stats { unsigned syscall_read_count; unsigned syscall_read_time; unsigned syscall_read_bytes; /* bytes read with read syscall */ + unsigned syscall_pread_count; + unsigned syscall_pread_time; + unsigned syscall_pread_bytes; /* bytes read with pread syscall */ unsigned syscall_write_count; unsigned syscall_write_time; unsigned syscall_write_bytes; /* bytes written with write syscall */ + unsigned syscall_pwrite_count; + unsigned syscall_pwrite_time; + unsigned syscall_pwrite_bytes; /* bytes written with pwrite syscall */ unsigned syscall_lseek_count; unsigned syscall_lseek_time; unsigned syscall_sendfile_count; diff --git a/source3/include/vfs.h b/source3/include/vfs.h index dd489702aa..8caf64fd99 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -51,7 +51,8 @@ /* Changed to version 7 to include the get_nt_acl info parameter. JRA. */ /* Changed to version 8 includes EA calls. JRA. */ /* Changed to version 9 to include the get_shadow_data call. --metze */ -#define SMB_VFS_INTERFACE_VERSION 9 +/* Changed to version 10 to include pread/pwrite calls. */ +#define SMB_VFS_INTERFACE_VERSION 10 /* to bug old modules witch are trying to compile with the old functions */ @@ -107,7 +108,9 @@ typedef enum _vfs_op_type { SMB_VFS_OP_OPEN, SMB_VFS_OP_CLOSE, SMB_VFS_OP_READ, + SMB_VFS_OP_PREAD, SMB_VFS_OP_WRITE, + SMB_VFS_OP_PWRITE, SMB_VFS_OP_LSEEK, SMB_VFS_OP_SENDFILE, SMB_VFS_OP_RENAME, @@ -213,7 +216,9 @@ struct vfs_ops { int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode); int (*close)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n); + ssize_t (*pread)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset); ssize_t (*write)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n); + ssize_t (*pwrite)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset); SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence); ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count); int (*rename)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *old, const char *new); @@ -311,7 +316,9 @@ struct vfs_ops { struct vfs_handle_struct *open; struct vfs_handle_struct *close; struct vfs_handle_struct *read; + struct vfs_handle_struct *pread; struct vfs_handle_struct *write; + struct vfs_handle_struct *pwrite; struct vfs_handle_struct *lseek; struct vfs_handle_struct *sendfile; struct vfs_handle_struct *rename; diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index c4f63c352e..1ec1c5a778 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -46,7 +46,9 @@ #define SMB_VFS_OPEN(conn, fname, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (conn), (fname), (flags), (mode))) #define SMB_VFS_CLOSE(fsp, fd) ((fsp)->conn->vfs.ops.close((fsp)->conn->vfs.handles.close, (fsp), (fd))) #define SMB_VFS_READ(fsp, fd, data, n) ((fsp)->conn->vfs.ops.read((fsp)->conn->vfs.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pread((fsp)->conn->vfs.handles.pread, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_WRITE(fsp, fd, data, n) ((fsp)->conn->vfs.ops.write((fsp)->conn->vfs.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pwrite((fsp)->conn->vfs.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) #define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (conn), (old), (new))) @@ -142,7 +144,9 @@ #define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (conn), (fname), (flags), (mode))) #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) ((fsp)->conn->vfs_opaque.ops.close((fsp)->conn->vfs_opaque.handles.close, (fsp), (fd))) #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.read((fsp)->conn->vfs_opaque.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_OPAQUE_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pread((fsp)->conn->vfs_opaque.handles.pread, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.write((fsp)->conn->vfs_opaque.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_OPAQUE_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pwrite((fsp)->conn->vfs_opaque.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) #define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (conn), (old), (new))) @@ -238,7 +242,9 @@ #define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (conn), (fname), (flags), (mode))) #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) ((handle)->vfs_next.ops.close((handle)->vfs_next.handles.close, (fsp), (fd))) #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.read((handle)->vfs_next.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pread((handle)->vfs_next.handles.pread, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.write((handle)->vfs_next.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pwrite((handle)->vfs_next.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) #define SMB_VFS_NEXT_RENAME(handle, conn, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (conn), (old), (new))) diff --git a/source3/lib/system.c b/source3/lib/system.c index 577f0b9a20..16384c8bdf 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -100,6 +100,47 @@ ssize_t sys_write(int fd, const void *buf, size_t count) return ret; } + +/******************************************************************* +A pread wrapper that will deal with EINTR and 64-bit file offsets. +********************************************************************/ + +#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) +ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off) +{ + ssize_t ret; + + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64) + ret = pread64(fd, buf, count, off); +#else + ret = pread(fd, buf, count, off); +#endif + } while (ret == -1 && errno == EINTR); + return ret; +} +#endif + +/******************************************************************* +A write wrapper that will deal with EINTR and 64-bit file offsets. +********************************************************************/ + +#if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64) +ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off) +{ + ssize_t ret; + + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64) + ret = pwrite64(fd, buf, count, off); +#else + ret = pwrite(fd, buf, count, off); +#endif + } while (ret == -1 && errno == EINTR); + return ret; +} +#endif + /******************************************************************* A send wrapper that will deal with EINTR. ********************************************************************/ diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 84339c3a6f..f395954d05 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -95,16 +95,14 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) flush_write_cache(fsp, READ_FLUSH); - if (seek_file(fsp,pos) == -1) { - DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); - return(ret); - } - + fsp->pos = pos; + if (n > 0) { #ifdef DMF_FIX int numretries = 3; tryagain: - readret = SMB_VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); @@ -115,7 +113,8 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = SMB_VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + if (readret == -1) return -1; #endif @@ -143,10 +142,12 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ { ssize_t ret; - if ((pos != -1) && (seek_file(fsp,pos) == -1)) - return -1; - - ret = vfs_write_data(fsp,data,n); + if (pos == -1) + ret = vfs_write_data(fsp, data, n); + else { + fsp->pos = pos; + ret = vfs_pwrite_data(fsp, data, n, pos); + } DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 378a0a1e53..4f2d82734f 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -44,10 +44,10 @@ void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - SMB_BIG_UINT result; + SMB_BIG_UINT result; - result = sys_disk_free(path, small_query, bsize, dfree, dsize); - return result; + result = sys_disk_free(path, small_query, bsize, dfree, dsize); + return result; } int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) @@ -90,22 +90,22 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { - DIR *result; + DIR *result; - START_PROFILE(syscall_opendir); - result = opendir(fname); - END_PROFILE(syscall_opendir); - return result; + START_PROFILE(syscall_opendir); + result = opendir(fname); + END_PROFILE(syscall_opendir); + return result; } struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { - struct dirent *result; + struct dirent *result; - START_PROFILE(syscall_readdir); - result = readdir(dirp); - END_PROFILE(syscall_readdir); - return result; + START_PROFILE(syscall_readdir); + result = readdir(dirp); + END_PROFILE(syscall_readdir); + return result; } int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) @@ -133,71 +133,154 @@ int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char errno = saved_errno; } - END_PROFILE(syscall_mkdir); - return result; + END_PROFILE(syscall_mkdir); + return result; } int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_rmdir); - result = rmdir(path); - END_PROFILE(syscall_rmdir); - return result; + START_PROFILE(syscall_rmdir); + result = rmdir(path); + END_PROFILE(syscall_rmdir); + return result; } int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { - int result; + int result; - START_PROFILE(syscall_closedir); - result = closedir(dirp); - END_PROFILE(syscall_closedir); - return result; + START_PROFILE(syscall_closedir); + result = closedir(dirp); + END_PROFILE(syscall_closedir); + return result; } /* File operations */ int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { - int result; + int result; - START_PROFILE(syscall_open); - result = sys_open(fname, flags, mode); - END_PROFILE(syscall_open); - return result; + START_PROFILE(syscall_open); + result = sys_open(fname, flags, mode); + END_PROFILE(syscall_open); + return result; } int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { - int result; + int result; - START_PROFILE(syscall_close); + START_PROFILE(syscall_close); - result = close(fd); - END_PROFILE(syscall_close); - return result; + result = close(fd); + END_PROFILE(syscall_close); + return result; } ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) { - ssize_t result; + ssize_t result; - START_PROFILE_BYTES(syscall_read, n); - result = sys_read(fd, data, n); - END_PROFILE(syscall_read); - return result; + START_PROFILE_BYTES(syscall_read, n); + result = sys_read(fd, data, n); + END_PROFILE(syscall_read); + return result; +} + +ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) + START_PROFILE_BYTES(syscall_pread, n); + result = sys_pread(fd, data, n, offset); + END_PROFILE(syscall_pread); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->pos = 0; + } + +#else /* HAVE_PREAD */ + SMB_OFF_T curr; + int lerrno; + + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->pos = 0; + return result; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + errno = 0; + result = SMB_VFS_READ(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PREAD */ + + return result; } ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { - ssize_t result; + ssize_t result; + + START_PROFILE_BYTES(syscall_write, n); + result = sys_write(fd, data, n); + END_PROFILE(syscall_write); + return result; +} + +ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) + START_PROFILE_BYTES(syscall_pwrite, n); + result = sys_pwrite(fd, data, n, offset); + END_PROFILE(syscall_pwrite); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be sought on. */ + result = SMB_VFS_WRITE(fsp, fd, data, n); + } + +#else /* HAVE_PWRITE */ + SMB_OFF_T curr; + int lerrno; - START_PROFILE_BYTES(syscall_write, n); - result = sys_write(fd, data, n); - END_PROFILE(syscall_write); - return result; + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1) { + return -1; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + result = SMB_VFS_WRITE(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PWRITE */ + + return result; } SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) @@ -340,13 +423,12 @@ int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const cha int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) { #ifdef HAVE_FSYNC - int result; - - START_PROFILE(syscall_fsync); + int result; - result = fsync(fd); - END_PROFILE(syscall_fsync); - return result; + START_PROFILE(syscall_fsync); + result = fsync(fd); + END_PROFILE(syscall_fsync); + return result; #else return 0; #endif @@ -354,49 +436,49 @@ int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_stat); - result = sys_stat(fname, sbuf); - END_PROFILE(syscall_stat); - return result; + START_PROFILE(syscall_stat); + result = sys_stat(fname, sbuf); + END_PROFILE(syscall_stat); + return result; } int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_fstat); - result = sys_fstat(fd, sbuf); - END_PROFILE(syscall_fstat); - return result; + START_PROFILE(syscall_fstat); + result = sys_fstat(fd, sbuf); + END_PROFILE(syscall_fstat); + return result; } int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_lstat); - result = sys_lstat(path, sbuf); - END_PROFILE(syscall_lstat); - return result; + START_PROFILE(syscall_lstat); + result = sys_lstat(path, sbuf); + END_PROFILE(syscall_lstat); + return result; } int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_unlink); - result = unlink(path); - END_PROFILE(syscall_unlink); - return result; + START_PROFILE(syscall_unlink); + result = unlink(path); + END_PROFILE(syscall_unlink); + return result; } int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result; + int result; - START_PROFILE(syscall_chmod); + START_PROFILE(syscall_chmod); /* * We need to do this due to the fact that the default POSIX ACL @@ -415,9 +497,9 @@ int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char errno = saved_errno; } - result = chmod(path, mode); - END_PROFILE(syscall_chmod); - return result; + result = chmod(path, mode); + END_PROFILE(syscall_chmod); + return result; } int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) @@ -455,58 +537,57 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) { - int result; + int result; - START_PROFILE(syscall_chown); - result = sys_chown(path, uid, gid); - END_PROFILE(syscall_chown); - return result; + START_PROFILE(syscall_chown); + result = sys_chown(path, uid, gid); + END_PROFILE(syscall_chown); + return result; } int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) { #ifdef HAVE_FCHOWN - int result; - - START_PROFILE(syscall_fchown); + int result; - result = fchown(fd, uid, gid); - END_PROFILE(syscall_fchown); - return result; + START_PROFILE(syscall_fchown); + result = fchown(fd, uid, gid); + END_PROFILE(syscall_fchown); + return result; #else - errno = ENOSYS; - return -1; + errno = ENOSYS; + return -1; #endif } int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_chdir); - result = chdir(path); - END_PROFILE(syscall_chdir); - return result; + START_PROFILE(syscall_chdir); + result = chdir(path); + END_PROFILE(syscall_chdir); + return result; } char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) { - char *result; + char *result; - START_PROFILE(syscall_getwd); - result = sys_getwd(path); - END_PROFILE(syscall_getwd); - return result; + START_PROFILE(syscall_getwd); + result = sys_getwd(path); + END_PROFILE(syscall_getwd); + return result; } int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) { - int result; + int result; - START_PROFILE(syscall_utime); - result = utime(path, times); - END_PROFILE(syscall_utime); - return result; + START_PROFILE(syscall_utime); + result = utime(path, times); + END_PROFILE(syscall_utime); + return result; } /********************************************************************* @@ -643,33 +724,32 @@ int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - BOOL result; - - START_PROFILE(syscall_fcntl_lock); + BOOL result; - result = fcntl_lock(fd, op, offset, count,type); - END_PROFILE(syscall_fcntl_lock); - return result; + START_PROFILE(syscall_fcntl_lock); + result = fcntl_lock(fd, op, offset, count,type); + END_PROFILE(syscall_fcntl_lock); + return result; } int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { - int result; + int result; - START_PROFILE(syscall_symlink); - result = sys_symlink(oldpath, newpath); - END_PROFILE(syscall_symlink); - return result; + START_PROFILE(syscall_symlink); + result = sys_symlink(oldpath, newpath); + END_PROFILE(syscall_symlink); + return result; } int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) { - int result; + int result; - START_PROFILE(syscall_readlink); - result = sys_readlink(path, buf, bufsiz); - END_PROFILE(syscall_readlink); - return result; + START_PROFILE(syscall_readlink); + result = sys_readlink(path, buf, bufsiz); + END_PROFILE(syscall_readlink); + return result; } int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 753db4cece..2f981c743f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -71,7 +71,9 @@ static struct vfs_ops default_vfs = { vfswrap_open, vfswrap_close, vfswrap_read, + vfswrap_pread, vfswrap_write, + vfswrap_pwrite, vfswrap_lseek, vfswrap_sendfile, vfswrap_rename, @@ -429,6 +431,28 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) return (ssize_t)total; } +ssize_t vfs_pread_data(files_struct *fsp, char *buf, + size_t byte_count, SMB_OFF_T offset) +{ + size_t total=0; + + while (total < byte_count) + { + ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fd, buf + total, + byte_count - total, offset + total); + + if (ret == 0) return total; + if (ret == -1) { + if (errno == EINTR) + continue; + else + return -1; + } + total += ret; + } + return (ssize_t)total; +} + /**************************************************************************** Write data to a fd on the vfs. ****************************************************************************/ @@ -451,6 +475,25 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) return (ssize_t)total; } +ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer, + size_t N, SMB_OFF_T offset) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + ret = SMB_VFS_PWRITE(fsp, fsp->fd, buffer + total, + N - total, offset + total); + + if (ret == -1) + return -1; + if (ret == 0) + return total; + + total += ret; + } + return (ssize_t)total; +} /**************************************************************************** An allocate file space call using the vfs interface. Allocates space for a file from a filedescriptor. diff --git a/source3/utils/status.c b/source3/utils/status.c index 54dce1ecf0..4585b101b2 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -197,6 +197,12 @@ static int profile_dump(void) d_printf("write_count: %u\n", profile_p->syscall_write_count); d_printf("write_time: %u\n", profile_p->syscall_write_time); d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes); + d_printf("pread_count: %u\n", profile_p->syscall_pread_count); + d_printf("pread_time: %u\n", profile_p->syscall_pread_time); + d_printf("pread_bytes: %u\n", profile_p->syscall_pread_bytes); + d_printf("pwrite_count: %u\n", profile_p->syscall_pwrite_count); + d_printf("pwrite_time: %u\n", profile_p->syscall_pwrite_time); + d_printf("pwrite_bytes: %u\n", profile_p->syscall_pwrite_bytes); #ifdef WITH_SENDFILE d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count); d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time); -- cgit