xref: /titanic_50/usr/src/lib/libnsctl/common/cache.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/fcntl.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <signal.h>
32 #include <strings.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 
36 #include "libnsctl.h"
37 #include <nsctl.h>
38 
39 
40 static int _nsc_open_path(nsc_fd_t *);
41 static int _nsc_open_check(nsc_fd_t *);
42 
43 
44 /*
45  * Turn off ckdchk checking of nsc_open()'d volumes since we have no CKD
46  * formatted volumes right now.  If/when we come back with CKD volumes,
47  * we could do this more sanely by completing the implementation of the
48  * CKD module, and having nsc_open() prevent any non-NSC_CKD_DISK open
49  * of a CKD volume.
50  * -- Simon, Thu Feb 18 10:49:46 GMT 1999
51  */
52 static int ckdchk = 0;
53 
54 
55 nsc_fd_t *
nsc_open(path,flag,mode)56 nsc_open(path, flag, mode)
57 char *path;
58 int flag, mode;
59 {
60 	nsc_fd_t *fd;
61 
62 	if (strlen(path) >= NSC_MAXPATH) {
63 		errno = ENAMETOOLONG;
64 		return (0);
65 	}
66 
67 	if (!(fd = (nsc_fd_t *)calloc(1, sizeof (nsc_fd_t))))
68 		return (0);
69 
70 	if ((mode & O_ACCMODE) == O_WRONLY) {
71 		mode &= ~O_ACCMODE;
72 		mode |= O_RDWR;
73 	}
74 
75 	fd->sf_flag = flag;
76 	fd->sf_fmode = mode;
77 
78 	strcpy(fd->sf_path, path);
79 
80 	if (!_nsc_open_path(fd)) {
81 		free(fd);
82 		return (0);
83 	}
84 
85 	if (ckdchk && !_nsc_open_check(fd)) {
86 		(void) nsc_close(fd);
87 		return (0);
88 	}
89 
90 	return (fd);
91 }
92 
93 
94 nsc_fd_t *
nsc_fdopen(id,path,mode)95 nsc_fdopen(id, path, mode)
96 int id, mode;
97 char *path;
98 {
99 	struct flock lk;
100 	nsc_fd_t *fd;
101 	int i;
102 
103 	if (strlen(path) >= NSC_MAXPATH) {
104 		errno = ENAMETOOLONG;
105 		return (0);
106 	}
107 
108 	if (!(fd = (nsc_fd_t *)calloc(1, sizeof (nsc_fd_t))))
109 		return (0);
110 
111 	lk.l_type = F_WRLCK;
112 	lk.l_whence = SEEK_SET;
113 	lk.l_start = 0;
114 	lk.l_len = 0;
115 
116 	if (fcntl(id, F_SETLKW, &lk) < 0)
117 		return (0);
118 
119 	i = fcntl(id, F_GETFL);
120 
121 	if ((mode & O_ACCMODE) != O_RDONLY) {
122 		if ((i & O_ACCMODE) == O_RDONLY) {
123 			errno = EBADF;
124 			return (0);
125 		}
126 	}
127 
128 	if ((mode & O_ACCMODE) != O_WRONLY) {
129 		if ((i & O_ACCMODE) == O_WRONLY) {
130 			errno = EBADF;
131 			return (0);
132 		}
133 	}
134 
135 	mode = (i & O_ACCMODE) | (mode & ~O_ACCMODE);
136 
137 	if (fcntl(id, F_SETFL, mode) < 0)
138 		return (0);
139 
140 	if (lseek(id, 0, SEEK_SET) < 0)
141 		return (0);
142 
143 	fd->sf_fd = id;
144 	fd->sf_fmode = mode;
145 
146 	strcpy(fd->sf_path, path);
147 
148 	return (fd);
149 }
150 
151 
152 static int
_nsc_open_path(fd)153 _nsc_open_path(fd)
154 nsc_fd_t *fd;
155 {
156 	struct nscioc_open op;
157 
158 	memset(&op, 0, sizeof (op));
159 
160 	op.flag = fd->sf_flag;
161 	op.mode = fd->sf_fmode;
162 	strcpy(op.path, fd->sf_path);
163 
164 	if ((fd->sf_fd = open(_NSC_DEV_PATH, fd->sf_fmode)) < 0)
165 		return (0);
166 
167 	if (ioctl(fd->sf_fd, NSCIOC_OPEN, &op) == 0)
168 		return (1);
169 
170 	close(fd->sf_fd);
171 	return (0);
172 }
173 
174 
175 static int
_nsc_open_check(fd)176 _nsc_open_check(fd)
177 nsc_fd_t *fd;
178 {
179 	struct flock lk;
180 	char s[30];
181 	pid_t pid;
182 	int i;
183 
184 	if ((fd->sf_fmode & O_ACCMODE) == O_RDONLY)
185 		return (1);
186 
187 	if (access(_NSC_CKDCHK_PATH, X_OK) != 0)
188 		return (0);
189 
190 	lk.l_type = F_WRLCK;
191 	lk.l_whence = SEEK_SET;
192 	lk.l_start = 0;
193 	lk.l_len = 0;
194 
195 	if (fcntl(fd->sf_fd, F_SETLKW, &lk) < 0)
196 		return (0);
197 
198 	if ((pid = fork()) == 0) {
199 		for (i = 1; i <= NSIG; i++)
200 			signal(i, SIG_IGN);
201 
202 		for (i = fd->sf_fd; i <= 2 && (i = dup(i)) != -1; )
203 			fd->sf_fd = i;
204 
205 		for (i = sysconf(_SC_OPEN_MAX); i >= 0; i--)
206 			if (i != fd->sf_fd)
207 				close(i);
208 
209 		fcntl(fd->sf_fd, F_SETFD, 0);
210 
211 		(void) open("/dev/null", 0);
212 		(void) open(_NSC_CKDCHK_LOG, O_WRONLY|O_CREAT|O_APPEND, 0666);
213 		(void) open(_NSC_CKDCHK_LOG, O_WRONLY|O_CREAT|O_APPEND, 0666);
214 
215 		(void) sprintf(s, "%d", fd->sf_fd);
216 
217 		(void) execl(_NSC_CKDCHK_PATH, "ckdchk", "-u", "-F",
218 			s, fd->sf_path, 0);
219 
220 		exit(1);
221 	}
222 
223 	return (pid != -1);
224 }
225 
226 
227 int
nsc_close(fd)228 nsc_close(fd)
229 nsc_fd_t *fd;
230 {
231 	int rc;
232 
233 	if (!fd)
234 		return (0);
235 
236 	rc = close(fd->sf_fd);
237 	free(fd);
238 
239 	return (rc);
240 }
241 
242 
243 int
nsc_reserve(fd)244 nsc_reserve(fd)
245 nsc_fd_t *fd;
246 {
247 	return ((fd) ? ioctl(fd->sf_fd, NSCIOC_RESERVE, 0) : 0);
248 }
249 
250 
251 int
nsc_release(fd)252 nsc_release(fd)
253 nsc_fd_t *fd;
254 {
255 	if (!fd)
256 		return (0);
257 
258 	if (ckdchk && (fd->sf_fmode & O_ACCMODE) != O_RDONLY) {
259 		errno = EINVAL;
260 		return (-1);
261 	}
262 
263 	return (ioctl(fd->sf_fd, NSCIOC_RELEASE, 0));
264 }
265 
266 
267 int
nsc_partsize(nsc_fd_t * fd,nsc_size_t * rvp)268 nsc_partsize(nsc_fd_t *fd, nsc_size_t *rvp)
269 {
270 	struct nscioc_partsize partsize;
271 	int rc;
272 
273 	if (!fd)
274 		return (0);
275 
276 	rc = ioctl(fd->sf_fd, NSCIOC_PARTSIZE, &partsize);
277 	if (rc != 0) {
278 		return (rc);
279 	}
280 
281 	*rvp = (nsc_size_t)partsize.partsize;
282 	return (0);
283 }
284 
285 
286 int
nsc_fileno(fd)287 nsc_fileno(fd)
288 nsc_fd_t *fd;
289 {
290 	return ((fd) ? fd->sf_fd : -1);
291 }
292 
293 
294 void
_nsc_nocheck()295 _nsc_nocheck()
296 {
297 	ckdchk = 0;
298 }
299 
300 
301 static int
_nsc_do_ioctl(cmd,arg)302 _nsc_do_ioctl(cmd, arg)
303 int cmd;
304 void *arg;
305 {
306 	int fd, rc, save_errno;
307 
308 	fd = open(_NSC_DEV_PATH, O_RDONLY);
309 	if (fd < 0)
310 		return (-1);
311 
312 	rc = save_errno = 0;
313 	rc = ioctl(fd, cmd, arg);
314 	if (rc < 0)
315 		save_errno = errno;
316 
317 	close(fd);
318 
319 	errno = save_errno;
320 	return (rc);
321 }
322 
323 
324 /*
325  * int
326  * nsc_freeze(char *path)
327  *	Freeze a pathname
328  *
329  * Calling/Exit State:
330  *	Returns 0 for success, or -1 and sets errno.
331  *
332  * Description:
333  *	This is the user level interface to the nsctl freeze operation.
334  *	See uts/common/ns/nsctl/nsc_freeze.c for more information.
335  */
336 int
nsc_freeze(path)337 nsc_freeze(path)
338 char *path;
339 {
340 	if (strlen(path) >= NSC_MAXPATH) {
341 		errno = ENAMETOOLONG;
342 		return (-1);
343 	}
344 
345 	return (_nsc_do_ioctl(NSCIOC_FREEZE, path));
346 }
347 
348 /*
349  * int
350  * nsc_unfreeze(char *path)
351  *	Unfreeze a pathname
352  *
353  * Calling/Exit State:
354  *	Returns 0 for success, or -1 and sets errno.
355  *
356  * Description:
357  *	This is the user level interface to the nsctl unfreeze operation.
358  *	See uts/common/ns/nsctl/nsc_freeze.c for more information.
359  */
360 int
nsc_unfreeze(path)361 nsc_unfreeze(path)
362 char *path;
363 {
364 	if (strlen(path) >= NSC_MAXPATH) {
365 		errno = ENAMETOOLONG;
366 		return (-1);
367 	}
368 
369 	return (_nsc_do_ioctl(NSCIOC_UNFREEZE, path));
370 }
371 
372 
373 /*
374  * int
375  * nsc_isfrozen(char *path)
376  *	Test if a pathname is frozen
377  *
378  * Calling/Exit State:
379  *	Returns:
380  *		0	path is frozen
381  *		1	path is not frozen
382  *		-1	error (errno will be set)
383  *
384  * Description
385  *	This is the user level interface to to the nsctl isfrozen operation.
386  *	See uts/common/ns/nsctl/nsc_freeze.c for more information.
387  */
388 int
nsc_isfrozen(path)389 nsc_isfrozen(path)
390 char *path;
391 {
392 	if (strlen(path) >= NSC_MAXPATH) {
393 		errno = ENAMETOOLONG;
394 		return (-1);
395 	}
396 
397 	return (_nsc_do_ioctl(NSCIOC_ISFROZEN, path));
398 }
399 
400 int
nsc_gmem_sizes(int * size)401 nsc_gmem_sizes(int *size)
402 {
403 	return (_nsc_do_ioctl(NSCIOC_GLOBAL_SIZES, size));
404 }
405 
406 int
nsc_gmem_data(char * addr)407 nsc_gmem_data(char *addr)
408 {
409 	return (_nsc_do_ioctl(NSCIOC_GLOBAL_DATA, addr));
410 }
411 
412 /*
413  * int
414  * nsc_nvclean()
415  *	mark nvmem clean, to prevent a warmstart of the cache on reboot
416  */
417 int
nsc_nvclean(int force)418 nsc_nvclean(int force)
419 {
420 	int cmd;
421 
422 	cmd = force ? NSCIOC_NVMEM_CLEANF : NSCIOC_NVMEM_CLEAN;
423 
424 	return (_nsc_do_ioctl(cmd, (void *)0));
425 }
426