1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * index.h - Defines for NTFS kernel index handling. Part of the Linux-NTFS
4*4882a593Smuzhiyun * project.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (c) 2004 Anton Altaparmakov
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #ifndef _LINUX_NTFS_INDEX_H
10*4882a593Smuzhiyun #define _LINUX_NTFS_INDEX_H
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/fs.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include "types.h"
15*4882a593Smuzhiyun #include "layout.h"
16*4882a593Smuzhiyun #include "inode.h"
17*4882a593Smuzhiyun #include "attrib.h"
18*4882a593Smuzhiyun #include "mft.h"
19*4882a593Smuzhiyun #include "aops.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /**
22*4882a593Smuzhiyun * @idx_ni: index inode containing the @entry described by this context
23*4882a593Smuzhiyun * @entry: index entry (points into @ir or @ia)
24*4882a593Smuzhiyun * @data: index entry data (points into @entry)
25*4882a593Smuzhiyun * @data_len: length in bytes of @data
26*4882a593Smuzhiyun * @is_in_root: 'true' if @entry is in @ir and 'false' if it is in @ia
27*4882a593Smuzhiyun * @ir: index root if @is_in_root and NULL otherwise
28*4882a593Smuzhiyun * @actx: attribute search context if @is_in_root and NULL otherwise
29*4882a593Smuzhiyun * @base_ni: base inode if @is_in_root and NULL otherwise
30*4882a593Smuzhiyun * @ia: index block if @is_in_root is 'false' and NULL otherwise
31*4882a593Smuzhiyun * @page: page if @is_in_root is 'false' and NULL otherwise
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * @idx_ni is the index inode this context belongs to.
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * @entry is the index entry described by this context. @data and @data_len
36*4882a593Smuzhiyun * are the index entry data and its length in bytes, respectively. @data
37*4882a593Smuzhiyun * simply points into @entry. This is probably what the user is interested in.
38*4882a593Smuzhiyun *
39*4882a593Smuzhiyun * If @is_in_root is 'true', @entry is in the index root attribute @ir described
40*4882a593Smuzhiyun * by the attribute search context @actx and the base inode @base_ni. @ia and
41*4882a593Smuzhiyun * @page are NULL in this case.
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * If @is_in_root is 'false', @entry is in the index allocation attribute and @ia
44*4882a593Smuzhiyun * and @page point to the index allocation block and the mapped, locked page it
45*4882a593Smuzhiyun * is in, respectively. @ir, @actx and @base_ni are NULL in this case.
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * To obtain a context call ntfs_index_ctx_get().
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * We use this context to allow ntfs_index_lookup() to return the found index
50*4882a593Smuzhiyun * @entry and its @data without having to allocate a buffer and copy the @entry
51*4882a593Smuzhiyun * and/or its @data into it.
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * When finished with the @entry and its @data, call ntfs_index_ctx_put() to
54*4882a593Smuzhiyun * free the context and other associated resources.
55*4882a593Smuzhiyun *
56*4882a593Smuzhiyun * If the index entry was modified, call flush_dcache_index_entry_page()
57*4882a593Smuzhiyun * immediately after the modification and either ntfs_index_entry_mark_dirty()
58*4882a593Smuzhiyun * or ntfs_index_entry_write() before the call to ntfs_index_ctx_put() to
59*4882a593Smuzhiyun * ensure that the changes are written to disk.
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun typedef struct {
62*4882a593Smuzhiyun ntfs_inode *idx_ni;
63*4882a593Smuzhiyun INDEX_ENTRY *entry;
64*4882a593Smuzhiyun void *data;
65*4882a593Smuzhiyun u16 data_len;
66*4882a593Smuzhiyun bool is_in_root;
67*4882a593Smuzhiyun INDEX_ROOT *ir;
68*4882a593Smuzhiyun ntfs_attr_search_ctx *actx;
69*4882a593Smuzhiyun ntfs_inode *base_ni;
70*4882a593Smuzhiyun INDEX_ALLOCATION *ia;
71*4882a593Smuzhiyun struct page *page;
72*4882a593Smuzhiyun } ntfs_index_context;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni);
75*4882a593Smuzhiyun extern void ntfs_index_ctx_put(ntfs_index_context *ictx);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun extern int ntfs_index_lookup(const void *key, const int key_len,
78*4882a593Smuzhiyun ntfs_index_context *ictx);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #ifdef NTFS_RW
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /**
83*4882a593Smuzhiyun * ntfs_index_entry_flush_dcache_page - flush_dcache_page() for index entries
84*4882a593Smuzhiyun * @ictx: ntfs index context describing the index entry
85*4882a593Smuzhiyun *
86*4882a593Smuzhiyun * Call flush_dcache_page() for the page in which an index entry resides.
87*4882a593Smuzhiyun *
88*4882a593Smuzhiyun * This must be called every time an index entry is modified, just after the
89*4882a593Smuzhiyun * modification.
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * If the index entry is in the index root attribute, simply flush the page
92*4882a593Smuzhiyun * containing the mft record containing the index root attribute.
93*4882a593Smuzhiyun *
94*4882a593Smuzhiyun * If the index entry is in an index block belonging to the index allocation
95*4882a593Smuzhiyun * attribute, simply flush the page cache page containing the index block.
96*4882a593Smuzhiyun */
ntfs_index_entry_flush_dcache_page(ntfs_index_context * ictx)97*4882a593Smuzhiyun static inline void ntfs_index_entry_flush_dcache_page(ntfs_index_context *ictx)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun if (ictx->is_in_root)
100*4882a593Smuzhiyun flush_dcache_mft_record_page(ictx->actx->ntfs_ino);
101*4882a593Smuzhiyun else
102*4882a593Smuzhiyun flush_dcache_page(ictx->page);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /**
106*4882a593Smuzhiyun * ntfs_index_entry_mark_dirty - mark an index entry dirty
107*4882a593Smuzhiyun * @ictx: ntfs index context describing the index entry
108*4882a593Smuzhiyun *
109*4882a593Smuzhiyun * Mark the index entry described by the index entry context @ictx dirty.
110*4882a593Smuzhiyun *
111*4882a593Smuzhiyun * If the index entry is in the index root attribute, simply mark the mft
112*4882a593Smuzhiyun * record containing the index root attribute dirty. This ensures the mft
113*4882a593Smuzhiyun * record, and hence the index root attribute, will be written out to disk
114*4882a593Smuzhiyun * later.
115*4882a593Smuzhiyun *
116*4882a593Smuzhiyun * If the index entry is in an index block belonging to the index allocation
117*4882a593Smuzhiyun * attribute, mark the buffers belonging to the index record as well as the
118*4882a593Smuzhiyun * page cache page the index block is in dirty. This automatically marks the
119*4882a593Smuzhiyun * VFS inode of the ntfs index inode to which the index entry belongs dirty,
120*4882a593Smuzhiyun * too (I_DIRTY_PAGES) and this in turn ensures the page buffers, and hence the
121*4882a593Smuzhiyun * dirty index block, will be written out to disk later.
122*4882a593Smuzhiyun */
ntfs_index_entry_mark_dirty(ntfs_index_context * ictx)123*4882a593Smuzhiyun static inline void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun if (ictx->is_in_root)
126*4882a593Smuzhiyun mark_mft_record_dirty(ictx->actx->ntfs_ino);
127*4882a593Smuzhiyun else
128*4882a593Smuzhiyun mark_ntfs_record_dirty(ictx->page,
129*4882a593Smuzhiyun (u8*)ictx->ia - (u8*)page_address(ictx->page));
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #endif /* NTFS_RW */
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun #endif /* _LINUX_NTFS_INDEX_H */
135