~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/ntfs3/record.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/ntfs3/record.c (Version linux-6.12-rc7) and /fs/ntfs3/record.c (Version linux-5.17.15)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                                  2 /*
  3  *                                                  3  *
  4  * Copyright (C) 2019-2021 Paragon Software Gm      4  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
  5  *                                                  5  *
  6  */                                                 6  */
  7                                                     7 
  8 #include <linux/fs.h>                               8 #include <linux/fs.h>
  9                                                     9 
 10 #include "debug.h"                                 10 #include "debug.h"
 11 #include "ntfs.h"                                  11 #include "ntfs.h"
 12 #include "ntfs_fs.h"                               12 #include "ntfs_fs.h"
 13                                                    13 
 14 static inline int compare_attr(const struct AT     14 static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
 15                                const __le16 *n     15                                const __le16 *name, u8 name_len,
 16                                const u16 *upca     16                                const u16 *upcase)
 17 {                                                  17 {
 18         /* First, compare the type codes. */       18         /* First, compare the type codes. */
 19         int diff = le32_to_cpu(left->type) - l     19         int diff = le32_to_cpu(left->type) - le32_to_cpu(type);
 20                                                    20 
 21         if (diff)                                  21         if (diff)
 22                 return diff;                       22                 return diff;
 23                                                    23 
 24         /* They have the same type code, so we     24         /* They have the same type code, so we have to compare the names. */
 25         return ntfs_cmp_names(attr_name(left),     25         return ntfs_cmp_names(attr_name(left), left->name_len, name, name_len,
 26                               upcase, true);       26                               upcase, true);
 27 }                                                  27 }
 28                                                    28 
 29 /*                                                 29 /*
 30  * mi_new_attt_id                                  30  * mi_new_attt_id
 31  *                                                 31  *
 32  * Return: Unused attribute id that is less th     32  * Return: Unused attribute id that is less than mrec->next_attr_id.
 33  */                                                33  */
 34 static __le16 mi_new_attt_id(struct mft_inode      34 static __le16 mi_new_attt_id(struct mft_inode *mi)
 35 {                                                  35 {
 36         u16 free_id, max_id, t16;                  36         u16 free_id, max_id, t16;
 37         struct MFT_REC *rec = mi->mrec;            37         struct MFT_REC *rec = mi->mrec;
 38         struct ATTRIB *attr;                       38         struct ATTRIB *attr;
 39         __le16 id;                                 39         __le16 id;
 40                                                    40 
 41         id = rec->next_attr_id;                    41         id = rec->next_attr_id;
 42         free_id = le16_to_cpu(id);                 42         free_id = le16_to_cpu(id);
 43         if (free_id < 0x7FFF) {                    43         if (free_id < 0x7FFF) {
 44                 rec->next_attr_id = cpu_to_le1     44                 rec->next_attr_id = cpu_to_le16(free_id + 1);
 45                 return id;                         45                 return id;
 46         }                                          46         }
 47                                                    47 
 48         /* One record can store up to 1024/24      48         /* One record can store up to 1024/24 ~= 42 attributes. */
 49         free_id = 0;                               49         free_id = 0;
 50         max_id = 0;                                50         max_id = 0;
 51                                                    51 
 52         attr = NULL;                               52         attr = NULL;
 53                                                    53 
 54         for (;;) {                                 54         for (;;) {
 55                 attr = mi_enum_attr(mi, attr);     55                 attr = mi_enum_attr(mi, attr);
 56                 if (!attr) {                       56                 if (!attr) {
 57                         rec->next_attr_id = cp     57                         rec->next_attr_id = cpu_to_le16(max_id + 1);
 58                         mi->dirty = true;          58                         mi->dirty = true;
 59                         return cpu_to_le16(fre     59                         return cpu_to_le16(free_id);
 60                 }                                  60                 }
 61                                                    61 
 62                 t16 = le16_to_cpu(attr->id);       62                 t16 = le16_to_cpu(attr->id);
 63                 if (t16 == free_id) {              63                 if (t16 == free_id) {
 64                         free_id += 1;              64                         free_id += 1;
 65                         attr = NULL;               65                         attr = NULL;
 66                 } else if (max_id < t16)           66                 } else if (max_id < t16)
 67                         max_id = t16;              67                         max_id = t16;
 68         }                                          68         }
 69 }                                                  69 }
 70                                                    70 
 71 int mi_get(struct ntfs_sb_info *sbi, CLST rno,     71 int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi)
 72 {                                                  72 {
 73         int err;                                   73         int err;
 74         struct mft_inode *m = kzalloc(sizeof(s     74         struct mft_inode *m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
 75                                                    75 
 76         if (!m)                                    76         if (!m)
 77                 return -ENOMEM;                    77                 return -ENOMEM;
 78                                                    78 
 79         err = mi_init(m, sbi, rno);                79         err = mi_init(m, sbi, rno);
 80         if (err) {                                 80         if (err) {
 81                 kfree(m);                          81                 kfree(m);
 82                 return err;                        82                 return err;
 83         }                                          83         }
 84                                                    84 
 85         err = mi_read(m, false);                   85         err = mi_read(m, false);
 86         if (err) {                                 86         if (err) {
 87                 mi_put(m);                         87                 mi_put(m);
 88                 return err;                        88                 return err;
 89         }                                          89         }
 90                                                    90 
 91         *mi = m;                                   91         *mi = m;
 92         return 0;                                  92         return 0;
 93 }                                                  93 }
 94                                                    94 
 95 void mi_put(struct mft_inode *mi)                  95 void mi_put(struct mft_inode *mi)
 96 {                                                  96 {
 97         mi_clear(mi);                              97         mi_clear(mi);
 98         kfree(mi);                                 98         kfree(mi);
 99 }                                                  99 }
100                                                   100 
101 int mi_init(struct mft_inode *mi, struct ntfs_    101 int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno)
102 {                                                 102 {
103         mi->sbi = sbi;                            103         mi->sbi = sbi;
104         mi->rno = rno;                            104         mi->rno = rno;
105         mi->mrec = kmalloc(sbi->record_size, G    105         mi->mrec = kmalloc(sbi->record_size, GFP_NOFS);
106         if (!mi->mrec)                            106         if (!mi->mrec)
107                 return -ENOMEM;                   107                 return -ENOMEM;
108                                                   108 
109         return 0;                                 109         return 0;
110 }                                                 110 }
111                                                   111 
112 /*                                                112 /*
113  * mi_read - Read MFT data.                       113  * mi_read - Read MFT data.
114  */                                               114  */
115 int mi_read(struct mft_inode *mi, bool is_mft)    115 int mi_read(struct mft_inode *mi, bool is_mft)
116 {                                                 116 {
117         int err;                                  117         int err;
118         struct MFT_REC *rec = mi->mrec;           118         struct MFT_REC *rec = mi->mrec;
119         struct ntfs_sb_info *sbi = mi->sbi;       119         struct ntfs_sb_info *sbi = mi->sbi;
120         u32 bpr = sbi->record_size;               120         u32 bpr = sbi->record_size;
121         u64 vbo = (u64)mi->rno << sbi->record_    121         u64 vbo = (u64)mi->rno << sbi->record_bits;
122         struct ntfs_inode *mft_ni = sbi->mft.n    122         struct ntfs_inode *mft_ni = sbi->mft.ni;
123         struct runs_tree *run = mft_ni ? &mft_    123         struct runs_tree *run = mft_ni ? &mft_ni->file.run : NULL;
124         struct rw_semaphore *rw_lock = NULL;      124         struct rw_semaphore *rw_lock = NULL;
125                                                   125 
126         if (is_mounted(sbi)) {                    126         if (is_mounted(sbi)) {
127                 if (!is_mft && mft_ni) {       !! 127                 if (!is_mft) {
128                         rw_lock = &mft_ni->fil    128                         rw_lock = &mft_ni->file.run_lock;
129                         down_read(rw_lock);       129                         down_read(rw_lock);
130                 }                                 130                 }
131         }                                         131         }
132                                                   132 
133         err = ntfs_read_bh(sbi, run, vbo, &rec    133         err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
134         if (rw_lock)                              134         if (rw_lock)
135                 up_read(rw_lock);                 135                 up_read(rw_lock);
136         if (!err)                                 136         if (!err)
137                 goto ok;                          137                 goto ok;
138                                                   138 
139         if (err == -E_NTFS_FIXUP) {               139         if (err == -E_NTFS_FIXUP) {
140                 mi->dirty = true;                 140                 mi->dirty = true;
141                 goto ok;                          141                 goto ok;
142         }                                         142         }
143                                                   143 
144         if (err != -ENOENT)                       144         if (err != -ENOENT)
145                 goto out;                         145                 goto out;
146                                                   146 
147         if (rw_lock) {                            147         if (rw_lock) {
148                 ni_lock(mft_ni);                  148                 ni_lock(mft_ni);
149                 down_write(rw_lock);              149                 down_write(rw_lock);
150         }                                         150         }
151         err = attr_load_runs_vcn(mft_ni, ATTR_ !! 151         err = attr_load_runs_vcn(mft_ni, ATTR_DATA, NULL, 0, &mft_ni->file.run,
152                                  vbo >> sbi->c    152                                  vbo >> sbi->cluster_bits);
153         if (rw_lock) {                            153         if (rw_lock) {
154                 up_write(rw_lock);                154                 up_write(rw_lock);
155                 ni_unlock(mft_ni);                155                 ni_unlock(mft_ni);
156         }                                         156         }
157         if (err)                                  157         if (err)
158                 goto out;                         158                 goto out;
159                                                   159 
160         if (rw_lock)                              160         if (rw_lock)
161                 down_read(rw_lock);               161                 down_read(rw_lock);
162         err = ntfs_read_bh(sbi, run, vbo, &rec    162         err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
163         if (rw_lock)                              163         if (rw_lock)
164                 up_read(rw_lock);                 164                 up_read(rw_lock);
165                                                   165 
166         if (err == -E_NTFS_FIXUP) {               166         if (err == -E_NTFS_FIXUP) {
167                 mi->dirty = true;                 167                 mi->dirty = true;
168                 goto ok;                          168                 goto ok;
169         }                                         169         }
170         if (err)                                  170         if (err)
171                 goto out;                         171                 goto out;
172                                                   172 
173 ok:                                               173 ok:
174         /* Check field 'total' only here. */      174         /* Check field 'total' only here. */
175         if (le32_to_cpu(rec->total) != bpr) {     175         if (le32_to_cpu(rec->total) != bpr) {
176                 err = -EINVAL;                    176                 err = -EINVAL;
177                 goto out;                         177                 goto out;
178         }                                         178         }
179                                                   179 
180         return 0;                                 180         return 0;
181                                                   181 
182 out:                                              182 out:
183         if (err == -E_NTFS_CORRUPT) {          << 
184                 ntfs_err(sbi->sb, "mft corrupt << 
185                 ntfs_set_state(sbi, NTFS_DIRTY << 
186                 err = -EINVAL;                 << 
187         }                                      << 
188                                                << 
189         return err;                               183         return err;
190 }                                                 184 }
191                                                   185 
192 /*                                             << 
193  * mi_enum_attr - start/continue attributes en << 
194  *                                             << 
195  * NOTE: mi->mrec - memory of size sbi->record << 
196  * here we sure that mi->mrec->total == sbi->r << 
197  */                                            << 
198 struct ATTRIB *mi_enum_attr(struct mft_inode *    186 struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
199 {                                                 187 {
200         const struct MFT_REC *rec = mi->mrec;     188         const struct MFT_REC *rec = mi->mrec;
201         u32 used = le32_to_cpu(rec->used);        189         u32 used = le32_to_cpu(rec->used);
202         u32 t32, off, asize, prev_type;        !! 190         u32 t32, off, asize;
203         u16 t16;                                  191         u16 t16;
204         u64 data_size, alloc_size, tot_size;   << 
205                                                   192 
206         if (!attr) {                              193         if (!attr) {
207                 u32 total = le32_to_cpu(rec->t    194                 u32 total = le32_to_cpu(rec->total);
208                                                   195 
209                 off = le16_to_cpu(rec->attr_of    196                 off = le16_to_cpu(rec->attr_off);
210                                                   197 
211                 if (used > total)                 198                 if (used > total)
212                         return NULL;              199                         return NULL;
213                                                   200 
214                 if (off >= used || off < MFTRE    201                 if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
215                     !IS_ALIGNED(off, 4)) {        202                     !IS_ALIGNED(off, 4)) {
216                         return NULL;              203                         return NULL;
217                 }                                 204                 }
218                                                   205 
219                 /* Skip non-resident records.     206                 /* Skip non-resident records. */
220                 if (!is_rec_inuse(rec))           207                 if (!is_rec_inuse(rec))
221                         return NULL;              208                         return NULL;
222                                                   209 
223                 prev_type = 0;                 << 
224                 attr = Add2Ptr(rec, off);         210                 attr = Add2Ptr(rec, off);
225         } else {                                  211         } else {
226                 /*                             !! 212                 /* Check if input attr inside record. */
227                  * We don't need to check prev << 
228                  * a bounds checking in the pr << 
229                  */                            << 
230                 off = PtrOffset(rec, attr);       213                 off = PtrOffset(rec, attr);
                                                   >> 214                 if (off >= used)
                                                   >> 215                         return NULL;
231                                                   216 
232                 asize = le32_to_cpu(attr->size    217                 asize = le32_to_cpu(attr->size);
                                                   >> 218                 if (asize < SIZEOF_RESIDENT) {
                                                   >> 219                         /* Impossible 'cause we should not return such attribute. */
                                                   >> 220                         return NULL;
                                                   >> 221                 }
233                                                   222 
234                 prev_type = le32_to_cpu(attr-> << 
235                 attr = Add2Ptr(attr, asize);      223                 attr = Add2Ptr(attr, asize);
236                 off += asize;                     224                 off += asize;
237         }                                         225         }
238                                                   226 
                                                   >> 227         asize = le32_to_cpu(attr->size);
                                                   >> 228 
239         /* Can we use the first field (attr->t    229         /* Can we use the first field (attr->type). */
240         /* NOTE: this code also checks attr->s << 
241         if (off + 8 > used) {                     230         if (off + 8 > used) {
242                 static_assert(ALIGN(sizeof(enu    231                 static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
243                 return NULL;                      232                 return NULL;
244         }                                         233         }
245                                                   234 
246         if (attr->type == ATTR_END) {             235         if (attr->type == ATTR_END) {
247                 /* End of enumeration. */         236                 /* End of enumeration. */
248                 return NULL;                      237                 return NULL;
249         }                                         238         }
250                                                   239 
251         /* 0x100 is last known attribute for n    240         /* 0x100 is last known attribute for now. */
252         t32 = le32_to_cpu(attr->type);            241         t32 = le32_to_cpu(attr->type);
253         if (!t32 || (t32 & 0xf) || (t32 > 0x10 !! 242         if ((t32 & 0xf) || (t32 > 0x100))
254                 return NULL;                      243                 return NULL;
255                                                   244 
256         /* attributes in record must be ordere !! 245         /* Check boundary. */
257         if (t32 < prev_type)                   !! 246         if (off + asize > used)
258                 return NULL;                   << 
259                                                << 
260         asize = le32_to_cpu(attr->size);       << 
261                                                << 
262         /* Check overflow and boundary. */     << 
263         if (off + asize < off || off + asize > << 
264                 return NULL;                      247                 return NULL;
265                                                   248 
266         /* Check size of attribute. */            249         /* Check size of attribute. */
267         if (!attr->non_res) {                     250         if (!attr->non_res) {
268                 /* Check resident fields. */   << 
269                 if (asize < SIZEOF_RESIDENT)      251                 if (asize < SIZEOF_RESIDENT)
270                         return NULL;              252                         return NULL;
271                                                   253 
272                 t16 = le16_to_cpu(attr->res.da    254                 t16 = le16_to_cpu(attr->res.data_off);
273                 if (t16 > asize)               << 
274                         return NULL;           << 
275                                                   255 
276                 if (le32_to_cpu(attr->res.data !! 256                 if (t16 > asize)
277                         return NULL;              257                         return NULL;
278                                                   258 
279                 t32 = sizeof(short) * attr->na !! 259                 t32 = le32_to_cpu(attr->res.data_size);
280                 if (t32 && le16_to_cpu(attr->n !! 260                 if (t16 + t32 > asize)
281                         return NULL;              261                         return NULL;
282                                                   262 
283                 return attr;                      263                 return attr;
284         }                                         264         }
285                                                   265 
286         /* Check nonresident fields. */        !! 266         /* Check some nonresident fields. */
287         if (attr->non_res != 1)                !! 267         if (attr->name_len &&
288                 return NULL;                   !! 268             le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
289                                                !! 269                     le16_to_cpu(attr->nres.run_off)) {
290         /* Can we use memory including attr->n << 
291         if (asize < SIZEOF_NONRESIDENT)        << 
292                 return NULL;                   << 
293                                                << 
294         t16 = le16_to_cpu(attr->nres.run_off); << 
295         if (t16 > asize)                       << 
296                 return NULL;                   << 
297                                                << 
298         t32 = sizeof(short) * attr->name_len;  << 
299         if (t32 && le16_to_cpu(attr->name_off) << 
300                 return NULL;                   << 
301                                                << 
302         /* Check start/end vcn. */             << 
303         if (le64_to_cpu(attr->nres.svcn) > le6 << 
304                 return NULL;                   << 
305                                                << 
306         data_size = le64_to_cpu(attr->nres.dat << 
307         if (le64_to_cpu(attr->nres.valid_size) << 
308                 return NULL;                      270                 return NULL;
                                                   >> 271         }
309                                                   272 
310         alloc_size = le64_to_cpu(attr->nres.al !! 273         if (attr->nres.svcn || !is_attr_ext(attr)) {
311         if (data_size > alloc_size)            !! 274                 if (asize + 8 < SIZEOF_NONRESIDENT)
312                 return NULL;                   << 
313                                                << 
314         t32 = mi->sbi->cluster_mask;           << 
315         if (alloc_size & t32)                  << 
316                 return NULL;                   << 
317                                                << 
318         if (!attr->nres.svcn && is_attr_ext(at << 
319                 /* First segment of sparse/com << 
320                 /* Can we use memory including << 
321                 if (asize < SIZEOF_NONRESIDENT << 
322                         return NULL;           << 
323                                                << 
324                 tot_size = le64_to_cpu(attr->n << 
325                 if (tot_size & t32)            << 
326                         return NULL;              275                         return NULL;
327                                                   276 
328                 if (tot_size > alloc_size)     << 
329                         return NULL;           << 
330         } else {                               << 
331                 if (attr->nres.c_unit)            277                 if (attr->nres.c_unit)
332                         return NULL;              278                         return NULL;
333                                                !! 279         } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
334                 if (alloc_size > mi->sbi->volu !! 280                 return NULL;
335                         return NULL;           << 
336         }                                      << 
337                                                   281 
338         return attr;                              282         return attr;
339 }                                                 283 }
340                                                   284 
341 /*                                                285 /*
342  * mi_find_attr - Find the attribute by type a    286  * mi_find_attr - Find the attribute by type and name and id.
343  */                                               287  */
344 struct ATTRIB *mi_find_attr(struct mft_inode *    288 struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
345                             enum ATTR_TYPE typ    289                             enum ATTR_TYPE type, const __le16 *name,
346                             u8 name_len, const !! 290                             size_t name_len, const __le16 *id)
347 {                                                 291 {
348         u32 type_in = le32_to_cpu(type);          292         u32 type_in = le32_to_cpu(type);
349         u32 atype;                                293         u32 atype;
350                                                   294 
351 next_attr:                                        295 next_attr:
352         attr = mi_enum_attr(mi, attr);            296         attr = mi_enum_attr(mi, attr);
353         if (!attr)                                297         if (!attr)
354                 return NULL;                      298                 return NULL;
355                                                   299 
356         atype = le32_to_cpu(attr->type);          300         atype = le32_to_cpu(attr->type);
357         if (atype > type_in)                      301         if (atype > type_in)
358                 return NULL;                      302                 return NULL;
359                                                   303 
360         if (atype < type_in)                      304         if (atype < type_in)
361                 goto next_attr;                   305                 goto next_attr;
362                                                   306 
363         if (attr->name_len != name_len)           307         if (attr->name_len != name_len)
364                 goto next_attr;                   308                 goto next_attr;
365                                                   309 
366         if (name_len && memcmp(attr_name(attr)    310         if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
367                 goto next_attr;                   311                 goto next_attr;
368                                                   312 
369         if (id && *id != attr->id)                313         if (id && *id != attr->id)
370                 goto next_attr;                   314                 goto next_attr;
371                                                   315 
372         return attr;                              316         return attr;
373 }                                                 317 }
374                                                   318 
375 int mi_write(struct mft_inode *mi, int wait)      319 int mi_write(struct mft_inode *mi, int wait)
376 {                                                 320 {
377         struct MFT_REC *rec;                      321         struct MFT_REC *rec;
378         int err;                                  322         int err;
379         struct ntfs_sb_info *sbi;                 323         struct ntfs_sb_info *sbi;
380                                                   324 
381         if (!mi->dirty)                           325         if (!mi->dirty)
382                 return 0;                         326                 return 0;
383                                                   327 
384         sbi = mi->sbi;                            328         sbi = mi->sbi;
385         rec = mi->mrec;                           329         rec = mi->mrec;
386                                                   330 
387         err = ntfs_write_bh(sbi, &rec->rhdr, &    331         err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
388         if (err)                                  332         if (err)
389                 return err;                       333                 return err;
390                                                   334 
391         if (mi->rno < sbi->mft.recs_mirr)         335         if (mi->rno < sbi->mft.recs_mirr)
392                 sbi->flags |= NTFS_FLAGS_MFTMI    336                 sbi->flags |= NTFS_FLAGS_MFTMIRR;
393                                                   337 
394         mi->dirty = false;                        338         mi->dirty = false;
395                                                   339 
396         return 0;                                 340         return 0;
397 }                                                 341 }
398                                                   342 
399 int mi_format_new(struct mft_inode *mi, struct    343 int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
400                   __le16 flags, bool is_mft)      344                   __le16 flags, bool is_mft)
401 {                                                 345 {
402         int err;                                  346         int err;
403         u16 seq = 1;                              347         u16 seq = 1;
404         struct MFT_REC *rec;                      348         struct MFT_REC *rec;
405         u64 vbo = (u64)rno << sbi->record_bits    349         u64 vbo = (u64)rno << sbi->record_bits;
406                                                   350 
407         err = mi_init(mi, sbi, rno);              351         err = mi_init(mi, sbi, rno);
408         if (err)                                  352         if (err)
409                 return err;                       353                 return err;
410                                                   354 
411         rec = mi->mrec;                           355         rec = mi->mrec;
412                                                   356 
413         if (rno == MFT_REC_MFT) {                 357         if (rno == MFT_REC_MFT) {
414                 ;                                 358                 ;
415         } else if (rno < MFT_REC_FREE) {          359         } else if (rno < MFT_REC_FREE) {
416                 seq = rno;                        360                 seq = rno;
417         } else if (rno >= sbi->mft.used) {        361         } else if (rno >= sbi->mft.used) {
418                 ;                                 362                 ;
419         } else if (mi_read(mi, is_mft)) {         363         } else if (mi_read(mi, is_mft)) {
420                 ;                                 364                 ;
421         } else if (rec->rhdr.sign == NTFS_FILE    365         } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
422                 /* Record is reused. Update it    366                 /* Record is reused. Update its sequence number. */
423                 seq = le16_to_cpu(rec->seq) +     367                 seq = le16_to_cpu(rec->seq) + 1;
424                 if (!seq)                         368                 if (!seq)
425                         seq = 1;                  369                         seq = 1;
426         }                                         370         }
427                                                   371 
428         memcpy(rec, sbi->new_rec, sbi->record_    372         memcpy(rec, sbi->new_rec, sbi->record_size);
429                                                   373 
430         rec->seq = cpu_to_le16(seq);              374         rec->seq = cpu_to_le16(seq);
431         rec->flags = RECORD_FLAG_IN_USE | flag    375         rec->flags = RECORD_FLAG_IN_USE | flags;
432         if (MFTRECORD_FIXUP_OFFSET == MFTRECOR << 
433                 rec->mft_record = cpu_to_le32( << 
434                                                   376 
435         mi->dirty = true;                         377         mi->dirty = true;
436                                                   378 
437         if (!mi->nb.nbufs) {                      379         if (!mi->nb.nbufs) {
438                 struct ntfs_inode *ni = sbi->m    380                 struct ntfs_inode *ni = sbi->mft.ni;
439                 bool lock = false;                381                 bool lock = false;
440                                                   382 
441                 if (is_mounted(sbi) && !is_mft    383                 if (is_mounted(sbi) && !is_mft) {
442                         down_read(&ni->file.ru    384                         down_read(&ni->file.run_lock);
443                         lock = true;              385                         lock = true;
444                 }                                 386                 }
445                                                   387 
446                 err = ntfs_get_bh(sbi, &ni->fi    388                 err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
447                                   &mi->nb);       389                                   &mi->nb);
448                 if (lock)                         390                 if (lock)
449                         up_read(&ni->file.run_    391                         up_read(&ni->file.run_lock);
450         }                                         392         }
451                                                   393 
452         return err;                               394         return err;
453 }                                                 395 }
454                                                   396 
455 /*                                                397 /*
                                                   >> 398  * mi_mark_free - Mark record as unused and marks it as free in bitmap.
                                                   >> 399  */
                                                   >> 400 void mi_mark_free(struct mft_inode *mi)
                                                   >> 401 {
                                                   >> 402         CLST rno = mi->rno;
                                                   >> 403         struct ntfs_sb_info *sbi = mi->sbi;
                                                   >> 404 
                                                   >> 405         if (rno >= MFT_REC_RESERVED && rno < MFT_REC_FREE) {
                                                   >> 406                 ntfs_clear_mft_tail(sbi, rno, rno + 1);
                                                   >> 407                 mi->dirty = false;
                                                   >> 408                 return;
                                                   >> 409         }
                                                   >> 410 
                                                   >> 411         if (mi->mrec) {
                                                   >> 412                 clear_rec_inuse(mi->mrec);
                                                   >> 413                 mi->dirty = true;
                                                   >> 414                 mi_write(mi, 0);
                                                   >> 415         }
                                                   >> 416         ntfs_mark_rec_free(sbi, rno);
                                                   >> 417 }
                                                   >> 418 
                                                   >> 419 /*
456  * mi_insert_attr - Reserve space for new attr    420  * mi_insert_attr - Reserve space for new attribute.
457  *                                                421  *
458  * Return: Not full constructed attribute or N    422  * Return: Not full constructed attribute or NULL if not possible to create.
459  */                                               423  */
460 struct ATTRIB *mi_insert_attr(struct mft_inode    424 struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
461                               const __le16 *na    425                               const __le16 *name, u8 name_len, u32 asize,
462                               u16 name_off)       426                               u16 name_off)
463 {                                                 427 {
464         size_t tail;                              428         size_t tail;
465         struct ATTRIB *attr;                      429         struct ATTRIB *attr;
466         __le16 id;                                430         __le16 id;
467         struct MFT_REC *rec = mi->mrec;           431         struct MFT_REC *rec = mi->mrec;
468         struct ntfs_sb_info *sbi = mi->sbi;       432         struct ntfs_sb_info *sbi = mi->sbi;
469         u32 used = le32_to_cpu(rec->used);        433         u32 used = le32_to_cpu(rec->used);
470         const u16 *upcase = sbi->upcase;          434         const u16 *upcase = sbi->upcase;
                                                   >> 435         int diff;
471                                                   436 
472         /* Can we insert mi attribute? */         437         /* Can we insert mi attribute? */
473         if (used + asize > sbi->record_size)   !! 438         if (used + asize > mi->sbi->record_size)
474                 return NULL;                      439                 return NULL;
475                                                   440 
476         /*                                        441         /*
477          * Scan through the list of attributes    442          * Scan through the list of attributes to find the point
478          * at which we should insert it.          443          * at which we should insert it.
479          */                                       444          */
480         attr = NULL;                              445         attr = NULL;
481         while ((attr = mi_enum_attr(mi, attr))    446         while ((attr = mi_enum_attr(mi, attr))) {
482                 int diff = compare_attr(attr,  !! 447                 diff = compare_attr(attr, type, name, name_len, upcase);
483                                                !! 448                 if (diff > 0)
                                                   >> 449                         break;
484                 if (diff < 0)                     450                 if (diff < 0)
485                         continue;                 451                         continue;
486                                                   452 
487                 if (!diff && !is_attr_indexed( !! 453                 if (!is_attr_indexed(attr))
488                         return NULL;              454                         return NULL;
489                 break;                            455                 break;
490         }                                         456         }
491                                                   457 
492         if (!attr) {                              458         if (!attr) {
493                 /* Append. */                  !! 459                 tail = 8; /* Not used, just to suppress warning. */
494                 tail = 8;                      << 
495                 attr = Add2Ptr(rec, used - 8);    460                 attr = Add2Ptr(rec, used - 8);
496         } else {                                  461         } else {
497                 /* Insert before 'attr'. */    << 
498                 tail = used - PtrOffset(rec, a    462                 tail = used - PtrOffset(rec, attr);
499         }                                         463         }
500                                                   464 
501         id = mi_new_attt_id(mi);                  465         id = mi_new_attt_id(mi);
502                                                   466 
503         memmove(Add2Ptr(attr, asize), attr, ta    467         memmove(Add2Ptr(attr, asize), attr, tail);
504         memset(attr, 0, asize);                   468         memset(attr, 0, asize);
505                                                   469 
506         attr->type = type;                        470         attr->type = type;
507         attr->size = cpu_to_le32(asize);          471         attr->size = cpu_to_le32(asize);
508         attr->name_len = name_len;                472         attr->name_len = name_len;
509         attr->name_off = cpu_to_le16(name_off)    473         attr->name_off = cpu_to_le16(name_off);
510         attr->id = id;                            474         attr->id = id;
511                                                   475 
512         memmove(Add2Ptr(attr, name_off), name,    476         memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
513         rec->used = cpu_to_le32(used + asize);    477         rec->used = cpu_to_le32(used + asize);
514                                                   478 
515         mi->dirty = true;                         479         mi->dirty = true;
516                                                   480 
517         return attr;                              481         return attr;
518 }                                                 482 }
519                                                   483 
520 /*                                                484 /*
521  * mi_remove_attr - Remove the attribute from     485  * mi_remove_attr - Remove the attribute from record.
522  *                                                486  *
523  * NOTE: The source attr will point to next at    487  * NOTE: The source attr will point to next attribute.
524  */                                               488  */
525 bool mi_remove_attr(struct ntfs_inode *ni, str    489 bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
526                     struct ATTRIB *attr)          490                     struct ATTRIB *attr)
527 {                                                 491 {
528         struct MFT_REC *rec = mi->mrec;           492         struct MFT_REC *rec = mi->mrec;
529         u32 aoff = PtrOffset(rec, attr);          493         u32 aoff = PtrOffset(rec, attr);
530         u32 used = le32_to_cpu(rec->used);        494         u32 used = le32_to_cpu(rec->used);
531         u32 asize = le32_to_cpu(attr->size);      495         u32 asize = le32_to_cpu(attr->size);
532                                                   496 
533         if (aoff + asize > used)                  497         if (aoff + asize > used)
534                 return false;                     498                 return false;
535                                                   499 
536         if (ni && is_attr_indexed(attr) && att !! 500         if (ni && is_attr_indexed(attr)) {
537                 u16 links = le16_to_cpu(ni->mi !! 501                 le16_add_cpu(&ni->mi.mrec->hard_links, -1);
538                 if (!links) {                  !! 502                 ni->mi.dirty = true;
539                         /* minor error. Not cr << 
540                 } else {                       << 
541                         ni->mi.mrec->hard_link << 
542                         ni->mi.dirty = true;   << 
543                 }                              << 
544         }                                         503         }
545                                                   504 
546         used -= asize;                            505         used -= asize;
547         memmove(attr, Add2Ptr(attr, asize), us    506         memmove(attr, Add2Ptr(attr, asize), used - aoff);
548         rec->used = cpu_to_le32(used);            507         rec->used = cpu_to_le32(used);
549         mi->dirty = true;                         508         mi->dirty = true;
550                                                   509 
551         return true;                              510         return true;
552 }                                                 511 }
553                                                   512 
554 /* bytes = "new attribute size" - "old attribu    513 /* bytes = "new attribute size" - "old attribute size" */
555 bool mi_resize_attr(struct mft_inode *mi, stru    514 bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
556 {                                                 515 {
557         struct MFT_REC *rec = mi->mrec;           516         struct MFT_REC *rec = mi->mrec;
558         u32 aoff = PtrOffset(rec, attr);          517         u32 aoff = PtrOffset(rec, attr);
559         u32 total, used = le32_to_cpu(rec->use    518         u32 total, used = le32_to_cpu(rec->used);
560         u32 nsize, asize = le32_to_cpu(attr->s    519         u32 nsize, asize = le32_to_cpu(attr->size);
561         u32 rsize = le32_to_cpu(attr->res.data    520         u32 rsize = le32_to_cpu(attr->res.data_size);
562         int tail = (int)(used - aoff - asize);    521         int tail = (int)(used - aoff - asize);
563         int dsize;                                522         int dsize;
564         char *next;                               523         char *next;
565                                                   524 
566         if (tail < 0 || aoff >= used)             525         if (tail < 0 || aoff >= used)
567                 return false;                     526                 return false;
568                                                   527 
569         if (!bytes)                               528         if (!bytes)
570                 return true;                      529                 return true;
571                                                   530 
572         total = le32_to_cpu(rec->total);          531         total = le32_to_cpu(rec->total);
573         next = Add2Ptr(attr, asize);              532         next = Add2Ptr(attr, asize);
574                                                   533 
575         if (bytes > 0) {                          534         if (bytes > 0) {
576                 dsize = ALIGN(bytes, 8);          535                 dsize = ALIGN(bytes, 8);
577                 if (used + dsize > total)         536                 if (used + dsize > total)
578                         return false;             537                         return false;
579                 nsize = asize + dsize;            538                 nsize = asize + dsize;
580                 /* Move tail */                   539                 /* Move tail */
581                 memmove(next + dsize, next, ta    540                 memmove(next + dsize, next, tail);
582                 memset(next, 0, dsize);           541                 memset(next, 0, dsize);
583                 used += dsize;                    542                 used += dsize;
584                 rsize += dsize;                   543                 rsize += dsize;
585         } else {                                  544         } else {
586                 dsize = ALIGN(-bytes, 8);         545                 dsize = ALIGN(-bytes, 8);
587                 if (dsize > asize)                546                 if (dsize > asize)
588                         return false;             547                         return false;
589                 nsize = asize - dsize;            548                 nsize = asize - dsize;
590                 memmove(next - dsize, next, ta    549                 memmove(next - dsize, next, tail);
591                 used -= dsize;                    550                 used -= dsize;
592                 rsize -= dsize;                   551                 rsize -= dsize;
593         }                                         552         }
594                                                   553 
595         rec->used = cpu_to_le32(used);            554         rec->used = cpu_to_le32(used);
596         attr->size = cpu_to_le32(nsize);          555         attr->size = cpu_to_le32(nsize);
597         if (!attr->non_res)                       556         if (!attr->non_res)
598                 attr->res.data_size = cpu_to_l    557                 attr->res.data_size = cpu_to_le32(rsize);
599         mi->dirty = true;                         558         mi->dirty = true;
600                                                   559 
601         return true;                              560         return true;
602 }                                                 561 }
603                                                   562 
604 /*                                             << 
605  * Pack runs in MFT record.                    << 
606  * If failed record is not changed.            << 
607  */                                            << 
608 int mi_pack_runs(struct mft_inode *mi, struct     563 int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
609                  struct runs_tree *run, CLST l    564                  struct runs_tree *run, CLST len)
610 {                                                 565 {
611         int err = 0;                              566         int err = 0;
612         struct ntfs_sb_info *sbi = mi->sbi;       567         struct ntfs_sb_info *sbi = mi->sbi;
613         u32 new_run_size;                         568         u32 new_run_size;
614         CLST plen;                                569         CLST plen;
615         struct MFT_REC *rec = mi->mrec;           570         struct MFT_REC *rec = mi->mrec;
616         CLST svcn = le64_to_cpu(attr->nres.svc    571         CLST svcn = le64_to_cpu(attr->nres.svcn);
617         u32 used = le32_to_cpu(rec->used);        572         u32 used = le32_to_cpu(rec->used);
618         u32 aoff = PtrOffset(rec, attr);          573         u32 aoff = PtrOffset(rec, attr);
619         u32 asize = le32_to_cpu(attr->size);      574         u32 asize = le32_to_cpu(attr->size);
620         char *next = Add2Ptr(attr, asize);        575         char *next = Add2Ptr(attr, asize);
621         u16 run_off = le16_to_cpu(attr->nres.r    576         u16 run_off = le16_to_cpu(attr->nres.run_off);
622         u32 run_size = asize - run_off;           577         u32 run_size = asize - run_off;
623         u32 tail = used - aoff - asize;           578         u32 tail = used - aoff - asize;
624         u32 dsize = sbi->record_size - used;      579         u32 dsize = sbi->record_size - used;
625                                                   580 
626         /* Make a maximum gap in current recor    581         /* Make a maximum gap in current record. */
627         memmove(next + dsize, next, tail);        582         memmove(next + dsize, next, tail);
628                                                   583 
629         /* Pack as much as possible. */           584         /* Pack as much as possible. */
630         err = run_pack(run, svcn, len, Add2Ptr    585         err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
631                        &plen);                    586                        &plen);
632         if (err < 0) {                            587         if (err < 0) {
633                 memmove(next, next + dsize, ta    588                 memmove(next, next + dsize, tail);
634                 return err;                       589                 return err;
635         }                                         590         }
636                                                   591 
637         new_run_size = ALIGN(err, 8);             592         new_run_size = ALIGN(err, 8);
638                                                   593 
639         memmove(next + new_run_size - run_size    594         memmove(next + new_run_size - run_size, next + dsize, tail);
640                                                   595 
641         attr->size = cpu_to_le32(asize + new_r    596         attr->size = cpu_to_le32(asize + new_run_size - run_size);
642         attr->nres.evcn = cpu_to_le64(svcn + p    597         attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
643         rec->used = cpu_to_le32(used + new_run    598         rec->used = cpu_to_le32(used + new_run_size - run_size);
644         mi->dirty = true;                         599         mi->dirty = true;
645                                                   600 
646         return 0;                                 601         return 0;
647 }                                                 602 }
648                                                   603 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php