]>
Commit | Line | Data |
---|---|---|
0b3cf046 | 1 | #include <sys/sysmacros.h> |
2 | #include "config.h" | |
3 | ||
4 | /* | |
5 | * XXX: currently borrrowed from libsolcompat until this | |
6 | * can be adapted to the linux kernel interfaces. | |
7 | */ | |
8 | #if 0 | |
9 | /* | |
10 | * ========================================================================= | |
11 | * vnode operations | |
12 | * ========================================================================= | |
13 | */ | |
14 | /* | |
15 | * Note: for the xxxat() versions of these functions, we assume that the | |
16 | * starting vp is always rootdir (which is true for spa_directory.c, the only | |
17 | * ZFS consumer of these interfaces). We assert this is true, and then emulate | |
18 | * them by adding '/' in front of the path. | |
19 | */ | |
20 | ||
21 | /*ARGSUSED*/ | |
22 | int | |
23 | vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) | |
24 | { | |
25 | int fd; | |
26 | vnode_t *vp; | |
27 | int old_umask; | |
28 | char realpath[MAXPATHLEN]; | |
29 | struct stat64 st; | |
30 | ||
31 | /* | |
32 | * If we're accessing a real disk from userland, we need to use | |
33 | * the character interface to avoid caching. This is particularly | |
34 | * important if we're trying to look at a real in-kernel storage | |
35 | * pool from userland, e.g. via zdb, because otherwise we won't | |
36 | * see the changes occurring under the segmap cache. | |
37 | * On the other hand, the stupid character device returns zero | |
38 | * for its size. So -- gag -- we open the block device to get | |
39 | * its size, and remember it for subsequent VOP_GETATTR(). | |
40 | */ | |
41 | #if defined(__sun__) || defined(__sun) | |
42 | if (strncmp(path, "/dev/", 5) == 0) { | |
43 | #else | |
44 | if (0) { | |
45 | #endif | |
46 | char *dsk; | |
47 | fd = open64(path, O_RDONLY); | |
48 | if (fd == -1) | |
49 | return (errno); | |
50 | if (fstat64(fd, &st) == -1) { | |
51 | close(fd); | |
52 | return (errno); | |
53 | } | |
54 | close(fd); | |
55 | (void) sprintf(realpath, "%s", path); | |
56 | dsk = strstr(path, "/dsk/"); | |
57 | if (dsk != NULL) | |
58 | (void) sprintf(realpath + (dsk - path) + 1, "r%s", | |
59 | dsk + 1); | |
60 | } else { | |
61 | (void) sprintf(realpath, "%s", path); | |
62 | if (!(flags & FCREAT) && stat64(realpath, &st) == -1) | |
63 | return (errno); | |
64 | } | |
65 | ||
66 | #ifdef __linux__ | |
67 | if (!(flags & FCREAT) && S_ISBLK(st.st_mode)) { | |
68 | flags |= O_DIRECT; | |
69 | if (flags & FWRITE) | |
70 | flags |= O_EXCL; | |
71 | } | |
72 | #endif | |
73 | ||
74 | if (flags & FCREAT) | |
75 | old_umask = umask(0); | |
76 | ||
77 | /* | |
78 | * The construct 'flags - FREAD' conveniently maps combinations of | |
79 | * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. | |
80 | */ | |
81 | fd = open64(realpath, flags - FREAD, mode); | |
82 | ||
83 | if (flags & FCREAT) | |
84 | (void) umask(old_umask); | |
85 | ||
86 | if (fd == -1) | |
87 | return (errno); | |
88 | ||
89 | if (fstat64(fd, &st) == -1) { | |
90 | close(fd); | |
91 | return (errno); | |
92 | } | |
93 | ||
94 | (void) fcntl(fd, F_SETFD, FD_CLOEXEC); | |
95 | ||
96 | *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); | |
97 | ||
98 | vp->v_fd = fd; | |
99 | vp->v_size = st.st_size; | |
100 | vp->v_mode = st.st_mode; | |
101 | vp->v_path = spa_strdup(path); | |
102 | ||
103 | return (0); | |
104 | } | |
105 | ||
106 | /*ARGSUSED*/ | |
107 | int | |
108 | vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, | |
109 | int x3, vnode_t *startvp, int fd) | |
110 | { | |
111 | char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); | |
112 | int ret; | |
113 | ||
114 | ASSERT(startvp == rootdir); | |
115 | (void) sprintf(realpath, "/%s", path); | |
116 | ||
117 | /* fd ignored for now, need if want to simulate nbmand support */ | |
118 | ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); | |
119 | ||
120 | umem_free(realpath, strlen(path) + 2); | |
121 | ||
122 | return (ret); | |
123 | } | |
124 | ||
125 | /*ARGSUSED*/ | |
126 | int | |
127 | vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, | |
128 | int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) | |
129 | { | |
130 | ssize_t iolen, split; | |
131 | ||
132 | if (uio == UIO_READ) { | |
133 | iolen = pread64(vp->v_fd, addr, len, offset); | |
134 | } else { | |
135 | /* | |
136 | * To simulate partial disk writes, we split writes into two | |
137 | * system calls so that the process can be killed in between. | |
138 | */ | |
139 | #ifdef ZFS_DEBUG | |
140 | if (!S_ISBLK(vp->v_mode) && !S_ISCHR(vp->v_mode)) { | |
141 | split = (len > 0 ? rand() % len : 0); | |
142 | iolen = pwrite64(vp->v_fd, addr, split, offset); | |
143 | iolen += pwrite64(vp->v_fd, (char *)addr + split, | |
144 | len - split, offset + split); | |
145 | } else | |
146 | iolen = pwrite64(vp->v_fd, addr, len, offset); | |
147 | #else | |
148 | iolen = pwrite64(vp->v_fd, addr, len, offset); | |
149 | #endif | |
150 | } | |
151 | ||
152 | if (iolen < 0) | |
153 | return (errno); | |
154 | if (residp) | |
155 | *residp = len - iolen; | |
156 | else if (iolen != len) | |
157 | return (EIO); | |
158 | return (0); | |
159 | } | |
160 | ||
161 | void | |
162 | vn_close(vnode_t *vp) | |
163 | { | |
164 | close(vp->v_fd); | |
165 | spa_strfree(vp->v_path); | |
166 | umem_free(vp, sizeof (vnode_t)); | |
167 | } | |
168 | #endif |