~ [ 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.15.171)


  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 && mft_ni) {
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, 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) {             183         if (err == -E_NTFS_CORRUPT) {
184                 ntfs_err(sbi->sb, "mft corrupt    184                 ntfs_err(sbi->sb, "mft corrupted");
185                 ntfs_set_state(sbi, NTFS_DIRTY    185                 ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
186                 err = -EINVAL;                    186                 err = -EINVAL;
187         }                                         187         }
188                                                   188 
189         return err;                               189         return err;
190 }                                                 190 }
191                                                   191 
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 *    192 struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
199 {                                                 193 {
200         const struct MFT_REC *rec = mi->mrec;     194         const struct MFT_REC *rec = mi->mrec;
201         u32 used = le32_to_cpu(rec->used);        195         u32 used = le32_to_cpu(rec->used);
202         u32 t32, off, asize, prev_type;        !! 196         u32 t32, off, asize;
203         u16 t16;                                  197         u16 t16;
204         u64 data_size, alloc_size, tot_size;   << 
205                                                   198 
206         if (!attr) {                              199         if (!attr) {
207                 u32 total = le32_to_cpu(rec->t    200                 u32 total = le32_to_cpu(rec->total);
208                                                   201 
209                 off = le16_to_cpu(rec->attr_of    202                 off = le16_to_cpu(rec->attr_off);
210                                                   203 
211                 if (used > total)                 204                 if (used > total)
212                         return NULL;              205                         return NULL;
213                                                   206 
214                 if (off >= used || off < MFTRE    207                 if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
215                     !IS_ALIGNED(off, 4)) {        208                     !IS_ALIGNED(off, 4)) {
216                         return NULL;              209                         return NULL;
217                 }                                 210                 }
218                                                   211 
219                 /* Skip non-resident records.     212                 /* Skip non-resident records. */
220                 if (!is_rec_inuse(rec))           213                 if (!is_rec_inuse(rec))
221                         return NULL;              214                         return NULL;
222                                                   215 
223                 prev_type = 0;                 << 
224                 attr = Add2Ptr(rec, off);         216                 attr = Add2Ptr(rec, off);
225         } else {                                  217         } else {
226                 /*                             !! 218                 /* 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);       219                 off = PtrOffset(rec, attr);
                                                   >> 220                 if (off >= used)
                                                   >> 221                         return NULL;
231                                                   222 
232                 asize = le32_to_cpu(attr->size    223                 asize = le32_to_cpu(attr->size);
                                                   >> 224                 if (asize < SIZEOF_RESIDENT) {
                                                   >> 225                         /* Impossible 'cause we should not return such attribute. */
                                                   >> 226                         return NULL;
                                                   >> 227                 }
233                                                   228 
234                 prev_type = le32_to_cpu(attr-> << 
235                 attr = Add2Ptr(attr, asize);      229                 attr = Add2Ptr(attr, asize);
236                 off += asize;                     230                 off += asize;
237         }                                         231         }
238                                                   232 
                                                   >> 233         asize = le32_to_cpu(attr->size);
                                                   >> 234 
239         /* Can we use the first field (attr->t    235         /* Can we use the first field (attr->type). */
240         /* NOTE: this code also checks attr->s << 
241         if (off + 8 > used) {                     236         if (off + 8 > used) {
242                 static_assert(ALIGN(sizeof(enu    237                 static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
243                 return NULL;                      238                 return NULL;
244         }                                         239         }
245                                                   240 
246         if (attr->type == ATTR_END) {             241         if (attr->type == ATTR_END) {
247                 /* End of enumeration. */         242                 /* End of enumeration. */
248                 return NULL;                      243                 return NULL;
249         }                                         244         }
250                                                   245 
251         /* 0x100 is last known attribute for n    246         /* 0x100 is last known attribute for now. */
252         t32 = le32_to_cpu(attr->type);            247         t32 = le32_to_cpu(attr->type);
253         if (!t32 || (t32 & 0xf) || (t32 > 0x10 !! 248         if ((t32 & 0xf) || (t32 > 0x100))
254                 return NULL;                   << 
255                                                << 
256         /* attributes in record must be ordere << 
257         if (t32 < prev_type)                   << 
258                 return NULL;                      249                 return NULL;
259                                                   250 
260         asize = le32_to_cpu(attr->size);       << 
261                                                << 
262         /* Check overflow and boundary. */        251         /* Check overflow and boundary. */
263         if (off + asize < off || off + asize >    252         if (off + asize < off || off + asize > used)
264                 return NULL;                      253                 return NULL;
265                                                   254 
266         /* Check size of attribute. */            255         /* Check size of attribute. */
267         if (!attr->non_res) {                     256         if (!attr->non_res) {
268                 /* Check resident fields. */   << 
269                 if (asize < SIZEOF_RESIDENT)      257                 if (asize < SIZEOF_RESIDENT)
270                         return NULL;              258                         return NULL;
271                                                   259 
272                 t16 = le16_to_cpu(attr->res.da    260                 t16 = le16_to_cpu(attr->res.data_off);
                                                   >> 261 
273                 if (t16 > asize)                  262                 if (t16 > asize)
274                         return NULL;              263                         return NULL;
275                                                   264 
276                 if (le32_to_cpu(attr->res.data !! 265                 t32 = le32_to_cpu(attr->res.data_size);
                                                   >> 266                 if (t16 + t32 > asize)
277                         return NULL;              267                         return NULL;
278                                                   268 
279                 t32 = sizeof(short) * attr->na !! 269                 if (attr->name_len &&
280                 if (t32 && le16_to_cpu(attr->n !! 270                     le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len > t16) {
281                         return NULL;              271                         return NULL;
                                                   >> 272                 }
282                                                   273 
283                 return attr;                      274                 return attr;
284         }                                         275         }
285                                                   276 
286         /* Check nonresident fields. */        !! 277         /* Check some nonresident fields. */
287         if (attr->non_res != 1)                !! 278         if (attr->name_len &&
288                 return NULL;                   !! 279             le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
289                                                !! 280                     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;                   << 
309                                                << 
310         alloc_size = le64_to_cpu(attr->nres.al << 
311         if (data_size > alloc_size)            << 
312                 return NULL;                   << 
313                                                << 
314         t32 = mi->sbi->cluster_mask;           << 
315         if (alloc_size & t32)                  << 
316                 return NULL;                      281                 return NULL;
                                                   >> 282         }
317                                                   283 
318         if (!attr->nres.svcn && is_attr_ext(at !! 284         if (attr->nres.svcn || !is_attr_ext(attr)) {
319                 /* First segment of sparse/com !! 285                 if (asize + 8 < SIZEOF_NONRESIDENT)
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;              286                         return NULL;
327                                                   287 
328                 if (tot_size > alloc_size)     << 
329                         return NULL;           << 
330         } else {                               << 
331                 if (attr->nres.c_unit)            288                 if (attr->nres.c_unit)
332                         return NULL;              289                         return NULL;
333                                                !! 290         } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
334                 if (alloc_size > mi->sbi->volu !! 291                 return NULL;
335                         return NULL;           << 
336         }                                      << 
337                                                   292 
338         return attr;                              293         return attr;
339 }                                                 294 }
340                                                   295 
341 /*                                                296 /*
342  * mi_find_attr - Find the attribute by type a    297  * mi_find_attr - Find the attribute by type and name and id.
343  */                                               298  */
344 struct ATTRIB *mi_find_attr(struct mft_inode *    299 struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
345                             enum ATTR_TYPE typ    300                             enum ATTR_TYPE type, const __le16 *name,
346                             u8 name_len, const !! 301                             size_t name_len, const __le16 *id)
347 {                                                 302 {
348         u32 type_in = le32_to_cpu(type);          303         u32 type_in = le32_to_cpu(type);
349         u32 atype;                                304         u32 atype;
350                                                   305 
351 next_attr:                                        306 next_attr:
352         attr = mi_enum_attr(mi, attr);            307         attr = mi_enum_attr(mi, attr);
353         if (!attr)                                308         if (!attr)
354                 return NULL;                      309                 return NULL;
355                                                   310 
356         atype = le32_to_cpu(attr->type);          311         atype = le32_to_cpu(attr->type);
357         if (atype > type_in)                      312         if (atype > type_in)
358                 return NULL;                      313                 return NULL;
359                                                   314 
360         if (atype < type_in)                      315         if (atype < type_in)
361                 goto next_attr;                   316                 goto next_attr;
362                                                   317 
363         if (attr->name_len != name_len)           318         if (attr->name_len != name_len)
364                 goto next_attr;                   319                 goto next_attr;
365                                                   320 
366         if (name_len && memcmp(attr_name(attr)    321         if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
367                 goto next_attr;                   322                 goto next_attr;
368                                                   323 
369         if (id && *id != attr->id)                324         if (id && *id != attr->id)
370                 goto next_attr;                   325                 goto next_attr;
371                                                   326 
372         return attr;                              327         return attr;
373 }                                                 328 }
374                                                   329 
375 int mi_write(struct mft_inode *mi, int wait)      330 int mi_write(struct mft_inode *mi, int wait)
376 {                                                 331 {
377         struct MFT_REC *rec;                      332         struct MFT_REC *rec;
378         int err;                                  333         int err;
379         struct ntfs_sb_info *sbi;                 334         struct ntfs_sb_info *sbi;
380                                                   335 
381         if (!mi->dirty)                           336         if (!mi->dirty)
382                 return 0;                         337                 return 0;
383                                                   338 
384         sbi = mi->sbi;                            339         sbi = mi->sbi;
385         rec = mi->mrec;                           340         rec = mi->mrec;
386                                                   341 
387         err = ntfs_write_bh(sbi, &rec->rhdr, &    342         err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
388         if (err)                                  343         if (err)
389                 return err;                       344                 return err;
390                                                   345 
391         if (mi->rno < sbi->mft.recs_mirr)         346         if (mi->rno < sbi->mft.recs_mirr)
392                 sbi->flags |= NTFS_FLAGS_MFTMI    347                 sbi->flags |= NTFS_FLAGS_MFTMIRR;
393                                                   348 
394         mi->dirty = false;                        349         mi->dirty = false;
395                                                   350 
396         return 0;                                 351         return 0;
397 }                                                 352 }
398                                                   353 
399 int mi_format_new(struct mft_inode *mi, struct    354 int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
400                   __le16 flags, bool is_mft)      355                   __le16 flags, bool is_mft)
401 {                                                 356 {
402         int err;                                  357         int err;
403         u16 seq = 1;                              358         u16 seq = 1;
404         struct MFT_REC *rec;                      359         struct MFT_REC *rec;
405         u64 vbo = (u64)rno << sbi->record_bits    360         u64 vbo = (u64)rno << sbi->record_bits;
406                                                   361 
407         err = mi_init(mi, sbi, rno);              362         err = mi_init(mi, sbi, rno);
408         if (err)                                  363         if (err)
409                 return err;                       364                 return err;
410                                                   365 
411         rec = mi->mrec;                           366         rec = mi->mrec;
412                                                   367 
413         if (rno == MFT_REC_MFT) {                 368         if (rno == MFT_REC_MFT) {
414                 ;                                 369                 ;
415         } else if (rno < MFT_REC_FREE) {          370         } else if (rno < MFT_REC_FREE) {
416                 seq = rno;                        371                 seq = rno;
417         } else if (rno >= sbi->mft.used) {        372         } else if (rno >= sbi->mft.used) {
418                 ;                                 373                 ;
419         } else if (mi_read(mi, is_mft)) {         374         } else if (mi_read(mi, is_mft)) {
420                 ;                                 375                 ;
421         } else if (rec->rhdr.sign == NTFS_FILE    376         } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
422                 /* Record is reused. Update it    377                 /* Record is reused. Update its sequence number. */
423                 seq = le16_to_cpu(rec->seq) +     378                 seq = le16_to_cpu(rec->seq) + 1;
424                 if (!seq)                         379                 if (!seq)
425                         seq = 1;                  380                         seq = 1;
426         }                                         381         }
427                                                   382 
428         memcpy(rec, sbi->new_rec, sbi->record_    383         memcpy(rec, sbi->new_rec, sbi->record_size);
429                                                   384 
430         rec->seq = cpu_to_le16(seq);              385         rec->seq = cpu_to_le16(seq);
431         rec->flags = RECORD_FLAG_IN_USE | flag    386         rec->flags = RECORD_FLAG_IN_USE | flags;
432         if (MFTRECORD_FIXUP_OFFSET == MFTRECOR << 
433                 rec->mft_record = cpu_to_le32( << 
434                                                   387 
435         mi->dirty = true;                         388         mi->dirty = true;
436                                                   389 
437         if (!mi->nb.nbufs) {                      390         if (!mi->nb.nbufs) {
438                 struct ntfs_inode *ni = sbi->m    391                 struct ntfs_inode *ni = sbi->mft.ni;
439                 bool lock = false;                392                 bool lock = false;
440                                                   393 
441                 if (is_mounted(sbi) && !is_mft    394                 if (is_mounted(sbi) && !is_mft) {
442                         down_read(&ni->file.ru    395                         down_read(&ni->file.run_lock);
443                         lock = true;              396                         lock = true;
444                 }                                 397                 }
445                                                   398 
446                 err = ntfs_get_bh(sbi, &ni->fi    399                 err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
447                                   &mi->nb);       400                                   &mi->nb);
448                 if (lock)                         401                 if (lock)
449                         up_read(&ni->file.run_    402                         up_read(&ni->file.run_lock);
450         }                                         403         }
451                                                   404 
452         return err;                               405         return err;
453 }                                                 406 }
454                                                   407 
455 /*                                                408 /*
                                                   >> 409  * mi_mark_free - Mark record as unused and marks it as free in bitmap.
                                                   >> 410  */
                                                   >> 411 void mi_mark_free(struct mft_inode *mi)
                                                   >> 412 {
                                                   >> 413         CLST rno = mi->rno;
                                                   >> 414         struct ntfs_sb_info *sbi = mi->sbi;
                                                   >> 415 
                                                   >> 416         if (rno >= MFT_REC_RESERVED && rno < MFT_REC_FREE) {
                                                   >> 417                 ntfs_clear_mft_tail(sbi, rno, rno + 1);
                                                   >> 418                 mi->dirty = false;
                                                   >> 419                 return;
                                                   >> 420         }
                                                   >> 421 
                                                   >> 422         if (mi->mrec) {
                                                   >> 423                 clear_rec_inuse(mi->mrec);
                                                   >> 424                 mi->dirty = true;
                                                   >> 425                 mi_write(mi, 0);
                                                   >> 426         }
                                                   >> 427         ntfs_mark_rec_free(sbi, rno);
                                                   >> 428 }
                                                   >> 429 
                                                   >> 430 /*
456  * mi_insert_attr - Reserve space for new attr    431  * mi_insert_attr - Reserve space for new attribute.
457  *                                                432  *
458  * Return: Not full constructed attribute or N    433  * Return: Not full constructed attribute or NULL if not possible to create.
459  */                                               434  */
460 struct ATTRIB *mi_insert_attr(struct mft_inode    435 struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
461                               const __le16 *na    436                               const __le16 *name, u8 name_len, u32 asize,
462                               u16 name_off)       437                               u16 name_off)
463 {                                                 438 {
464         size_t tail;                              439         size_t tail;
465         struct ATTRIB *attr;                      440         struct ATTRIB *attr;
466         __le16 id;                                441         __le16 id;
467         struct MFT_REC *rec = mi->mrec;           442         struct MFT_REC *rec = mi->mrec;
468         struct ntfs_sb_info *sbi = mi->sbi;       443         struct ntfs_sb_info *sbi = mi->sbi;
469         u32 used = le32_to_cpu(rec->used);        444         u32 used = le32_to_cpu(rec->used);
470         const u16 *upcase = sbi->upcase;          445         const u16 *upcase = sbi->upcase;
                                                   >> 446         int diff;
471                                                   447 
472         /* Can we insert mi attribute? */         448         /* Can we insert mi attribute? */
473         if (used + asize > sbi->record_size)   !! 449         if (used + asize > mi->sbi->record_size)
474                 return NULL;                      450                 return NULL;
475                                                   451 
476         /*                                        452         /*
477          * Scan through the list of attributes    453          * Scan through the list of attributes to find the point
478          * at which we should insert it.          454          * at which we should insert it.
479          */                                       455          */
480         attr = NULL;                              456         attr = NULL;
481         while ((attr = mi_enum_attr(mi, attr))    457         while ((attr = mi_enum_attr(mi, attr))) {
482                 int diff = compare_attr(attr,  !! 458                 diff = compare_attr(attr, type, name, name_len, upcase);
483                                                !! 459                 if (diff > 0)
                                                   >> 460                         break;
484                 if (diff < 0)                     461                 if (diff < 0)
485                         continue;                 462                         continue;
486                                                   463 
487                 if (!diff && !is_attr_indexed( !! 464                 if (!is_attr_indexed(attr))
488                         return NULL;              465                         return NULL;
489                 break;                            466                 break;
490         }                                         467         }
491                                                   468 
492         if (!attr) {                              469         if (!attr) {
493                 /* Append. */                  !! 470                 tail = 8; /* Not used, just to suppress warning. */
494                 tail = 8;                      << 
495                 attr = Add2Ptr(rec, used - 8);    471                 attr = Add2Ptr(rec, used - 8);
496         } else {                                  472         } else {
497                 /* Insert before 'attr'. */    << 
498                 tail = used - PtrOffset(rec, a    473                 tail = used - PtrOffset(rec, attr);
499         }                                         474         }
500                                                   475 
501         id = mi_new_attt_id(mi);                  476         id = mi_new_attt_id(mi);
502                                                   477 
503         memmove(Add2Ptr(attr, asize), attr, ta    478         memmove(Add2Ptr(attr, asize), attr, tail);
504         memset(attr, 0, asize);                   479         memset(attr, 0, asize);
505                                                   480 
506         attr->type = type;                        481         attr->type = type;
507         attr->size = cpu_to_le32(asize);          482         attr->size = cpu_to_le32(asize);
508         attr->name_len = name_len;                483         attr->name_len = name_len;
509         attr->name_off = cpu_to_le16(name_off)    484         attr->name_off = cpu_to_le16(name_off);
510         attr->id = id;                            485         attr->id = id;
511                                                   486 
512         memmove(Add2Ptr(attr, name_off), name,    487         memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
513         rec->used = cpu_to_le32(used + asize);    488         rec->used = cpu_to_le32(used + asize);
514                                                   489 
515         mi->dirty = true;                         490         mi->dirty = true;
516                                                   491 
517         return attr;                              492         return attr;
518 }                                                 493 }
519                                                   494 
520 /*                                                495 /*
521  * mi_remove_attr - Remove the attribute from     496  * mi_remove_attr - Remove the attribute from record.
522  *                                                497  *
523  * NOTE: The source attr will point to next at    498  * NOTE: The source attr will point to next attribute.
524  */                                               499  */
525 bool mi_remove_attr(struct ntfs_inode *ni, str    500 bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
526                     struct ATTRIB *attr)          501                     struct ATTRIB *attr)
527 {                                                 502 {
528         struct MFT_REC *rec = mi->mrec;           503         struct MFT_REC *rec = mi->mrec;
529         u32 aoff = PtrOffset(rec, attr);          504         u32 aoff = PtrOffset(rec, attr);
530         u32 used = le32_to_cpu(rec->used);        505         u32 used = le32_to_cpu(rec->used);
531         u32 asize = le32_to_cpu(attr->size);      506         u32 asize = le32_to_cpu(attr->size);
532                                                   507 
533         if (aoff + asize > used)                  508         if (aoff + asize > used)
534                 return false;                     509                 return false;
535                                                   510 
536         if (ni && is_attr_indexed(attr) && att    511         if (ni && is_attr_indexed(attr) && attr->type == ATTR_NAME) {
537                 u16 links = le16_to_cpu(ni->mi    512                 u16 links = le16_to_cpu(ni->mi.mrec->hard_links);
538                 if (!links) {                     513                 if (!links) {
539                         /* minor error. Not cr    514                         /* minor error. Not critical. */
540                 } else {                          515                 } else {
541                         ni->mi.mrec->hard_link    516                         ni->mi.mrec->hard_links = cpu_to_le16(links - 1);
542                         ni->mi.dirty = true;      517                         ni->mi.dirty = true;
543                 }                                 518                 }
544         }                                         519         }
545                                                   520 
546         used -= asize;                            521         used -= asize;
547         memmove(attr, Add2Ptr(attr, asize), us    522         memmove(attr, Add2Ptr(attr, asize), used - aoff);
548         rec->used = cpu_to_le32(used);            523         rec->used = cpu_to_le32(used);
549         mi->dirty = true;                         524         mi->dirty = true;
550                                                   525 
551         return true;                              526         return true;
552 }                                                 527 }
553                                                   528 
554 /* bytes = "new attribute size" - "old attribu    529 /* bytes = "new attribute size" - "old attribute size" */
555 bool mi_resize_attr(struct mft_inode *mi, stru    530 bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
556 {                                                 531 {
557         struct MFT_REC *rec = mi->mrec;           532         struct MFT_REC *rec = mi->mrec;
558         u32 aoff = PtrOffset(rec, attr);          533         u32 aoff = PtrOffset(rec, attr);
559         u32 total, used = le32_to_cpu(rec->use    534         u32 total, used = le32_to_cpu(rec->used);
560         u32 nsize, asize = le32_to_cpu(attr->s    535         u32 nsize, asize = le32_to_cpu(attr->size);
561         u32 rsize = le32_to_cpu(attr->res.data    536         u32 rsize = le32_to_cpu(attr->res.data_size);
562         int tail = (int)(used - aoff - asize);    537         int tail = (int)(used - aoff - asize);
563         int dsize;                                538         int dsize;
564         char *next;                               539         char *next;
565                                                   540 
566         if (tail < 0 || aoff >= used)             541         if (tail < 0 || aoff >= used)
567                 return false;                     542                 return false;
568                                                   543 
569         if (!bytes)                               544         if (!bytes)
570                 return true;                      545                 return true;
571                                                   546 
572         total = le32_to_cpu(rec->total);          547         total = le32_to_cpu(rec->total);
573         next = Add2Ptr(attr, asize);              548         next = Add2Ptr(attr, asize);
574                                                   549 
575         if (bytes > 0) {                          550         if (bytes > 0) {
576                 dsize = ALIGN(bytes, 8);          551                 dsize = ALIGN(bytes, 8);
577                 if (used + dsize > total)         552                 if (used + dsize > total)
578                         return false;             553                         return false;
579                 nsize = asize + dsize;            554                 nsize = asize + dsize;
580                 /* Move tail */                   555                 /* Move tail */
581                 memmove(next + dsize, next, ta    556                 memmove(next + dsize, next, tail);
582                 memset(next, 0, dsize);           557                 memset(next, 0, dsize);
583                 used += dsize;                    558                 used += dsize;
584                 rsize += dsize;                   559                 rsize += dsize;
585         } else {                                  560         } else {
586                 dsize = ALIGN(-bytes, 8);         561                 dsize = ALIGN(-bytes, 8);
587                 if (dsize > asize)                562                 if (dsize > asize)
588                         return false;             563                         return false;
589                 nsize = asize - dsize;            564                 nsize = asize - dsize;
590                 memmove(next - dsize, next, ta    565                 memmove(next - dsize, next, tail);
591                 used -= dsize;                    566                 used -= dsize;
592                 rsize -= dsize;                   567                 rsize -= dsize;
593         }                                         568         }
594                                                   569 
595         rec->used = cpu_to_le32(used);            570         rec->used = cpu_to_le32(used);
596         attr->size = cpu_to_le32(nsize);          571         attr->size = cpu_to_le32(nsize);
597         if (!attr->non_res)                       572         if (!attr->non_res)
598                 attr->res.data_size = cpu_to_l    573                 attr->res.data_size = cpu_to_le32(rsize);
599         mi->dirty = true;                         574         mi->dirty = true;
600                                                   575 
601         return true;                              576         return true;
602 }                                                 577 }
603                                                   578 
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     579 int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
609                  struct runs_tree *run, CLST l    580                  struct runs_tree *run, CLST len)
610 {                                                 581 {
611         int err = 0;                              582         int err = 0;
612         struct ntfs_sb_info *sbi = mi->sbi;       583         struct ntfs_sb_info *sbi = mi->sbi;
613         u32 new_run_size;                         584         u32 new_run_size;
614         CLST plen;                                585         CLST plen;
615         struct MFT_REC *rec = mi->mrec;           586         struct MFT_REC *rec = mi->mrec;
616         CLST svcn = le64_to_cpu(attr->nres.svc    587         CLST svcn = le64_to_cpu(attr->nres.svcn);
617         u32 used = le32_to_cpu(rec->used);        588         u32 used = le32_to_cpu(rec->used);
618         u32 aoff = PtrOffset(rec, attr);          589         u32 aoff = PtrOffset(rec, attr);
619         u32 asize = le32_to_cpu(attr->size);      590         u32 asize = le32_to_cpu(attr->size);
620         char *next = Add2Ptr(attr, asize);        591         char *next = Add2Ptr(attr, asize);
621         u16 run_off = le16_to_cpu(attr->nres.r    592         u16 run_off = le16_to_cpu(attr->nres.run_off);
622         u32 run_size = asize - run_off;           593         u32 run_size = asize - run_off;
623         u32 tail = used - aoff - asize;           594         u32 tail = used - aoff - asize;
624         u32 dsize = sbi->record_size - used;      595         u32 dsize = sbi->record_size - used;
625                                                   596 
626         /* Make a maximum gap in current recor    597         /* Make a maximum gap in current record. */
627         memmove(next + dsize, next, tail);        598         memmove(next + dsize, next, tail);
628                                                   599 
629         /* Pack as much as possible. */           600         /* Pack as much as possible. */
630         err = run_pack(run, svcn, len, Add2Ptr    601         err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
631                        &plen);                    602                        &plen);
632         if (err < 0) {                            603         if (err < 0) {
633                 memmove(next, next + dsize, ta    604                 memmove(next, next + dsize, tail);
634                 return err;                       605                 return err;
635         }                                         606         }
636                                                   607 
637         new_run_size = ALIGN(err, 8);             608         new_run_size = ALIGN(err, 8);
638                                                   609 
639         memmove(next + new_run_size - run_size    610         memmove(next + new_run_size - run_size, next + dsize, tail);
640                                                   611 
641         attr->size = cpu_to_le32(asize + new_r    612         attr->size = cpu_to_le32(asize + new_run_size - run_size);
642         attr->nres.evcn = cpu_to_le64(svcn + p    613         attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
643         rec->used = cpu_to_le32(used + new_run    614         rec->used = cpu_to_le32(used + new_run_size - run_size);
644         mi->dirty = true;                         615         mi->dirty = true;
645                                                   616 
646         return 0;                                 617         return 0;
647 }                                                 618 }
648                                                   619 

~ [ 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