Source
28
28
#include "attrib.h"
29
29
#include "aops.h"
30
30
#include "bitmap.h"
31
31
#include "debug.h"
32
32
#include "dir.h"
33
33
#include "lcnalloc.h"
34
34
#include "malloc.h"
35
35
#include "mft.h"
36
36
#include "ntfs.h"
37
37
38
+
#define MAX_BHS (PAGE_SIZE / NTFS_BLOCK_SIZE)
39
+
38
40
/**
39
41
* map_mft_record_page - map the page in which a specific mft record resides
40
42
* @ni: ntfs inode whose mft record page to map
41
43
*
42
44
* This maps the page in which the mft record of the ntfs inode @ni is situated
43
45
* and returns a pointer to the mft record within the mapped page.
44
46
*
45
47
* Return value needs to be checked with IS_ERR() and if that is true PTR_ERR()
46
48
* contains the negative error code returned.
47
49
*/
462
464
*
463
465
* TODO: If @sync is false, want to do truly asynchronous i/o, i.e. just
464
466
* schedule i/o via ->writepage or do it via kntfsd or whatever.
465
467
*/
466
468
int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
467
469
MFT_RECORD *m, int sync)
468
470
{
469
471
struct page *page;
470
472
unsigned int blocksize = vol->sb->s_blocksize;
471
473
int max_bhs = vol->mft_record_size / blocksize;
472
-
struct buffer_head *bhs[max_bhs];
474
+
struct buffer_head *bhs[MAX_BHS];
473
475
struct buffer_head *bh, *head;
474
476
u8 *kmirr;
475
477
runlist_element *rl;
476
478
unsigned int block_start, block_end, m_start, m_end, page_ofs;
477
479
int i_bhs, nr_bhs, err = 0;
478
480
unsigned char blocksize_bits = vol->sb->s_blocksize_bits;
479
481
480
482
ntfs_debug("Entering for inode 0x%lx.", mft_no);
481
483
BUG_ON(!max_bhs);
484
+
if (WARN_ON(max_bhs > MAX_BHS))
485
+
return -EINVAL;
482
486
if (unlikely(!vol->mftmirr_ino)) {
483
487
/* This could happen during umount... */
484
488
err = ntfs_sync_mft_mirror_umount(vol, mft_no, m);
485
489
if (likely(!err))
486
490
return err;
487
491
goto err_out;
488
492
}
489
493
/* Get the page containing the mirror copy of the mft record @m. */
490
494
page = ntfs_map_page(vol->mftmirr_ino->i_mapping, mft_no >>
491
495
(PAGE_SHIFT - vol->mft_record_size_bits));
667
671
* TODO: If @sync is false, want to do truly asynchronous i/o, i.e. just
668
672
* schedule i/o via ->writepage or do it via kntfsd or whatever.
669
673
*/
670
674
int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
671
675
{
672
676
ntfs_volume *vol = ni->vol;
673
677
struct page *page = ni->page;
674
678
unsigned int blocksize = vol->sb->s_blocksize;
675
679
unsigned char blocksize_bits = vol->sb->s_blocksize_bits;
676
680
int max_bhs = vol->mft_record_size / blocksize;
677
-
struct buffer_head *bhs[max_bhs];
681
+
struct buffer_head *bhs[MAX_BHS];
678
682
struct buffer_head *bh, *head;
679
683
runlist_element *rl;
680
684
unsigned int block_start, block_end, m_start, m_end;
681
685
int i_bhs, nr_bhs, err = 0;
682
686
683
687
ntfs_debug("Entering for inode 0x%lx.", ni->mft_no);
684
688
BUG_ON(NInoAttr(ni));
685
689
BUG_ON(!max_bhs);
686
690
BUG_ON(!PageLocked(page));
691
+
if (WARN_ON(max_bhs > MAX_BHS)) {
692
+
err = -EINVAL;
693
+
goto err_out;
694
+
}
687
695
/*
688
696
* If the ntfs_inode is clean no need to do anything. If it is dirty,
689
697
* mark it as clean now so that it can be redirtied later on if needed.
690
698
* There is no danger of races since the caller is holding the locks
691
699
* for the mft record @m and the page it is in.
692
700
*/
693
701
if (!NInoTestClearDirty(ni))
694
702
goto done;
695
703
bh = head = page_buffers(page);
696
704
BUG_ON(!bh);