Blame view

fs/xfs/xfs_dquot.c 34.3 KB
0b61f8a40   Dave Chinner   xfs: convert to S...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
4ce3121f6   Nathan Scott   [XFS] Update lice...
3
4
   * Copyright (c) 2000-2003 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
  #include "xfs.h"
  #include "xfs_fs.h"
6ca1c9063   Dave Chinner   xfs: separate dqu...
8
  #include "xfs_format.h"
239880ef6   Dave Chinner   xfs: decouple log...
9
  #include "xfs_log_format.h"
70a9883c5   Dave Chinner   xfs: create a sha...
10
  #include "xfs_shared.h"
239880ef6   Dave Chinner   xfs: decouple log...
11
  #include "xfs_trans_resv.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
12
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include "xfs_mount.h"
3ab78df2a   Darrick J. Wong   xfs: rework xfs_b...
14
  #include "xfs_defer.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include "xfs_inode.h"
  #include "xfs_bmap.h"
239880ef6   Dave Chinner   xfs: decouple log...
17
  #include "xfs_quota.h"
239880ef6   Dave Chinner   xfs: decouple log...
18
  #include "xfs_trans.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
  #include "xfs_buf_item.h"
  #include "xfs_trans_space.h"
  #include "xfs_trans_priv.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "xfs_qm.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
23
  #include "xfs_trace.h"
239880ef6   Dave Chinner   xfs: decouple log...
24
  #include "xfs_log.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
25
  #include "xfs_bmap_btree.h"
