18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Generic part */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_citypedef struct { 58c2ecf20Sopenharmony_ci block_t *p; 68c2ecf20Sopenharmony_ci block_t key; 78c2ecf20Sopenharmony_ci struct buffer_head *bh; 88c2ecf20Sopenharmony_ci} Indirect; 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistatic DEFINE_RWLOCK(pointers_lock); 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic inline void add_chain(Indirect *p, struct buffer_head *bh, block_t *v) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci p->key = *(p->p = v); 158c2ecf20Sopenharmony_ci p->bh = bh; 168c2ecf20Sopenharmony_ci} 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic inline int verify_chain(Indirect *from, Indirect *to) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci while (from <= to && from->key == *from->p) 218c2ecf20Sopenharmony_ci from++; 228c2ecf20Sopenharmony_ci return (from > to); 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic inline block_t *block_end(struct buffer_head *bh) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci return (block_t *)((char*)bh->b_data + bh->b_size); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic inline Indirect *get_branch(struct inode *inode, 318c2ecf20Sopenharmony_ci int depth, 328c2ecf20Sopenharmony_ci int *offsets, 338c2ecf20Sopenharmony_ci Indirect chain[DEPTH], 348c2ecf20Sopenharmony_ci int *err) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct super_block *sb = inode->i_sb; 378c2ecf20Sopenharmony_ci Indirect *p = chain; 388c2ecf20Sopenharmony_ci struct buffer_head *bh; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci *err = 0; 418c2ecf20Sopenharmony_ci /* i_data is not going away, no lock needed */ 428c2ecf20Sopenharmony_ci add_chain (chain, NULL, i_data(inode) + *offsets); 438c2ecf20Sopenharmony_ci if (!p->key) 448c2ecf20Sopenharmony_ci goto no_block; 458c2ecf20Sopenharmony_ci while (--depth) { 468c2ecf20Sopenharmony_ci bh = sb_bread(sb, block_to_cpu(p->key)); 478c2ecf20Sopenharmony_ci if (!bh) 488c2ecf20Sopenharmony_ci goto failure; 498c2ecf20Sopenharmony_ci read_lock(&pointers_lock); 508c2ecf20Sopenharmony_ci if (!verify_chain(chain, p)) 518c2ecf20Sopenharmony_ci goto changed; 528c2ecf20Sopenharmony_ci add_chain(++p, bh, (block_t *)bh->b_data + *++offsets); 538c2ecf20Sopenharmony_ci read_unlock(&pointers_lock); 548c2ecf20Sopenharmony_ci if (!p->key) 558c2ecf20Sopenharmony_ci goto no_block; 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci return NULL; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cichanged: 608c2ecf20Sopenharmony_ci read_unlock(&pointers_lock); 618c2ecf20Sopenharmony_ci brelse(bh); 628c2ecf20Sopenharmony_ci *err = -EAGAIN; 638c2ecf20Sopenharmony_ci goto no_block; 648c2ecf20Sopenharmony_cifailure: 658c2ecf20Sopenharmony_ci *err = -EIO; 668c2ecf20Sopenharmony_cino_block: 678c2ecf20Sopenharmony_ci return p; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int alloc_branch(struct inode *inode, 718c2ecf20Sopenharmony_ci int num, 728c2ecf20Sopenharmony_ci int *offsets, 738c2ecf20Sopenharmony_ci Indirect *branch) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci int n = 0; 768c2ecf20Sopenharmony_ci int i; 778c2ecf20Sopenharmony_ci int parent = minix_new_block(inode); 788c2ecf20Sopenharmony_ci int err = -ENOSPC; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci branch[0].key = cpu_to_block(parent); 818c2ecf20Sopenharmony_ci if (parent) for (n = 1; n < num; n++) { 828c2ecf20Sopenharmony_ci struct buffer_head *bh; 838c2ecf20Sopenharmony_ci /* Allocate the next block */ 848c2ecf20Sopenharmony_ci int nr = minix_new_block(inode); 858c2ecf20Sopenharmony_ci if (!nr) 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci branch[n].key = cpu_to_block(nr); 888c2ecf20Sopenharmony_ci bh = sb_getblk(inode->i_sb, parent); 898c2ecf20Sopenharmony_ci if (!bh) { 908c2ecf20Sopenharmony_ci minix_free_block(inode, nr); 918c2ecf20Sopenharmony_ci err = -ENOMEM; 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci lock_buffer(bh); 958c2ecf20Sopenharmony_ci memset(bh->b_data, 0, bh->b_size); 968c2ecf20Sopenharmony_ci branch[n].bh = bh; 978c2ecf20Sopenharmony_ci branch[n].p = (block_t*) bh->b_data + offsets[n]; 988c2ecf20Sopenharmony_ci *branch[n].p = branch[n].key; 998c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 1008c2ecf20Sopenharmony_ci unlock_buffer(bh); 1018c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 1028c2ecf20Sopenharmony_ci parent = nr; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci if (n == num) 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Allocation failed, free what we already allocated */ 1088c2ecf20Sopenharmony_ci for (i = 1; i < n; i++) 1098c2ecf20Sopenharmony_ci bforget(branch[i].bh); 1108c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 1118c2ecf20Sopenharmony_ci minix_free_block(inode, block_to_cpu(branch[i].key)); 1128c2ecf20Sopenharmony_ci return err; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic inline int splice_branch(struct inode *inode, 1168c2ecf20Sopenharmony_ci Indirect chain[DEPTH], 1178c2ecf20Sopenharmony_ci Indirect *where, 1188c2ecf20Sopenharmony_ci int num) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int i; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci write_lock(&pointers_lock); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Verify that place we are splicing to is still there and vacant */ 1258c2ecf20Sopenharmony_ci if (!verify_chain(chain, where-1) || *where->p) 1268c2ecf20Sopenharmony_ci goto changed; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci *where->p = where->key; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci write_unlock(&pointers_lock); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* We are done with atomic stuff, now do the rest of housekeeping */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci inode->i_ctime = current_time(inode); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* had we spliced it onto indirect block? */ 1378c2ecf20Sopenharmony_ci if (where->bh) 1388c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(where->bh, inode); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cichanged: 1448c2ecf20Sopenharmony_ci write_unlock(&pointers_lock); 1458c2ecf20Sopenharmony_ci for (i = 1; i < num; i++) 1468c2ecf20Sopenharmony_ci bforget(where[i].bh); 1478c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) 1488c2ecf20Sopenharmony_ci minix_free_block(inode, block_to_cpu(where[i].key)); 1498c2ecf20Sopenharmony_ci return -EAGAIN; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic int get_block(struct inode * inode, sector_t block, 1538c2ecf20Sopenharmony_ci struct buffer_head *bh, int create) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci int err = -EIO; 1568c2ecf20Sopenharmony_ci int offsets[DEPTH]; 1578c2ecf20Sopenharmony_ci Indirect chain[DEPTH]; 1588c2ecf20Sopenharmony_ci Indirect *partial; 1598c2ecf20Sopenharmony_ci int left; 1608c2ecf20Sopenharmony_ci int depth = block_to_path(inode, block, offsets); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (depth == 0) 1638c2ecf20Sopenharmony_ci goto out; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cireread: 1668c2ecf20Sopenharmony_ci partial = get_branch(inode, depth, offsets, chain, &err); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* Simplest case - block found, no allocation needed */ 1698c2ecf20Sopenharmony_ci if (!partial) { 1708c2ecf20Sopenharmony_cigot_it: 1718c2ecf20Sopenharmony_ci map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); 1728c2ecf20Sopenharmony_ci /* Clean up and exit */ 1738c2ecf20Sopenharmony_ci partial = chain+depth-1; /* the whole chain */ 1748c2ecf20Sopenharmony_ci goto cleanup; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* Next simple case - plain lookup or failed read of indirect block */ 1788c2ecf20Sopenharmony_ci if (!create || err == -EIO) { 1798c2ecf20Sopenharmony_cicleanup: 1808c2ecf20Sopenharmony_ci while (partial > chain) { 1818c2ecf20Sopenharmony_ci brelse(partial->bh); 1828c2ecf20Sopenharmony_ci partial--; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ciout: 1858c2ecf20Sopenharmony_ci return err; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci /* 1898c2ecf20Sopenharmony_ci * Indirect block might be removed by truncate while we were 1908c2ecf20Sopenharmony_ci * reading it. Handling of that case (forget what we've got and 1918c2ecf20Sopenharmony_ci * reread) is taken out of the main path. 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_ci if (err == -EAGAIN) 1948c2ecf20Sopenharmony_ci goto changed; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci left = (chain + depth) - partial; 1978c2ecf20Sopenharmony_ci err = alloc_branch(inode, left, offsets+(partial-chain), partial); 1988c2ecf20Sopenharmony_ci if (err) 1998c2ecf20Sopenharmony_ci goto cleanup; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (splice_branch(inode, chain, partial, left) < 0) 2028c2ecf20Sopenharmony_ci goto changed; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci set_buffer_new(bh); 2058c2ecf20Sopenharmony_ci goto got_it; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cichanged: 2088c2ecf20Sopenharmony_ci while (partial > chain) { 2098c2ecf20Sopenharmony_ci brelse(partial->bh); 2108c2ecf20Sopenharmony_ci partial--; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci goto reread; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic inline int all_zeroes(block_t *p, block_t *q) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci while (p < q) 2188c2ecf20Sopenharmony_ci if (*p++) 2198c2ecf20Sopenharmony_ci return 0; 2208c2ecf20Sopenharmony_ci return 1; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic Indirect *find_shared(struct inode *inode, 2248c2ecf20Sopenharmony_ci int depth, 2258c2ecf20Sopenharmony_ci int offsets[DEPTH], 2268c2ecf20Sopenharmony_ci Indirect chain[DEPTH], 2278c2ecf20Sopenharmony_ci block_t *top) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci Indirect *partial, *p; 2308c2ecf20Sopenharmony_ci int k, err; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci *top = 0; 2338c2ecf20Sopenharmony_ci for (k = depth; k > 1 && !offsets[k-1]; k--) 2348c2ecf20Sopenharmony_ci ; 2358c2ecf20Sopenharmony_ci partial = get_branch(inode, k, offsets, chain, &err); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci write_lock(&pointers_lock); 2388c2ecf20Sopenharmony_ci if (!partial) 2398c2ecf20Sopenharmony_ci partial = chain + k-1; 2408c2ecf20Sopenharmony_ci if (!partial->key && *partial->p) { 2418c2ecf20Sopenharmony_ci write_unlock(&pointers_lock); 2428c2ecf20Sopenharmony_ci goto no_top; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--) 2458c2ecf20Sopenharmony_ci ; 2468c2ecf20Sopenharmony_ci if (p == chain + k - 1 && p > chain) { 2478c2ecf20Sopenharmony_ci p->p--; 2488c2ecf20Sopenharmony_ci } else { 2498c2ecf20Sopenharmony_ci *top = *p->p; 2508c2ecf20Sopenharmony_ci *p->p = 0; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci write_unlock(&pointers_lock); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci while(partial > p) 2558c2ecf20Sopenharmony_ci { 2568c2ecf20Sopenharmony_ci brelse(partial->bh); 2578c2ecf20Sopenharmony_ci partial--; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_cino_top: 2608c2ecf20Sopenharmony_ci return partial; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic inline void free_data(struct inode *inode, block_t *p, block_t *q) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci unsigned long nr; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci for ( ; p < q ; p++) { 2688c2ecf20Sopenharmony_ci nr = block_to_cpu(*p); 2698c2ecf20Sopenharmony_ci if (nr) { 2708c2ecf20Sopenharmony_ci *p = 0; 2718c2ecf20Sopenharmony_ci minix_free_block(inode, nr); 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic void free_branches(struct inode *inode, block_t *p, block_t *q, int depth) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci struct buffer_head * bh; 2798c2ecf20Sopenharmony_ci unsigned long nr; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (depth--) { 2828c2ecf20Sopenharmony_ci for ( ; p < q ; p++) { 2838c2ecf20Sopenharmony_ci nr = block_to_cpu(*p); 2848c2ecf20Sopenharmony_ci if (!nr) 2858c2ecf20Sopenharmony_ci continue; 2868c2ecf20Sopenharmony_ci *p = 0; 2878c2ecf20Sopenharmony_ci bh = sb_bread(inode->i_sb, nr); 2888c2ecf20Sopenharmony_ci if (!bh) 2898c2ecf20Sopenharmony_ci continue; 2908c2ecf20Sopenharmony_ci free_branches(inode, (block_t*)bh->b_data, 2918c2ecf20Sopenharmony_ci block_end(bh), depth); 2928c2ecf20Sopenharmony_ci bforget(bh); 2938c2ecf20Sopenharmony_ci minix_free_block(inode, nr); 2948c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci } else 2978c2ecf20Sopenharmony_ci free_data(inode, p, q); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic inline void truncate (struct inode * inode) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct super_block *sb = inode->i_sb; 3038c2ecf20Sopenharmony_ci block_t *idata = i_data(inode); 3048c2ecf20Sopenharmony_ci int offsets[DEPTH]; 3058c2ecf20Sopenharmony_ci Indirect chain[DEPTH]; 3068c2ecf20Sopenharmony_ci Indirect *partial; 3078c2ecf20Sopenharmony_ci block_t nr = 0; 3088c2ecf20Sopenharmony_ci int n; 3098c2ecf20Sopenharmony_ci int first_whole; 3108c2ecf20Sopenharmony_ci long iblock; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits; 3138c2ecf20Sopenharmony_ci block_truncate_page(inode->i_mapping, inode->i_size, get_block); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci n = block_to_path(inode, iblock, offsets); 3168c2ecf20Sopenharmony_ci if (!n) 3178c2ecf20Sopenharmony_ci return; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (n == 1) { 3208c2ecf20Sopenharmony_ci free_data(inode, idata+offsets[0], idata + DIRECT); 3218c2ecf20Sopenharmony_ci first_whole = 0; 3228c2ecf20Sopenharmony_ci goto do_indirects; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci first_whole = offsets[0] + 1 - DIRECT; 3268c2ecf20Sopenharmony_ci partial = find_shared(inode, n, offsets, chain, &nr); 3278c2ecf20Sopenharmony_ci if (nr) { 3288c2ecf20Sopenharmony_ci if (partial == chain) 3298c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 3308c2ecf20Sopenharmony_ci else 3318c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(partial->bh, inode); 3328c2ecf20Sopenharmony_ci free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci /* Clear the ends of indirect blocks on the shared branch */ 3358c2ecf20Sopenharmony_ci while (partial > chain) { 3368c2ecf20Sopenharmony_ci free_branches(inode, partial->p + 1, block_end(partial->bh), 3378c2ecf20Sopenharmony_ci (chain+n-1) - partial); 3388c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(partial->bh, inode); 3398c2ecf20Sopenharmony_ci brelse (partial->bh); 3408c2ecf20Sopenharmony_ci partial--; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_cido_indirects: 3438c2ecf20Sopenharmony_ci /* Kill the remaining (whole) subtrees */ 3448c2ecf20Sopenharmony_ci while (first_whole < DEPTH-1) { 3458c2ecf20Sopenharmony_ci nr = idata[DIRECT+first_whole]; 3468c2ecf20Sopenharmony_ci if (nr) { 3478c2ecf20Sopenharmony_ci idata[DIRECT+first_whole] = 0; 3488c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 3498c2ecf20Sopenharmony_ci free_branches(inode, &nr, &nr+1, first_whole+1); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci first_whole++; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci inode->i_mtime = inode->i_ctime = current_time(inode); 3548c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic inline unsigned nblocks(loff_t size, struct super_block *sb) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci int k = sb->s_blocksize_bits - 10; 3608c2ecf20Sopenharmony_ci unsigned blocks, res, direct = DIRECT, i = DEPTH; 3618c2ecf20Sopenharmony_ci blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k); 3628c2ecf20Sopenharmony_ci res = blocks; 3638c2ecf20Sopenharmony_ci while (--i && blocks > direct) { 3648c2ecf20Sopenharmony_ci blocks -= direct; 3658c2ecf20Sopenharmony_ci blocks += sb->s_blocksize/sizeof(block_t) - 1; 3668c2ecf20Sopenharmony_ci blocks /= sb->s_blocksize/sizeof(block_t); 3678c2ecf20Sopenharmony_ci res += blocks; 3688c2ecf20Sopenharmony_ci direct = 1; 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci return res; 3718c2ecf20Sopenharmony_ci} 372