Lines Matching +full:multi +full:- +full:word

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * logfile.c - NTFS kernel journal handling. Part of the Linux-NTFS project.
5 * Copyright (c) 2002-2007 Anton Altaparmakov
27 * ntfs_check_restart_page_header - check the page header for consistency
50 logfile_system_page_size = le32_to_cpu(rp->system_page_size); in ntfs_check_restart_page_header()
51 logfile_log_page_size = le32_to_cpu(rp->log_page_size); in ntfs_check_restart_page_header()
55 (logfile_system_page_size - 1) || in ntfs_check_restart_page_header()
57 ntfs_error(vi->i_sb, "$LogFile uses unsupported page size."); in ntfs_check_restart_page_header()
65 ntfs_error(vi->i_sb, "Found restart area in incorrect " in ntfs_check_restart_page_header()
70 if (sle16_to_cpu(rp->major_ver) != 1 || in ntfs_check_restart_page_header()
71 sle16_to_cpu(rp->minor_ver) != 1) { in ntfs_check_restart_page_header()
72 ntfs_error(vi->i_sb, "$LogFile version %i.%i is not " in ntfs_check_restart_page_header()
74 "1.1 only.)", (int)sle16_to_cpu(rp->major_ver), in ntfs_check_restart_page_header()
75 (int)sle16_to_cpu(rp->minor_ver)); in ntfs_check_restart_page_header()
82 if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { in ntfs_check_restart_page_header()
88 if (usa_count != le16_to_cpu(rp->usa_count)) { in ntfs_check_restart_page_header()
89 ntfs_error(vi->i_sb, "$LogFile restart page specifies " in ntfs_check_restart_page_header()
94 usa_ofs = le16_to_cpu(rp->usa_ofs); in ntfs_check_restart_page_header()
97 usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) { in ntfs_check_restart_page_header()
98 ntfs_error(vi->i_sb, "$LogFile restart page specifies " in ntfs_check_restart_page_header()
105 * - aligned to 8-byte boundary, in ntfs_check_restart_page_header()
106 * - after the update sequence array, and in ntfs_check_restart_page_header()
107 * - within the system page size. in ntfs_check_restart_page_header()
109 ra_ofs = le16_to_cpu(rp->restart_area_offset); in ntfs_check_restart_page_header()
113 ntfs_error(vi->i_sb, "$LogFile restart page specifies " in ntfs_check_restart_page_header()
121 if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) { in ntfs_check_restart_page_header()
122 ntfs_error(vi->i_sb, "$LogFile restart page is not modified " in ntfs_check_restart_page_header()
131 * ntfs_check_restart_area - check the restart area for consistency
152 ra_ofs = le16_to_cpu(rp->restart_area_offset); in ntfs_check_restart_area()
155 * Everything before ra->file_size must be before the first word in ntfs_check_restart_area()
157 * safe to access ra->client_array_offset. in ntfs_check_restart_area()
160 NTFS_BLOCK_SIZE - sizeof(u16)) { in ntfs_check_restart_area()
161 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
166 * Now that we can access ra->client_array_offset, make sure everything in ntfs_check_restart_area()
167 * up to the log client array is before the first word protected by an in ntfs_check_restart_area()
170 * aligned to an 8-byte boundary. in ntfs_check_restart_area()
172 ca_ofs = le16_to_cpu(ra->client_array_offset); in ntfs_check_restart_area()
174 ra_ofs + ca_ofs > NTFS_BLOCK_SIZE - sizeof(u16)) { in ntfs_check_restart_area()
175 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
181 * calculated manually and as specified by ra->restart_area_length. in ntfs_check_restart_area()
184 ra_len = ca_ofs + le16_to_cpu(ra->log_clients) * in ntfs_check_restart_area()
186 if (ra_ofs + ra_len > le32_to_cpu(rp->system_page_size) || in ntfs_check_restart_area()
187 ra_ofs + le16_to_cpu(ra->restart_area_length) > in ntfs_check_restart_area()
188 le32_to_cpu(rp->system_page_size) || in ntfs_check_restart_area()
189 ra_len > le16_to_cpu(ra->restart_area_length)) { in ntfs_check_restart_area()
190 ntfs_error(vi->i_sb, "$LogFile restart area is out of bounds " in ntfs_check_restart_area()
197 * The ra->client_free_list and ra->client_in_use_list must be either in ntfs_check_restart_area()
198 * LOGFILE_NO_CLIENT or less than ra->log_clients or they are in ntfs_check_restart_area()
201 if ((ra->client_free_list != LOGFILE_NO_CLIENT && in ntfs_check_restart_area()
202 le16_to_cpu(ra->client_free_list) >= in ntfs_check_restart_area()
203 le16_to_cpu(ra->log_clients)) || in ntfs_check_restart_area()
204 (ra->client_in_use_list != LOGFILE_NO_CLIENT && in ntfs_check_restart_area()
205 le16_to_cpu(ra->client_in_use_list) >= in ntfs_check_restart_area()
206 le16_to_cpu(ra->log_clients))) { in ntfs_check_restart_area()
207 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
212 * Check ra->seq_number_bits against ra->file_size for consistency. in ntfs_check_restart_area()
215 file_size = (u64)sle64_to_cpu(ra->file_size); in ntfs_check_restart_area()
221 if (le32_to_cpu(ra->seq_number_bits) != 67 - fs_bits) { in ntfs_check_restart_area()
222 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
227 if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) != in ntfs_check_restart_area()
228 le16_to_cpu(ra->log_record_header_length)) { in ntfs_check_restart_area()
229 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
234 if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) != in ntfs_check_restart_area()
235 le16_to_cpu(ra->log_page_data_offset)) { in ntfs_check_restart_area()
236 ntfs_error(vi->i_sb, "$LogFile restart area specifies " in ntfs_check_restart_area()
245 * ntfs_check_log_client_array - check the log client array for consistency
256 * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full
257 * restart page and the page must be multi sector transfer deprotected.
268 ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); in ntfs_check_log_client_array()
270 le16_to_cpu(ra->client_array_offset)); in ntfs_check_log_client_array()
272 * Check the ra->client_free_list first and then check the in ntfs_check_log_client_array()
273 * ra->client_in_use_list. Check each of the log client records in in ntfs_check_log_client_array()
275 * ra->log_clients value. Also keep track of the number of records in ntfs_check_log_client_array()
276 * visited as there cannot be more than ra->log_clients records and in ntfs_check_log_client_array()
279 nr_clients = le16_to_cpu(ra->log_clients); in ntfs_check_log_client_array()
280 idx = le16_to_cpu(ra->client_free_list); in ntfs_check_log_client_array()
283 for (idx_is_first = true; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--, in ntfs_check_log_client_array()
284 idx = le16_to_cpu(cr->next_client)) { in ntfs_check_log_client_array()
285 if (!nr_clients || idx >= le16_to_cpu(ra->log_clients)) in ntfs_check_log_client_array()
291 if (cr->prev_client != LOGFILE_NO_CLIENT) in ntfs_check_log_client_array()
299 idx = le16_to_cpu(ra->client_in_use_list); in ntfs_check_log_client_array()
305 ntfs_error(vi->i_sb, "$LogFile log client array is corrupt."); in ntfs_check_log_client_array()
310 * ntfs_check_and_load_restart_page - check the restart page for consistency
314 * @wrp: [OUT] copy of the multi sector transfer deprotected restart page
318 * and -errno otherwise. The restart page may have been modified by chkdsk in
325 * copy of the complete multi sector transfer deprotected page. On failure,
332 * -EINVAL - The restart page is inconsistent.
333 * -ENOMEM - Not enough memory to load the restart page.
334 * -EIO - Failed to reading from $LogFile.
348 return -EINVAL; in ntfs_check_and_load_restart_page()
353 return -EINVAL; in ntfs_check_and_load_restart_page()
355 ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); in ntfs_check_and_load_restart_page()
357 * Allocate a buffer to store the whole restart page so we can multi in ntfs_check_and_load_restart_page()
360 trp = ntfs_malloc_nofs(le32_to_cpu(rp->system_page_size)); in ntfs_check_and_load_restart_page()
362 ntfs_error(vi->i_sb, "Failed to allocate memory for $LogFile " in ntfs_check_and_load_restart_page()
364 return -ENOMEM; in ntfs_check_and_load_restart_page()
371 size = PAGE_SIZE - (pos & ~PAGE_MASK); in ntfs_check_and_load_restart_page()
372 if (size >= le32_to_cpu(rp->system_page_size)) { in ntfs_check_and_load_restart_page()
373 memcpy(trp, rp, le32_to_cpu(rp->system_page_size)); in ntfs_check_and_load_restart_page()
383 to_read = le32_to_cpu(rp->system_page_size) - size; in ntfs_check_and_load_restart_page()
387 page = ntfs_map_page(vi->i_mapping, idx); in ntfs_check_and_load_restart_page()
389 ntfs_error(vi->i_sb, "Error mapping $LogFile " in ntfs_check_and_load_restart_page()
392 if (err != -EIO && err != -ENOMEM) in ntfs_check_and_load_restart_page()
393 err = -EIO; in ntfs_check_and_load_restart_page()
400 to_read -= size; in ntfs_check_and_load_restart_page()
405 * Perform the multi sector transfer deprotection on the buffer if the in ntfs_check_and_load_restart_page()
408 if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) in ntfs_check_and_load_restart_page()
410 le32_to_cpu(rp->system_page_size))) { in ntfs_check_and_load_restart_page()
412 * A multi sector tranfer error was detected. We only need to in ntfs_check_and_load_restart_page()
413 * abort if the restart page contents exceed the multi sector in ntfs_check_and_load_restart_page()
416 if (le16_to_cpu(rp->restart_area_offset) + in ntfs_check_and_load_restart_page()
417 le16_to_cpu(ra->restart_area_length) > in ntfs_check_and_load_restart_page()
418 NTFS_BLOCK_SIZE - sizeof(u16)) { in ntfs_check_and_load_restart_page()
419 ntfs_error(vi->i_sb, "Multi sector transfer error " in ntfs_check_and_load_restart_page()
421 err = -EINVAL; in ntfs_check_and_load_restart_page()
431 if (ntfs_is_rstr_record(rp->magic) && in ntfs_check_and_load_restart_page()
432 ra->client_in_use_list != LOGFILE_NO_CLIENT) { in ntfs_check_and_load_restart_page()
434 err = -EINVAL; in ntfs_check_and_load_restart_page()
439 if (ntfs_is_rstr_record(rp->magic)) in ntfs_check_and_load_restart_page()
440 *lsn = sle64_to_cpu(ra->current_lsn); in ntfs_check_and_load_restart_page()
441 else /* if (ntfs_is_chkd_record(rp->magic)) */ in ntfs_check_and_load_restart_page()
442 *lsn = sle64_to_cpu(rp->chkdsk_lsn); in ntfs_check_and_load_restart_page()
455 * ntfs_check_logfile - check the journal for consistency
475 ntfs_volume *vol = NTFS_SB(log_vi->i_sb); in ntfs_check_logfile()
476 struct address_space *mapping = log_vi->i_mapping; in ntfs_check_logfile()
504 log_page_mask = log_page_size - 1; in ntfs_check_logfile()
509 log_page_bits = ntfs_ffs(log_page_size) - 1; in ntfs_check_logfile()
510 size &= ~(s64)(log_page_size - 1); in ntfs_check_logfile()
515 if (size < log_page_size * 2 || (size - log_page_size * 2) >> in ntfs_check_logfile()
517 ntfs_error(vol->sb, "$LogFile is too small."); in ntfs_check_logfile()
530 if (!page || page->index != idx) { in ntfs_check_logfile()
535 ntfs_error(vol->sb, "Error mapping $LogFile " in ntfs_check_logfile()
542 * A non-empty block means the logfile is not empty while an in ntfs_check_logfile()
543 * empty block after a non-empty block has been encountered in ntfs_check_logfile()
565 * and get a copy of the complete multi sector transfer in ntfs_check_logfile()
592 if (err != -EINVAL) { in ntfs_check_logfile()
610 ntfs_error(vol->sb, "Did not find any restart pages in " in ntfs_check_logfile()
647 * ntfs_is_logfile_clean - check in the journal if the volume is clean
658 * not have any pending, non-check-pointed i/o, i.e. they were completely idle
668 ntfs_volume *vol = NTFS_SB(log_vi->i_sb); in ntfs_is_logfile_clean()
678 if (!ntfs_is_rstr_record(rp->magic) && in ntfs_is_logfile_clean()
679 !ntfs_is_chkd_record(rp->magic)) { in ntfs_is_logfile_clean()
680 ntfs_error(vol->sb, "Restart page buffer is invalid. This is " in ntfs_is_logfile_clean()
686 ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); in ntfs_is_logfile_clean()
692 if (ra->client_in_use_list != LOGFILE_NO_CLIENT && in ntfs_is_logfile_clean()
693 !(ra->flags & RESTART_VOLUME_IS_CLEAN)) { in ntfs_is_logfile_clean()
703 * ntfs_empty_logfile - empty the contents of the $LogFile journal
717 ntfs_volume *vol = log_ni->vol; in ntfs_empty_logfile()
718 struct super_block *sb = vol->sb; in ntfs_empty_logfile()
737 block_size = sb->s_blocksize; in ntfs_empty_logfile()
738 block_size_bits = sb->s_blocksize_bits; in ntfs_empty_logfile()
740 read_lock_irqsave(&log_ni->size_lock, flags); in ntfs_empty_logfile()
741 end_vcn = (log_ni->initialized_size + vol->cluster_size_mask) >> in ntfs_empty_logfile()
742 vol->cluster_size_bits; in ntfs_empty_logfile()
743 read_unlock_irqrestore(&log_ni->size_lock, flags); in ntfs_empty_logfile()
744 truncate_inode_pages(log_vi->i_mapping, 0); in ntfs_empty_logfile()
745 down_write(&log_ni->runlist.lock); in ntfs_empty_logfile()
746 rl = log_ni->runlist.rl; in ntfs_empty_logfile()
747 if (unlikely(!rl || vcn < rl->vcn || !rl->length)) { in ntfs_empty_logfile()
752 "%d).", -err); in ntfs_empty_logfile()
755 rl = log_ni->runlist.rl; in ntfs_empty_logfile()
756 BUG_ON(!rl || vcn < rl->vcn || !rl->length); in ntfs_empty_logfile()
759 while (rl->length && vcn >= rl[1].vcn) in ntfs_empty_logfile()
770 lcn = rl->lcn; in ntfs_empty_logfile()
772 vcn = rl->vcn; in ntfs_empty_logfile()
776 if (unlikely(!rl->length || lcn < LCN_HOLE)) in ntfs_empty_logfile()
781 block = lcn << vol->cluster_size_bits >> block_size_bits; in ntfs_empty_logfile()
782 len = rl->length; in ntfs_empty_logfile()
784 len = end_vcn - rl->vcn; in ntfs_empty_logfile()
785 end_block = (lcn + len) << vol->cluster_size_bits >> in ntfs_empty_logfile()
796 bh->b_end_io = end_buffer_write_sync; in ntfs_empty_logfile()
799 memset(bh->b_data, -1, block_size); in ntfs_empty_logfile()
820 } while ((++rl)->vcn < end_vcn); in ntfs_empty_logfile()
821 up_write(&log_ni->runlist.lock); in ntfs_empty_logfile()
830 truncate_inode_pages(log_vi->i_mapping, 0); in ntfs_empty_logfile()
842 err = -EIO; in ntfs_empty_logfile()
844 up_write(&log_ni->runlist.lock); in ntfs_empty_logfile()
846 -err); in ntfs_empty_logfile()