Lines Matching +full:record +full:- +full:size
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project.
5 * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc.
25 * ntfs_map_runlist_nolock - map (a part of) a runlist of an ntfs inode
33 * record. This is needed when ntfs_map_runlist_nolock() encounters unmapped
35 * record mapped, you can specify @ctx as NULL and ntfs_map_runlist_nolock()
44 * m = ctx->mrec;
45 * a = ctx->attr;
46 * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
47 * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
49 * Return 0 on success and -errno on error. There is one special error code
50 * which is not an error as such. This is -ENOENT. It means that @vcn is out
54 * the attribute has zero allocated size, i.e. there simply is no runlist.
57 * returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
60 * In that case PTR_ERR(@ctx->mrec) will give you the error code for
63 * Locking: - The runlist described by @ni must be locked for writing on entry
65 * - If @ctx is NULL, the base mft record of @ni must not be mapped on
67 * - If @ctx is not NULL, the base mft record must be mapped on entry
88 base_ni = ni->ext.base_ntfs_ino; in ntfs_map_runlist_nolock()
96 err = -ENOMEM; in ntfs_map_runlist_nolock()
102 BUG_ON(IS_ERR(ctx->mrec)); in ntfs_map_runlist_nolock()
103 a = ctx->attr; in ntfs_map_runlist_nolock()
104 BUG_ON(!a->non_resident); in ntfs_map_runlist_nolock()
106 end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn); in ntfs_map_runlist_nolock()
107 read_lock_irqsave(&ni->size_lock, flags); in ntfs_map_runlist_nolock()
108 allocated_size_vcn = ni->allocated_size >> in ntfs_map_runlist_nolock()
109 ni->vol->cluster_size_bits; in ntfs_map_runlist_nolock()
110 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_map_runlist_nolock()
111 if (!a->data.non_resident.lowest_vcn && end_vcn <= 0) in ntfs_map_runlist_nolock()
112 end_vcn = allocated_size_vcn - 1; in ntfs_map_runlist_nolock()
116 * that if vcn exceeds the allocated size, we will refuse to in ntfs_map_runlist_nolock()
120 if (vcn >= allocated_size_vcn || (a->type == ni->type && in ntfs_map_runlist_nolock()
121 a->name_length == ni->name_len && in ntfs_map_runlist_nolock()
122 !memcmp((u8*)a + le16_to_cpu(a->name_offset), in ntfs_map_runlist_nolock()
123 ni->name, ni->name_len) && in ntfs_map_runlist_nolock()
124 sle64_to_cpu(a->data.non_resident.lowest_vcn) in ntfs_map_runlist_nolock()
135 * record so we do not accidentally drop changes to the in ntfs_map_runlist_nolock()
136 * mft record when it has not been marked dirty yet. in ntfs_map_runlist_nolock()
140 put_this_page = old_ctx.ntfs_ino->page; in ntfs_map_runlist_nolock()
152 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, in ntfs_map_runlist_nolock()
155 if (err == -ENOENT) in ntfs_map_runlist_nolock()
156 err = -EIO; in ntfs_map_runlist_nolock()
159 BUG_ON(!ctx->attr->non_resident); in ntfs_map_runlist_nolock()
161 a = ctx->attr; in ntfs_map_runlist_nolock()
168 end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1; in ntfs_map_runlist_nolock()
170 err = -ENOENT; in ntfs_map_runlist_nolock()
173 rl = ntfs_mapping_pairs_decompress(ni->vol, a, ni->runlist.rl); in ntfs_map_runlist_nolock()
177 ni->runlist.rl = rl; in ntfs_map_runlist_nolock()
197 if (ctx->ntfs_ino != old_ctx.ntfs_ino) { in ntfs_map_runlist_nolock()
202 if (ctx->base_ntfs_ino && ctx->ntfs_ino != in ntfs_map_runlist_nolock()
203 ctx->base_ntfs_ino) { in ntfs_map_runlist_nolock()
204 unmap_extent_mft_record(ctx->ntfs_ino); in ntfs_map_runlist_nolock()
205 ctx->mrec = ctx->base_mrec; in ntfs_map_runlist_nolock()
206 BUG_ON(!ctx->mrec); in ntfs_map_runlist_nolock()
216 ctx->mrec = map_mft_record( in ntfs_map_runlist_nolock()
222 * return the error code in ctx->mrec. in ntfs_map_runlist_nolock()
228 if (IS_ERR(ctx->mrec)) { in ntfs_map_runlist_nolock()
229 if (PTR_ERR(ctx->mrec) == in ntfs_map_runlist_nolock()
230 -ENOMEM) { in ntfs_map_runlist_nolock()
241 if (ctx->mrec != old_ctx.mrec) { in ntfs_map_runlist_nolock()
242 if (!IS_ERR(ctx->mrec)) in ntfs_map_runlist_nolock()
244 (u8*)ctx->mrec + in ntfs_map_runlist_nolock()
245 ((u8*)old_ctx.attr - in ntfs_map_runlist_nolock()
247 old_ctx.mrec = ctx->mrec; in ntfs_map_runlist_nolock()
254 * case that IS_ERR(ctx->mrec) is true this means we might lose in ntfs_map_runlist_nolock()
255 * some changes to the mft record that had been made between in ntfs_map_runlist_nolock()
258 * enough that the mft record cannot be written out anyway and in ntfs_map_runlist_nolock()
270 * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode
276 * Return 0 on success and -errno on error. There is one special error code
277 * which is not an error as such. This is -ENOENT. It means that @vcn is out
280 * Locking: - The runlist must be unlocked on entry and is unlocked on return.
281 * - This function takes the runlist lock for writing and may modify
288 down_write(&ni->runlist.lock); in ntfs_map_runlist()
290 if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <= in ntfs_map_runlist()
293 up_write(&ni->runlist.lock); in ntfs_map_runlist()
298 * ntfs_attr_vcn_to_lcn_nolock - convert a vcn into a lcn given an ntfs inode
322 * Locking: - The runlist must be locked on entry and is left locked on return.
323 * - If @write_locked is 'false', i.e. the runlist is locked for reading,
336 ni->mft_no, (unsigned long long)vcn, in ntfs_attr_vcn_to_lcn_nolock()
340 if (!ni->runlist.rl) { in ntfs_attr_vcn_to_lcn_nolock()
341 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_vcn_to_lcn_nolock()
342 if (!ni->allocated_size) { in ntfs_attr_vcn_to_lcn_nolock()
343 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_vcn_to_lcn_nolock()
346 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_vcn_to_lcn_nolock()
350 lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn); in ntfs_attr_vcn_to_lcn_nolock()
362 up_read(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
363 down_write(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
364 if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != in ntfs_attr_vcn_to_lcn_nolock()
366 up_write(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
367 down_read(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
373 up_write(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
374 down_read(&ni->runlist.lock); in ntfs_attr_vcn_to_lcn_nolock()
380 if (err == -ENOENT) in ntfs_attr_vcn_to_lcn_nolock()
382 else if (err == -ENOMEM) in ntfs_attr_vcn_to_lcn_nolock()
388 ntfs_error(ni->vol->sb, "Failed with error code %lli.", in ntfs_attr_vcn_to_lcn_nolock()
394 * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode
406 * record. This is needed when ntfs_attr_find_vcn_nolock() encounters unmapped
408 * record mapped, you can specify @ctx as NULL and ntfs_attr_find_vcn_nolock()
417 * m = ctx->mrec;
418 * a = ctx->attr;
419 * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
420 * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
426 * ERR_PTR(-errno) on error. You need to test the return value with IS_ERR()
431 * -ENOENT - No such vcn in the runlist, i.e. @vcn is out of bounds.
432 * -ENOMEM - Not enough memory to map runlist.
433 * -EIO - Critical error (runlist/file is corrupt, i/o error, etc).
436 * returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
439 * In that case PTR_ERR(@ctx->mrec) will give you the error code for
442 * Locking: - The runlist described by @ni must be locked for writing on entry
445 * - If @ctx is NULL, the base mft record of @ni must not be mapped on
447 * - If @ctx is not NULL, the base mft record must be mapped on entry
460 ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out"); in ntfs_attr_find_vcn_nolock()
463 if (!ni->runlist.rl) { in ntfs_attr_find_vcn_nolock()
464 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_find_vcn_nolock()
465 if (!ni->allocated_size) { in ntfs_attr_find_vcn_nolock()
466 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_find_vcn_nolock()
467 return ERR_PTR(-ENOENT); in ntfs_attr_find_vcn_nolock()
469 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_find_vcn_nolock()
472 rl = ni->runlist.rl; in ntfs_attr_find_vcn_nolock()
474 while (likely(rl->length)) { in ntfs_attr_find_vcn_nolock()
476 if (likely(rl->lcn >= LCN_HOLE)) { in ntfs_attr_find_vcn_nolock()
484 if (likely(rl->lcn != LCN_RL_NOT_MAPPED)) { in ntfs_attr_find_vcn_nolock()
485 if (likely(rl->lcn == LCN_ENOENT)) in ntfs_attr_find_vcn_nolock()
486 err = -ENOENT; in ntfs_attr_find_vcn_nolock()
488 err = -EIO; in ntfs_attr_find_vcn_nolock()
496 if (IS_ERR(ctx->mrec)) in ntfs_attr_find_vcn_nolock()
497 err = PTR_ERR(ctx->mrec); in ntfs_attr_find_vcn_nolock()
509 if (err == -EINVAL) in ntfs_attr_find_vcn_nolock()
510 err = -EIO; in ntfs_attr_find_vcn_nolock()
512 err = -EIO; in ntfs_attr_find_vcn_nolock()
513 if (err != -ENOENT) in ntfs_attr_find_vcn_nolock()
514 ntfs_error(ni->vol->sb, "Failed with error code %i.", err); in ntfs_attr_find_vcn_nolock()
519 * ntfs_attr_find - find (next) attribute in mft record
526 * @ctx: search context with mft record and attribute to search from
532 * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
535 * If the attribute is found, ntfs_attr_find() returns 0 and @ctx->attr will
538 * If the attribute is not found, ntfs_attr_find() returns -ENOENT and
539 * @ctx->attr will point to the attribute before which the attribute being
542 * On actual error, ntfs_attr_find() returns -EIO. In this case @ctx->attr is
545 * If @ctx->is_first is 'true', the search begins with @ctx->attr itself. If it
546 * is 'false', the search begins after @ctx->attr.
549 * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
550 * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
561 * ntfs_attr_find() only searches the specified mft record and it ignores the
565 * use ntfs_attr_find() to search for extent records of non-resident
567 * attribute list attribute only. - Note that it is possible that the first
569 * mft record, so do not rely on being able to find the first extent in the
570 * base mft record.
573 * non-resident as this most likely will result in a crash!
580 ntfs_volume *vol = ctx->ntfs_ino->vol; in ntfs_attr_find()
581 ntfschar *upcase = vol->upcase; in ntfs_attr_find()
582 u32 upcase_len = vol->upcase_len; in ntfs_attr_find()
585 * Iterate over attributes in mft record starting at @ctx->attr, or the in ntfs_attr_find()
586 * attribute following that, if @ctx->is_first is 'true'. in ntfs_attr_find()
588 if (ctx->is_first) { in ntfs_attr_find()
589 a = ctx->attr; in ntfs_attr_find()
590 ctx->is_first = false; in ntfs_attr_find()
592 a = (ATTR_RECORD*)((u8*)ctx->attr + in ntfs_attr_find()
593 le32_to_cpu(ctx->attr->length)); in ntfs_attr_find()
594 for (;; a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length))) { in ntfs_attr_find()
595 u8 *mrec_end = (u8 *)ctx->mrec + in ntfs_attr_find()
596 le32_to_cpu(ctx->mrec->bytes_allocated); in ntfs_attr_find()
600 if ((u8 *)a < (u8 *)ctx->mrec) in ntfs_attr_find()
603 /* check whether Attribute Record Header is within bounds */ in ntfs_attr_find()
609 name_end = (u8 *)a + le16_to_cpu(a->name_offset) + in ntfs_attr_find()
610 a->name_length * sizeof(ntfschar); in ntfs_attr_find()
614 ctx->attr = a; in ntfs_attr_find()
615 if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) || in ntfs_attr_find()
616 a->type == AT_END)) in ntfs_attr_find()
617 return -ENOENT; in ntfs_attr_find()
618 if (unlikely(!a->length)) in ntfs_attr_find()
622 if ((u8 *)a + le32_to_cpu(a->length) < (u8 *)a) in ntfs_attr_find()
625 if ((u8 *)a + le32_to_cpu(a->length) > mrec_end) in ntfs_attr_find()
628 if (a->type != type) in ntfs_attr_find()
636 if (a->name_length) in ntfs_attr_find()
637 return -ENOENT; in ntfs_attr_find()
639 (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), in ntfs_attr_find()
640 a->name_length, ic, upcase, upcase_len)) { in ntfs_attr_find()
645 le16_to_cpu(a->name_offset)), in ntfs_attr_find()
646 a->name_length, 1, IGNORE_CASE, in ntfs_attr_find()
649 * If @name collates before a->name, there is no in ntfs_attr_find()
652 if (rc == -1) in ntfs_attr_find()
653 return -ENOENT; in ntfs_attr_find()
659 le16_to_cpu(a->name_offset)), in ntfs_attr_find()
660 a->name_length, 1, CASE_SENSITIVE, in ntfs_attr_find()
662 if (rc == -1) in ntfs_attr_find()
663 return -ENOENT; in ntfs_attr_find()
679 a->data.resident.value_offset), in ntfs_attr_find()
681 a->data.resident.value_length))); in ntfs_attr_find()
690 a->data.resident.value_length); in ntfs_attr_find()
694 return -ENOENT; in ntfs_attr_find()
696 return -ENOENT; in ntfs_attr_find()
699 ntfs_error(vol->sb, "Inode is corrupt. Run chkdsk."); in ntfs_attr_find()
701 return -EIO; in ntfs_attr_find()
705 * load_attribute_list - load an attribute list into memory
709 * @size: size of the destination buffer in bytes
710 * @initialized_size: initialized size of the attribute list
713 * the linear buffer @al. The maximum number of bytes copied to @al is @size
714 * bytes. Note, @size does not need to be a multiple of the cluster size. If
715 * @initialized_size is less than @size, the region in @al between
716 * @initialized_size and @size will be zeroed and not read from disk.
718 * Return 0 on success or -errno on error.
721 const s64 size, const s64 initialized_size) in load_attribute_list() argument
735 if (!vol || !runlist || !al || size <= 0 || initialized_size < 0 || in load_attribute_list()
736 initialized_size > size) in load_attribute_list()
737 return -EINVAL; in load_attribute_list()
739 memset(al, 0, size); in load_attribute_list()
742 sb = vol->sb; in load_attribute_list()
743 block_size = sb->s_blocksize; in load_attribute_list()
744 block_size_bits = sb->s_blocksize_bits; in load_attribute_list()
745 down_read(&runlist->lock); in load_attribute_list()
746 rl = runlist->rl; in load_attribute_list()
753 while (rl->length) { in load_attribute_list()
754 lcn = ntfs_rl_vcn_to_lcn(rl, rl->vcn); in load_attribute_list()
756 (unsigned long long)rl->vcn, in load_attribute_list()
764 block = lcn << vol->cluster_size_bits >> block_size_bits; in load_attribute_list()
766 max_block = block + (rl->length << vol->cluster_size_bits >> in load_attribute_list()
779 memcpy(al, bh->b_data, block_size); in load_attribute_list()
785 if (initialized_size < size) { in load_attribute_list()
787 memset(al_start + initialized_size, 0, size - initialized_size); in load_attribute_list()
790 up_read(&runlist->lock); in load_attribute_list()
802 memcpy(al, bh->b_data, al_end - al); in load_attribute_list()
804 if (initialized_size < size) in load_attribute_list()
813 err = -EIO; in load_attribute_list()
818 * ntfs_external_attr_find - find an attribute in the attribute list of an inode
823 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
826 * @ctx: search context with mft record and attribute to search from
832 * attribute list entry. Having found the entry, map the mft record if the
833 * attribute is in a different mft record/inode, ntfs_attr_find() the attribute
836 * On first search @ctx->ntfs_ino must be the base mft record and @ctx must
838 * calls @ctx->ntfs_ino can be any extent inode, too (@ctx->base_ntfs_ino is
841 * After finishing with the attribute/mft record you need to call
846 * @ctx->attr will point to the found attribute. @ctx->mrec will point to the
847 * mft record in which @ctx->attr is located and @ctx->al_entry will point to
850 * If the attribute is not found, ntfs_external_attr_find() returns -ENOENT and
851 * @ctx->attr will point to the attribute in the base mft record before which
853 * were to be desired. @ctx->mrec will point to the mft record in which
854 * @ctx->attr is located and @ctx->al_entry will point to the attribute list
859 * @ctx->mrec (the base mft record) and if there is not enough space, the
860 * attribute should be placed in a newly allocated extent mft record. The
862 * attribute list attribute at @ctx->al_entry.
864 * On actual error, ntfs_external_attr_find() returns -EIO. In this case
865 * @ctx->attr is undefined and in particular do not rely on it not changing.
882 ni = ctx->ntfs_ino; in ntfs_external_attr_find()
883 base_ni = ctx->base_ntfs_ino; in ntfs_external_attr_find()
884 ntfs_debug("Entering for inode 0x%lx, type 0x%x.", ni->mft_no, type); in ntfs_external_attr_find()
886 /* First call happens with the base mft record. */ in ntfs_external_attr_find()
887 base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino; in ntfs_external_attr_find()
888 ctx->base_mrec = ctx->mrec; in ntfs_external_attr_find()
891 ctx->base_attr = ctx->attr; in ntfs_external_attr_find()
894 vol = base_ni->vol; in ntfs_external_attr_find()
895 al_start = base_ni->attr_list; in ntfs_external_attr_find()
896 al_end = al_start + base_ni->attr_list_size; in ntfs_external_attr_find()
897 if (!ctx->al_entry) in ntfs_external_attr_find()
898 ctx->al_entry = (ATTR_LIST_ENTRY*)al_start; in ntfs_external_attr_find()
900 * Iterate over entries in attribute list starting at @ctx->al_entry, in ntfs_external_attr_find()
901 * or the entry following that, if @ctx->is_first is 'true'. in ntfs_external_attr_find()
903 if (ctx->is_first) { in ntfs_external_attr_find()
904 al_entry = ctx->al_entry; in ntfs_external_attr_find()
905 ctx->is_first = false; in ntfs_external_attr_find()
907 al_entry = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry + in ntfs_external_attr_find()
908 le16_to_cpu(ctx->al_entry->length)); in ntfs_external_attr_find()
911 if ((u8*)al_entry < base_ni->attr_list || in ntfs_external_attr_find()
914 ctx->al_entry = al_entry; in ntfs_external_attr_find()
918 if (!al_entry->length) in ntfs_external_attr_find()
921 le16_to_cpu(al_entry->length) > al_end) in ntfs_external_attr_find()
924 le16_to_cpu(al_entry->length)); in ntfs_external_attr_find()
925 if (le32_to_cpu(al_entry->type) > le32_to_cpu(type)) in ntfs_external_attr_find()
927 if (type != al_entry->type) in ntfs_external_attr_find()
933 al_name_len = al_entry->name_length; in ntfs_external_attr_find()
934 al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset); in ntfs_external_attr_find()
939 name_len, ic, vol->upcase, vol->upcase_len)) { in ntfs_external_attr_find()
944 vol->upcase, vol->upcase_len); in ntfs_external_attr_find()
949 if (rc == -1) in ntfs_external_attr_find()
964 vol->upcase, vol->upcase_len); in ntfs_external_attr_find()
965 if (rc == -1) in ntfs_external_attr_find()
979 next_al_entry->length) <= al_end && in ntfs_external_attr_find()
980 sle64_to_cpu(next_al_entry->lowest_vcn) <= in ntfs_external_attr_find()
982 next_al_entry->type == al_entry->type && in ntfs_external_attr_find()
983 next_al_entry->name_length == al_name_len && in ntfs_external_attr_find()
986 next_al_entry->name_offset), in ntfs_external_attr_find()
987 next_al_entry->name_length, in ntfs_external_attr_find()
989 vol->upcase, vol->upcase_len)) in ntfs_external_attr_find()
991 if (MREF_LE(al_entry->mft_reference) == ni->mft_no) { in ntfs_external_attr_find()
992 if (MSEQNO_LE(al_entry->mft_reference) != ni->seq_no) { in ntfs_external_attr_find()
993 ntfs_error(vol->sb, "Found stale mft " in ntfs_external_attr_find()
996 base_ni->mft_no, es); in ntfs_external_attr_find()
997 err = -EIO; in ntfs_external_attr_find()
1001 /* If there is a mapped record unmap it first. */ in ntfs_external_attr_find()
1004 /* Do we want the base record back? */ in ntfs_external_attr_find()
1005 if (MREF_LE(al_entry->mft_reference) == in ntfs_external_attr_find()
1006 base_ni->mft_no) { in ntfs_external_attr_find()
1007 ni = ctx->ntfs_ino = base_ni; in ntfs_external_attr_find()
1008 ctx->mrec = ctx->base_mrec; in ntfs_external_attr_find()
1010 /* We want an extent record. */ in ntfs_external_attr_find()
1011 ctx->mrec = map_extent_mft_record(base_ni, in ntfs_external_attr_find()
1013 al_entry->mft_reference), &ni); in ntfs_external_attr_find()
1014 if (IS_ERR(ctx->mrec)) { in ntfs_external_attr_find()
1015 ntfs_error(vol->sb, "Failed to map " in ntfs_external_attr_find()
1016 "extent mft record " in ntfs_external_attr_find()
1019 MREF_LE(al_entry-> in ntfs_external_attr_find()
1021 base_ni->mft_no, es); in ntfs_external_attr_find()
1022 err = PTR_ERR(ctx->mrec); in ntfs_external_attr_find()
1023 if (err == -ENOENT) in ntfs_external_attr_find()
1024 err = -EIO; in ntfs_external_attr_find()
1029 ctx->ntfs_ino = ni; in ntfs_external_attr_find()
1031 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + in ntfs_external_attr_find()
1032 le16_to_cpu(ctx->mrec->attrs_offset)); in ntfs_external_attr_find()
1035 * ctx->vfs_ino, ctx->mrec, and ctx->attr now point to the in ntfs_external_attr_find()
1036 * mft record containing the attribute represented by the in ntfs_external_attr_find()
1041 * attribute in this mft record but this would be less in ntfs_external_attr_find()
1047 * worth re-implementing a simplified ntfs_attr_find() here. in ntfs_external_attr_find()
1049 a = ctx->attr; in ntfs_external_attr_find()
1055 if ((u8*)a < (u8*)ctx->mrec || (u8*)a > (u8*)ctx->mrec + in ntfs_external_attr_find()
1056 le32_to_cpu(ctx->mrec->bytes_allocated)) in ntfs_external_attr_find()
1058 if (a->type == AT_END) in ntfs_external_attr_find()
1060 if (!a->length) in ntfs_external_attr_find()
1062 if (al_entry->instance != a->instance) in ntfs_external_attr_find()
1066 * attribute list entry and the attribute record, there is in ntfs_external_attr_find()
1069 if (al_entry->type != a->type) in ntfs_external_attr_find()
1072 le16_to_cpu(a->name_offset)), a->name_length, in ntfs_external_attr_find()
1074 vol->upcase, vol->upcase_len)) in ntfs_external_attr_find()
1076 ctx->attr = a; in ntfs_external_attr_find()
1081 if (!val || (!a->non_resident && le32_to_cpu( in ntfs_external_attr_find()
1082 a->data.resident.value_length) == val_len && in ntfs_external_attr_find()
1084 le16_to_cpu(a->data.resident.value_offset), in ntfs_external_attr_find()
1090 /* Proceed to the next attribute in the current mft record. */ in ntfs_external_attr_find()
1091 a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length)); in ntfs_external_attr_find()
1095 ntfs_error(vol->sb, "Base inode 0x%lx contains corrupt " in ntfs_external_attr_find()
1096 "attribute list attribute.%s", base_ni->mft_no, in ntfs_external_attr_find()
1098 err = -EIO; in ntfs_external_attr_find()
1103 ctx->ntfs_ino = base_ni; in ntfs_external_attr_find()
1104 ctx->mrec = ctx->base_mrec; in ntfs_external_attr_find()
1105 ctx->attr = ctx->base_attr; in ntfs_external_attr_find()
1107 if (err != -ENOMEM) in ntfs_external_attr_find()
1113 * use ntfs_attr_find() to seek to the end of the base mft record. in ntfs_external_attr_find()
1122 * @ctx->mrec and @ctx->attr indicate the position at which the in ntfs_external_attr_find()
1123 * attribute should be inserted in the base mft record. Since we also in ntfs_external_attr_find()
1124 * want to preserve @ctx->al_entry we cannot reinitialize the search in ntfs_external_attr_find()
1126 * @ctx->al_entry to NULL. Thus we do the necessary bits manually (see in ntfs_external_attr_find()
1128 * @ctx->al_entry as the remaining fields (base_*) are identical to in ntfs_external_attr_find()
1129 * their non base_ counterparts and we cannot set @ctx->base_attr in ntfs_external_attr_find()
1130 * correctly yet as we do not know what @ctx->attr will be set to by in ntfs_external_attr_find()
1135 ctx->mrec = ctx->base_mrec; in ntfs_external_attr_find()
1136 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + in ntfs_external_attr_find()
1137 le16_to_cpu(ctx->mrec->attrs_offset)); in ntfs_external_attr_find()
1138 ctx->is_first = true; in ntfs_external_attr_find()
1139 ctx->ntfs_ino = base_ni; in ntfs_external_attr_find()
1140 ctx->base_ntfs_ino = NULL; in ntfs_external_attr_find()
1141 ctx->base_mrec = NULL; in ntfs_external_attr_find()
1142 ctx->base_attr = NULL; in ntfs_external_attr_find()
1144 * In case there are multiple matches in the base mft record, need to in ntfs_external_attr_find()
1159 * ntfs_attr_lookup - find an attribute in an ntfs inode
1164 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
1167 * @ctx: search context with mft record and attribute to search from
1169 * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
1170 * be the base mft record and @ctx must have been obtained from a call to
1176 * After finishing with the attribute/mft record you need to call
1180 * Return 0 if the search was successful and -errno if not.
1182 * When 0, @ctx->attr is the found attribute and it is in mft record
1183 * @ctx->mrec. If an attribute list attribute is present, @ctx->al_entry is
1186 * When -ENOENT, @ctx->attr is the attribute which collates just after the
1188 * mft record this is the correct place to insert it into. If an attribute
1189 * list attribute is present, @ctx->al_entry is the attribute list entry which
1191 * for, i.e. if one wants to add the attribute to the mft record this is the
1194 * When -errno != -ENOENT, an error occurred during the lookup. @ctx->attr is
1205 BUG_ON(IS_ERR(ctx->mrec)); in ntfs_attr_lookup()
1206 if (ctx->base_ntfs_ino) in ntfs_attr_lookup()
1207 base_ni = ctx->base_ntfs_ino; in ntfs_attr_lookup()
1209 base_ni = ctx->ntfs_ino; in ntfs_attr_lookup()
1220 * ntfs_attr_init_search_ctx - initialize an attribute search context
1223 * @mrec: mft record with which to initialize the search context
1234 le16_to_cpu(mrec->attrs_offset)), in ntfs_attr_init_search_ctx()
1241 * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
1245 * extent mft record if present, and initialize the search context again.
1252 if (likely(!ctx->base_ntfs_ino)) { in ntfs_attr_reinit_search_ctx()
1254 ctx->is_first = true; in ntfs_attr_reinit_search_ctx()
1256 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + in ntfs_attr_reinit_search_ctx()
1257 le16_to_cpu(ctx->mrec->attrs_offset)); in ntfs_attr_reinit_search_ctx()
1260 * can leave it set despite having zeroed ctx->base_ntfs_ino. in ntfs_attr_reinit_search_ctx()
1262 ctx->al_entry = NULL; in ntfs_attr_reinit_search_ctx()
1265 if (ctx->ntfs_ino != ctx->base_ntfs_ino) in ntfs_attr_reinit_search_ctx()
1266 unmap_extent_mft_record(ctx->ntfs_ino); in ntfs_attr_reinit_search_ctx()
1267 ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec); in ntfs_attr_reinit_search_ctx()
1272 * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
1274 * @mrec: mft record with which to initialize the search context
1290 * ntfs_attr_put_search_ctx - release an attribute search context
1294 * mft record if present.
1298 if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino) in ntfs_attr_put_search_ctx()
1299 unmap_extent_mft_record(ctx->ntfs_ino); in ntfs_attr_put_search_ctx()
1307 * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
1311 * Search for the attribute definition record corresponding to the attribute
1314 * Return the attribute type definition record if found and NULL if not found.
1321 BUG_ON(!vol->attrdef); in ntfs_attr_find_in_attrdef()
1323 for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef < in ntfs_attr_find_in_attrdef()
1324 vol->attrdef_size && ad->type; ++ad) { in ntfs_attr_find_in_attrdef()
1326 if (likely(le32_to_cpu(ad->type) < le32_to_cpu(type))) in ntfs_attr_find_in_attrdef()
1329 if (likely(ad->type == type)) in ntfs_attr_find_in_attrdef()
1341 * ntfs_attr_size_bounds_check - check a size of an attribute type for validity
1344 * @size: size which to check
1346 * Check whether the @size in bytes is valid for an attribute of @type on the
1349 * Return 0 if valid, -ERANGE if not valid, or -ENOENT if the attribute is not
1353 const s64 size) in ntfs_attr_size_bounds_check() argument
1357 BUG_ON(size < 0); in ntfs_attr_size_bounds_check()
1359 * $ATTRIBUTE_LIST has a maximum size of 256kiB, but this is not in ntfs_attr_size_bounds_check()
1362 if (unlikely(type == AT_ATTRIBUTE_LIST && size > 256 * 1024)) in ntfs_attr_size_bounds_check()
1363 return -ERANGE; in ntfs_attr_size_bounds_check()
1367 return -ENOENT; in ntfs_attr_size_bounds_check()
1369 if (((sle64_to_cpu(ad->min_size) > 0) && in ntfs_attr_size_bounds_check()
1370 size < sle64_to_cpu(ad->min_size)) || in ntfs_attr_size_bounds_check()
1371 ((sle64_to_cpu(ad->max_size) > 0) && size > in ntfs_attr_size_bounds_check()
1372 sle64_to_cpu(ad->max_size))) in ntfs_attr_size_bounds_check()
1373 return -ERANGE; in ntfs_attr_size_bounds_check()
1378 * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
1383 * be non-resident. This information is obtained from $AttrDef system file.
1385 * Return 0 if the attribute is allowed to be non-resident, -EPERM if not, and
1386 * -ENOENT if the attribute is not listed in $AttrDef.
1392 /* Find the attribute definition record in $AttrDef. */ in ntfs_attr_can_be_non_resident()
1395 return -ENOENT; in ntfs_attr_can_be_non_resident()
1397 if (ad->flags & ATTR_DEF_RESIDENT) in ntfs_attr_can_be_non_resident()
1398 return -EPERM; in ntfs_attr_can_be_non_resident()
1403 * ntfs_attr_can_be_resident - check if an attribute can be resident
1413 * Return 0 if the attribute is allowed to be non-resident and -EPERM if not.
1415 * Warning: In the system file $MFT the attribute $Bitmap must be non-resident
1423 return -EPERM; in ntfs_attr_can_be_resident()
1428 * ntfs_attr_record_resize - resize an attribute record
1429 * @m: mft record containing attribute record
1430 * @a: attribute record to resize
1431 * @new_size: new size in bytes to which to resize the attribute record @a
1433 * Resize the attribute record @a, i.e. the resident part of the attribute, in
1434 * the mft record @m to @new_size bytes.
1436 * Return 0 on success and -errno on error. The following error codes are
1438 * -ENOSPC - Not enough space in the mft record @m to perform the resize.
1442 * Warning: If you make a record smaller without having copied all the data you
1452 if (new_size != le32_to_cpu(a->length)) { in ntfs_attr_record_resize()
1453 u32 new_muse = le32_to_cpu(m->bytes_in_use) - in ntfs_attr_record_resize()
1454 le32_to_cpu(a->length) + new_size; in ntfs_attr_record_resize()
1455 /* Not enough space in this mft record. */ in ntfs_attr_record_resize()
1456 if (new_muse > le32_to_cpu(m->bytes_allocated)) in ntfs_attr_record_resize()
1457 return -ENOSPC; in ntfs_attr_record_resize()
1459 memmove((u8*)a + new_size, (u8*)a + le32_to_cpu(a->length), in ntfs_attr_record_resize()
1460 le32_to_cpu(m->bytes_in_use) - ((u8*)a - in ntfs_attr_record_resize()
1461 (u8*)m) - le32_to_cpu(a->length)); in ntfs_attr_record_resize()
1463 m->bytes_in_use = cpu_to_le32(new_muse); in ntfs_attr_record_resize()
1464 /* Adjust @a to reflect the new size. */ in ntfs_attr_record_resize()
1465 if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length)) in ntfs_attr_record_resize()
1466 a->length = cpu_to_le32(new_size); in ntfs_attr_record_resize()
1472 * ntfs_resident_attr_value_resize - resize the value of a resident attribute
1473 * @m: mft record containing attribute record
1474 * @a: attribute record whose value to resize
1475 * @new_size: new size in bytes to which to resize the attribute value of @a
1477 * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
1480 * Return 0 on success and -errno on error. The following error codes are
1482 * -ENOSPC - Not enough space in the mft record @m to perform the resize.
1486 * Warning: If you make a record smaller without having copied all the data you
1494 /* Resize the resident part of the attribute record. */ in ntfs_resident_attr_value_resize()
1496 le16_to_cpu(a->data.resident.value_offset) + new_size)) in ntfs_resident_attr_value_resize()
1497 return -ENOSPC; in ntfs_resident_attr_value_resize()
1500 * the area between the old size and @new_size. in ntfs_resident_attr_value_resize()
1502 old_size = le32_to_cpu(a->data.resident.value_length); in ntfs_resident_attr_value_resize()
1504 memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) + in ntfs_resident_attr_value_resize()
1505 old_size, 0, new_size - old_size); in ntfs_resident_attr_value_resize()
1507 a->data.resident.value_length = cpu_to_le32(new_size); in ntfs_resident_attr_value_resize()
1512 * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
1514 * @data_size: size of the resident data to copy to the non-resident attribute
1517 * non-resident one.
1519 * @data_size must be equal to the attribute value size. This is needed since
1520 * we need to know the size before we can map the mft record and our callers
1521 * always know it. The reason we cannot simply read the size from the vfs
1523 * ntfs_attr_make_non_resident() is called in the ->truncate call path(s).
1525 * Return 0 on success and -errno on error. The following error return codes
1527 * -EPERM - The attribute is not allowed to be non-resident.
1528 * -ENOMEM - Not enough memory.
1529 * -ENOSPC - Not enough disk space.
1530 * -EINVAL - Attribute not defined on the volume.
1531 * -EIO - I/o error or other error.
1532 * Note that -ENOSPC is also returned in the case that there is not enough
1533 * space in the mft record to do the conversion. This can happen when the mft
1534 * record is already very full. The caller is responsible for trying to make
1535 * space in the mft record and trying again. FIXME: Do we need a separate
1536 * error return code for this kind of -ENOSPC or is it always worth trying
1538 * make it non-resident at all? Ho-hum... (AIA)
1541 * a resident to a non-resident attribute.
1543 * Locking: - The caller must hold i_mutex on the inode.
1549 ntfs_volume *vol = ni->vol; in ntfs_attr_make_non_resident()
1562 /* Check that the attribute is allowed to be non-resident. */ in ntfs_attr_make_non_resident()
1563 err = ntfs_attr_can_be_non_resident(vol, ni->type); in ntfs_attr_make_non_resident()
1565 if (err == -EPERM) in ntfs_attr_make_non_resident()
1567 "non-resident."); in ntfs_attr_make_non_resident()
1580 * The size needs to be aligned to a cluster boundary for allocation in ntfs_attr_make_non_resident()
1583 new_size = (data_size + vol->cluster_size - 1) & in ntfs_attr_make_non_resident()
1584 ~(vol->cluster_size - 1); in ntfs_attr_make_non_resident()
1590 page = find_or_create_page(vi->i_mapping, 0, in ntfs_attr_make_non_resident()
1591 mapping_gfp_mask(vi->i_mapping)); in ntfs_attr_make_non_resident()
1593 return -ENOMEM; in ntfs_attr_make_non_resident()
1596 vol->cluster_size_bits, -1, DATA_ZONE, true); in ntfs_attr_make_non_resident()
1601 vol->cluster_size_bits) > 1 ? "s" : "", in ntfs_attr_make_non_resident()
1609 /* Determine the size of the mapping pairs array. */ in ntfs_attr_make_non_resident()
1610 mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, -1); in ntfs_attr_make_non_resident()
1613 ntfs_debug("Failed to get size for mapping pairs array, error " in ntfs_attr_make_non_resident()
1617 down_write(&ni->runlist.lock); in ntfs_attr_make_non_resident()
1621 base_ni = ni->ext.base_ntfs_ino; in ntfs_attr_make_non_resident()
1631 err = -ENOMEM; in ntfs_attr_make_non_resident()
1634 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, in ntfs_attr_make_non_resident()
1637 if (err == -ENOENT) in ntfs_attr_make_non_resident()
1638 err = -EIO; in ntfs_attr_make_non_resident()
1641 m = ctx->mrec; in ntfs_attr_make_non_resident()
1642 a = ctx->attr; in ntfs_attr_make_non_resident()
1644 BUG_ON(a->non_resident); in ntfs_attr_make_non_resident()
1651 sizeof(a->data.non_resident.compressed_size) + in ntfs_attr_make_non_resident()
1656 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; in ntfs_attr_make_non_resident()
1658 * Determine the size of the resident part of the now non-resident in ntfs_attr_make_non_resident()
1659 * attribute record. in ntfs_attr_make_non_resident()
1666 attr_size = le32_to_cpu(a->data.resident.value_length); in ntfs_attr_make_non_resident()
1671 le16_to_cpu(a->data.resident.value_offset), in ntfs_attr_make_non_resident()
1673 memset(kaddr + attr_size, 0, PAGE_SIZE - attr_size); in ntfs_attr_make_non_resident()
1679 old_res_attr_flags = a->data.resident.flags; in ntfs_attr_make_non_resident()
1680 /* Resize the resident part of the attribute record. */ in ntfs_attr_make_non_resident()
1685 * Convert the resident part of the attribute record to describe a in ntfs_attr_make_non_resident()
1686 * non-resident attribute. in ntfs_attr_make_non_resident()
1688 a->non_resident = 1; in ntfs_attr_make_non_resident()
1690 if (a->name_length) in ntfs_attr_make_non_resident()
1691 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), in ntfs_attr_make_non_resident()
1692 a->name_length * sizeof(ntfschar)); in ntfs_attr_make_non_resident()
1693 a->name_offset = cpu_to_le16(name_ofs); in ntfs_attr_make_non_resident()
1694 /* Setup the fields specific to non-resident attributes. */ in ntfs_attr_make_non_resident()
1695 a->data.non_resident.lowest_vcn = 0; in ntfs_attr_make_non_resident()
1696 a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >> in ntfs_attr_make_non_resident()
1697 vol->cluster_size_bits); in ntfs_attr_make_non_resident()
1698 a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs); in ntfs_attr_make_non_resident()
1699 memset(&a->data.non_resident.reserved, 0, in ntfs_attr_make_non_resident()
1700 sizeof(a->data.non_resident.reserved)); in ntfs_attr_make_non_resident()
1701 a->data.non_resident.allocated_size = cpu_to_sle64(new_size); in ntfs_attr_make_non_resident()
1702 a->data.non_resident.data_size = in ntfs_attr_make_non_resident()
1703 a->data.non_resident.initialized_size = in ntfs_attr_make_non_resident()
1706 a->data.non_resident.compression_unit = 0; in ntfs_attr_make_non_resident()
1707 if (NInoCompressed(ni) || vol->major_ver < 3) in ntfs_attr_make_non_resident()
1708 a->data.non_resident.compression_unit = 4; in ntfs_attr_make_non_resident()
1709 a->data.non_resident.compressed_size = in ntfs_attr_make_non_resident()
1710 a->data.non_resident.allocated_size; in ntfs_attr_make_non_resident()
1712 a->data.non_resident.compression_unit = 0; in ntfs_attr_make_non_resident()
1713 /* Generate the mapping pairs array into the attribute record. */ in ntfs_attr_make_non_resident()
1715 arec_size - mp_ofs, rl, 0, -1, NULL); in ntfs_attr_make_non_resident()
1721 /* Setup the in-memory attribute structure to be non-resident. */ in ntfs_attr_make_non_resident()
1722 ni->runlist.rl = rl; in ntfs_attr_make_non_resident()
1723 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1724 ni->allocated_size = new_size; in ntfs_attr_make_non_resident()
1726 ni->itype.compressed.size = ni->allocated_size; in ntfs_attr_make_non_resident()
1727 if (a->data.non_resident.compression_unit) { in ntfs_attr_make_non_resident()
1728 ni->itype.compressed.block_size = 1U << (a->data. in ntfs_attr_make_non_resident()
1730 vol->cluster_size_bits); in ntfs_attr_make_non_resident()
1731 ni->itype.compressed.block_size_bits = in ntfs_attr_make_non_resident()
1732 ffs(ni->itype.compressed.block_size) - in ntfs_attr_make_non_resident()
1734 ni->itype.compressed.block_clusters = 1U << in ntfs_attr_make_non_resident()
1735 a->data.non_resident.compression_unit; in ntfs_attr_make_non_resident()
1737 ni->itype.compressed.block_size = 0; in ntfs_attr_make_non_resident()
1738 ni->itype.compressed.block_size_bits = 0; in ntfs_attr_make_non_resident()
1739 ni->itype.compressed.block_clusters = 0; in ntfs_attr_make_non_resident()
1741 vi->i_blocks = ni->itype.compressed.size >> 9; in ntfs_attr_make_non_resident()
1743 vi->i_blocks = ni->allocated_size >> 9; in ntfs_attr_make_non_resident()
1744 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1746 * This needs to be last since the address space operations ->read_folio in ntfs_attr_make_non_resident()
1747 * and ->writepage can run concurrently with us as they are not in ntfs_attr_make_non_resident()
1752 /* Mark the mft record dirty, so it gets written back. */ in ntfs_attr_make_non_resident()
1753 flush_dcache_mft_record_page(ctx->ntfs_ino); in ntfs_attr_make_non_resident()
1754 mark_mft_record_dirty(ctx->ntfs_ino); in ntfs_attr_make_non_resident()
1757 up_write(&ni->runlist.lock); in ntfs_attr_make_non_resident()
1767 a->non_resident = 0; in ntfs_attr_make_non_resident()
1770 sizeof(a->data.resident.reserved) + 7) & ~7; in ntfs_attr_make_non_resident()
1771 if (a->name_length) in ntfs_attr_make_non_resident()
1772 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), in ntfs_attr_make_non_resident()
1773 a->name_length * sizeof(ntfschar)); in ntfs_attr_make_non_resident()
1774 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; in ntfs_attr_make_non_resident()
1775 a->name_offset = cpu_to_le16(name_ofs); in ntfs_attr_make_non_resident()
1777 /* Resize the resident part of the attribute record. */ in ntfs_attr_make_non_resident()
1783 * If the old size is too small, truncate the attribute, in ntfs_attr_make_non_resident()
1784 * otherwise simply give it a larger allocated size. in ntfs_attr_make_non_resident()
1786 * allocated size is much bigger than the resident value size. in ntfs_attr_make_non_resident()
1788 arec_size = le32_to_cpu(a->length); in ntfs_attr_make_non_resident()
1791 attr_size = arec_size - mp_ofs; in ntfs_attr_make_non_resident()
1792 ntfs_error(vol->sb, "Failed to undo partial resident " in ntfs_attr_make_non_resident()
1793 "to non-resident attribute " in ntfs_attr_make_non_resident()
1799 vi->i_ino, in ntfs_attr_make_non_resident()
1800 (unsigned)le32_to_cpu(ni->type), in ntfs_attr_make_non_resident()
1801 err2, attr_size, err2 - attr_size, in ntfs_attr_make_non_resident()
1802 ((ni->type == AT_DATA) && in ntfs_attr_make_non_resident()
1803 !ni->name_len) ? "FILE": "ATTRIBUTE"); in ntfs_attr_make_non_resident()
1804 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1805 ni->initialized_size = attr_size; in ntfs_attr_make_non_resident()
1807 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1811 a->data.resident.value_length = cpu_to_le32(attr_size); in ntfs_attr_make_non_resident()
1812 a->data.resident.value_offset = cpu_to_le16(mp_ofs); in ntfs_attr_make_non_resident()
1813 a->data.resident.flags = old_res_attr_flags; in ntfs_attr_make_non_resident()
1814 memset(&a->data.resident.reserved, 0, in ntfs_attr_make_non_resident()
1815 sizeof(a->data.resident.reserved)); in ntfs_attr_make_non_resident()
1822 /* Setup the allocated size in the ntfs inode in case it changed. */ in ntfs_attr_make_non_resident()
1823 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1824 ni->allocated_size = arec_size - mp_ofs; in ntfs_attr_make_non_resident()
1825 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_make_non_resident()
1826 /* Mark the mft record dirty, so it gets written back. */ in ntfs_attr_make_non_resident()
1827 flush_dcache_mft_record_page(ctx->ntfs_ino); in ntfs_attr_make_non_resident()
1828 mark_mft_record_dirty(ctx->ntfs_ino); in ntfs_attr_make_non_resident()
1834 ni->runlist.rl = NULL; in ntfs_attr_make_non_resident()
1835 up_write(&ni->runlist.lock); in ntfs_attr_make_non_resident()
1839 ntfs_error(vol->sb, "Failed to release allocated " in ntfs_attr_make_non_resident()
1850 if (err == -EINVAL) in ntfs_attr_make_non_resident()
1851 err = -EIO; in ntfs_attr_make_non_resident()
1856 * ntfs_attr_extend_allocation - extend the allocated space of an attribute
1858 * @new_alloc_size: new size in bytes to which to extend the allocation to
1859 * @new_data_size: new size in bytes to which to extend the data to
1860 * @data_start: beginning of region which is required to be non-sparse
1863 * to @new_alloc_size bytes. If @data_start is -1, the whole extension may be
1866 * region between the old allocated size and @data_start - 1 may be made sparse
1870 * If @new_data_size is -1, it is ignored. If it is >= 0, then the data size
1872 * vfs inode is not updated. Only the data size in the base attribute record
1875 * size as well as for @new_data_size to be greater than @new_alloc_size.
1877 * For resident attributes this involves resizing the attribute record and if
1879 * converting the attribute to a non-resident attribute which in turn involves
1880 * extending the allocation of a non-resident attribute as described below.
1882 * For non-resident attributes this involves allocating clusters in the data
1886 * resizing the attribute record and if necessary moving it and/or other
1887 * attributes into extent mft records and/or splitting the attribute record
1894 * Return the new allocated size on success and -errno on error. In the case
1897 * and this is returned. This means the caller must check the returned size to
1898 * determine if the extension was partial. If @data_start is -1 then partial
1904 * locking the mft record of the base ntfs inode. These locks are maintained
1907 * from resident to non-resident safely.
1920 ntfs_volume *vol = ni->vol; in ntfs_attr_extend_allocation()
1932 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
1933 allocated_size = ni->allocated_size; in ntfs_attr_extend_allocation()
1934 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
1938 "data_start 0x%llx.", vi->i_ino, in ntfs_attr_extend_allocation()
1939 (unsigned)le32_to_cpu(ni->type), in ntfs_attr_extend_allocation()
1947 * For non-resident attributes, @start and @new_size need to be aligned in ntfs_attr_extend_allocation()
1952 start &= ~(s64)vol->cluster_size_mask; in ntfs_attr_extend_allocation()
1953 new_alloc_size = (new_alloc_size + vol->cluster_size - 1) & in ntfs_attr_extend_allocation()
1954 ~(s64)vol->cluster_size_mask; in ntfs_attr_extend_allocation()
1957 /* Check if new size is allowed in $AttrDef. */ in ntfs_attr_extend_allocation()
1958 err = ntfs_attr_size_bounds_check(vol, ni->type, new_alloc_size); in ntfs_attr_extend_allocation()
1961 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
1962 allocated_size = ni->allocated_size; in ntfs_attr_extend_allocation()
1963 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
1965 if (err == -ERANGE) { in ntfs_attr_extend_allocation()
1966 ntfs_error(vol->sb, "Cannot extend allocation " in ntfs_attr_extend_allocation()
1970 "maximum allowed size for " in ntfs_attr_extend_allocation()
1972 vi->i_ino, (unsigned) in ntfs_attr_extend_allocation()
1973 le32_to_cpu(ni->type)); in ntfs_attr_extend_allocation()
1975 ntfs_error(vol->sb, "Cannot extend allocation " in ntfs_attr_extend_allocation()
1982 vi->i_ino, (unsigned) in ntfs_attr_extend_allocation()
1983 le32_to_cpu(ni->type)); in ntfs_attr_extend_allocation()
1987 if (err == -ERANGE) in ntfs_attr_extend_allocation()
1988 err = -EFBIG; in ntfs_attr_extend_allocation()
1990 err = -EIO; in ntfs_attr_extend_allocation()
1996 base_ni = ni->ext.base_ntfs_ino; in ntfs_attr_extend_allocation()
1998 * We will be modifying both the runlist (if non-resident) and the mft in ntfs_attr_extend_allocation()
1999 * record so lock them both down. in ntfs_attr_extend_allocation()
2001 down_write(&ni->runlist.lock); in ntfs_attr_extend_allocation()
2011 err = -ENOMEM; in ntfs_attr_extend_allocation()
2014 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2015 allocated_size = ni->allocated_size; in ntfs_attr_extend_allocation()
2016 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2018 * If non-resident, seek to the last extent. If resident, there is in ntfs_attr_extend_allocation()
2021 vcn = NInoNonResident(ni) ? allocated_size >> vol->cluster_size_bits : in ntfs_attr_extend_allocation()
2025 * just converted the attribute from resident to non-resident it is in ntfs_attr_extend_allocation()
2027 * abort if we need to update the data size. in ntfs_attr_extend_allocation()
2030 ntfs_debug("Allocated size already exceeds requested size."); in ntfs_attr_extend_allocation()
2036 * data size. in ntfs_attr_extend_allocation()
2040 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, in ntfs_attr_extend_allocation()
2043 if (err == -ENOENT) in ntfs_attr_extend_allocation()
2044 err = -EIO; in ntfs_attr_extend_allocation()
2047 m = ctx->mrec; in ntfs_attr_extend_allocation()
2048 a = ctx->attr; in ntfs_attr_extend_allocation()
2050 if (a->non_resident) in ntfs_attr_extend_allocation()
2054 attr_len = le32_to_cpu(a->data.resident.value_length); in ntfs_attr_extend_allocation()
2056 * Extend the attribute record to be able to store the new attribute in ntfs_attr_extend_allocation()
2057 * size. ntfs_attr_record_resize() will not do anything if the size is in ntfs_attr_extend_allocation()
2060 if (new_alloc_size < vol->mft_record_size && in ntfs_attr_extend_allocation()
2062 le16_to_cpu(a->data.resident.value_offset) + in ntfs_attr_extend_allocation()
2065 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2066 ni->allocated_size = le32_to_cpu(a->length) - in ntfs_attr_extend_allocation()
2067 le16_to_cpu(a->data.resident.value_offset); in ntfs_attr_extend_allocation()
2068 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2071 a->data.resident.value_length = in ntfs_attr_extend_allocation()
2078 * ntfs_attr_make_non_resident(). This could be optimised by try- in ntfs_attr_extend_allocation()
2086 up_write(&ni->runlist.lock); in ntfs_attr_extend_allocation()
2088 * Not enough space in the mft record, try to make the attribute in ntfs_attr_extend_allocation()
2089 * non-resident and if successful restart the extension process. in ntfs_attr_extend_allocation()
2095 * Could not make non-resident. If this is due to this not being in ntfs_attr_extend_allocation()
2097 * try to make other attributes non-resident. Otherwise fail. in ntfs_attr_extend_allocation()
2099 if (unlikely(err != -EPERM && err != -ENOSPC)) { in ntfs_attr_extend_allocation()
2101 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2102 allocated_size = ni->allocated_size; in ntfs_attr_extend_allocation()
2103 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2105 ntfs_error(vol->sb, "Cannot extend allocation of " in ntfs_attr_extend_allocation()
2108 "to non-resident attribute failed " in ntfs_attr_extend_allocation()
2109 "with error code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2110 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2111 if (err != -ENOMEM) in ntfs_attr_extend_allocation()
2112 err = -EIO; in ntfs_attr_extend_allocation()
2116 read_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2117 allocated_size = ni->allocated_size; in ntfs_attr_extend_allocation()
2118 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2120 if (err == -ENOSPC) in ntfs_attr_extend_allocation()
2121 ntfs_error(vol->sb, "Not enough space in the mft " in ntfs_attr_extend_allocation()
2122 "record/on disk for the non-resident " in ntfs_attr_extend_allocation()
2125 else /* if (err == -EPERM) */ in ntfs_attr_extend_allocation()
2126 ntfs_error(vol->sb, "This attribute type may not be " in ntfs_attr_extend_allocation()
2127 "non-resident. This case is not " in ntfs_attr_extend_allocation()
2130 err = -EOPNOTSUPP; in ntfs_attr_extend_allocation()
2133 // TODO: Attempt to make other attributes non-resident. in ntfs_attr_extend_allocation()
2142 if (ni->type == AT_ATTRIBUTE_LIST || in ntfs_attr_extend_allocation()
2143 ni->type == AT_STANDARD_INFORMATION) { in ntfs_attr_extend_allocation()
2146 err = -EOPNOTSUPP; in ntfs_attr_extend_allocation()
2151 // TODO: Attempt to move this attribute to an extent mft record, but in ntfs_attr_extend_allocation()
2152 // only if it is not already the only attribute in an mft record in in ntfs_attr_extend_allocation()
2154 err = -EOPNOTSUPP; in ntfs_attr_extend_allocation()
2157 /* There is nothing we can do to make enough space. )-: */ in ntfs_attr_extend_allocation()
2170 * allocated size and the start of the data. Otherwise simply proceed in ntfs_attr_extend_allocation()
2171 * with filling the whole space between the old allocated size and the in ntfs_attr_extend_allocation()
2172 * new allocated size with clusters. in ntfs_attr_extend_allocation()
2174 if ((start >= 0 && start <= allocated_size) || ni->type != AT_DATA || in ntfs_attr_extend_allocation()
2179 ntfs_debug("Inserting holes is not-implemented yet. Falling back to " in ntfs_attr_extend_allocation()
2182 rl = ni->runlist.rl; in ntfs_attr_extend_allocation()
2185 while (rl->length) in ntfs_attr_extend_allocation()
2189 if (unlikely(!rl || rl->lcn == LCN_RL_NOT_MAPPED || in ntfs_attr_extend_allocation()
2190 (rl->lcn == LCN_ENOENT && rl > ni->runlist.rl && in ntfs_attr_extend_allocation()
2191 (rl-1)->lcn == LCN_RL_NOT_MAPPED))) { in ntfs_attr_extend_allocation()
2194 rl = ntfs_mapping_pairs_decompress(vol, a, ni->runlist.rl); in ntfs_attr_extend_allocation()
2198 ntfs_error(vol->sb, "Cannot extend allocation " in ntfs_attr_extend_allocation()
2203 "code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2204 (unsigned)le32_to_cpu(ni->type), in ntfs_attr_extend_allocation()
2206 if (err != -ENOMEM) in ntfs_attr_extend_allocation()
2207 err = -EIO; in ntfs_attr_extend_allocation()
2210 ni->runlist.rl = rl; in ntfs_attr_extend_allocation()
2212 while (rl->length) in ntfs_attr_extend_allocation()
2223 while (rl->lcn < 0 && rl > ni->runlist.rl) in ntfs_attr_extend_allocation()
2224 rl--; in ntfs_attr_extend_allocation()
2229 rl2 = ntfs_cluster_alloc(vol, allocated_size >> vol->cluster_size_bits, in ntfs_attr_extend_allocation()
2230 (new_alloc_size - allocated_size) >> in ntfs_attr_extend_allocation()
2231 vol->cluster_size_bits, (rl && (rl->lcn >= 0)) ? in ntfs_attr_extend_allocation()
2232 rl->lcn + rl->length : -1, DATA_ZONE, true); in ntfs_attr_extend_allocation()
2236 ntfs_error(vol->sb, "Cannot extend allocation of " in ntfs_attr_extend_allocation()
2239 "failed with error code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2240 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2241 if (err != -ENOMEM && err != -ENOSPC) in ntfs_attr_extend_allocation()
2242 err = -EIO; in ntfs_attr_extend_allocation()
2245 rl = ntfs_runlists_merge(ni->runlist.rl, rl2); in ntfs_attr_extend_allocation()
2249 ntfs_error(vol->sb, "Cannot extend allocation of " in ntfs_attr_extend_allocation()
2252 "with error code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2253 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2254 if (err != -ENOMEM) in ntfs_attr_extend_allocation()
2255 err = -EIO; in ntfs_attr_extend_allocation()
2257 ntfs_error(vol->sb, "Failed to release allocated " in ntfs_attr_extend_allocation()
2266 ni->runlist.rl = rl; in ntfs_attr_extend_allocation()
2267 ntfs_debug("Allocated 0x%llx clusters.", (long long)(new_alloc_size - in ntfs_attr_extend_allocation()
2268 allocated_size) >> vol->cluster_size_bits); in ntfs_attr_extend_allocation()
2270 ll = sle64_to_cpu(a->data.non_resident.lowest_vcn); in ntfs_attr_extend_allocation()
2273 BUG_ON(!rl2->length); in ntfs_attr_extend_allocation()
2274 BUG_ON(rl2->lcn < LCN_HOLE); in ntfs_attr_extend_allocation()
2276 /* Get the size for the new mapping pairs array for this extent. */ in ntfs_attr_extend_allocation()
2277 mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1); in ntfs_attr_extend_allocation()
2281 ntfs_error(vol->sb, "Cannot extend allocation of " in ntfs_attr_extend_allocation()
2283 "because determining the size for the " in ntfs_attr_extend_allocation()
2285 "%i.", vi->i_ino, in ntfs_attr_extend_allocation()
2286 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2287 err = -EIO; in ntfs_attr_extend_allocation()
2290 /* Extend the attribute record to fit the bigger mapping pairs array. */ in ntfs_attr_extend_allocation()
2291 attr_len = le32_to_cpu(a->length); in ntfs_attr_extend_allocation()
2293 le16_to_cpu(a->data.non_resident.mapping_pairs_offset)); in ntfs_attr_extend_allocation()
2295 BUG_ON(err != -ENOSPC); in ntfs_attr_extend_allocation()
2297 // record or by starting a new extent in a new mft record, in ntfs_attr_extend_allocation()
2300 // other attributes non-resident and/or by moving other in ntfs_attr_extend_allocation()
2301 // attributes out of this mft record. in ntfs_attr_extend_allocation()
2303 ntfs_error(vol->sb, "Not enough space in the mft " in ntfs_attr_extend_allocation()
2304 "record for the extended attribute " in ntfs_attr_extend_allocation()
2305 "record. This case is not " in ntfs_attr_extend_allocation()
2307 err = -EOPNOTSUPP; in ntfs_attr_extend_allocation()
2311 /* Generate the mapping pairs array directly into the attr record. */ in ntfs_attr_extend_allocation()
2313 le16_to_cpu(a->data.non_resident.mapping_pairs_offset), in ntfs_attr_extend_allocation()
2314 mp_size, rl2, ll, -1, NULL); in ntfs_attr_extend_allocation()
2317 ntfs_error(vol->sb, "Cannot extend allocation of " in ntfs_attr_extend_allocation()
2320 "failed with error code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2321 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2322 err = -EIO; in ntfs_attr_extend_allocation()
2326 a->data.non_resident.highest_vcn = cpu_to_sle64((new_alloc_size >> in ntfs_attr_extend_allocation()
2327 vol->cluster_size_bits) - 1); in ntfs_attr_extend_allocation()
2329 * We now have extended the allocated size of the attribute. Reflect in ntfs_attr_extend_allocation()
2330 * this in the ntfs_inode structure and the attribute record. in ntfs_attr_extend_allocation()
2332 if (a->data.non_resident.lowest_vcn) { in ntfs_attr_extend_allocation()
2337 flush_dcache_mft_record_page(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2338 mark_mft_record_dirty(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2340 err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, in ntfs_attr_extend_allocation()
2345 a = ctx->attr; in ntfs_attr_extend_allocation()
2347 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2348 ni->allocated_size = new_alloc_size; in ntfs_attr_extend_allocation()
2349 a->data.non_resident.allocated_size = cpu_to_sle64(new_alloc_size); in ntfs_attr_extend_allocation()
2361 ni->itype.compressed.size += new_alloc_size - allocated_size; in ntfs_attr_extend_allocation()
2362 a->data.non_resident.compressed_size = in ntfs_attr_extend_allocation()
2363 cpu_to_sle64(ni->itype.compressed.size); in ntfs_attr_extend_allocation()
2364 vi->i_blocks = ni->itype.compressed.size >> 9; in ntfs_attr_extend_allocation()
2366 vi->i_blocks = new_alloc_size >> 9; in ntfs_attr_extend_allocation()
2367 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2371 sle64_to_cpu(a->data.non_resident.data_size)); in ntfs_attr_extend_allocation()
2372 a->data.non_resident.data_size = cpu_to_sle64(new_data_size); in ntfs_attr_extend_allocation()
2376 flush_dcache_mft_record_page(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2377 mark_mft_record_dirty(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2381 up_write(&ni->runlist.lock); in ntfs_attr_extend_allocation()
2387 ntfs_error(vol->sb, "Cannot complete extension of allocation " in ntfs_attr_extend_allocation()
2390 "error code %i.", vi->i_ino, in ntfs_attr_extend_allocation()
2391 (unsigned)le32_to_cpu(ni->type), err); in ntfs_attr_extend_allocation()
2392 if (err == -ENOENT) in ntfs_attr_extend_allocation()
2393 err = -EIO; in ntfs_attr_extend_allocation()
2395 if (ntfs_attr_lookup(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, in ntfs_attr_extend_allocation()
2396 allocated_size >> vol->cluster_size_bits, NULL, 0, in ntfs_attr_extend_allocation()
2398 ntfs_error(vol->sb, "Failed to find last attribute extent of " in ntfs_attr_extend_allocation()
2401 write_lock_irqsave(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2402 ni->allocated_size = new_alloc_size; in ntfs_attr_extend_allocation()
2409 ni->itype.compressed.size += new_alloc_size - in ntfs_attr_extend_allocation()
2411 vi->i_blocks = ni->itype.compressed.size >> 9; in ntfs_attr_extend_allocation()
2413 vi->i_blocks = new_alloc_size >> 9; in ntfs_attr_extend_allocation()
2414 write_unlock_irqrestore(&ni->size_lock, flags); in ntfs_attr_extend_allocation()
2417 up_write(&ni->runlist.lock); in ntfs_attr_extend_allocation()
2419 * The only thing that is now wrong is the allocated size of the in ntfs_attr_extend_allocation()
2425 ctx->attr->data.non_resident.highest_vcn = cpu_to_sle64( in ntfs_attr_extend_allocation()
2426 (allocated_size >> vol->cluster_size_bits) - 1); in ntfs_attr_extend_allocation()
2428 ll = allocated_size >> vol->cluster_size_bits; in ntfs_attr_extend_allocation()
2429 if (ntfs_cluster_free(ni, ll, -1, ctx) < 0) { in ntfs_attr_extend_allocation()
2430 ntfs_error(vol->sb, "Failed to release allocated cluster(s) " in ntfs_attr_extend_allocation()
2435 m = ctx->mrec; in ntfs_attr_extend_allocation()
2436 a = ctx->attr; in ntfs_attr_extend_allocation()
2439 * longer valid, we cannot resize the attribute record or build the in ntfs_attr_extend_allocation()
2443 if (ntfs_rl_truncate_nolock(vol, &ni->runlist, ll) || IS_ERR(m)) { in ntfs_attr_extend_allocation()
2444 ntfs_error(vol->sb, "Failed to %s in error code path. Run " in ntfs_attr_extend_allocation()
2451 ntfs_error(vol->sb, "Failed to restore attribute " in ntfs_attr_extend_allocation()
2452 "record in error code path. Run " in ntfs_attr_extend_allocation()
2457 a->data.non_resident. in ntfs_attr_extend_allocation()
2458 mapping_pairs_offset), attr_len - in ntfs_attr_extend_allocation()
2459 le16_to_cpu(a->data.non_resident. in ntfs_attr_extend_allocation()
2460 mapping_pairs_offset), rl2, ll, -1, in ntfs_attr_extend_allocation()
2462 ntfs_error(vol->sb, "Failed to restore " in ntfs_attr_extend_allocation()
2468 flush_dcache_mft_record_page(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2469 mark_mft_record_dirty(ctx->ntfs_ino); in ntfs_attr_extend_allocation()
2477 up_write(&ni->runlist.lock); in ntfs_attr_extend_allocation()
2484 * ntfs_attr_set - fill (a part of) an attribute with a byte
2488 * @val: the unsigned 8-bit value with which to fill the attribute
2497 * pages to be written to the mft record/disk.
2499 * Return 0 on success and -errno on error. An error code of -ESPIPE means
2505 ntfs_volume *vol = ni->vol; in ntfs_attr_set()
2510 unsigned start_ofs, end_ofs, size; in ntfs_attr_set() local
2524 mapping = VFS_I(ni)->i_mapping; in ntfs_attr_set()
2531 /* If the end is outside the inode size return -ESPIPE. */ in ntfs_attr_set()
2533 ntfs_error(vol->sb, "Request exceeds end of attribute."); in ntfs_attr_set()
2534 return -ESPIPE; in ntfs_attr_set()
2541 ntfs_error(vol->sb, "Failed to read first partial " in ntfs_attr_set()
2549 size = PAGE_SIZE; in ntfs_attr_set()
2551 size = end_ofs; in ntfs_attr_set()
2553 memset(kaddr + start_ofs, val, size - start_ofs); in ntfs_attr_set()
2569 ntfs_error(vol->sb, "Insufficient memory to grab " in ntfs_attr_set()
2571 return -ENOMEM; in ntfs_attr_set()
2587 } while ((bh = bh->b_this_page) != head); in ntfs_attr_set()
2606 ntfs_error(vol->sb, "Failed to read last partial page " in ntfs_attr_set()