Skip to content

Commit 099ef9a

Browse files
fs/ntfs3: implement iomap-based file operations
This patch modifies the ntfs3 driver by replacing the buffer_head-based operations with the iomap ones. Implementation details: - Implements core iomap operations (ntfs_iomap_begin/end) for block mapping: Proper handling of resident attributes via IOMAP_INLINE. Support for sparse files through IOMAP_HOLE semantics. Correct unwritten extent handling for zeroing operations. - Replaces custom implementations with standardized iomap helpers: Converts buffered reads to use iomap_read_folio and iomap_readahead. Implements iomap_file_buffered_write for write operations. Uses iomap_dio_rw for direct I/O paths. Migrates zero range operations to iomap_zero_range. - Preserves special handling paths for compressed files - Implements proper EOF/valid data size management during writes Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent e37a75b commit 099ef9a

8 files changed

Lines changed: 600 additions & 789 deletions

File tree

fs/ntfs3/attrib.c

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
166166
continue;
167167
}
168168

169+
if (err == -ENOSPC && new_len && vcn - vcn0) {
170+
/* Keep already allocated clusters. */
171+
*alen = vcn - vcn0;
172+
return 0;
173+
}
174+
169175
if (err)
170176
goto out;
171177

@@ -886,7 +892,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
886892
* - new allocated clusters are zeroed via blkdev_issue_zeroout.
887893
*/
888894
int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
889-
CLST *len, bool *new, bool zero)
895+
CLST *len, bool *new, bool zero, void **res)
890896
{
891897
int err = 0;
892898
struct runs_tree *run = &ni->file.run;
@@ -903,6 +909,8 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
903909

904910
if (new)
905911
*new = false;
912+
if (res)
913+
*res = NULL;
906914

907915
/* Try to find in cache. */
908916
down_read(&ni->file.run_lock);
@@ -939,8 +947,15 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
939947
}
940948

941949
if (!attr_b->non_res) {
950+
u32 data_size = le32_to_cpu(attr_b->res.data_size);
942951
*lcn = RESIDENT_LCN;
943-
*len = le32_to_cpu(attr_b->res.data_size);
952+
*len = data_size;
953+
if (res && data_size) {
954+
*res = kmemdup(resident_data(attr_b), data_size,
955+
GFP_KERNEL);
956+
if (!*res)
957+
err = -ENOMEM;
958+
}
944959
goto out;
945960
}
946961

@@ -1028,7 +1043,8 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
10281043
to_alloc = ((vcn0 + clen + clst_per_frame - 1) & cmask) - vcn;
10291044
if (fr < clst_per_frame)
10301045
fr = clst_per_frame;
1031-
zero = true;
1046+
if (vcn != vcn0)
1047+
zero = true;
10321048

10331049
/* Check if 'vcn' and 'vcn0' in different attribute segments. */
10341050
if (vcn < svcn || evcn1 <= vcn) {
@@ -1244,33 +1260,6 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
12441260
goto out;
12451261
}
12461262

1247-
int attr_data_read_resident(struct ntfs_inode *ni, struct folio *folio)
1248-
{
1249-
u64 vbo;
1250-
struct ATTRIB *attr;
1251-
u32 data_size;
1252-
size_t len;
1253-
1254-
attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, NULL);
1255-
if (!attr)
1256-
return -EINVAL;
1257-
1258-
if (attr->non_res)
1259-
return E_NTFS_NONRESIDENT;
1260-
1261-
vbo = folio->index << PAGE_SHIFT;
1262-
data_size = le32_to_cpu(attr->res.data_size);
1263-
if (vbo > data_size)
1264-
len = 0;
1265-
else
1266-
len = min(data_size - vbo, folio_size(folio));
1267-
1268-
folio_fill_tail(folio, 0, resident_data(attr) + vbo, len);
1269-
folio_mark_uptodate(folio);
1270-
1271-
return 0;
1272-
}
1273-
12741263
int attr_data_write_resident(struct ntfs_inode *ni, struct folio *folio)
12751264
{
12761265
u64 vbo;
@@ -1287,7 +1276,7 @@ int attr_data_write_resident(struct ntfs_inode *ni, struct folio *folio)
12871276
return E_NTFS_NONRESIDENT;
12881277
}
12891278

1290-
vbo = folio->index << PAGE_SHIFT;
1279+
vbo = folio_pos(folio);
12911280
data_size = le32_to_cpu(attr->res.data_size);
12921281
if (vbo < data_size) {
12931282
char *data = resident_data(attr);
@@ -1360,21 +1349,20 @@ int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type,
13601349
int retry = 0;
13611350

13621351
for (vcn = from >> cluster_bits; vcn <= vcn_last; vcn += clen) {
1363-
if (!run_lookup_entry(run, vcn, &lcn, &clen, NULL)) {
1364-
if (retry != 0) { /* Next run_lookup_entry(vcn) also failed. */
1365-
err = -EINVAL;
1366-
break;
1367-
}
1368-
err = attr_load_runs_vcn(ni, type, name, name_len, run,
1369-
vcn);
1370-
if (err)
1371-
break;
1372-
1373-
clen = 0; /* Next run_lookup_entry(vcn) must be success. */
1374-
retry++;
1375-
}
1376-
else
1352+
if (run_lookup_entry(run, vcn, &lcn, &clen, NULL)) {
13771353
retry = 0;
1354+
continue;
1355+
}
1356+
if (retry) {
1357+
err = -EINVAL;
1358+
break;
1359+
}
1360+
err = attr_load_runs_vcn(ni, type, name, name_len, run, vcn);
1361+
if (err)
1362+
break;
1363+
1364+
clen = 0; /* Next run_lookup_entry(vcn) must be success. */
1365+
retry++;
13781366
}
13791367

13801368
return err;

0 commit comments

Comments
 (0)