24 #include <linux/types.h>
28 #include <linux/bitops.h>
51 static bool ntfs_check_restart_page_header(
struct inode *vi,
54 u32 logfile_system_page_size, logfile_log_page_size;
55 u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
63 logfile_system_page_size =
le32_to_cpu(rp->system_page_size);
64 logfile_log_page_size =
le32_to_cpu(rp->log_page_size);
67 logfile_system_page_size &
68 (logfile_system_page_size - 1) ||
77 if (pos && pos != logfile_system_page_size) {
79 "position in $LogFile.");
83 if (sle16_to_cpu(rp->major_ver) != 1 ||
84 sle16_to_cpu(rp->minor_ver) != 1) {
86 "supported. (This driver supports version "
87 "1.1 only.)", (
int)sle16_to_cpu(rp->major_ver),
88 (
int)sle16_to_cpu(rp->minor_ver));
103 "inconsistent update sequence array count.");
108 usa_end = usa_ofs + usa_count *
sizeof(
u16);
109 if (usa_ofs <
sizeof(RESTART_PAGE_HEADER) ||
112 "inconsistent update sequence array offset.");
123 if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
124 ra_ofs <
sizeof(RESTART_PAGE_HEADER)) ||
125 ra_ofs > logfile_system_page_size) {
127 "inconsistent restart area offset.");
136 "by chkdsk but a chkdsk LSN is specified.");
157 static bool ntfs_check_restart_area(
struct inode *vi, RESTART_PAGE_HEADER *rp)
161 u16 ra_ofs, ra_len, ca_ofs;
166 ra = (RESTART_AREA*)((
u8*)rp + ra_ofs);
172 if (ra_ofs +
offsetof(RESTART_AREA, file_size) >
175 "inconsistent file offset.");
186 if (((ca_ofs + 7) & ~7) != ca_ofs ||
189 "inconsistent client array offset.");
198 sizeof(LOG_CLIENT_RECORD);
199 if (ra_ofs + ra_len >
le32_to_cpu(rp->system_page_size) ||
204 "of the system page size specified by the "
205 "restart page header and/or the specified "
206 "restart area length is inconsistent.");
214 if ((ra->client_free_list != LOGFILE_NO_CLIENT &&
217 (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
221 "overflowing client free and/or in use lists.");
228 file_size = (
u64)sle64_to_cpu(ra->file_size);
234 if (
le32_to_cpu(ra->seq_number_bits) != 67 - fs_bits) {
236 "inconsistent sequence number bits.");
240 if (((
le16_to_cpu(ra->log_record_header_length) + 7) & ~7) !=
243 "inconsistent log record header length.");
247 if (((
le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) !=
250 "inconsistent log page data offset.");
272 static bool ntfs_check_log_client_array(
struct inode *vi,
273 RESTART_PAGE_HEADER *rp)
276 LOG_CLIENT_RECORD *
ca, *
cr;
278 bool in_free_list, idx_is_first;
281 ra = (RESTART_AREA*)((
u8*)rp +
le16_to_cpu(rp->restart_area_offset));
282 ca = (LOG_CLIENT_RECORD*)((
u8*)ra +
296 for (idx_is_first =
true; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
298 if (!nr_clients || idx >=
le16_to_cpu(ra->log_clients))
304 if (cr->prev_client != LOGFILE_NO_CLIENT)
306 idx_is_first =
false;
311 in_free_list =
false;
349 static int ntfs_check_and_load_restart_page(
struct inode *vi,
350 RESTART_PAGE_HEADER *rp,
s64 pos, RESTART_PAGE_HEADER **wrp,
354 RESTART_PAGE_HEADER *trp;
359 if (!ntfs_check_restart_page_header(vi, rp, pos)) {
364 if (!ntfs_check_restart_area(vi, rp)) {
368 ra = (RESTART_AREA*)((
u8*)rp +
le16_to_cpu(rp->restart_area_offset));
373 trp = ntfs_malloc_nofs(
le32_to_cpu(rp->system_page_size));
376 "restart page buffer.");
390 int have_read, to_read;
400 page = ntfs_map_page(vi->
i_mapping, idx);
403 "page (index %lu).", idx);
411 ntfs_unmap_page(page);
415 }
while (to_read > 0);
433 "detected in $LogFile restart page.");
445 ra->client_in_use_list != LOGFILE_NO_CLIENT) {
446 if (!ntfs_check_log_client_array(vi, trp)) {
453 *lsn = sle64_to_cpu(ra->current_lsn);
455 *lsn = sle64_to_cpu(rp->chkdsk_lsn);
484 bool ntfs_check_logfile(
struct inode *log_vi, RESTART_PAGE_HEADER **rp)
487 LSN rstr1_lsn, rstr2_lsn;
490 struct page *page =
NULL;
492 RESTART_PAGE_HEADER *rstr1_ph =
NULL;
493 RESTART_PAGE_HEADER *rstr2_ph =
NULL;
494 int log_page_size, log_page_mask,
err;
495 bool logfile_is_empty =
true;
500 if (NVolLogFileEmpty(vol))
502 size = i_size_read(log_vi);
504 if (size > MaxLogFileSize)
505 size = MaxLogFileSize;
513 DefaultLogPageSize * 2)
514 log_page_size = DefaultLogPageSize;
517 log_page_mask = log_page_size - 1;
522 log_page_bits = ntfs_ffs(log_page_size) - 1;
523 size &= ~(
s64)(log_page_size - 1);
528 if (size < log_page_size * 2 || (size - log_page_size * 2) >>
529 log_page_bits < MinLogRecordPages) {
541 for (pos = 0; pos <
size; pos <<= 1) {
543 if (!page || page->
index != idx) {
545 ntfs_unmap_page(page);
546 page = ntfs_map_page(mapping, idx);
549 "page (index %lu).", idx);
560 logfile_is_empty =
false;
561 else if (!logfile_is_empty)
581 err = ntfs_check_and_load_restart_page(log_vi,
582 (RESTART_PAGE_HEADER*)kaddr, pos,
583 !rstr1_ph ? &rstr1_ph : &rstr2_ph,
584 !rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
606 ntfs_unmap_page(page);
614 ntfs_unmap_page(page);
615 if (logfile_is_empty) {
616 NVolSetLogFileEmpty(vol);
623 ntfs_error(vol->
sb,
"Did not find any restart pages in "
624 "$LogFile and it was not empty.");
633 if (rstr2_lsn > rstr1_lsn) {
634 ntfs_debug(
"Using second restart page as it is more "
640 ntfs_debug(
"Using first restart page as it is more "
679 bool ntfs_is_logfile_clean(
struct inode *log_vi,
const RESTART_PAGE_HEADER *rp)
686 if (NVolLogFileEmpty(vol)) {
693 ntfs_error(vol->
sb,
"Restart page buffer is invalid. This is "
694 "probably a bug in that the $LogFile should "
695 "have been consistency checked before calling "
699 ra = (RESTART_AREA*)((
u8*)rp +
le16_to_cpu(rp->restart_area_offset));
705 if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
706 !(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
707 ntfs_debug(
"Done. $LogFile indicates a dirty shutdown.");
711 ntfs_debug(
"Done. $LogFile indicates a clean shutdown.");
726 bool ntfs_empty_logfile(
struct inode *log_vi)
736 bool should_wait =
true;
739 if (NVolLogFileEmpty(vol)) {
764 ntfs_error(sb,
"Failed to map runlist fragment (error "
796 if (rl[1].vcn > end_vcn)
797 len = end_vcn - rl->
vcn;
802 struct buffer_head *bh;
805 bh = sb_getblk(sb, block);
812 memset(bh->b_data, -1, block_size);
813 if (!buffer_uptodate(bh))
814 set_buffer_uptodate(bh);
815 if (buffer_dirty(bh))
816 clear_buffer_dirty(bh);
832 }
while (++block < end_block);
833 }
while ((++rl)->vcn < end_vcn);
845 NVolSetLogFileEmpty(vol);
849 ntfs_error(sb,
"Failed to write buffer. Unmount and run chkdsk.");
852 ntfs_error(sb,
"Runlist is corrupt. Unmount and run chkdsk.");
858 ntfs_error(sb,
"Failed to fill $LogFile with 0xff bytes (error %d).",