Re: [bug report] fs/ntfs3: missing error code in attr_data_get_block()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Aug 27, 2021 at 11:57:57AM +0300, Dan Carpenter wrote:
> Hello Konstantin Komarov,
> 
> The patch be71b5cba2e6: "fs/ntfs3: Add attrib operations" from Aug
> 13, 2021, leads to the following
> Smatch static checker warning:
> 
> 	fs/ntfs3/attrib.c:1031 attr_data_get_block()
> 	warn: missing error code here? 'ni_load_mi()' failed. 'err' = '0'
> 
> fs/ntfs3/attrib.c
>     823 int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
>     824                         CLST *len, bool *new)
>     825 {
>     826         int err = 0;
>     827         struct runs_tree *run = &ni->file.run;
>     828         struct ntfs_sb_info *sbi;
>     829         u8 cluster_bits;
>     830         struct ATTRIB *attr = NULL, *attr_b;
>     831         struct ATTR_LIST_ENTRY *le, *le_b;
>     832         struct mft_inode *mi, *mi_b;
>     833         CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end;
>     834         u64 total_size;
>     835         u32 clst_per_frame;
>     836         bool ok;
>     837 
>     838         if (new)
>     839                 *new = false;
>     840 
>     841         down_read(&ni->file.run_lock);
>     842         ok = run_lookup_entry(run, vcn, lcn, len, NULL);
>     843         up_read(&ni->file.run_lock);
>     844 
>     845         if (ok && (*lcn != SPARSE_LCN || !new)) {
>     846                 /* normal way */
>     847                 return 0;
>     848         }
>     849 
>     850         if (!clen)
>     851                 clen = 1;
>     852 
>     853         if (ok && clen > *len)
>     854                 clen = *len;
>     855 
>     856         sbi = ni->mi.sbi;
>     857         cluster_bits = sbi->cluster_bits;
>     858 
>     859         ni_lock(ni);
>     860         down_write(&ni->file.run_lock);
>     861 
>     862         le_b = NULL;
>     863         attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
>     864         if (!attr_b) {
>     865                 err = -ENOENT;
>     866                 goto out;
>     867         }
>     868 
>     869         if (!attr_b->non_res) {
>     870                 *lcn = RESIDENT_LCN;
>     871                 *len = 1;
>     872                 goto out;
>     873         }
>     874 
>     875         asize = le64_to_cpu(attr_b->nres.alloc_size) >> sbi->cluster_bits;
>     876         if (vcn >= asize) {
>     877                 err = -EINVAL;
>     878                 goto out;
>     879         }
>     880 
>     881         clst_per_frame = 1u << attr_b->nres.c_unit;
>     882         to_alloc = (clen + clst_per_frame - 1) & ~(clst_per_frame - 1);
>     883 
>     884         if (vcn + to_alloc > asize)
>     885                 to_alloc = asize - vcn;
>     886 
>     887         svcn = le64_to_cpu(attr_b->nres.svcn);
>     888         evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
>     889 
>     890         attr = attr_b;
>     891         le = le_b;
>     892         mi = mi_b;
>     893 
>     894         if (le_b && (vcn < svcn || evcn1 <= vcn)) {
>     895                 attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
>     896                                     &mi);
>     897                 if (!attr) {
>     898                         err = -EINVAL;
>     899                         goto out;
>     900                 }
>     901                 svcn = le64_to_cpu(attr->nres.svcn);
>     902                 evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
>     903         }
>     904 
>     905         err = attr_load_runs(attr, ni, run, NULL);
>     906         if (err)
>     907                 goto out;
>     908 
>     909         if (!ok) {
>     910                 ok = run_lookup_entry(run, vcn, lcn, len, NULL);
>     911                 if (ok && (*lcn != SPARSE_LCN || !new)) {
>     912                         /* normal way */
>     913                         err = 0;
>     914                         goto ok;
>     915                 }
>     916 
>     917                 if (!ok && !new) {
>     918                         *len = 0;
>     919                         err = 0;
>     920                         goto ok;
>     921                 }
>     922 
>     923                 if (ok && clen > *len) {
>     924                         clen = *len;
>     925                         to_alloc = (clen + clst_per_frame - 1) &
>     926                                    ~(clst_per_frame - 1);
>     927                 }
>     928         }
>     929 
>     930         if (!is_attr_ext(attr_b)) {
>     931                 err = -EINVAL;
>     932                 goto out;
>     933         }
>     934 
>     935         /* Get the last lcn to allocate from */
>     936         hint = 0;
>     937 
>     938         if (vcn > evcn1) {
>     939                 if (!run_add_entry(run, evcn1, SPARSE_LCN, vcn - evcn1,
>     940                                    false)) {
>     941                         err = -ENOMEM;
>     942                         goto out;
>     943                 }
>     944         } else if (vcn && !run_lookup_entry(run, vcn - 1, &hint, NULL, NULL)) {
>     945                 hint = -1;
>     946         }
>     947 
>     948         err = attr_allocate_clusters(
>     949                 sbi, run, vcn, hint + 1, to_alloc, NULL, 0, len,
>     950                 (sbi->record_size - le32_to_cpu(mi->mrec->used) + 8) / 3 + 1,
>     951                 lcn);
>     952         if (err)
>     953                 goto out;
>     954         *new = true;
>     955 
>     956         end = vcn + *len;
>     957 
>     958         total_size = le64_to_cpu(attr_b->nres.total_size) +
>     959                      ((u64)*len << cluster_bits);
>     960 
>     961 repack:
>     962         err = mi_pack_runs(mi, attr, run, max(end, evcn1) - svcn);
>     963         if (err)
>     964                 goto out;
>     965 
>     966         attr_b->nres.total_size = cpu_to_le64(total_size);
>     967         inode_set_bytes(&ni->vfs_inode, total_size);
>     968         ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
>     969 
>     970         mi_b->dirty = true;
>     971         mark_inode_dirty(&ni->vfs_inode);
>     972 
>     973         /* stored [vcn : next_svcn) from [vcn : end) */
>     974         next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
>     975 
>     976         if (end <= evcn1) {
>     977                 if (next_svcn == evcn1) {
>     978                         /* Normal way. update attribute and exit */
>     979                         goto ok;
>     980                 }
>     981                 /* add new segment [next_svcn : evcn1 - next_svcn )*/
>     982                 if (!ni->attr_list.size) {
>     983                         err = ni_create_attr_list(ni);
>     984                         if (err)
>     985                                 goto out;
>     986                         /* layout of records is changed */
>     987                         le_b = NULL;
>     988                         attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL,
>     989                                               0, NULL, &mi_b);
>     990                         if (!attr_b) {
>     991                                 err = -ENOENT;
>     992                                 goto out;
>     993                         }
>     994 
>     995                         attr = attr_b;
>     996                         le = le_b;
>     997                         mi = mi_b;
>     998                         goto repack;
>     999                 }
>     1000         }
>     1001 
>     1002         svcn = evcn1;
>     1003 
>     1004         /* Estimate next attribute */
>     1005         attr = ni_find_attr(ni, attr, &le, ATTR_DATA, NULL, 0, &svcn, &mi);
>     1006 
>     1007         if (attr) {
>     1008                 CLST alloc = bytes_to_cluster(
>     1009                         sbi, le64_to_cpu(attr_b->nres.alloc_size));
>     1010                 CLST evcn = le64_to_cpu(attr->nres.evcn);
>     1011 
>     1012                 if (end < next_svcn)
>     1013                         end = next_svcn;
>     1014                 while (end > evcn) {
>     1015                         /* remove segment [svcn : evcn)*/
>     1016                         mi_remove_attr(mi, attr);
>     1017 
>     1018                         if (!al_remove_le(ni, le)) {
>     1019                                 err = -EINVAL;
>     1020                                 goto out;
>     1021                         }
>     1022 
>     1023                         if (evcn + 1 >= alloc) {
>     1024                                 /* last attribute segment */
>     1025                                 evcn1 = evcn + 1;
>     1026                                 goto ins_ext;
>     1027                         }
>     1028 
>     1029                         if (ni_load_mi(ni, le, &mi)) {
>     1030                                 attr = NULL;
> 
> No error code on this path.  Also no need to set "attr" to NULL.

This same code can also be founded from attr_allocate_frame(). This
"repack" really needs to be own function.

> 
> --> 1031                                 goto out;
>     1032                         }
>     1033 
>     1034                         attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0,
>     1035                                             &le->id);
>     1036                         if (!attr) {
>     1037                                 err = -EINVAL;
>     1038                                 goto out;
>     1039                         }
>     1040                         svcn = le64_to_cpu(attr->nres.svcn);
>     1041                         evcn = le64_to_cpu(attr->nres.evcn);
>     1042                 }
>     1043 
>     1044                 if (end < svcn)
>     1045                         end = svcn;
>     1046 
>     1047                 err = attr_load_runs(attr, ni, run, &end);
>     1048                 if (err)
>     1049                         goto out;
>     1050 
>     1051                 evcn1 = evcn + 1;
>     1052                 attr->nres.svcn = cpu_to_le64(next_svcn);
>     1053                 err = mi_pack_runs(mi, attr, run, evcn1 - next_svcn);
>     1054                 if (err)
>     1055                         goto out;
>     1056 
>     1057                 le->vcn = cpu_to_le64(next_svcn);
>     1058                 ni->attr_list.dirty = true;
>     1059                 mi->dirty = true;
>     1060 
>     1061                 next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
>     1062         }
>     1063 ins_ext:
>     1064         if (evcn1 > next_svcn) {
>     1065                 err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run,
>     1066                                             next_svcn, evcn1 - next_svcn,
>     1067                                             attr_b->flags, &attr, &mi);
>     1068                 if (err)
>     1069                         goto out;
>     1070         }
>     1071 ok:
>     1072         run_truncate_around(run, vcn);
>     1073 out:
>     1074         up_write(&ni->file.run_lock);
>     1075         ni_unlock(ni);
>     1076 
>     1077         return err;
>     1078 }
> 
> regards,
> dan carpenter
> 




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux