Blame view

fs/xfs/xfs_qm.c 46.4 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-2005 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"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
8
  #include "xfs_shared.h"
6ca1c9063   Dave Chinner   xfs: separate dqu...
9
  #include "xfs_format.h"
239880ef6   Dave Chinner   xfs: decouple log...
10
  #include "xfs_log_format.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_sb.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include "xfs_mount.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include "xfs_inode.h"
ebd126a65   Darrick J. Wong   xfs: convert quot...
16
  #include "xfs_iwalk.h"
239880ef6   Dave Chinner   xfs: decouple log...
17
  #include "xfs_quota.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
18
  #include "xfs_bmap.h"
8bfadd8d0   Christoph Hellwig   xfs: replace xfs_...
19
  #include "xfs_bmap_util.h"
239880ef6   Dave Chinner   xfs: decouple log...
20
  #include "xfs_trans.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  #include "xfs_trans_space.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"
33479e054   Dave Chinner   xfs: remove xfs_i...
24
  #include "xfs_icache.h"
a5155b870   Darrick J. Wong   xfs: always log c...
25
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
  
  /*
   * The global quota manager. There is only one of these for the entire
   * system, _not_ one per file system. XQM keeps track of the overall
   * quota functionality, including maintaining the freelist and hash
   * tables of dquots.
   */
c072fbefe   Pavel Reichl   xfs: remove the x...
33
34
  STATIC int	xfs_qm_init_quotainos(struct xfs_mount *mp);
  STATIC int	xfs_qm_init_quotainfo(struct xfs_mount *mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

c072fbefe   Pavel Reichl   xfs: remove the x...
36
  STATIC void	xfs_qm_destroy_quotainos(struct xfs_quotainfo *qi);
cd56a39a5   Dave Chinner   xfs: convert dquo...
37
  STATIC void	xfs_qm_dqfree_one(struct xfs_dquot *dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  /*
b84a3a967   Christoph Hellwig   xfs: remove the p...
39
40
41
42
43
44
45
46
47
48
49
   * We use the batch lookup interface to iterate over the dquots as it
   * currently is the only interface into the radix tree code that allows
   * fuzzy lookups instead of exact matches.  Holding the lock over multiple
   * operations is fine as all callers are used either during mount/umount
   * or quotaoff.
   */
  #define XFS_DQ_LOOKUP_BATCH	32
  
  STATIC int
  xfs_qm_dquot_walk(
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
50
  	xfs_dqtype_t		type,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
51
52
  	int			(*execute)(struct xfs_dquot *dqp, void *data),
  	void			*data)
b84a3a967   Christoph Hellwig   xfs: remove the p...
53
54
  {
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
329e08752   Chandra Seetharaman   xfs: Replace macr...
55
  	struct radix_tree_root	*tree = xfs_dquot_tree(qi, type);
b84a3a967   Christoph Hellwig   xfs: remove the p...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  	uint32_t		next_index;
  	int			last_error = 0;
  	int			skipped;
  	int			nr_found;
  
  restart:
  	skipped = 0;
  	next_index = 0;
  	nr_found = 0;
  
  	while (1) {
  		struct xfs_dquot *batch[XFS_DQ_LOOKUP_BATCH];
  		int		error = 0;
  		int		i;
  
  		mutex_lock(&qi->qi_tree_lock);
  		nr_found = radix_tree_gang_lookup(tree, (void **)batch,
  					next_index, XFS_DQ_LOOKUP_BATCH);
  		if (!nr_found) {
  			mutex_unlock(&qi->qi_tree_lock);
  			break;
  		}
  
  		for (i = 0; i < nr_found; i++) {
  			struct xfs_dquot *dqp = batch[i];
c51df7334   Darrick J. Wong   xfs: stop using q...
81
  			next_index = dqp->q_id + 1;
b84a3a967   Christoph Hellwig   xfs: remove the p...
82

43ff2122e   Christoph Hellwig   xfs: on-stack del...
83
  			error = execute(batch[i], data);
2451337dd   Dave Chinner   xfs: global error...
84
  			if (error == -EAGAIN) {
b84a3a967   Christoph Hellwig   xfs: remove the p...
85
86
87
  				skipped++;
  				continue;
  			}
2451337dd   Dave Chinner   xfs: global error...
88
  			if (error && last_error != -EFSCORRUPTED)
b84a3a967   Christoph Hellwig   xfs: remove the p...
89
90
91
92
93
94
  				last_error = error;
  		}
  
  		mutex_unlock(&qi->qi_tree_lock);
  
  		/* bail out if the filesystem is corrupted.  */
2451337dd   Dave Chinner   xfs: global error...
95
  		if (last_error == -EFSCORRUPTED) {
b84a3a967   Christoph Hellwig   xfs: remove the p...
96
97
98
  			skipped = 0;
  			break;
  		}
cfaf2d034   Brian Foster   xfs: fix quotache...
99
100
101
  		/* we're done if id overflows back to zero */
  		if (!next_index)
  			break;
b84a3a967   Christoph Hellwig   xfs: remove the p...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  	}
  
  	if (skipped) {
  		delay(1);
  		goto restart;
  	}
  
  	return last_error;
  }
  
  
  /*
   * Purge a dquot from all tracking data structures and free it.
   */
  STATIC int
  xfs_qm_dqpurge(
43ff2122e   Christoph Hellwig   xfs: on-stack del...
118
119
  	struct xfs_dquot	*dqp,
  	void			*data)
b84a3a967   Christoph Hellwig   xfs: remove the p...
120
121
122
  {
  	struct xfs_mount	*mp = dqp->q_mount;
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
8d3d7e2b3   Brian Foster   xfs: trylock unde...
123
  	int			error = -EAGAIN;
b84a3a967   Christoph Hellwig   xfs: remove the p...
124
125
  
  	xfs_dqlock(dqp);
985a78fdd   Darrick J. Wong   xfs: rename dquot...
126
  	if ((dqp->q_flags & XFS_DQFLAG_FREEING) || dqp->q_nrefs != 0)
8d3d7e2b3   Brian Foster   xfs: trylock unde...
127
  		goto out_unlock;
b84a3a967   Christoph Hellwig   xfs: remove the p...
128

985a78fdd   Darrick J. Wong   xfs: rename dquot...
129
  	dqp->q_flags |= XFS_DQFLAG_FREEING;
b84a3a967   Christoph Hellwig   xfs: remove the p...
130

43ff2122e   Christoph Hellwig   xfs: on-stack del...
131
  	xfs_dqflock(dqp);
b84a3a967   Christoph Hellwig   xfs: remove the p...
132
133
134
135
136
137
138
  
  	/*
  	 * If we are turning this type of quotas off, we don't care
  	 * about the dirty metadata sitting in this dquot. OTOH, if
  	 * we're unmounting, we do care, so we flush it and wait.
  	 */
  	if (XFS_DQ_IS_DIRTY(dqp)) {
fe7257fd4   Christoph Hellwig   xfs: do not write...
139
  		struct xfs_buf	*bp = NULL;
b84a3a967   Christoph Hellwig   xfs: remove the p...
140
141
142
143
144
  
  		/*
  		 * We don't care about getting disk errors here. We need
  		 * to purge this dquot anyway, so we go ahead regardless.
  		 */
fe7257fd4   Christoph Hellwig   xfs: do not write...
145
  		error = xfs_qm_dqflush(dqp, &bp);
609001bca   Darrick J. Wong   xfs: don't spray ...
146
  		if (!error) {
fe7257fd4   Christoph Hellwig   xfs: do not write...
147
148
  			error = xfs_bwrite(bp);
  			xfs_buf_relse(bp);
8d3d7e2b3   Brian Foster   xfs: trylock unde...
149
  		} else if (error == -EAGAIN) {
985a78fdd   Darrick J. Wong   xfs: rename dquot...
150
  			dqp->q_flags &= ~XFS_DQFLAG_FREEING;
8d3d7e2b3   Brian Foster   xfs: trylock unde...
151
  			goto out_unlock;
fe7257fd4   Christoph Hellwig   xfs: do not write...
152
  		}
b84a3a967   Christoph Hellwig   xfs: remove the p...
153
154
155
156
157
  		xfs_dqflock(dqp);
  	}
  
  	ASSERT(atomic_read(&dqp->q_pincount) == 0);
  	ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
22525c17e   Dave Chinner   xfs: log item fla...
158
  		!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
b84a3a967   Christoph Hellwig   xfs: remove the p...
159
160
161
  
  	xfs_dqfunlock(dqp);
  	xfs_dqunlock(dqp);
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
162
  	radix_tree_delete(xfs_dquot_tree(qi, xfs_dquot_type(dqp)), dqp->q_id);
b84a3a967   Christoph Hellwig   xfs: remove the p...
163
164
165
166
167
168
  	qi->qi_dquots--;
  
  	/*
  	 * We move dquots to the freelist as soon as their reference count
  	 * hits zero, so it really should be on the freelist here.
  	 */
b84a3a967   Christoph Hellwig   xfs: remove the p...
169
  	ASSERT(!list_empty(&dqp->q_lru));
cd56a39a5   Dave Chinner   xfs: convert dquo...
170
  	list_lru_del(&qi->qi_lru, &dqp->q_lru);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
171
  	XFS_STATS_DEC(mp, xs_qm_dquot_unused);
b84a3a967   Christoph Hellwig   xfs: remove the p...
172
173
  
  	xfs_qm_dqdestroy(dqp);
df8052e7d   Jie Liu   xfs: fix infinite...
174
  	return 0;
8d3d7e2b3   Brian Foster   xfs: trylock unde...
175
176
177
178
  
  out_unlock:
  	xfs_dqunlock(dqp);
  	return error;
df8052e7d   Jie Liu   xfs: fix infinite...
179
180
181
  }
  
  /*
b84a3a967   Christoph Hellwig   xfs: remove the p...
182
183
184
185
186
187
188
   * Purge the dquot cache.
   */
  void
  xfs_qm_dqpurge_all(
  	struct xfs_mount	*mp,
  	uint			flags)
  {
3c3533757   Dave Chinner   xfs: remove dquot...
189
  	if (flags & XFS_QMOPT_UQUOTA)
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
190
  		xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_dqpurge, NULL);
b84a3a967   Christoph Hellwig   xfs: remove the p...
191
  	if (flags & XFS_QMOPT_GQUOTA)
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
192
  		xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_dqpurge, NULL);
b84a3a967   Christoph Hellwig   xfs: remove the p...
193
  	if (flags & XFS_QMOPT_PQUOTA)
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
194
  		xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_dqpurge, NULL);
