4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Common subroutines used by the programs in these subdirectories.
46 #include <sys/types.h>
50 #include <sys/param.h>
52 #include <sys/fcntl.h>
53 #include <sys/mount.h>
54 #include <sys/mntent.h>
55 #include <sys/mnttab.h>
57 #include <sys/fs/cachefs_fs.h>
65 * Gets a lock on the cache directory.
66 * To release the lock, call cachefs_dir_unlock
67 * with the returned value.
69 * cachedirp name of the cache directory
70 * shared 1 if shared, 0 if not
72 * Returns -1 if the lock cannot be obtained immediatly.
73 * If the lock is obtained, returns a value >= 0.
79 cachefs_dir_lock(const char *cachedirp
, int shared
)
89 /* make a path prefix to the cache directory lock file */
90 strp
= CACHEFS_ROOTRUN
;
91 xx
= stat(strp
, &statb
);
92 if ((xx
< 0) || ((statb
.st_mode
& S_IFMT
) != S_IFDIR
))
96 len
= snprintf(buf
, sizeof (buf
), "%s/%s", strp
, CACHEFS_LOCKDIR_PRE
);
98 if (strlcat(buf
, cachedirp
, sizeof (buf
)) >= sizeof (buf
)) {
99 pr_err(gettext("Cache directory name %s is too long"),
106 while (strp
= strchr(strp
, '/')) { /* convert path to a file */
111 * Create and open the cache directory lock file.
112 * This file will be <2G.
114 fd
= open(buf
, O_RDWR
| O_CREAT
, 0700);
116 pr_err(gettext("Cannot open lock file %s"), buf
);
120 /* try to set the lock */
121 fl
.l_type
= (shared
== 1) ? F_RDLCK
: F_WRLCK
;
127 /* CACHEFS_LOCK_FILE will be <2GB */
128 xx
= fcntl(fd
, F_SETLKW
, &fl
);
130 if (errno
== EAGAIN
) {
131 pr_err(gettext("Cannot gain access to the "
132 "cache directory %s."), cachedirp
);
134 pr_err(gettext("Unexpected failure on lock file %s %s"),
135 buf
, strerror(errno
));
141 /* return the file descriptor which can be used to release the lock */
150 * Releases an advisory lock on the cache directory.
152 * fd cookie returned by cachefs_dir_lock
154 * Returns -1 if the lock cannot be released or 0 for success.
159 cachefs_dir_unlock(int fd
)
165 /* release the lock */
172 /* fd will be <2GB */
173 xx
= fcntl(fd
, F_SETLK
, &fl
);
175 pr_err(gettext("Unexpected failure releasing lock file %s"),
180 /* close the lock file */
188 * cachefs_label_file_get
191 * Gets the contents of a cache label file.
192 * Performs error checking on the file.
194 * filep name of the cache label file
195 * clabelp where to put the file contents
197 * Returns 0 for success or -1 if an error occurs.
204 cachefs_label_file_get(const char *filep
, struct cache_label
*clabelp
)
208 struct stat64 statinfo
;
210 /* get info on the file */
211 xx
= lstat64(filep
, &statinfo
);
213 if (errno
!= ENOENT
) {
214 pr_err(gettext("Cannot stat file %s: %s"),
215 filep
, strerror(errno
));
217 pr_err(gettext("File %s does not exist."), filep
);
223 /* if the file is the wrong type */
224 if (!S_ISREG(statinfo
.st_mode
)) {
225 pr_err(gettext("Cache label file %s corrupted"), filep
);
229 /* if the file is the wrong size; it will be <2GB */
230 if (statinfo
.st_size
!= (offset_t
)sizeof (struct cache_label
)) {
231 pr_err(gettext("Cache label file %s wrong size"), filep
);
235 /* open the cache label file */
236 fd
= open(filep
, O_RDONLY
);
238 pr_err(gettext("Error opening %s: %s"), filep
,
243 /* read the current set of parameters */
244 xx
= read(fd
, clabelp
, sizeof (struct cache_label
));
245 if (xx
!= sizeof (struct cache_label
)) {
246 pr_err(gettext("Reading %s failed: %s\n"), filep
,
259 * cachefs_label_file_put
262 * Outputs the contents of a cache label object to a file.
264 * filep name of the cache label file
265 * clabelp where to get the file contents
267 * Returns 0 for success or -1 if an error occurs.
274 cachefs_label_file_put(const char *filep
, struct cache_label
*clabelp
)
279 /* get rid of the file if it already exists */
281 if ((xx
== -1) && (errno
!= ENOENT
)) {
282 pr_err(gettext("Could not remove %s: %s"), filep
,
287 /* open the cache label file; this file will be <2GB */
288 fd
= open(filep
, O_CREAT
| O_RDWR
, 0600);
290 pr_err(gettext("Error creating %s: %s"), filep
,
295 /* write out the cache label object */
296 xx
= write(fd
, clabelp
, sizeof (struct cache_label
));
297 if (xx
!= sizeof (struct cache_label
)) {
298 pr_err(gettext("Writing %s failed: %s"), filep
,
304 /* make sure the contents get to disk */
305 if (fsync(fd
) != 0) {
306 pr_err(gettext("Writing %s failed on sync: %s"), filep
,
319 cachefs_label_file_vcheck(char *filep
, struct cache_label
*clabelp
)
321 /* check for an invalid version number */
322 if (clabelp
->cl_cfsversion
!= CFSVERSION
) {
323 pr_err(gettext("Cache label file %s corrupted"), filep
);
335 * Tests whether or not the cache directory is in use by
336 * the cache file system.
338 * cachedirp name of the file system cache directory
340 * Returns 1 if the cache is in use or an error, 0 if not.
346 cachefs_inuse(const char *cachedirp
)
350 char buf
[MAXPATHLEN
];
351 char *lockp
= CACHEFS_LOCK_FILE
;
354 /* see if path name is too long */
355 xx
= strlen(cachedirp
) + strlen(lockp
) + 3;
356 if (xx
>= MAXPATHLEN
) {
357 pr_err(gettext("Cache directory name %s is too long"),
362 /* make a path to the cache directory lock file */
363 snprintf(buf
, sizeof (buf
), "%s/%s", cachedirp
, lockp
);
365 /* Open the kernel in use lock file. This file will be <2GB. */
366 fd
= open(buf
, O_RDWR
, 0700);
368 pr_err(gettext("Cannot open lock file %s"), buf
);
372 /* test the lock status */
379 xx
= fcntl(fd
, F_GETLK
, &fl
);
381 pr_err(gettext("Unexpected failure on lock file %s %s"),
382 buf
, strerror(errno
));
388 if (fl
.l_type
== F_UNLCK
)
393 /* return whether or not the cache is in use */
399 * cachefs_resouce_size
402 * Returns information about a resource file.
404 * maxinodes number of inodes to be managed by the resource file
405 * rinfop set to info about the resource file
412 cachefs_resource_size(int maxinodes
, struct cachefs_rinfo
*rinfop
)
418 rinfop
->r_ptroffset
= fsize
;
420 fsize
+= MAXBSIZE
* (maxinodes
/ CACHEFS_RLPMBS
);
421 if ((maxinodes
% CACHEFS_RLPMBS
) != 0)
424 rinfop
->r_fsize
= fsize
;
429 * cachefs_create_cache
432 * Creates the specified cache directory and populates it as
435 * dirp the name of the cache directory
436 * uv user values (may be NULL)
437 * clabel label file contents, or placeholder for this
439 * Returns 0 for success or:
441 * -2 for an error and cache directory partially created
447 cachefs_create_cache(char *dirp
, struct cachefs_user_values
*uv
,
448 struct cache_label
*clabel
)
451 char path
[CACHEFS_XMAXPATH
];
455 struct cache_usage cu
;
458 struct statvfs64 svfs
;
464 /* make sure cache dir name is not too long */
465 if (strlen(dirp
) > (size_t)PATH_MAX
) {
466 pr_err(gettext("path name %s is too long."), dirp
);
470 /* ensure the path isn't in cachefs */
471 parent
= cachefs_file_to_dir(dirp
);
472 if (parent
== NULL
) {
473 pr_err(gettext("Out of memory"));
476 if (statvfs64(parent
, &svfs
) != 0) {
477 pr_err(gettext("%s: %s"), parent
, strerror(errno
));
481 if (strcmp(svfs
.f_basetype
, CACHEFS_BASETYPE
) == 0) {
482 pr_err(gettext("Cannot create cache in cachefs filesystem"));
488 /* make the directory */
489 if (mkdir(dirp
, 0) == -1) {
492 pr_err(gettext("%s already exists."), dirp
);
496 pr_err(gettext("mkdir %s failed: %s"),
497 dirp
, strerror(errno
));
501 cu
.cu_filesused
+= 1;
504 /* convert user values to a cache_label */
506 xx
= cachefs_convert_uv2cl(uv
, clabel
, dirp
);
512 * Create the cache directory lock file.
513 * Used by the kernel module to indicate the cache is in use.
514 * This file will be <2G.
516 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_LOCK_FILE
);
517 fd
= open(path
, O_RDWR
| O_CREAT
, 0700);
519 pr_err(gettext("Cannot create lock file %s"), path
);
524 /* make the directory for the back file system mount points */
525 /* note: we do not count this directory in the resources */
526 snprintf(path
, sizeof (path
), "%s/%s", dirp
, BACKMNT_NAME
);
527 if (mkdir(path
, 0700) == -1) {
528 pr_err(gettext("mkdir %s failed: %s"), path
,
533 /* make the directory for lost+found */
534 /* note: we do not count this directory in the resources */
535 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_LOSTFOUND_NAME
);
536 if (mkdir(path
, 0700) == -1) {
537 pr_err(gettext("mkdir %s failed: %s"), path
,
542 /* make the networker "don't back up" file; this file is <2GB */
544 snprintf(path
, sizeof (path
), "%s/%s", dirp
, NOBACKUP_NAME
);
545 if ((fp
= fopen(path
, "w")) != NULL
) {
546 if (realpath(dirp
, path
) != NULL
) {
547 fprintf(fp
, "<< ./ >>\n");
548 fprintf(fp
, "+skip: .?* *\n");
554 snprintf(path
, sizeof (path
), "%s/%s", dirp
, NOBACKUP_NAME
);
555 pr_err(gettext("can't create %s"), path
);
558 cu
.cu_filesused
+= 1;
562 /* create the unmount file */
564 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_UNMNT_FILE
);
565 if ((fp
= fopen(path
, "w")) != NULL
) {
568 btime
= get_boottime();
569 fwrite((void *)&btime
, sizeof (btime
), 1, fp
);
574 pr_err(gettext("can't create .cfs_unmnt file"));
576 /* create the cache label file */
577 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHELABEL_NAME
);
578 xx
= cachefs_label_file_put(path
, clabel
);
580 pr_err(gettext("creating %s failed."), path
);
583 cu
.cu_filesused
+= 1;
586 /* create the cache label duplicate file */
587 snprintf(path
, sizeof (path
), "%s/%s.dup", dirp
, CACHELABEL_NAME
);
588 xx
= cachefs_label_file_put(path
, clabel
);
590 pr_err(gettext("creating %s failed."), path
);
593 cu
.cu_filesused
+= 1;
596 /* create the resouce file; this file will be <2GB */
597 snprintf(path
, sizeof (path
), "%s/%s", dirp
, RESOURCE_NAME
);
598 fd
= open(path
, O_CREAT
| O_RDWR
, 0600);
600 pr_err(gettext("create %s failed: %s"), path
,
604 cu
.cu_filesused
+= 1;
606 /* allocate a zeroed buffer for filling the resouce file */
607 bufp
= calloc(1, MAXBSIZE
);
609 pr_err(gettext("out of space %d."), MAXBSIZE
);
614 /* determine number of MAXBSIZE chunks to make the file */
615 cnt
= 1; /* for the header */
616 cnt
+= clabel
->cl_maxinodes
/ CACHEFS_RLPMBS
;
617 if ((clabel
->cl_maxinodes
% CACHEFS_RLPMBS
) != 0)
620 /* fill up the file with zeros */
621 for (xx
= 0; xx
< cnt
; xx
++) {
622 if (write(fd
, bufp
, MAXBSIZE
) != MAXBSIZE
) {
623 pr_err(gettext("write %s failed: %s"), path
,
631 cu
.cu_blksused
+= cnt
;
633 /* position to the begining of the file */
634 if (lseek(fd
, 0, SEEK_SET
) == -1) {
635 pr_err(gettext("lseek %s failed: %s"), path
,
641 /* write the cache usage structure */
642 xx
= sizeof (struct cache_usage
);
643 if (write(fd
, &cu
, xx
) != xx
) {
644 pr_err(gettext("cu write %s failed: %s"), path
,
650 /* make sure the contents get to disk */
651 if (fsync(fd
) != 0) {
652 pr_err(gettext("fsync %s failed: %s"), path
,
665 * cachefs_delete_all_cache
668 * Delete all caches in cache directory.
670 * dirp the pathname of of the cache directory to delete
672 * Returns 0 for success or -1 for an error.
678 cachefs_delete_all_cache(char *dirp
)
681 struct dirent64
*dep
;
683 char path
[CACHEFS_XMAXPATH
];
684 struct stat64 statinfo
;
686 /* make sure cache dir name is not too long */
687 if (strlen(dirp
) > (size_t)PATH_MAX
) {
688 pr_err(gettext("path name %s is too long."),
693 /* check that dirp is probably a cachefs directory */
694 snprintf(path
, sizeof (path
), "%s/%s", dirp
, BACKMNT_NAME
);
695 xx
= access(path
, R_OK
| W_OK
| X_OK
);
697 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHELABEL_NAME
);
698 xx
|= access(path
, R_OK
| W_OK
);
701 pr_err(gettext("%s does not appear to be a "
702 "cachefs cache directory."), dirp
);
706 /* remove the lost+found directory if it exists and is empty */
707 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_LOSTFOUND_NAME
);
710 if (errno
== EEXIST
) {
711 pr_err(gettext("Cannot delete cache '%s'. "
712 "First move files in '%s' to a safe location."),
715 } else if (errno
!= ENOENT
) {
716 pr_err(gettext("rmdir %s failed: %s"), path
,
722 /* delete the back FS mount point directory if it exists */
723 snprintf(path
, sizeof (path
), "%s/%s", dirp
, BACKMNT_NAME
);
724 xx
= lstat64(path
, &statinfo
);
726 if (errno
!= ENOENT
) {
727 pr_err(gettext("lstat %s failed: %s"), path
,
732 xx
= nftw64(path
, cachefs_delete_file
, 16,
733 FTW_PHYS
| FTW_DEPTH
| FTW_MOUNT
);
735 pr_err(gettext("unable to delete %s"), path
);
740 /* open the cache directory specified */
741 if ((dp
= opendir(dirp
)) == NULL
) {
742 pr_err(gettext("cannot open cache directory %s: %s"),
743 dirp
, strerror(errno
));
747 /* read the file names in the cache directory */
748 while ((dep
= readdir64(dp
)) != NULL
) {
749 /* ignore . and .. */
750 if (strcmp(dep
->d_name
, ".") == 0 ||
751 strcmp(dep
->d_name
, "..") == 0)
755 snprintf(path
, sizeof (path
), "%s/%s", dirp
, dep
->d_name
);
756 xx
= lstat64(path
, &statinfo
);
758 if (errno
== ENOENT
) {
759 /* delete_cache may have nuked a directory */
763 pr_err(gettext("lstat %s failed: %s"),
764 path
, strerror(errno
));
769 /* ignore anything that is not a link */
770 if (!S_ISLNK(statinfo
.st_mode
))
773 /* delete the file system cache directory */
774 xx
= cachefs_delete_cache(dirp
, dep
->d_name
);
782 /* remove the cache dir unmount file */
783 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_UNMNT_FILE
);
785 if ((xx
== -1) && (errno
!= ENOENT
)) {
786 pr_err(gettext("unlink %s failed: %s"), path
,
791 /* remove the cache label file */
792 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHELABEL_NAME
);
794 if ((xx
== -1) && (errno
!= ENOENT
)) {
795 pr_err(gettext("unlink %s failed: %s"), path
,
800 /* remove the cache label duplicate file */
801 snprintf(path
, sizeof (path
), "%s/%s.dup", dirp
, CACHELABEL_NAME
);
803 if ((xx
== -1) && (errno
!= ENOENT
)) {
804 pr_err(gettext("unlink %s failed: %s"), path
,
809 /* remove the resource file */
810 snprintf(path
, sizeof (path
), "%s/%s", dirp
, RESOURCE_NAME
);
812 if ((xx
== -1) && (errno
!= ENOENT
)) {
813 pr_err(gettext("unlink %s failed: %s"), path
,
818 /* remove the cachefslog file if it exists */
819 snprintf(path
, sizeof (path
), "%s/%s", dirp
, LOG_STATUS_NAME
);
822 /* remove the networker "don't back up" file if it exists */
823 snprintf(path
, sizeof (path
), "%s/%s", dirp
, NOBACKUP_NAME
);
826 /* remove the lock file */
827 snprintf(path
, sizeof (path
), "%s/%s", dirp
, CACHEFS_LOCK_FILE
);
829 if ((xx
== -1) && (errno
!= ENOENT
)) {
830 pr_err(gettext("unlink %s failed: %s"), path
,
835 /* remove the directory */
838 pr_err(gettext("rmdir %s failed: %s"), dirp
,
849 * cachefs_delete_cache
852 * Deletes the specified file system cache.
854 * dirp cache directory name
855 * namep file system cache directory to delete
857 * Returns 0 for success, -1 for failure.
864 cachefs_delete_cache(char *dirp
, char *namep
)
866 char path
[CACHEFS_XMAXPATH
];
867 char buf
[CACHEFS_XMAXPATH
];
869 struct stat64 statinfo
;
871 /* make sure cache dir name is not too long */
872 if (strlen(dirp
) > (size_t)PATH_MAX
) {
873 pr_err(gettext("path name %s is too long."),
878 /* construct the path name of the file system cache directory */
879 snprintf(path
, sizeof (path
), "%s/%s", dirp
, namep
);
881 /* stat the specified file */
882 xx
= lstat64(path
, &statinfo
);
884 pr_err(gettext("lstat %s failed: %s"), path
,
889 /* make sure name is a symbolic link */
890 if (!S_ISLNK(statinfo
.st_mode
)) {
891 pr_err(gettext("\"%s\" is not a valid cache id."), namep
);
895 /* read the contents of the symbolic link */
896 xx
= readlink(path
, buf
, sizeof (buf
));
898 pr_err(gettext("Readlink of %s failed: %s"), path
,
904 /* remove the directory */
905 snprintf(path
, sizeof (path
), "%s/%s", dirp
, buf
);
906 xx
= nftw64(path
, cachefs_delete_file
, 16,
907 FTW_PHYS
| FTW_DEPTH
| FTW_MOUNT
);
909 pr_err(gettext("directory walk of %s failed."), dirp
);
913 /* delete the link */
914 snprintf(path
, sizeof (path
), "%s/%s", dirp
, namep
);
915 if (unlink(path
) == -1) {
916 pr_err(gettext("unlink %s failed: %s"), path
,
927 * cachefs_delete_file
930 * Remove a file or directory; called by nftw64().
932 * namep pathname of the file
933 * statp stat info about the file
934 * flg info about file
935 * ftwp depth information
937 * Returns 0 for success, -1 for failure.
943 cachefs_delete_file(const char *namep
, const struct stat64
*statp
, int flg
,
946 /* ignore . and .. */
947 if (strcmp(namep
, ".") == 0 || strcmp(namep
, "..") == 0)
951 case FTW_F
: /* files */
953 if (unlink(namep
) == -1) {
954 pr_err(gettext("unlink %s failed: %s"),
955 namep
, strerror(errno
));
960 case FTW_DP
: /* directories that have their children processed */
961 if (rmdir(namep
) == -1) {
962 pr_err(gettext("rmdir %s failed: %s"),
963 namep
, strerror(errno
));
968 case FTW_D
: /* ignore directories if children not processed */
972 pr_err(gettext("failure on file %s, flg %d."),
983 * cachefs_convert_uv2cl
986 * Copies the contents of a cachefs_user_values object into a
987 * cache_label object, performing the necessary conversions.
989 * uvp cachefs_user_values to copy from
990 * clp cache_label to copy into
991 * dirp cache directory
993 * Returns 0 for success, -1 for an error.
1001 cachefs_convert_uv2cl(const struct cachefs_user_values
*uvp
,
1002 struct cache_label
*clp
, const char *dirp
)
1004 struct statvfs64 fs
;
1009 /* get file system information */
1010 xx
= statvfs64(dirp
, &fs
);
1012 pr_err(gettext("statvfs %s failed: %s"), dirp
,
1017 ftmp
= (double)fs
.f_frsize
/ (double)MAXBSIZE
;
1019 /* front fs is less than 1 terabyte */
1020 temp
= (double)uvp
->uv_maxblocks
/ 100.0 *
1021 (double)fs
.f_blocks
* ftmp
+ .5;
1022 clp
->cl_maxblks
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1024 temp
= (double)uvp
->uv_minblocks
/ 100.0 *
1025 (double)fs
.f_blocks
* ftmp
+ .5;
1026 clp
->cl_blockmin
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1028 temp
= (double)uvp
->uv_threshblocks
/ 100.0 *
1029 (double)fs
.f_blocks
* ftmp
+ .5;
1030 clp
->cl_blocktresh
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1032 temp
= (double)uvp
->uv_maxfiles
/ 100.0 * (double)fs
.f_files
+ .5;
1033 clp
->cl_maxinodes
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1035 temp
= (double)uvp
->uv_minfiles
/ 100.0 * (double)fs
.f_files
+ .5;
1036 clp
->cl_filemin
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1038 temp
= (double)uvp
->uv_threshfiles
/ 100.0 * (double)fs
.f_files
+.5;
1039 clp
->cl_filetresh
= temp
< (double)INT_MAX
? (int)temp
: INT_MAX
;
1041 ftmp
= (double)(1024 * 1024) / (double)MAXBSIZE
;
1042 clp
->cl_maxfiles
= uvp
->uv_maxfilesize
* ftmp
+ .5;
1044 clp
->cl_blkhiwat
= uvp
->uv_hiblocks
/ 100.0 * clp
->cl_maxblks
+ .5;
1045 clp
->cl_blklowat
= uvp
->uv_lowblocks
/ 100.0 * clp
->cl_maxblks
+ .5;
1047 clp
->cl_filehiwat
= uvp
->uv_hifiles
/ 100.0 * clp
->cl_maxinodes
+ .5;
1048 clp
->cl_filelowat
= uvp
->uv_lowfiles
/ 100.0 * clp
->cl_maxinodes
+ .5;
1050 clp
->cl_cfsversion
= CFSVERSION
;
1052 /* return success */
1058 * cachefs_convert_cl2uv
1061 * Copies the contents of a cache_label object into a
1062 * cachefs_user_values object, performing the necessary conversions.
1064 * clp cache_label to copy from
1065 * uvp cachefs_user_values to copy into
1066 * dirp cache directory
1068 * Returns 0 for success, -1 for an error.
1076 cachefs_convert_cl2uv(const struct cache_label
*clp
,
1077 struct cachefs_user_values
*uvp
, const char *dirp
)
1079 struct statvfs64 fs
;
1085 /* get file system information */
1086 xx
= statvfs64(dirp
, &fs
);
1088 pr_err(gettext("statvfs %s failed: %s"), dirp
,
1094 yy = (yy < 0) ? 0 : yy; \
1095 yy = (yy > 100) ? 100 : yy;
1097 ftmp
= (double)MAXBSIZE
/ (double)fs
.f_frsize
;
1099 temp
= (double)clp
->cl_maxblks
* ftmp
/
1100 (double)fs
.f_blocks
* 100. + .5;
1102 uvp
->uv_maxblocks
= (int)temp
;
1104 temp
= (double)clp
->cl_blockmin
* ftmp
/
1105 (double)fs
.f_blocks
* 100. + .5;
1107 uvp
->uv_minblocks
= (int)temp
;
1109 temp
= (double)clp
->cl_blocktresh
* ftmp
/
1110 (double)fs
.f_blocks
* 100. + .5;
1112 uvp
->uv_threshblocks
= (int)temp
;
1114 temp
= ((double)clp
->cl_maxinodes
/ fs
.f_files
) * 100. + .5;
1116 uvp
->uv_maxfiles
= (int)temp
;
1118 temp
= ((double)clp
->cl_filemin
/ fs
.f_files
) * 100. + .5;
1120 uvp
->uv_minfiles
= (int)temp
;
1122 temp
= ((double)clp
->cl_filetresh
/ fs
.f_files
) * 100. + .5;
1124 uvp
->uv_threshfiles
= (int)temp
;
1126 ltmp
= ((long long)clp
->cl_maxfiles
* MAXBSIZE
);
1127 uvp
->uv_maxfilesize
= (ltmp
+ (MAXBSIZE
/ 2)) / (1024 * 1024);
1129 xx
= ((double)clp
->cl_blkhiwat
/ clp
->cl_maxblks
) * 100. + .5;
1131 uvp
->uv_hiblocks
= xx
;
1133 xx
= ((double)clp
->cl_blklowat
/ clp
->cl_maxblks
) * 100. + .5;
1135 uvp
->uv_lowblocks
= xx
;
1137 xx
= ((double)clp
->cl_filehiwat
/ clp
->cl_maxinodes
) * 100. + .5;
1139 uvp
->uv_hifiles
= xx
;
1141 xx
= ((double)clp
->cl_filelowat
/ clp
->cl_maxinodes
) * 100. + .5;
1143 uvp
->uv_lowfiles
= xx
;
1145 /* return success */
1150 * cachefs_file_to_dir
1152 * takes in a path, and returns the parent directory of that path.
1154 * it's the caller's responsibility to free the pointer returned by
1159 cachefs_file_to_dir(const char *path
)
1170 if ((cp
= strrchr(rc
, '/')) == NULL
) {
1173 * if no slashes at all, return "." (current directory).
1179 } else if (cp
== rc
) {
1182 * else, if the last '/' is the first character, chop
1183 * off from there (i.e. return "/").
1191 * else, we have a path like /foo/bar or foo/bar.
1192 * chop off from the last '/'.
1203 * cachefs_clean_flag_test
1206 * Tests whether or not the clean flag on the file system
1209 * cachedirp name of the the file system cache directory
1211 * Returns 1 if the cache was shut down cleanly, 0 if not.
1213 * precond(cachedirp)
1217 cachefs_clean_flag_test(const char *cachedirp
)
1221 char buf
[MAXPATHLEN
];
1223 struct cache_usage cu
;
1225 /* construct the path name of the resource file */
1226 namep
= RESOURCE_NAME
;
1227 xx
= strlen(cachedirp
) + strlen(namep
) + 3;
1228 if (xx
>= MAXPATHLEN
) {
1229 pr_err(gettext("Path name too long %s/%s"),
1233 snprintf(buf
, sizeof (buf
), "%s/%s", cachedirp
, namep
);
1235 /* open the file; it will be <2GB */
1236 fd
= open(buf
, O_RDONLY
);
1238 pr_err(gettext("Cannot open %s: %s"), buf
, strerror(errno
));
1242 /* read the cache_usage structure */
1243 xx
= read(fd
, &cu
, sizeof (cu
));
1244 if (xx
!= sizeof (cu
)) {
1245 pr_err(gettext("Error reading %s: %d %s"), buf
,
1246 xx
, strerror(errno
));
1252 /* return state of the cache */
1253 return ((cu
.cu_flags
& CUSAGE_ACTIVE
) == 0);
1259 struct utmpx id
, *putmp
;
1261 id
.ut_type
= BOOT_TIME
;
1263 if ((putmp
= getutxid(&id
)) != NULL
)
1264 return ((time32_t
)putmp
->ut_tv
.tv_sec
);