1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 29e33d69fSJan Kara /* 39e33d69fSJan Kara * Implementation of operations over local quota file 49e33d69fSJan Kara */ 59e33d69fSJan Kara 69e33d69fSJan Kara #include <linux/fs.h> 75a0e3ad6STejun Heo #include <linux/slab.h> 89e33d69fSJan Kara #include <linux/quota.h> 99e33d69fSJan Kara #include <linux/quotaops.h> 109e33d69fSJan Kara #include <linux/module.h> 119e33d69fSJan Kara 129e33d69fSJan Kara #include <cluster/masklog.h> 139e33d69fSJan Kara 149e33d69fSJan Kara #include "ocfs2_fs.h" 159e33d69fSJan Kara #include "ocfs2.h" 169e33d69fSJan Kara #include "inode.h" 179e33d69fSJan Kara #include "alloc.h" 189e33d69fSJan Kara #include "file.h" 199e33d69fSJan Kara #include "buffer_head_io.h" 209e33d69fSJan Kara #include "journal.h" 219e33d69fSJan Kara #include "sysfile.h" 229e33d69fSJan Kara #include "dlmglue.h" 239e33d69fSJan Kara #include "quota.h" 244b3fa190SJan Kara #include "uptodate.h" 25fb8dd8d7SJan Kara #include "super.h" 2638877a43STao Ma #include "ocfs2_trace.h" 279e33d69fSJan Kara 289e33d69fSJan Kara /* Number of local quota structures per block */ 299e33d69fSJan Kara static inline unsigned int ol_quota_entries_per_block(struct super_block *sb) 309e33d69fSJan Kara { 319e33d69fSJan Kara return ((sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) / 329e33d69fSJan Kara sizeof(struct ocfs2_local_disk_dqblk)); 339e33d69fSJan Kara } 349e33d69fSJan Kara 359e33d69fSJan Kara /* Number of blocks with entries in one chunk */ 369e33d69fSJan Kara static inline unsigned int ol_chunk_blocks(struct super_block *sb) 379e33d69fSJan Kara { 389e33d69fSJan Kara return ((sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) - 399e33d69fSJan Kara OCFS2_QBLK_RESERVED_SPACE) << 3) / 409e33d69fSJan Kara ol_quota_entries_per_block(sb); 419e33d69fSJan Kara } 429e33d69fSJan Kara 439e33d69fSJan Kara /* Number of entries in a chunk bitmap */ 449e33d69fSJan Kara static unsigned int ol_chunk_entries(struct super_block *sb) 459e33d69fSJan Kara { 469e33d69fSJan Kara return ol_chunk_blocks(sb) * ol_quota_entries_per_block(sb); 479e33d69fSJan Kara } 489e33d69fSJan Kara 499e33d69fSJan Kara /* Offset of the chunk in quota file */ 509e33d69fSJan Kara static unsigned int ol_quota_chunk_block(struct super_block *sb, int c) 519e33d69fSJan Kara { 529e33d69fSJan Kara /* 1 block for local quota file info, 1 block per chunk for chunk info */ 539e33d69fSJan Kara return 1 + (ol_chunk_blocks(sb) + 1) * c; 549e33d69fSJan Kara } 559e33d69fSJan Kara 562205363dSJan Kara static unsigned int ol_dqblk_block(struct super_block *sb, int c, int off) 579e33d69fSJan Kara { 589e33d69fSJan Kara int epb = ol_quota_entries_per_block(sb); 599e33d69fSJan Kara 602205363dSJan Kara return ol_quota_chunk_block(sb, c) + 1 + off / epb; 612205363dSJan Kara } 622205363dSJan Kara 632205363dSJan Kara static unsigned int ol_dqblk_block_off(struct super_block *sb, int c, int off) 642205363dSJan Kara { 652205363dSJan Kara int epb = ol_quota_entries_per_block(sb); 662205363dSJan Kara 672205363dSJan Kara return (off % epb) * sizeof(struct ocfs2_local_disk_dqblk); 682205363dSJan Kara } 692205363dSJan Kara 702205363dSJan Kara /* Offset of the dquot structure in the quota file */ 712205363dSJan Kara static loff_t ol_dqblk_off(struct super_block *sb, int c, int off) 722205363dSJan Kara { 732205363dSJan Kara return (ol_dqblk_block(sb, c, off) << sb->s_blocksize_bits) + 742205363dSJan Kara ol_dqblk_block_off(sb, c, off); 759e33d69fSJan Kara } 769e33d69fSJan Kara 779e33d69fSJan Kara static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off) 789e33d69fSJan Kara { 799e33d69fSJan Kara return off & ((1 << sb->s_blocksize_bits) - 1); 809e33d69fSJan Kara } 819e33d69fSJan Kara 829e33d69fSJan Kara /* Compute offset in the chunk of a structure with the given offset */ 839e33d69fSJan Kara static int ol_dqblk_chunk_off(struct super_block *sb, int c, loff_t off) 849e33d69fSJan Kara { 859e33d69fSJan Kara int epb = ol_quota_entries_per_block(sb); 869e33d69fSJan Kara 879e33d69fSJan Kara return ((off >> sb->s_blocksize_bits) - 889e33d69fSJan Kara ol_quota_chunk_block(sb, c) - 1) * epb 899e33d69fSJan Kara + ((unsigned int)(off & ((1 << sb->s_blocksize_bits) - 1))) / 909e33d69fSJan Kara sizeof(struct ocfs2_local_disk_dqblk); 919e33d69fSJan Kara } 929e33d69fSJan Kara 939e33d69fSJan Kara /* Write bufferhead into the fs */ 949e33d69fSJan Kara static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh, 959e33d69fSJan Kara void (*modify)(struct buffer_head *, void *), void *private) 969e33d69fSJan Kara { 979e33d69fSJan Kara struct super_block *sb = inode->i_sb; 989e33d69fSJan Kara handle_t *handle; 999e33d69fSJan Kara int status; 1009e33d69fSJan Kara 1010584974aSJan Kara handle = ocfs2_start_trans(OCFS2_SB(sb), 1020584974aSJan Kara OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); 1039e33d69fSJan Kara if (IS_ERR(handle)) { 1049e33d69fSJan Kara status = PTR_ERR(handle); 1059e33d69fSJan Kara mlog_errno(status); 1069e33d69fSJan Kara return status; 1079e33d69fSJan Kara } 1080cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(inode), bh, 1099e33d69fSJan Kara OCFS2_JOURNAL_ACCESS_WRITE); 1109e33d69fSJan Kara if (status < 0) { 1119e33d69fSJan Kara mlog_errno(status); 1129e33d69fSJan Kara ocfs2_commit_trans(OCFS2_SB(sb), handle); 1139e33d69fSJan Kara return status; 1149e33d69fSJan Kara } 1159e33d69fSJan Kara lock_buffer(bh); 1169e33d69fSJan Kara modify(bh, private); 1179e33d69fSJan Kara unlock_buffer(bh); 118ec20cec7SJoel Becker ocfs2_journal_dirty(handle, bh); 119ec20cec7SJoel Becker 1209e33d69fSJan Kara status = ocfs2_commit_trans(OCFS2_SB(sb), handle); 1219e33d69fSJan Kara if (status < 0) { 1229e33d69fSJan Kara mlog_errno(status); 1239e33d69fSJan Kara return status; 1249e33d69fSJan Kara } 1259e33d69fSJan Kara return 0; 1269e33d69fSJan Kara } 1279e33d69fSJan Kara 128fb8dd8d7SJan Kara /* 129fb8dd8d7SJan Kara * Read quota block from a given logical offset. 130fb8dd8d7SJan Kara * 131fb8dd8d7SJan Kara * This function acquires ip_alloc_sem and thus it must not be called with a 132fb8dd8d7SJan Kara * transaction started. 133fb8dd8d7SJan Kara */ 134fb8dd8d7SJan Kara static int ocfs2_read_quota_block(struct inode *inode, u64 v_block, 135fb8dd8d7SJan Kara struct buffer_head **bh) 136fb8dd8d7SJan Kara { 137fb8dd8d7SJan Kara int rc = 0; 138fb8dd8d7SJan Kara struct buffer_head *tmp = *bh; 139fb8dd8d7SJan Kara 14093f5920dSJun Piao if (i_size_read(inode) >> inode->i_sb->s_blocksize_bits <= v_block) 14193f5920dSJun Piao return ocfs2_error(inode->i_sb, 1427ecef14aSJoe Perches "Quota file %llu is probably corrupted! Requested to read block %Lu but file has size only %Lu\n", 143fb8dd8d7SJan Kara (unsigned long long)OCFS2_I(inode)->ip_blkno, 144fb8dd8d7SJan Kara (unsigned long long)v_block, 145fb8dd8d7SJan Kara (unsigned long long)i_size_read(inode)); 14693f5920dSJun Piao 147fb8dd8d7SJan Kara rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0, 148fb8dd8d7SJan Kara ocfs2_validate_quota_block); 149fb8dd8d7SJan Kara if (rc) 150fb8dd8d7SJan Kara mlog_errno(rc); 151fb8dd8d7SJan Kara 152fb8dd8d7SJan Kara /* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */ 153fb8dd8d7SJan Kara if (!rc && !*bh) 154fb8dd8d7SJan Kara *bh = tmp; 155fb8dd8d7SJan Kara 156fb8dd8d7SJan Kara return rc; 157fb8dd8d7SJan Kara } 158fb8dd8d7SJan Kara 1599e33d69fSJan Kara /* Check whether we understand format of quota files */ 1609e33d69fSJan Kara static int ocfs2_local_check_quota_file(struct super_block *sb, int type) 1619e33d69fSJan Kara { 16252362810SJan Kara unsigned int lmagics[OCFS2_MAXQUOTAS] = OCFS2_LOCAL_QMAGICS; 16352362810SJan Kara unsigned int lversions[OCFS2_MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS; 16452362810SJan Kara unsigned int gmagics[OCFS2_MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS; 16552362810SJan Kara unsigned int gversions[OCFS2_MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS; 16652362810SJan Kara unsigned int ino[OCFS2_MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, 1679e33d69fSJan Kara GROUP_QUOTA_SYSTEM_INODE }; 16885eb8b73SJoel Becker struct buffer_head *bh = NULL; 1699e33d69fSJan Kara struct inode *linode = sb_dqopt(sb)->files[type]; 1709e33d69fSJan Kara struct inode *ginode = NULL; 1719e33d69fSJan Kara struct ocfs2_disk_dqheader *dqhead; 1729e33d69fSJan Kara int status, ret = 0; 1739e33d69fSJan Kara 1749e33d69fSJan Kara /* First check whether we understand local quota file */ 17585eb8b73SJoel Becker status = ocfs2_read_quota_block(linode, 0, &bh); 17685eb8b73SJoel Becker if (status) { 1779e33d69fSJan Kara mlog_errno(status); 1789e33d69fSJan Kara mlog(ML_ERROR, "failed to read quota file header (type=%d)\n", 1799e33d69fSJan Kara type); 1809e33d69fSJan Kara goto out_err; 1819e33d69fSJan Kara } 1829e33d69fSJan Kara dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data); 1839e33d69fSJan Kara if (le32_to_cpu(dqhead->dqh_magic) != lmagics[type]) { 1849e33d69fSJan Kara mlog(ML_ERROR, "quota file magic does not match (%u != %u)," 1859e33d69fSJan Kara " type=%d\n", le32_to_cpu(dqhead->dqh_magic), 1869e33d69fSJan Kara lmagics[type], type); 1879e33d69fSJan Kara goto out_err; 1889e33d69fSJan Kara } 1899e33d69fSJan Kara if (le32_to_cpu(dqhead->dqh_version) != lversions[type]) { 1909e33d69fSJan Kara mlog(ML_ERROR, "quota file version does not match (%u != %u)," 1919e33d69fSJan Kara " type=%d\n", le32_to_cpu(dqhead->dqh_version), 1929e33d69fSJan Kara lversions[type], type); 1939e33d69fSJan Kara goto out_err; 1949e33d69fSJan Kara } 1959e33d69fSJan Kara brelse(bh); 1969e33d69fSJan Kara bh = NULL; 1979e33d69fSJan Kara 1989e33d69fSJan Kara /* Next check whether we understand global quota file */ 1999e33d69fSJan Kara ginode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type], 2009e33d69fSJan Kara OCFS2_INVALID_SLOT); 2019e33d69fSJan Kara if (!ginode) { 2029e33d69fSJan Kara mlog(ML_ERROR, "cannot get global quota file inode " 2039e33d69fSJan Kara "(type=%d)\n", type); 2049e33d69fSJan Kara goto out_err; 2059e33d69fSJan Kara } 2069e33d69fSJan Kara /* Since the header is read only, we don't care about locking */ 20785eb8b73SJoel Becker status = ocfs2_read_quota_block(ginode, 0, &bh); 20885eb8b73SJoel Becker if (status) { 2099e33d69fSJan Kara mlog_errno(status); 2109e33d69fSJan Kara mlog(ML_ERROR, "failed to read global quota file header " 2119e33d69fSJan Kara "(type=%d)\n", type); 2129e33d69fSJan Kara goto out_err; 2139e33d69fSJan Kara } 2149e33d69fSJan Kara dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data); 2159e33d69fSJan Kara if (le32_to_cpu(dqhead->dqh_magic) != gmagics[type]) { 2169e33d69fSJan Kara mlog(ML_ERROR, "global quota file magic does not match " 2179e33d69fSJan Kara "(%u != %u), type=%d\n", 2189e33d69fSJan Kara le32_to_cpu(dqhead->dqh_magic), gmagics[type], type); 2199e33d69fSJan Kara goto out_err; 2209e33d69fSJan Kara } 2219e33d69fSJan Kara if (le32_to_cpu(dqhead->dqh_version) != gversions[type]) { 2229e33d69fSJan Kara mlog(ML_ERROR, "global quota file version does not match " 2239e33d69fSJan Kara "(%u != %u), type=%d\n", 2249e33d69fSJan Kara le32_to_cpu(dqhead->dqh_version), gversions[type], 2259e33d69fSJan Kara type); 2269e33d69fSJan Kara goto out_err; 2279e33d69fSJan Kara } 2289e33d69fSJan Kara 2299e33d69fSJan Kara ret = 1; 2309e33d69fSJan Kara out_err: 2319e33d69fSJan Kara brelse(bh); 2329e33d69fSJan Kara iput(ginode); 2339e33d69fSJan Kara return ret; 2349e33d69fSJan Kara } 2359e33d69fSJan Kara 2369e33d69fSJan Kara /* Release given list of quota file chunks */ 2379e33d69fSJan Kara static void ocfs2_release_local_quota_bitmaps(struct list_head *head) 2389e33d69fSJan Kara { 2399e33d69fSJan Kara struct ocfs2_quota_chunk *pos, *next; 2409e33d69fSJan Kara 2419e33d69fSJan Kara list_for_each_entry_safe(pos, next, head, qc_chunk) { 2429e33d69fSJan Kara list_del(&pos->qc_chunk); 2439e33d69fSJan Kara brelse(pos->qc_headerbh); 2449e33d69fSJan Kara kmem_cache_free(ocfs2_qf_chunk_cachep, pos); 2459e33d69fSJan Kara } 2469e33d69fSJan Kara } 2479e33d69fSJan Kara 2489e33d69fSJan Kara /* Load quota bitmaps into memory */ 2499e33d69fSJan Kara static int ocfs2_load_local_quota_bitmaps(struct inode *inode, 2509e33d69fSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo, 2519e33d69fSJan Kara struct list_head *head) 2529e33d69fSJan Kara { 2539e33d69fSJan Kara struct ocfs2_quota_chunk *newchunk; 2549e33d69fSJan Kara int i, status; 2559e33d69fSJan Kara 2569e33d69fSJan Kara INIT_LIST_HEAD(head); 2579e33d69fSJan Kara for (i = 0; i < le32_to_cpu(ldinfo->dqi_chunks); i++) { 2589e33d69fSJan Kara newchunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS); 2599e33d69fSJan Kara if (!newchunk) { 2609e33d69fSJan Kara ocfs2_release_local_quota_bitmaps(head); 2619e33d69fSJan Kara return -ENOMEM; 2629e33d69fSJan Kara } 2639e33d69fSJan Kara newchunk->qc_num = i; 26485eb8b73SJoel Becker newchunk->qc_headerbh = NULL; 26585eb8b73SJoel Becker status = ocfs2_read_quota_block(inode, 2669e33d69fSJan Kara ol_quota_chunk_block(inode->i_sb, i), 26785eb8b73SJoel Becker &newchunk->qc_headerbh); 26885eb8b73SJoel Becker if (status) { 2699e33d69fSJan Kara mlog_errno(status); 2709e33d69fSJan Kara kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk); 2719e33d69fSJan Kara ocfs2_release_local_quota_bitmaps(head); 2729e33d69fSJan Kara return status; 2739e33d69fSJan Kara } 2749e33d69fSJan Kara list_add_tail(&newchunk->qc_chunk, head); 2759e33d69fSJan Kara } 2769e33d69fSJan Kara return 0; 2779e33d69fSJan Kara } 2789e33d69fSJan Kara 2799e33d69fSJan Kara static void olq_update_info(struct buffer_head *bh, void *private) 2809e33d69fSJan Kara { 2819e33d69fSJan Kara struct mem_dqinfo *info = private; 2829e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; 2839e33d69fSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo; 2849e33d69fSJan Kara 2859e33d69fSJan Kara ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + 2869e33d69fSJan Kara OCFS2_LOCAL_INFO_OFF); 2879e33d69fSJan Kara spin_lock(&dq_data_lock); 28896827adcSJan Kara ldinfo->dqi_flags = cpu_to_le32(oinfo->dqi_flags); 2899e33d69fSJan Kara ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks); 2909e33d69fSJan Kara ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks); 2919e33d69fSJan Kara spin_unlock(&dq_data_lock); 2929e33d69fSJan Kara } 2939e33d69fSJan Kara 2942205363dSJan Kara static int ocfs2_add_recovery_chunk(struct super_block *sb, 2952205363dSJan Kara struct ocfs2_local_disk_chunk *dchunk, 2962205363dSJan Kara int chunk, 2972205363dSJan Kara struct list_head *head) 2982205363dSJan Kara { 2992205363dSJan Kara struct ocfs2_recovery_chunk *rc; 3002205363dSJan Kara 3012205363dSJan Kara rc = kmalloc(sizeof(struct ocfs2_recovery_chunk), GFP_NOFS); 3022205363dSJan Kara if (!rc) 3032205363dSJan Kara return -ENOMEM; 3042205363dSJan Kara rc->rc_chunk = chunk; 3052205363dSJan Kara rc->rc_bitmap = kmalloc(sb->s_blocksize, GFP_NOFS); 3062205363dSJan Kara if (!rc->rc_bitmap) { 3072205363dSJan Kara kfree(rc); 3082205363dSJan Kara return -ENOMEM; 3092205363dSJan Kara } 3102205363dSJan Kara memcpy(rc->rc_bitmap, dchunk->dqc_bitmap, 3112205363dSJan Kara (ol_chunk_entries(sb) + 7) >> 3); 3122205363dSJan Kara list_add_tail(&rc->rc_list, head); 3132205363dSJan Kara return 0; 3142205363dSJan Kara } 3152205363dSJan Kara 3162205363dSJan Kara static void free_recovery_list(struct list_head *head) 3172205363dSJan Kara { 3182205363dSJan Kara struct ocfs2_recovery_chunk *next; 3192205363dSJan Kara struct ocfs2_recovery_chunk *rchunk; 3202205363dSJan Kara 3212205363dSJan Kara list_for_each_entry_safe(rchunk, next, head, rc_list) { 3222205363dSJan Kara list_del(&rchunk->rc_list); 3232205363dSJan Kara kfree(rchunk->rc_bitmap); 3242205363dSJan Kara kfree(rchunk); 3252205363dSJan Kara } 3262205363dSJan Kara } 3272205363dSJan Kara 3282205363dSJan Kara void ocfs2_free_quota_recovery(struct ocfs2_quota_recovery *rec) 3292205363dSJan Kara { 3302205363dSJan Kara int type; 3312205363dSJan Kara 33252362810SJan Kara for (type = 0; type < OCFS2_MAXQUOTAS; type++) 3332205363dSJan Kara free_recovery_list(&(rec->r_list[type])); 3342205363dSJan Kara kfree(rec); 3352205363dSJan Kara } 3362205363dSJan Kara 3372205363dSJan Kara /* Load entries in our quota file we have to recover*/ 3382205363dSJan Kara static int ocfs2_recovery_load_quota(struct inode *lqinode, 3392205363dSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo, 3402205363dSJan Kara int type, 3412205363dSJan Kara struct list_head *head) 3422205363dSJan Kara { 3432205363dSJan Kara struct super_block *sb = lqinode->i_sb; 3442205363dSJan Kara struct buffer_head *hbh; 3452205363dSJan Kara struct ocfs2_local_disk_chunk *dchunk; 3462205363dSJan Kara int i, chunks = le32_to_cpu(ldinfo->dqi_chunks); 3472205363dSJan Kara int status = 0; 3482205363dSJan Kara 3492205363dSJan Kara for (i = 0; i < chunks; i++) { 35085eb8b73SJoel Becker hbh = NULL; 35185eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 3522205363dSJan Kara ol_quota_chunk_block(sb, i), 35385eb8b73SJoel Becker &hbh); 35485eb8b73SJoel Becker if (status) { 3552205363dSJan Kara mlog_errno(status); 3562205363dSJan Kara break; 3572205363dSJan Kara } 3582205363dSJan Kara dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data; 3592205363dSJan Kara if (le32_to_cpu(dchunk->dqc_free) < ol_chunk_entries(sb)) 3602205363dSJan Kara status = ocfs2_add_recovery_chunk(sb, dchunk, i, head); 3612205363dSJan Kara brelse(hbh); 3622205363dSJan Kara if (status < 0) 3632205363dSJan Kara break; 3642205363dSJan Kara } 3652205363dSJan Kara if (status < 0) 3662205363dSJan Kara free_recovery_list(head); 3672205363dSJan Kara return status; 3682205363dSJan Kara } 3692205363dSJan Kara 3702205363dSJan Kara static struct ocfs2_quota_recovery *ocfs2_alloc_quota_recovery(void) 3712205363dSJan Kara { 3722205363dSJan Kara int type; 3732205363dSJan Kara struct ocfs2_quota_recovery *rec; 3742205363dSJan Kara 3752205363dSJan Kara rec = kmalloc(sizeof(struct ocfs2_quota_recovery), GFP_NOFS); 3762205363dSJan Kara if (!rec) 3772205363dSJan Kara return NULL; 37852362810SJan Kara for (type = 0; type < OCFS2_MAXQUOTAS; type++) 3792205363dSJan Kara INIT_LIST_HEAD(&(rec->r_list[type])); 3802205363dSJan Kara return rec; 3812205363dSJan Kara } 3822205363dSJan Kara 3832205363dSJan Kara /* Load information we need for quota recovery into memory */ 3842205363dSJan Kara struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery( 3852205363dSJan Kara struct ocfs2_super *osb, 3862205363dSJan Kara int slot_num) 3872205363dSJan Kara { 38852362810SJan Kara unsigned int feature[OCFS2_MAXQUOTAS] = { 38952362810SJan Kara OCFS2_FEATURE_RO_COMPAT_USRQUOTA, 3902205363dSJan Kara OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; 39152362810SJan Kara unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, 3922205363dSJan Kara LOCAL_GROUP_QUOTA_SYSTEM_INODE }; 3932205363dSJan Kara struct super_block *sb = osb->sb; 3942205363dSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo; 3952205363dSJan Kara struct inode *lqinode; 3962205363dSJan Kara struct buffer_head *bh; 3972205363dSJan Kara int type; 3982205363dSJan Kara int status = 0; 3992205363dSJan Kara struct ocfs2_quota_recovery *rec; 4002205363dSJan Kara 401619c200dSSunil Mushran printk(KERN_NOTICE "ocfs2: Beginning quota recovery on device (%s) for " 402619c200dSSunil Mushran "slot %u\n", osb->dev_str, slot_num); 403619c200dSSunil Mushran 4042205363dSJan Kara rec = ocfs2_alloc_quota_recovery(); 4052205363dSJan Kara if (!rec) 4062205363dSJan Kara return ERR_PTR(-ENOMEM); 4072205363dSJan Kara /* First init... */ 4082205363dSJan Kara 40952362810SJan Kara for (type = 0; type < OCFS2_MAXQUOTAS; type++) { 4102205363dSJan Kara if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) 4112205363dSJan Kara continue; 4122205363dSJan Kara /* At this point, journal of the slot is already replayed so 4132205363dSJan Kara * we can trust metadata and data of the quota file */ 4142205363dSJan Kara lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num); 4152205363dSJan Kara if (!lqinode) { 4162205363dSJan Kara status = -ENOENT; 4172205363dSJan Kara goto out; 4182205363dSJan Kara } 4192205363dSJan Kara status = ocfs2_inode_lock_full(lqinode, NULL, 1, 4202205363dSJan Kara OCFS2_META_LOCK_RECOVERY); 4212205363dSJan Kara if (status < 0) { 4222205363dSJan Kara mlog_errno(status); 4232205363dSJan Kara goto out_put; 4242205363dSJan Kara } 4252205363dSJan Kara /* Now read local header */ 42685eb8b73SJoel Becker bh = NULL; 42785eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 0, &bh); 42885eb8b73SJoel Becker if (status) { 4292205363dSJan Kara mlog_errno(status); 4302205363dSJan Kara mlog(ML_ERROR, "failed to read quota file info header " 4312205363dSJan Kara "(slot=%d type=%d)\n", slot_num, type); 4322205363dSJan Kara goto out_lock; 4332205363dSJan Kara } 4342205363dSJan Kara ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + 4352205363dSJan Kara OCFS2_LOCAL_INFO_OFF); 4362205363dSJan Kara status = ocfs2_recovery_load_quota(lqinode, ldinfo, type, 4372205363dSJan Kara &rec->r_list[type]); 4382205363dSJan Kara brelse(bh); 4392205363dSJan Kara out_lock: 4402205363dSJan Kara ocfs2_inode_unlock(lqinode, 1); 4412205363dSJan Kara out_put: 4422205363dSJan Kara iput(lqinode); 4432205363dSJan Kara if (status < 0) 4442205363dSJan Kara break; 4452205363dSJan Kara } 4462205363dSJan Kara out: 4472205363dSJan Kara if (status < 0) { 4482205363dSJan Kara ocfs2_free_quota_recovery(rec); 4492205363dSJan Kara rec = ERR_PTR(status); 4502205363dSJan Kara } 4512205363dSJan Kara return rec; 4522205363dSJan Kara } 4532205363dSJan Kara 4542205363dSJan Kara /* Sync changes in local quota file into global quota file and 4552205363dSJan Kara * reinitialize local quota file. 4562205363dSJan Kara * The function expects local quota file to be already locked and 4575f530de6SJan Kara * s_umount locked in shared mode. */ 4582205363dSJan Kara static int ocfs2_recover_local_quota_file(struct inode *lqinode, 4592205363dSJan Kara int type, 4602205363dSJan Kara struct ocfs2_quota_recovery *rec) 4612205363dSJan Kara { 4622205363dSJan Kara struct super_block *sb = lqinode->i_sb; 4632205363dSJan Kara struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv; 4642205363dSJan Kara struct ocfs2_local_disk_chunk *dchunk; 4652205363dSJan Kara struct ocfs2_local_disk_dqblk *dqblk; 4662205363dSJan Kara struct dquot *dquot; 4672205363dSJan Kara handle_t *handle; 4682205363dSJan Kara struct buffer_head *hbh = NULL, *qbh = NULL; 4692205363dSJan Kara int status = 0; 4702205363dSJan Kara int bit, chunk; 4712205363dSJan Kara struct ocfs2_recovery_chunk *rchunk, *next; 4722205363dSJan Kara qsize_t spacechange, inodechange; 4736c5026c1SJan Kara unsigned int memalloc; 4742205363dSJan Kara 47538877a43STao Ma trace_ocfs2_recover_local_quota_file((unsigned long)lqinode->i_ino, type); 4762205363dSJan Kara 4772205363dSJan Kara list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { 4782205363dSJan Kara chunk = rchunk->rc_chunk; 47985eb8b73SJoel Becker hbh = NULL; 48085eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 4812205363dSJan Kara ol_quota_chunk_block(sb, chunk), 48285eb8b73SJoel Becker &hbh); 48385eb8b73SJoel Becker if (status) { 4842205363dSJan Kara mlog_errno(status); 4852205363dSJan Kara break; 4862205363dSJan Kara } 4872205363dSJan Kara dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data; 488984b3f57SAkinobu Mita for_each_set_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) { 48985eb8b73SJoel Becker qbh = NULL; 49085eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 4912205363dSJan Kara ol_dqblk_block(sb, chunk, bit), 49285eb8b73SJoel Becker &qbh); 49385eb8b73SJoel Becker if (status) { 4942205363dSJan Kara mlog_errno(status); 4952205363dSJan Kara break; 4962205363dSJan Kara } 4972205363dSJan Kara dqblk = (struct ocfs2_local_disk_dqblk *)(qbh->b_data + 4982205363dSJan Kara ol_dqblk_block_off(sb, chunk, bit)); 499aca645a6SEric W. Biederman dquot = dqget(sb, 500aca645a6SEric W. Biederman make_kqid(&init_user_ns, type, 501aca645a6SEric W. Biederman le64_to_cpu(dqblk->dqb_id))); 5026184fc0bSJan Kara if (IS_ERR(dquot)) { 5036184fc0bSJan Kara status = PTR_ERR(dquot); 5042205363dSJan Kara mlog(ML_ERROR, "Failed to get quota structure " 5052205363dSJan Kara "for id %u, type %d. Cannot finish quota " 5062205363dSJan Kara "file recovery.\n", 5072205363dSJan Kara (unsigned)le64_to_cpu(dqblk->dqb_id), 5082205363dSJan Kara type); 5092205363dSJan Kara goto out_put_bh; 5102205363dSJan Kara } 51180d73f15SJan Kara status = ocfs2_lock_global_qf(oinfo, 1); 51280d73f15SJan Kara if (status < 0) { 51380d73f15SJan Kara mlog_errno(status); 51480d73f15SJan Kara goto out_put_dquot; 51580d73f15SJan Kara } 51680d73f15SJan Kara 5172205363dSJan Kara handle = ocfs2_start_trans(OCFS2_SB(sb), 5182205363dSJan Kara OCFS2_QSYNC_CREDITS); 5192205363dSJan Kara if (IS_ERR(handle)) { 5202205363dSJan Kara status = PTR_ERR(handle); 5212205363dSJan Kara mlog_errno(status); 52280d73f15SJan Kara goto out_drop_lock; 5232205363dSJan Kara } 524bc8230eeSJan Kara down_write(&sb_dqopt(sb)->dqio_sem); 5256c5026c1SJan Kara memalloc = memalloc_nofs_save(); 5267b9ca4c6SJan Kara spin_lock(&dquot->dq_dqb_lock); 5272205363dSJan Kara /* Add usage from quota entry into quota changes 5282205363dSJan Kara * of our node. Auxiliary variables are important 5292205363dSJan Kara * due to signedness */ 5302205363dSJan Kara spacechange = le64_to_cpu(dqblk->dqb_spacemod); 5312205363dSJan Kara inodechange = le64_to_cpu(dqblk->dqb_inodemod); 5322205363dSJan Kara dquot->dq_dqb.dqb_curspace += spacechange; 5332205363dSJan Kara dquot->dq_dqb.dqb_curinodes += inodechange; 5347b9ca4c6SJan Kara spin_unlock(&dquot->dq_dqb_lock); 5352205363dSJan Kara /* We want to drop reference held by the crashed 5362205363dSJan Kara * node. Since we have our own reference we know 5372205363dSJan Kara * global structure actually won't be freed. */ 5382205363dSJan Kara status = ocfs2_global_release_dquot(dquot); 5392205363dSJan Kara if (status < 0) { 5402205363dSJan Kara mlog_errno(status); 5412205363dSJan Kara goto out_commit; 5422205363dSJan Kara } 5432205363dSJan Kara /* Release local quota file entry */ 5440cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, 5450cf2f763SJoel Becker INODE_CACHE(lqinode), 5462205363dSJan Kara qbh, OCFS2_JOURNAL_ACCESS_WRITE); 5472205363dSJan Kara if (status < 0) { 5482205363dSJan Kara mlog_errno(status); 5492205363dSJan Kara goto out_commit; 5502205363dSJan Kara } 5512205363dSJan Kara lock_buffer(qbh); 55293925579SAkinobu Mita WARN_ON(!ocfs2_test_bit_unaligned(bit, dchunk->dqc_bitmap)); 55393925579SAkinobu Mita ocfs2_clear_bit_unaligned(bit, dchunk->dqc_bitmap); 5542205363dSJan Kara le32_add_cpu(&dchunk->dqc_free, 1); 5552205363dSJan Kara unlock_buffer(qbh); 556ec20cec7SJoel Becker ocfs2_journal_dirty(handle, qbh); 5572205363dSJan Kara out_commit: 5586c5026c1SJan Kara memalloc_nofs_restore(memalloc); 559bc8230eeSJan Kara up_write(&sb_dqopt(sb)->dqio_sem); 5602205363dSJan Kara ocfs2_commit_trans(OCFS2_SB(sb), handle); 56180d73f15SJan Kara out_drop_lock: 56280d73f15SJan Kara ocfs2_unlock_global_qf(oinfo, 1); 5632205363dSJan Kara out_put_dquot: 5642205363dSJan Kara dqput(dquot); 5652205363dSJan Kara out_put_bh: 5662205363dSJan Kara brelse(qbh); 5672205363dSJan Kara if (status < 0) 5682205363dSJan Kara break; 5692205363dSJan Kara } 5702205363dSJan Kara brelse(hbh); 5712205363dSJan Kara list_del(&rchunk->rc_list); 5722205363dSJan Kara kfree(rchunk->rc_bitmap); 5732205363dSJan Kara kfree(rchunk); 5742205363dSJan Kara if (status < 0) 5752205363dSJan Kara break; 5762205363dSJan Kara } 5772205363dSJan Kara if (status < 0) 5782205363dSJan Kara free_recovery_list(&(rec->r_list[type])); 579c1e8d35eSTao Ma if (status) 580c1e8d35eSTao Ma mlog_errno(status); 5812205363dSJan Kara return status; 5822205363dSJan Kara } 5832205363dSJan Kara 5842205363dSJan Kara /* Recover local quota files for given node different from us */ 5852205363dSJan Kara int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, 5862205363dSJan Kara struct ocfs2_quota_recovery *rec, 5872205363dSJan Kara int slot_num) 5882205363dSJan Kara { 58952362810SJan Kara unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, 5902205363dSJan Kara LOCAL_GROUP_QUOTA_SYSTEM_INODE }; 5912205363dSJan Kara struct super_block *sb = osb->sb; 5922205363dSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo; 5932205363dSJan Kara struct buffer_head *bh; 5942205363dSJan Kara handle_t *handle; 5952205363dSJan Kara int type; 5962205363dSJan Kara int status = 0; 5972205363dSJan Kara struct inode *lqinode; 5982205363dSJan Kara unsigned int flags; 5992205363dSJan Kara 600619c200dSSunil Mushran printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for " 601619c200dSSunil Mushran "slot %u\n", osb->dev_str, slot_num); 602619c200dSSunil Mushran 6035f530de6SJan Kara down_read(&sb->s_umount); 60452362810SJan Kara for (type = 0; type < OCFS2_MAXQUOTAS; type++) { 6052205363dSJan Kara if (list_empty(&(rec->r_list[type]))) 6062205363dSJan Kara continue; 60738877a43STao Ma trace_ocfs2_finish_quota_recovery(slot_num); 6082205363dSJan Kara lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num); 6092205363dSJan Kara if (!lqinode) { 6102205363dSJan Kara status = -ENOENT; 6112205363dSJan Kara goto out; 6122205363dSJan Kara } 6132205363dSJan Kara status = ocfs2_inode_lock_full(lqinode, NULL, 1, 6142205363dSJan Kara OCFS2_META_LOCK_NOQUEUE); 6152205363dSJan Kara /* Someone else is holding the lock? Then he must be 6162205363dSJan Kara * doing the recovery. Just skip the file... */ 6172205363dSJan Kara if (status == -EAGAIN) { 618619c200dSSunil Mushran printk(KERN_NOTICE "ocfs2: Skipping quota recovery on " 619619c200dSSunil Mushran "device (%s) for slot %d because quota file is " 620619c200dSSunil Mushran "locked.\n", osb->dev_str, slot_num); 6212205363dSJan Kara status = 0; 6222205363dSJan Kara goto out_put; 6232205363dSJan Kara } else if (status < 0) { 6242205363dSJan Kara mlog_errno(status); 6252205363dSJan Kara goto out_put; 6262205363dSJan Kara } 6272205363dSJan Kara /* Now read local header */ 62885eb8b73SJoel Becker bh = NULL; 62985eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 0, &bh); 63085eb8b73SJoel Becker if (status) { 6312205363dSJan Kara mlog_errno(status); 6322205363dSJan Kara mlog(ML_ERROR, "failed to read quota file info header " 6332205363dSJan Kara "(slot=%d type=%d)\n", slot_num, type); 6342205363dSJan Kara goto out_lock; 6352205363dSJan Kara } 6362205363dSJan Kara ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + 6372205363dSJan Kara OCFS2_LOCAL_INFO_OFF); 6382205363dSJan Kara /* Is recovery still needed? */ 6392205363dSJan Kara flags = le32_to_cpu(ldinfo->dqi_flags); 6402205363dSJan Kara if (!(flags & OLQF_CLEAN)) 6412205363dSJan Kara status = ocfs2_recover_local_quota_file(lqinode, 6422205363dSJan Kara type, 6432205363dSJan Kara rec); 6442205363dSJan Kara /* We don't want to mark file as clean when it is actually 6452205363dSJan Kara * active */ 6462205363dSJan Kara if (slot_num == osb->slot_num) 6472205363dSJan Kara goto out_bh; 6482205363dSJan Kara /* Mark quota file as clean if we are recovering quota file of 6492205363dSJan Kara * some other node. */ 6500584974aSJan Kara handle = ocfs2_start_trans(osb, 6510584974aSJan Kara OCFS2_LOCAL_QINFO_WRITE_CREDITS); 6522205363dSJan Kara if (IS_ERR(handle)) { 6532205363dSJan Kara status = PTR_ERR(handle); 6542205363dSJan Kara mlog_errno(status); 6552205363dSJan Kara goto out_bh; 6562205363dSJan Kara } 6570cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), 6580cf2f763SJoel Becker bh, 6592205363dSJan Kara OCFS2_JOURNAL_ACCESS_WRITE); 6602205363dSJan Kara if (status < 0) { 6612205363dSJan Kara mlog_errno(status); 6622205363dSJan Kara goto out_trans; 6632205363dSJan Kara } 6642205363dSJan Kara lock_buffer(bh); 6652205363dSJan Kara ldinfo->dqi_flags = cpu_to_le32(flags | OLQF_CLEAN); 6662205363dSJan Kara unlock_buffer(bh); 667ec20cec7SJoel Becker ocfs2_journal_dirty(handle, bh); 6682205363dSJan Kara out_trans: 6692205363dSJan Kara ocfs2_commit_trans(osb, handle); 6702205363dSJan Kara out_bh: 6712205363dSJan Kara brelse(bh); 6722205363dSJan Kara out_lock: 6732205363dSJan Kara ocfs2_inode_unlock(lqinode, 1); 6742205363dSJan Kara out_put: 6752205363dSJan Kara iput(lqinode); 6762205363dSJan Kara if (status < 0) 6772205363dSJan Kara break; 6782205363dSJan Kara } 6792205363dSJan Kara out: 6805f530de6SJan Kara up_read(&sb->s_umount); 6812205363dSJan Kara kfree(rec); 6822205363dSJan Kara return status; 6832205363dSJan Kara } 6842205363dSJan Kara 6859e33d69fSJan Kara /* Read information header from quota file */ 6869e33d69fSJan Kara static int ocfs2_local_read_info(struct super_block *sb, int type) 6879e33d69fSJan Kara { 6889e33d69fSJan Kara struct ocfs2_local_disk_dqinfo *ldinfo; 6899e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 6909e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo; 6919e33d69fSJan Kara struct inode *lqinode = sb_dqopt(sb)->files[type]; 6929e33d69fSJan Kara int status; 6939e33d69fSJan Kara struct buffer_head *bh = NULL; 6942205363dSJan Kara struct ocfs2_quota_recovery *rec; 695*35fccce2SJoseph Qi int locked = 0, global_read = 0; 6969e33d69fSJan Kara 697b10a0819SJan Kara info->dqi_max_spc_limit = 0x7fffffffffffffffLL; 698b10a0819SJan Kara info->dqi_max_ino_limit = 0x7fffffffffffffffLL; 6999e33d69fSJan Kara oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); 7009e33d69fSJan Kara if (!oinfo) { 7019e33d69fSJan Kara mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" 7029e33d69fSJan Kara " info."); 703*35fccce2SJoseph Qi status = -ENOMEM; 7049e33d69fSJan Kara goto out_err; 7059e33d69fSJan Kara } 7069e33d69fSJan Kara info->dqi_priv = oinfo; 7079e33d69fSJan Kara oinfo->dqi_type = type; 7089e33d69fSJan Kara INIT_LIST_HEAD(&oinfo->dqi_chunk); 7092205363dSJan Kara oinfo->dqi_rec = NULL; 7109e33d69fSJan Kara oinfo->dqi_lqi_bh = NULL; 711ae4f6ef1SJan Kara oinfo->dqi_libh = NULL; 7129e33d69fSJan Kara 7139e33d69fSJan Kara status = ocfs2_global_read_info(sb, type); 7149e33d69fSJan Kara if (status < 0) 7159e33d69fSJan Kara goto out_err; 716*35fccce2SJoseph Qi global_read = 1; 7179e33d69fSJan Kara 7189e33d69fSJan Kara status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1); 7199e33d69fSJan Kara if (status < 0) { 7209e33d69fSJan Kara mlog_errno(status); 7219e33d69fSJan Kara goto out_err; 7229e33d69fSJan Kara } 7239e33d69fSJan Kara locked = 1; 7249e33d69fSJan Kara 7259e33d69fSJan Kara /* Now read local header */ 72685eb8b73SJoel Becker status = ocfs2_read_quota_block(lqinode, 0, &bh); 72785eb8b73SJoel Becker if (status) { 7289e33d69fSJan Kara mlog_errno(status); 7299e33d69fSJan Kara mlog(ML_ERROR, "failed to read quota file info header " 7309e33d69fSJan Kara "(type=%d)\n", type); 7319e33d69fSJan Kara goto out_err; 7329e33d69fSJan Kara } 7339e33d69fSJan Kara ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + 7349e33d69fSJan Kara OCFS2_LOCAL_INFO_OFF); 73596827adcSJan Kara oinfo->dqi_flags = le32_to_cpu(ldinfo->dqi_flags); 7369e33d69fSJan Kara oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks); 7379e33d69fSJan Kara oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks); 738ae4f6ef1SJan Kara oinfo->dqi_libh = bh; 7399e33d69fSJan Kara 7409e33d69fSJan Kara /* We crashed when using local quota file? */ 74196827adcSJan Kara if (!(oinfo->dqi_flags & OLQF_CLEAN)) { 7422205363dSJan Kara rec = OCFS2_SB(sb)->quota_rec; 7432205363dSJan Kara if (!rec) { 7442205363dSJan Kara rec = ocfs2_alloc_quota_recovery(); 7452205363dSJan Kara if (!rec) { 7462205363dSJan Kara status = -ENOMEM; 7472205363dSJan Kara mlog_errno(status); 7482205363dSJan Kara goto out_err; 7492205363dSJan Kara } 7502205363dSJan Kara OCFS2_SB(sb)->quota_rec = rec; 7512205363dSJan Kara } 7529e33d69fSJan Kara 7532205363dSJan Kara status = ocfs2_recovery_load_quota(lqinode, ldinfo, type, 7542205363dSJan Kara &rec->r_list[type]); 7552205363dSJan Kara if (status < 0) { 7562205363dSJan Kara mlog_errno(status); 7572205363dSJan Kara goto out_err; 7582205363dSJan Kara } 7592205363dSJan Kara } 7602205363dSJan Kara 7612205363dSJan Kara status = ocfs2_load_local_quota_bitmaps(lqinode, 7629e33d69fSJan Kara ldinfo, 7639e33d69fSJan Kara &oinfo->dqi_chunk); 7649e33d69fSJan Kara if (status < 0) { 7659e33d69fSJan Kara mlog_errno(status); 7669e33d69fSJan Kara goto out_err; 7679e33d69fSJan Kara } 7689e33d69fSJan Kara 7699e33d69fSJan Kara /* Now mark quota file as used */ 77096827adcSJan Kara oinfo->dqi_flags &= ~OLQF_CLEAN; 7719e33d69fSJan Kara status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info); 7729e33d69fSJan Kara if (status < 0) { 7739e33d69fSJan Kara mlog_errno(status); 7749e33d69fSJan Kara goto out_err; 7759e33d69fSJan Kara } 7769e33d69fSJan Kara 7779e33d69fSJan Kara return 0; 7789e33d69fSJan Kara out_err: 7799e33d69fSJan Kara if (oinfo) { 7809e33d69fSJan Kara iput(oinfo->dqi_gqinode); 7819e33d69fSJan Kara ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock); 7829e33d69fSJan Kara ocfs2_lock_res_free(&oinfo->dqi_gqlock); 7839e33d69fSJan Kara brelse(oinfo->dqi_lqi_bh); 7849e33d69fSJan Kara if (locked) 7859e33d69fSJan Kara ocfs2_inode_unlock(lqinode, 1); 7869e33d69fSJan Kara ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); 787*35fccce2SJoseph Qi if (global_read) 788*35fccce2SJoseph Qi cancel_delayed_work_sync(&oinfo->dqi_sync_work); 7899e33d69fSJan Kara kfree(oinfo); 7909e33d69fSJan Kara } 7919e33d69fSJan Kara brelse(bh); 792*35fccce2SJoseph Qi return status; 7939e33d69fSJan Kara } 7949e33d69fSJan Kara 7959e33d69fSJan Kara /* Write local info to quota file */ 7969e33d69fSJan Kara static int ocfs2_local_write_info(struct super_block *sb, int type) 7979e33d69fSJan Kara { 7989e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 7999e33d69fSJan Kara struct buffer_head *bh = ((struct ocfs2_mem_dqinfo *)info->dqi_priv) 800ae4f6ef1SJan Kara ->dqi_libh; 8019e33d69fSJan Kara int status; 8029e33d69fSJan Kara 8039e33d69fSJan Kara status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], bh, olq_update_info, 8049e33d69fSJan Kara info); 8059e33d69fSJan Kara if (status < 0) { 8069e33d69fSJan Kara mlog_errno(status); 8079e33d69fSJan Kara return -1; 8089e33d69fSJan Kara } 8099e33d69fSJan Kara 8109e33d69fSJan Kara return 0; 8119e33d69fSJan Kara } 8129e33d69fSJan Kara 8139e33d69fSJan Kara /* Release info from memory */ 8149e33d69fSJan Kara static int ocfs2_local_free_info(struct super_block *sb, int type) 8159e33d69fSJan Kara { 8169e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 8179e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; 8189e33d69fSJan Kara struct ocfs2_quota_chunk *chunk; 8199e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 8209e33d69fSJan Kara int mark_clean = 1, len; 821d32840adSJoseph Qi int status = 0; 8229e33d69fSJan Kara 8239e33d69fSJan Kara iput(oinfo->dqi_gqinode); 8249e33d69fSJan Kara ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock); 8259e33d69fSJan Kara ocfs2_lock_res_free(&oinfo->dqi_gqlock); 8269e33d69fSJan Kara list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) { 8279e33d69fSJan Kara dchunk = (struct ocfs2_local_disk_chunk *) 8289e33d69fSJan Kara (chunk->qc_headerbh->b_data); 8299e33d69fSJan Kara if (chunk->qc_num < oinfo->dqi_chunks - 1) { 8309e33d69fSJan Kara len = ol_chunk_entries(sb); 8319e33d69fSJan Kara } else { 8329e33d69fSJan Kara len = (oinfo->dqi_blocks - 8339e33d69fSJan Kara ol_quota_chunk_block(sb, chunk->qc_num) - 1) 8349e33d69fSJan Kara * ol_quota_entries_per_block(sb); 8359e33d69fSJan Kara } 8369e33d69fSJan Kara /* Not all entries free? Bug! */ 8379e33d69fSJan Kara if (le32_to_cpu(dchunk->dqc_free) != len) { 8389e33d69fSJan Kara mlog(ML_ERROR, "releasing quota file with used " 8399e33d69fSJan Kara "entries (type=%d)\n", type); 8409e33d69fSJan Kara mark_clean = 0; 8419e33d69fSJan Kara } 8429e33d69fSJan Kara } 8439e33d69fSJan Kara ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); 8449e33d69fSJan Kara 8455f530de6SJan Kara /* 8465f530de6SJan Kara * s_umount held in exclusive mode protects us against racing with 8475f530de6SJan Kara * recovery thread... 8485f530de6SJan Kara */ 8492205363dSJan Kara if (oinfo->dqi_rec) { 8502205363dSJan Kara ocfs2_free_quota_recovery(oinfo->dqi_rec); 8512205363dSJan Kara mark_clean = 0; 8522205363dSJan Kara } 8532205363dSJan Kara 8549e33d69fSJan Kara if (!mark_clean) 8559e33d69fSJan Kara goto out; 8569e33d69fSJan Kara 8579e33d69fSJan Kara /* Mark local file as clean */ 85896827adcSJan Kara oinfo->dqi_flags |= OLQF_CLEAN; 8599e33d69fSJan Kara status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], 860ae4f6ef1SJan Kara oinfo->dqi_libh, 8619e33d69fSJan Kara olq_update_info, 8629e33d69fSJan Kara info); 863d32840adSJoseph Qi if (status < 0) 8649e33d69fSJan Kara mlog_errno(status); 8659e33d69fSJan Kara out: 8669e33d69fSJan Kara ocfs2_inode_unlock(sb_dqopt(sb)->files[type], 1); 867ae4f6ef1SJan Kara brelse(oinfo->dqi_libh); 8689e33d69fSJan Kara brelse(oinfo->dqi_lqi_bh); 8699e33d69fSJan Kara kfree(oinfo); 870d32840adSJoseph Qi return status; 8719e33d69fSJan Kara } 8729e33d69fSJan Kara 8739e33d69fSJan Kara static void olq_set_dquot(struct buffer_head *bh, void *private) 8749e33d69fSJan Kara { 8759e33d69fSJan Kara struct ocfs2_dquot *od = private; 8769e33d69fSJan Kara struct ocfs2_local_disk_dqblk *dqblk; 8779e33d69fSJan Kara struct super_block *sb = od->dq_dquot.dq_sb; 8789e33d69fSJan Kara 8799e33d69fSJan Kara dqblk = (struct ocfs2_local_disk_dqblk *)(bh->b_data 8809e33d69fSJan Kara + ol_dqblk_block_offset(sb, od->dq_local_off)); 8819e33d69fSJan Kara 8824c376dcaSEric W. Biederman dqblk->dqb_id = cpu_to_le64(from_kqid(&init_user_ns, 8834c376dcaSEric W. Biederman od->dq_dquot.dq_id)); 8847b9ca4c6SJan Kara spin_lock(&od->dq_dquot.dq_dqb_lock); 8859e33d69fSJan Kara dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace - 8869e33d69fSJan Kara od->dq_origspace); 8879e33d69fSJan Kara dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes - 8889e33d69fSJan Kara od->dq_originodes); 8897b9ca4c6SJan Kara spin_unlock(&od->dq_dquot.dq_dqb_lock); 89038877a43STao Ma trace_olq_set_dquot( 89138877a43STao Ma (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod), 89238877a43STao Ma (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod), 8934c376dcaSEric W. Biederman from_kqid(&init_user_ns, od->dq_dquot.dq_id)); 8949e33d69fSJan Kara } 8959e33d69fSJan Kara 8969e33d69fSJan Kara /* Write dquot to local quota file */ 897741e1289SJan Kara int ocfs2_local_write_dquot(struct dquot *dquot) 8989e33d69fSJan Kara { 8999e33d69fSJan Kara struct super_block *sb = dquot->dq_sb; 9009e33d69fSJan Kara struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); 901f64dd44eSJan Kara struct buffer_head *bh; 9024c376dcaSEric W. Biederman struct inode *lqinode = sb_dqopt(sb)->files[dquot->dq_id.type]; 9039e33d69fSJan Kara int status; 9049e33d69fSJan Kara 905f64dd44eSJan Kara status = ocfs2_read_quota_phys_block(lqinode, od->dq_local_phys_blk, 90685eb8b73SJoel Becker &bh); 90785eb8b73SJoel Becker if (status) { 9089e33d69fSJan Kara mlog_errno(status); 9099e33d69fSJan Kara goto out; 9109e33d69fSJan Kara } 911f64dd44eSJan Kara status = ocfs2_modify_bh(lqinode, bh, olq_set_dquot, od); 9129e33d69fSJan Kara if (status < 0) { 9139e33d69fSJan Kara mlog_errno(status); 9149e33d69fSJan Kara goto out; 9159e33d69fSJan Kara } 9169e33d69fSJan Kara out: 9179e33d69fSJan Kara brelse(bh); 9189e33d69fSJan Kara return status; 9199e33d69fSJan Kara } 9209e33d69fSJan Kara 9219e33d69fSJan Kara /* Find free entry in local quota file */ 9229e33d69fSJan Kara static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb, 9239e33d69fSJan Kara int type, 9249e33d69fSJan Kara int *offset) 9259e33d69fSJan Kara { 9269e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 9279e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; 92881cd1ae9SJakob Koschel struct ocfs2_quota_chunk *chunk = NULL, *iter; 9299e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 9309e33d69fSJan Kara int found = 0, len; 9319e33d69fSJan Kara 93281cd1ae9SJakob Koschel list_for_each_entry(iter, &oinfo->dqi_chunk, qc_chunk) { 9339e33d69fSJan Kara dchunk = (struct ocfs2_local_disk_chunk *) 93481cd1ae9SJakob Koschel iter->qc_headerbh->b_data; 9359e33d69fSJan Kara if (le32_to_cpu(dchunk->dqc_free) > 0) { 93681cd1ae9SJakob Koschel chunk = iter; 9379e33d69fSJan Kara break; 9389e33d69fSJan Kara } 9399e33d69fSJan Kara } 94081cd1ae9SJakob Koschel if (!chunk) 9419e33d69fSJan Kara return NULL; 9429e33d69fSJan Kara 9439e33d69fSJan Kara if (chunk->qc_num < oinfo->dqi_chunks - 1) { 9449e33d69fSJan Kara len = ol_chunk_entries(sb); 9459e33d69fSJan Kara } else { 9469e33d69fSJan Kara len = (oinfo->dqi_blocks - 9479e33d69fSJan Kara ol_quota_chunk_block(sb, chunk->qc_num) - 1) 9489e33d69fSJan Kara * ol_quota_entries_per_block(sb); 9499e33d69fSJan Kara } 9509e33d69fSJan Kara 95193925579SAkinobu Mita found = ocfs2_find_next_zero_bit_unaligned(dchunk->dqc_bitmap, len, 0); 9529e33d69fSJan Kara /* We failed? */ 9539e33d69fSJan Kara if (found == len) { 9549e33d69fSJan Kara mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u" 9559e33d69fSJan Kara " entries free (type=%d)\n", chunk->qc_num, 9569e33d69fSJan Kara le32_to_cpu(dchunk->dqc_free), type); 9579e33d69fSJan Kara return ERR_PTR(-EIO); 9589e33d69fSJan Kara } 9599e33d69fSJan Kara *offset = found; 9609e33d69fSJan Kara return chunk; 9619e33d69fSJan Kara } 9629e33d69fSJan Kara 9639e33d69fSJan Kara /* Add new chunk to the local quota file */ 9649e33d69fSJan Kara static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( 9659e33d69fSJan Kara struct super_block *sb, 9669e33d69fSJan Kara int type, 9679e33d69fSJan Kara int *offset) 9689e33d69fSJan Kara { 9699e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 9709e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; 9719e33d69fSJan Kara struct inode *lqinode = sb_dqopt(sb)->files[type]; 9729e33d69fSJan Kara struct ocfs2_quota_chunk *chunk = NULL; 9739e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 9749e33d69fSJan Kara int status; 9759e33d69fSJan Kara handle_t *handle; 9760e7f387bSJan Kara struct buffer_head *bh = NULL, *dbh = NULL; 9779e33d69fSJan Kara u64 p_blkno; 9789e33d69fSJan Kara 9799e33d69fSJan Kara /* We are protected by dqio_sem so no locking needed */ 9805693486bSJoel Becker status = ocfs2_extend_no_holes(lqinode, NULL, 981f17c20ddSJunxiao Bi i_size_read(lqinode) + 2 * sb->s_blocksize, 982f17c20ddSJunxiao Bi i_size_read(lqinode)); 9839e33d69fSJan Kara if (status < 0) { 9849e33d69fSJan Kara mlog_errno(status); 9859e33d69fSJan Kara goto out; 9869e33d69fSJan Kara } 9879e33d69fSJan Kara status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh, 988f17c20ddSJunxiao Bi i_size_read(lqinode) + 2 * sb->s_blocksize); 9899e33d69fSJan Kara if (status < 0) { 9909e33d69fSJan Kara mlog_errno(status); 9919e33d69fSJan Kara goto out; 9929e33d69fSJan Kara } 9939e33d69fSJan Kara 9949e33d69fSJan Kara chunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS); 9959e33d69fSJan Kara if (!chunk) { 9969e33d69fSJan Kara status = -ENOMEM; 9979e33d69fSJan Kara mlog_errno(status); 9989e33d69fSJan Kara goto out; 9999e33d69fSJan Kara } 10000584974aSJan Kara /* Local quota info and two new blocks we initialize */ 10010584974aSJan Kara handle = ocfs2_start_trans(OCFS2_SB(sb), 10020584974aSJan Kara OCFS2_LOCAL_QINFO_WRITE_CREDITS + 10030584974aSJan Kara 2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); 10049e33d69fSJan Kara if (IS_ERR(handle)) { 10059e33d69fSJan Kara status = PTR_ERR(handle); 10069e33d69fSJan Kara mlog_errno(status); 10079e33d69fSJan Kara goto out; 10089e33d69fSJan Kara } 10099e33d69fSJan Kara 10100e7f387bSJan Kara /* Initialize chunk header */ 10110e7f387bSJan Kara status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, 10120e7f387bSJan Kara &p_blkno, NULL, NULL); 10130e7f387bSJan Kara if (status < 0) { 10140e7f387bSJan Kara mlog_errno(status); 10150e7f387bSJan Kara goto out_trans; 10160e7f387bSJan Kara } 10170e7f387bSJan Kara bh = sb_getblk(sb, p_blkno); 10180e7f387bSJan Kara if (!bh) { 10190e7f387bSJan Kara status = -ENOMEM; 10200e7f387bSJan Kara mlog_errno(status); 10210e7f387bSJan Kara goto out_trans; 10220e7f387bSJan Kara } 10230e7f387bSJan Kara dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; 10248cb471e8SJoel Becker ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), bh); 10250cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), bh, 10260e7f387bSJan Kara OCFS2_JOURNAL_ACCESS_CREATE); 10279e33d69fSJan Kara if (status < 0) { 10289e33d69fSJan Kara mlog_errno(status); 10299e33d69fSJan Kara goto out_trans; 10309e33d69fSJan Kara } 10319e33d69fSJan Kara lock_buffer(bh); 1032df32b334STao Ma dchunk->dqc_free = cpu_to_le32(ol_quota_entries_per_block(sb)); 10339e33d69fSJan Kara memset(dchunk->dqc_bitmap, 0, 10349e33d69fSJan Kara sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) - 10359e33d69fSJan Kara OCFS2_QBLK_RESERVED_SPACE); 10369e33d69fSJan Kara unlock_buffer(bh); 1037ec20cec7SJoel Becker ocfs2_journal_dirty(handle, bh); 10389e33d69fSJan Kara 10390e7f387bSJan Kara /* Initialize new block with structures */ 10400e7f387bSJan Kara status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1, 10410e7f387bSJan Kara &p_blkno, NULL, NULL); 10420e7f387bSJan Kara if (status < 0) { 10430e7f387bSJan Kara mlog_errno(status); 10440e7f387bSJan Kara goto out_trans; 10450e7f387bSJan Kara } 10460e7f387bSJan Kara dbh = sb_getblk(sb, p_blkno); 10470e7f387bSJan Kara if (!dbh) { 10480e7f387bSJan Kara status = -ENOMEM; 10490e7f387bSJan Kara mlog_errno(status); 10500e7f387bSJan Kara goto out_trans; 10510e7f387bSJan Kara } 10528cb471e8SJoel Becker ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), dbh); 10530cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), dbh, 10540e7f387bSJan Kara OCFS2_JOURNAL_ACCESS_CREATE); 10550e7f387bSJan Kara if (status < 0) { 10560e7f387bSJan Kara mlog_errno(status); 10570e7f387bSJan Kara goto out_trans; 10580e7f387bSJan Kara } 10590e7f387bSJan Kara lock_buffer(dbh); 10600e7f387bSJan Kara memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE); 10610e7f387bSJan Kara unlock_buffer(dbh); 1062ec20cec7SJoel Becker ocfs2_journal_dirty(handle, dbh); 10630e7f387bSJan Kara 10640e7f387bSJan Kara /* Update local quotafile info */ 10659e33d69fSJan Kara oinfo->dqi_blocks += 2; 10669e33d69fSJan Kara oinfo->dqi_chunks++; 10679e33d69fSJan Kara status = ocfs2_local_write_info(sb, type); 10689e33d69fSJan Kara if (status < 0) { 10699e33d69fSJan Kara mlog_errno(status); 10709e33d69fSJan Kara goto out_trans; 10719e33d69fSJan Kara } 10729e33d69fSJan Kara status = ocfs2_commit_trans(OCFS2_SB(sb), handle); 10739e33d69fSJan Kara if (status < 0) { 10749e33d69fSJan Kara mlog_errno(status); 10759e33d69fSJan Kara goto out; 10769e33d69fSJan Kara } 10779e33d69fSJan Kara 10789e33d69fSJan Kara list_add_tail(&chunk->qc_chunk, &oinfo->dqi_chunk); 10799e33d69fSJan Kara chunk->qc_num = list_entry(chunk->qc_chunk.prev, 10809e33d69fSJan Kara struct ocfs2_quota_chunk, 10819e33d69fSJan Kara qc_chunk)->qc_num + 1; 10829e33d69fSJan Kara chunk->qc_headerbh = bh; 10839e33d69fSJan Kara *offset = 0; 10849e33d69fSJan Kara return chunk; 10859e33d69fSJan Kara out_trans: 10869e33d69fSJan Kara ocfs2_commit_trans(OCFS2_SB(sb), handle); 10879e33d69fSJan Kara out: 10889e33d69fSJan Kara brelse(bh); 10890e7f387bSJan Kara brelse(dbh); 10909e33d69fSJan Kara kmem_cache_free(ocfs2_qf_chunk_cachep, chunk); 10919e33d69fSJan Kara return ERR_PTR(status); 10929e33d69fSJan Kara } 10939e33d69fSJan Kara 10949e33d69fSJan Kara /* Find free entry in local quota file */ 10959e33d69fSJan Kara static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( 10969e33d69fSJan Kara struct super_block *sb, 10979e33d69fSJan Kara int type, 10989e33d69fSJan Kara int *offset) 10999e33d69fSJan Kara { 11009e33d69fSJan Kara struct mem_dqinfo *info = sb_dqinfo(sb, type); 11019e33d69fSJan Kara struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; 11029e33d69fSJan Kara struct ocfs2_quota_chunk *chunk; 11039e33d69fSJan Kara struct inode *lqinode = sb_dqopt(sb)->files[type]; 11049e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 11059e33d69fSJan Kara int epb = ol_quota_entries_per_block(sb); 11069e33d69fSJan Kara unsigned int chunk_blocks; 11070e7f387bSJan Kara struct buffer_head *bh; 11080e7f387bSJan Kara u64 p_blkno; 11099e33d69fSJan Kara int status; 11109e33d69fSJan Kara handle_t *handle; 11119e33d69fSJan Kara 11129e33d69fSJan Kara if (list_empty(&oinfo->dqi_chunk)) 11139e33d69fSJan Kara return ocfs2_local_quota_add_chunk(sb, type, offset); 11149e33d69fSJan Kara /* Is the last chunk full? */ 11159e33d69fSJan Kara chunk = list_entry(oinfo->dqi_chunk.prev, 11169e33d69fSJan Kara struct ocfs2_quota_chunk, qc_chunk); 11179e33d69fSJan Kara chunk_blocks = oinfo->dqi_blocks - 11189e33d69fSJan Kara ol_quota_chunk_block(sb, chunk->qc_num) - 1; 11199e33d69fSJan Kara if (ol_chunk_blocks(sb) == chunk_blocks) 11209e33d69fSJan Kara return ocfs2_local_quota_add_chunk(sb, type, offset); 11219e33d69fSJan Kara 11229e33d69fSJan Kara /* We are protected by dqio_sem so no locking needed */ 11235693486bSJoel Becker status = ocfs2_extend_no_holes(lqinode, NULL, 1124f17c20ddSJunxiao Bi i_size_read(lqinode) + sb->s_blocksize, 1125f17c20ddSJunxiao Bi i_size_read(lqinode)); 11269e33d69fSJan Kara if (status < 0) { 11279e33d69fSJan Kara mlog_errno(status); 11289e33d69fSJan Kara goto out; 11299e33d69fSJan Kara } 11309e33d69fSJan Kara status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh, 1131f17c20ddSJunxiao Bi i_size_read(lqinode) + sb->s_blocksize); 11329e33d69fSJan Kara if (status < 0) { 11339e33d69fSJan Kara mlog_errno(status); 11349e33d69fSJan Kara goto out; 11359e33d69fSJan Kara } 11360e7f387bSJan Kara 11370e7f387bSJan Kara /* Get buffer from the just added block */ 11380e7f387bSJan Kara status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, 11390e7f387bSJan Kara &p_blkno, NULL, NULL); 11400e7f387bSJan Kara if (status < 0) { 11410e7f387bSJan Kara mlog_errno(status); 11420e7f387bSJan Kara goto out; 11430e7f387bSJan Kara } 11440e7f387bSJan Kara bh = sb_getblk(sb, p_blkno); 11450e7f387bSJan Kara if (!bh) { 11460e7f387bSJan Kara status = -ENOMEM; 11470e7f387bSJan Kara mlog_errno(status); 11480e7f387bSJan Kara goto out; 11490e7f387bSJan Kara } 11508cb471e8SJoel Becker ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), bh); 11510e7f387bSJan Kara 11520584974aSJan Kara /* Local quota info, chunk header and the new block we initialize */ 11530584974aSJan Kara handle = ocfs2_start_trans(OCFS2_SB(sb), 11540584974aSJan Kara OCFS2_LOCAL_QINFO_WRITE_CREDITS + 11550584974aSJan Kara 2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); 11569e33d69fSJan Kara if (IS_ERR(handle)) { 11579e33d69fSJan Kara status = PTR_ERR(handle); 11589e33d69fSJan Kara mlog_errno(status); 11599e33d69fSJan Kara goto out; 11609e33d69fSJan Kara } 11610e7f387bSJan Kara /* Zero created block */ 11620cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), bh, 11630e7f387bSJan Kara OCFS2_JOURNAL_ACCESS_CREATE); 11640e7f387bSJan Kara if (status < 0) { 11650e7f387bSJan Kara mlog_errno(status); 11660e7f387bSJan Kara goto out_trans; 11670e7f387bSJan Kara } 11680e7f387bSJan Kara lock_buffer(bh); 11690e7f387bSJan Kara memset(bh->b_data, 0, sb->s_blocksize); 11700e7f387bSJan Kara unlock_buffer(bh); 1171ec20cec7SJoel Becker ocfs2_journal_dirty(handle, bh); 1172ec20cec7SJoel Becker 11730e7f387bSJan Kara /* Update chunk header */ 11740cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), 11750cf2f763SJoel Becker chunk->qc_headerbh, 11769e33d69fSJan Kara OCFS2_JOURNAL_ACCESS_WRITE); 11779e33d69fSJan Kara if (status < 0) { 11789e33d69fSJan Kara mlog_errno(status); 11799e33d69fSJan Kara goto out_trans; 11809e33d69fSJan Kara } 11819e33d69fSJan Kara 11829e33d69fSJan Kara dchunk = (struct ocfs2_local_disk_chunk *)chunk->qc_headerbh->b_data; 11839e33d69fSJan Kara lock_buffer(chunk->qc_headerbh); 11849e33d69fSJan Kara le32_add_cpu(&dchunk->dqc_free, ol_quota_entries_per_block(sb)); 11859e33d69fSJan Kara unlock_buffer(chunk->qc_headerbh); 1186ec20cec7SJoel Becker ocfs2_journal_dirty(handle, chunk->qc_headerbh); 1187ec20cec7SJoel Becker 11880e7f387bSJan Kara /* Update file header */ 11899e33d69fSJan Kara oinfo->dqi_blocks++; 11909e33d69fSJan Kara status = ocfs2_local_write_info(sb, type); 11919e33d69fSJan Kara if (status < 0) { 11929e33d69fSJan Kara mlog_errno(status); 11939e33d69fSJan Kara goto out_trans; 11949e33d69fSJan Kara } 11959e33d69fSJan Kara 11969e33d69fSJan Kara status = ocfs2_commit_trans(OCFS2_SB(sb), handle); 11979e33d69fSJan Kara if (status < 0) { 11989e33d69fSJan Kara mlog_errno(status); 11999e33d69fSJan Kara goto out; 12009e33d69fSJan Kara } 12019e33d69fSJan Kara *offset = chunk_blocks * epb; 12029e33d69fSJan Kara return chunk; 12039e33d69fSJan Kara out_trans: 12049e33d69fSJan Kara ocfs2_commit_trans(OCFS2_SB(sb), handle); 12059e33d69fSJan Kara out: 12069e33d69fSJan Kara return ERR_PTR(status); 12079e33d69fSJan Kara } 12089e33d69fSJan Kara 1209df32b334STao Ma static void olq_alloc_dquot(struct buffer_head *bh, void *private) 12109e33d69fSJan Kara { 12119e33d69fSJan Kara int *offset = private; 12129e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 12139e33d69fSJan Kara 12149e33d69fSJan Kara dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; 121593925579SAkinobu Mita ocfs2_set_bit_unaligned(*offset, dchunk->dqc_bitmap); 12169e33d69fSJan Kara le32_add_cpu(&dchunk->dqc_free, -1); 12179e33d69fSJan Kara } 12189e33d69fSJan Kara 12199e33d69fSJan Kara /* Create dquot in the local file for given id */ 1220fb8dd8d7SJan Kara int ocfs2_create_local_dquot(struct dquot *dquot) 12219e33d69fSJan Kara { 12229e33d69fSJan Kara struct super_block *sb = dquot->dq_sb; 12234c376dcaSEric W. Biederman int type = dquot->dq_id.type; 12249e33d69fSJan Kara struct inode *lqinode = sb_dqopt(sb)->files[type]; 12259e33d69fSJan Kara struct ocfs2_quota_chunk *chunk; 12269e33d69fSJan Kara struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); 12279e33d69fSJan Kara int offset; 12289e33d69fSJan Kara int status; 1229f64dd44eSJan Kara u64 pcount; 12309e33d69fSJan Kara 1231f64dd44eSJan Kara down_write(&OCFS2_I(lqinode)->ip_alloc_sem); 12329e33d69fSJan Kara chunk = ocfs2_find_free_entry(sb, type, &offset); 12339e33d69fSJan Kara if (!chunk) { 12349e33d69fSJan Kara chunk = ocfs2_extend_local_quota_file(sb, type, &offset); 1235f64dd44eSJan Kara if (IS_ERR(chunk)) { 1236f64dd44eSJan Kara status = PTR_ERR(chunk); 1237f64dd44eSJan Kara goto out; 1238f64dd44eSJan Kara } 12399e33d69fSJan Kara } else if (IS_ERR(chunk)) { 1240f64dd44eSJan Kara status = PTR_ERR(chunk); 1241f64dd44eSJan Kara goto out; 12429e33d69fSJan Kara } 12439e33d69fSJan Kara od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset); 12449e33d69fSJan Kara od->dq_chunk = chunk; 1245f64dd44eSJan Kara status = ocfs2_extent_map_get_blocks(lqinode, 1246f64dd44eSJan Kara ol_dqblk_block(sb, chunk->qc_num, offset), 1247f64dd44eSJan Kara &od->dq_local_phys_blk, 1248f64dd44eSJan Kara &pcount, 1249f64dd44eSJan Kara NULL); 12501b13a703SArtem Chernyshev if (status < 0) { 12511b13a703SArtem Chernyshev mlog_errno(status); 12521b13a703SArtem Chernyshev goto out; 12531b13a703SArtem Chernyshev } 12549e33d69fSJan Kara 12559e33d69fSJan Kara /* Initialize dquot structure on disk */ 12569e33d69fSJan Kara status = ocfs2_local_write_dquot(dquot); 12579e33d69fSJan Kara if (status < 0) { 12589e33d69fSJan Kara mlog_errno(status); 12599e33d69fSJan Kara goto out; 12609e33d69fSJan Kara } 12619e33d69fSJan Kara 12629e33d69fSJan Kara /* Mark structure as allocated */ 12639e33d69fSJan Kara status = ocfs2_modify_bh(lqinode, chunk->qc_headerbh, olq_alloc_dquot, 12649e33d69fSJan Kara &offset); 12659e33d69fSJan Kara if (status < 0) { 12669e33d69fSJan Kara mlog_errno(status); 12679e33d69fSJan Kara goto out; 12689e33d69fSJan Kara } 12699e33d69fSJan Kara out: 1270f64dd44eSJan Kara up_write(&OCFS2_I(lqinode)->ip_alloc_sem); 12719e33d69fSJan Kara return status; 12729e33d69fSJan Kara } 12739e33d69fSJan Kara 1274fb8dd8d7SJan Kara /* 1275fb8dd8d7SJan Kara * Release dquot structure from local quota file. ocfs2_release_dquot() has 1276fb8dd8d7SJan Kara * already started a transaction and written all changes to global quota file 1277fb8dd8d7SJan Kara */ 1278fb8dd8d7SJan Kara int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot) 12799e33d69fSJan Kara { 12809e33d69fSJan Kara int status; 12814c376dcaSEric W. Biederman int type = dquot->dq_id.type; 12829e33d69fSJan Kara struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); 12839e33d69fSJan Kara struct super_block *sb = dquot->dq_sb; 12849e33d69fSJan Kara struct ocfs2_local_disk_chunk *dchunk; 12859e33d69fSJan Kara int offset; 12869e33d69fSJan Kara 12870cf2f763SJoel Becker status = ocfs2_journal_access_dq(handle, 12880cf2f763SJoel Becker INODE_CACHE(sb_dqopt(sb)->files[type]), 12899e33d69fSJan Kara od->dq_chunk->qc_headerbh, OCFS2_JOURNAL_ACCESS_WRITE); 12909e33d69fSJan Kara if (status < 0) { 12919e33d69fSJan Kara mlog_errno(status); 12929e33d69fSJan Kara goto out; 12939e33d69fSJan Kara } 12949e33d69fSJan Kara offset = ol_dqblk_chunk_off(sb, od->dq_chunk->qc_num, 12959e33d69fSJan Kara od->dq_local_off); 12969e33d69fSJan Kara dchunk = (struct ocfs2_local_disk_chunk *) 12979e33d69fSJan Kara (od->dq_chunk->qc_headerbh->b_data); 12989e33d69fSJan Kara /* Mark structure as freed */ 12999e33d69fSJan Kara lock_buffer(od->dq_chunk->qc_headerbh); 130093925579SAkinobu Mita ocfs2_clear_bit_unaligned(offset, dchunk->dqc_bitmap); 13019e33d69fSJan Kara le32_add_cpu(&dchunk->dqc_free, 1); 13029e33d69fSJan Kara unlock_buffer(od->dq_chunk->qc_headerbh); 1303ec20cec7SJoel Becker ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); 1304ec20cec7SJoel Becker 13059e33d69fSJan Kara out: 13069e33d69fSJan Kara return status; 13079e33d69fSJan Kara } 13089e33d69fSJan Kara 13091472da5fSAlexey Dobriyan static const struct quota_format_ops ocfs2_format_ops = { 13109e33d69fSJan Kara .check_quota_file = ocfs2_local_check_quota_file, 13119e33d69fSJan Kara .read_file_info = ocfs2_local_read_info, 13129e33d69fSJan Kara .write_file_info = ocfs2_global_write_info, 13139e33d69fSJan Kara .free_file_info = ocfs2_local_free_info, 13149e33d69fSJan Kara }; 13159e33d69fSJan Kara 13169e33d69fSJan Kara struct quota_format_type ocfs2_quota_format = { 13179e33d69fSJan Kara .qf_fmt_id = QFMT_OCFS2, 13189e33d69fSJan Kara .qf_ops = &ocfs2_format_ops, 13199e33d69fSJan Kara .qf_owner = THIS_MODULE 13209e33d69fSJan Kara }; 1321