b84a3a967   Christoph Hellwig   xfs: remove the p...
195
196
197
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
   * Just destroy the quotainfo structure.
   */
  void
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
201
202
  xfs_qm_unmount(
  	struct xfs_mount	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  {
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
204
  	if (mp->m_quotainfo) {
8112e9dc6   Christoph Hellwig   xfs: removed unus...
205
  		xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  		xfs_qm_destroy_quotainfo(mp);
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
207
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
  /*
   * Called from the vfsops layer.
   */
e57481dc2   Christoph Hellwig   no explicit xfs_i...
212
  void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
  xfs_qm_unmount_quotas(
  	xfs_mount_t	*mp)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
222
223
224
225
226
227
  	/*
  	 * Release the dquots that root inode, et al might be holding,
  	 * before we flush quotas and blow away the quotainfo structure.
  	 */
  	ASSERT(mp->m_rootip);
  	xfs_qm_dqdetach(mp->m_rootip);
  	if (mp->m_rbmip)
  		xfs_qm_dqdetach(mp->m_rbmip);
  	if (mp->m_rsumip)
  		xfs_qm_dqdetach(mp->m_rsumip);
  
  	/*
e57481dc2   Christoph Hellwig   no explicit xfs_i...
228
  	 * Release the quota inodes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  	if (mp->m_quotainfo) {
e57481dc2   Christoph Hellwig   no explicit xfs_i...
231
  		if (mp->m_quotainfo->qi_uquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
232
  			xfs_irele(mp->m_quotainfo->qi_uquotaip);
e57481dc2   Christoph Hellwig   no explicit xfs_i...
233
  			mp->m_quotainfo->qi_uquotaip = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  		}
e57481dc2   Christoph Hellwig   no explicit xfs_i...
235
  		if (mp->m_quotainfo->qi_gquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
236
  			xfs_irele(mp->m_quotainfo->qi_gquotaip);
e57481dc2   Christoph Hellwig   no explicit xfs_i...
237
  			mp->m_quotainfo->qi_gquotaip = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  		}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
239
  		if (mp->m_quotainfo->qi_pquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
240
  			xfs_irele(mp->m_quotainfo->qi_pquotaip);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
241
242
  			mp->m_quotainfo->qi_pquotaip = NULL;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
  STATIC int
  xfs_qm_dqattach_one(
aefe69a45   Pavel Reichl   xfs: remove the x...
247
  	struct xfs_inode	*ip,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
248
  	xfs_dqtype_t		type,
aefe69a45   Pavel Reichl   xfs: remove the x...
249
250
  	bool			doalloc,
  	struct xfs_dquot	**IO_idqpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  {
aefe69a45   Pavel Reichl   xfs: remove the x...
252
253
  	struct xfs_dquot	*dqp;
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

579aa9caf   Christoph Hellwig   [XFS] shrink mrlo...
255
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  	error = 0;
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
257

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	/*
3c3533757   Dave Chinner   xfs: remove dquot...
259
260
261
  	 * See if we already have it in the inode itself. IO_idqpp is &i_udquot
  	 * or &i_gdquot. This made the code look weird, but made the logic a lot
  	 * simpler.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  	 */
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
263
264
  	dqp = *IO_idqpp;
  	if (dqp) {
0b1b213fc   Christoph Hellwig   xfs: event tracin...
265
  		trace_xfs_dqattach_found(dqp);
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
266
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
  	}
  
  	/*
3c3533757   Dave Chinner   xfs: remove dquot...
270
271
272
273
  	 * Find the dquot from somewhere. This bumps the reference count of
  	 * dquot and returns it locked.  This can return ENOENT if dquot didn't
  	 * exist on disk and we didn't ask it to allocate; ESRCH if quotas got
  	 * turned off suddenly.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  	 */
4882c19d2   Darrick J. Wong   xfs: split out dq...
275
  	error = xfs_qm_dqget_inode(ip, type, doalloc, &dqp);
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
276
277
  	if (error)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

0b1b213fc   Christoph Hellwig   xfs: event tracin...
279
  	trace_xfs_dqattach_get(dqp);
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
280

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
285
  	/*
  	 * dqget may have dropped and re-acquired the ilock, but it guarantees
  	 * that the dquot returned is the one that should go in the inode.
  	 */
  	*IO_idqpp = dqp;
8e9b6e7fa   Christoph Hellwig   xfs: remove the u...
286
287
  	xfs_dqunlock(dqp);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  }
b4d05e301   Christoph Hellwig   xfs: avoid taking...
289
290
291
292
293
294
295
296
297
298
299
300
  static bool
  xfs_qm_need_dqattach(
  	struct xfs_inode	*ip)
  {
  	struct xfs_mount	*mp = ip->i_mount;
  
  	if (!XFS_IS_QUOTA_RUNNING(mp))
  		return false;
  	if (!XFS_IS_QUOTA_ON(mp))
  		return false;
  	if (!XFS_NOT_DQATTACHED(mp, ip))
  		return false;
9cad19d2c   Chandra Seetharaman   xfs: Define a new...
301
  	if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
b4d05e301   Christoph Hellwig   xfs: avoid taking...
302
303
304
  		return false;
  	return true;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  
  /*
c8ad20ffe   Nathan Scott   [XFS] Add support...
307
308
   * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
   * into account.
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
309
   * If @doalloc is true, the dquot(s) will be allocated if needed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
   * Inode may get unlocked and relocked in here, and the caller must deal with
   * the consequences.
   */
  int
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
314
  xfs_qm_dqattach_locked(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	xfs_inode_t	*ip,
4882c19d2   Darrick J. Wong   xfs: split out dq...
316
  	bool		doalloc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  {
  	xfs_mount_t	*mp = ip->i_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  	int		error = 0;
b4d05e301   Christoph Hellwig   xfs: avoid taking...
320
  	if (!xfs_qm_need_dqattach(ip))
014c2544e   Jesper Juhl   return statement ...
321
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
323
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324

3c3533757   Dave Chinner   xfs: remove dquot...
325
  	if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) {
74af4c177   Kaixu Xia   xfs: remove the u...
326
327
  		error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_USER,
  				doalloc, &ip->i_udquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  		if (error)
  			goto done;
3c3533757   Dave Chinner   xfs: remove dquot...
330
  		ASSERT(ip->i_udquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  	}
579aa9caf   Christoph Hellwig   [XFS] shrink mrlo...
332

3c3533757   Dave Chinner   xfs: remove dquot...
333
  	if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) {
74af4c177   Kaixu Xia   xfs: remove the u...
334
335
  		error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_GROUP,
  				doalloc, &ip->i_gdquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
  		if (error)
  			goto done;
3c3533757   Dave Chinner   xfs: remove dquot...
338
  		ASSERT(ip->i_gdquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  	}
3c3533757   Dave Chinner   xfs: remove dquot...
340
  	if (XFS_IS_PQUOTA_ON(mp) && !ip->i_pdquot) {
74af4c177   Kaixu Xia   xfs: remove the u...
341
  		error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_PROJ,
4882c19d2   Darrick J. Wong   xfs: split out dq...
342
  				doalloc, &ip->i_pdquot);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
343
344
  		if (error)
  			goto done;
3c3533757   Dave Chinner   xfs: remove dquot...
345
  		ASSERT(ip->i_pdquot);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
346
  	}
3c3533757   Dave Chinner   xfs: remove dquot...
347
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	/*
3c3533757   Dave Chinner   xfs: remove dquot...
349
350
  	 * Don't worry about the dquots that we may have attached before any
  	 * error - they'll get detached later if it has not already been done.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  	 */
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
352
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
353
354
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
356
357
  int
  xfs_qm_dqattach(
c14cfccab   Darrick J. Wong   xfs: remove unnec...
358
  	struct xfs_inode	*ip)
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
359
360
  {
  	int			error;
b4d05e301   Christoph Hellwig   xfs: avoid taking...
361
362
  	if (!xfs_qm_need_dqattach(ip))
  		return 0;
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
363
  	xfs_ilock(ip, XFS_ILOCK_EXCL);
4882c19d2   Darrick J. Wong   xfs: split out dq...
364
  	error = xfs_qm_dqattach_locked(ip, false);
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
365
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

014c2544e   Jesper Juhl   return statement ...
367
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
375
376
377
378
  }
  
  /*
   * Release dquots (and their references) if any.
   * The inode should be locked EXCL except when this's called by
   * xfs_ireclaim.
   */
  void
  xfs_qm_dqdetach(
  	xfs_inode_t	*ip)
  {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
379
  	if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
  		return;
0b1b213fc   Christoph Hellwig   xfs: event tracin...
381
  	trace_xfs_dquot_dqdetach(ip);
9cad19d2c   Chandra Seetharaman   xfs: Define a new...
382
  	ASSERT(!xfs_is_quota_inode(&ip->i_mount->m_sb, ip->i_ino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
389
390
  	if (ip->i_udquot) {
  		xfs_qm_dqrele(ip->i_udquot);
  		ip->i_udquot = NULL;
  	}
  	if (ip->i_gdquot) {
  		xfs_qm_dqrele(ip->i_gdquot);
  		ip->i_gdquot = NULL;
  	}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
391
392
393
394
  	if (ip->i_pdquot) {
  		xfs_qm_dqrele(ip->i_pdquot);
  		ip->i_pdquot = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  }
cd56a39a5   Dave Chinner   xfs: convert dquo...
396
397
398
399
400
401
402
403
  struct xfs_qm_isolate {
  	struct list_head	buffers;
  	struct list_head	dispose;
  };
  
  static enum lru_status
  xfs_qm_dquot_isolate(
  	struct list_head	*item,
3f97b1632   Vladimir Davydov   list_lru: add hel...
404
  	struct list_lru_one	*lru,
cd56a39a5   Dave Chinner   xfs: convert dquo...
405
406
  	spinlock_t		*lru_lock,
  	void			*arg)
bf1ed3833   Dave Chinner   xfs: xfs_qm_dquot...
407
  		__releases(lru_lock) __acquires(lru_lock)
cd56a39a5   Dave Chinner   xfs: convert dquo...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  {
  	struct xfs_dquot	*dqp = container_of(item,
  						struct xfs_dquot, q_lru);
  	struct xfs_qm_isolate	*isol = arg;
  
  	if (!xfs_dqlock_nowait(dqp))
  		goto out_miss_busy;
  
  	/*
  	 * This dquot has acquired a reference in the meantime remove it from
  	 * the freelist and try again.
  	 */
  	if (dqp->q_nrefs) {
  		xfs_dqunlock(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
422
  		XFS_STATS_INC(dqp->q_mount, xs_qm_dqwants);
cd56a39a5   Dave Chinner   xfs: convert dquo...
423
424
  
  		trace_xfs_dqreclaim_want(dqp);
3f97b1632   Vladimir Davydov   list_lru: add hel...
425
  		list_lru_isolate(lru, &dqp->q_lru);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
426
  		XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot_unused);
35163417f   Dave Chinner   xfs: fix dquot is...
427
  		return LRU_REMOVED;
cd56a39a5   Dave Chinner   xfs: convert dquo...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  	}
  
  	/*
  	 * If the dquot is dirty, flush it. If it's already being flushed, just
  	 * skip it so there is time for the IO to complete before we try to
  	 * reclaim it again on the next LRU pass.
  	 */
  	if (!xfs_dqflock_nowait(dqp)) {
  		xfs_dqunlock(dqp);
  		goto out_miss_busy;
  	}
  
  	if (XFS_DQ_IS_DIRTY(dqp)) {
  		struct xfs_buf	*bp = NULL;
  		int		error;
  
  		trace_xfs_dqreclaim_dirty(dqp);
  
  		/* we have to drop the LRU lock to flush the dquot */
  		spin_unlock(lru_lock);
  
  		error = xfs_qm_dqflush(dqp, &bp);
609001bca   Darrick J. Wong   xfs: don't spray ...
450
  		if (error)
cd56a39a5   Dave Chinner   xfs: convert dquo...
451
  			goto out_unlock_dirty;
cd56a39a5   Dave Chinner   xfs: convert dquo...
452
453
454
455
456
457
458
459
460
461
  
  		xfs_buf_delwri_queue(bp, &isol->buffers);
  		xfs_buf_relse(bp);
  		goto out_unlock_dirty;
  	}
  	xfs_dqfunlock(dqp);
  
  	/*
  	 * Prevent lookups now that we are past the point of no return.
  	 */
985a78fdd   Darrick J. Wong   xfs: rename dquot...
462
  	dqp->q_flags |= XFS_DQFLAG_FREEING;
cd56a39a5   Dave Chinner   xfs: convert dquo...
463
464
465
  	xfs_dqunlock(dqp);
  
  	ASSERT(dqp->q_nrefs == 0);
3f97b1632   Vladimir Davydov   list_lru: add hel...
466
  	list_lru_isolate_move(lru, &dqp->q_lru, &isol->dispose);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
467
  	XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot_unused);
cd56a39a5   Dave Chinner   xfs: convert dquo...
468
  	trace_xfs_dqreclaim_done(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
469
  	XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaims);
35163417f   Dave Chinner   xfs: fix dquot is...
470
  	return LRU_REMOVED;
cd56a39a5   Dave Chinner   xfs: convert dquo...
471
472
473
  
  out_miss_busy:
  	trace_xfs_dqreclaim_busy(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
474
  	XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaim_misses);
35163417f   Dave Chinner   xfs: fix dquot is...
475
  	return LRU_SKIP;
cd56a39a5   Dave Chinner   xfs: convert dquo...
476
477
478
  
  out_unlock_dirty:
  	trace_xfs_dqreclaim_busy(dqp);
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
479
  	XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaim_misses);
35163417f   Dave Chinner   xfs: fix dquot is...
480
481
482
  	xfs_dqunlock(dqp);
  	spin_lock(lru_lock);
  	return LRU_RETRY;
cd56a39a5   Dave Chinner   xfs: convert dquo...
483
  }
2f5b56f85   Andrew Morton   xfs-convert-dquot...
484
  static unsigned long
cd56a39a5   Dave Chinner   xfs: convert dquo...
485
486
487
488
489
490
491
  xfs_qm_shrink_scan(
  	struct shrinker		*shrink,
  	struct shrink_control	*sc)
  {
  	struct xfs_quotainfo	*qi = container_of(shrink,
  					struct xfs_quotainfo, qi_shrinker);
  	struct xfs_qm_isolate	isol;
2f5b56f85   Andrew Morton   xfs-convert-dquot...
492
  	unsigned long		freed;
cd56a39a5   Dave Chinner   xfs: convert dquo...
493
  	int			error;
cd56a39a5   Dave Chinner   xfs: convert dquo...
494

d0164adc8   Mel Gorman   mm, page_alloc: d...
495
  	if ((sc->gfp_mask & (__GFP_FS|__GFP_DIRECT_RECLAIM)) != (__GFP_FS|__GFP_DIRECT_RECLAIM))
cd56a39a5   Dave Chinner   xfs: convert dquo...
496
497
498
499
  		return 0;
  
  	INIT_LIST_HEAD(&isol.buffers);
  	INIT_LIST_HEAD(&isol.dispose);
503c358cf   Vladimir Davydov   list_lru: introdu...
500
501
  	freed = list_lru_shrink_walk(&qi->qi_lru, sc,
  				     xfs_qm_dquot_isolate, &isol);
cd56a39a5   Dave Chinner   xfs: convert dquo...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  
  	error = xfs_buf_delwri_submit(&isol.buffers);
  	if (error)
  		xfs_warn(NULL, "%s: dquot reclaim failed", __func__);
  
  	while (!list_empty(&isol.dispose)) {
  		struct xfs_dquot	*dqp;
  
  		dqp = list_first_entry(&isol.dispose, struct xfs_dquot, q_lru);
  		list_del_init(&dqp->q_lru);
  		xfs_qm_dqfree_one(dqp);
  	}
  
  	return freed;
  }
2f5b56f85   Andrew Morton   xfs-convert-dquot...
517
  static unsigned long
cd56a39a5   Dave Chinner   xfs: convert dquo...
518
519
520
521
522
523
  xfs_qm_shrink_count(
  	struct shrinker		*shrink,
  	struct shrink_control	*sc)
  {
  	struct xfs_quotainfo	*qi = container_of(shrink,
  					struct xfs_quotainfo, qi_shrinker);
503c358cf   Vladimir Davydov   list_lru: introdu...
524
  	return list_lru_shrink_count(&qi->qi_lru, sc);
cd56a39a5   Dave Chinner   xfs: convert dquo...
525
  }
be6079461   Carlos Maiolino   xfs: Split defaul...
526
527
  STATIC void
  xfs_qm_set_defquota(
c072fbefe   Pavel Reichl   xfs: remove the x...
528
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
529
  	xfs_dqtype_t		type,
c072fbefe   Pavel Reichl   xfs: remove the x...
530
  	struct xfs_quotainfo	*qinf)
be6079461   Carlos Maiolino   xfs: Split defaul...
531
  {
aefe69a45   Pavel Reichl   xfs: remove the x...
532
533
  	struct xfs_dquot	*dqp;
  	struct xfs_def_quota	*defq;
be6079461   Carlos Maiolino   xfs: Split defaul...
534
  	int			error;
114e73ccf   Darrick J. Wong   xfs: remove direc...
535
  	error = xfs_qm_dqget_uncached(mp, 0, type, &dqp);
eac69e167   Darrick J. Wong   xfs: refactor quo...
536
537
  	if (error)
  		return;
be6079461   Carlos Maiolino   xfs: Split defaul...
538

ce6e7e79c   Eric Sandeen   xfs: switch xfs_g...
539
  	defq = xfs_get_defquota(qinf, xfs_dquot_type(dqp));
be6079461   Carlos Maiolino   xfs: Split defaul...
540

eac69e167   Darrick J. Wong   xfs: refactor quo...
541
542
543
544
  	/*
  	 * Timers and warnings have been already set, let's just set the
  	 * default limits for this quota type
  	 */
438769e31   Darrick J. Wong   xfs: refactor def...
545
546
547
548
549
550
  	defq->blk.hard = dqp->q_blk.hardlimit;
  	defq->blk.soft = dqp->q_blk.softlimit;
  	defq->ino.hard = dqp->q_ino.hardlimit;
  	defq->ino.soft = dqp->q_ino.softlimit;
  	defq->rtb.hard = dqp->q_rtb.hardlimit;
  	defq->rtb.soft = dqp->q_rtb.softlimit;
eac69e167   Darrick J. Wong   xfs: refactor quo...
551
552
553
554
555
556
557
  	xfs_qm_dqdestroy(dqp);
  }
  
  /* Initialize quota time limits from the root dquot. */
  static void
  xfs_qm_init_timelimits(
  	struct xfs_mount	*mp,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
558
  	xfs_dqtype_t		type)
eac69e167   Darrick J. Wong   xfs: refactor quo...
559
  {
e850301f0   Eric Sandeen   xfs: per-type quo...
560
561
  	struct xfs_quotainfo	*qinf = mp->m_quotainfo;
  	struct xfs_def_quota	*defq;
eac69e167   Darrick J. Wong   xfs: refactor quo...
562
  	struct xfs_dquot	*dqp;
eac69e167   Darrick J. Wong   xfs: refactor quo...
563
  	int			error;
e850301f0   Eric Sandeen   xfs: per-type quo...
564
  	defq = xfs_get_defquota(qinf, type);
438769e31   Darrick J. Wong   xfs: refactor def...
565
566
567
568
569
570
  	defq->blk.time = XFS_QM_BTIMELIMIT;
  	defq->ino.time = XFS_QM_ITIMELIMIT;
  	defq->rtb.time = XFS_QM_RTBTIMELIMIT;
  	defq->blk.warn = XFS_QM_BWARNLIMIT;
  	defq->ino.warn = XFS_QM_IWARNLIMIT;
  	defq->rtb.warn = XFS_QM_RTBWARNLIMIT;
eac69e167   Darrick J. Wong   xfs: refactor quo...
571
572
573
574
575
576
577
  
  	/*
  	 * We try to get the limits from the superuser's limits fields.
  	 * This is quite hacky, but it is standard quota practice.
  	 *
  	 * Since we may not have done a quotacheck by this point, just read
  	 * the dquot without attaching it to any hashtables or lists.
eac69e167   Darrick J. Wong   xfs: refactor quo...
578
  	 */
eac69e167   Darrick J. Wong   xfs: refactor quo...
579
580
581
  	error = xfs_qm_dqget_uncached(mp, 0, type, &dqp);
  	if (error)
  		return;
eac69e167   Darrick J. Wong   xfs: refactor quo...
582
583
584
585
586
  	/*
  	 * The warnings and timers set the grace period given to
  	 * a user or group before he or she can not perform any
  	 * more writing. If it is zero, a default is used.
  	 */
19dce7eae   Darrick J. Wong   xfs: stop using q...
587
  	if (dqp->q_blk.timer)
438769e31   Darrick J. Wong   xfs: refactor def...
588
  		defq->blk.time = dqp->q_blk.timer;
19dce7eae   Darrick J. Wong   xfs: stop using q...
589
  	if (dqp->q_ino.timer)
438769e31   Darrick J. Wong   xfs: refactor def...
590
  		defq->ino.time = dqp->q_ino.timer;
19dce7eae   Darrick J. Wong   xfs: stop using q...
591
  	if (dqp->q_rtb.timer)
438769e31   Darrick J. Wong   xfs: refactor def...
592
  		defq->rtb.time = dqp->q_rtb.timer;
c8c45fb2f   Darrick J. Wong   xfs: stop using q...
593
  	if (dqp->q_blk.warnings)
438769e31   Darrick J. Wong   xfs: refactor def...
594
  		defq->blk.warn = dqp->q_blk.warnings;
c8c45fb2f   Darrick J. Wong   xfs: stop using q...
595
  	if (dqp->q_ino.warnings)
438769e31   Darrick J. Wong   xfs: refactor def...
596
  		defq->ino.warn = dqp->q_ino.warnings;
c8c45fb2f   Darrick J. Wong   xfs: stop using q...
597
  	if (dqp->q_rtb.warnings)
438769e31   Darrick J. Wong   xfs: refactor def...
598
  		defq->rtb.warn = dqp->q_rtb.warnings;
eac69e167   Darrick J. Wong   xfs: refactor quo...
599
600
  
  	xfs_qm_dqdestroy(dqp);
be6079461   Carlos Maiolino   xfs: Split defaul...
601
  }
a4edd1da2   Christoph Hellwig   xfs: add a separa...
602
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
   * This initializes all the quota information that's kept in the
   * mount structure
   */
ba0f32d46   Christoph Hellwig   [XFS] mark variou...
606
  STATIC int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  xfs_qm_init_quotainfo(
114e73ccf   Darrick J. Wong   xfs: remove direc...
608
  	struct xfs_mount	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
114e73ccf   Darrick J. Wong   xfs: remove direc...
610
  	struct xfs_quotainfo	*qinf;
114e73ccf   Darrick J. Wong   xfs: remove direc...
611
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  
  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
c072fbefe   Pavel Reichl   xfs: remove the x...
614
  	qinf = mp->m_quotainfo = kmem_zalloc(sizeof(struct xfs_quotainfo), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615

2451337dd   Dave Chinner   xfs: global error...
616
  	error = list_lru_init(&qinf->qi_lru);
ee4eec478   Dave Chinner   xfs: list_lru_ini...
617
618
  	if (error)
  		goto out_free_qinf;
5ca302c8e   Glauber Costa   list_lru: dynamic...
619

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
623
  	/*
  	 * See if quotainodes are setup, and if not, allocate them,
  	 * and change the superblock accordingly.
  	 */
ee4eec478   Dave Chinner   xfs: list_lru_ini...
624
625
626
  	error = xfs_qm_init_quotainos(mp);
  	if (error)
  		goto out_free_lru;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

9f920f116   Christoph Hellwig   xfs: use per-file...
628
629
  	INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
  	INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
630
  	INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
9f920f116   Christoph Hellwig   xfs: use per-file...
631
  	mutex_init(&qinf->qi_tree_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  	/* mutex used to serialize quotaoffs */
794ee1bae   Jes Sorensen   [PATCH] mutex sub...
633
  	mutex_init(&qinf->qi_quotaofflock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
  
  	/* Precalc some constants */
  	qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB);
6ea94bb5b   Eric Sandeen   xfs: remove unuse...
637
  	qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen);
4ea1ff3b4   Darrick J. Wong   xfs: widen ondisk...
638
639
640
641
642
643
644
645
646
  	if (xfs_sb_version_hasbigtime(&mp->m_sb)) {
  		qinf->qi_expiry_min =
  			xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN);
  		qinf->qi_expiry_max =
  			xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX);
  	} else {
  		qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN;
  		qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX;
  	}
06dbf82b0   Darrick J. Wong   xfs: trace timest...
647
648
  	trace_xfs_quota_expiry_range(mp, qinf->qi_expiry_min,
  			qinf->qi_expiry_max);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
  
  	mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD);
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
651
652
653
  	xfs_qm_init_timelimits(mp, XFS_DQTYPE_USER);
  	xfs_qm_init_timelimits(mp, XFS_DQTYPE_GROUP);
  	xfs_qm_init_timelimits(mp, XFS_DQTYPE_PROJ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654

be6079461   Carlos Maiolino   xfs: Split defaul...
655
  	if (XFS_IS_UQUOTA_RUNNING(mp))
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
656
  		xfs_qm_set_defquota(mp, XFS_DQTYPE_USER, qinf);
be6079461   Carlos Maiolino   xfs: Split defaul...
657
  	if (XFS_IS_GQUOTA_RUNNING(mp))
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
658
  		xfs_qm_set_defquota(mp, XFS_DQTYPE_GROUP, qinf);
be6079461   Carlos Maiolino   xfs: Split defaul...
659
  	if (XFS_IS_PQUOTA_RUNNING(mp))
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
660
  		xfs_qm_set_defquota(mp, XFS_DQTYPE_PROJ, qinf);
be6079461   Carlos Maiolino   xfs: Split defaul...
661

cd56a39a5   Dave Chinner   xfs: convert dquo...
662
663
  	qinf->qi_shrinker.count_objects = xfs_qm_shrink_count;
  	qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan;
f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
664
  	qinf->qi_shrinker.seeks = DEFAULT_SEEKS;
cd56a39a5   Dave Chinner   xfs: convert dquo...
665
  	qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE;
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
666
667
668
669
  
  	error = register_shrinker(&qinf->qi_shrinker);
  	if (error)
  		goto out_free_inos;
014c2544e   Jesper Juhl   return statement ...
670
  	return 0;
ee4eec478   Dave Chinner   xfs: list_lru_ini...
671

3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
672
673
674
675
  out_free_inos:
  	mutex_destroy(&qinf->qi_quotaofflock);
  	mutex_destroy(&qinf->qi_tree_lock);
  	xfs_qm_destroy_quotainos(qinf);
ee4eec478   Dave Chinner   xfs: list_lru_ini...
676
677
678
679
680
681
  out_free_lru:
  	list_lru_destroy(&qinf->qi_lru);
  out_free_qinf:
  	kmem_free(qinf);
  	mp->m_quotainfo = NULL;
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
685
686
687
688
689
  /*
   * Gets called when unmounting a filesystem or when all quotas get
   * turned off.
   * This purges the quota inodes, destroys locks and frees itself.
   */
  void
  xfs_qm_destroy_quotainfo(
c072fbefe   Pavel Reichl   xfs: remove the x...
690
  	struct xfs_mount	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  {
c072fbefe   Pavel Reichl   xfs: remove the x...
692
  	struct xfs_quotainfo	*qi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
695
  
  	qi = mp->m_quotainfo;
  	ASSERT(qi != NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696

f8739c3ce   Christoph Hellwig   xfs: per-filesyst...
697
  	unregister_shrinker(&qi->qi_shrinker);
f5e1dd345   Glauber Costa   super: fix for de...
698
  	list_lru_destroy(&qi->qi_lru);
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
699
  	xfs_qm_destroy_quotainos(qi);
219688156   Aliaksei Karaliou   xfs: quota: fix m...
700
  	mutex_destroy(&qi->qi_tree_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	mutex_destroy(&qi->qi_quotaofflock);
f0e2d93c2   Denys Vlasenko   [XFS] Remove unus...
702
  	kmem_free(qi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
  	mp->m_quotainfo = NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
710
711
712
  /*
   * Create an inode and return with a reference already taken, but unlocked
   * This is how we create quota inodes
   */
  STATIC int
  xfs_qm_qino_alloc(
  	xfs_mount_t	*mp,
  	xfs_inode_t	**ip,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
715
716
  	uint		flags)
  {
  	xfs_trans_t	*tp;
  	int		error;
58c904734   Dave Chinner   xfs: inodes are n...
717
  	bool		need_alloc = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718

d892d5864   Chandra Seetharaman   xfs: Start using ...
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  	*ip = NULL;
  	/*
  	 * With superblock that doesn't have separate pquotino, we
  	 * share an inode between gquota and pquota. If the on-disk
  	 * superblock has GQUOTA and the filesystem is now mounted
  	 * with PQUOTA, just use sb_gquotino for sb_pquotino and
  	 * vice-versa.
  	 */
  	if (!xfs_sb_version_has_pquotino(&mp->m_sb) &&
  			(flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) {
  		xfs_ino_t ino = NULLFSINO;
  
  		if ((flags & XFS_QMOPT_PQUOTA) &&
  			     (mp->m_sb.sb_gquotino != NULLFSINO)) {
  			ino = mp->m_sb.sb_gquotino;
a71895c5d   Darrick J. Wong   xfs: convert open...
734
735
  			if (XFS_IS_CORRUPT(mp,
  					   mp->m_sb.sb_pquotino != NULLFSINO))
a5155b870   Darrick J. Wong   xfs: always log c...
736
  				return -EFSCORRUPTED;
d892d5864   Chandra Seetharaman   xfs: Start using ...
737
738
739
  		} else if ((flags & XFS_QMOPT_GQUOTA) &&
  			     (mp->m_sb.sb_pquotino != NULLFSINO)) {
  			ino = mp->m_sb.sb_pquotino;
a71895c5d   Darrick J. Wong   xfs: convert open...
740
741
  			if (XFS_IS_CORRUPT(mp,
  					   mp->m_sb.sb_gquotino != NULLFSINO))
a5155b870   Darrick J. Wong   xfs: always log c...
742
  				return -EFSCORRUPTED;
d892d5864   Chandra Seetharaman   xfs: Start using ...
743
744
745
746
747
748
749
  		}
  		if (ino != NULLFSINO) {
  			error = xfs_iget(mp, NULL, ino, 0, 0, ip);
  			if (error)
  				return error;
  			mp->m_sb.sb_gquotino = NULLFSINO;
  			mp->m_sb.sb_pquotino = NULLFSINO;
58c904734   Dave Chinner   xfs: inodes are n...
750
  			need_alloc = false;
d892d5864   Chandra Seetharaman   xfs: Start using ...
751
752
  		}
  	}
253f4911f   Christoph Hellwig   xfs: better xfs_t...
753
  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create,
fb353ff19   Kaixu Xia   xfs: reserve quot...
754
755
  			need_alloc ? XFS_QM_QINOCREATE_SPACE_RES(mp) : 0,
  			0, 0, &tp);
253f4911f   Christoph Hellwig   xfs: better xfs_t...
756
  	if (error)
014c2544e   Jesper Juhl   return statement ...
757
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

58c904734   Dave Chinner   xfs: inodes are n...
759
  	if (need_alloc) {
c959025ed   Chandan Rajendra   xfs: Remove "comm...
760
  		error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, ip);
d892d5864   Chandra Seetharaman   xfs: Start using ...
761
  		if (error) {
4906e2154   Christoph Hellwig   xfs: remove the f...
762
  			xfs_trans_cancel(tp);
d892d5864   Chandra Seetharaman   xfs: Start using ...
763
764
  			return error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
  	}
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
770
771
  	 * Make the changes in the superblock, and log those too.
  	 * sbfields arg may contain fields other than *QUOTINO;
  	 * VERSIONNUM for example.
  	 */
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
772
  	spin_lock(&mp->m_sb_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
  	if (flags & XFS_QMOPT_SBVERSION) {
621187099   Eric Sandeen   [XFS] remove shou...
774
  		ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775

621187099   Eric Sandeen   [XFS] remove shou...
776
  		xfs_sb_version_addquota(&mp->m_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
  		mp->m_sb.sb_uquotino = NULLFSINO;
  		mp->m_sb.sb_gquotino = NULLFSINO;
d892d5864   Chandra Seetharaman   xfs: Start using ...
779
  		mp->m_sb.sb_pquotino = NULLFSINO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780

d892d5864   Chandra Seetharaman   xfs: Start using ...
781
782
  		/* qflags will get updated fully _after_ quotacheck */
  		mp->m_sb.sb_qflags = mp->m_qflags & XFS_ALL_QUOTA_ACCT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
785
  	}
  	if (flags & XFS_QMOPT_UQUOTA)
  		mp->m_sb.sb_uquotino = (*ip)->i_ino;
d892d5864   Chandra Seetharaman   xfs: Start using ...
786
  	else if (flags & XFS_QMOPT_GQUOTA)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  		mp->m_sb.sb_gquotino = (*ip)->i_ino;
d892d5864   Chandra Seetharaman   xfs: Start using ...
788
789
  	else
  		mp->m_sb.sb_pquotino = (*ip)->i_ino;
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
790
  	spin_unlock(&mp->m_sb_lock);
61e63ecb5   Dave Chinner   xfs: consolidate ...
791
  	xfs_log_sb(tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792

70393313d   Christoph Hellwig   xfs: saner xfs_tr...
793
  	error = xfs_trans_commit(tp);
58c904734   Dave Chinner   xfs: inodes are n...
794
795
  	if (error) {
  		ASSERT(XFS_FORCED_SHUTDOWN(mp));
534877869   Dave Chinner   xfs: convert xfs_...
796
  		xfs_alert(mp, "%s failed (error %d)!", __func__, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  	}
58c904734   Dave Chinner   xfs: inodes are n...
798
799
800
  	if (need_alloc)
  		xfs_finish_inode_setup(*ip);
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  }
5b1397385   David Chinner   [XFS] xfs_qm_rese...
802
  STATIC void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  xfs_qm_reset_dqcounts(
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
804
805
806
807
  	struct xfs_mount	*mp,
  	struct xfs_buf		*bp,
  	xfs_dqid_t		id,
  	xfs_dqtype_t		type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  {
6fcdc59de   Dave Chinner   xfs: rework dquot...
809
  	struct xfs_dqblk	*dqb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
  	int			j;
0b1b213fc   Christoph Hellwig   xfs: event tracin...
811
  	trace_xfs_reset_dqcounts(bp, _RET_IP_);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
814
815
816
  	/*
  	 * Reset all counters and timers. They'll be
  	 * started afresh by xfs_qm_quotacheck.
  	 */
  #ifdef DEBUG
90115407c   Eric Sandeen   xfs: remove use o...
817
818
  	j = (int)XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) /
  		sizeof(xfs_dqblk_t);
8a7b8a89a   Christoph Hellwig   xfs: access quota...
819
  	ASSERT(mp->m_quotainfo->qi_dqperchunk == j);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  #endif
6fcdc59de   Dave Chinner   xfs: rework dquot...
821
  	dqb = bp->b_addr;
8a7b8a89a   Christoph Hellwig   xfs: access quota...
822
  	for (j = 0; j < mp->m_quotainfo->qi_dqperchunk; j++) {
6fcdc59de   Dave Chinner   xfs: rework dquot...
823
824
825
  		struct xfs_disk_dquot	*ddq;
  
  		ddq = (struct xfs_disk_dquot *)&dqb[j];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
828
  		/*
  		 * Do a sanity check, and if needed, repair the dqblk. Don't
  		 * output any warnings because it's perfectly possible to
eebf3cab9   Darrick J. Wong   xfs: standardize ...
829
830
  		 * find uninitialised dquot blks. See comment in
  		 * xfs_dquot_verify.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  		 */
f9751c4ad   Darrick J. Wong   xfs: drop the typ...
832
  		if (xfs_dqblk_verify(mp, &dqb[j], id + j) ||
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
833
  		    (dqb[j].dd_diskdq.d_type & XFS_DQTYPE_REC_MASK) != type)
48fa1db87   Eric Sandeen   xfs: pass full xf...
834
  			xfs_dqblk_repair(mp, &dqb[j], id + j, type);
eeea79802   Darrick J. Wong   xfs: separate dqu...
835

dfcc70a8c   Jan Kara   xfs: Fix quota ty...
836
837
838
839
  		/*
  		 * Reset type in case we are reusing group quota file for
  		 * project quotas or vice versa
  		 */
d8c1af0d6   Darrick J. Wong   xfs: rename the o...
840
  		ddq->d_type = type;
1149d96ae   Christoph Hellwig   [XFS] endianess a...
841
842
843
  		ddq->d_bcount = 0;
  		ddq->d_icount = 0;
  		ddq->d_rtbcount = 0;
5885539f0   Darrick J. Wong   xfs: preserve def...
844
845
846
847
848
849
850
851
852
853
854
855
856
  
  		/*
  		 * dquot id 0 stores the default grace period and the maximum
  		 * warning limit that were set by the administrator, so we
  		 * should not reset them.
  		 */
  		if (ddq->d_id != 0) {
  			ddq->d_btimer = 0;
  			ddq->d_itimer = 0;
  			ddq->d_rtbtimer = 0;
  			ddq->d_bwarns = 0;
  			ddq->d_iwarns = 0;
  			ddq->d_rtbwarns = 0;
4ea1ff3b4   Darrick J. Wong   xfs: widen ondisk...
857
858
  			if (xfs_sb_version_hasbigtime(&mp->m_sb))
  				ddq->d_type |= XFS_DQTYPE_BIGTIME;
5885539f0   Darrick J. Wong   xfs: preserve def...
859
  		}
6fcdc59de   Dave Chinner   xfs: rework dquot...
860
861
862
863
864
865
  
  		if (xfs_sb_version_hascrc(&mp->m_sb)) {
  			xfs_update_cksum((char *)&dqb[j],
  					 sizeof(struct xfs_dqblk),
  					 XFS_DQUOT_CRC_OFF);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
  }
  
  STATIC int
28b9060bd   Darrick J. Wong   xfs: rename on-di...
870
  xfs_qm_reset_dqcounts_all(
43ff2122e   Christoph Hellwig   xfs: on-stack del...
871
872
873
874
  	struct xfs_mount	*mp,
  	xfs_dqid_t		firstid,
  	xfs_fsblock_t		bno,
  	xfs_filblks_t		blkcnt,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
875
  	xfs_dqtype_t		type,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
876
  	struct list_head	*buffer_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  {
43ff2122e   Christoph Hellwig   xfs: on-stack del...
878
  	struct xfs_buf		*bp;
0dcc0728c   Darrick J. Wong   xfs: refactor quo...
879
  	int			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  
  	ASSERT(blkcnt > 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
885
886
887
888
889
890
891
892
893
894
  
  	/*
  	 * Blkcnt arg can be a very big number, and might even be
  	 * larger than the log itself. So, we have to break it up into
  	 * manageable-sized transactions.
  	 * Note that we don't start a permanent transaction here; we might
  	 * not be able to get a log reservation for the whole thing up front,
  	 * and we don't really care to either, because we just discard
  	 * everything if we were to crash in the middle of this loop.
  	 */
  	while (blkcnt--) {
  		error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
  			      XFS_FSB_TO_DADDR(mp, bno),
c63191987   Dave Chinner   xfs: verify dquot...
895
  			      mp->m_quotainfo->qi_dqchunklen, 0, &bp,
1813dd640   Dave Chinner   xfs: convert buff...
896
  			      &xfs_dquot_buf_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897

3fe58f30b   Christoph Hellwig   xfs: add CRC chec...
898
  		/*
6fcdc59de   Dave Chinner   xfs: rework dquot...
899
900
901
902
903
  		 * CRC and validation errors will return a EFSCORRUPTED here. If
  		 * this occurs, re-read without CRC validation so that we can
  		 * repair the damage via xfs_qm_reset_dqcounts(). This process
  		 * will leave a trace in the log indicating corruption has
  		 * been detected.
3fe58f30b   Christoph Hellwig   xfs: add CRC chec...
904
  		 */
2451337dd   Dave Chinner   xfs: global error...
905
  		if (error == -EFSCORRUPTED) {
6fcdc59de   Dave Chinner   xfs: rework dquot...
906
907
908
909
910
911
912
913
  			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
  				      XFS_FSB_TO_DADDR(mp, bno),
  				      mp->m_quotainfo->qi_dqchunklen, 0, &bp,
  				      NULL);
  		}
  
  		if (error)
  			break;
5fd364fee   Dave Chinner   xfs: quotacheck l...
914
915
916
917
918
919
  		/*
  		 * A corrupt buffer might not have a verifier attached, so
  		 * make sure we have the correct one attached before writeback
  		 * occurs.
  		 */
  		bp->b_ops = &xfs_dquot_buf_ops;
5b1397385   David Chinner   [XFS] xfs_qm_rese...
920
  		xfs_qm_reset_dqcounts(mp, bp, firstid, type);
43ff2122e   Christoph Hellwig   xfs: on-stack del...
921
  		xfs_buf_delwri_queue(bp, buffer_list);
61551f1ee   Christoph Hellwig   xfs: call xfs_buf...
922
  		xfs_buf_relse(bp);
6fcdc59de   Dave Chinner   xfs: rework dquot...
923
924
  
  		/* goto the next block. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
  		bno++;
8a7b8a89a   Christoph Hellwig   xfs: access quota...
926
  		firstid += mp->m_quotainfo->qi_dqperchunk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
  	}
43ff2122e   Christoph Hellwig   xfs: on-stack del...
928

014c2544e   Jesper Juhl   return statement ...
929
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
  }
  
  /*
28b9060bd   Darrick J. Wong   xfs: rename on-di...
933
934
   * Iterate over all allocated dquot blocks in this quota inode, zeroing all
   * counters for every chunk of dquots that we find.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
936
   */
  STATIC int
28b9060bd   Darrick J. Wong   xfs: rename on-di...
937
  xfs_qm_reset_dqcounts_buf(
43ff2122e   Christoph Hellwig   xfs: on-stack del...
938
939
  	struct xfs_mount	*mp,
  	struct xfs_inode	*qip,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
940
  	xfs_dqtype_t		type,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
941
  	struct list_head	*buffer_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
  {
43ff2122e   Christoph Hellwig   xfs: on-stack del...
943
  	struct xfs_bmbt_irec	*map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
951
952
953
  	int			i, nmaps;	/* number of map entries */
  	int			error;		/* return value */
  	xfs_fileoff_t		lblkno;
  	xfs_filblks_t		maxlblkcnt;
  	xfs_dqid_t		firstid;
  	xfs_fsblock_t		rablkno;
  	xfs_filblks_t		rablkcnt;
  
  	error = 0;
  	/*
c41564b5a   Nathan Scott   [XFS] We really s...
954
  	 * This looks racy, but we can't keep an inode lock across a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
957
958
  	 * trans_reserve. But, this gets called during quotacheck, and that
  	 * happens only at mount time which is single threaded.
  	 */
  	if (qip->i_d.di_nblocks == 0)
014c2544e   Jesper Juhl   return statement ...
959
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960

707e0ddaf   Tetsuo Handa   fs: xfs: Remove K...
961
  	map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
  
  	lblkno = 0;
32972383c   Dave Chinner   xfs: make largest...
964
  	maxlblkcnt = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  	do {
da51d32d4   Christoph Hellwig   xfs: use xfs_iloc...
966
  		uint		lock_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
970
971
972
  		nmaps = XFS_DQITER_MAP_SIZE;
  		/*
  		 * We aren't changing the inode itself. Just changing
  		 * some of its data. No new blocks are added here, and
  		 * the inode is never added to the transaction.
  		 */
da51d32d4   Christoph Hellwig   xfs: use xfs_iloc...
973
  		lock_mode = xfs_ilock_data_map_shared(qip);
5c8ed2021   Dave Chinner   xfs: introduce xf...
974
975
  		error = xfs_bmapi_read(qip, lblkno, maxlblkcnt - lblkno,
  				       map, &nmaps, 0);
da51d32d4   Christoph Hellwig   xfs: use xfs_iloc...
976
  		xfs_iunlock(qip, lock_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
  		if (error)
  			break;
  
  		ASSERT(nmaps <= XFS_DQITER_MAP_SIZE);
  		for (i = 0; i < nmaps; i++) {
  			ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
  			ASSERT(map[i].br_blockcount);
  
  
  			lblkno += map[i].br_blockcount;
  
  			if (map[i].br_startblock == HOLESTARTBLOCK)
  				continue;
  
  			firstid = (xfs_dqid_t) map[i].br_startoff *
8a7b8a89a   Christoph Hellwig   xfs: access quota...
992
  				mp->m_quotainfo->qi_dqperchunk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
998
999
1000
  			/*
  			 * Do a read-ahead on the next extent.
  			 */
  			if ((i+1 < nmaps) &&
  			    (map[i+1].br_startblock != HOLESTARTBLOCK)) {
  				rablkcnt =  map[i+1].br_blockcount;
  				rablkno = map[i+1].br_startblock;
  				while (rablkcnt--) {
1a1a3e97b   Christoph Hellwig   xfs: remove xfs_b...
1001
  					xfs_buf_readahead(mp->m_ddev_targp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  					       XFS_FSB_TO_DADDR(mp, rablkno),
c3f8fc73a   Dave Chinner   xfs: make buffer ...
1003
  					       mp->m_quotainfo->qi_dqchunklen,
5fd364fee   Dave Chinner   xfs: quotacheck l...
1004
  					       &xfs_dquot_buf_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
1006
1007
1008
1009
1010
1011
  					rablkno++;
  				}
  			}
  			/*
  			 * Iterate thru all the blks in the extent and
  			 * reset the counters of all the dquots inside them.
  			 */
28b9060bd   Darrick J. Wong   xfs: rename on-di...
1012
  			error = xfs_qm_reset_dqcounts_all(mp, firstid,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1013
1014
  						   map[i].br_startblock,
  						   map[i].br_blockcount,
0dcc0728c   Darrick J. Wong   xfs: refactor quo...
1015
  						   type, buffer_list);
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1016
1017
  			if (error)
  				goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  	} while (nmaps > 0);
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1020
  out:
f0e2d93c2   Denys Vlasenko   [XFS] Remove unus...
1021
  	kmem_free(map);
014c2544e   Jesper Juhl   return statement ...
1022
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
  }
  
  /*
   * Called by dqusage_adjust in doing a quotacheck.
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1027
1028
1029
1030
1031
   *
   * Given the inode, and a dquot id this updates both the incore dqout as well
   * as the buffer copy. This is so that once the quotacheck is done, we can
   * just log all the buffers, as opposed to logging numerous updates to
   * individual dquots.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
   */
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1033
  STATIC int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  xfs_qm_quotacheck_dqadjust(
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1035
  	struct xfs_inode	*ip,
1a7ed2716   Darrick J. Wong   xfs: create xfs_d...
1036
  	xfs_dqtype_t		type,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
1039
  	xfs_qcnt_t		nblks,
  	xfs_qcnt_t		rtblks)
  {
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1040
1041
  	struct xfs_mount	*mp = ip->i_mount;
  	struct xfs_dquot	*dqp;
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1042
  	xfs_dqid_t		id;
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1043
  	int			error;
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1044
  	id = xfs_qm_id_for_quotatype(ip, type);
30ab2dcf2   Darrick J. Wong   xfs: replace XFS_...
1045
  	error = xfs_qm_dqget(mp, id, type, true, &dqp);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1046
1047
1048
1049
  	if (error) {
  		/*
  		 * Shouldn't be able to turn off quotas here.
  		 */
2451337dd   Dave Chinner   xfs: global error...
1050
1051
  		ASSERT(error != -ESRCH);
  		ASSERT(error != -ENOENT);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1052
1053
  		return error;
  	}
0b1b213fc   Christoph Hellwig   xfs: event tracin...
1054
1055
  
  	trace_xfs_dqadjust(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
1058
1059
  	/*
  	 * Adjust the inode count and the block count to reflect this inode's
  	 * resource usage.
  	 */
be37d40c1   Darrick J. Wong   xfs: stop using q...
1060
  	dqp->q_ino.count++;
784e80f56   Darrick J. Wong   xfs: use a per-re...
1061
  	dqp->q_ino.reserved++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
  	if (nblks) {
be37d40c1   Darrick J. Wong   xfs: stop using q...
1063
  		dqp->q_blk.count += nblks;
784e80f56   Darrick J. Wong   xfs: use a per-re...
1064
  		dqp->q_blk.reserved += nblks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
  	}
  	if (rtblks) {
be37d40c1   Darrick J. Wong   xfs: stop using q...
1067
  		dqp->q_rtb.count += rtblks;
784e80f56   Darrick J. Wong   xfs: use a per-re...
1068
  		dqp->q_rtb.reserved += rtblks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1069
1070
1071
1072
  	}
  
  	/*
  	 * Set default limits, adjust timers (since we changed usages)
191f8488f   Christoph Hellwig   xfs: remove a few...
1073
1074
  	 *
  	 * There are no timers for the default values set in the root dquot.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075
  	 */
c51df7334   Darrick J. Wong   xfs: stop using q...
1076
  	if (dqp->q_id) {
c8c753e19   Darrick J. Wong   xfs: remove unnec...
1077
1078
  		xfs_qm_adjust_dqlimits(dqp);
  		xfs_qm_adjust_dqtimers(dqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
  	}
985a78fdd   Darrick J. Wong   xfs: rename dquot...
1080
  	dqp->q_flags |= XFS_DQFLAG_DIRTY;
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1081
1082
  	xfs_qm_dqput(dqp);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
1085
1086
1087
1088
1089
1090
  /*
   * callback routine supplied to bulkstat(). Given an inumber, find its
   * dquots and update them to account for resources taken by that inode.
   */
  /* ARGSUSED */
  STATIC int
  xfs_qm_dqusage_adjust(
ebd126a65   Darrick J. Wong   xfs: convert quot...
1091
1092
1093
1094
  	struct xfs_mount	*mp,
  	struct xfs_trans	*tp,
  	xfs_ino_t		ino,
  	void			*data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
  {
ebd126a65   Darrick J. Wong   xfs: convert quot...
1096
1097
1098
1099
  	struct xfs_inode	*ip;
  	xfs_qcnt_t		nblks;
  	xfs_filblks_t		rtblks = 0;	/* total rt blks */
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
1102
1103
1104
1105
1106
  
  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
  
  	/*
  	 * rootino must have its resources accounted for, not so with the quota
  	 * inodes.
  	 */
ebd126a65   Darrick J. Wong   xfs: convert quot...
1107
1108
  	if (xfs_is_quota_inode(&mp->m_sb, ino))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
1110
  
  	/*
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1111
1112
  	 * We don't _need_ to take the ilock EXCL here because quotacheck runs
  	 * at mount time and therefore nobody will be racing chown/chproj.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
  	 */
ebd126a65   Darrick J. Wong   xfs: convert quot...
1114
1115
1116
1117
  	error = xfs_iget(mp, tp, ino, XFS_IGET_DONTCACHE, 0, &ip);
  	if (error == -EINVAL || error == -ENOENT)
  		return 0;
  	if (error)
014c2544e   Jesper Juhl   return statement ...
1118
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119

52fda1142   Christoph Hellwig   xfs: simplify xfs...
1120
  	ASSERT(ip->i_delayed_blks == 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121

52fda1142   Christoph Hellwig   xfs: simplify xfs...
1122
  	if (XFS_IS_REALTIME_INODE(ip)) {
8bfadd8d0   Christoph Hellwig   xfs: replace xfs_...
1123
1124
1125
  		struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
  
  		if (!(ifp->if_flags & XFS_IFEXTENTS)) {
ebd126a65   Darrick J. Wong   xfs: convert quot...
1126
  			error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
8bfadd8d0   Christoph Hellwig   xfs: replace xfs_...
1127
1128
1129
1130
1131
  			if (error)
  				goto error0;
  		}
  
  		xfs_bmap_count_leaves(ifp, &rtblks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133

52fda1142   Christoph Hellwig   xfs: simplify xfs...
1134
  	nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
  
  	/*
  	 * Add the (disk blocks and inode) resources occupied by this
  	 * inode to its dquots. We do this adjustment in the incore dquot,
  	 * and also copy the changes to its buffer.
  	 * We don't care about putting these changes in a transaction
  	 * envelope because if we crash in the middle of a 'quotacheck'
  	 * we have to start from the beginning anyway.
  	 * Once we're done, we'll log all the dquot bufs.
  	 *
c41564b5a   Nathan Scott   [XFS] We really s...
1145
  	 * The *QUOTA_ON checks below may look pretty racy, but quotachecks
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
1147
1148
  	 * and quotaoffs don't race. (Quotachecks happen at mount time only).
  	 */
  	if (XFS_IS_UQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1149
  		error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_USER, nblks,
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1150
  				rtblks);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1151
1152
  		if (error)
  			goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
  	}
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1154
1155
  
  	if (XFS_IS_GQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1156
  		error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_GROUP, nblks,
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1157
  				rtblks);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1158
1159
  		if (error)
  			goto error0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161

52fda1142   Christoph Hellwig   xfs: simplify xfs...
1162
  	if (XFS_IS_PQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1163
  		error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_PROJ, nblks,
0fcef1270   Darrick J. Wong   xfs: fetch dquots...
1164
  				rtblks);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1165
1166
1167
  		if (error)
  			goto error0;
  	}
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1168
  error0:
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1169
  	xfs_irele(ip);
52fda1142   Christoph Hellwig   xfs: simplify xfs...
1170
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  }
b84a3a967   Christoph Hellwig   xfs: remove the p...
1172
1173
  STATIC int
  xfs_qm_flush_one(
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1174
1175
  	struct xfs_dquot	*dqp,
  	void			*data)
b84a3a967   Christoph Hellwig   xfs: remove the p...
1176
  {
7912e7fef   Brian Foster   xfs: push buffer ...
1177
  	struct xfs_mount	*mp = dqp->q_mount;
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1178
  	struct list_head	*buffer_list = data;
fe7257fd4   Christoph Hellwig   xfs: do not write...
1179
  	struct xfs_buf		*bp = NULL;
b84a3a967   Christoph Hellwig   xfs: remove the p...
1180
1181
1182
  	int			error = 0;
  
  	xfs_dqlock(dqp);
985a78fdd   Darrick J. Wong   xfs: rename dquot...
1183
  	if (dqp->q_flags & XFS_DQFLAG_FREEING)
b84a3a967   Christoph Hellwig   xfs: remove the p...
1184
1185
1186
  		goto out_unlock;
  	if (!XFS_DQ_IS_DIRTY(dqp))
  		goto out_unlock;
7912e7fef   Brian Foster   xfs: push buffer ...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  	/*
  	 * The only way the dquot is already flush locked by the time quotacheck
  	 * gets here is if reclaim flushed it before the dqadjust walk dirtied
  	 * it for the final time. Quotacheck collects all dquot bufs in the
  	 * local delwri queue before dquots are dirtied, so reclaim can't have
  	 * possibly queued it for I/O. The only way out is to push the buffer to
  	 * cycle the flush lock.
  	 */
  	if (!xfs_dqflock_nowait(dqp)) {
  		/* buf is pinned in-core by delwri list */
8925a3dc4   Dave Chinner   xfs: make xfs_buf...
1197
1198
  		bp = xfs_buf_incore(mp->m_ddev_targp, dqp->q_blkno,
  				mp->m_quotainfo->qi_dqchunklen, 0);
7912e7fef   Brian Foster   xfs: push buffer ...
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
  		if (!bp) {
  			error = -EINVAL;
  			goto out_unlock;
  		}
  		xfs_buf_unlock(bp);
  
  		xfs_buf_delwri_pushbuf(bp, buffer_list);
  		xfs_buf_rele(bp);
  
  		error = -EAGAIN;
  		goto out_unlock;
  	}
fe7257fd4   Christoph Hellwig   xfs: do not write...
1211
1212
1213
  	error = xfs_qm_dqflush(dqp, &bp);
  	if (error)
  		goto out_unlock;
b84a3a967   Christoph Hellwig   xfs: remove the p...
1214

43ff2122e   Christoph Hellwig   xfs: on-stack del...
1215
  	xfs_buf_delwri_queue(bp, buffer_list);
fe7257fd4   Christoph Hellwig   xfs: do not write...
1216
  	xfs_buf_relse(bp);
b84a3a967   Christoph Hellwig   xfs: remove the p...
1217
1218
1219
1220
  out_unlock:
  	xfs_dqunlock(dqp);
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
1223
1224
  /*
   * Walk thru all the filesystem inodes and construct a consistent view
   * of the disk quota world. If the quotacheck fails, disable quotas.
   */
eb866bbf0   Jie Liu   xfs: mark xfs_qm_...
1225
  STATIC int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
1228
  xfs_qm_quotacheck(
  	xfs_mount_t	*mp)
  {
ebd126a65   Darrick J. Wong   xfs: convert quot...
1229
  	int			error, error2;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1230
1231
1232
1233
  	uint			flags;
  	LIST_HEAD		(buffer_list);
  	struct xfs_inode	*uip = mp->m_quotainfo->qi_uquotaip;
  	struct xfs_inode	*gip = mp->m_quotainfo->qi_gquotaip;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1234
  	struct xfs_inode	*pip = mp->m_quotainfo->qi_pquotaip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  	flags = 0;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1237
  	ASSERT(uip || gip || pip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
0b932cccb   Dave Chinner   xfs: Convert rema...
1239
  	xfs_notice(mp, "Quotacheck needed: Please wait.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
1241
  
  	/*
c8ad20ffe   Nathan Scott   [XFS] Add support...
1242
  	 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
  	 * their counters to zero. We need a clean slate.
  	 * We don't log our changes till later.
  	 */
8a7b8a89a   Christoph Hellwig   xfs: access quota...
1246
  	if (uip) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1247
  		error = xfs_qm_reset_dqcounts_buf(mp, uip, XFS_DQTYPE_USER,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1248
  					 &buffer_list);
8a7b8a89a   Christoph Hellwig   xfs: access quota...
1249
  		if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
1251
1252
  			goto error_return;
  		flags |= XFS_UQUOTA_CHKD;
  	}
8a7b8a89a   Christoph Hellwig   xfs: access quota...
1253
  	if (gip) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1254
  		error = xfs_qm_reset_dqcounts_buf(mp, gip, XFS_DQTYPE_GROUP,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1255
  					 &buffer_list);
8a7b8a89a   Christoph Hellwig   xfs: access quota...
1256
  		if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
  			goto error_return;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1258
1259
1260
1261
  		flags |= XFS_GQUOTA_CHKD;
  	}
  
  	if (pip) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1262
  		error = xfs_qm_reset_dqcounts_buf(mp, pip, XFS_DQTYPE_PROJ,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1263
1264
1265
1266
  					 &buffer_list);
  		if (error)
  			goto error_return;
  		flags |= XFS_PQUOTA_CHKD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
  	}
13d59a2a6   Darrick J. Wong   xfs: specify AG i...
1268
1269
  	error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
  			NULL);
ebd126a65   Darrick J. Wong   xfs: convert quot...
1270
1271
  	if (error)
  		goto error_return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
  
  	/*
b84a3a967   Christoph Hellwig   xfs: remove the p...
1274
1275
  	 * We've made all the changes that we need to make incore.  Flush them
  	 * down to disk buffers if everything was updated successfully.
4b8879df8   David Chinner   [XFS] Propagate x...
1276
  	 */
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1277
  	if (XFS_IS_UQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1278
  		error = xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_flush_one,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1279
1280
  					  &buffer_list);
  	}
b84a3a967   Christoph Hellwig   xfs: remove the p...
1281
  	if (XFS_IS_GQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1282
  		error2 = xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_flush_one,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1283
  					   &buffer_list);
b84a3a967   Christoph Hellwig   xfs: remove the p...
1284
1285
1286
1287
  		if (!error)
  			error = error2;
  	}
  	if (XFS_IS_PQUOTA_ON(mp)) {
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1288
  		error2 = xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_flush_one,
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1289
  					   &buffer_list);
b84a3a967   Christoph Hellwig   xfs: remove the p...
1290
1291
1292
  		if (!error)
  			error = error2;
  	}
4b8879df8   David Chinner   [XFS] Propagate x...
1293

43ff2122e   Christoph Hellwig   xfs: on-stack del...
1294
1295
1296
  	error2 = xfs_buf_delwri_submit(&buffer_list);
  	if (!error)
  		error = error2;
4b8879df8   David Chinner   [XFS] Propagate x...
1297
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
1299
1300
1301
1302
1303
1304
  	 * We can get this error if we couldn't do a dquot allocation inside
  	 * xfs_qm_dqusage_adjust (via bulkstat). We don't care about the
  	 * dirty dquots that might be cached, we just want to get rid of them
  	 * and turn quotaoff. The dquots won't be attached to any of the inodes
  	 * at this point (because we intentionally didn't in dqget_noattach).
  	 */
  	if (error) {
8112e9dc6   Christoph Hellwig   xfs: removed unus...
1305
  		xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
1307
  		goto error_return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
  	 * If one type of quotas is off, then it will lose its
  	 * quotachecked status, since we won't be doing accounting for
  	 * that type anymore.
  	 */
4177af3a8   Chandra Seetharaman   Define new macro ...
1314
  	mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  	mp->m_qflags |= flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
   error_return:
20e8a0637   Brian Foster   xfs: fix up quota...
1317
  	xfs_buf_delwri_cancel(&buffer_list);
43ff2122e   Christoph Hellwig   xfs: on-stack del...
1318

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1320
1321
1322
  		xfs_warn(mp,
  	"Quotacheck: Unsuccessful (Error %d): Disabling quotas.",
  			error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
1326
  		/*
  		 * We must turn off quotas.
  		 */
  		ASSERT(mp->m_quotainfo != NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
  		xfs_qm_destroy_quotainfo(mp);
31d5577b3   David Chinner   [XFS] Catch error...
1328
  		if (xfs_mount_reset_sbqflags(mp)) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1329
1330
  			xfs_warn(mp,
  				"Quotacheck: Failed to reset quota flags.");
31d5577b3   David Chinner   [XFS] Catch error...
1331
  		}
0b932cccb   Dave Chinner   xfs: Convert rema...
1332
1333
  	} else
  		xfs_notice(mp, "Quotacheck: Done.");
d99831ff3   Eric Sandeen   xfs: return is no...
1334
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
  }
  
  /*
eb866bbf0   Jie Liu   xfs: mark xfs_qm_...
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
   * This is called from xfs_mountfs to start quotas and initialize all
   * necessary data structures like quotainfo.  This is also responsible for
   * running a quotacheck as necessary.  We are guaranteed that the superblock
   * is consistently read in at this point.
   *
   * If we fail here, the mount will continue with quota turned off. We don't
   * need to inidicate success or failure at all.
   */
  void
  xfs_qm_mount_quotas(
  	struct xfs_mount	*mp)
  {
  	int			error = 0;
  	uint			sbf;
  
  	/*
  	 * If quotas on realtime volumes is not supported, we disable
  	 * quotas immediately.
  	 */
  	if (mp->m_sb.sb_rextents) {
  		xfs_notice(mp, "Cannot turn on quotas for realtime filesystem");
  		mp->m_qflags = 0;
  		goto write_changes;
  	}
  
  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
  
  	/*
  	 * Allocate the quotainfo structure inside the mount struct, and
  	 * create quotainode(s), and change/rev superblock if necessary.
  	 */
  	error = xfs_qm_init_quotainfo(mp);
  	if (error) {
  		/*
  		 * We must turn off quotas.
  		 */
  		ASSERT(mp->m_quotainfo == NULL);
  		mp->m_qflags = 0;
  		goto write_changes;
  	}
  	/*
  	 * If any of the quotas are not consistent, do a quotacheck.
  	 */
  	if (XFS_QM_NEED_QUOTACHECK(mp)) {
  		error = xfs_qm_quotacheck(mp);
  		if (error) {
  			/* Quotacheck failed and disabled quotas. */
  			return;
  		}
  	}
  	/*
  	 * If one type of quotas is off, then it will lose its
  	 * quotachecked status, since we won't be doing accounting for
  	 * that type anymore.
  	 */
  	if (!XFS_IS_UQUOTA_ON(mp))
  		mp->m_qflags &= ~XFS_UQUOTA_CHKD;
  	if (!XFS_IS_GQUOTA_ON(mp))
  		mp->m_qflags &= ~XFS_GQUOTA_CHKD;
  	if (!XFS_IS_PQUOTA_ON(mp))
  		mp->m_qflags &= ~XFS_PQUOTA_CHKD;
  
   write_changes:
  	/*
  	 * We actually don't have to acquire the m_sb_lock at all.
  	 * This can only be called from mount, and that's single threaded. XXX
  	 */
  	spin_lock(&mp->m_sb_lock);
  	sbf = mp->m_sb.sb_qflags;
  	mp->m_sb.sb_qflags = mp->m_qflags & XFS_MOUNT_QUOTA_ALL;
  	spin_unlock(&mp->m_sb_lock);
  
  	if (sbf != (mp->m_qflags & XFS_MOUNT_QUOTA_ALL)) {
61e63ecb5   Dave Chinner   xfs: consolidate ...
1411
  		if (xfs_sync_sb(mp, false)) {
eb866bbf0   Jie Liu   xfs: mark xfs_qm_...
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
  			/*
  			 * We could only have been turning quotas off.
  			 * We aren't in very good shape actually because
  			 * the incore structures are convinced that quotas are
  			 * off, but the on disk superblock doesn't know that !
  			 */
  			ASSERT(!(XFS_IS_QUOTA_RUNNING(mp)));
  			xfs_alert(mp, "%s: Superblock update failed!",
  				__func__);
  		}
  	}
  
  	if (error) {
  		xfs_warn(mp, "Failed to initialize disk quotas.");
  		return;
  	}
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
1433
1434
1435
1436
1437
   * This is called after the superblock has been read in and we're ready to
   * iget the quota inodes.
   */
  STATIC int
  xfs_qm_init_quotainos(
  	xfs_mount_t	*mp)
  {
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1438
1439
  	struct xfs_inode	*uip = NULL;
  	struct xfs_inode	*gip = NULL;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1440
  	struct xfs_inode	*pip = NULL;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1441
  	int			error;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1442
  	uint			flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
  
  	ASSERT(mp->m_quotainfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
1446
1447
1448
  
  	/*
  	 * Get the uquota and gquota inodes
  	 */
621187099   Eric Sandeen   [XFS] remove shou...
1449
  	if (xfs_sb_version_hasquota(&mp->m_sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
1452
  		if (XFS_IS_UQUOTA_ON(mp) &&
  		    mp->m_sb.sb_uquotino != NULLFSINO) {
  			ASSERT(mp->m_sb.sb_uquotino > 0);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1453
1454
1455
  			error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
  					     0, 0, &uip);
  			if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
1456
  				return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  		}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1458
  		if (XFS_IS_GQUOTA_ON(mp) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
  		    mp->m_sb.sb_gquotino != NULLFSINO) {
  			ASSERT(mp->m_sb.sb_gquotino > 0);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1461
1462
1463
1464
  			error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
  					     0, 0, &gip);
  			if (error)
  				goto error_rele;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
  		}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1466
  		if (XFS_IS_PQUOTA_ON(mp) &&
d892d5864   Chandra Seetharaman   xfs: Start using ...
1467
1468
1469
  		    mp->m_sb.sb_pquotino != NULLFSINO) {
  			ASSERT(mp->m_sb.sb_pquotino > 0);
  			error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1470
1471
1472
1473
  					     0, 0, &pip);
  			if (error)
  				goto error_rele;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
  	} else {
  		flags |= XFS_QMOPT_SBVERSION;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
1478
  	}
  
  	/*
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1479
  	 * Create the three inodes, if they don't exist already. The changes
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
1482
1483
1484
  	 * made above will get added to a transaction and logged in one of
  	 * the qino_alloc calls below.  If the device is readonly,
  	 * temporarily switch to read-write to do this.
  	 */
  	if (XFS_IS_UQUOTA_ON(mp) && uip == NULL) {
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1485
  		error = xfs_qm_qino_alloc(mp, &uip,
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1486
1487
1488
  					      flags | XFS_QMOPT_UQUOTA);
  		if (error)
  			goto error_rele;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
1490
1491
  
  		flags &= ~XFS_QMOPT_SBVERSION;
  	}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1492
  	if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
c8ad20ffe   Nathan Scott   [XFS] Add support...
1493
  		error = xfs_qm_qino_alloc(mp, &gip,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1494
1495
1496
1497
1498
1499
1500
  					  flags | XFS_QMOPT_GQUOTA);
  		if (error)
  			goto error_rele;
  
  		flags &= ~XFS_QMOPT_SBVERSION;
  	}
  	if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1501
  		error = xfs_qm_qino_alloc(mp, &pip,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1502
  					  flags | XFS_QMOPT_PQUOTA);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1503
1504
  		if (error)
  			goto error_rele;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
  	}
8a7b8a89a   Christoph Hellwig   xfs: access quota...
1506
1507
  	mp->m_quotainfo->qi_uquotaip = uip;
  	mp->m_quotainfo->qi_gquotaip = gip;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1508
  	mp->m_quotainfo->qi_pquotaip = pip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509

014c2544e   Jesper Juhl   return statement ...
1510
  	return 0;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1511
1512
1513
  
  error_rele:
  	if (uip)
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1514
  		xfs_irele(uip);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1515
  	if (gip)
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1516
  		xfs_irele(gip);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1517
  	if (pip)
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1518
  		xfs_irele(pip);
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
1519
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520
  }
92b2e5b31   Christoph Hellwig   xfs: use a normal...
1521
  STATIC void
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
1522
  xfs_qm_destroy_quotainos(
c072fbefe   Pavel Reichl   xfs: remove the x...
1523
  	struct xfs_quotainfo	*qi)
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
1524
1525
  {
  	if (qi->qi_uquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1526
  		xfs_irele(qi->qi_uquotaip);
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
1527
1528
1529
  		qi->qi_uquotaip = NULL; /* paranoia */
  	}
  	if (qi->qi_gquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1530
  		xfs_irele(qi->qi_gquotaip);
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
1531
1532
1533
  		qi->qi_gquotaip = NULL;
  	}
  	if (qi->qi_pquotaip) {
44a8736bd   Darrick J. Wong   xfs: clean up IRE...
1534
  		xfs_irele(qi->qi_pquotaip);
3a3882ff2   Aliaksei Karaliou   xfs: quota: check...
1535
1536
1537
1538
1539
  		qi->qi_pquotaip = NULL;
  	}
  }
  
  STATIC void
92b2e5b31   Christoph Hellwig   xfs: use a normal...
1540
1541
1542
1543
1544
  xfs_qm_dqfree_one(
  	struct xfs_dquot	*dqp)
  {
  	struct xfs_mount	*mp = dqp->q_mount;
  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545

9f920f116   Christoph Hellwig   xfs: use per-file...
1546
  	mutex_lock(&qi->qi_tree_lock);
51dbb1be5   Darrick J. Wong   xfs: remove qcore...
1547
  	radix_tree_delete(xfs_dquot_tree(qi, xfs_dquot_type(dqp)), dqp->q_id);
368e13617   Dave Chinner   xfs: remove dupli...
1548

92b2e5b31   Christoph Hellwig   xfs: use a normal...
1549
  	qi->qi_dquots--;
b84a3a967   Christoph Hellwig   xfs: remove the p...
1550
  	mutex_unlock(&qi->qi_tree_lock);
92b2e5b31   Christoph Hellwig   xfs: use a normal...
1551
1552
1553
  
  	xfs_qm_dqdestroy(dqp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
1555
1556
1557
  /* --------------- utility functions for vnodeops ---------------- */
  
  
  /*
6c77b0ea1   Christoph Hellwig   xfs: remove xfs_c...
1558
   * Given an inode, a uid, gid and prid make sure that we have
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
   * allocated relevant dquot(s) on disk, and that we won't exceed inode
   * quotas by creating this file.
   * This also attaches dquot(s) to the given inode after locking it,
   * and returns the dquots corresponding to the uid and/or gid.
   *
   * in	: inode (unlocked)
   * out	: udquot, gdquot with references taken and unlocked
   */
  int
  xfs_qm_vop_dqalloc(
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1569
  	struct xfs_inode	*ip,
542951592   Christoph Hellwig   xfs: remove the i...
1570
1571
  	kuid_t			uid,
  	kgid_t			gid,
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1572
1573
1574
  	prid_t			prid,
  	uint			flags,
  	struct xfs_dquot	**O_udqpp,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1575
1576
  	struct xfs_dquot	**O_gdqpp,
  	struct xfs_dquot	**O_pdqpp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  {
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1578
  	struct xfs_mount	*mp = ip->i_mount;
542951592   Christoph Hellwig   xfs: remove the i...
1579
  	struct inode		*inode = VFS_I(ip);
ba8adad5d   Christoph Hellwig   xfs: remove the k...
1580
  	struct user_namespace	*user_ns = inode->i_sb->s_user_ns;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1581
1582
  	struct xfs_dquot	*uq = NULL;
  	struct xfs_dquot	*gq = NULL;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1583
  	struct xfs_dquot	*pq = NULL;
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1584
1585
  	int			error;
  	uint			lockflags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1587
  	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1588
1589
1590
1591
  		return 0;
  
  	lockflags = XFS_ILOCK_EXCL;
  	xfs_ilock(ip, lockflags);
bd186aa90   Christoph Hellwig   [XFS] kill the vf...
1592
  	if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
542951592   Christoph Hellwig   xfs: remove the i...
1593
  		gid = inode->i_gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
1595
1596
1597
1598
1599
  
  	/*
  	 * Attach the dquot(s) to this inode, doing a dquot allocation
  	 * if necessary. The dquot(s) will not be locked.
  	 */
  	if (XFS_NOT_DQATTACHED(mp, ip)) {
4882c19d2   Darrick J. Wong   xfs: split out dq...
1600
  		error = xfs_qm_dqattach_locked(ip, true);
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1601
  		if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
  			xfs_iunlock(ip, lockflags);
014c2544e   Jesper Juhl   return statement ...
1603
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
1605
  		}
  	}
c8ad20ffe   Nathan Scott   [XFS] Add support...
1606
  	if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
97611f936   Kaixu Xia   xfs: do the ASSER...
1607
  		ASSERT(O_udqpp);
542951592   Christoph Hellwig   xfs: remove the i...
1608
  		if (!uid_eq(inode->i_uid, uid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
  			/*
  			 * What we need is the dquot that has this uid, and
  			 * if we send the inode to dqget, the uid of the inode
  			 * takes priority over what's sent in the uid argument.
  			 * We must unlock inode here before calling dqget if
  			 * we're not sending the inode, because otherwise
  			 * we'll deadlock by doing trans_reserve while
  			 * holding ilock.
  			 */
  			xfs_iunlock(ip, lockflags);
ba8adad5d   Christoph Hellwig   xfs: remove the k...
1619
  			error = xfs_qm_dqget(mp, from_kuid(user_ns, uid),
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1620
  					XFS_DQTYPE_USER, true, &uq);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1621
  			if (error) {
2451337dd   Dave Chinner   xfs: global error...
1622
  				ASSERT(error != -ENOENT);
014c2544e   Jesper Juhl   return statement ...
1623
  				return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
  			}
  			/*
  			 * Get the ilock in the right order.
  			 */
  			xfs_dqunlock(uq);
  			lockflags = XFS_ILOCK_SHARED;
  			xfs_ilock(ip, lockflags);
  		} else {
  			/*
  			 * Take an extra reference, because we'll return
  			 * this to caller
  			 */
  			ASSERT(ip->i_udquot);
78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1637
  			uq = xfs_qm_dqhold(ip->i_udquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
1639
  		}
  	}
c8ad20ffe   Nathan Scott   [XFS] Add support...
1640
  	if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
97611f936   Kaixu Xia   xfs: do the ASSER...
1641
  		ASSERT(O_gdqpp);
542951592   Christoph Hellwig   xfs: remove the i...
1642
  		if (!gid_eq(inode->i_gid, gid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
  			xfs_iunlock(ip, lockflags);
ba8adad5d   Christoph Hellwig   xfs: remove the k...
1644
  			error = xfs_qm_dqget(mp, from_kgid(user_ns, gid),
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1645
  					XFS_DQTYPE_GROUP, true, &gq);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1646
  			if (error) {
2451337dd   Dave Chinner   xfs: global error...
1647
  				ASSERT(error != -ENOENT);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1648
  				goto error_rele;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
1650
1651
1652
1653
1654
  			}
  			xfs_dqunlock(gq);
  			lockflags = XFS_ILOCK_SHARED;
  			xfs_ilock(ip, lockflags);
  		} else {
  			ASSERT(ip->i_gdquot);
78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1655
  			gq = xfs_qm_dqhold(ip->i_gdquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
  		}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1657
1658
  	}
  	if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
97611f936   Kaixu Xia   xfs: do the ASSER...
1659
  		ASSERT(O_pdqpp);
de7a866fd   Christoph Hellwig   xfs: merge the pr...
1660
  		if (ip->i_d.di_projid != prid) {
c8ad20ffe   Nathan Scott   [XFS] Add support...
1661
  			xfs_iunlock(ip, lockflags);
5aff6750d   Kaixu Xia   xfs: remove the u...
1662
  			error = xfs_qm_dqget(mp, prid,
8cd4901da   Darrick J. Wong   xfs: rename XFS_D...
1663
  					XFS_DQTYPE_PROJ, true, &pq);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1664
  			if (error) {
2451337dd   Dave Chinner   xfs: global error...
1665
  				ASSERT(error != -ENOENT);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1666
  				goto error_rele;
c8ad20ffe   Nathan Scott   [XFS] Add support...
1667
  			}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1668
  			xfs_dqunlock(pq);
c8ad20ffe   Nathan Scott   [XFS] Add support...
1669
1670
1671
  			lockflags = XFS_ILOCK_SHARED;
  			xfs_ilock(ip, lockflags);
  		} else {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1672
1673
  			ASSERT(ip->i_pdquot);
  			pq = xfs_qm_dqhold(ip->i_pdquot);
c8ad20ffe   Nathan Scott   [XFS] Add support...
1674
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
  	}
c140735bb   Kaixu Xia   xfs: trace quota ...
1676
  	trace_xfs_dquot_dqalloc(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
1678
1679
1680
  
  	xfs_iunlock(ip, lockflags);
  	if (O_udqpp)
  		*O_udqpp = uq;
d2a5e3c6f   Markus Elfring   xfs: remove unnec...
1681
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
1684
  		xfs_qm_dqrele(uq);
  	if (O_gdqpp)
  		*O_gdqpp = gq;
d2a5e3c6f   Markus Elfring   xfs: remove unnec...
1685
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
  		xfs_qm_dqrele(gq);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1687
1688
  	if (O_pdqpp)
  		*O_pdqpp = pq;
d2a5e3c6f   Markus Elfring   xfs: remove unnec...
1689
  	else
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1690
  		xfs_qm_dqrele(pq);
014c2544e   Jesper Juhl   return statement ...
1691
  	return 0;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1692
1693
  
  error_rele:
d2a5e3c6f   Markus Elfring   xfs: remove unnec...
1694
1695
  	xfs_qm_dqrele(gq);
  	xfs_qm_dqrele(uq);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1696
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697
1698
1699
1700
1701
1702
  }
  
  /*
   * Actually transfer ownership, and do dquot modifications.
   * These were already reserved.
   */
aefe69a45   Pavel Reichl   xfs: remove the x...
1703
  struct xfs_dquot *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1704
  xfs_qm_vop_chown(
aefe69a45   Pavel Reichl   xfs: remove the x...
1705
1706
1707
1708
  	struct xfs_trans	*tp,
  	struct xfs_inode	*ip,
  	struct xfs_dquot	**IO_olddq,
  	struct xfs_dquot	*newdq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
  {
aefe69a45   Pavel Reichl   xfs: remove the x...
1710
  	struct xfs_dquot	*prevdq;
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
1711
1712
  	uint		bfield = XFS_IS_REALTIME_INODE(ip) ?
  				 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1713

579aa9caf   Christoph Hellwig   [XFS] shrink mrlo...
1714
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1715
1716
1717
1718
1719
1720
  	ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
  
  	/* old dquot */
  	prevdq = *IO_olddq;
  	ASSERT(prevdq);
  	ASSERT(prevdq != newdq);
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
1721
1722
  	xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
  	xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
  
  	/* the sparkling new dquot */
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
1725
1726
  	xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
  	xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
1728
  
  	/*
78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1729
1730
  	 * Take an extra reference, because the inode is going to keep
  	 * this dquot pointer even after the trans_commit.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
  	 */
78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1732
  	*IO_olddq = xfs_qm_dqhold(newdq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1733

014c2544e   Jesper Juhl   return statement ...
1734
  	return prevdq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1735
1736
1737
  }
  
  /*
c8ad20ffe   Nathan Scott   [XFS] Add support...
1738
   * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739
1740
1741
   */
  int
  xfs_qm_vop_chown_reserve(
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1742
1743
1744
1745
  	struct xfs_trans	*tp,
  	struct xfs_inode	*ip,
  	struct xfs_dquot	*udqp,
  	struct xfs_dquot	*gdqp,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1746
  	struct xfs_dquot	*pdqp,
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1747
  	uint			flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
  {
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1749
  	struct xfs_mount	*mp = ip->i_mount;
394aafdc1   Darrick J. Wong   xfs: widen inode ...
1750
  	uint64_t		delblks;
dcf1ccc99   Eric Sandeen   xfs: always retur...
1751
  	unsigned int		blkflags;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1752
1753
  	struct xfs_dquot	*udq_unres = NULL;
  	struct xfs_dquot	*gdq_unres = NULL;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1754
  	struct xfs_dquot	*pdq_unres = NULL;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1755
1756
  	struct xfs_dquot	*udq_delblks = NULL;
  	struct xfs_dquot	*gdq_delblks = NULL;
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1757
  	struct xfs_dquot	*pdq_delblks = NULL;
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1758
  	int			error;
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1759

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760

579aa9caf   Christoph Hellwig   [XFS] shrink mrlo...
1761
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1762
1763
1764
  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
  
  	delblks = ip->i_delayed_blks;
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
1765
1766
  	blkflags = XFS_IS_REALTIME_INODE(ip) ?
  			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
1768
  
  	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
c51df7334   Darrick J. Wong   xfs: stop using q...
1769
  	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1770
  		udq_delblks = udqp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771
1772
1773
1774
1775
1776
1777
  		/*
  		 * If there are delayed allocation blocks, then we have to
  		 * unreserve those from the old dquot, and add them to the
  		 * new dquot.
  		 */
  		if (delblks) {
  			ASSERT(ip->i_udquot);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1778
  			udq_unres = ip->i_udquot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779
1780
  		}
  	}
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1781
  	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
c51df7334   Darrick J. Wong   xfs: stop using q...
1782
  	    i_gid_read(VFS_I(ip)) != gdqp->q_id) {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1783
1784
1785
1786
1787
1788
1789
1790
  		gdq_delblks = gdqp;
  		if (delblks) {
  			ASSERT(ip->i_gdquot);
  			gdq_unres = ip->i_gdquot;
  		}
  	}
  
  	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
c51df7334   Darrick J. Wong   xfs: stop using q...
1791
  	    ip->i_d.di_projid != pdqp->q_id) {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1792
1793
1794
1795
  		pdq_delblks = pdqp;
  		if (delblks) {
  			ASSERT(ip->i_pdquot);
  			pdq_unres = ip->i_pdquot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796
1797
  		}
  	}
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1798
  	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1799
  				udq_delblks, gdq_delblks, pdq_delblks,
dcf1ccc99   Eric Sandeen   xfs: always retur...
1800
  				ip->i_d.di_nblocks, 1, flags | blkflags);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1801
1802
  	if (error)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
  
  	/*
  	 * Do the delayed blks reservations/unreservations now. Since, these
  	 * are done without the help of a transaction, if a reservation fails
  	 * its previous reservations won't be automatically undone by trans
  	 * code. So, we have to do it manually here.
  	 */
  	if (delblks) {
  		/*
  		 * Do the reservations first. Unreservation can't fail.
  		 */
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1814
1815
  		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
  		ASSERT(udq_unres || gdq_unres || pdq_unres);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1816
  		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1817
  			    udq_delblks, gdq_delblks, pdq_delblks,
dcf1ccc99   Eric Sandeen   xfs: always retur...
1818
  			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
113a56835   Chandra Seetharaman   xfs: Code cleanup...
1819
1820
  		if (error)
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
  		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1822
1823
  				udq_unres, gdq_unres, pdq_unres,
  				-((xfs_qcnt_t)delblks), 0, blkflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824
  	}
d99831ff3   Eric Sandeen   xfs: return is no...
1825
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
1827
1828
1829
  }
  
  int
  xfs_qm_vop_rename_dqattach(
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1830
  	struct xfs_inode	**i_tab)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
  {
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1832
1833
  	struct xfs_mount	*mp = i_tab[0]->i_mount;
  	int			i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1835
  	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
014c2544e   Jesper Juhl   return statement ...
1836
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1838
1839
1840
  	for (i = 0; (i < 4 && i_tab[i]); i++) {
  		struct xfs_inode	*ip = i_tab[i];
  		int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
1842
1843
  		/*
  		 * Watch out for duplicate entries in the table.
  		 */
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1844
1845
  		if (i == 0 || ip != i_tab[i-1]) {
  			if (XFS_NOT_DQATTACHED(mp, ip)) {
c14cfccab   Darrick J. Wong   xfs: remove unnec...
1846
  				error = xfs_qm_dqattach(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
  				if (error)
014c2544e   Jesper Juhl   return statement ...
1848
  					return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
1850
1851
  			}
  		}
  	}
014c2544e   Jesper Juhl   return statement ...
1852
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
1854
1855
  }
  
  void
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1856
1857
1858
1859
  xfs_qm_vop_create_dqattach(
  	struct xfs_trans	*tp,
  	struct xfs_inode	*ip,
  	struct xfs_dquot	*udqp,
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1860
1861
  	struct xfs_dquot	*gdqp,
  	struct xfs_dquot	*pdqp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
  {
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1863
1864
1865
  	struct xfs_mount	*mp = tp->t_mountp;
  
  	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
  		return;
579aa9caf   Christoph Hellwig   [XFS] shrink mrlo...
1867
  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868

37eb9706e   Jie Liu   xfs: fix false as...
1869
  	if (udqp && XFS_IS_UQUOTA_ON(mp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  		ASSERT(ip->i_udquot == NULL);
c51df7334   Darrick J. Wong   xfs: stop using q...
1871
  		ASSERT(i_uid_read(VFS_I(ip)) == udqp->q_id);
78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1872
1873
  
  		ip->i_udquot = xfs_qm_dqhold(udqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
  		xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
  	}
37eb9706e   Jie Liu   xfs: fix false as...
1876
  	if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877
  		ASSERT(ip->i_gdquot == NULL);
c51df7334   Darrick J. Wong   xfs: stop using q...
1878
  		ASSERT(i_gid_read(VFS_I(ip)) == gdqp->q_id);
542951592   Christoph Hellwig   xfs: remove the i...
1879

78e55892d   Christoph Hellwig   xfs: add a xfs_dq...
1880
  		ip->i_gdquot = xfs_qm_dqhold(gdqp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
1882
  		xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
  	}
37eb9706e   Jie Liu   xfs: fix false as...
1883
  	if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1884
  		ASSERT(ip->i_pdquot == NULL);
c51df7334   Darrick J. Wong   xfs: stop using q...
1885
  		ASSERT(ip->i_d.di_projid == pdqp->q_id);
92f8ff73f   Chandra Seetharaman   xfs: Add pquota f...
1886
1887
1888
1889
  
  		ip->i_pdquot = xfs_qm_dqhold(pdqp);
  		xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
  }