xref: /linux/fs/ocfs2/quota_local.c (revision 839c4f596f898edc424070dc8b517381572f8502)
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