afeda6000   Darrick J. Wong   xfs: validate ond...
26
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  /*
bf72de319   Christoph Hellwig   xfs: nest qm_dqfr...
29
30
31
   * Lock order:
   *
   * ip->i_lock
9f920f116   Christoph Hellwig   xfs: use per-file...
32
   *   qi->qi_tree_lock
b84a3a967   Christoph Hellwig   xfs: remove the p...
33
34
35
   *     dquot->q_qlock (xfs_dqlock() and friends)
   *       dquot->q_flush (xfs_dqflock() and friends)
   *       qi->qi_lru_lock
bf72de319   Christoph Hellwig   xfs: nest qm_dqfr...
36
37
38
39
   *
   * If two dquots need to be locked the order is user before group/project,
   * otherwise by the lowest id first, see xfs_dqlock2.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

a05931ceb   Christoph Hellwig   xfs: remove the g...
41
42
  struct kmem_zone		*xfs_qm_dqtrxzone;
  static struct kmem_zone		*xfs_qm_dqzone;
f112a0497   Dave Chinner   xfs: lockdep need...
43
44
  static struct lock_class_key xfs_dquot_group_class;
  static struct lock_class_key xfs_dquot_project_class;
98b8c7a0c   Christoph Hellwig   xfs: add a lock c...
45

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
   * This is called to free all the memory associated with a dquot
   */
  void
  xfs_qm_dqdestroy(
aefe69a45   Pavel Reichl   xfs: remove the x...
51
  	struct xfs_dquot	*dqp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  {
f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
53
  	ASSERT(list_empty(&dqp->q_lru));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

b1c5ebb21   Dave Chinner   xfs: allocate log...
55
  	kmem_free(dqp->q_logitem.qli_item.li_lv_shadow);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	mutex_destroy(&dqp->q_qlock);
0b1b213fc   Christoph Hellwig   xfs: event tracin...
57

ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
58
  	XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot);
377bcd5f3   Carlos Maiolino   xfs: Remove kmem_...
59
  	kmem_cache_free(xfs_qm_dqzone, dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
   * If default limits are in force, push them into the dquot now.
   * We overwrite the dquot limits only if they are zero and this
   * is not the root dquot.
   */
  void
  xfs_qm_adjust_dqlimits(
4b6eae2e6   Brian Foster   xfs: pass xfs_dqu...
69
  	struct xfs_dquot	*dq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {
c8c753e19   Darrick J. Wong   xfs: remove unnec...
71
  	struct xfs_mount	*mp = dq->q_mount;
4b6eae2e6   Brian Foster   xfs: pass xfs_dqu...
72
  	struct xfs_quotainfo	*q = mp->m_quotainfo;
be6079461   Carlos Maiolino   xfs: Split defaul...
73
  	struct xfs_def_quota	*defq;
b13664511   Brian Foster   xfs: xfs_dquot pr...
74
  	int			prealloc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75

c51df7334   Darrick J. Wong   xfs: stop using q...
76
  	ASSERT(dq->q_id);
ce6e7e79c   Eric Sandeen   xfs: switch xfs_g...
77
  	defq = xfs_get_defquota(q, xfs_dquot_type(dq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

12d720fb8   Darrick J. Wong   xfs: assume the d...
79
  	if (!dq->q_blk.softlimit) {
438769e31   Darrick J. Wong   xfs: refactor def...
80
  		dq->q_blk.softlimit = defq->blk.soft;
b13664511   Brian Foster   xfs: xfs_dquot pr...
81
82
  		prealloc = 1;
  	}
12d720fb8   Darrick J. Wong   xfs: assume the d...
83
  	if (!dq->q_blk.hardlimit) {
438769e31   Darrick J. Wong   xfs: refactor def...
84
  		dq->q_blk.hardlimit = defq->blk.hard;
b13664511   Brian Foster   xfs: xfs_dquot pr...
85
86
  		prealloc = 1;
  	}
12d720fb8   Darrick J. Wong   xfs: assume the d...
87
  	if (!dq->q_ino.softlimit)
438769e31   Darrick J. Wong   xfs: refactor def...
88
  		dq->q_ino.softlimit = defq->ino.soft;
12d720fb8   Darrick J. Wong   xfs: assume the d...
89
  	if (!dq->q_ino.hardlimit)
438769e31   Darrick J. Wong   xfs: refactor def...
90
  		dq->q_ino.hardlimit = defq->ino.hard;
12d720fb8   Darrick J. Wong   xfs: assume the d...
91
  	if (!dq->q_rtb.softlimit)
438769e31   Darrick J. Wong   xfs: refactor def...
92
  		dq->q_rtb.softlimit = defq->rtb.soft;
12d720fb8   Darrick J. Wong   xfs: assume the d...
93
  	if (!dq->q_rtb.hardlimit)
438769e31   Darrick J. Wong   xfs: refactor def...
94
  		dq->q_rtb.hardlimit = defq->rtb.hard;
b13664511   Brian Foster   xfs: xfs_dquot pr...
95
96
97
  
  	if (prealloc)
  		xfs_dquot_set_prealloc_limits(dq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  }
11d8a9190   Darrick J. Wong   xfs: refactor quo...
99
100
101
102
103
104
105
106
107
108
109
  /* Set the expiration time of a quota's grace period. */
  time64_t
  xfs_dquot_set_timeout(
  	struct xfs_mount	*mp,
  	time64_t		timeout)
  {
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
  
  	return clamp_t(time64_t, timeout, qi->qi_expiry_min,
  					  qi->qi_expiry_max);
  }
ccc8e771a   Darrick J. Wong   xfs: refactor def...
110
111
112
113
114
115
116
  /* Set the length of the default grace period. */
  time64_t
  xfs_dquot_set_grace_period(
  	time64_t		grace)
  {
  	return clamp_t(time64_t, grace, XFS_DQ_GRACE_MIN, XFS_DQ_GRACE_MAX);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  /*
ea0cc6fa8   Darrick J. Wong   xfs: refactor quo...
118
119
120
121
122
   * Determine if this quota counter is over either limit and set the quota
   * timers as appropriate.
   */
  static inline void
  xfs_qm_adjust_res_timer(
11d8a9190   Darrick J. Wong   xfs: refactor quo...
123
  	struct xfs_mount	*mp,
ea0cc6fa8   Darrick J. Wong   xfs: refactor quo...
124
125
126
127
128
129
130
131
  	struct xfs_dquot_res	*res,
  	struct xfs_quota_limits	*qlim)
  {
  	ASSERT(res->hardlimit == 0 || res->softlimit <= res->hardlimit);
  
  	if ((res->softlimit && res->count > res->softlimit) ||
  	    (res->hardlimit && res->count > res->hardlimit)) {
  		if (res->timer == 0)
11d8a9190   Darrick J. Wong   xfs: refactor quo...
132
133
  			res->timer = xfs_dquot_set_timeout(mp,
  					ktime_get_real_seconds() + qlim->time);
ea0cc6fa8   Darrick J. Wong   xfs: refactor quo...
134
135
136
137
138
139
140
141
142
  	} else {
  		if (res->timer == 0)
  			res->warnings = 0;
  		else
  			res->timer = 0;
  	}
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
149
150
   * Check the limits and timers of a dquot and start or reset timers
   * if necessary.
   * This gets called even when quota enforcement is OFF, which makes our
   * life a little less complicated. (We just don't reject any quota
   * reservations in that case, when enforcement is off).
   * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
   * enforcement's off.
   * In contrast, warnings are a little different in that they don't
754002b4f   Nathan Scott   [XFS] Merge a few...
151
152
153
   * 'automatically' get started when limits get exceeded.  They do
   * get reset to zero, however, when we find the count to be under
   * the soft limit (they are only ever set non-zero via userspace).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
   */
  void
  xfs_qm_adjust_dqtimers(
3dbb9aa31   Eric Sandeen   xfs: pass xfs_dqu...
157
  	struct xfs_dquot	*dq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  {
c8c753e19   Darrick J. Wong   xfs: remove unnec...
159
  	struct xfs_mount	*mp = dq->q_mount;
e850301f0   Eric Sandeen   xfs: per-type quo...
160
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
e850301f0   Eric Sandeen   xfs: per-type quo...
161
  	struct xfs_def_quota	*defq;
c51df7334   Darrick J. Wong   xfs: stop using q...
162
  	ASSERT(dq->q_id);
e850301f0   Eric Sandeen   xfs: per-type quo...
163
  	defq = xfs_get_defquota(qi, xfs_dquot_type(dq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

11d8a9190   Darrick J. Wong   xfs: refactor quo...
165
166
167
  	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_blk, &defq->blk);
  	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_ino, &defq->ino);
  	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_rtb, &defq->rtb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
   * initialize a buffer full of dquots and log the whole thing
   */
  STATIC void
  xfs_qm_init_dquot_blk(
78bba5c81   Darrick J. Wong   xfs: use ordered ...
175
176
177
  	struct xfs_trans	*tp,
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
178
  	xfs_dqtype_t		type,
78bba5c81   Darrick J. Wong   xfs: use ordered ...
179
  	struct xfs_buf		*bp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  {
8a7b8a89a   Christoph Hellwig   xfs: access quota...
181
  	struct xfs_quotainfo	*q = mp->m_quotainfo;
78bba5c81   Darrick J. Wong   xfs: use ordered ...
182
183
184
185
186
  	struct xfs_dqblk	*d;
  	xfs_dqid_t		curid;
  	unsigned int		qflag;
  	unsigned int		blftype;
  	int			i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
  
  	ASSERT(tp);
0c842ad46   Christoph Hellwig   xfs: clean up buf...
189
  	ASSERT(xfs_buf_islocked(bp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

e6eb603c7   Darrick J. Wong   xfs: refactor quo...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  	switch (type) {
  	case XFS_DQTYPE_USER:
  		qflag = XFS_UQUOTA_CHKD;
  		blftype = XFS_BLF_UDQUOT_BUF;
  		break;
  	case XFS_DQTYPE_PROJ:
  		qflag = XFS_PQUOTA_CHKD;
  		blftype = XFS_BLF_PDQUOT_BUF;
  		break;
  	case XFS_DQTYPE_GROUP:
  		qflag = XFS_GQUOTA_CHKD;
  		blftype = XFS_BLF_GDQUOT_BUF;
  		break;
  	default:
  		ASSERT(0);
  		return;
  	}
629260444   Chandra Seetharaman   xfs: Remove the m...
208
  	d = bp->b_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
  
  	/*
  	 * ID of the first dquot in the block - id's are zero based.
  	 */
8a7b8a89a   Christoph Hellwig   xfs: access quota...
213
  	curid = id - (id % q->qi_dqperchunk);
8a7b8a89a   Christoph Hellwig   xfs: access quota...
214
  	memset(d, 0, BBTOB(q->qi_dqchunklen));
49d35a5cf   Christoph Hellwig   xfs: merge xfs_qm...
215
216
217
218
  	for (i = 0; i < q->qi_dqperchunk; i++, d++, curid++) {
  		d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
  		d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
  		d->dd_diskdq.d_id = cpu_to_be32(curid);
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
219
  		d->dd_diskdq.d_type = type;
4ea1ff3b4   Darrick J. Wong   xfs: widen ondisk...
220
221
  		if (curid > 0 && xfs_sb_version_hasbigtime(&mp->m_sb))
  			d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME;
6fcdc59de   Dave Chinner   xfs: rework dquot...
222
  		if (xfs_sb_version_hascrc(&mp->m_sb)) {
928634514   Dave Chinner   xfs: dquots shoul...
223
  			uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid);
6fcdc59de   Dave Chinner   xfs: rework dquot...
224
225
226
  			xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
  					 XFS_DQUOT_CRC_OFF);
  		}
49d35a5cf   Christoph Hellwig   xfs: merge xfs_qm...
227
  	}
78bba5c81   Darrick J. Wong   xfs: use ordered ...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  	xfs_trans_dquot_buf(tp, bp, blftype);
  
  	/*
  	 * quotacheck uses delayed writes to update all the dquots on disk in an
  	 * efficient manner instead of logging the individual dquot changes as
  	 * they are made. However if we log the buffer allocated here and crash
  	 * after quotacheck while the logged initialisation is still in the
  	 * active region of the log, log recovery can replay the dquot buffer
  	 * initialisation over the top of the checked dquots and corrupt quota
  	 * accounting.
  	 *
  	 * To avoid this problem, quotacheck cannot log the initialised buffer.
  	 * We must still dirty the buffer and write it back before the
  	 * allocation transaction clears the log. Therefore, mark the buffer as
  	 * ordered instead of logging it directly. This is safe for quotacheck
  	 * because it detects and repairs allocated but initialized dquot blocks
  	 * in the quota inodes.
  	 */
  	if (!(mp->m_qflags & qflag))
  		xfs_trans_ordered_buf(tp, bp);
  	else
  		xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  }
b13664511   Brian Foster   xfs: xfs_dquot pr...
251
252
253
254
255
256
257
258
  /*
   * Initialize the dynamic speculative preallocation thresholds. The lo/hi
   * watermarks correspond to the soft and hard limits by default. If a soft limit
   * is not specified, we use 95% of the hard limit.
   */
  void
  xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
  {
c8ce540db   Darrick J. Wong   xfs: remove doubl...
259
  	uint64_t space;
b13664511   Brian Foster   xfs: xfs_dquot pr...
260

d3537cf93   Darrick J. Wong   xfs: stop using q...
261
262
  	dqp->q_prealloc_hi_wmark = dqp->q_blk.hardlimit;
  	dqp->q_prealloc_lo_wmark = dqp->q_blk.softlimit;
b13664511   Brian Foster   xfs: xfs_dquot pr...
263
264
265
266
267
268
269
270
271
272
273
274
275
  	if (!dqp->q_prealloc_lo_wmark) {
  		dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
  		do_div(dqp->q_prealloc_lo_wmark, 100);
  		dqp->q_prealloc_lo_wmark *= 95;
  	}
  
  	space = dqp->q_prealloc_hi_wmark;
  
  	do_div(space, 100);
  	dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
  	dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
  	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  /*
d63192c89   Darrick J. Wong   xfs: refactor xfs...
277
   * Ensure that the given in-core dquot has a buffer on disk backing it, and
710d707d2   Darrick J. Wong   xfs: always rejoi...
278
279
   * return the buffer locked and held. This is called when the bmapi finds a
   * hole.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
   */
  STATIC int
d63192c89   Darrick J. Wong   xfs: refactor xfs...
282
283
284
285
  xfs_dquot_disk_alloc(
  	struct xfs_trans	**tpp,
  	struct xfs_dquot	*dqp,
  	struct xfs_buf		**bpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  {
d63192c89   Darrick J. Wong   xfs: refactor xfs...
287
  	struct xfs_bmbt_irec	map;
2ba137212   Brian Foster   xfs: use ->t_dfop...
288
289
  	struct xfs_trans	*tp = *tpp;
  	struct xfs_mount	*mp = tp->t_mountp;
d63192c89   Darrick J. Wong   xfs: refactor xfs...
290
  	struct xfs_buf		*bp;
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
291
  	xfs_dqtype_t		qtype = xfs_dquot_type(dqp);
0b04dd5d7   Darrick J. Wong   xfs: always use x...
292
  	struct xfs_inode	*quotip = xfs_quota_inode(mp, qtype);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
293
294
  	int			nmaps = 1;
  	int			error;
0b1b213fc   Christoph Hellwig   xfs: event tracin...
295
296
  
  	trace_xfs_dqalloc(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  	xfs_ilock(quotip, XFS_ILOCK_EXCL);
0b04dd5d7   Darrick J. Wong   xfs: always use x...
299
  	if (!xfs_this_quota_on(dqp->q_mount, qtype)) {
d63192c89   Darrick J. Wong   xfs: refactor xfs...
300
301
302
303
  		/*
  		 * Return if this type of quotas is turned off while we didn't
  		 * have an inode lock
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  		xfs_iunlock(quotip, XFS_ILOCK_EXCL);
2451337dd   Dave Chinner   xfs: global error...
305
  		return -ESRCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	}
d63192c89   Darrick J. Wong   xfs: refactor xfs...
307
  	/* Create the block mapping. */
2ba137212   Brian Foster   xfs: use ->t_dfop...
308
309
  	xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
  	error = xfs_bmapi_write(tp, quotip, dqp->q_fileoffset,
da781e64b   Brian Foster   xfs: don't set bm...
310
311
  			XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, 0, &map,
  			&nmaps);
c0dc7828a   Dave Chinner   xfs: rename xfs_b...
312
  	if (error)
73971b172   Brian Foster   xfs: remove dead ...
313
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
320
321
322
323
324
  	ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
  	ASSERT(nmaps == 1);
  	ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
  	       (map.br_startblock != HOLESTARTBLOCK));
  
  	/*
  	 * Keep track of the blkno to save a lookup later
  	 */
  	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
  
  	/* now we can just get the buffer (there's nothing to read yet) */
ce92464c1   Darrick J. Wong   xfs: make xfs_tra...
325
326
327
328
  	error = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno,
  			mp->m_quotainfo->qi_dqchunklen, 0, &bp);
  	if (error)
  		return error;
1813dd640   Dave Chinner   xfs: convert buff...
329
  	bp->b_ops = &xfs_dquot_buf_ops;
2a30f36d9   Chandra Seetharaman   xfs: Check the re...
330

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
333
334
  	/*
  	 * Make a chunk of dquots out of this buffer and log
  	 * the entire thing.
  	 */
0b04dd5d7   Darrick J. Wong   xfs: always use x...
335
  	xfs_qm_init_dquot_blk(tp, mp, dqp->q_id, qtype, bp);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
336
  	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

efa092f3d   Tim Shimmin   [XFS] Fixes a bug...
338
  	/*
7b6b50f55   Darrick J. Wong   xfs: release new ...
339
340
341
342
343
344
345
346
  	 * Hold the buffer and join it to the dfops so that we'll still own
  	 * the buffer when we return to the caller.  The buffer disposal on
  	 * error must be paid attention to very carefully, as it has been
  	 * broken since commit efa092f3d4c6 "[XFS] Fixes a bug in the quota
  	 * code when allocating a new dquot record" in 2005, and the later
  	 * conversion to xfs_defer_ops in commit 310a75a3c6c747 failed to keep
  	 * the buffer locked across the _defer_finish call.  We can now do
  	 * this correctly with xfs_defer_bjoin.
efa092f3d   Tim Shimmin   [XFS] Fixes a bug...
347
  	 *
73971b172   Brian Foster   xfs: remove dead ...
348
349
  	 * Above, we allocated a disk block for the dquot information and used
  	 * get_buf to initialize the dquot. If the _defer_finish fails, the old
7b6b50f55   Darrick J. Wong   xfs: release new ...
350
351
  	 * transaction is gone but the new buffer is not joined or held to any
  	 * transaction, so we must _buf_relse it.
efa092f3d   Tim Shimmin   [XFS] Fixes a bug...
352
  	 *
7b6b50f55   Darrick J. Wong   xfs: release new ...
353
  	 * If everything succeeds, the caller of this function is returned a
d63192c89   Darrick J. Wong   xfs: refactor xfs...
354
  	 * buffer that is locked and held to the transaction.  The caller
7b6b50f55   Darrick J. Wong   xfs: release new ...
355
  	 * is responsible for unlocking any buffer passed back, either
710d707d2   Darrick J. Wong   xfs: always rejoi...
356
357
  	 * manually or by committing the transaction.  On error, the buffer is
  	 * released and not passed back.
efa092f3d   Tim Shimmin   [XFS] Fixes a bug...
358
  	 */
2ba137212   Brian Foster   xfs: use ->t_dfop...
359
  	xfs_trans_bhold(tp, bp);
9e28a242b   Brian Foster   xfs: drop unneces...
360
  	error = xfs_defer_finish(tpp);
7b6b50f55   Darrick J. Wong   xfs: release new ...
361
  	if (error) {
710d707d2   Darrick J. Wong   xfs: always rejoi...
362
363
  		xfs_trans_bhold_release(*tpp, bp);
  		xfs_trans_brelse(*tpp, bp);
73971b172   Brian Foster   xfs: remove dead ...
364
  		return error;
efa092f3d   Tim Shimmin   [XFS] Fixes a bug...
365
  	}
d63192c89   Darrick J. Wong   xfs: refactor xfs...
366
  	*bpp = bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  }
9aede1d81   Dave Chinner   xfs: split dquot ...
369

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  /*
d63192c89   Darrick J. Wong   xfs: refactor xfs...
371
372
   * Read in the in-core dquot's on-disk metadata and return the buffer.
   * Returns ENOENT to signal a hole.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
   */
  STATIC int
d63192c89   Darrick J. Wong   xfs: refactor xfs...
375
376
377
378
  xfs_dquot_disk_read(
  	struct xfs_mount	*mp,
  	struct xfs_dquot	*dqp,
  	struct xfs_buf		**bpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  {
113a56835   Chandra Seetharaman   xfs: Code cleanup...
380
  	struct xfs_bmbt_irec	map;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
381
  	struct xfs_buf		*bp;
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
382
  	xfs_dqtype_t		qtype = xfs_dquot_type(dqp);
0b04dd5d7   Darrick J. Wong   xfs: always use x...
383
  	struct xfs_inode	*quotip = xfs_quota_inode(mp, qtype);
0891f9971   Christoph Hellwig   Revert "xfs: grab...
384
  	uint			lock_mode;
d63192c89   Darrick J. Wong   xfs: refactor xfs...
385
386
  	int			nmaps = 1;
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

0891f9971   Christoph Hellwig   Revert "xfs: grab...
388
  	lock_mode = xfs_ilock_data_map_shared(quotip);
0b04dd5d7   Darrick J. Wong   xfs: always use x...
389
  	if (!xfs_this_quota_on(mp, qtype)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  		/*
acecf1b5d   Christoph Hellwig   xfs: stop using x...
391
392
  		 * Return if this type of quotas is turned off while we
  		 * didn't have the quota inode lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  		 */
0891f9971   Christoph Hellwig   Revert "xfs: grab...
394
  		xfs_iunlock(quotip, lock_mode);
2451337dd   Dave Chinner   xfs: global error...
395
  		return -ESRCH;
acecf1b5d   Christoph Hellwig   xfs: stop using x...
396
397
398
399
400
  	}
  
  	/*
  	 * Find the block map; no allocations yet
  	 */
5c8ed2021   Dave Chinner   xfs: introduce xf...
401
  	error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
d63192c89   Darrick J. Wong   xfs: refactor xfs...
402
  			XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
0891f9971   Christoph Hellwig   Revert "xfs: grab...
403
  	xfs_iunlock(quotip, lock_mode);
acecf1b5d   Christoph Hellwig   xfs: stop using x...
404
405
406
407
  	if (error)
  		return error;
  
  	ASSERT(nmaps == 1);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
408
409
410
411
412
413
  	ASSERT(map.br_blockcount >= 1);
  	ASSERT(map.br_startblock != DELAYSTARTBLOCK);
  	if (map.br_startblock == HOLESTARTBLOCK)
  		return -ENOENT;
  
  	trace_xfs_dqtobp_read(dqp);
acecf1b5d   Christoph Hellwig   xfs: stop using x...
414
415
  
  	/*
d63192c89   Darrick J. Wong   xfs: refactor xfs...
416
417
  	 * store the blkno etc so that we don't have to do the
  	 * mapping all the time
acecf1b5d   Christoph Hellwig   xfs: stop using x...
418
  	 */
d63192c89   Darrick J. Wong   xfs: refactor xfs...
419
  	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420

d63192c89   Darrick J. Wong   xfs: refactor xfs...
421
422
423
424
425
426
  	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
  			mp->m_quotainfo->qi_dqchunklen, 0, &bp,
  			&xfs_dquot_buf_ops);
  	if (error) {
  		ASSERT(bp == NULL);
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	}
c63191987   Dave Chinner   xfs: verify dquot...
428
  	ASSERT(xfs_buf_islocked(bp));
d63192c89   Darrick J. Wong   xfs: refactor xfs...
429
430
  	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
  	*bpp = bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431

d99831ff3   Eric Sandeen   xfs: return is no...
432
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  }
617cd5c12   Darrick J. Wong   xfs: refactor inc...
434
435
436
  /* Allocate and initialize everything we need for an incore dquot. */
  STATIC struct xfs_dquot *
  xfs_dquot_alloc(
97e7ade50   Christoph Hellwig   xfs: kill xfs_qm_...
437
438
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
439
  	xfs_dqtype_t		type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  {
97e7ade50   Christoph Hellwig   xfs: kill xfs_qm_...
441
  	struct xfs_dquot	*dqp;
92b2e5b31   Christoph Hellwig   xfs: use a normal...
442

32a2b11f4   Carlos Maiolino   xfs: Remove kmem_...
443
  	dqp = kmem_cache_zalloc(xfs_qm_dqzone, GFP_KERNEL | __GFP_NOFAIL);
92b2e5b31   Christoph Hellwig   xfs: use a normal...
444

1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
445
  	dqp->q_type = type;
c51df7334   Darrick J. Wong   xfs: stop using q...
446
  	dqp->q_id = id;
92b2e5b31   Christoph Hellwig   xfs: use a normal...
447
  	dqp->q_mount = mp;
f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
448
  	INIT_LIST_HEAD(&dqp->q_lru);
92b2e5b31   Christoph Hellwig   xfs: use a normal...
449
450
  	mutex_init(&dqp->q_qlock);
  	init_waitqueue_head(&dqp->q_pinwait);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
451
452
453
454
455
456
  	dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
  	/*
  	 * Offset of dquot in the (fixed sized) dquot chunk.
  	 */
  	dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
  			sizeof(xfs_dqblk_t);
92b2e5b31   Christoph Hellwig   xfs: use a normal...
457
458
459
460
461
462
463
464
465
466
467
468
469
  
  	/*
  	 * Because we want to use a counting completion, complete
  	 * the flush completion once to allow a single access to
  	 * the flush completion without blocking.
  	 */
  	init_completion(&dqp->q_flush);
  	complete(&dqp->q_flush);
  
  	/*
  	 * Make sure group quotas have a different lock class than user
  	 * quotas.
  	 */
f112a0497   Dave Chinner   xfs: lockdep need...
470
  	switch (type) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
471
  	case XFS_DQTYPE_USER:
f112a0497   Dave Chinner   xfs: lockdep need...
472
473
  		/* uses the default lock class */
  		break;
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
474
  	case XFS_DQTYPE_GROUP:
f112a0497   Dave Chinner   xfs: lockdep need...
475
476
  		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class);
  		break;
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
477
  	case XFS_DQTYPE_PROJ:
f112a0497   Dave Chinner   xfs: lockdep need...
478
479
480
481
482
483
  		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class);
  		break;
  	default:
  		ASSERT(0);
  		break;
  	}
92b2e5b31   Christoph Hellwig   xfs: use a normal...
484

617cd5c12   Darrick J. Wong   xfs: refactor inc...
485
  	xfs_qm_dquot_logitem_init(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
486
  	XFS_STATS_INC(mp, xs_qm_dquot);
617cd5c12   Darrick J. Wong   xfs: refactor inc...
487
488
489
490
  	return dqp;
  }
  
  /* Copy the in-core quota fields in from the on-disk buffer. */
afeda6000   Darrick J. Wong   xfs: validate ond...
491
  STATIC int
617cd5c12   Darrick J. Wong   xfs: refactor inc...
492
493
  xfs_dquot_from_disk(
  	struct xfs_dquot	*dqp,
d63192c89   Darrick J. Wong   xfs: refactor xfs...
494
  	struct xfs_buf		*bp)
617cd5c12   Darrick J. Wong   xfs: refactor inc...
495
  {
d63192c89   Darrick J. Wong   xfs: refactor xfs...
496
  	struct xfs_disk_dquot	*ddqp = bp->b_addr + dqp->q_bufoffset;
afeda6000   Darrick J. Wong   xfs: validate ond...
497
498
499
500
  	/*
  	 * Ensure that we got the type and ID we were looking for.
  	 * Everything else was checked by the dquot buffer verifier.
  	 */
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
501
  	if ((ddqp->d_type & XFS_DQTYPE_REC_MASK) != xfs_dquot_type(dqp) ||
c51df7334   Darrick J. Wong   xfs: stop using q...
502
  	    be32_to_cpu(ddqp->d_id) != dqp->q_id) {
afeda6000   Darrick J. Wong   xfs: validate ond...
503
504
  		xfs_alert_tag(bp->b_mount, XFS_PTAG_VERIFIER_ERROR,
  			  "Metadata corruption detected at %pS, quota %u",
c51df7334   Darrick J. Wong   xfs: stop using q...
505
  			  __this_address, dqp->q_id);
afeda6000   Darrick J. Wong   xfs: validate ond...
506
507
508
  		xfs_alert(bp->b_mount, "Unmount and run xfs_repair");
  		return -EFSCORRUPTED;
  	}
617cd5c12   Darrick J. Wong   xfs: refactor inc...
509
  	/* copy everything from disk dquot to the incore dquot */
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
510
  	dqp->q_type = ddqp->d_type;
d3537cf93   Darrick J. Wong   xfs: stop using q...
511
512
513
514
515
516
  	dqp->q_blk.hardlimit = be64_to_cpu(ddqp->d_blk_hardlimit);
  	dqp->q_blk.softlimit = be64_to_cpu(ddqp->d_blk_softlimit);
  	dqp->q_ino.hardlimit = be64_to_cpu(ddqp->d_ino_hardlimit);
  	dqp->q_ino.softlimit = be64_to_cpu(ddqp->d_ino_softlimit);
  	dqp->q_rtb.hardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit);
  	dqp->q_rtb.softlimit = be64_to_cpu(ddqp->d_rtb_softlimit);
617cd5c12   Darrick J. Wong   xfs: refactor inc...
517

be37d40c1   Darrick J. Wong   xfs: stop using q...
518
519
520
  	dqp->q_blk.count = be64_to_cpu(ddqp->d_bcount);
  	dqp->q_ino.count = be64_to_cpu(ddqp->d_icount);
  	dqp->q_rtb.count = be64_to_cpu(ddqp->d_rtbcount);
c8c45fb2f   Darrick J. Wong   xfs: stop using q...
521
522
523
  	dqp->q_blk.warnings = be16_to_cpu(ddqp->d_bwarns);
  	dqp->q_ino.warnings = be16_to_cpu(ddqp->d_iwarns);
  	dqp->q_rtb.warnings = be16_to_cpu(ddqp->d_rtbwarns);
9f99c8fe5   Darrick J. Wong   xfs: refactor quo...
524
525
526
  	dqp->q_blk.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_btimer);
  	dqp->q_ino.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_itimer);
  	dqp->q_rtb.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_rtbtimer);
19dce7eae   Darrick J. Wong   xfs: stop using q...
527

617cd5c12   Darrick J. Wong   xfs: refactor inc...
528
529
530
531
  	/*
  	 * Reservation counters are defined as reservation plus current usage
  	 * to avoid having to add every time.
  	 */
be37d40c1   Darrick J. Wong   xfs: stop using q...
532
533
534
  	dqp->q_blk.reserved = dqp->q_blk.count;
  	dqp->q_ino.reserved = dqp->q_ino.count;
  	dqp->q_rtb.reserved = dqp->q_rtb.count;
617cd5c12   Darrick J. Wong   xfs: refactor inc...
535
536
537
  
  	/* initialize the dquot speculative prealloc thresholds */
  	xfs_dquot_set_prealloc_limits(dqp);
afeda6000   Darrick J. Wong   xfs: validate ond...
538
  	return 0;
617cd5c12   Darrick J. Wong   xfs: refactor inc...
539
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540

0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
541
542
543
544
545
546
  /* Copy the in-core quota fields into the on-disk buffer. */
  void
  xfs_dquot_to_disk(
  	struct xfs_disk_dquot	*ddqp,
  	struct xfs_dquot	*dqp)
  {
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
547
548
  	ddqp->d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
  	ddqp->d_version = XFS_DQUOT_VERSION;
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
549
  	ddqp->d_type = dqp->q_type;
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
550
551
552
  	ddqp->d_id = cpu_to_be32(dqp->q_id);
  	ddqp->d_pad0 = 0;
  	ddqp->d_pad = 0;
d3537cf93   Darrick J. Wong   xfs: stop using q...
553
554
555
556
557
558
  	ddqp->d_blk_hardlimit = cpu_to_be64(dqp->q_blk.hardlimit);
  	ddqp->d_blk_softlimit = cpu_to_be64(dqp->q_blk.softlimit);
  	ddqp->d_ino_hardlimit = cpu_to_be64(dqp->q_ino.hardlimit);
  	ddqp->d_ino_softlimit = cpu_to_be64(dqp->q_ino.softlimit);
  	ddqp->d_rtb_hardlimit = cpu_to_be64(dqp->q_rtb.hardlimit);
  	ddqp->d_rtb_softlimit = cpu_to_be64(dqp->q_rtb.softlimit);
be37d40c1   Darrick J. Wong   xfs: stop using q...
559
560
561
562
  
  	ddqp->d_bcount = cpu_to_be64(dqp->q_blk.count);
  	ddqp->d_icount = cpu_to_be64(dqp->q_ino.count);
  	ddqp->d_rtbcount = cpu_to_be64(dqp->q_rtb.count);
c8c45fb2f   Darrick J. Wong   xfs: stop using q...
563
564
565
566
  
  	ddqp->d_bwarns = cpu_to_be16(dqp->q_blk.warnings);
  	ddqp->d_iwarns = cpu_to_be16(dqp->q_ino.warnings);
  	ddqp->d_rtbwarns = cpu_to_be16(dqp->q_rtb.warnings);
19dce7eae   Darrick J. Wong   xfs: stop using q...
567

9f99c8fe5   Darrick J. Wong   xfs: refactor quo...
568
569
570
  	ddqp->d_btimer = xfs_dquot_to_disk_ts(dqp, dqp->q_blk.timer);
  	ddqp->d_itimer = xfs_dquot_to_disk_ts(dqp, dqp->q_ino.timer);
  	ddqp->d_rtbtimer = xfs_dquot_to_disk_ts(dqp, dqp->q_rtb.timer);
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
571
  }
d63192c89   Darrick J. Wong   xfs: refactor xfs...
572
573
574
575
576
577
578
579
  /* Allocate and initialize the dquot buffer for this in-core dquot. */
  static int
  xfs_qm_dqread_alloc(
  	struct xfs_mount	*mp,
  	struct xfs_dquot	*dqp,
  	struct xfs_buf		**bpp)
  {
  	struct xfs_trans	*tp;
d63192c89   Darrick J. Wong   xfs: refactor xfs...
580
581
582
583
584
585
  	int			error;
  
  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
  			XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
  	if (error)
  		goto err;
710d707d2   Darrick J. Wong   xfs: always rejoi...
586
  	error = xfs_dquot_disk_alloc(&tp, dqp, bpp);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
587
588
589
590
591
592
593
594
595
  	if (error)
  		goto err_cancel;
  
  	error = xfs_trans_commit(tp);
  	if (error) {
  		/*
  		 * Buffer was held to the transaction, so we have to unlock it
  		 * manually here because we're not passing it back.
  		 */
710d707d2   Darrick J. Wong   xfs: always rejoi...
596
597
  		xfs_buf_relse(*bpp);
  		*bpp = NULL;
d63192c89   Darrick J. Wong   xfs: refactor xfs...
598
599
  		goto err;
  	}
d63192c89   Darrick J. Wong   xfs: refactor xfs...
600
601
602
603
604
605
606
  	return 0;
  
  err_cancel:
  	xfs_trans_cancel(tp);
  err:
  	return error;
  }
617cd5c12   Darrick J. Wong   xfs: refactor inc...
607
608
  /*
   * Read in the ondisk dquot using dqtobp() then copy it to an incore version,
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
609
610
   * and release the buffer immediately.  If @can_alloc is true, fill any
   * holes in the on-disk metadata.
617cd5c12   Darrick J. Wong   xfs: refactor inc...
611
   */
114e73ccf   Darrick J. Wong   xfs: remove direc...
612
  static int
617cd5c12   Darrick J. Wong   xfs: refactor inc...
613
614
615
  xfs_qm_dqread(
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
616
  	xfs_dqtype_t		type,
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
617
  	bool			can_alloc,
d63192c89   Darrick J. Wong   xfs: refactor xfs...
618
  	struct xfs_dquot	**dqpp)
617cd5c12   Darrick J. Wong   xfs: refactor inc...
619
620
  {
  	struct xfs_dquot	*dqp;
617cd5c12   Darrick J. Wong   xfs: refactor inc...
621
  	struct xfs_buf		*bp;
617cd5c12   Darrick J. Wong   xfs: refactor inc...
622
623
624
  	int			error;
  
  	dqp = xfs_dquot_alloc(mp, id, type);
0b1b213fc   Christoph Hellwig   xfs: event tracin...
625
  	trace_xfs_dqread(dqp);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
626
627
  	/* Try to read the buffer, allocating if necessary. */
  	error = xfs_dquot_disk_read(mp, dqp, &bp);
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
628
  	if (error == -ENOENT && can_alloc)
d63192c89   Darrick J. Wong   xfs: refactor xfs...
629
630
631
  		error = xfs_qm_dqread_alloc(mp, dqp, &bp);
  	if (error)
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
  
  	/*
d63192c89   Darrick J. Wong   xfs: refactor xfs...
634
635
636
637
  	 * At this point we should have a clean locked buffer.  Copy the data
  	 * to the incore dquot and release the buffer since the incore dquot
  	 * has its own locking protocol so we needn't tie up the buffer any
  	 * further.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  	 */
0c842ad46   Christoph Hellwig   xfs: clean up buf...
639
  	ASSERT(xfs_buf_islocked(bp));
afeda6000   Darrick J. Wong   xfs: validate ond...
640
  	error = xfs_dquot_from_disk(dqp, bp);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
641
  	xfs_buf_relse(bp);
afeda6000   Darrick J. Wong   xfs: validate ond...
642
643
  	if (error)
  		goto err;
d63192c89   Darrick J. Wong   xfs: refactor xfs...
644
  	*dqpp = dqp;
97e7ade50   Christoph Hellwig   xfs: kill xfs_qm_...
645
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646

d63192c89   Darrick J. Wong   xfs: refactor xfs...
647
648
  err:
  	trace_xfs_dqread_fail(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  	xfs_qm_dqdestroy(dqp);
d63192c89   Darrick J. Wong   xfs: refactor xfs...
650
  	*dqpp = NULL;
97e7ade50   Christoph Hellwig   xfs: kill xfs_qm_...
651
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
654
  }
  
  /*
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
655
656
657
658
   * Advance to the next id in the current chunk, or if at the
   * end of the chunk, skip ahead to first id in next allocated chunk
   * using the SEEK_DATA interface.
   */
6e3e6d55e   Eryu Guan   xfs: mute some sp...
659
  static int
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
660
  xfs_dq_get_next_id(
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
661
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
662
  	xfs_dqtype_t		type,
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
663
  	xfs_dqid_t		*id)
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
664
  {
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
665
666
667
668
  	struct xfs_inode	*quotip = xfs_quota_inode(mp, type);
  	xfs_dqid_t		next_id = *id + 1; /* simple advance */
  	uint			lock_flags;
  	struct xfs_bmbt_irec	got;
b2b1712a6   Christoph Hellwig   xfs: introduce th...
669
  	struct xfs_iext_cursor	cur;
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
670
  	xfs_fsblock_t		start;
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
671
  	int			error = 0;
657bdfb7f   Eric Sandeen   xfs: don't wrap I...
672
673
674
  	/* If we'd wrap past the max ID, stop */
  	if (next_id < *id)
  		return -ENOENT;
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
675
676
677
678
679
680
681
682
  	/* If new ID is within the current chunk, advancing it sufficed */
  	if (next_id % mp->m_quotainfo->qi_dqperchunk) {
  		*id = next_id;
  		return 0;
  	}
  
  	/* Nope, next_id is now past the current chunk, so find the next one */
  	start = (xfs_fsblock_t)next_id / mp->m_quotainfo->qi_dqperchunk;
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
683
684
685
686
687
688
  	lock_flags = xfs_ilock_data_map_shared(quotip);
  	if (!(quotip->i_df.if_flags & XFS_IFEXTENTS)) {
  		error = xfs_iread_extents(NULL, quotip, XFS_DATA_FORK);
  		if (error)
  			return error;
  	}
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
689

b2b1712a6   Christoph Hellwig   xfs: introduce th...
690
  	if (xfs_iext_lookup_extent(quotip, &quotip->i_df, start, &cur, &got)) {
2192b0bae   Brian Foster   xfs: fix contiguo...
691
692
693
  		/* contiguous chunk, bump startoff for the id calculation */
  		if (got.br_startoff < start)
  			got.br_startoff = start;
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
694
  		*id = got.br_startoff * mp->m_quotainfo->qi_dqperchunk;
2192b0bae   Brian Foster   xfs: fix contiguo...
695
  	} else {
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
696
  		error = -ENOENT;
2192b0bae   Brian Foster   xfs: fix contiguo...
697
  	}
bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
698
  	xfs_iunlock(quotip, lock_flags);
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
699

bda250dba   Christoph Hellwig   xfs: rewrite xfs_...
700
  	return error;
296c24e26   Eric Sandeen   xfs: wire up Q_XG...
701
702
703
  }
  
  /*
cc2047c4d   Darrick J. Wong   xfs: refactor dqu...
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
   * Look up the dquot in the in-core cache.  If found, the dquot is returned
   * locked and ready to go.
   */
  static struct xfs_dquot *
  xfs_qm_dqget_cache_lookup(
  	struct xfs_mount	*mp,
  	struct xfs_quotainfo	*qi,
  	struct radix_tree_root	*tree,
  	xfs_dqid_t		id)
  {
  	struct xfs_dquot	*dqp;
  
  restart:
  	mutex_lock(&qi->qi_tree_lock);
  	dqp = radix_tree_lookup(tree, id);
  	if (!dqp) {
  		mutex_unlock(&qi->qi_tree_lock);
  		XFS_STATS_INC(mp, xs_qm_dqcachemisses);
  		return NULL;
  	}
  
  	xfs_dqlock(dqp);
985a78fdd   Darrick J. Wong   xfs: rename dquot...
726
  	if (dqp->q_flags & XFS_DQFLAG_FREEING) {
cc2047c4d   Darrick J. Wong   xfs: refactor dqu...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  		xfs_dqunlock(dqp);
  		mutex_unlock(&qi->qi_tree_lock);
  		trace_xfs_dqget_freeing(dqp);
  		delay(1);
  		goto restart;
  	}
  
  	dqp->q_nrefs++;
  	mutex_unlock(&qi->qi_tree_lock);
  
  	trace_xfs_dqget_hit(dqp);
  	XFS_STATS_INC(mp, xs_qm_dqcachehits);
  	return dqp;
  }
  
  /*
   * Try to insert a new dquot into the in-core cache.  If an error occurs the
   * caller should throw away the dquot and start over.  Otherwise, the dquot
   * is returned locked (and held by the cache) as if there had been a cache
   * hit.
   */
  static int
  xfs_qm_dqget_cache_insert(
  	struct xfs_mount	*mp,
  	struct xfs_quotainfo	*qi,
  	struct radix_tree_root	*tree,
  	xfs_dqid_t		id,
  	struct xfs_dquot	*dqp)
  {
  	int			error;
  
  	mutex_lock(&qi->qi_tree_lock);
  	error = radix_tree_insert(tree, id, dqp);
  	if (unlikely(error)) {
  		/* Duplicate found!  Caller must try again. */
  		WARN_ON(error != -EEXIST);
  		mutex_unlock(&qi->qi_tree_lock);
  		trace_xfs_dqget_dup(dqp);
  		return error;
  	}
  
  	/* Return a locked dquot to the caller, with a reference taken. */
  	xfs_dqlock(dqp);
  	dqp->q_nrefs = 1;
  
  	qi->qi_dquots++;
  	mutex_unlock(&qi->qi_tree_lock);
  
  	return 0;
  }
d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
777
778
779
780
  /* Check our input parameters. */
  static int
  xfs_qm_dqget_checks(
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
781
  	xfs_dqtype_t		type)
d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
782
783
784
785
786
  {
  	if (WARN_ON_ONCE(!XFS_IS_QUOTA_RUNNING(mp)))
  		return -ESRCH;
  
  	switch (type) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
787
  	case XFS_DQTYPE_USER:
d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
788
789
790
  		if (!XFS_IS_UQUOTA_ON(mp))
  			return -ESRCH;
  		return 0;
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
791
  	case XFS_DQTYPE_GROUP:
d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
792
793
794
  		if (!XFS_IS_GQUOTA_ON(mp))
  			return -ESRCH;
  		return 0;
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
795
  	case XFS_DQTYPE_PROJ:
d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
796
797
798
799
800
801
802
803
  		if (!XFS_IS_PQUOTA_ON(mp))
  			return -ESRCH;
  		return 0;
  	default:
  		WARN_ON_ONCE(0);
  		return -EINVAL;
  	}
  }
cc2047c4d   Darrick J. Wong   xfs: refactor dqu...
804
  /*
a647d109e   Kaixu Xia   xfs: fix some com...
805
806
   * Given the file system, id, and type (UDQUOT/GDQUOT/PDQUOT), return a
   * locked dquot, doing an allocation (if requested) as needed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
   */
  int
  xfs_qm_dqget(
4882c19d2   Darrick J. Wong   xfs: split out dq...
810
811
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
812
  	xfs_dqtype_t		type,
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
813
  	bool			can_alloc,
4882c19d2   Darrick J. Wong   xfs: split out dq...
814
  	struct xfs_dquot	**O_dqpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  {
9f920f116   Christoph Hellwig   xfs: use per-file...
816
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
4882c19d2   Darrick J. Wong   xfs: split out dq...
817
  	struct radix_tree_root	*tree = xfs_dquot_tree(qi, type);
9f920f116   Christoph Hellwig   xfs: use per-file...
818
819
  	struct xfs_dquot	*dqp;
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820

d7103eeb0   Darrick J. Wong   xfs: delegate dqg...
821
822
823
  	error = xfs_qm_dqget_checks(mp, type);
  	if (error)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

4882c19d2   Darrick J. Wong   xfs: split out dq...
825
826
827
828
829
830
  restart:
  	dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
  	if (dqp) {
  		*O_dqpp = dqp;
  		return 0;
  	}
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
831
  	error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp);
4882c19d2   Darrick J. Wong   xfs: split out dq...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  	if (error)
  		return error;
  
  	error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
  	if (error) {
  		/*
  		 * Duplicate found. Just throw away the new dquot and start
  		 * over.
  		 */
  		xfs_qm_dqdestroy(dqp);
  		XFS_STATS_INC(mp, xs_qm_dquot_dups);
  		goto restart;
  	}
  
  	trace_xfs_dqget_miss(dqp);
  	*O_dqpp = dqp;
  	return 0;
  }
114e73ccf   Darrick J. Wong   xfs: remove direc...
850
851
852
853
854
855
856
857
858
859
  /*
   * Given a dquot id and type, read and initialize a dquot from the on-disk
   * metadata.  This function is only for use during quota initialization so
   * it ignores the dquot cache assuming that the dquot shrinker isn't set up.
   * The caller is responsible for _qm_dqdestroy'ing the returned dquot.
   */
  int
  xfs_qm_dqget_uncached(
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
860
  	xfs_dqtype_t		type,
114e73ccf   Darrick J. Wong   xfs: remove direc...
861
862
863
864
865
866
867
868
869
870
  	struct xfs_dquot	**dqpp)
  {
  	int			error;
  
  	error = xfs_qm_dqget_checks(mp, type);
  	if (error)
  		return error;
  
  	return xfs_qm_dqread(mp, id, type, 0, dqpp);
  }
4882c19d2   Darrick J. Wong   xfs: split out dq...
871
872
873
874
  /* Return the quota id for a given inode and type. */
  xfs_dqid_t
  xfs_qm_id_for_quotatype(
  	struct xfs_inode	*ip,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
875
  	xfs_dqtype_t		type)
4882c19d2   Darrick J. Wong   xfs: split out dq...
876
877
  {
  	switch (type) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
878
  	case XFS_DQTYPE_USER:
ba8adad5d   Christoph Hellwig   xfs: remove the k...
879
  		return i_uid_read(VFS_I(ip));
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
880
  	case XFS_DQTYPE_GROUP:
ba8adad5d   Christoph Hellwig   xfs: remove the k...
881
  		return i_gid_read(VFS_I(ip));
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
882
  	case XFS_DQTYPE_PROJ:
de7a866fd   Christoph Hellwig   xfs: merge the pr...
883
  		return ip->i_d.di_projid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
  	}
4882c19d2   Darrick J. Wong   xfs: split out dq...
885
886
887
888
889
890
891
892
893
894
895
896
  	ASSERT(0);
  	return 0;
  }
  
  /*
   * Return the dquot for a given inode and type.  If @can_alloc is true, then
   * allocate blocks if needed.  The inode's ILOCK must be held and it must not
   * have already had an inode attached.
   */
  int
  xfs_qm_dqget_inode(
  	struct xfs_inode	*ip,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
897
  	xfs_dqtype_t		type,
4882c19d2   Darrick J. Wong   xfs: split out dq...
898
899
900
901
902
903
904
905
  	bool			can_alloc,
  	struct xfs_dquot	**O_dqpp)
  {
  	struct xfs_mount	*mp = ip->i_mount;
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
  	struct radix_tree_root	*tree = xfs_dquot_tree(qi, type);
  	struct xfs_dquot	*dqp;
  	xfs_dqid_t		id;
4882c19d2   Darrick J. Wong   xfs: split out dq...
906
907
908
909
910
  	int			error;
  
  	error = xfs_qm_dqget_checks(mp, type);
  	if (error)
  		return error;
4882c19d2   Darrick J. Wong   xfs: split out dq...
911
912
913
914
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
  	ASSERT(xfs_inode_dquot(ip, type) == NULL);
  
  	id = xfs_qm_id_for_quotatype(ip, type);
92678554a   Christoph Hellwig   xfs: flatten the ...
915
916
  
  restart:
cc2047c4d   Darrick J. Wong   xfs: refactor dqu...
917
  	dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
9f920f116   Christoph Hellwig   xfs: use per-file...
918
  	if (dqp) {
9f920f116   Christoph Hellwig   xfs: use per-file...
919
920
  		*O_dqpp = dqp;
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
924
925
926
927
928
929
  
  	/*
  	 * Dquot cache miss. We don't want to keep the inode lock across
  	 * a (potential) disk read. Also we don't want to deal with the lock
  	 * ordering between quotainode and this inode. OTOH, dropping the inode
  	 * lock here means dealing with a chown that can happen before
  	 * we re-acquire the lock.
  	 */
4882c19d2   Darrick J. Wong   xfs: split out dq...
930
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
931
  	error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp);
4882c19d2   Darrick J. Wong   xfs: split out dq...
932
  	xfs_ilock(ip, XFS_ILOCK_EXCL);
7ae444072   Christoph Hellwig   xfs: remove XFS_Q...
933
934
  	if (error)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935

4882c19d2   Darrick J. Wong   xfs: split out dq...
936
937
938
939
940
941
942
943
944
  	/*
  	 * A dquot could be attached to this inode by now, since we had
  	 * dropped the ilock.
  	 */
  	if (xfs_this_quota_on(mp, type)) {
  		struct xfs_dquot	*dqp1;
  
  		dqp1 = xfs_inode_dquot(ip, type);
  		if (dqp1) {
367314108   Chandra Seetharaman   Define a new func...
945
  			xfs_qm_dqdestroy(dqp);
4882c19d2   Darrick J. Wong   xfs: split out dq...
946
947
948
  			dqp = dqp1;
  			xfs_dqlock(dqp);
  			goto dqret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
  		}
4882c19d2   Darrick J. Wong   xfs: split out dq...
950
951
952
953
  	} else {
  		/* inode stays locked on return */
  		xfs_qm_dqdestroy(dqp);
  		return -ESRCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
  	}
cc2047c4d   Darrick J. Wong   xfs: refactor dqu...
955
956
  	error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
  	if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  		/*
9f920f116   Christoph Hellwig   xfs: use per-file...
958
959
  		 * Duplicate found. Just throw away the new dquot and start
  		 * over.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  		 */
9f920f116   Christoph Hellwig   xfs: use per-file...
961
  		xfs_qm_dqdestroy(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
962
  		XFS_STATS_INC(mp, xs_qm_dquot_dups);
9f920f116   Christoph Hellwig   xfs: use per-file...
963
  		goto restart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  	}
4882c19d2   Darrick J. Wong   xfs: split out dq...
965
966
  dqret:
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
0b1b213fc   Christoph Hellwig   xfs: event tracin...
967
  	trace_xfs_dqget_miss(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
  	*O_dqpp = dqp;
d99831ff3   Eric Sandeen   xfs: return is no...
969
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  }
f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
971
  /*
2e330e76e   Darrick J. Wong   xfs: refactor XFS...
972
973
974
975
976
977
978
   * Starting at @id and progressing upwards, look for an initialized incore
   * dquot, lock it, and return it.
   */
  int
  xfs_qm_dqget_next(
  	struct xfs_mount	*mp,
  	xfs_dqid_t		id,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
979
  	xfs_dqtype_t		type,
2e330e76e   Darrick J. Wong   xfs: refactor XFS...
980
981
982
983
984
985
986
  	struct xfs_dquot	**dqpp)
  {
  	struct xfs_dquot	*dqp;
  	int			error = 0;
  
  	*dqpp = NULL;
  	for (; !error; error = xfs_dq_get_next_id(mp, type, &id)) {
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
987
  		error = xfs_qm_dqget(mp, id, type, false, &dqp);
2e330e76e   Darrick J. Wong   xfs: refactor XFS...
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
  		if (error == -ENOENT)
  			continue;
  		else if (error != 0)
  			break;
  
  		if (!XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
  			*dqpp = dqp;
  			return 0;
  		}
  
  		xfs_qm_dqput(dqp);
  	}
  
  	return error;
  }
  
  /*
f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
   * Release a reference to the dquot (decrement ref-count) and unlock it.
   *
   * If there is a group quota attached to this dquot, carefully release that
   * too without tripping over deadlocks'n'stuff.
   */
  void
  xfs_qm_dqput(
  	struct xfs_dquot	*dqp)
  {
  	ASSERT(dqp->q_nrefs > 0);
  	ASSERT(XFS_DQ_IS_LOCKED(dqp));
  
  	trace_xfs_dqput(dqp);
3c3533757   Dave Chinner   xfs: remove dquot...
1018
1019
1020
1021
1022
  	if (--dqp->q_nrefs == 0) {
  		struct xfs_quotainfo	*qi = dqp->q_mount->m_quotainfo;
  		trace_xfs_dqput_free(dqp);
  
  		if (list_lru_add(&qi->qi_lru, &dqp->q_lru))
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
1023
  			XFS_STATS_INC(dqp->q_mount, xs_qm_dquot_unused);
3c3533757   Dave Chinner   xfs: remove dquot...
1024
1025
  	}
  	xfs_dqunlock(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
1028
1029
1030
1031
1032
1033
  }
  
  /*
   * Release a dquot. Flush it if dirty, then dqput() it.
   * dquot must not be locked.
   */
  void
  xfs_qm_dqrele(
aefe69a45   Pavel Reichl   xfs: remove the x...
1034
  	struct xfs_dquot	*dqp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  {
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1036
1037
  	if (!dqp)
  		return;
0b1b213fc   Christoph Hellwig   xfs: event tracin...
1038
  	trace_xfs_dqrele(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  
  	xfs_dqlock(dqp);
  	/*
  	 * We don't care to flush it if the dquot is dirty here.
  	 * That will create stutters that we want to avoid.
  	 * Instead we do a delayed write when we try to reclaim
  	 * a dirty dquot. Also xfs_sync will take part of the burden...
  	 */
  	xfs_qm_dqput(dqp);
  }
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1049
1050
1051
1052
1053
1054
1055
  /*
   * This is the dquot flushing I/O completion routine.  It is called
   * from interrupt level when the buffer containing the dquot is
   * flushed to disk.  It is responsible for removing the dquot logitem
   * from the AIL if it has not been re-logged, and unlocking the dquot's
   * flush lock. This behavior is very similar to that of inodes..
   */
6f5de1808   Dave Chinner   xfs: use direct c...
1056
  static void
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1057
  xfs_qm_dqflush_done(
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1058
1059
  	struct xfs_log_item	*lip)
  {
fd8b81dbb   Pavel Reichl   xfs: remove the x...
1060
  	struct xfs_dq_logitem	*qip = (struct xfs_dq_logitem *)lip;
aefe69a45   Pavel Reichl   xfs: remove the x...
1061
  	struct xfs_dquot	*dqp = qip->qli_dquot;
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1062
  	struct xfs_ail		*ailp = lip->li_ailp;
849274c10   Brian Foster   xfs: acquire ->ai...
1063
  	xfs_lsn_t		tail_lsn;
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1064
1065
1066
1067
1068
1069
1070
1071
1072
  
  	/*
  	 * We only want to pull the item from the AIL if its
  	 * location in the log has not changed since we started the flush.
  	 * Thus, we only bother if the dquot's lsn has
  	 * not changed. First we check the lsn outside the lock
  	 * since it's cheaper, and then we recheck while
  	 * holding the lock before removing the dquot from the AIL.
  	 */
22525c17e   Dave Chinner   xfs: log item fla...
1073
  	if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) &&
373b0589d   Carlos Maiolino   xfs: Properly ret...
1074
  	    ((lip->li_lsn == qip->qli_flush_lsn) ||
22525c17e   Dave Chinner   xfs: log item fla...
1075
  	     test_bit(XFS_LI_FAILED, &lip->li_flags))) {
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1076

57e809561   Matthew Wilcox   xfs: Rename xa_ e...
1077
  		spin_lock(&ailp->ail_lock);
e98084b8b   Dave Chinner   xfs: move xfs_cle...
1078
  		xfs_clear_li_failed(lip);
373b0589d   Carlos Maiolino   xfs: Properly ret...
1079
  		if (lip->li_lsn == qip->qli_flush_lsn) {
849274c10   Brian Foster   xfs: acquire ->ai...
1080
1081
1082
  			/* xfs_ail_update_finish() drops the AIL lock */
  			tail_lsn = xfs_ail_delete_one(ailp, lip);
  			xfs_ail_update_finish(ailp, tail_lsn);
373b0589d   Carlos Maiolino   xfs: Properly ret...
1083
  		} else {
57e809561   Matthew Wilcox   xfs: Rename xa_ e...
1084
  			spin_unlock(&ailp->ail_lock);
373b0589d   Carlos Maiolino   xfs: Properly ret...
1085
  		}
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1086
1087
1088
1089
1090
1091
1092
  	}
  
  	/*
  	 * Release the dq's flush lock since we're done with it.
  	 */
  	xfs_dqfunlock(dqp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093

6f5de1808   Dave Chinner   xfs: use direct c...
1094
  void
664ffb8a4   Christoph Hellwig   xfs: move the buf...
1095
  xfs_buf_dquot_iodone(
6f5de1808   Dave Chinner   xfs: use direct c...
1096
1097
1098
1099
1100
1101
1102
1103
1104
  	struct xfs_buf		*bp)
  {
  	struct xfs_log_item	*lip, *n;
  
  	list_for_each_entry_safe(lip, n, &bp->b_li_list, li_bio_list) {
  		list_del_init(&lip->li_bio_list);
  		xfs_qm_dqflush_done(lip);
  	}
  }
664ffb8a4   Christoph Hellwig   xfs: move the buf...
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  void
  xfs_buf_dquot_io_fail(
  	struct xfs_buf		*bp)
  {
  	struct xfs_log_item	*lip;
  
  	spin_lock(&bp->b_mount->m_ail->ail_lock);
  	list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
  		xfs_set_li_failed(lip, bp);
  	spin_unlock(&bp->b_mount->m_ail->ail_lock);
  }
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1116
1117
1118
1119
1120
  /* Check incore dquot for errors before we flush. */
  static xfs_failaddr_t
  xfs_qm_dqflush_check(
  	struct xfs_dquot	*dqp)
  {
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
1121
  	xfs_dqtype_t		type = xfs_dquot_type(dqp);
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1122

8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1123
1124
1125
  	if (type != XFS_DQTYPE_USER &&
  	    type != XFS_DQTYPE_GROUP &&
  	    type != XFS_DQTYPE_PROJ)
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1126
  		return __this_address;
d3537cf93   Darrick J. Wong   xfs: stop using q...
1127
1128
  	if (dqp->q_id == 0)
  		return NULL;
be37d40c1   Darrick J. Wong   xfs: stop using q...
1129
  	if (dqp->q_blk.softlimit && dqp->q_blk.count > dqp->q_blk.softlimit &&
19dce7eae   Darrick J. Wong   xfs: stop using q...
1130
  	    !dqp->q_blk.timer)
d3537cf93   Darrick J. Wong   xfs: stop using q...
1131
  		return __this_address;
be37d40c1   Darrick J. Wong   xfs: stop using q...
1132
  	if (dqp->q_ino.softlimit && dqp->q_ino.count > dqp->q_ino.softlimit &&
19dce7eae   Darrick J. Wong   xfs: stop using q...
1133
  	    !dqp->q_ino.timer)
d3537cf93   Darrick J. Wong   xfs: stop using q...
1134
  		return __this_address;
be37d40c1   Darrick J. Wong   xfs: stop using q...
1135
  	if (dqp->q_rtb.softlimit && dqp->q_rtb.count > dqp->q_rtb.softlimit &&
19dce7eae   Darrick J. Wong   xfs: stop using q...
1136
  	    !dqp->q_rtb.timer)
d3537cf93   Darrick J. Wong   xfs: stop using q...
1137
  		return __this_address;
4ea1ff3b4   Darrick J. Wong   xfs: widen ondisk...
1138
1139
1140
1141
1142
1143
1144
  	/* bigtime flag should never be set on root dquots */
  	if (dqp->q_type & XFS_DQTYPE_BIGTIME) {
  		if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb))
  			return __this_address;
  		if (dqp->q_id == 0)
  			return __this_address;
  	}
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1145
1146
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  /*
   * Write a modified dquot to disk.
   * The dquot must be locked and the flush lock too taken by caller.
   * The flush lock will not be unlocked until the dquot reaches the disk,
   * but the dquot is free to be unlocked and modified by the caller
   * in the interim. Dquot is still locked on return. This behavior is
   * identical to that of inodes.
   */
  int
  xfs_qm_dqflush(
fe7257fd4   Christoph Hellwig   xfs: do not write...
1157
1158
  	struct xfs_dquot	*dqp,
  	struct xfs_buf		**bpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  {
acecf1b5d   Christoph Hellwig   xfs: stop using x...
1160
  	struct xfs_mount	*mp = dqp->q_mount;
b707fffda   Brian Foster   xfs: abort consis...
1161
  	struct xfs_log_item	*lip = &dqp->q_logitem.qli_item;
acecf1b5d   Christoph Hellwig   xfs: stop using x...
1162
  	struct xfs_buf		*bp;
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
1163
  	struct xfs_dqblk	*dqblk;
eebf3cab9   Darrick J. Wong   xfs: standardize ...
1164
  	xfs_failaddr_t		fa;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  
  	ASSERT(XFS_DQ_IS_LOCKED(dqp));
e1f49cf20   David Chinner   [XFS] replace dqu...
1168
  	ASSERT(!completion_done(&dqp->q_flush));
acecf1b5d   Christoph Hellwig   xfs: stop using x...
1169

0b1b213fc   Christoph Hellwig   xfs: event tracin...
1170
  	trace_xfs_dqflush(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171

fe7257fd4   Christoph Hellwig   xfs: do not write...
1172
  	*bpp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
1174
1175
  	xfs_qm_dqunpin_wait(dqp);
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  	 * Get the buffer containing the on-disk dquot
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  	 */
acecf1b5d   Christoph Hellwig   xfs: stop using x...
1178
  	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
8d3d7e2b3   Brian Foster   xfs: trylock unde...
1179
1180
  				   mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
  				   &bp, &xfs_dquot_buf_ops);
b707fffda   Brian Foster   xfs: abort consis...
1181
  	if (error == -EAGAIN)
fe7257fd4   Christoph Hellwig   xfs: do not write...
1182
  		goto out_unlock;
b707fffda   Brian Foster   xfs: abort consis...
1183
1184
  	if (error)
  		goto out_abort;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185

0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1186
1187
1188
  	fa = xfs_qm_dqflush_check(dqp);
  	if (fa) {
  		xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
c51df7334   Darrick J. Wong   xfs: stop using q...
1189
  				dqp->q_id, fa);
0b0fa1d1d   Darrick J. Wong   xfs: stop using q...
1190
1191
1192
1193
  		xfs_buf_relse(bp);
  		error = -EFSCORRUPTED;
  		goto out_abort;
  	}
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
1194
1195
1196
  	/* Flush the incore dquot to the ondisk buffer. */
  	dqblk = bp->b_addr + dqp->q_bufoffset;
  	xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
1198
1199
1200
  
  	/*
  	 * Clear the dirty field and remember the flush lsn for later use.
  	 */
985a78fdd   Darrick J. Wong   xfs: rename dquot...
1201
  	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202

7b2e2a31f   David Chinner   [XFS] Allow 64 bi...
1203
1204
  	xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
  					&dqp->q_logitem.qli_item.li_lsn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
  
  	/*
3fe58f30b   Christoph Hellwig   xfs: add CRC chec...
1207
1208
1209
  	 * copy the lsn into the on-disk dquot now while we have the in memory
  	 * dquot here. This can't be done later in the write verifier as we
  	 * can't get access to the log item at that point in time.
6fcdc59de   Dave Chinner   xfs: rework dquot...
1210
1211
1212
1213
  	 *
  	 * We also calculate the CRC here so that the on-disk dquot in the
  	 * buffer always has a valid CRC. This ensures there is no possibility
  	 * of a dquot without an up-to-date CRC getting to disk.
3fe58f30b   Christoph Hellwig   xfs: add CRC chec...
1214
1215
  	 */
  	if (xfs_sb_version_hascrc(&mp->m_sb)) {
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
1216
1217
  		dqblk->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
  		xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
6fcdc59de   Dave Chinner   xfs: rework dquot...
1218
  				 XFS_DQUOT_CRC_OFF);
3fe58f30b   Christoph Hellwig   xfs: add CRC chec...
1219
1220
1221
  	}
  
  	/*
2ef3f7f5d   Dave Chinner   xfs: get rid of l...
1222
1223
  	 * Attach the dquot to the buffer so that we can remove this dquot from
  	 * the AIL and release the flush lock once the dquot is synced to disk.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  	 */
0c7e5afbe   Dave Chinner   xfs: mark dquot b...
1225
  	bp->b_flags |= _XBF_DQUOTS;
2ef3f7f5d   Dave Chinner   xfs: get rid of l...
1226
  	list_add_tail(&dqp->q_logitem.qli_item.li_bio_list, &bp->b_li_list);
ca30b2a7b   Christoph Hellwig   xfs: give li_cb c...
1227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
1230
1231
  	/*
  	 * If the buffer is pinned then push on the log so we won't
  	 * get stuck waiting in the write for too long.
  	 */
811e64c71   Chandra Seetharaman   Replace the macro...
1232
  	if (xfs_buf_ispinned(bp)) {
0b1b213fc   Christoph Hellwig   xfs: event tracin...
1233
  		trace_xfs_dqflush_force(dqp);
a14a348bf   Christoph Hellwig   xfs: cleanup up x...
1234
  		xfs_log_force(mp, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  	}
0b1b213fc   Christoph Hellwig   xfs: event tracin...
1236
  	trace_xfs_dqflush_done(dqp);
fe7257fd4   Christoph Hellwig   xfs: do not write...
1237
1238
  	*bpp = bp;
  	return 0;
0b1b213fc   Christoph Hellwig   xfs: event tracin...
1239

b707fffda   Brian Foster   xfs: abort consis...
1240
  out_abort:
985a78fdd   Darrick J. Wong   xfs: rename dquot...
1241
  	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
2b3cf0935   Brian Foster   xfs: combine xfs_...
1242
  	xfs_trans_ail_delete(lip, 0);
b707fffda   Brian Foster   xfs: abort consis...
1243
  	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
fe7257fd4   Christoph Hellwig   xfs: do not write...
1244
1245
  out_unlock:
  	xfs_dqfunlock(dqp);
8d3d7e2b3   Brian Foster   xfs: trylock unde...
1246
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
  }
5bb87a33b   Christoph Hellwig   xfs: lockdep anno...
1248
1249
1250
1251
1252
1253
  /*
   * Lock two xfs_dquot structures.
   *
   * To avoid deadlocks we always lock the quota structure with
   * the lowerd id first.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
  void
  xfs_dqlock2(
aefe69a45   Pavel Reichl   xfs: remove the x...
1256
1257
  	struct xfs_dquot	*d1,
  	struct xfs_dquot	*d2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
1260
  {
  	if (d1 && d2) {
  		ASSERT(d1 != d2);
c51df7334   Darrick J. Wong   xfs: stop using q...
1261
  		if (d1->q_id > d2->q_id) {
5bb87a33b   Christoph Hellwig   xfs: lockdep anno...
1262
1263
  			mutex_lock(&d2->q_qlock);
  			mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
  		} else {
5bb87a33b   Christoph Hellwig   xfs: lockdep anno...
1265
1266
  			mutex_lock(&d1->q_qlock);
  			mutex_lock_nested(&d2->q_qlock, XFS_QLOCK_NESTED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
  		}
5bb87a33b   Christoph Hellwig   xfs: lockdep anno...
1268
1269
1270
1271
  	} else if (d1) {
  		mutex_lock(&d1->q_qlock);
  	} else if (d2) {
  		mutex_lock(&d2->q_qlock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
  	}
  }
a05931ceb   Christoph Hellwig   xfs: remove the g...
1274
1275
1276
  int __init
  xfs_qm_init(void)
  {
b1231760e   Carlos Maiolino   xfs: Remove slab ...
1277
1278
1279
  	xfs_qm_dqzone = kmem_cache_create("xfs_dquot",
  					  sizeof(struct xfs_dquot),
  					  0, 0, NULL);
a05931ceb   Christoph Hellwig   xfs: remove the g...
1280
1281
  	if (!xfs_qm_dqzone)
  		goto out;
b1231760e   Carlos Maiolino   xfs: Remove slab ...
1282
1283
1284
  	xfs_qm_dqtrxzone = kmem_cache_create("xfs_dqtrx",
  					     sizeof(struct xfs_dquot_acct),
  					     0, 0, NULL);
a05931ceb   Christoph Hellwig   xfs: remove the g...
1285
1286
1287
1288
1289
1290
  	if (!xfs_qm_dqtrxzone)
  		goto out_free_dqzone;
  
  	return 0;
  
  out_free_dqzone:
aaf54eb8b   Carlos Maiolino   xfs: Remove kmem_...
1291
  	kmem_cache_destroy(xfs_qm_dqzone);
a05931ceb   Christoph Hellwig   xfs: remove the g...
1292
1293
1294
  out:
  	return -ENOMEM;
  }
1c2ccc66b   Gerard Snitselaar   fs: xfs: fix sect...
1295
  void
a05931ceb   Christoph Hellwig   xfs: remove the g...
1296
1297
  xfs_qm_exit(void)
  {
aaf54eb8b   Carlos Maiolino   xfs: Remove kmem_...
1298
1299
  	kmem_cache_destroy(xfs_qm_dqtrxzone);
  	kmem_cache_destroy(xfs_qm_dqzone);
a05931ceb   Christoph Hellwig   xfs: remove the g...
1300
  }
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1301
1302
1303
1304
  
  /*
   * Iterate every dquot of a particular type.  The caller must ensure that the
   * particular quota type is active.  iter_fn can return negative error codes,
e7ee96dfb   Darrick J. Wong   xfs: remove all *...
1305
   * or -ECANCELED to indicate that it wants to stop iterating.
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1306
1307
1308
1309
   */
  int
  xfs_qm_dqiterate(
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
1310
  	xfs_dqtype_t		type,
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1311
1312
1313
1314
1315
1316
1317
1318
  	xfs_qm_dqiterate_fn	iter_fn,
  	void			*priv)
  {
  	struct xfs_dquot	*dq;
  	xfs_dqid_t		id = 0;
  	int			error;
  
  	do {
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
1319
  		error = xfs_qm_dqget_next(mp, id, type, &dq);
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1320
1321
1322
1323
  		if (error == -ENOENT)
  			return 0;
  		if (error)
  			return error;
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
1324
  		error = iter_fn(dq, type, priv);
c51df7334   Darrick J. Wong   xfs: stop using q...
1325
  		id = dq->q_id;
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1326
  		xfs_qm_dqput(dq);
554ba9654   Darrick J. Wong   xfs: refactor dqu...
1327
1328
1329
1330
  	} while (error == 0 && id != 0);
  
  	return error;
  }