linux/fs/exfat/fatent.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
   4 */
   5
   6#include <linux/slab.h>
   7#include <asm/unaligned.h>
   8#include <linux/buffer_head.h>
   9
  10#include "exfat_raw.h"
  11#include "exfat_fs.h"
  12
  13static int exfat_mirror_bh(struct super_block *sb, sector_t sec,
  14                struct buffer_head *bh)
  15{
  16        struct buffer_head *c_bh;
  17        struct exfat_sb_info *sbi = EXFAT_SB(sb);
  18        sector_t sec2;
  19        int err = 0;
  20
  21        if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) {
  22                sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector;
  23                c_bh = sb_getblk(sb, sec2);
  24                if (!c_bh)
  25                        return -ENOMEM;
  26                memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
  27                set_buffer_uptodate(c_bh);
  28                mark_buffer_dirty(c_bh);
  29                if (sb->s_flags & SB_SYNCHRONOUS)
  30                        err = sync_dirty_buffer(c_bh);
  31                brelse(c_bh);
  32        }
  33
  34        return err;
  35}
  36
  37static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
  38                unsigned int *content)
  39{
  40        unsigned int off;
  41        sector_t sec;
  42        struct buffer_head *bh;
  43
  44        sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
  45        off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
  46
  47        bh = sb_bread(sb, sec);
  48        if (!bh)
  49                return -EIO;
  50
  51        *content = le32_to_cpu(*(__le32 *)(&bh->b_data[off]));
  52
  53        /* remap reserved clusters to simplify code */
  54        if (*content > EXFAT_BAD_CLUSTER)
  55                *content = EXFAT_EOF_CLUSTER;
  56
  57        brelse(bh);
  58        return 0;
  59}
  60
  61int exfat_ent_set(struct super_block *sb, unsigned int loc,
  62                unsigned int content)
  63{
  64        unsigned int off;
  65        sector_t sec;
  66        __le32 *fat_entry;
  67        struct buffer_head *bh;
  68
  69        sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
  70        off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
  71
  72        bh = sb_bread(sb, sec);
  73        if (!bh)
  74                return -EIO;
  75
  76        fat_entry = (__le32 *)&(bh->b_data[off]);
  77        *fat_entry = cpu_to_le32(content);
  78        exfat_update_bh(bh, sb->s_flags & SB_SYNCHRONOUS);
  79        exfat_mirror_bh(sb, sec, bh);
  80        brelse(bh);
  81        return 0;
  82}
  83
  84static inline bool is_valid_cluster(struct exfat_sb_info *sbi,
  85                unsigned int clus)
  86{
  87        if (clus < EXFAT_FIRST_CLUSTER || sbi->num_clusters <= clus)
  88                return false;
  89        return true;
  90}
  91
  92int exfat_ent_get(struct super_block *sb, unsigned int loc,
  93                unsigned int *content)
  94{
  95        struct exfat_sb_info *sbi = EXFAT_SB(sb);
  96        int err;
  97
  98        if (!is_valid_cluster(sbi, loc)) {
  99                exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)",
 100                        loc);
 101                return -EIO;
 102        }
 103
 104        err = __exfat_ent_get(sb, loc, content);
 105        if (err) {
 106                exfat_fs_error(sb,
 107                        "failed to access to FAT (entry 0x%08x, err:%d)",
 108                        loc, err);
 109                return err;
 110        }
 111
 112        if (*content == EXFAT_FREE_CLUSTER) {
 113                exfat_fs_error(sb,
 114                        "invalid access to FAT free cluster (entry 0x%08x)",
 115                        loc);
 116                return -EIO;
 117        }
 118
 119        if (*content == EXFAT_BAD_CLUSTER) {
 120                exfat_fs_error(sb,
 121                        "invalid access to FAT bad cluster (entry 0x%08x)",
 122                        loc);
 123                return -EIO;
 124        }
 125
 126        if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) {
 127                exfat_fs_error(sb,
 128                        "invalid access to FAT (entry 0x%08x) bogus content (0x%08x)",
 129                        loc, *content);
 130                return -EIO;
 131        }
 132
 133        return 0;
 134}
 135
 136int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
 137                unsigned int len)
 138{
 139        if (!len)
 140                return 0;
 141
 142        while (len > 1) {
 143                if (exfat_ent_set(sb, chain, chain + 1))
 144                        return -EIO;
 145                chain++;
 146                len--;
 147        }
 148
 149        if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER))
 150                return -EIO;
 151        return 0;
 152}
 153
 154int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
 155{
 156        unsigned int num_clusters = 0;
 157        unsigned int clu;
 158        struct super_block *sb = inode->i_sb;
 159        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 160
 161        /* invalid cluster number */
 162        if (p_chain->dir == EXFAT_FREE_CLUSTER ||
 163            p_chain->dir == EXFAT_EOF_CLUSTER ||
 164            p_chain->dir < EXFAT_FIRST_CLUSTER)
 165                return 0;
 166
 167        /* no cluster to truncate */
 168        if (p_chain->size == 0)
 169                return 0;
 170
 171        /* check cluster validation */
 172        if (!is_valid_cluster(sbi, p_chain->dir)) {
 173                exfat_err(sb, "invalid start cluster (%u)", p_chain->dir);
 174                return -EIO;
 175        }
 176
 177        clu = p_chain->dir;
 178
 179        if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 180                do {
 181                        exfat_clear_bitmap(inode, clu);
 182                        clu++;
 183
 184                        num_clusters++;
 185                } while (num_clusters < p_chain->size);
 186        } else {
 187                do {
 188                        exfat_clear_bitmap(inode, clu);
 189
 190                        if (exfat_get_next_cluster(sb, &clu))
 191                                goto dec_used_clus;
 192
 193                        num_clusters++;
 194                } while (clu != EXFAT_EOF_CLUSTER);
 195        }
 196
 197dec_used_clus:
 198        sbi->used_clusters -= num_clusters;
 199        return 0;
 200}
 201
 202int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
 203                unsigned int *ret_clu)
 204{
 205        unsigned int clu, next;
 206        unsigned int count = 0;
 207
 208        next = p_chain->dir;
 209        if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 210                *ret_clu = next + p_chain->size - 1;
 211                return 0;
 212        }
 213
 214        do {
 215                count++;
 216                clu = next;
 217                if (exfat_ent_get(sb, clu, &next))
 218                        return -EIO;
 219        } while (next != EXFAT_EOF_CLUSTER);
 220
 221        if (p_chain->size != count) {
 222                exfat_fs_error(sb,
 223                        "bogus directory size (clus : ondisk(%d) != counted(%d))",
 224                        p_chain->size, count);
 225                return -EIO;
 226        }
 227
 228        *ret_clu = clu;
 229        return 0;
 230}
 231
 232int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
 233{
 234        struct super_block *sb = dir->i_sb;
 235        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 236        struct buffer_head *bhs[MAX_BUF_PER_PAGE];
 237        int nr_bhs = MAX_BUF_PER_PAGE;
 238        sector_t blknr, last_blknr;
 239        int err, i, n;
 240
 241        blknr = exfat_cluster_to_sector(sbi, clu);
 242        last_blknr = blknr + sbi->sect_per_clus;
 243
 244        if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) {
 245                exfat_fs_error_ratelimit(sb,
 246                        "%s: out of range(sect:%llu len:%u)",
 247                        __func__, (unsigned long long)blknr,
 248                        sbi->sect_per_clus);
 249                return -EIO;
 250        }
 251
 252        /* Zeroing the unused blocks on this cluster */
 253        while (blknr < last_blknr) {
 254                for (n = 0; n < nr_bhs && blknr < last_blknr; n++, blknr++) {
 255                        bhs[n] = sb_getblk(sb, blknr);
 256                        if (!bhs[n]) {
 257                                err = -ENOMEM;
 258                                goto release_bhs;
 259                        }
 260                        memset(bhs[n]->b_data, 0, sb->s_blocksize);
 261                }
 262
 263                err = exfat_update_bhs(bhs, n, IS_DIRSYNC(dir));
 264                if (err)
 265                        goto release_bhs;
 266
 267                for (i = 0; i < n; i++)
 268                        brelse(bhs[i]);
 269        }
 270        return 0;
 271
 272release_bhs:
 273        exfat_err(sb, "failed zeroed sect %llu\n", (unsigned long long)blknr);
 274        for (i = 0; i < n; i++)
 275                bforget(bhs[i]);
 276        return err;
 277}
 278
 279int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
 280                struct exfat_chain *p_chain)
 281{
 282        int ret = -ENOSPC;
 283        unsigned int num_clusters = 0, total_cnt;
 284        unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
 285        struct super_block *sb = inode->i_sb;
 286        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 287
 288        total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi);
 289
 290        if (unlikely(total_cnt < sbi->used_clusters)) {
 291                exfat_fs_error_ratelimit(sb,
 292                        "%s: invalid used clusters(t:%u,u:%u)\n",
 293                        __func__, total_cnt, sbi->used_clusters);
 294                return -EIO;
 295        }
 296
 297        if (num_alloc > total_cnt - sbi->used_clusters)
 298                return -ENOSPC;
 299
 300        hint_clu = p_chain->dir;
 301        /* find new cluster */
 302        if (hint_clu == EXFAT_EOF_CLUSTER) {
 303                if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
 304                        exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)\n",
 305                                  sbi->clu_srch_ptr);
 306                        sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
 307                }
 308
 309                hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
 310                if (hint_clu == EXFAT_EOF_CLUSTER)
 311                        return -ENOSPC;
 312        }
 313
 314        /* check cluster validation */
 315        if (!is_valid_cluster(sbi, hint_clu)) {
 316                exfat_err(sb, "hint_cluster is invalid (%u)",
 317                        hint_clu);
 318                hint_clu = EXFAT_FIRST_CLUSTER;
 319                if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 320                        if (exfat_chain_cont_cluster(sb, p_chain->dir,
 321                                        num_clusters))
 322                                return -EIO;
 323                        p_chain->flags = ALLOC_FAT_CHAIN;
 324                }
 325        }
 326
 327        p_chain->dir = EXFAT_EOF_CLUSTER;
 328
 329        while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) !=
 330               EXFAT_EOF_CLUSTER) {
 331                if (new_clu != hint_clu &&
 332                    p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 333                        if (exfat_chain_cont_cluster(sb, p_chain->dir,
 334                                        num_clusters)) {
 335                                ret = -EIO;
 336                                goto free_cluster;
 337                        }
 338                        p_chain->flags = ALLOC_FAT_CHAIN;
 339                }
 340
 341                /* update allocation bitmap */
 342                if (exfat_set_bitmap(inode, new_clu)) {
 343                        ret = -EIO;
 344                        goto free_cluster;
 345                }
 346
 347                num_clusters++;
 348
 349                /* update FAT table */
 350                if (p_chain->flags == ALLOC_FAT_CHAIN) {
 351                        if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
 352                                ret = -EIO;
 353                                goto free_cluster;
 354                        }
 355                }
 356
 357                if (p_chain->dir == EXFAT_EOF_CLUSTER) {
 358                        p_chain->dir = new_clu;
 359                } else if (p_chain->flags == ALLOC_FAT_CHAIN) {
 360                        if (exfat_ent_set(sb, last_clu, new_clu)) {
 361                                ret = -EIO;
 362                                goto free_cluster;
 363                        }
 364                }
 365                last_clu = new_clu;
 366
 367                if (--num_alloc == 0) {
 368                        sbi->clu_srch_ptr = hint_clu;
 369                        sbi->used_clusters += num_clusters;
 370
 371                        p_chain->size += num_clusters;
 372                        return 0;
 373                }
 374
 375                hint_clu = new_clu + 1;
 376                if (hint_clu >= sbi->num_clusters) {
 377                        hint_clu = EXFAT_FIRST_CLUSTER;
 378
 379                        if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 380                                if (exfat_chain_cont_cluster(sb, p_chain->dir,
 381                                                num_clusters)) {
 382                                        ret = -EIO;
 383                                        goto free_cluster;
 384                                }
 385                                p_chain->flags = ALLOC_FAT_CHAIN;
 386                        }
 387                }
 388        }
 389free_cluster:
 390        if (num_clusters)
 391                exfat_free_cluster(inode, p_chain);
 392        return ret;
 393}
 394
 395int exfat_count_num_clusters(struct super_block *sb,
 396                struct exfat_chain *p_chain, unsigned int *ret_count)
 397{
 398        unsigned int i, count;
 399        unsigned int clu;
 400        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 401
 402        if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) {
 403                *ret_count = 0;
 404                return 0;
 405        }
 406
 407        if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
 408                *ret_count = p_chain->size;
 409                return 0;
 410        }
 411
 412        clu = p_chain->dir;
 413        count = 0;
 414        for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
 415                count++;
 416                if (exfat_ent_get(sb, clu, &clu))
 417                        return -EIO;
 418                if (clu == EXFAT_EOF_CLUSTER)
 419                        break;
 420        }
 421
 422        *ret_count = count;
 423        return 0;
 424}
 425