diff options
author | Brian Behlendorf <[email protected]> | 2010-08-26 11:56:53 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2010-08-31 13:42:00 -0700 |
commit | d603ed6c278f9c25b17ba8e75e9bce6e5d715ac0 (patch) | |
tree | 61dc04f07ed9772dd97faefd879412e2a6578be0 /lib/libzpool/kernel.c | |
parent | f1fb119f6bb0c3185ec88912e4488fdd9ec08ab2 (diff) |
Add linux user disk support
This topic branch contains all the changes needed to integrate the user
side zfs tools with Linux style devices. Primarily this includes fixing
up the Solaris libefi library to be Linux friendly, and integrating with
the libblkid library which is provided by e2fsprogs.
Signed-off-by: Brian Behlendorf <[email protected]>
Diffstat (limited to 'lib/libzpool/kernel.c')
-rw-r--r-- | lib/libzpool/kernel.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 494e544ea..6f06f4001 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -35,6 +35,8 @@ #include <sys/processor.h> #include <sys/zfs_context.h> #include <sys/utsname.h> +#include <sys/time.h> +#include <sys/mount.h> /* for BLKGETSIZE64 */ #include <sys/systeminfo.h> /* @@ -533,7 +535,11 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) * for its size. So -- gag -- we open the block device to get * its size, and remember it for subsequent VOP_GETATTR(). */ +#if defined(__sun__) || defined(__sun) if (strncmp(path, "/dev/", 5) == 0) { +#else + if (0) { +#endif char *dsk; fd = open64(path, O_RDONLY); if (fd == -1) { @@ -562,6 +568,14 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) } } + if (!(flags & FCREAT) && S_ISBLK(st.st_mode)) { +#ifdef __linux__ + flags |= O_DIRECT; +#endif + /* We shouldn't be writing to block devices in userspace */ + VERIFY(!(flags & FWRITE)); + } + if (flags & FCREAT) old_umask = umask(0); @@ -584,6 +598,16 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) return (err); } +#ifdef __linux__ + /* In Linux, use an ioctl to get the size of a block device. */ + if (S_ISBLK(st.st_mode)) { + if (ioctl(fd, BLKGETSIZE64, &st.st_size) != 0) { + err = errno; + close(fd); + return (err); + } + } +#endif (void) fcntl(fd, F_SETFD, FD_CLOEXEC); *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); @@ -637,6 +661,16 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, } } +#ifdef __linux__ + if (rc == -1 && errno == EINVAL) { + /* + * Under Linux, this most likely means an alignment issue + * (memory or disk) due to O_DIRECT, so we abort() in order to + * catch the offender. + */ + abort(); + } +#endif if (rc == -1) return (errno); |