11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 3*5218cd10SNamjae Jeon * NTFS kernel journal handling. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2002-2007 Anton Altaparmakov 61e9ea7e0SNamjae Jeon */ 71e9ea7e0SNamjae Jeon 8*5218cd10SNamjae Jeon #include <linux/blkdev.h> 91e9ea7e0SNamjae Jeon 101e9ea7e0SNamjae Jeon #include "attrib.h" 111e9ea7e0SNamjae Jeon #include "logfile.h" 121e9ea7e0SNamjae Jeon #include "ntfs.h" 131e9ea7e0SNamjae Jeon 14*5218cd10SNamjae Jeon /* 151e9ea7e0SNamjae Jeon * ntfs_check_restart_page_header - check the page header for consistency 16*5218cd10SNamjae Jeon * @vi: LogFile inode to which the restart page header belongs 171e9ea7e0SNamjae Jeon * @rp: restart page header to check 181e9ea7e0SNamjae Jeon * @pos: position in @vi at which the restart page header resides 191e9ea7e0SNamjae Jeon * 201e9ea7e0SNamjae Jeon * Check the restart page header @rp for consistency and return 'true' if it is 211e9ea7e0SNamjae Jeon * consistent and 'false' otherwise. 221e9ea7e0SNamjae Jeon * 231e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 241e9ea7e0SNamjae Jeon * require the full restart page. 251e9ea7e0SNamjae Jeon */ 261e9ea7e0SNamjae Jeon static bool ntfs_check_restart_page_header(struct inode *vi, 27*5218cd10SNamjae Jeon struct restart_page_header *rp, s64 pos) 281e9ea7e0SNamjae Jeon { 291e9ea7e0SNamjae Jeon u32 logfile_system_page_size, logfile_log_page_size; 301e9ea7e0SNamjae Jeon u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; 311e9ea7e0SNamjae Jeon bool have_usa = true; 321e9ea7e0SNamjae Jeon 331e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 341e9ea7e0SNamjae Jeon /* 351e9ea7e0SNamjae Jeon * If the system or log page sizes are smaller than the ntfs block size 361e9ea7e0SNamjae Jeon * or either is not a power of 2 we cannot handle this log file. 371e9ea7e0SNamjae Jeon */ 381e9ea7e0SNamjae Jeon logfile_system_page_size = le32_to_cpu(rp->system_page_size); 391e9ea7e0SNamjae Jeon logfile_log_page_size = le32_to_cpu(rp->log_page_size); 401e9ea7e0SNamjae Jeon if (logfile_system_page_size < NTFS_BLOCK_SIZE || 411e9ea7e0SNamjae Jeon logfile_log_page_size < NTFS_BLOCK_SIZE || 421e9ea7e0SNamjae Jeon logfile_system_page_size & 431e9ea7e0SNamjae Jeon (logfile_system_page_size - 1) || 441e9ea7e0SNamjae Jeon !is_power_of_2(logfile_log_page_size)) { 45*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, "LogFile uses unsupported page size."); 461e9ea7e0SNamjae Jeon return false; 471e9ea7e0SNamjae Jeon } 481e9ea7e0SNamjae Jeon /* 491e9ea7e0SNamjae Jeon * We must be either at !pos (1st restart page) or at pos = system page 501e9ea7e0SNamjae Jeon * size (2nd restart page). 511e9ea7e0SNamjae Jeon */ 521e9ea7e0SNamjae Jeon if (pos && pos != logfile_system_page_size) { 53*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, "Found restart area in incorrect position in LogFile."); 541e9ea7e0SNamjae Jeon return false; 551e9ea7e0SNamjae Jeon } 561e9ea7e0SNamjae Jeon /* We only know how to handle version 1.1. */ 57*5218cd10SNamjae Jeon if (le16_to_cpu(rp->major_ver) != 1 || 58*5218cd10SNamjae Jeon le16_to_cpu(rp->minor_ver) != 1) { 59*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 60*5218cd10SNamjae Jeon "LogFile version %i.%i is not supported. (This driver supports version 1.1 only.)", 61*5218cd10SNamjae Jeon (int)le16_to_cpu(rp->major_ver), 62*5218cd10SNamjae Jeon (int)le16_to_cpu(rp->minor_ver)); 631e9ea7e0SNamjae Jeon return false; 641e9ea7e0SNamjae Jeon } 651e9ea7e0SNamjae Jeon /* 661e9ea7e0SNamjae Jeon * If chkdsk has been run the restart page may not be protected by an 671e9ea7e0SNamjae Jeon * update sequence array. 681e9ea7e0SNamjae Jeon */ 691e9ea7e0SNamjae Jeon if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { 701e9ea7e0SNamjae Jeon have_usa = false; 711e9ea7e0SNamjae Jeon goto skip_usa_checks; 721e9ea7e0SNamjae Jeon } 731e9ea7e0SNamjae Jeon /* Verify the size of the update sequence array. */ 741e9ea7e0SNamjae Jeon usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); 751e9ea7e0SNamjae Jeon if (usa_count != le16_to_cpu(rp->usa_count)) { 76*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 77*5218cd10SNamjae Jeon "LogFile restart page specifies inconsistent update sequence array count."); 781e9ea7e0SNamjae Jeon return false; 791e9ea7e0SNamjae Jeon } 801e9ea7e0SNamjae Jeon /* Verify the position of the update sequence array. */ 811e9ea7e0SNamjae Jeon usa_ofs = le16_to_cpu(rp->usa_ofs); 821e9ea7e0SNamjae Jeon usa_end = usa_ofs + usa_count * sizeof(u16); 83*5218cd10SNamjae Jeon if (usa_ofs < sizeof(struct restart_page_header) || 841e9ea7e0SNamjae Jeon usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) { 85*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 86*5218cd10SNamjae Jeon "LogFile restart page specifies inconsistent update sequence array offset."); 871e9ea7e0SNamjae Jeon return false; 881e9ea7e0SNamjae Jeon } 891e9ea7e0SNamjae Jeon skip_usa_checks: 901e9ea7e0SNamjae Jeon /* 911e9ea7e0SNamjae Jeon * Verify the position of the restart area. It must be: 921e9ea7e0SNamjae Jeon * - aligned to 8-byte boundary, 931e9ea7e0SNamjae Jeon * - after the update sequence array, and 941e9ea7e0SNamjae Jeon * - within the system page size. 951e9ea7e0SNamjae Jeon */ 961e9ea7e0SNamjae Jeon ra_ofs = le16_to_cpu(rp->restart_area_offset); 971e9ea7e0SNamjae Jeon if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : 98*5218cd10SNamjae Jeon ra_ofs < sizeof(struct restart_page_header)) || 991e9ea7e0SNamjae Jeon ra_ofs > logfile_system_page_size) { 100*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 101*5218cd10SNamjae Jeon "LogFile restart page specifies inconsistent restart area offset."); 1021e9ea7e0SNamjae Jeon return false; 1031e9ea7e0SNamjae Jeon } 1041e9ea7e0SNamjae Jeon /* 1051e9ea7e0SNamjae Jeon * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn 1061e9ea7e0SNamjae Jeon * set. 1071e9ea7e0SNamjae Jeon */ 108*5218cd10SNamjae Jeon if (!ntfs_is_chkd_record(rp->magic) && le64_to_cpu(rp->chkdsk_lsn)) { 109*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 110*5218cd10SNamjae Jeon "LogFile restart page is not modified by chkdsk but a chkdsk LSN is specified."); 1111e9ea7e0SNamjae Jeon return false; 1121e9ea7e0SNamjae Jeon } 1131e9ea7e0SNamjae Jeon ntfs_debug("Done."); 1141e9ea7e0SNamjae Jeon return true; 1151e9ea7e0SNamjae Jeon } 1161e9ea7e0SNamjae Jeon 117*5218cd10SNamjae Jeon /* 1181e9ea7e0SNamjae Jeon * ntfs_check_restart_area - check the restart area for consistency 119*5218cd10SNamjae Jeon * @vi: LogFile inode to which the restart page belongs 1201e9ea7e0SNamjae Jeon * @rp: restart page whose restart area to check 1211e9ea7e0SNamjae Jeon * 1221e9ea7e0SNamjae Jeon * Check the restart area of the restart page @rp for consistency and return 1231e9ea7e0SNamjae Jeon * 'true' if it is consistent and 'false' otherwise. 1241e9ea7e0SNamjae Jeon * 1251e9ea7e0SNamjae Jeon * This function assumes that the restart page header has already been 1261e9ea7e0SNamjae Jeon * consistency checked. 1271e9ea7e0SNamjae Jeon * 1281e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 1291e9ea7e0SNamjae Jeon * require the full restart page. 1301e9ea7e0SNamjae Jeon */ 131*5218cd10SNamjae Jeon static bool ntfs_check_restart_area(struct inode *vi, struct restart_page_header *rp) 1321e9ea7e0SNamjae Jeon { 1331e9ea7e0SNamjae Jeon u64 file_size; 134*5218cd10SNamjae Jeon struct restart_area *ra; 1351e9ea7e0SNamjae Jeon u16 ra_ofs, ra_len, ca_ofs; 1361e9ea7e0SNamjae Jeon u8 fs_bits; 1371e9ea7e0SNamjae Jeon 1381e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 1391e9ea7e0SNamjae Jeon ra_ofs = le16_to_cpu(rp->restart_area_offset); 140*5218cd10SNamjae Jeon ra = (struct restart_area *)((u8 *)rp + ra_ofs); 1411e9ea7e0SNamjae Jeon /* 1421e9ea7e0SNamjae Jeon * Everything before ra->file_size must be before the first word 1431e9ea7e0SNamjae Jeon * protected by an update sequence number. This ensures that it is 1441e9ea7e0SNamjae Jeon * safe to access ra->client_array_offset. 1451e9ea7e0SNamjae Jeon */ 146*5218cd10SNamjae Jeon if (ra_ofs + offsetof(struct restart_area, file_size) > 1471e9ea7e0SNamjae Jeon NTFS_BLOCK_SIZE - sizeof(u16)) { 148*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 149*5218cd10SNamjae Jeon "LogFile restart area specifies inconsistent file offset."); 1501e9ea7e0SNamjae Jeon return false; 1511e9ea7e0SNamjae Jeon } 1521e9ea7e0SNamjae Jeon /* 1531e9ea7e0SNamjae Jeon * Now that we can access ra->client_array_offset, make sure everything 1541e9ea7e0SNamjae Jeon * up to the log client array is before the first word protected by an 1551e9ea7e0SNamjae Jeon * update sequence number. This ensures we can access all of the 1561e9ea7e0SNamjae Jeon * restart area elements safely. Also, the client array offset must be 1571e9ea7e0SNamjae Jeon * aligned to an 8-byte boundary. 1581e9ea7e0SNamjae Jeon */ 1591e9ea7e0SNamjae Jeon ca_ofs = le16_to_cpu(ra->client_array_offset); 1601e9ea7e0SNamjae Jeon if (((ca_ofs + 7) & ~7) != ca_ofs || 1611e9ea7e0SNamjae Jeon ra_ofs + ca_ofs > NTFS_BLOCK_SIZE - sizeof(u16)) { 162*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 163*5218cd10SNamjae Jeon "LogFile restart area specifies inconsistent client array offset."); 1641e9ea7e0SNamjae Jeon return false; 1651e9ea7e0SNamjae Jeon } 1661e9ea7e0SNamjae Jeon /* 1671e9ea7e0SNamjae Jeon * The restart area must end within the system page size both when 1681e9ea7e0SNamjae Jeon * calculated manually and as specified by ra->restart_area_length. 1691e9ea7e0SNamjae Jeon * Also, the calculated length must not exceed the specified length. 1701e9ea7e0SNamjae Jeon */ 1711e9ea7e0SNamjae Jeon ra_len = ca_ofs + le16_to_cpu(ra->log_clients) * 172*5218cd10SNamjae Jeon sizeof(struct log_client_record); 1731e9ea7e0SNamjae Jeon if (ra_ofs + ra_len > le32_to_cpu(rp->system_page_size) || 1741e9ea7e0SNamjae Jeon ra_ofs + le16_to_cpu(ra->restart_area_length) > 1751e9ea7e0SNamjae Jeon le32_to_cpu(rp->system_page_size) || 1761e9ea7e0SNamjae Jeon ra_len > le16_to_cpu(ra->restart_area_length)) { 177*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 178*5218cd10SNamjae Jeon "LogFile restart area is out of bounds of the system page size specified by the restart page header and/or the specified restart area length is inconsistent."); 1791e9ea7e0SNamjae Jeon return false; 1801e9ea7e0SNamjae Jeon } 1811e9ea7e0SNamjae Jeon /* 1821e9ea7e0SNamjae Jeon * The ra->client_free_list and ra->client_in_use_list must be either 1831e9ea7e0SNamjae Jeon * LOGFILE_NO_CLIENT or less than ra->log_clients or they are 1841e9ea7e0SNamjae Jeon * overflowing the client array. 1851e9ea7e0SNamjae Jeon */ 1861e9ea7e0SNamjae Jeon if ((ra->client_free_list != LOGFILE_NO_CLIENT && 1871e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_free_list) >= 1881e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_clients)) || 1891e9ea7e0SNamjae Jeon (ra->client_in_use_list != LOGFILE_NO_CLIENT && 1901e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_in_use_list) >= 1911e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_clients))) { 192*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 193*5218cd10SNamjae Jeon "LogFile restart area specifies overflowing client free and/or in use lists."); 1941e9ea7e0SNamjae Jeon return false; 1951e9ea7e0SNamjae Jeon } 1961e9ea7e0SNamjae Jeon /* 1971e9ea7e0SNamjae Jeon * Check ra->seq_number_bits against ra->file_size for consistency. 1981e9ea7e0SNamjae Jeon * We cannot just use ffs() because the file size is not a power of 2. 1991e9ea7e0SNamjae Jeon */ 200*5218cd10SNamjae Jeon file_size = le64_to_cpu(ra->file_size); 2011e9ea7e0SNamjae Jeon fs_bits = 0; 2021e9ea7e0SNamjae Jeon while (file_size) { 2031e9ea7e0SNamjae Jeon file_size >>= 1; 2041e9ea7e0SNamjae Jeon fs_bits++; 2051e9ea7e0SNamjae Jeon } 2061e9ea7e0SNamjae Jeon if (le32_to_cpu(ra->seq_number_bits) != 67 - fs_bits) { 207*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 208*5218cd10SNamjae Jeon "LogFile restart area specifies inconsistent sequence number bits."); 2091e9ea7e0SNamjae Jeon return false; 2101e9ea7e0SNamjae Jeon } 2111e9ea7e0SNamjae Jeon /* The log record header length must be a multiple of 8. */ 2121e9ea7e0SNamjae Jeon if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) != 2131e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_record_header_length)) { 214*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 215*5218cd10SNamjae Jeon "LogFile restart area specifies inconsistent log record header length."); 2161e9ea7e0SNamjae Jeon return false; 2171e9ea7e0SNamjae Jeon } 2181e9ea7e0SNamjae Jeon /* Dito for the log page data offset. */ 2191e9ea7e0SNamjae Jeon if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) != 2201e9ea7e0SNamjae Jeon le16_to_cpu(ra->log_page_data_offset)) { 221*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 222*5218cd10SNamjae Jeon "LogFile restart area specifies inconsistent log page data offset."); 2231e9ea7e0SNamjae Jeon return false; 2241e9ea7e0SNamjae Jeon } 2251e9ea7e0SNamjae Jeon ntfs_debug("Done."); 2261e9ea7e0SNamjae Jeon return true; 2271e9ea7e0SNamjae Jeon } 2281e9ea7e0SNamjae Jeon 229*5218cd10SNamjae Jeon /* 2301e9ea7e0SNamjae Jeon * ntfs_check_log_client_array - check the log client array for consistency 231*5218cd10SNamjae Jeon * @vi: LogFile inode to which the restart page belongs 2321e9ea7e0SNamjae Jeon * @rp: restart page whose log client array to check 2331e9ea7e0SNamjae Jeon * 2341e9ea7e0SNamjae Jeon * Check the log client array of the restart page @rp for consistency and 2351e9ea7e0SNamjae Jeon * return 'true' if it is consistent and 'false' otherwise. 2361e9ea7e0SNamjae Jeon * 2371e9ea7e0SNamjae Jeon * This function assumes that the restart page header and the restart area have 2381e9ea7e0SNamjae Jeon * already been consistency checked. 2391e9ea7e0SNamjae Jeon * 2401e9ea7e0SNamjae Jeon * Unlike ntfs_check_restart_page_header() and ntfs_check_restart_area(), this 2411e9ea7e0SNamjae Jeon * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full 2421e9ea7e0SNamjae Jeon * restart page and the page must be multi sector transfer deprotected. 2431e9ea7e0SNamjae Jeon */ 2441e9ea7e0SNamjae Jeon static bool ntfs_check_log_client_array(struct inode *vi, 245*5218cd10SNamjae Jeon struct restart_page_header *rp) 2461e9ea7e0SNamjae Jeon { 247*5218cd10SNamjae Jeon struct restart_area *ra; 248*5218cd10SNamjae Jeon struct log_client_record *ca, *cr; 2491e9ea7e0SNamjae Jeon u16 nr_clients, idx; 2501e9ea7e0SNamjae Jeon bool in_free_list, idx_is_first; 2511e9ea7e0SNamjae Jeon 2521e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 253*5218cd10SNamjae Jeon ra = (struct restart_area *)((u8 *)rp + le16_to_cpu(rp->restart_area_offset)); 254*5218cd10SNamjae Jeon ca = (struct log_client_record *)((u8 *)ra + 2551e9ea7e0SNamjae Jeon le16_to_cpu(ra->client_array_offset)); 2561e9ea7e0SNamjae Jeon /* 2571e9ea7e0SNamjae Jeon * Check the ra->client_free_list first and then check the 2581e9ea7e0SNamjae Jeon * ra->client_in_use_list. Check each of the log client records in 2591e9ea7e0SNamjae Jeon * each of the lists and check that the array does not overflow the 2601e9ea7e0SNamjae Jeon * ra->log_clients value. Also keep track of the number of records 2611e9ea7e0SNamjae Jeon * visited as there cannot be more than ra->log_clients records and 2621e9ea7e0SNamjae Jeon * that way we detect eventual loops in within a list. 2631e9ea7e0SNamjae Jeon */ 2641e9ea7e0SNamjae Jeon nr_clients = le16_to_cpu(ra->log_clients); 2651e9ea7e0SNamjae Jeon idx = le16_to_cpu(ra->client_free_list); 2661e9ea7e0SNamjae Jeon in_free_list = true; 2671e9ea7e0SNamjae Jeon check_list: 2681e9ea7e0SNamjae Jeon for (idx_is_first = true; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--, 2691e9ea7e0SNamjae Jeon idx = le16_to_cpu(cr->next_client)) { 2701e9ea7e0SNamjae Jeon if (!nr_clients || idx >= le16_to_cpu(ra->log_clients)) 2711e9ea7e0SNamjae Jeon goto err_out; 2721e9ea7e0SNamjae Jeon /* Set @cr to the current log client record. */ 2731e9ea7e0SNamjae Jeon cr = ca + idx; 2741e9ea7e0SNamjae Jeon /* The first log client record must not have a prev_client. */ 2751e9ea7e0SNamjae Jeon if (idx_is_first) { 2761e9ea7e0SNamjae Jeon if (cr->prev_client != LOGFILE_NO_CLIENT) 2771e9ea7e0SNamjae Jeon goto err_out; 2781e9ea7e0SNamjae Jeon idx_is_first = false; 2791e9ea7e0SNamjae Jeon } 2801e9ea7e0SNamjae Jeon } 2811e9ea7e0SNamjae Jeon /* Switch to and check the in use list if we just did the free list. */ 2821e9ea7e0SNamjae Jeon if (in_free_list) { 2831e9ea7e0SNamjae Jeon in_free_list = false; 2841e9ea7e0SNamjae Jeon idx = le16_to_cpu(ra->client_in_use_list); 2851e9ea7e0SNamjae Jeon goto check_list; 2861e9ea7e0SNamjae Jeon } 2871e9ea7e0SNamjae Jeon ntfs_debug("Done."); 2881e9ea7e0SNamjae Jeon return true; 2891e9ea7e0SNamjae Jeon err_out: 290*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, "LogFile log client array is corrupt."); 2911e9ea7e0SNamjae Jeon return false; 2921e9ea7e0SNamjae Jeon } 2931e9ea7e0SNamjae Jeon 294*5218cd10SNamjae Jeon /* 2951e9ea7e0SNamjae Jeon * ntfs_check_and_load_restart_page - check the restart page for consistency 296*5218cd10SNamjae Jeon * @vi: LogFile inode to which the restart page belongs 2971e9ea7e0SNamjae Jeon * @rp: restart page to check 2981e9ea7e0SNamjae Jeon * @pos: position in @vi at which the restart page resides 2991e9ea7e0SNamjae Jeon * @wrp: [OUT] copy of the multi sector transfer deprotected restart page 3001e9ea7e0SNamjae Jeon * @lsn: [OUT] set to the current logfile lsn on success 3011e9ea7e0SNamjae Jeon * 3021e9ea7e0SNamjae Jeon * Check the restart page @rp for consistency and return 0 if it is consistent 3031e9ea7e0SNamjae Jeon * and -errno otherwise. The restart page may have been modified by chkdsk in 3041e9ea7e0SNamjae Jeon * which case its magic is CHKD instead of RSTR. 3051e9ea7e0SNamjae Jeon * 3061e9ea7e0SNamjae Jeon * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not 3071e9ea7e0SNamjae Jeon * require the full restart page. 3081e9ea7e0SNamjae Jeon * 3091e9ea7e0SNamjae Jeon * If @wrp is not NULL, on success, *@wrp will point to a buffer containing a 3101e9ea7e0SNamjae Jeon * copy of the complete multi sector transfer deprotected page. On failure, 3111e9ea7e0SNamjae Jeon * *@wrp is undefined. 3121e9ea7e0SNamjae Jeon * 3131e9ea7e0SNamjae Jeon * Simillarly, if @lsn is not NULL, on success *@lsn will be set to the current 3141e9ea7e0SNamjae Jeon * logfile lsn according to this restart page. On failure, *@lsn is undefined. 3151e9ea7e0SNamjae Jeon * 3161e9ea7e0SNamjae Jeon * The following error codes are defined: 3171e9ea7e0SNamjae Jeon * -EINVAL - The restart page is inconsistent. 3181e9ea7e0SNamjae Jeon * -ENOMEM - Not enough memory to load the restart page. 319*5218cd10SNamjae Jeon * -EIO - Failed to reading from LogFile. 3201e9ea7e0SNamjae Jeon */ 3211e9ea7e0SNamjae Jeon static int ntfs_check_and_load_restart_page(struct inode *vi, 322*5218cd10SNamjae Jeon struct restart_page_header *rp, s64 pos, struct restart_page_header **wrp, 323*5218cd10SNamjae Jeon s64 *lsn) 3241e9ea7e0SNamjae Jeon { 325*5218cd10SNamjae Jeon struct restart_area *ra; 326*5218cd10SNamjae Jeon struct restart_page_header *trp; 3271e9ea7e0SNamjae Jeon int size, err; 3281e9ea7e0SNamjae Jeon 3291e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 3301e9ea7e0SNamjae Jeon /* Check the restart page header for consistency. */ 3311e9ea7e0SNamjae Jeon if (!ntfs_check_restart_page_header(vi, rp, pos)) { 3321e9ea7e0SNamjae Jeon /* Error output already done inside the function. */ 3331e9ea7e0SNamjae Jeon return -EINVAL; 3341e9ea7e0SNamjae Jeon } 3351e9ea7e0SNamjae Jeon /* Check the restart area for consistency. */ 3361e9ea7e0SNamjae Jeon if (!ntfs_check_restart_area(vi, rp)) { 3371e9ea7e0SNamjae Jeon /* Error output already done inside the function. */ 3381e9ea7e0SNamjae Jeon return -EINVAL; 3391e9ea7e0SNamjae Jeon } 340*5218cd10SNamjae Jeon ra = (struct restart_area *)((u8 *)rp + le16_to_cpu(rp->restart_area_offset)); 3411e9ea7e0SNamjae Jeon /* 3421e9ea7e0SNamjae Jeon * Allocate a buffer to store the whole restart page so we can multi 3431e9ea7e0SNamjae Jeon * sector transfer deprotect it. 3441e9ea7e0SNamjae Jeon */ 345*5218cd10SNamjae Jeon trp = kvzalloc(le32_to_cpu(rp->system_page_size), GFP_NOFS); 3461e9ea7e0SNamjae Jeon if (!trp) { 347*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, "Failed to allocate memory for LogFile restart page buffer."); 3481e9ea7e0SNamjae Jeon return -ENOMEM; 3491e9ea7e0SNamjae Jeon } 3501e9ea7e0SNamjae Jeon /* 3511e9ea7e0SNamjae Jeon * Read the whole of the restart page into the buffer. If it fits 3521e9ea7e0SNamjae Jeon * completely inside @rp, just copy it from there. Otherwise map all 3531e9ea7e0SNamjae Jeon * the required pages and copy the data from them. 3541e9ea7e0SNamjae Jeon */ 3551e9ea7e0SNamjae Jeon size = PAGE_SIZE - (pos & ~PAGE_MASK); 3561e9ea7e0SNamjae Jeon if (size >= le32_to_cpu(rp->system_page_size)) { 3571e9ea7e0SNamjae Jeon memcpy(trp, rp, le32_to_cpu(rp->system_page_size)); 3581e9ea7e0SNamjae Jeon } else { 3591e9ea7e0SNamjae Jeon pgoff_t idx; 360*5218cd10SNamjae Jeon struct folio *folio; 3611e9ea7e0SNamjae Jeon int have_read, to_read; 3621e9ea7e0SNamjae Jeon 3631e9ea7e0SNamjae Jeon /* First copy what we already have in @rp. */ 3641e9ea7e0SNamjae Jeon memcpy(trp, rp, size); 3651e9ea7e0SNamjae Jeon /* Copy the remaining data one page at a time. */ 3661e9ea7e0SNamjae Jeon have_read = size; 3671e9ea7e0SNamjae Jeon to_read = le32_to_cpu(rp->system_page_size) - size; 3681e9ea7e0SNamjae Jeon idx = (pos + size) >> PAGE_SHIFT; 3691e9ea7e0SNamjae Jeon do { 370*5218cd10SNamjae Jeon folio = read_mapping_folio(vi->i_mapping, idx, NULL); 371*5218cd10SNamjae Jeon if (IS_ERR(folio)) { 372*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, "Error mapping LogFile page (index %lu).", 373*5218cd10SNamjae Jeon idx); 374*5218cd10SNamjae Jeon err = PTR_ERR(folio); 3751e9ea7e0SNamjae Jeon if (err != -EIO && err != -ENOMEM) 3761e9ea7e0SNamjae Jeon err = -EIO; 3771e9ea7e0SNamjae Jeon goto err_out; 3781e9ea7e0SNamjae Jeon } 3791e9ea7e0SNamjae Jeon size = min_t(int, to_read, PAGE_SIZE); 380*5218cd10SNamjae Jeon memcpy((u8 *)trp + have_read, folio_address(folio), size); 381*5218cd10SNamjae Jeon folio_put(folio); 3821e9ea7e0SNamjae Jeon have_read += size; 3831e9ea7e0SNamjae Jeon to_read -= size; 3841e9ea7e0SNamjae Jeon idx++; 3851e9ea7e0SNamjae Jeon } while (to_read > 0); 3861e9ea7e0SNamjae Jeon } 3871e9ea7e0SNamjae Jeon /* 3881e9ea7e0SNamjae Jeon * Perform the multi sector transfer deprotection on the buffer if the 3891e9ea7e0SNamjae Jeon * restart page is protected. 3901e9ea7e0SNamjae Jeon */ 391*5218cd10SNamjae Jeon if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) && 392*5218cd10SNamjae Jeon post_read_mst_fixup((struct ntfs_record *)trp, le32_to_cpu(rp->system_page_size))) { 3931e9ea7e0SNamjae Jeon /* 394*5218cd10SNamjae Jeon * A multi sector transfer error was detected. We only need to 3951e9ea7e0SNamjae Jeon * abort if the restart page contents exceed the multi sector 3961e9ea7e0SNamjae Jeon * transfer fixup of the first sector. 3971e9ea7e0SNamjae Jeon */ 3981e9ea7e0SNamjae Jeon if (le16_to_cpu(rp->restart_area_offset) + 3991e9ea7e0SNamjae Jeon le16_to_cpu(ra->restart_area_length) > 4001e9ea7e0SNamjae Jeon NTFS_BLOCK_SIZE - sizeof(u16)) { 401*5218cd10SNamjae Jeon ntfs_error(vi->i_sb, 402*5218cd10SNamjae Jeon "Multi sector transfer error detected in LogFile restart page."); 4031e9ea7e0SNamjae Jeon err = -EINVAL; 4041e9ea7e0SNamjae Jeon goto err_out; 4051e9ea7e0SNamjae Jeon } 4061e9ea7e0SNamjae Jeon } 4071e9ea7e0SNamjae Jeon /* 4081e9ea7e0SNamjae Jeon * If the restart page is modified by chkdsk or there are no active 4091e9ea7e0SNamjae Jeon * logfile clients, the logfile is consistent. Otherwise, need to 4101e9ea7e0SNamjae Jeon * check the log client records for consistency, too. 4111e9ea7e0SNamjae Jeon */ 4121e9ea7e0SNamjae Jeon err = 0; 4131e9ea7e0SNamjae Jeon if (ntfs_is_rstr_record(rp->magic) && 4141e9ea7e0SNamjae Jeon ra->client_in_use_list != LOGFILE_NO_CLIENT) { 4151e9ea7e0SNamjae Jeon if (!ntfs_check_log_client_array(vi, trp)) { 4161e9ea7e0SNamjae Jeon err = -EINVAL; 4171e9ea7e0SNamjae Jeon goto err_out; 4181e9ea7e0SNamjae Jeon } 4191e9ea7e0SNamjae Jeon } 4201e9ea7e0SNamjae Jeon if (lsn) { 4211e9ea7e0SNamjae Jeon if (ntfs_is_rstr_record(rp->magic)) 422*5218cd10SNamjae Jeon *lsn = le64_to_cpu(ra->current_lsn); 4231e9ea7e0SNamjae Jeon else /* if (ntfs_is_chkd_record(rp->magic)) */ 424*5218cd10SNamjae Jeon *lsn = le64_to_cpu(rp->chkdsk_lsn); 4251e9ea7e0SNamjae Jeon } 4261e9ea7e0SNamjae Jeon ntfs_debug("Done."); 4271e9ea7e0SNamjae Jeon if (wrp) 4281e9ea7e0SNamjae Jeon *wrp = trp; 4291e9ea7e0SNamjae Jeon else { 4301e9ea7e0SNamjae Jeon err_out: 431*5218cd10SNamjae Jeon kvfree(trp); 4321e9ea7e0SNamjae Jeon } 4331e9ea7e0SNamjae Jeon return err; 4341e9ea7e0SNamjae Jeon } 4351e9ea7e0SNamjae Jeon 436*5218cd10SNamjae Jeon /* 4371e9ea7e0SNamjae Jeon * ntfs_check_logfile - check the journal for consistency 438*5218cd10SNamjae Jeon * @log_vi: struct inode of loaded journal LogFile to check 4391e9ea7e0SNamjae Jeon * @rp: [OUT] on success this is a copy of the current restart page 4401e9ea7e0SNamjae Jeon * 441*5218cd10SNamjae Jeon * Check the LogFile journal for consistency and return 'true' if it is 4421e9ea7e0SNamjae Jeon * consistent and 'false' if not. On success, the current restart page is 443*5218cd10SNamjae Jeon * returned in *@rp. Caller must call kvfree(*@rp) when finished with it. 4441e9ea7e0SNamjae Jeon * 4451e9ea7e0SNamjae Jeon * At present we only check the two restart pages and ignore the log record 4461e9ea7e0SNamjae Jeon * pages. 4471e9ea7e0SNamjae Jeon * 448*5218cd10SNamjae Jeon * Note that the MstProtected flag is not set on the LogFile inode and hence 4491e9ea7e0SNamjae Jeon * when reading pages they are not deprotected. This is because we do not know 450*5218cd10SNamjae Jeon * if the LogFile was created on a system with a different page size to ours 4511e9ea7e0SNamjae Jeon * yet and mst deprotection would fail if our page size is smaller. 4521e9ea7e0SNamjae Jeon */ 453*5218cd10SNamjae Jeon bool ntfs_check_logfile(struct inode *log_vi, struct restart_page_header **rp) 4541e9ea7e0SNamjae Jeon { 4551e9ea7e0SNamjae Jeon s64 size, pos; 456*5218cd10SNamjae Jeon s64 rstr1_lsn, rstr2_lsn; 457*5218cd10SNamjae Jeon struct ntfs_volume *vol = NTFS_SB(log_vi->i_sb); 4581e9ea7e0SNamjae Jeon struct address_space *mapping = log_vi->i_mapping; 459*5218cd10SNamjae Jeon struct folio *folio = NULL; 4601e9ea7e0SNamjae Jeon u8 *kaddr = NULL; 461*5218cd10SNamjae Jeon struct restart_page_header *rstr1_ph = NULL; 462*5218cd10SNamjae Jeon struct restart_page_header *rstr2_ph = NULL; 4631e9ea7e0SNamjae Jeon int log_page_size, err; 4641e9ea7e0SNamjae Jeon bool logfile_is_empty = true; 4651e9ea7e0SNamjae Jeon u8 log_page_bits; 4661e9ea7e0SNamjae Jeon 4671e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 468*5218cd10SNamjae Jeon /* An empty LogFile must have been clean before it got emptied. */ 4691e9ea7e0SNamjae Jeon if (NVolLogFileEmpty(vol)) 4701e9ea7e0SNamjae Jeon goto is_empty; 4711e9ea7e0SNamjae Jeon size = i_size_read(log_vi); 4721e9ea7e0SNamjae Jeon /* Make sure the file doesn't exceed the maximum allowed size. */ 4731e9ea7e0SNamjae Jeon if (size > MaxLogFileSize) 4741e9ea7e0SNamjae Jeon size = MaxLogFileSize; 4751e9ea7e0SNamjae Jeon /* 4761e9ea7e0SNamjae Jeon * Truncate size to a multiple of the page cache size or the default 4771e9ea7e0SNamjae Jeon * log page size if the page cache size is between the default log page 4781e9ea7e0SNamjae Jeon * log page size if the page cache size is between the default log page 4791e9ea7e0SNamjae Jeon * size and twice that. 4801e9ea7e0SNamjae Jeon */ 481*5218cd10SNamjae Jeon if (DefaultLogPageSize <= PAGE_SIZE && 482*5218cd10SNamjae Jeon DefaultLogPageSize * 2 <= PAGE_SIZE) 4831e9ea7e0SNamjae Jeon log_page_size = DefaultLogPageSize; 4841e9ea7e0SNamjae Jeon else 4851e9ea7e0SNamjae Jeon log_page_size = PAGE_SIZE; 4861e9ea7e0SNamjae Jeon /* 4871e9ea7e0SNamjae Jeon * Use ntfs_ffs() instead of ffs() to enable the compiler to 4881e9ea7e0SNamjae Jeon * optimize log_page_size and log_page_bits into constants. 4891e9ea7e0SNamjae Jeon */ 4901e9ea7e0SNamjae Jeon log_page_bits = ntfs_ffs(log_page_size) - 1; 4911e9ea7e0SNamjae Jeon size &= ~(s64)(log_page_size - 1); 4921e9ea7e0SNamjae Jeon /* 4931e9ea7e0SNamjae Jeon * Ensure the log file is big enough to store at least the two restart 4941e9ea7e0SNamjae Jeon * pages and the minimum number of log record pages. 4951e9ea7e0SNamjae Jeon */ 4961e9ea7e0SNamjae Jeon if (size < log_page_size * 2 || (size - log_page_size * 2) >> 4971e9ea7e0SNamjae Jeon log_page_bits < MinLogRecordPages) { 498*5218cd10SNamjae Jeon ntfs_error(vol->sb, "LogFile is too small."); 4991e9ea7e0SNamjae Jeon return false; 5001e9ea7e0SNamjae Jeon } 5011e9ea7e0SNamjae Jeon /* 5021e9ea7e0SNamjae Jeon * Read through the file looking for a restart page. Since the restart 5031e9ea7e0SNamjae Jeon * page header is at the beginning of a page we only need to search at 5041e9ea7e0SNamjae Jeon * what could be the beginning of a page (for each page size) rather 5051e9ea7e0SNamjae Jeon * than scanning the whole file byte by byte. If all potential places 5061e9ea7e0SNamjae Jeon * contain empty and uninitialzed records, the log file can be assumed 5071e9ea7e0SNamjae Jeon * to be empty. 5081e9ea7e0SNamjae Jeon */ 5091e9ea7e0SNamjae Jeon for (pos = 0; pos < size; pos <<= 1) { 5101e9ea7e0SNamjae Jeon pgoff_t idx = pos >> PAGE_SHIFT; 511*5218cd10SNamjae Jeon 512*5218cd10SNamjae Jeon if (!folio || folio->index != idx) { 513*5218cd10SNamjae Jeon if (folio) { 514*5218cd10SNamjae Jeon kunmap_local(kaddr); 515*5218cd10SNamjae Jeon folio_put(folio); 516*5218cd10SNamjae Jeon } 517*5218cd10SNamjae Jeon folio = read_mapping_folio(mapping, idx, NULL); 518*5218cd10SNamjae Jeon if (IS_ERR(folio)) { 519*5218cd10SNamjae Jeon ntfs_error(vol->sb, "Error mapping LogFile page (index %lu).", 520*5218cd10SNamjae Jeon idx); 5211e9ea7e0SNamjae Jeon goto err_out; 5221e9ea7e0SNamjae Jeon } 5231e9ea7e0SNamjae Jeon } 524*5218cd10SNamjae Jeon kaddr = (u8 *)kmap_local_folio(folio, 0) + (pos & ~PAGE_MASK); 5251e9ea7e0SNamjae Jeon /* 5261e9ea7e0SNamjae Jeon * A non-empty block means the logfile is not empty while an 5271e9ea7e0SNamjae Jeon * empty block after a non-empty block has been encountered 5281e9ea7e0SNamjae Jeon * means we are done. 5291e9ea7e0SNamjae Jeon */ 530*5218cd10SNamjae Jeon if (!ntfs_is_empty_recordp((__le32 *)kaddr)) 5311e9ea7e0SNamjae Jeon logfile_is_empty = false; 5321e9ea7e0SNamjae Jeon else if (!logfile_is_empty) 5331e9ea7e0SNamjae Jeon break; 5341e9ea7e0SNamjae Jeon /* 5351e9ea7e0SNamjae Jeon * A log record page means there cannot be a restart page after 5361e9ea7e0SNamjae Jeon * this so no need to continue searching. 5371e9ea7e0SNamjae Jeon */ 538*5218cd10SNamjae Jeon if (ntfs_is_rcrd_recordp((__le32 *)kaddr)) 5391e9ea7e0SNamjae Jeon break; 5401e9ea7e0SNamjae Jeon /* If not a (modified by chkdsk) restart page, continue. */ 541*5218cd10SNamjae Jeon if (!ntfs_is_rstr_recordp((__le32 *)kaddr) && 542*5218cd10SNamjae Jeon !ntfs_is_chkd_recordp((__le32 *)kaddr)) { 5431e9ea7e0SNamjae Jeon if (!pos) 5441e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 5451e9ea7e0SNamjae Jeon continue; 5461e9ea7e0SNamjae Jeon } 5471e9ea7e0SNamjae Jeon /* 5481e9ea7e0SNamjae Jeon * Check the (modified by chkdsk) restart page for consistency 5491e9ea7e0SNamjae Jeon * and get a copy of the complete multi sector transfer 5501e9ea7e0SNamjae Jeon * deprotected restart page. 5511e9ea7e0SNamjae Jeon */ 5521e9ea7e0SNamjae Jeon err = ntfs_check_and_load_restart_page(log_vi, 553*5218cd10SNamjae Jeon (struct restart_page_header *)kaddr, pos, 5541e9ea7e0SNamjae Jeon !rstr1_ph ? &rstr1_ph : &rstr2_ph, 5551e9ea7e0SNamjae Jeon !rstr1_ph ? &rstr1_lsn : &rstr2_lsn); 5561e9ea7e0SNamjae Jeon if (!err) { 5571e9ea7e0SNamjae Jeon /* 5581e9ea7e0SNamjae Jeon * If we have now found the first (modified by chkdsk) 5591e9ea7e0SNamjae Jeon * restart page, continue looking for the second one. 5601e9ea7e0SNamjae Jeon */ 5611e9ea7e0SNamjae Jeon if (!pos) { 5621e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 5631e9ea7e0SNamjae Jeon continue; 5641e9ea7e0SNamjae Jeon } 5651e9ea7e0SNamjae Jeon /* 5661e9ea7e0SNamjae Jeon * We have now found the second (modified by chkdsk) 5671e9ea7e0SNamjae Jeon * restart page, so we can stop looking. 5681e9ea7e0SNamjae Jeon */ 5691e9ea7e0SNamjae Jeon break; 5701e9ea7e0SNamjae Jeon } 5711e9ea7e0SNamjae Jeon /* 5721e9ea7e0SNamjae Jeon * Error output already done inside the function. Note, we do 5731e9ea7e0SNamjae Jeon * not abort if the restart page was invalid as we might still 5741e9ea7e0SNamjae Jeon * find a valid one further in the file. 5751e9ea7e0SNamjae Jeon */ 5761e9ea7e0SNamjae Jeon if (err != -EINVAL) { 577*5218cd10SNamjae Jeon kunmap_local(kaddr); 578*5218cd10SNamjae Jeon folio_put(folio); 5791e9ea7e0SNamjae Jeon goto err_out; 5801e9ea7e0SNamjae Jeon } 5811e9ea7e0SNamjae Jeon /* Continue looking. */ 5821e9ea7e0SNamjae Jeon if (!pos) 5831e9ea7e0SNamjae Jeon pos = NTFS_BLOCK_SIZE >> 1; 5841e9ea7e0SNamjae Jeon } 585*5218cd10SNamjae Jeon if (folio) { 586*5218cd10SNamjae Jeon kunmap_local(kaddr); 587*5218cd10SNamjae Jeon folio_put(folio); 588*5218cd10SNamjae Jeon } 5891e9ea7e0SNamjae Jeon if (logfile_is_empty) { 5901e9ea7e0SNamjae Jeon NVolSetLogFileEmpty(vol); 5911e9ea7e0SNamjae Jeon is_empty: 592*5218cd10SNamjae Jeon ntfs_debug("Done. (LogFile is empty.)"); 5931e9ea7e0SNamjae Jeon return true; 5941e9ea7e0SNamjae Jeon } 5951e9ea7e0SNamjae Jeon if (!rstr1_ph) { 596*5218cd10SNamjae Jeon ntfs_error(vol->sb, 597*5218cd10SNamjae Jeon "Did not find any restart pages in LogFile and it was not empty."); 5981e9ea7e0SNamjae Jeon return false; 5991e9ea7e0SNamjae Jeon } 6001e9ea7e0SNamjae Jeon /* If both restart pages were found, use the more recent one. */ 6011e9ea7e0SNamjae Jeon if (rstr2_ph) { 6021e9ea7e0SNamjae Jeon /* 6031e9ea7e0SNamjae Jeon * If the second restart area is more recent, switch to it. 6041e9ea7e0SNamjae Jeon * Otherwise just throw it away. 6051e9ea7e0SNamjae Jeon */ 6061e9ea7e0SNamjae Jeon if (rstr2_lsn > rstr1_lsn) { 607*5218cd10SNamjae Jeon ntfs_debug("Using second restart page as it is more recent."); 608*5218cd10SNamjae Jeon kvfree(rstr1_ph); 6091e9ea7e0SNamjae Jeon rstr1_ph = rstr2_ph; 6101e9ea7e0SNamjae Jeon /* rstr1_lsn = rstr2_lsn; */ 6111e9ea7e0SNamjae Jeon } else { 612*5218cd10SNamjae Jeon ntfs_debug("Using first restart page as it is more recent."); 613*5218cd10SNamjae Jeon kvfree(rstr2_ph); 6141e9ea7e0SNamjae Jeon } 6151e9ea7e0SNamjae Jeon rstr2_ph = NULL; 6161e9ea7e0SNamjae Jeon } 6171e9ea7e0SNamjae Jeon /* All consistency checks passed. */ 6181e9ea7e0SNamjae Jeon if (rp) 6191e9ea7e0SNamjae Jeon *rp = rstr1_ph; 6201e9ea7e0SNamjae Jeon else 621*5218cd10SNamjae Jeon kvfree(rstr1_ph); 6221e9ea7e0SNamjae Jeon ntfs_debug("Done."); 6231e9ea7e0SNamjae Jeon return true; 6241e9ea7e0SNamjae Jeon err_out: 6251e9ea7e0SNamjae Jeon if (rstr1_ph) 626*5218cd10SNamjae Jeon kvfree(rstr1_ph); 6271e9ea7e0SNamjae Jeon return false; 6281e9ea7e0SNamjae Jeon } 6291e9ea7e0SNamjae Jeon 6301e9ea7e0SNamjae Jeon /* 631*5218cd10SNamjae Jeon * ntfs_empty_logfile - empty the contents of the LogFile journal 632*5218cd10SNamjae Jeon * @log_vi: struct inode of loaded journal LogFile to empty 6331e9ea7e0SNamjae Jeon * 634*5218cd10SNamjae Jeon * Empty the contents of the LogFile journal @log_vi and return 'true' on 6351e9ea7e0SNamjae Jeon * success and 'false' on error. 6361e9ea7e0SNamjae Jeon * 637*5218cd10SNamjae Jeon * This function assumes that the LogFile journal has already been consistency 6381e9ea7e0SNamjae Jeon * checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean() 639*5218cd10SNamjae Jeon * has been used to ensure that the LogFile is clean. 6401e9ea7e0SNamjae Jeon */ 6411e9ea7e0SNamjae Jeon bool ntfs_empty_logfile(struct inode *log_vi) 6421e9ea7e0SNamjae Jeon { 643*5218cd10SNamjae Jeon s64 vcn, end_vcn; 644*5218cd10SNamjae Jeon struct ntfs_inode *log_ni = NTFS_I(log_vi); 645*5218cd10SNamjae Jeon struct ntfs_volume *vol = log_ni->vol; 6461e9ea7e0SNamjae Jeon struct super_block *sb = vol->sb; 647*5218cd10SNamjae Jeon struct runlist_element *rl; 6481e9ea7e0SNamjae Jeon unsigned long flags; 6491e9ea7e0SNamjae Jeon int err; 6501e9ea7e0SNamjae Jeon bool should_wait = true; 651*5218cd10SNamjae Jeon char *empty_buf = NULL; 652*5218cd10SNamjae Jeon struct file_ra_state *ra = NULL; 6531e9ea7e0SNamjae Jeon 6541e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 6551e9ea7e0SNamjae Jeon if (NVolLogFileEmpty(vol)) { 6561e9ea7e0SNamjae Jeon ntfs_debug("Done."); 6571e9ea7e0SNamjae Jeon return true; 6581e9ea7e0SNamjae Jeon } 659*5218cd10SNamjae Jeon 6601e9ea7e0SNamjae Jeon /* 6611e9ea7e0SNamjae Jeon * We cannot use ntfs_attr_set() because we may be still in the middle 6621e9ea7e0SNamjae Jeon * of a mount operation. Thus we do the emptying by hand by first 663*5218cd10SNamjae Jeon * zapping the page cache pages for the LogFile/DATA attribute and 6641e9ea7e0SNamjae Jeon * then emptying each of the buffers in each of the clusters specified 6651e9ea7e0SNamjae Jeon * by the runlist by hand. 6661e9ea7e0SNamjae Jeon */ 6671e9ea7e0SNamjae Jeon vcn = 0; 6681e9ea7e0SNamjae Jeon read_lock_irqsave(&log_ni->size_lock, flags); 6691e9ea7e0SNamjae Jeon end_vcn = (log_ni->initialized_size + vol->cluster_size_mask) >> 6701e9ea7e0SNamjae Jeon vol->cluster_size_bits; 6711e9ea7e0SNamjae Jeon read_unlock_irqrestore(&log_ni->size_lock, flags); 6721e9ea7e0SNamjae Jeon truncate_inode_pages(log_vi->i_mapping, 0); 6731e9ea7e0SNamjae Jeon down_write(&log_ni->runlist.lock); 6741e9ea7e0SNamjae Jeon rl = log_ni->runlist.rl; 6751e9ea7e0SNamjae Jeon if (unlikely(!rl || vcn < rl->vcn || !rl->length)) { 6761e9ea7e0SNamjae Jeon map_vcn: 6771e9ea7e0SNamjae Jeon err = ntfs_map_runlist_nolock(log_ni, vcn, NULL); 6781e9ea7e0SNamjae Jeon if (err) { 679*5218cd10SNamjae Jeon ntfs_error(sb, "Failed to map runlist fragment (error %d).", -err); 6801e9ea7e0SNamjae Jeon goto err; 6811e9ea7e0SNamjae Jeon } 6821e9ea7e0SNamjae Jeon rl = log_ni->runlist.rl; 6831e9ea7e0SNamjae Jeon } 6841e9ea7e0SNamjae Jeon /* Seek to the runlist element containing @vcn. */ 6851e9ea7e0SNamjae Jeon while (rl->length && vcn >= rl[1].vcn) 6861e9ea7e0SNamjae Jeon rl++; 687*5218cd10SNamjae Jeon 688*5218cd10SNamjae Jeon err = -ENOMEM; 689*5218cd10SNamjae Jeon empty_buf = kvzalloc(vol->cluster_size, GFP_NOFS); 690*5218cd10SNamjae Jeon if (!empty_buf) 691*5218cd10SNamjae Jeon goto err; 692*5218cd10SNamjae Jeon 693*5218cd10SNamjae Jeon memset(empty_buf, 0xff, vol->cluster_size); 694*5218cd10SNamjae Jeon 695*5218cd10SNamjae Jeon ra = kzalloc(sizeof(*ra), GFP_NOFS); 696*5218cd10SNamjae Jeon if (!ra) 697*5218cd10SNamjae Jeon goto err; 698*5218cd10SNamjae Jeon 699*5218cd10SNamjae Jeon file_ra_state_init(ra, sb->s_bdev->bd_mapping); 7001e9ea7e0SNamjae Jeon do { 701*5218cd10SNamjae Jeon s64 lcn; 702*5218cd10SNamjae Jeon loff_t start, end; 7031e9ea7e0SNamjae Jeon s64 len; 7041e9ea7e0SNamjae Jeon 7051e9ea7e0SNamjae Jeon /* 7061e9ea7e0SNamjae Jeon * If this run is not mapped map it now and start again as the 7071e9ea7e0SNamjae Jeon * runlist will have been updated. 7081e9ea7e0SNamjae Jeon */ 7091e9ea7e0SNamjae Jeon lcn = rl->lcn; 7101e9ea7e0SNamjae Jeon if (unlikely(lcn == LCN_RL_NOT_MAPPED)) { 7111e9ea7e0SNamjae Jeon vcn = rl->vcn; 712*5218cd10SNamjae Jeon kvfree(empty_buf); 7131e9ea7e0SNamjae Jeon goto map_vcn; 7141e9ea7e0SNamjae Jeon } 7151e9ea7e0SNamjae Jeon /* If this run is not valid abort with an error. */ 7161e9ea7e0SNamjae Jeon if (unlikely(!rl->length || lcn < LCN_HOLE)) 7171e9ea7e0SNamjae Jeon goto rl_err; 7181e9ea7e0SNamjae Jeon /* Skip holes. */ 7191e9ea7e0SNamjae Jeon if (lcn == LCN_HOLE) 7201e9ea7e0SNamjae Jeon continue; 721*5218cd10SNamjae Jeon start = NTFS_CLU_TO_B(vol, lcn); 7221e9ea7e0SNamjae Jeon len = rl->length; 7231e9ea7e0SNamjae Jeon if (rl[1].vcn > end_vcn) 7241e9ea7e0SNamjae Jeon len = end_vcn - rl->vcn; 725*5218cd10SNamjae Jeon end = NTFS_CLU_TO_B(vol, lcn + len); 7261e9ea7e0SNamjae Jeon 727*5218cd10SNamjae Jeon page_cache_sync_readahead(sb->s_bdev->bd_mapping, ra, NULL, 728*5218cd10SNamjae Jeon start >> PAGE_SHIFT, (end - start) >> PAGE_SHIFT); 729*5218cd10SNamjae Jeon 730*5218cd10SNamjae Jeon do { 731*5218cd10SNamjae Jeon err = ntfs_bdev_write(sb, empty_buf, start, 732*5218cd10SNamjae Jeon vol->cluster_size); 733*5218cd10SNamjae Jeon if (err) { 734*5218cd10SNamjae Jeon ntfs_error(sb, "ntfs_dev_write failed, err : %d\n", err); 735*5218cd10SNamjae Jeon goto io_err; 736*5218cd10SNamjae Jeon } 737*5218cd10SNamjae Jeon 7381e9ea7e0SNamjae Jeon /* 7391e9ea7e0SNamjae Jeon * Submit the buffer and wait for i/o to complete but 7401e9ea7e0SNamjae Jeon * only for the first buffer so we do not miss really 7411e9ea7e0SNamjae Jeon * serious i/o errors. Once the first buffer has 7421e9ea7e0SNamjae Jeon * completed ignore errors afterwards as we can assume 7431e9ea7e0SNamjae Jeon * that if one buffer worked all of them will work. 7441e9ea7e0SNamjae Jeon */ 7451e9ea7e0SNamjae Jeon if (should_wait) { 7461e9ea7e0SNamjae Jeon should_wait = false; 747*5218cd10SNamjae Jeon err = filemap_write_and_wait_range(sb->s_bdev->bd_mapping, 748*5218cd10SNamjae Jeon start, start + vol->cluster_size); 749*5218cd10SNamjae Jeon if (err) 7501e9ea7e0SNamjae Jeon goto io_err; 7511e9ea7e0SNamjae Jeon } 752*5218cd10SNamjae Jeon start += vol->cluster_size; 753*5218cd10SNamjae Jeon } while (start < end); 7541e9ea7e0SNamjae Jeon } while ((++rl)->vcn < end_vcn); 7551e9ea7e0SNamjae Jeon up_write(&log_ni->runlist.lock); 756*5218cd10SNamjae Jeon kfree(empty_buf); 757*5218cd10SNamjae Jeon kfree(ra); 7581e9ea7e0SNamjae Jeon truncate_inode_pages(log_vi->i_mapping, 0); 7591e9ea7e0SNamjae Jeon /* Set the flag so we do not have to do it again on remount. */ 7601e9ea7e0SNamjae Jeon NVolSetLogFileEmpty(vol); 7611e9ea7e0SNamjae Jeon ntfs_debug("Done."); 7621e9ea7e0SNamjae Jeon return true; 7631e9ea7e0SNamjae Jeon io_err: 7641e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to write buffer. Unmount and run chkdsk."); 7651e9ea7e0SNamjae Jeon goto dirty_err; 7661e9ea7e0SNamjae Jeon rl_err: 7671e9ea7e0SNamjae Jeon ntfs_error(sb, "Runlist is corrupt. Unmount and run chkdsk."); 7681e9ea7e0SNamjae Jeon dirty_err: 7691e9ea7e0SNamjae Jeon NVolSetErrors(vol); 7701e9ea7e0SNamjae Jeon err = -EIO; 7711e9ea7e0SNamjae Jeon err: 772*5218cd10SNamjae Jeon kvfree(empty_buf); 773*5218cd10SNamjae Jeon kfree(ra); 7741e9ea7e0SNamjae Jeon up_write(&log_ni->runlist.lock); 775*5218cd10SNamjae Jeon ntfs_error(sb, "Failed to fill LogFile with 0xff bytes (error %d).", 7761e9ea7e0SNamjae Jeon -err); 7771e9ea7e0SNamjae Jeon return false; 7781e9ea7e0SNamjae Jeon } 779