1*1e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 2*1e9ea7e0SNamjae Jeon /* 3*1e9ea7e0SNamjae Jeon * logfile.c - NTFS kernel journal handling. Part of the Linux-NTFS project. 4*1e9ea7e0SNamjae Jeon * 5*1e9ea7e0SNamjae Jeon * Copyright (c) 2002-2007 Anton Altaparmakov 6*1e9ea7e0SNamjae Jeon */ 7*1e9ea7e0SNamjae Jeon 8*1e9ea7e0SNamjae Jeon #ifdef NTFS_RW 9*1e9ea7e0SNamjae Jeon 10*1e9ea7e0SNamjae Jeon #include <linux/types.h> 11*1e9ea7e0SNamjae Jeon #include <linux/fs.h> 12*1e9ea7e0SNamjae Jeon #include <linux/highmem.h> 13*1e9ea7e0SNamjae Jeon #include <linux/buffer_head.h> 14*1e9ea7e0SNamjae Jeon #include <linux/bitops.h> 15*1e9ea7e0SNamjae Jeon #include <linux/log2.h> 16*1e9ea7e0SNamjae Jeon #include <linux/bio.h> 17*1e9ea7e0SNamjae Jeon 18*1e9ea7e0SNamjae Jeon #include "attrib.h" 19*1e9ea7e0SNamjae Jeon #include "aops.h" 20*1e9ea7e0SNamjae Jeon #include "debug.h" 21*1e9ea7e0SNamjae Jeon #include "logfile.h" 22*1e9ea7e0SNamjae Jeon #include "malloc.h" 23*1e9ea7e0SNamjae Jeon #include "volume.h" 24*1e9ea7e0SNamjae Jeon #include "ntfs.h" 25*1e9ea7e0SNamjae Jeon 26*1e9ea7e0SNamjae Jeon /** 27*1e9ea7e0SNamjae Jeon * ntfs_check_restart_page_header - check the page header for consistency 28*1e9ea7e0SNamjae Jeon * @vi: $LogFile inode to which the restart page header belongs 29*1e9ea7e0SNamjae Jeon * @rp: restart page header to check 30*1e9ea7e0SNamjae Jeon * @pos: position in @vi at which the restart page header resides 31*1e9ea7e0SNamjae Jeon * 32*1e9ea7e0SNamjae Jeon * Check the restart page header @rp for consistency and return 'true' if it is 33*1e9ea7e0SNamjae Jeon * consistent and 'false' otherwise. 34*1e9ea7e0SNamjae Jeon * 35*1e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 36*1e9ea7e0SNamjae Jeon * require the full restart page. 37*1e9ea7e0SNamjae Jeon */ 38*1e9ea7e0SNamjae Jeon static bool ntfs_check_restart_page_header(struct inode *vi, 39*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *rp, s64 pos) 40*1e9ea7e0SNamjae Jeon { 41*1e9ea7e0SNamjae Jeon u32 logfile_system_page_size, logfile_log_page_size; 42*1e9ea7e0SNamjae Jeon u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; 43*1e9ea7e0SNamjae Jeon bool have_usa = true; 44*1e9ea7e0SNamjae Jeon 45*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 46*1e9ea7e0SNamjae Jeon /* 47*1e9ea7e0SNamjae Jeon * If the system or log page sizes are smaller than the ntfs block size 48*1e9ea7e0SNamjae Jeon * or either is not a power of 2 we cannot handle this log file. 49*1e9ea7e0SNamjae Jeon */ 50*1e9ea7e0SNamjae Jeon logfile_system_page_size = le32_to_cpu(rp->system_page_size); 51*1e9ea7e0SNamjae Jeon logfile_log_page_size = le32_to_cpu(rp->log_page_size); 52*1e9ea7e0SNamjae Jeon if (logfile_system_page_size < NTFS_BLOCK_SIZE || 53*1e9ea7e0SNamjae Jeon logfile_log_page_size < NTFS_BLOCK_SIZE || 54*1e9ea7e0SNamjae Jeon logfile_system_page_size & 55*1e9ea7e0SNamjae Jeon (logfile_system_page_size - 1) || 56*1e9ea7e0SNamjae Jeon !is_power_of_2(logfile_log_page_size)) { 57*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile uses unsupported page size."); 58*1e9ea7e0SNamjae Jeon return false; 59*1e9ea7e0SNamjae Jeon } 60*1e9ea7e0SNamjae Jeon /* 61*1e9ea7e0SNamjae Jeon * We must be either at !pos (1st restart page) or at pos = system page 62*1e9ea7e0SNamjae Jeon * size (2nd restart page). 63*1e9ea7e0SNamjae Jeon */ 64*1e9ea7e0SNamjae Jeon if (pos && pos != logfile_system_page_size) { 65*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Found restart area in incorrect " 66*1e9ea7e0SNamjae Jeon "position in $LogFile."); 67*1e9ea7e0SNamjae Jeon return false; 68*1e9ea7e0SNamjae Jeon } 69*1e9ea7e0SNamjae Jeon /* We only know how to handle version 1.1. */ 70*1e9ea7e0SNamjae Jeon if (sle16_to_cpu(rp->major_ver) != 1 || 71*1e9ea7e0SNamjae Jeon sle16_to_cpu(rp->minor_ver) != 1) { 72*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile version %i.%i is not " 73*1e9ea7e0SNamjae Jeon "supported. (This driver supports version " 74*1e9ea7e0SNamjae Jeon "1.1 only.)", (int)sle16_to_cpu(rp->major_ver), 75*1e9ea7e0SNamjae Jeon (int)sle16_to_cpu(rp->minor_ver)); 76*1e9ea7e0SNamjae Jeon return false; 77*1e9ea7e0SNamjae Jeon } 78*1e9ea7e0SNamjae Jeon /* 79*1e9ea7e0SNamjae Jeon * If chkdsk has been run the restart page may not be protected by an 80*1e9ea7e0SNamjae Jeon * update sequence array. 81*1e9ea7e0SNamjae Jeon */ 82*1e9ea7e0SNamjae Jeon if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { 83*1e9ea7e0SNamjae Jeon have_usa = false; 84*1e9ea7e0SNamjae Jeon goto skip_usa_checks; 85*1e9ea7e0SNamjae Jeon } 86*1e9ea7e0SNamjae Jeon /* Verify the size of the update sequence array. */ 87*1e9ea7e0SNamjae Jeon usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); 88*1e9ea7e0SNamjae Jeon if (usa_count != le16_to_cpu(rp->usa_count)) { 89*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart page specifies " 90*1e9ea7e0SNamjae Jeon "inconsistent update sequence array count."); 91*1e9ea7e0SNamjae Jeon return false; 92*1e9ea7e0SNamjae Jeon } 93*1e9ea7e0SNamjae Jeon /* Verify the position of the update sequence array. */ 94*1e9ea7e0SNamjae Jeon usa_ofs = le16_to_cpu(rp->usa_ofs); 95*1e9ea7e0SNamjae Jeon usa_end = usa_ofs + usa_count * sizeof(u16); 96*1e9ea7e0SNamjae Jeon if (usa_ofs < sizeof(RESTART_PAGE_HEADER) || 97*1e9ea7e0SNamjae Jeon usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) { 98*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart page specifies " 99*1e9ea7e0SNamjae Jeon "inconsistent update sequence array offset."); 100*1e9ea7e0SNamjae Jeon return false; 101*1e9ea7e0SNamjae Jeon } 102*1e9ea7e0SNamjae Jeon skip_usa_checks: 103*1e9ea7e0SNamjae Jeon /* 104*1e9ea7e0SNamjae Jeon * Verify the position of the restart area. It must be: 105*1e9ea7e0SNamjae Jeon * - aligned to 8-byte boundary, 106*1e9ea7e0SNamjae Jeon * - after the update sequence array, and 107*1e9ea7e0SNamjae Jeon * - within the system page size. 108*1e9ea7e0SNamjae Jeon */ 109*1e9ea7e0SNamjae Jeon ra_ofs = le16_to_cpu(rp->restart_area_offset); 110*1e9ea7e0SNamjae Jeon if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : 111*1e9ea7e0SNamjae Jeon ra_ofs < sizeof(RESTART_PAGE_HEADER)) || 112*1e9ea7e0SNamjae Jeon ra_ofs > logfile_system_page_size) { 113*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart page specifies " 114*1e9ea7e0SNamjae Jeon "inconsistent restart area offset."); 115*1e9ea7e0SNamjae Jeon return false; 116*1e9ea7e0SNamjae Jeon } 117*1e9ea7e0SNamjae Jeon /* 118*1e9ea7e0SNamjae Jeon * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn 119*1e9ea7e0SNamjae Jeon * set. 120*1e9ea7e0SNamjae Jeon */ 121*1e9ea7e0SNamjae Jeon if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) { 122*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart page is not modified " 123*1e9ea7e0SNamjae Jeon "by chkdsk but a chkdsk LSN is specified."); 124*1e9ea7e0SNamjae Jeon return false; 125*1e9ea7e0SNamjae Jeon } 126*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 127*1e9ea7e0SNamjae Jeon return true; 128*1e9ea7e0SNamjae Jeon } 129*1e9ea7e0SNamjae Jeon 130*1e9ea7e0SNamjae Jeon /** 131*1e9ea7e0SNamjae Jeon * ntfs_check_restart_area - check the restart area for consistency 132*1e9ea7e0SNamjae Jeon * @vi: $LogFile inode to which the restart page belongs 133*1e9ea7e0SNamjae Jeon * @rp: restart page whose restart area to check 134*1e9ea7e0SNamjae Jeon * 135*1e9ea7e0SNamjae Jeon * Check the restart area of the restart page @rp for consistency and return 136*1e9ea7e0SNamjae Jeon * 'true' if it is consistent and 'false' otherwise. 137*1e9ea7e0SNamjae Jeon * 138*1e9ea7e0SNamjae Jeon * This function assumes that the restart page header has already been 139*1e9ea7e0SNamjae Jeon * consistency checked. 140*1e9ea7e0SNamjae Jeon * 141*1e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 142*1e9ea7e0SNamjae Jeon * require the full restart page. 143*1e9ea7e0SNamjae Jeon */ 144*1e9ea7e0SNamjae Jeon static bool ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp) 145*1e9ea7e0SNamjae Jeon { 146*1e9ea7e0SNamjae Jeon u64 file_size; 147*1e9ea7e0SNamjae Jeon RESTART_AREA *ra; 148*1e9ea7e0SNamjae Jeon u16 ra_ofs, ra_len, ca_ofs; 149*1e9ea7e0SNamjae Jeon u8 fs_bits; 150*1e9ea7e0SNamjae Jeon 151*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 152*1e9ea7e0SNamjae Jeon ra_ofs = le16_to_cpu(rp->restart_area_offset); 153*1e9ea7e0SNamjae Jeon ra = (RESTART_AREA*)((u8*)rp + ra_ofs); 154*1e9ea7e0SNamjae Jeon /* 155*1e9ea7e0SNamjae Jeon * Everything before ra->file_size must be before the first word 156*1e9ea7e0SNamjae Jeon * protected by an update sequence number. This ensures that it is 157*1e9ea7e0SNamjae Jeon * safe to access ra->client_array_offset. 158*1e9ea7e0SNamjae Jeon */ 159*1e9ea7e0SNamjae Jeon if (ra_ofs + offsetof(RESTART_AREA, file_size) > 160*1e9ea7e0SNamjae Jeon NTFS_BLOCK_SIZE - sizeof(u16)) { 161*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 162*1e9ea7e0SNamjae Jeon "inconsistent file offset."); 163*1e9ea7e0SNamjae Jeon return false; 164*1e9ea7e0SNamjae Jeon } 165*1e9ea7e0SNamjae Jeon /* 166*1e9ea7e0SNamjae Jeon * Now that we can access ra->client_array_offset, make sure everything 167*1e9ea7e0SNamjae Jeon * up to the log client array is before the first word protected by an 168*1e9ea7e0SNamjae Jeon * update sequence number. This ensures we can access all of the 169*1e9ea7e0SNamjae Jeon * restart area elements safely. Also, the client array offset must be 170*1e9ea7e0SNamjae Jeon * aligned to an 8-byte boundary. 171*1e9ea7e0SNamjae Jeon */ 172*1e9ea7e0SNamjae Jeon ca_ofs = le16_to_cpu(ra->client_array_offset); 173*1e9ea7e0SNamjae Jeon if (((ca_ofs + 7) & ~7) != ca_ofs || 174*1e9ea7e0SNamjae Jeon ra_ofs + ca_ofs > NTFS_BLOCK_SIZE - sizeof(u16)) { 175*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 176*1e9ea7e0SNamjae Jeon "inconsistent client array offset."); 177*1e9ea7e0SNamjae Jeon return false; 178*1e9ea7e0SNamjae Jeon } 179*1e9ea7e0SNamjae Jeon /* 180*1e9ea7e0SNamjae Jeon * The restart area must end within the system page size both when 181*1e9ea7e0SNamjae Jeon * calculated manually and as specified by ra->restart_area_length. 182*1e9ea7e0SNamjae Jeon * Also, the calculated length must not exceed the specified length. 183*1e9ea7e0SNamjae Jeon */ 184*1e9ea7e0SNamjae Jeon ra_len = ca_ofs + le16_to_cpu(ra->log_clients) * 185*1e9ea7e0SNamjae Jeon sizeof(LOG_CLIENT_RECORD); 186*1e9ea7e0SNamjae Jeon if (ra_ofs + ra_len > le32_to_cpu(rp->system_page_size) || 187*1e9ea7e0SNamjae Jeon ra_ofs + le16_to_cpu(ra->restart_area_length) > 188*1e9ea7e0SNamjae Jeon le32_to_cpu(rp->system_page_size) || 189*1e9ea7e0SNamjae Jeon ra_len > le16_to_cpu(ra->restart_area_length)) { 190*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area is out of bounds " 191*1e9ea7e0SNamjae Jeon "of the system page size specified by the " 192*1e9ea7e0SNamjae Jeon "restart page header and/or the specified " 193*1e9ea7e0SNamjae Jeon "restart area length is inconsistent."); 194*1e9ea7e0SNamjae Jeon return false; 195*1e9ea7e0SNamjae Jeon } 196*1e9ea7e0SNamjae Jeon /* 197*1e9ea7e0SNamjae Jeon * The ra->client_free_list and ra->client_in_use_list must be either 198*1e9ea7e0SNamjae Jeon * LOGFILE_NO_CLIENT or less than ra->log_clients or they are 199*1e9ea7e0SNamjae Jeon * overflowing the client array. 200*1e9ea7e0SNamjae Jeon */ 201*1e9ea7e0SNamjae Jeon if ((ra->client_free_list != LOGFILE_NO_CLIENT && 202*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_free_list) >= 203*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_clients)) || 204*1e9ea7e0SNamjae Jeon (ra->client_in_use_list != LOGFILE_NO_CLIENT && 205*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_in_use_list) >= 206*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_clients))) { 207*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 208*1e9ea7e0SNamjae Jeon "overflowing client free and/or in use lists."); 209*1e9ea7e0SNamjae Jeon return false; 210*1e9ea7e0SNamjae Jeon } 211*1e9ea7e0SNamjae Jeon /* 212*1e9ea7e0SNamjae Jeon * Check ra->seq_number_bits against ra->file_size for consistency. 213*1e9ea7e0SNamjae Jeon * We cannot just use ffs() because the file size is not a power of 2. 214*1e9ea7e0SNamjae Jeon */ 215*1e9ea7e0SNamjae Jeon file_size = (u64)sle64_to_cpu(ra->file_size); 216*1e9ea7e0SNamjae Jeon fs_bits = 0; 217*1e9ea7e0SNamjae Jeon while (file_size) { 218*1e9ea7e0SNamjae Jeon file_size >>= 1; 219*1e9ea7e0SNamjae Jeon fs_bits++; 220*1e9ea7e0SNamjae Jeon } 221*1e9ea7e0SNamjae Jeon if (le32_to_cpu(ra->seq_number_bits) != 67 - fs_bits) { 222*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 223*1e9ea7e0SNamjae Jeon "inconsistent sequence number bits."); 224*1e9ea7e0SNamjae Jeon return false; 225*1e9ea7e0SNamjae Jeon } 226*1e9ea7e0SNamjae Jeon /* The log record header length must be a multiple of 8. */ 227*1e9ea7e0SNamjae Jeon if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) != 228*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_record_header_length)) { 229*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 230*1e9ea7e0SNamjae Jeon "inconsistent log record header length."); 231*1e9ea7e0SNamjae Jeon return false; 232*1e9ea7e0SNamjae Jeon } 233*1e9ea7e0SNamjae Jeon /* Dito for the log page data offset. */ 234*1e9ea7e0SNamjae Jeon if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) != 235*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_page_data_offset)) { 236*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile restart area specifies " 237*1e9ea7e0SNamjae Jeon "inconsistent log page data offset."); 238*1e9ea7e0SNamjae Jeon return false; 239*1e9ea7e0SNamjae Jeon } 240*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 241*1e9ea7e0SNamjae Jeon return true; 242*1e9ea7e0SNamjae Jeon } 243*1e9ea7e0SNamjae Jeon 244*1e9ea7e0SNamjae Jeon /** 245*1e9ea7e0SNamjae Jeon * ntfs_check_log_client_array - check the log client array for consistency 246*1e9ea7e0SNamjae Jeon * @vi: $LogFile inode to which the restart page belongs 247*1e9ea7e0SNamjae Jeon * @rp: restart page whose log client array to check 248*1e9ea7e0SNamjae Jeon * 249*1e9ea7e0SNamjae Jeon * Check the log client array of the restart page @rp for consistency and 250*1e9ea7e0SNamjae Jeon * return 'true' if it is consistent and 'false' otherwise. 251*1e9ea7e0SNamjae Jeon * 252*1e9ea7e0SNamjae Jeon * This function assumes that the restart page header and the restart area have 253*1e9ea7e0SNamjae Jeon * already been consistency checked. 254*1e9ea7e0SNamjae Jeon * 255*1e9ea7e0SNamjae Jeon * Unlike ntfs_check_restart_page_header() and ntfs_check_restart_area(), this 256*1e9ea7e0SNamjae Jeon * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full 257*1e9ea7e0SNamjae Jeon * restart page and the page must be multi sector transfer deprotected. 258*1e9ea7e0SNamjae Jeon */ 259*1e9ea7e0SNamjae Jeon static bool ntfs_check_log_client_array(struct inode *vi, 260*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *rp) 261*1e9ea7e0SNamjae Jeon { 262*1e9ea7e0SNamjae Jeon RESTART_AREA *ra; 263*1e9ea7e0SNamjae Jeon LOG_CLIENT_RECORD *ca, *cr; 264*1e9ea7e0SNamjae Jeon u16 nr_clients, idx; 265*1e9ea7e0SNamjae Jeon bool in_free_list, idx_is_first; 266*1e9ea7e0SNamjae Jeon 267*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 268*1e9ea7e0SNamjae Jeon ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); 269*1e9ea7e0SNamjae Jeon ca = (LOG_CLIENT_RECORD*)((u8*)ra + 270*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_array_offset)); 271*1e9ea7e0SNamjae Jeon /* 272*1e9ea7e0SNamjae Jeon * Check the ra->client_free_list first and then check the 273*1e9ea7e0SNamjae Jeon * ra->client_in_use_list. Check each of the log client records in 274*1e9ea7e0SNamjae Jeon * each of the lists and check that the array does not overflow the 275*1e9ea7e0SNamjae Jeon * ra->log_clients value. Also keep track of the number of records 276*1e9ea7e0SNamjae Jeon * visited as there cannot be more than ra->log_clients records and 277*1e9ea7e0SNamjae Jeon * that way we detect eventual loops in within a list. 278*1e9ea7e0SNamjae Jeon */ 279*1e9ea7e0SNamjae Jeon nr_clients = le16_to_cpu(ra->log_clients); 280*1e9ea7e0SNamjae Jeon idx = le16_to_cpu(ra->client_free_list); 281*1e9ea7e0SNamjae Jeon in_free_list = true; 282*1e9ea7e0SNamjae Jeon check_list: 283*1e9ea7e0SNamjae Jeon for (idx_is_first = true; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--, 284*1e9ea7e0SNamjae Jeon idx = le16_to_cpu(cr->next_client)) { 285*1e9ea7e0SNamjae Jeon if (!nr_clients || idx >= le16_to_cpu(ra->log_clients)) 286*1e9ea7e0SNamjae Jeon goto err_out; 287*1e9ea7e0SNamjae Jeon /* Set @cr to the current log client record. */ 288*1e9ea7e0SNamjae Jeon cr = ca + idx; 289*1e9ea7e0SNamjae Jeon /* The first log client record must not have a prev_client. */ 290*1e9ea7e0SNamjae Jeon if (idx_is_first) { 291*1e9ea7e0SNamjae Jeon if (cr->prev_client != LOGFILE_NO_CLIENT) 292*1e9ea7e0SNamjae Jeon goto err_out; 293*1e9ea7e0SNamjae Jeon idx_is_first = false; 294*1e9ea7e0SNamjae Jeon } 295*1e9ea7e0SNamjae Jeon } 296*1e9ea7e0SNamjae Jeon /* Switch to and check the in use list if we just did the free list. */ 297*1e9ea7e0SNamjae Jeon if (in_free_list) { 298*1e9ea7e0SNamjae Jeon in_free_list = false; 299*1e9ea7e0SNamjae Jeon idx = le16_to_cpu(ra->client_in_use_list); 300*1e9ea7e0SNamjae Jeon goto check_list; 301*1e9ea7e0SNamjae Jeon } 302*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 303*1e9ea7e0SNamjae Jeon return true; 304*1e9ea7e0SNamjae Jeon err_out: 305*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$LogFile log client array is corrupt."); 306*1e9ea7e0SNamjae Jeon return false; 307*1e9ea7e0SNamjae Jeon } 308*1e9ea7e0SNamjae Jeon 309*1e9ea7e0SNamjae Jeon /** 310*1e9ea7e0SNamjae Jeon * ntfs_check_and_load_restart_page - check the restart page for consistency 311*1e9ea7e0SNamjae Jeon * @vi: $LogFile inode to which the restart page belongs 312*1e9ea7e0SNamjae Jeon * @rp: restart page to check 313*1e9ea7e0SNamjae Jeon * @pos: position in @vi at which the restart page resides 314*1e9ea7e0SNamjae Jeon * @wrp: [OUT] copy of the multi sector transfer deprotected restart page 315*1e9ea7e0SNamjae Jeon * @lsn: [OUT] set to the current logfile lsn on success 316*1e9ea7e0SNamjae Jeon * 317*1e9ea7e0SNamjae Jeon * Check the restart page @rp for consistency and return 0 if it is consistent 318*1e9ea7e0SNamjae Jeon * and -errno otherwise. The restart page may have been modified by chkdsk in 319*1e9ea7e0SNamjae Jeon * which case its magic is CHKD instead of RSTR. 320*1e9ea7e0SNamjae Jeon * 321*1e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 322*1e9ea7e0SNamjae Jeon * require the full restart page. 323*1e9ea7e0SNamjae Jeon * 324*1e9ea7e0SNamjae Jeon * If @wrp is not NULL, on success, *@wrp will point to a buffer containing a 325*1e9ea7e0SNamjae Jeon * copy of the complete multi sector transfer deprotected page. On failure, 326*1e9ea7e0SNamjae Jeon * *@wrp is undefined. 327*1e9ea7e0SNamjae Jeon * 328*1e9ea7e0SNamjae Jeon * Simillarly, if @lsn is not NULL, on success *@lsn will be set to the current 329*1e9ea7e0SNamjae Jeon * logfile lsn according to this restart page. On failure, *@lsn is undefined. 330*1e9ea7e0SNamjae Jeon * 331*1e9ea7e0SNamjae Jeon * The following error codes are defined: 332*1e9ea7e0SNamjae Jeon * -EINVAL - The restart page is inconsistent. 333*1e9ea7e0SNamjae Jeon * -ENOMEM - Not enough memory to load the restart page. 334*1e9ea7e0SNamjae Jeon * -EIO - Failed to reading from $LogFile. 335*1e9ea7e0SNamjae Jeon */ 336*1e9ea7e0SNamjae Jeon static int ntfs_check_and_load_restart_page(struct inode *vi, 337*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp, 338*1e9ea7e0SNamjae Jeon LSN *lsn) 339*1e9ea7e0SNamjae Jeon { 340*1e9ea7e0SNamjae Jeon RESTART_AREA *ra; 341*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *trp; 342*1e9ea7e0SNamjae Jeon int size, err; 343*1e9ea7e0SNamjae Jeon 344*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 345*1e9ea7e0SNamjae Jeon /* Check the restart page header for consistency. */ 346*1e9ea7e0SNamjae Jeon if (!ntfs_check_restart_page_header(vi, rp, pos)) { 347*1e9ea7e0SNamjae Jeon /* Error output already done inside the function. */ 348*1e9ea7e0SNamjae Jeon return -EINVAL; 349*1e9ea7e0SNamjae Jeon } 350*1e9ea7e0SNamjae Jeon /* Check the restart area for consistency. */ 351*1e9ea7e0SNamjae Jeon if (!ntfs_check_restart_area(vi, rp)) { 352*1e9ea7e0SNamjae Jeon /* Error output already done inside the function. */ 353*1e9ea7e0SNamjae Jeon return -EINVAL; 354*1e9ea7e0SNamjae Jeon } 355*1e9ea7e0SNamjae Jeon ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); 356*1e9ea7e0SNamjae Jeon /* 357*1e9ea7e0SNamjae Jeon * Allocate a buffer to store the whole restart page so we can multi 358*1e9ea7e0SNamjae Jeon * sector transfer deprotect it. 359*1e9ea7e0SNamjae Jeon */ 360*1e9ea7e0SNamjae Jeon trp = ntfs_malloc_nofs(le32_to_cpu(rp->system_page_size)); 361*1e9ea7e0SNamjae Jeon if (!trp) { 362*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Failed to allocate memory for $LogFile " 363*1e9ea7e0SNamjae Jeon "restart page buffer."); 364*1e9ea7e0SNamjae Jeon return -ENOMEM; 365*1e9ea7e0SNamjae Jeon } 366*1e9ea7e0SNamjae Jeon /* 367*1e9ea7e0SNamjae Jeon * Read the whole of the restart page into the buffer. If it fits 368*1e9ea7e0SNamjae Jeon * completely inside @rp, just copy it from there. Otherwise map all 369*1e9ea7e0SNamjae Jeon * the required pages and copy the data from them. 370*1e9ea7e0SNamjae Jeon */ 371*1e9ea7e0SNamjae Jeon size = PAGE_SIZE - (pos & ~PAGE_MASK); 372*1e9ea7e0SNamjae Jeon if (size >= le32_to_cpu(rp->system_page_size)) { 373*1e9ea7e0SNamjae Jeon memcpy(trp, rp, le32_to_cpu(rp->system_page_size)); 374*1e9ea7e0SNamjae Jeon } else { 375*1e9ea7e0SNamjae Jeon pgoff_t idx; 376*1e9ea7e0SNamjae Jeon struct page *page; 377*1e9ea7e0SNamjae Jeon int have_read, to_read; 378*1e9ea7e0SNamjae Jeon 379*1e9ea7e0SNamjae Jeon /* First copy what we already have in @rp. */ 380*1e9ea7e0SNamjae Jeon memcpy(trp, rp, size); 381*1e9ea7e0SNamjae Jeon /* Copy the remaining data one page at a time. */ 382*1e9ea7e0SNamjae Jeon have_read = size; 383*1e9ea7e0SNamjae Jeon to_read = le32_to_cpu(rp->system_page_size) - size; 384*1e9ea7e0SNamjae Jeon idx = (pos + size) >> PAGE_SHIFT; 385*1e9ea7e0SNamjae Jeon BUG_ON((pos + size) & ~PAGE_MASK); 386*1e9ea7e0SNamjae Jeon do { 387*1e9ea7e0SNamjae Jeon page = ntfs_map_page(vi->i_mapping, idx); 388*1e9ea7e0SNamjae Jeon if (IS_ERR(page)) { 389*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Error mapping $LogFile " 390*1e9ea7e0SNamjae Jeon "page (index %lu).", idx); 391*1e9ea7e0SNamjae Jeon err = PTR_ERR(page); 392*1e9ea7e0SNamjae Jeon if (err != -EIO && err != -ENOMEM) 393*1e9ea7e0SNamjae Jeon err = -EIO; 394*1e9ea7e0SNamjae Jeon goto err_out; 395*1e9ea7e0SNamjae Jeon } 396*1e9ea7e0SNamjae Jeon size = min_t(int, to_read, PAGE_SIZE); 397*1e9ea7e0SNamjae Jeon memcpy((u8*)trp + have_read, page_address(page), size); 398*1e9ea7e0SNamjae Jeon ntfs_unmap_page(page); 399*1e9ea7e0SNamjae Jeon have_read += size; 400*1e9ea7e0SNamjae Jeon to_read -= size; 401*1e9ea7e0SNamjae Jeon idx++; 402*1e9ea7e0SNamjae Jeon } while (to_read > 0); 403*1e9ea7e0SNamjae Jeon } 404*1e9ea7e0SNamjae Jeon /* 405*1e9ea7e0SNamjae Jeon * Perform the multi sector transfer deprotection on the buffer if the 406*1e9ea7e0SNamjae Jeon * restart page is protected. 407*1e9ea7e0SNamjae Jeon */ 408*1e9ea7e0SNamjae Jeon if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) 409*1e9ea7e0SNamjae Jeon && post_read_mst_fixup((NTFS_RECORD*)trp, 410*1e9ea7e0SNamjae Jeon le32_to_cpu(rp->system_page_size))) { 411*1e9ea7e0SNamjae Jeon /* 412*1e9ea7e0SNamjae Jeon * A multi sector tranfer error was detected. We only need to 413*1e9ea7e0SNamjae Jeon * abort if the restart page contents exceed the multi sector 414*1e9ea7e0SNamjae Jeon * transfer fixup of the first sector. 415*1e9ea7e0SNamjae Jeon */ 416*1e9ea7e0SNamjae Jeon if (le16_to_cpu(rp->restart_area_offset) + 417*1e9ea7e0SNamjae Jeon le16_to_cpu(ra->restart_area_length) > 418*1e9ea7e0SNamjae Jeon NTFS_BLOCK_SIZE - sizeof(u16)) { 419*1e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Multi sector transfer error " 420*1e9ea7e0SNamjae Jeon "detected in $LogFile restart page."); 421*1e9ea7e0SNamjae Jeon err = -EINVAL; 422*1e9ea7e0SNamjae Jeon goto err_out; 423*1e9ea7e0SNamjae Jeon } 424*1e9ea7e0SNamjae Jeon } 425*1e9ea7e0SNamjae Jeon /* 426*1e9ea7e0SNamjae Jeon * If the restart page is modified by chkdsk or there are no active 427*1e9ea7e0SNamjae Jeon * logfile clients, the logfile is consistent. Otherwise, need to 428*1e9ea7e0SNamjae Jeon * check the log client records for consistency, too. 429*1e9ea7e0SNamjae Jeon */ 430*1e9ea7e0SNamjae Jeon err = 0; 431*1e9ea7e0SNamjae Jeon if (ntfs_is_rstr_record(rp->magic) && 432*1e9ea7e0SNamjae Jeon ra->client_in_use_list != LOGFILE_NO_CLIENT) { 433*1e9ea7e0SNamjae Jeon if (!ntfs_check_log_client_array(vi, trp)) { 434*1e9ea7e0SNamjae Jeon err = -EINVAL; 435*1e9ea7e0SNamjae Jeon goto err_out; 436*1e9ea7e0SNamjae Jeon } 437*1e9ea7e0SNamjae Jeon } 438*1e9ea7e0SNamjae Jeon if (lsn) { 439*1e9ea7e0SNamjae Jeon if (ntfs_is_rstr_record(rp->magic)) 440*1e9ea7e0SNamjae Jeon *lsn = sle64_to_cpu(ra->current_lsn); 441*1e9ea7e0SNamjae Jeon else /* if (ntfs_is_chkd_record(rp->magic)) */ 442*1e9ea7e0SNamjae Jeon *lsn = sle64_to_cpu(rp->chkdsk_lsn); 443*1e9ea7e0SNamjae Jeon } 444*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 445*1e9ea7e0SNamjae Jeon if (wrp) 446*1e9ea7e0SNamjae Jeon *wrp = trp; 447*1e9ea7e0SNamjae Jeon else { 448*1e9ea7e0SNamjae Jeon err_out: 449*1e9ea7e0SNamjae Jeon ntfs_free(trp); 450*1e9ea7e0SNamjae Jeon } 451*1e9ea7e0SNamjae Jeon return err; 452*1e9ea7e0SNamjae Jeon } 453*1e9ea7e0SNamjae Jeon 454*1e9ea7e0SNamjae Jeon /** 455*1e9ea7e0SNamjae Jeon * ntfs_check_logfile - check the journal for consistency 456*1e9ea7e0SNamjae Jeon * @log_vi: struct inode of loaded journal $LogFile to check 457*1e9ea7e0SNamjae Jeon * @rp: [OUT] on success this is a copy of the current restart page 458*1e9ea7e0SNamjae Jeon * 459*1e9ea7e0SNamjae Jeon * Check the $LogFile journal for consistency and return 'true' if it is 460*1e9ea7e0SNamjae Jeon * consistent and 'false' if not. On success, the current restart page is 461*1e9ea7e0SNamjae Jeon * returned in *@rp. Caller must call ntfs_free(*@rp) when finished with it. 462*1e9ea7e0SNamjae Jeon * 463*1e9ea7e0SNamjae Jeon * At present we only check the two restart pages and ignore the log record 464*1e9ea7e0SNamjae Jeon * pages. 465*1e9ea7e0SNamjae Jeon * 466*1e9ea7e0SNamjae Jeon * Note that the MstProtected flag is not set on the $LogFile inode and hence 467*1e9ea7e0SNamjae Jeon * when reading pages they are not deprotected. This is because we do not know 468*1e9ea7e0SNamjae Jeon * if the $LogFile was created on a system with a different page size to ours 469*1e9ea7e0SNamjae Jeon * yet and mst deprotection would fail if our page size is smaller. 470*1e9ea7e0SNamjae Jeon */ 471*1e9ea7e0SNamjae Jeon bool ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp) 472*1e9ea7e0SNamjae Jeon { 473*1e9ea7e0SNamjae Jeon s64 size, pos; 474*1e9ea7e0SNamjae Jeon LSN rstr1_lsn, rstr2_lsn; 475*1e9ea7e0SNamjae Jeon ntfs_volume *vol = NTFS_SB(log_vi->i_sb); 476*1e9ea7e0SNamjae Jeon struct address_space *mapping = log_vi->i_mapping; 477*1e9ea7e0SNamjae Jeon struct page *page = NULL; 478*1e9ea7e0SNamjae Jeon u8 *kaddr = NULL; 479*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *rstr1_ph = NULL; 480*1e9ea7e0SNamjae Jeon RESTART_PAGE_HEADER *rstr2_ph = NULL; 481*1e9ea7e0SNamjae Jeon int log_page_size, err; 482*1e9ea7e0SNamjae Jeon bool logfile_is_empty = true; 483*1e9ea7e0SNamjae Jeon u8 log_page_bits; 484*1e9ea7e0SNamjae Jeon 485*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 486*1e9ea7e0SNamjae Jeon /* An empty $LogFile must have been clean before it got emptied. */ 487*1e9ea7e0SNamjae Jeon if (NVolLogFileEmpty(vol)) 488*1e9ea7e0SNamjae Jeon goto is_empty; 489*1e9ea7e0SNamjae Jeon size = i_size_read(log_vi); 490*1e9ea7e0SNamjae Jeon /* Make sure the file doesn't exceed the maximum allowed size. */ 491*1e9ea7e0SNamjae Jeon if (size > MaxLogFileSize) 492*1e9ea7e0SNamjae Jeon size = MaxLogFileSize; 493*1e9ea7e0SNamjae Jeon /* 494*1e9ea7e0SNamjae Jeon * Truncate size to a multiple of the page cache size or the default 495*1e9ea7e0SNamjae Jeon * log page size if the page cache size is between the default log page 496*1e9ea7e0SNamjae Jeon * log page size if the page cache size is between the default log page 497*1e9ea7e0SNamjae Jeon * size and twice that. 498*1e9ea7e0SNamjae Jeon */ 499*1e9ea7e0SNamjae Jeon if (PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= 500*1e9ea7e0SNamjae Jeon DefaultLogPageSize * 2) 501*1e9ea7e0SNamjae Jeon log_page_size = DefaultLogPageSize; 502*1e9ea7e0SNamjae Jeon else 503*1e9ea7e0SNamjae Jeon log_page_size = PAGE_SIZE; 504*1e9ea7e0SNamjae Jeon /* 505*1e9ea7e0SNamjae Jeon * Use ntfs_ffs() instead of ffs() to enable the compiler to 506*1e9ea7e0SNamjae Jeon * optimize log_page_size and log_page_bits into constants. 507*1e9ea7e0SNamjae Jeon */ 508*1e9ea7e0SNamjae Jeon log_page_bits = ntfs_ffs(log_page_size) - 1; 509*1e9ea7e0SNamjae Jeon size &= ~(s64)(log_page_size - 1); 510*1e9ea7e0SNamjae Jeon /* 511*1e9ea7e0SNamjae Jeon * Ensure the log file is big enough to store at least the two restart 512*1e9ea7e0SNamjae Jeon * pages and the minimum number of log record pages. 513*1e9ea7e0SNamjae Jeon */ 514*1e9ea7e0SNamjae Jeon if (size < log_page_size * 2 || (size - log_page_size * 2) >> 515*1e9ea7e0SNamjae Jeon log_page_bits < MinLogRecordPages) { 516*1e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "$LogFile is too small."); 517*1e9ea7e0SNamjae Jeon return false; 518*1e9ea7e0SNamjae Jeon } 519*1e9ea7e0SNamjae Jeon /* 520*1e9ea7e0SNamjae Jeon * Read through the file looking for a restart page. Since the restart 521*1e9ea7e0SNamjae Jeon * page header is at the beginning of a page we only need to search at 522*1e9ea7e0SNamjae Jeon * what could be the beginning of a page (for each page size) rather 523*1e9ea7e0SNamjae Jeon * than scanning the whole file byte by byte. If all potential places 524*1e9ea7e0SNamjae Jeon * contain empty and uninitialzed records, the log file can be assumed 525*1e9ea7e0SNamjae Jeon * to be empty. 526*1e9ea7e0SNamjae Jeon */ 527*1e9ea7e0SNamjae Jeon for (pos = 0; pos < size; pos <<= 1) { 528*1e9ea7e0SNamjae Jeon pgoff_t idx = pos >> PAGE_SHIFT; 529*1e9ea7e0SNamjae Jeon if (!page || page->index != idx) { 530*1e9ea7e0SNamjae Jeon if (page) 531*1e9ea7e0SNamjae Jeon ntfs_unmap_page(page); 532*1e9ea7e0SNamjae Jeon page = ntfs_map_page(mapping, idx); 533*1e9ea7e0SNamjae Jeon if (IS_ERR(page)) { 534*1e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "Error mapping $LogFile " 535*1e9ea7e0SNamjae Jeon "page (index %lu).", idx); 536*1e9ea7e0SNamjae Jeon goto err_out; 537*1e9ea7e0SNamjae Jeon } 538*1e9ea7e0SNamjae Jeon } 539*1e9ea7e0SNamjae Jeon kaddr = (u8*)page_address(page) + (pos & ~PAGE_MASK); 540*1e9ea7e0SNamjae Jeon /* 541*1e9ea7e0SNamjae Jeon * A non-empty block means the logfile is not empty while an 542*1e9ea7e0SNamjae Jeon * empty block after a non-empty block has been encountered 543*1e9ea7e0SNamjae Jeon * means we are done. 544*1e9ea7e0SNamjae Jeon */ 545*1e9ea7e0SNamjae Jeon if (!ntfs_is_empty_recordp((le32*)kaddr)) 546*1e9ea7e0SNamjae Jeon logfile_is_empty = false; 547*1e9ea7e0SNamjae Jeon else if (!logfile_is_empty) 548*1e9ea7e0SNamjae Jeon break; 549*1e9ea7e0SNamjae Jeon /* 550*1e9ea7e0SNamjae Jeon * A log record page means there cannot be a restart page after 551*1e9ea7e0SNamjae Jeon * this so no need to continue searching. 552*1e9ea7e0SNamjae Jeon */ 553*1e9ea7e0SNamjae Jeon if (ntfs_is_rcrd_recordp((le32*)kaddr)) 554*1e9ea7e0SNamjae Jeon break; 555*1e9ea7e0SNamjae Jeon /* If not a (modified by chkdsk) restart page, continue. */ 556*1e9ea7e0SNamjae Jeon if (!ntfs_is_rstr_recordp((le32*)kaddr) && 557*1e9ea7e0SNamjae Jeon !ntfs_is_chkd_recordp((le32*)kaddr)) { 558*1e9ea7e0SNamjae Jeon if (!pos) 559*1e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 560*1e9ea7e0SNamjae Jeon continue; 561*1e9ea7e0SNamjae Jeon } 562*1e9ea7e0SNamjae Jeon /* 563*1e9ea7e0SNamjae Jeon * Check the (modified by chkdsk) restart page for consistency 564*1e9ea7e0SNamjae Jeon * and get a copy of the complete multi sector transfer 565*1e9ea7e0SNamjae Jeon * deprotected restart page. 566*1e9ea7e0SNamjae Jeon */ 567*1e9ea7e0SNamjae Jeon err = ntfs_check_and_load_restart_page(log_vi, 568*1e9ea7e0SNamjae Jeon (RESTART_PAGE_HEADER*)kaddr, pos, 569*1e9ea7e0SNamjae Jeon !rstr1_ph ? &rstr1_ph : &rstr2_ph, 570*1e9ea7e0SNamjae Jeon !rstr1_ph ? &rstr1_lsn : &rstr2_lsn); 571*1e9ea7e0SNamjae Jeon if (!err) { 572*1e9ea7e0SNamjae Jeon /* 573*1e9ea7e0SNamjae Jeon * If we have now found the first (modified by chkdsk) 574*1e9ea7e0SNamjae Jeon * restart page, continue looking for the second one. 575*1e9ea7e0SNamjae Jeon */ 576*1e9ea7e0SNamjae Jeon if (!pos) { 577*1e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 578*1e9ea7e0SNamjae Jeon continue; 579*1e9ea7e0SNamjae Jeon } 580*1e9ea7e0SNamjae Jeon /* 581*1e9ea7e0SNamjae Jeon * We have now found the second (modified by chkdsk) 582*1e9ea7e0SNamjae Jeon * restart page, so we can stop looking. 583*1e9ea7e0SNamjae Jeon */ 584*1e9ea7e0SNamjae Jeon break; 585*1e9ea7e0SNamjae Jeon } 586*1e9ea7e0SNamjae Jeon /* 587*1e9ea7e0SNamjae Jeon * Error output already done inside the function. Note, we do 588*1e9ea7e0SNamjae Jeon * not abort if the restart page was invalid as we might still 589*1e9ea7e0SNamjae Jeon * find a valid one further in the file. 590*1e9ea7e0SNamjae Jeon */ 591*1e9ea7e0SNamjae Jeon if (err != -EINVAL) { 592*1e9ea7e0SNamjae Jeon ntfs_unmap_page(page); 593*1e9ea7e0SNamjae Jeon goto err_out; 594*1e9ea7e0SNamjae Jeon } 595*1e9ea7e0SNamjae Jeon /* Continue looking. */ 596*1e9ea7e0SNamjae Jeon if (!pos) 597*1e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 598*1e9ea7e0SNamjae Jeon } 599*1e9ea7e0SNamjae Jeon if (page) 600*1e9ea7e0SNamjae Jeon ntfs_unmap_page(page); 601*1e9ea7e0SNamjae Jeon if (logfile_is_empty) { 602*1e9ea7e0SNamjae Jeon NVolSetLogFileEmpty(vol); 603*1e9ea7e0SNamjae Jeon is_empty: 604*1e9ea7e0SNamjae Jeon ntfs_debug("Done. ($LogFile is empty.)"); 605*1e9ea7e0SNamjae Jeon return true; 606*1e9ea7e0SNamjae Jeon } 607*1e9ea7e0SNamjae Jeon if (!rstr1_ph) { 608*1e9ea7e0SNamjae Jeon BUG_ON(rstr2_ph); 609*1e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "Did not find any restart pages in " 610*1e9ea7e0SNamjae Jeon "$LogFile and it was not empty."); 611*1e9ea7e0SNamjae Jeon return false; 612*1e9ea7e0SNamjae Jeon } 613*1e9ea7e0SNamjae Jeon /* If both restart pages were found, use the more recent one. */ 614*1e9ea7e0SNamjae Jeon if (rstr2_ph) { 615*1e9ea7e0SNamjae Jeon /* 616*1e9ea7e0SNamjae Jeon * If the second restart area is more recent, switch to it. 617*1e9ea7e0SNamjae Jeon * Otherwise just throw it away. 618*1e9ea7e0SNamjae Jeon */ 619*1e9ea7e0SNamjae Jeon if (rstr2_lsn > rstr1_lsn) { 620*1e9ea7e0SNamjae Jeon ntfs_debug("Using second restart page as it is more " 621*1e9ea7e0SNamjae Jeon "recent."); 622*1e9ea7e0SNamjae Jeon ntfs_free(rstr1_ph); 623*1e9ea7e0SNamjae Jeon rstr1_ph = rstr2_ph; 624*1e9ea7e0SNamjae Jeon /* rstr1_lsn = rstr2_lsn; */ 625*1e9ea7e0SNamjae Jeon } else { 626*1e9ea7e0SNamjae Jeon ntfs_debug("Using first restart page as it is more " 627*1e9ea7e0SNamjae Jeon "recent."); 628*1e9ea7e0SNamjae Jeon ntfs_free(rstr2_ph); 629*1e9ea7e0SNamjae Jeon } 630*1e9ea7e0SNamjae Jeon rstr2_ph = NULL; 631*1e9ea7e0SNamjae Jeon } 632*1e9ea7e0SNamjae Jeon /* All consistency checks passed. */ 633*1e9ea7e0SNamjae Jeon if (rp) 634*1e9ea7e0SNamjae Jeon *rp = rstr1_ph; 635*1e9ea7e0SNamjae Jeon else 636*1e9ea7e0SNamjae Jeon ntfs_free(rstr1_ph); 637*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 638*1e9ea7e0SNamjae Jeon return true; 639*1e9ea7e0SNamjae Jeon err_out: 640*1e9ea7e0SNamjae Jeon if (rstr1_ph) 641*1e9ea7e0SNamjae Jeon ntfs_free(rstr1_ph); 642*1e9ea7e0SNamjae Jeon return false; 643*1e9ea7e0SNamjae Jeon } 644*1e9ea7e0SNamjae Jeon 645*1e9ea7e0SNamjae Jeon /** 646*1e9ea7e0SNamjae Jeon * ntfs_is_logfile_clean - check in the journal if the volume is clean 647*1e9ea7e0SNamjae Jeon * @log_vi: struct inode of loaded journal $LogFile to check 648*1e9ea7e0SNamjae Jeon * @rp: copy of the current restart page 649*1e9ea7e0SNamjae Jeon * 650*1e9ea7e0SNamjae Jeon * Analyze the $LogFile journal and return 'true' if it indicates the volume was 651*1e9ea7e0SNamjae Jeon * shutdown cleanly and 'false' if not. 652*1e9ea7e0SNamjae Jeon * 653*1e9ea7e0SNamjae Jeon * At present we only look at the two restart pages and ignore the log record 654*1e9ea7e0SNamjae Jeon * pages. This is a little bit crude in that there will be a very small number 655*1e9ea7e0SNamjae Jeon * of cases where we think that a volume is dirty when in fact it is clean. 656*1e9ea7e0SNamjae Jeon * This should only affect volumes that have not been shutdown cleanly but did 657*1e9ea7e0SNamjae Jeon * not have any pending, non-check-pointed i/o, i.e. they were completely idle 658*1e9ea7e0SNamjae Jeon * at least for the five seconds preceding the unclean shutdown. 659*1e9ea7e0SNamjae Jeon * 660*1e9ea7e0SNamjae Jeon * This function assumes that the $LogFile journal has already been consistency 661*1e9ea7e0SNamjae Jeon * checked by a call to ntfs_check_logfile() and in particular if the $LogFile 662*1e9ea7e0SNamjae Jeon * is empty this function requires that NVolLogFileEmpty() is true otherwise an 663*1e9ea7e0SNamjae Jeon * empty volume will be reported as dirty. 664*1e9ea7e0SNamjae Jeon */ 665*1e9ea7e0SNamjae Jeon bool ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp) 666*1e9ea7e0SNamjae Jeon { 667*1e9ea7e0SNamjae Jeon ntfs_volume *vol = NTFS_SB(log_vi->i_sb); 668*1e9ea7e0SNamjae Jeon RESTART_AREA *ra; 669*1e9ea7e0SNamjae Jeon 670*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 671*1e9ea7e0SNamjae Jeon /* An empty $LogFile must have been clean before it got emptied. */ 672*1e9ea7e0SNamjae Jeon if (NVolLogFileEmpty(vol)) { 673*1e9ea7e0SNamjae Jeon ntfs_debug("Done. ($LogFile is empty.)"); 674*1e9ea7e0SNamjae Jeon return true; 675*1e9ea7e0SNamjae Jeon } 676*1e9ea7e0SNamjae Jeon BUG_ON(!rp); 677*1e9ea7e0SNamjae Jeon if (!ntfs_is_rstr_record(rp->magic) && 678*1e9ea7e0SNamjae Jeon !ntfs_is_chkd_record(rp->magic)) { 679*1e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "Restart page buffer is invalid. This is " 680*1e9ea7e0SNamjae Jeon "probably a bug in that the $LogFile should " 681*1e9ea7e0SNamjae Jeon "have been consistency checked before calling " 682*1e9ea7e0SNamjae Jeon "this function."); 683*1e9ea7e0SNamjae Jeon return false; 684*1e9ea7e0SNamjae Jeon } 685*1e9ea7e0SNamjae Jeon ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); 686*1e9ea7e0SNamjae Jeon /* 687*1e9ea7e0SNamjae Jeon * If the $LogFile has active clients, i.e. it is open, and we do not 688*1e9ea7e0SNamjae Jeon * have the RESTART_VOLUME_IS_CLEAN bit set in the restart area flags, 689*1e9ea7e0SNamjae Jeon * we assume there was an unclean shutdown. 690*1e9ea7e0SNamjae Jeon */ 691*1e9ea7e0SNamjae Jeon if (ra->client_in_use_list != LOGFILE_NO_CLIENT && 692*1e9ea7e0SNamjae Jeon !(ra->flags & RESTART_VOLUME_IS_CLEAN)) { 693*1e9ea7e0SNamjae Jeon ntfs_debug("Done. $LogFile indicates a dirty shutdown."); 694*1e9ea7e0SNamjae Jeon return false; 695*1e9ea7e0SNamjae Jeon } 696*1e9ea7e0SNamjae Jeon /* $LogFile indicates a clean shutdown. */ 697*1e9ea7e0SNamjae Jeon ntfs_debug("Done. $LogFile indicates a clean shutdown."); 698*1e9ea7e0SNamjae Jeon return true; 699*1e9ea7e0SNamjae Jeon } 700*1e9ea7e0SNamjae Jeon 701*1e9ea7e0SNamjae Jeon /** 702*1e9ea7e0SNamjae Jeon * ntfs_empty_logfile - empty the contents of the $LogFile journal 703*1e9ea7e0SNamjae Jeon * @log_vi: struct inode of loaded journal $LogFile to empty 704*1e9ea7e0SNamjae Jeon * 705*1e9ea7e0SNamjae Jeon * Empty the contents of the $LogFile journal @log_vi and return 'true' on 706*1e9ea7e0SNamjae Jeon * success and 'false' on error. 707*1e9ea7e0SNamjae Jeon * 708*1e9ea7e0SNamjae Jeon * This function assumes that the $LogFile journal has already been consistency 709*1e9ea7e0SNamjae Jeon * checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean() 710*1e9ea7e0SNamjae Jeon * has been used to ensure that the $LogFile is clean. 711*1e9ea7e0SNamjae Jeon */ 712*1e9ea7e0SNamjae Jeon bool ntfs_empty_logfile(struct inode *log_vi) 713*1e9ea7e0SNamjae Jeon { 714*1e9ea7e0SNamjae Jeon VCN vcn, end_vcn; 715*1e9ea7e0SNamjae Jeon ntfs_inode *log_ni = NTFS_I(log_vi); 716*1e9ea7e0SNamjae Jeon ntfs_volume *vol = log_ni->vol; 717*1e9ea7e0SNamjae Jeon struct super_block *sb = vol->sb; 718*1e9ea7e0SNamjae Jeon runlist_element *rl; 719*1e9ea7e0SNamjae Jeon unsigned long flags; 720*1e9ea7e0SNamjae Jeon unsigned block_size, block_size_bits; 721*1e9ea7e0SNamjae Jeon int err; 722*1e9ea7e0SNamjae Jeon bool should_wait = true; 723*1e9ea7e0SNamjae Jeon 724*1e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 725*1e9ea7e0SNamjae Jeon if (NVolLogFileEmpty(vol)) { 726*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 727*1e9ea7e0SNamjae Jeon return true; 728*1e9ea7e0SNamjae Jeon } 729*1e9ea7e0SNamjae Jeon /* 730*1e9ea7e0SNamjae Jeon * We cannot use ntfs_attr_set() because we may be still in the middle 731*1e9ea7e0SNamjae Jeon * of a mount operation. Thus we do the emptying by hand by first 732*1e9ea7e0SNamjae Jeon * zapping the page cache pages for the $LogFile/$DATA attribute and 733*1e9ea7e0SNamjae Jeon * then emptying each of the buffers in each of the clusters specified 734*1e9ea7e0SNamjae Jeon * by the runlist by hand. 735*1e9ea7e0SNamjae Jeon */ 736*1e9ea7e0SNamjae Jeon block_size = sb->s_blocksize; 737*1e9ea7e0SNamjae Jeon block_size_bits = sb->s_blocksize_bits; 738*1e9ea7e0SNamjae Jeon vcn = 0; 739*1e9ea7e0SNamjae Jeon read_lock_irqsave(&log_ni->size_lock, flags); 740*1e9ea7e0SNamjae Jeon end_vcn = (log_ni->initialized_size + vol->cluster_size_mask) >> 741*1e9ea7e0SNamjae Jeon vol->cluster_size_bits; 742*1e9ea7e0SNamjae Jeon read_unlock_irqrestore(&log_ni->size_lock, flags); 743*1e9ea7e0SNamjae Jeon truncate_inode_pages(log_vi->i_mapping, 0); 744*1e9ea7e0SNamjae Jeon down_write(&log_ni->runlist.lock); 745*1e9ea7e0SNamjae Jeon rl = log_ni->runlist.rl; 746*1e9ea7e0SNamjae Jeon if (unlikely(!rl || vcn < rl->vcn || !rl->length)) { 747*1e9ea7e0SNamjae Jeon map_vcn: 748*1e9ea7e0SNamjae Jeon err = ntfs_map_runlist_nolock(log_ni, vcn, NULL); 749*1e9ea7e0SNamjae Jeon if (err) { 750*1e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to map runlist fragment (error " 751*1e9ea7e0SNamjae Jeon "%d).", -err); 752*1e9ea7e0SNamjae Jeon goto err; 753*1e9ea7e0SNamjae Jeon } 754*1e9ea7e0SNamjae Jeon rl = log_ni->runlist.rl; 755*1e9ea7e0SNamjae Jeon BUG_ON(!rl || vcn < rl->vcn || !rl->length); 756*1e9ea7e0SNamjae Jeon } 757*1e9ea7e0SNamjae Jeon /* Seek to the runlist element containing @vcn. */ 758*1e9ea7e0SNamjae Jeon while (rl->length && vcn >= rl[1].vcn) 759*1e9ea7e0SNamjae Jeon rl++; 760*1e9ea7e0SNamjae Jeon do { 761*1e9ea7e0SNamjae Jeon LCN lcn; 762*1e9ea7e0SNamjae Jeon sector_t block, end_block; 763*1e9ea7e0SNamjae Jeon s64 len; 764*1e9ea7e0SNamjae Jeon 765*1e9ea7e0SNamjae Jeon /* 766*1e9ea7e0SNamjae Jeon * If this run is not mapped map it now and start again as the 767*1e9ea7e0SNamjae Jeon * runlist will have been updated. 768*1e9ea7e0SNamjae Jeon */ 769*1e9ea7e0SNamjae Jeon lcn = rl->lcn; 770*1e9ea7e0SNamjae Jeon if (unlikely(lcn == LCN_RL_NOT_MAPPED)) { 771*1e9ea7e0SNamjae Jeon vcn = rl->vcn; 772*1e9ea7e0SNamjae Jeon goto map_vcn; 773*1e9ea7e0SNamjae Jeon } 774*1e9ea7e0SNamjae Jeon /* If this run is not valid abort with an error. */ 775*1e9ea7e0SNamjae Jeon if (unlikely(!rl->length || lcn < LCN_HOLE)) 776*1e9ea7e0SNamjae Jeon goto rl_err; 777*1e9ea7e0SNamjae Jeon /* Skip holes. */ 778*1e9ea7e0SNamjae Jeon if (lcn == LCN_HOLE) 779*1e9ea7e0SNamjae Jeon continue; 780*1e9ea7e0SNamjae Jeon block = lcn << vol->cluster_size_bits >> block_size_bits; 781*1e9ea7e0SNamjae Jeon len = rl->length; 782*1e9ea7e0SNamjae Jeon if (rl[1].vcn > end_vcn) 783*1e9ea7e0SNamjae Jeon len = end_vcn - rl->vcn; 784*1e9ea7e0SNamjae Jeon end_block = (lcn + len) << vol->cluster_size_bits >> 785*1e9ea7e0SNamjae Jeon block_size_bits; 786*1e9ea7e0SNamjae Jeon /* Iterate over the blocks in the run and empty them. */ 787*1e9ea7e0SNamjae Jeon do { 788*1e9ea7e0SNamjae Jeon struct buffer_head *bh; 789*1e9ea7e0SNamjae Jeon 790*1e9ea7e0SNamjae Jeon /* Obtain the buffer, possibly not uptodate. */ 791*1e9ea7e0SNamjae Jeon bh = sb_getblk(sb, block); 792*1e9ea7e0SNamjae Jeon BUG_ON(!bh); 793*1e9ea7e0SNamjae Jeon /* Setup buffer i/o submission. */ 794*1e9ea7e0SNamjae Jeon lock_buffer(bh); 795*1e9ea7e0SNamjae Jeon bh->b_end_io = end_buffer_write_sync; 796*1e9ea7e0SNamjae Jeon get_bh(bh); 797*1e9ea7e0SNamjae Jeon /* Set the entire contents of the buffer to 0xff. */ 798*1e9ea7e0SNamjae Jeon memset(bh->b_data, -1, block_size); 799*1e9ea7e0SNamjae Jeon if (!buffer_uptodate(bh)) 800*1e9ea7e0SNamjae Jeon set_buffer_uptodate(bh); 801*1e9ea7e0SNamjae Jeon if (buffer_dirty(bh)) 802*1e9ea7e0SNamjae Jeon clear_buffer_dirty(bh); 803*1e9ea7e0SNamjae Jeon /* 804*1e9ea7e0SNamjae Jeon * Submit the buffer and wait for i/o to complete but 805*1e9ea7e0SNamjae Jeon * only for the first buffer so we do not miss really 806*1e9ea7e0SNamjae Jeon * serious i/o errors. Once the first buffer has 807*1e9ea7e0SNamjae Jeon * completed ignore errors afterwards as we can assume 808*1e9ea7e0SNamjae Jeon * that if one buffer worked all of them will work. 809*1e9ea7e0SNamjae Jeon */ 810*1e9ea7e0SNamjae Jeon submit_bh(REQ_OP_WRITE, bh); 811*1e9ea7e0SNamjae Jeon if (should_wait) { 812*1e9ea7e0SNamjae Jeon should_wait = false; 813*1e9ea7e0SNamjae Jeon wait_on_buffer(bh); 814*1e9ea7e0SNamjae Jeon if (unlikely(!buffer_uptodate(bh))) 815*1e9ea7e0SNamjae Jeon goto io_err; 816*1e9ea7e0SNamjae Jeon } 817*1e9ea7e0SNamjae Jeon brelse(bh); 818*1e9ea7e0SNamjae Jeon } while (++block < end_block); 819*1e9ea7e0SNamjae Jeon } while ((++rl)->vcn < end_vcn); 820*1e9ea7e0SNamjae Jeon up_write(&log_ni->runlist.lock); 821*1e9ea7e0SNamjae Jeon /* 822*1e9ea7e0SNamjae Jeon * Zap the pages again just in case any got instantiated whilst we were 823*1e9ea7e0SNamjae Jeon * emptying the blocks by hand. FIXME: We may not have completed 824*1e9ea7e0SNamjae Jeon * writing to all the buffer heads yet so this may happen too early. 825*1e9ea7e0SNamjae Jeon * We really should use a kernel thread to do the emptying 826*1e9ea7e0SNamjae Jeon * asynchronously and then we can also set the volume dirty and output 827*1e9ea7e0SNamjae Jeon * an error message if emptying should fail. 828*1e9ea7e0SNamjae Jeon */ 829*1e9ea7e0SNamjae Jeon truncate_inode_pages(log_vi->i_mapping, 0); 830*1e9ea7e0SNamjae Jeon /* Set the flag so we do not have to do it again on remount. */ 831*1e9ea7e0SNamjae Jeon NVolSetLogFileEmpty(vol); 832*1e9ea7e0SNamjae Jeon ntfs_debug("Done."); 833*1e9ea7e0SNamjae Jeon return true; 834*1e9ea7e0SNamjae Jeon io_err: 835*1e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to write buffer. Unmount and run chkdsk."); 836*1e9ea7e0SNamjae Jeon goto dirty_err; 837*1e9ea7e0SNamjae Jeon rl_err: 838*1e9ea7e0SNamjae Jeon ntfs_error(sb, "Runlist is corrupt. Unmount and run chkdsk."); 839*1e9ea7e0SNamjae Jeon dirty_err: 840*1e9ea7e0SNamjae Jeon NVolSetErrors(vol); 841*1e9ea7e0SNamjae Jeon err = -EIO; 842*1e9ea7e0SNamjae Jeon err: 843*1e9ea7e0SNamjae Jeon up_write(&log_ni->runlist.lock); 844*1e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to fill $LogFile with 0xff bytes (error %d).", 845*1e9ea7e0SNamjae Jeon -err); 846*1e9ea7e0SNamjae Jeon return false; 847*1e9ea7e0SNamjae Jeon } 848*1e9ea7e0SNamjae Jeon 849*1e9ea7e0SNamjae Jeon #endif /* NTFS_RW */ 850