17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5fc1c62b8Sfrankho * Common Development and Distribution License (the "License"). 6fc1c62b8Sfrankho * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * Miscellaneous support subroutines for High Sierra filesystem 237c478bd9Sstevel@tonic-gate * 24d10b6702Sfrankho * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 25fc1c62b8Sfrankho * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/param.h> 327c478bd9Sstevel@tonic-gate #include <sys/time.h> 337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 347c478bd9Sstevel@tonic-gate #include <sys/systm.h> 357c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 367c478bd9Sstevel@tonic-gate #include <sys/buf.h> 377c478bd9Sstevel@tonic-gate #include <sys/conf.h> 387c478bd9Sstevel@tonic-gate #include <sys/user.h> 397c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 407c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 417c478bd9Sstevel@tonic-gate #include <sys/proc.h> 427c478bd9Sstevel@tonic-gate #include <sys/debug.h> 437c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 447c478bd9Sstevel@tonic-gate #include <sys/uio.h> 457c478bd9Sstevel@tonic-gate #include <vm/hat.h> 467c478bd9Sstevel@tonic-gate #include <vm/as.h> 477c478bd9Sstevel@tonic-gate #include <vm/seg.h> 487c478bd9Sstevel@tonic-gate #include <vm/page.h> 497c478bd9Sstevel@tonic-gate #include <vm/pvn.h> 507c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 517c478bd9Sstevel@tonic-gate #include <sys/swap.h> 527c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_spec.h> 557c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_node.h> 567c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_impl.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #define THE_EPOCH 1970 597c478bd9Sstevel@tonic-gate #define END_OF_TIME 2099 6084b82766Smg147109 extern int hsfs_lostpage; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #ifdef __STDC__ 637c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime(int year, int mon, int day, int gmtoff); 647c478bd9Sstevel@tonic-gate #else 657c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime(); 667c478bd9Sstevel@tonic-gate #endif 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Table used in logging non-fatal errors which should be recorded 707c478bd9Sstevel@tonic-gate * once per mount. Indexed by HSFS_ERR values (defined in hsfs_node.h). 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate struct hsfs_error { 737c478bd9Sstevel@tonic-gate char *hdr_text; /* msg prefix: general error type */ 747c478bd9Sstevel@tonic-gate /* must contain %s for mnt pt */ 757c478bd9Sstevel@tonic-gate char *err_text; /* specific error message */ 767c478bd9Sstevel@tonic-gate uchar_t multiple; /* > 1 such error per fs possible? */ 777c478bd9Sstevel@tonic-gate uchar_t n_printf_args; /* if err_text printf-like, # addtl args */ 787c478bd9Sstevel@tonic-gate } hsfs_error[] = { 797c478bd9Sstevel@tonic-gate /* HSFS_ERR_TRAILING_JUNK */ 80fc1c62b8Sfrankho "hsfs: Warning: the file system mounted on %s " 817c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 827c478bd9Sstevel@tonic-gate "trailing blanks or null characters in file or directory name.\n", 837c478bd9Sstevel@tonic-gate 1, 0, 847c478bd9Sstevel@tonic-gate /* HSFS_ERR_LOWER_CASE_NM */ 85fc1c62b8Sfrankho "hsfs: Warning: the file system mounted on %s " 867c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 877c478bd9Sstevel@tonic-gate "lower case characters in file or directory name.\n", 887c478bd9Sstevel@tonic-gate 1, 0, 897c478bd9Sstevel@tonic-gate /* HSFS_ERR_BAD_ROOT_DIR */ 90fc1c62b8Sfrankho "hsfs: Warning: the file system mounted on %s " 917c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 927c478bd9Sstevel@tonic-gate "invalid root directory.\n", 937c478bd9Sstevel@tonic-gate 0, 0, 947c478bd9Sstevel@tonic-gate /* HSFS_ERR_UNSUP_TYPE */ 95fc1c62b8Sfrankho "hsfs: Warning: the file system mounted on %s " 967c478bd9Sstevel@tonic-gate "contains a file or directory with an unsupported type:", 977c478bd9Sstevel@tonic-gate " 0x%x.\n", 987c478bd9Sstevel@tonic-gate 1, 1, 997c478bd9Sstevel@tonic-gate /* HSFS_ERR_BAD_FILE_LEN */ 100fc1c62b8Sfrankho "hsfs: Warning: file system mounted on %s " 1017c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 102fc1c62b8Sfrankho "file name length greater than max allowed\n", 103fc1c62b8Sfrankho 1, 0, 104fc1c62b8Sfrankho /* HSFS_ERR_BAD_JOLIET_FILE_LEN */ 105fc1c62b8Sfrankho "hsfs: Warning: file system mounted on %s " 106fc1c62b8Sfrankho "does not conform to the Joliet specification:", 107fc1c62b8Sfrankho "file name length greater than max allowed\n", 108fc1c62b8Sfrankho 1, 0, 109fc1c62b8Sfrankho /* HSFS_ERR_TRUNC_JOLIET_FILE_LEN */ 110fc1c62b8Sfrankho "hsfs: Warning: file system mounted on %s " 111fc1c62b8Sfrankho "does not conform to the Joliet specification:", 112fc1c62b8Sfrankho "file name length greater than MAXNAMELEN (truncated)\n", 113fc1c62b8Sfrankho 1, 0, 114fc1c62b8Sfrankho /* HSFS_ERR_BAD_DIR_ENTRY */ 115fc1c62b8Sfrankho "hsfs: Warning: file system mounted on %s " 116fc1c62b8Sfrankho "has inconsistent data:", 117fc1c62b8Sfrankho "invalid directory or file name length (ignored)\n", 1187c478bd9Sstevel@tonic-gate 1, 0, 119d10b6702Sfrankho /* HSFS_ERR_NEG_SUA_LEN */ 120d10b6702Sfrankho "hsfs: Warning: file system mounted on %s " 121d10b6702Sfrankho "has inconsistent Rock Ridge data:", 122d10b6702Sfrankho "negative SUA len\n", 123d10b6702Sfrankho 1, 0, 124d10b6702Sfrankho /* HSFS_ERR_BAD_SUA_LEN */ 125d10b6702Sfrankho "hsfs: Warning: file system mounted on %s " 126d10b6702Sfrankho "has inconsistent Rock Ridge data:", 127d10b6702Sfrankho "SUA len too big\n", 128d10b6702Sfrankho 1, 0, 1297c478bd9Sstevel@tonic-gate }; 1307c478bd9Sstevel@tonic-gate 13184b82766Smg147109 /* 13284b82766Smg147109 * Local datatype for defining tables of (Offset, Name) pairs for 13384b82766Smg147109 * kstats. 13484b82766Smg147109 */ 13584b82766Smg147109 typedef struct { 13684b82766Smg147109 offset_t index; 13784b82766Smg147109 char *name; 13884b82766Smg147109 } hsfs_ksindex_t; 1397c478bd9Sstevel@tonic-gate 14084b82766Smg147109 static const hsfs_ksindex_t hsfs_kstats[] = { 14184b82766Smg147109 { 0, "mountpoint" }, 14284b82766Smg147109 { 1, "pages_lost" }, 14384b82766Smg147109 { 2, "physical_read_pages" }, 14484b82766Smg147109 { 3, "cache_read_pages" }, 14584b82766Smg147109 { 4, "readahead_pages" }, 14684b82766Smg147109 { 5, "coalesced_pages" }, 14784b82766Smg147109 { 6, "total_pages_requested" }, 14884b82766Smg147109 {-1, NULL } 14984b82766Smg147109 }; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * hs_parse_dirdate 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * Parse the short 'directory-format' date into a Unix timeval. 1557c478bd9Sstevel@tonic-gate * This is the date format used in Directory Entries. 1567c478bd9Sstevel@tonic-gate * 1577c478bd9Sstevel@tonic-gate * If the date is not representable, make something up. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate void 1607c478bd9Sstevel@tonic-gate hs_parse_dirdate(dp, tvp) 1617c478bd9Sstevel@tonic-gate uchar_t *dp; 1627c478bd9Sstevel@tonic-gate struct timeval *tvp; 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate int year, month, day, hour, minute, sec, gmtoff; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate year = HDE_DATE_YEAR(dp); 1677c478bd9Sstevel@tonic-gate month = HDE_DATE_MONTH(dp); 1687c478bd9Sstevel@tonic-gate day = HDE_DATE_DAY(dp); 1697c478bd9Sstevel@tonic-gate hour = HDE_DATE_HOUR(dp); 1707c478bd9Sstevel@tonic-gate minute = HDE_DATE_MIN(dp); 1717c478bd9Sstevel@tonic-gate sec = HDE_DATE_SEC(dp); 1727c478bd9Sstevel@tonic-gate gmtoff = HDE_DATE_GMTOFF(dp); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate tvp->tv_usec = 0; 1757c478bd9Sstevel@tonic-gate if (year < THE_EPOCH) { 1767c478bd9Sstevel@tonic-gate tvp->tv_sec = 0; 1777c478bd9Sstevel@tonic-gate } else { 1787c478bd9Sstevel@tonic-gate tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff); 1797c478bd9Sstevel@tonic-gate if (tvp->tv_sec != -1) { 1807c478bd9Sstevel@tonic-gate tvp->tv_sec += ((hour * 60) + minute) * 60 + sec; 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate return; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * hs_parse_longdate 1907c478bd9Sstevel@tonic-gate * 1917c478bd9Sstevel@tonic-gate * Parse the long 'user-oriented' date into a Unix timeval. 1927c478bd9Sstevel@tonic-gate * This is the date format used in the Volume Descriptor. 1937c478bd9Sstevel@tonic-gate * 1947c478bd9Sstevel@tonic-gate * If the date is not representable, make something up. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate void 1977c478bd9Sstevel@tonic-gate hs_parse_longdate(dp, tvp) 1987c478bd9Sstevel@tonic-gate uchar_t *dp; 1997c478bd9Sstevel@tonic-gate struct timeval *tvp; 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate int year, month, day, hour, minute, sec, gmtoff; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate year = HSV_DATE_YEAR(dp); 2047c478bd9Sstevel@tonic-gate month = HSV_DATE_MONTH(dp); 2057c478bd9Sstevel@tonic-gate day = HSV_DATE_DAY(dp); 2067c478bd9Sstevel@tonic-gate hour = HSV_DATE_HOUR(dp); 2077c478bd9Sstevel@tonic-gate minute = HSV_DATE_MIN(dp); 2087c478bd9Sstevel@tonic-gate sec = HSV_DATE_SEC(dp); 2097c478bd9Sstevel@tonic-gate gmtoff = HSV_DATE_GMTOFF(dp); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate tvp->tv_usec = 0; 2127c478bd9Sstevel@tonic-gate if (year < THE_EPOCH) { 2137c478bd9Sstevel@tonic-gate tvp->tv_sec = 0; 2147c478bd9Sstevel@tonic-gate } else { 2157c478bd9Sstevel@tonic-gate tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff); 2167c478bd9Sstevel@tonic-gate if (tvp->tv_sec != -1) { 2177c478bd9Sstevel@tonic-gate tvp->tv_sec += ((hour * 60) + minute) * 60 + sec; 2187c478bd9Sstevel@tonic-gate tvp->tv_usec = HSV_DATE_HSEC(dp) * 10000; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* cumulative number of seconds per month, non-leap and leap-year versions */ 2257c478bd9Sstevel@tonic-gate static time_t cum_sec[] = { 2267c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280, 2277c478bd9Sstevel@tonic-gate 0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500 2287c478bd9Sstevel@tonic-gate }; 2297c478bd9Sstevel@tonic-gate static time_t cum_sec_leap[] = { 2307c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400, 2317c478bd9Sstevel@tonic-gate 0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680 2327c478bd9Sstevel@tonic-gate }; 2337c478bd9Sstevel@tonic-gate #define SEC_PER_DAY 0x15180 2347c478bd9Sstevel@tonic-gate #define SEC_PER_YEAR 0x1e13380 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * hs_date_to_gmtime 2387c478bd9Sstevel@tonic-gate * 2397c478bd9Sstevel@tonic-gate * Convert year(1970-2099)/month(1-12)/day(1-31) to seconds-since-1970/1/1. 2407c478bd9Sstevel@tonic-gate * 2417c478bd9Sstevel@tonic-gate * Returns -1 if the date is out of range. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate static time_t 2447c478bd9Sstevel@tonic-gate hs_date_to_gmtime(year, mon, day, gmtoff) 2457c478bd9Sstevel@tonic-gate int year; 2467c478bd9Sstevel@tonic-gate int mon; 2477c478bd9Sstevel@tonic-gate int day; 2487c478bd9Sstevel@tonic-gate int gmtoff; 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate time_t sum; 2517c478bd9Sstevel@tonic-gate time_t *cp; 2527c478bd9Sstevel@tonic-gate int y; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if ((year < THE_EPOCH) || (year > END_OF_TIME) || 2557c478bd9Sstevel@tonic-gate (mon < 1) || (mon > 12) || 2567c478bd9Sstevel@tonic-gate (day < 1) || (day > 31)) 2577c478bd9Sstevel@tonic-gate return (-1); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Figure seconds until this year and correct for leap years. 2617c478bd9Sstevel@tonic-gate * Note: 2000 is a leap year but not 2100. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate y = year - THE_EPOCH; 2647c478bd9Sstevel@tonic-gate sum = y * SEC_PER_YEAR; 2657c478bd9Sstevel@tonic-gate sum += ((y + 1) / 4) * SEC_PER_DAY; 2667c478bd9Sstevel@tonic-gate /* 2677c478bd9Sstevel@tonic-gate * Point to the correct table for this year and 2687c478bd9Sstevel@tonic-gate * add in seconds until this month. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate cp = ((y + 2) % 4) ? cum_sec : cum_sec_leap; 2717c478bd9Sstevel@tonic-gate sum += cp[mon - 1]; 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * Add in seconds until 0:00 of this day. 2747c478bd9Sstevel@tonic-gate * (days-per-month validation is not done here) 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate sum += (day - 1) * SEC_PER_DAY; 2777c478bd9Sstevel@tonic-gate sum -= (gmtoff * 15 * 60); 2787c478bd9Sstevel@tonic-gate return (sum); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Indicate whether the directory is valid. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate int 2867c478bd9Sstevel@tonic-gate hsfs_valid_dir(hd) 2877c478bd9Sstevel@tonic-gate struct hs_direntry *hd; 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * check to see if this directory is not marked as a directory. 2917c478bd9Sstevel@tonic-gate * check to see if data length is zero. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (hd->ext_size == 0) 2957c478bd9Sstevel@tonic-gate return (0); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (hd->type != VDIR) 2987c478bd9Sstevel@tonic-gate return (0); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate return (1); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * If we haven't complained about this error type yet, do. 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate void 3097c478bd9Sstevel@tonic-gate hs_log_bogus_disk_warning(fsp, errtype, data) 3107c478bd9Sstevel@tonic-gate struct hsfs *fsp; 3117c478bd9Sstevel@tonic-gate int errtype; 3127c478bd9Sstevel@tonic-gate uint_t data; 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (fsp->hsfs_err_flags & (1 << errtype)) 3167c478bd9Sstevel@tonic-gate return; /* already complained */ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, hsfs_error[errtype].hdr_text, 3197c478bd9Sstevel@tonic-gate fsp->hsfs_fsmnt); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate switch (hsfs_error[errtype].n_printf_args) { 3227c478bd9Sstevel@tonic-gate case 0: 3237c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, hsfs_error[errtype].err_text); 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate case 1: 3267c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, hsfs_error[errtype].err_text, data); 3277c478bd9Sstevel@tonic-gate break; 3287c478bd9Sstevel@tonic-gate default: 3297c478bd9Sstevel@tonic-gate /* don't currently handle more than 1 arg */ 3307c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "unknown problem; internal error.\n"); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 3337c478bd9Sstevel@tonic-gate "Due to this error, the file system may not be correctly interpreted.\n"); 3347c478bd9Sstevel@tonic-gate if (hsfs_error[errtype].multiple) 3357c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 3367c478bd9Sstevel@tonic-gate "Other such errors in this file system will be silently ignored.\n\n"); 3377c478bd9Sstevel@tonic-gate else 3387c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate fsp->hsfs_err_flags |= (1 << errtype); 3417c478bd9Sstevel@tonic-gate } 34284b82766Smg147109 34384b82766Smg147109 /* 34484b82766Smg147109 * Callback from kstat framework. Grab a snapshot of the current hsfs 34584b82766Smg147109 * counters and populate the kstats. 34684b82766Smg147109 */ 34784b82766Smg147109 static int 34884b82766Smg147109 hsfs_kstats_update(kstat_t *ksp, int flag) 34984b82766Smg147109 { 35084b82766Smg147109 struct hsfs *fsp; 35184b82766Smg147109 kstat_named_t *knp; 35284b82766Smg147109 uint64_t pages_lost; 35384b82766Smg147109 uint64_t physical_read_bytes; 35484b82766Smg147109 uint64_t cache_read_pages; 35584b82766Smg147109 uint64_t readahead_bytes; 35684b82766Smg147109 uint64_t coalesced_bytes; 35784b82766Smg147109 uint64_t total_pages_requested; 35884b82766Smg147109 35984b82766Smg147109 if (flag != KSTAT_READ) 36084b82766Smg147109 return (EACCES); 36184b82766Smg147109 36284b82766Smg147109 fsp = ksp->ks_private; 36384b82766Smg147109 knp = ksp->ks_data; 36484b82766Smg147109 36584b82766Smg147109 mutex_enter(&(fsp->hqueue->strategy_lock)); 36684b82766Smg147109 mutex_enter(&(fsp->hqueue->hsfs_queue_lock)); 36784b82766Smg147109 36884b82766Smg147109 cache_read_pages = fsp->cache_read_pages; 36984b82766Smg147109 pages_lost = hsfs_lostpage; 37084b82766Smg147109 physical_read_bytes = fsp->physical_read_bytes; 37184b82766Smg147109 readahead_bytes = fsp->readahead_bytes; 37284b82766Smg147109 coalesced_bytes = fsp->coalesced_bytes; 37384b82766Smg147109 total_pages_requested = fsp->total_pages_requested; 37484b82766Smg147109 37584b82766Smg147109 mutex_exit(&(fsp->hqueue->strategy_lock)); 37684b82766Smg147109 mutex_exit(&(fsp->hqueue->hsfs_queue_lock)); 37784b82766Smg147109 37884b82766Smg147109 knp++; 37984b82766Smg147109 (knp++)->value.ui64 = pages_lost; 38084b82766Smg147109 (knp++)->value.ui64 = howmany(physical_read_bytes, PAGESIZE); 38184b82766Smg147109 (knp++)->value.ui64 = cache_read_pages; 38284b82766Smg147109 (knp++)->value.ui64 = howmany(readahead_bytes, PAGESIZE); 38384b82766Smg147109 (knp++)->value.ui64 = howmany(coalesced_bytes, PAGESIZE); 38484b82766Smg147109 (knp++)->value.ui64 = total_pages_requested; 38584b82766Smg147109 38684b82766Smg147109 return (0); 38784b82766Smg147109 } 38884b82766Smg147109 38984b82766Smg147109 /* 39084b82766Smg147109 * Initialize hsfs kstats, which are all name value pairs with 39184b82766Smg147109 * values being various counters. 39284b82766Smg147109 */ 39384b82766Smg147109 static kstat_t * 39484b82766Smg147109 hsfs_setup_named_kstats(struct hsfs *fsp, int fsid, char *name, 395*f9ec9c5aSmg147109 const hsfs_ksindex_t *ksip, int (*update)(kstat_t *, int)) 39684b82766Smg147109 { 39784b82766Smg147109 kstat_t *ksp; 39884b82766Smg147109 kstat_named_t *knp; 39984b82766Smg147109 char *np; 40084b82766Smg147109 char *mntpt = fsp->hsfs_fsmnt; 401*f9ec9c5aSmg147109 size_t size; 40284b82766Smg147109 403*f9ec9c5aSmg147109 size = (sizeof (hsfs_kstats)) / (sizeof (hsfs_ksindex_t)); 40484b82766Smg147109 ksp = kstat_create("hsfs_fs", fsid, name, "hsfs", 40584b82766Smg147109 KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_VIRTUAL); 40684b82766Smg147109 if (ksp == NULL) 40784b82766Smg147109 return (NULL); 40884b82766Smg147109 40984b82766Smg147109 ksp->ks_data = kmem_alloc(sizeof (kstat_named_t) * size, KM_SLEEP); 41084b82766Smg147109 ksp->ks_private = fsp; 41184b82766Smg147109 ksp->ks_update = update; 41284b82766Smg147109 ksp->ks_data_size += strlen(mntpt) + 1; 41384b82766Smg147109 knp = ksp->ks_data; 41484b82766Smg147109 kstat_named_init(knp, ksip->name, KSTAT_DATA_STRING); 41584b82766Smg147109 kstat_named_setstr(knp, mntpt); 41684b82766Smg147109 knp++; 41784b82766Smg147109 ksip++; 41884b82766Smg147109 41984b82766Smg147109 for (; (np = ksip->name) != NULL; ++knp, ++ksip) { 42084b82766Smg147109 kstat_named_init(knp, np, KSTAT_DATA_UINT64); 42184b82766Smg147109 } 42284b82766Smg147109 kstat_install(ksp); 42384b82766Smg147109 42484b82766Smg147109 return (ksp); 42584b82766Smg147109 } 42684b82766Smg147109 42784b82766Smg147109 void 42884b82766Smg147109 hsfs_init_kstats(struct hsfs *fsp, int fsid) 42984b82766Smg147109 { 43084b82766Smg147109 fsp->hsfs_kstats = hsfs_setup_named_kstats(fsp, fsid, "hsfs_read_stats", 431*f9ec9c5aSmg147109 hsfs_kstats, hsfs_kstats_update); 43284b82766Smg147109 } 43384b82766Smg147109 43484b82766Smg147109 void 43584b82766Smg147109 hsfs_fini_kstats(struct hsfs *fsp) 43684b82766Smg147109 { 43784b82766Smg147109 void *data; 43884b82766Smg147109 43984b82766Smg147109 if (fsp->hsfs_kstats != NULL) { 44084b82766Smg147109 data = fsp->hsfs_kstats->ks_data; 44184b82766Smg147109 kstat_delete(fsp->hsfs_kstats); 442*f9ec9c5aSmg147109 kmem_free(data, sizeof (kstat_named_t) * 443*f9ec9c5aSmg147109 (sizeof (hsfs_kstats)) / (sizeof (hsfs_ksindex_t))); 44484b82766Smg147109 } 44584b82766Smg147109 fsp->hsfs_kstats = NULL; 44684b82766Smg147109 } 447