]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.suse/ocfs2-Add-quota-calls-for-allocation-and-freeing-of.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / ocfs2-Add-quota-calls-for-allocation-and-freeing-of.patch
1 From: Jan Kara <jack@suse.cz>
2 References: fate#302681
3 Subject: [PATCH 25/28] ocfs2: Add quota calls for allocation and freeing of inodes and space
4 Patch-mainline: 2.6.29?
5
6 Add quota calls for allocation and freeing of inodes and space, also update
7 estimates on number of needed credits for a transaction. Move out inode
8 allocation from ocfs2_mknod_locked() because vfs_dq_init() must be called
9 outside of a transaction.
10
11 Signed-off-by: Jan Kara <jack@suse.cz>
12 ---
13 fs/ocfs2/alloc.c | 20 +++++++++-
14 fs/ocfs2/aops.c | 16 ++++++--
15 fs/ocfs2/dir.c | 24 +++++++++++-
16 fs/ocfs2/file.c | 68 +++++++++++++++++++++++++++++++++---
17 fs/ocfs2/inode.c | 10 ++++-
18 fs/ocfs2/journal.h | 99 ++++++++++++++++++++++++++++++++++++-----------------
19 fs/ocfs2/namei.c | 44 +++++++++++++++++++++--
20 fs/ocfs2/xattr.c | 12 +++---
21 8 files changed, 239 insertions(+), 54 deletions(-)
22
23 --- a/fs/ocfs2/alloc.c
24 +++ b/fs/ocfs2/alloc.c
25 @@ -28,6 +28,7 @@
26 #include <linux/slab.h>
27 #include <linux/highmem.h>
28 #include <linux/swap.h>
29 +#include <linux/quotaops.h>
30
31 #define MLOG_MASK_PREFIX ML_DISK_ALLOC
32 #include <cluster/masklog.h>
33 @@ -5292,7 +5293,7 @@ int ocfs2_remove_btree_range(struct inod
34 }
35 }
36
37 - handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
38 + handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
39 if (IS_ERR(handle)) {
40 ret = PTR_ERR(handle);
41 mlog_errno(ret);
42 @@ -6523,6 +6524,8 @@ static int ocfs2_do_truncate(struct ocfs
43 goto bail;
44 }
45
46 + vfs_dq_free_space_nodirty(inode,
47 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
48 spin_lock(&OCFS2_I(inode)->ip_lock);
49 OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
50 clusters_to_del;
51 @@ -6836,6 +6839,7 @@ int ocfs2_convert_inline_data_to_extents
52 struct page **pages = NULL;
53 loff_t end = osb->s_clustersize;
54 struct ocfs2_extent_tree et;
55 + int did_quota = 0;
56
57 has_data = i_size_read(inode) ? 1 : 0;
58
59 @@ -6855,7 +6859,8 @@ int ocfs2_convert_inline_data_to_extents
60 }
61 }
62
63 - handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS);
64 + handle = ocfs2_start_trans(osb,
65 + ocfs2_inline_to_extents_credits(osb->sb));
66 if (IS_ERR(handle)) {
67 ret = PTR_ERR(handle);
68 mlog_errno(ret);
69 @@ -6874,6 +6879,13 @@ int ocfs2_convert_inline_data_to_extents
70 unsigned int page_end;
71 u64 phys;
72
73 + if (vfs_dq_alloc_space_nodirty(inode,
74 + ocfs2_clusters_to_bytes(osb->sb, 1))) {
75 + ret = -EDQUOT;
76 + goto out_commit;
77 + }
78 + did_quota = 1;
79 +
80 ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
81 &num);
82 if (ret) {
83 @@ -6947,6 +6959,10 @@ int ocfs2_convert_inline_data_to_extents
84 }
85
86 out_commit:
87 + if (ret < 0 && did_quota)
88 + vfs_dq_free_space_nodirty(inode,
89 + ocfs2_clusters_to_bytes(osb->sb, 1));
90 +
91 ocfs2_commit_trans(osb, handle);
92
93 out_unlock:
94 --- a/fs/ocfs2/aops.c
95 +++ b/fs/ocfs2/aops.c
96 @@ -27,6 +27,7 @@
97 #include <linux/swap.h>
98 #include <linux/pipe_fs_i.h>
99 #include <linux/mpage.h>
100 +#include <linux/quotaops.h>
101
102 #define MLOG_MASK_PREFIX ML_FILE_IO
103 #include <cluster/masklog.h>
104 @@ -1780,6 +1781,11 @@ int ocfs2_write_begin_nolock(struct addr
105
106 wc->w_handle = handle;
107
108 + if (clusters_to_alloc && vfs_dq_alloc_space_nodirty(inode,
109 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc))) {
110 + ret = -EDQUOT;
111 + goto out_commit;
112 + }
113 /*
114 * We don't want this to fail in ocfs2_write_end(), so do it
115 * here.
116 @@ -1788,7 +1794,7 @@ int ocfs2_write_begin_nolock(struct addr
117 OCFS2_JOURNAL_ACCESS_WRITE);
118 if (ret) {
119 mlog_errno(ret);
120 - goto out_commit;
121 + goto out_quota;
122 }
123
124 /*
125 @@ -1800,14 +1806,14 @@ int ocfs2_write_begin_nolock(struct addr
126 cluster_of_pages, mmap_page);
127 if (ret) {
128 mlog_errno(ret);
129 - goto out_commit;
130 + goto out_quota;
131 }
132
133 ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
134 len);
135 if (ret) {
136 mlog_errno(ret);
137 - goto out_commit;
138 + goto out_quota;
139 }
140
141 if (data_ac)
142 @@ -1819,6 +1825,10 @@ success:
143 *pagep = wc->w_target_page;
144 *fsdata = wc;
145 return 0;
146 +out_quota:
147 + if (clusters_to_alloc)
148 + vfs_dq_free_space(inode,
149 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
150 out_commit:
151 ocfs2_commit_trans(osb, handle);
152
153 --- a/fs/ocfs2/dir.c
154 +++ b/fs/ocfs2/dir.c
155 @@ -40,6 +40,7 @@
156 #include <linux/types.h>
157 #include <linux/slab.h>
158 #include <linux/highmem.h>
159 +#include <linux/quotaops.h>
160
161 #define MLOG_MASK_PREFIX ML_NAMEI
162 #include <cluster/masklog.h>
163 @@ -1216,9 +1217,9 @@ static int ocfs2_expand_inline_dir(struc
164 unsigned int blocks_wanted,
165 struct buffer_head **first_block_bh)
166 {
167 - int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS;
168 u32 alloc, bit_off, len;
169 struct super_block *sb = dir->i_sb;
170 + int ret, credits = ocfs2_inline_to_extents_credits(sb);
171 u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits;
172 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
173 struct ocfs2_inode_info *oi = OCFS2_I(dir);
174 @@ -1227,6 +1228,7 @@ static int ocfs2_expand_inline_dir(struc
175 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
176 handle_t *handle;
177 struct ocfs2_extent_tree et;
178 + int did_quota = 0;
179
180 ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
181
182 @@ -1264,6 +1266,12 @@ static int ocfs2_expand_inline_dir(struc
183 goto out_sem;
184 }
185
186 + if (vfs_dq_alloc_space_nodirty(dir,
187 + ocfs2_clusters_to_bytes(osb->sb, alloc))) {
188 + ret = -EDQUOT;
189 + goto out_commit;
190 + }
191 + did_quota = 1;
192 /*
193 * Try to claim as many clusters as the bitmap can give though
194 * if we only get one now, that's enough to continue. The rest
195 @@ -1386,6 +1394,9 @@ static int ocfs2_expand_inline_dir(struc
196 dirdata_bh = NULL;
197
198 out_commit:
199 + if (ret < 0 && did_quota)
200 + vfs_dq_free_space_nodirty(dir,
201 + ocfs2_clusters_to_bytes(osb->sb, 2));
202 ocfs2_commit_trans(osb, handle);
203
204 out_sem:
205 @@ -1410,7 +1421,7 @@ static int ocfs2_do_extend_dir(struct su
206 struct buffer_head **new_bh)
207 {
208 int status;
209 - int extend;
210 + int extend, did_quota = 0;
211 u64 p_blkno, v_blkno;
212
213 spin_lock(&OCFS2_I(dir)->ip_lock);
214 @@ -1420,6 +1431,13 @@ static int ocfs2_do_extend_dir(struct su
215 if (extend) {
216 u32 offset = OCFS2_I(dir)->ip_clusters;
217
218 + if (vfs_dq_alloc_space_nodirty(dir,
219 + ocfs2_clusters_to_bytes(sb, 1))) {
220 + status = -EDQUOT;
221 + goto bail;
222 + }
223 + did_quota = 1;
224 +
225 status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
226 1, 0, parent_fe_bh, handle,
227 data_ac, meta_ac, NULL);
228 @@ -1445,6 +1463,8 @@ static int ocfs2_do_extend_dir(struct su
229 }
230 status = 0;
231 bail:
232 + if (did_quota && status < 0)
233 + vfs_dq_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
234 mlog_exit(status);
235 return status;
236 }
237 --- a/fs/ocfs2/file.c
238 +++ b/fs/ocfs2/file.c
239 @@ -35,6 +35,7 @@
240 #include <linux/mount.h>
241 #include <linux/writeback.h>
242 #include <linux/falloc.h>
243 +#include <linux/quotaops.h>
244
245 #define MLOG_MASK_PREFIX ML_INODE
246 #include <cluster/masklog.h>
247 @@ -57,6 +58,7 @@
248 #include "super.h"
249 #include "xattr.h"
250 #include "acl.h"
251 +#include "quota.h"
252
253 #include "buffer_head_io.h"
254
255 @@ -537,6 +539,8 @@ static int __ocfs2_extend_allocation(str
256 enum ocfs2_alloc_restarted why;
257 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
258 struct ocfs2_extent_tree et;
259 + u32 total_clusters = clusters_to_add;
260 + int did_quota = 0;
261
262 mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
263
264 @@ -585,6 +589,12 @@ restart_all:
265 goto leave;
266 }
267
268 + if (!did_quota && vfs_dq_alloc_space_nodirty(inode,
269 + ocfs2_clusters_to_bytes(osb->sb, total_clusters))) {
270 + status = -EDQUOT;
271 + goto leave;
272 + }
273 + did_quota = 1;
274 restarted_transaction:
275 /* reserve a write to the file entry early on - that we if we
276 * run out of credits in the allocation path, we can still
277 @@ -655,6 +665,9 @@ restarted_transaction:
278 OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode));
279
280 leave:
281 + if (status < 0 && did_quota)
282 + vfs_dq_free_space(inode,
283 + ocfs2_clusters_to_bytes(osb->sb, total_clusters));
284 if (handle) {
285 ocfs2_commit_trans(osb, handle);
286 handle = NULL;
287 @@ -886,6 +899,9 @@ int ocfs2_setattr(struct dentry *dentry,
288 struct ocfs2_super *osb = OCFS2_SB(sb);
289 struct buffer_head *bh = NULL;
290 handle_t *handle = NULL;
291 + int locked[MAXQUOTAS] = {0, 0};
292 + int credits, qtype;
293 + struct ocfs2_mem_dqinfo *oinfo;
294
295 mlog_entry("(0x%p, '%.*s')\n", dentry,
296 dentry->d_name.len, dentry->d_name.name);
297 @@ -956,11 +972,47 @@ int ocfs2_setattr(struct dentry *dentry,
298 }
299 }
300
301 - handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
302 - if (IS_ERR(handle)) {
303 - status = PTR_ERR(handle);
304 - mlog_errno(status);
305 - goto bail_unlock;
306 + if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
307 + (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
308 + credits = OCFS2_INODE_UPDATE_CREDITS;
309 + if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
310 + && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
311 + OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
312 + oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv;
313 + status = ocfs2_lock_global_qf(oinfo, 1);
314 + if (status < 0)
315 + goto bail_unlock;
316 + credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) +
317 + ocfs2_calc_qdel_credits(sb, USRQUOTA);
318 + locked[USRQUOTA] = 1;
319 + }
320 + if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
321 + && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
322 + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
323 + oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv;
324 + status = ocfs2_lock_global_qf(oinfo, 1);
325 + if (status < 0)
326 + goto bail_unlock;
327 + credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) +
328 + ocfs2_calc_qdel_credits(sb, GRPQUOTA);
329 + locked[GRPQUOTA] = 1;
330 + }
331 + handle = ocfs2_start_trans(osb, credits);
332 + if (IS_ERR(handle)) {
333 + status = PTR_ERR(handle);
334 + mlog_errno(status);
335 + goto bail_unlock;
336 + }
337 + status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
338 + if (status < 0)
339 + goto bail_commit;
340 + } else {
341 + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
342 + if (IS_ERR(handle)) {
343 + status = PTR_ERR(handle);
344 + mlog_errno(status);
345 + goto bail_unlock;
346 + }
347 }
348
349 /*
350 @@ -983,6 +1035,12 @@ int ocfs2_setattr(struct dentry *dentry,
351 bail_commit:
352 ocfs2_commit_trans(osb, handle);
353 bail_unlock:
354 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
355 + if (!locked[qtype])
356 + continue;
357 + oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
358 + ocfs2_unlock_global_qf(oinfo, 1);
359 + }
360 ocfs2_inode_unlock(inode, 1);
361 bail_unlock_rw:
362 if (size_change)
363 --- a/fs/ocfs2/inode.c
364 +++ b/fs/ocfs2/inode.c
365 @@ -28,6 +28,7 @@
366 #include <linux/slab.h>
367 #include <linux/highmem.h>
368 #include <linux/pagemap.h>
369 +#include <linux/quotaops.h>
370
371 #include <asm/byteorder.h>
372
373 @@ -619,7 +620,8 @@ static int ocfs2_remove_inode(struct ino
374 goto bail;
375 }
376
377 - handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS);
378 + handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS +
379 + ocfs2_quota_trans_credits(inode->i_sb));
380 if (IS_ERR(handle)) {
381 status = PTR_ERR(handle);
382 mlog_errno(status);
383 @@ -651,6 +653,7 @@ static int ocfs2_remove_inode(struct ino
384 }
385
386 ocfs2_remove_from_cache(inode, di_bh);
387 + vfs_dq_free_inode(inode);
388
389 status = ocfs2_free_dinode(handle, inode_alloc_inode,
390 inode_alloc_bh, di);
391 @@ -933,7 +936,10 @@ void ocfs2_delete_inode(struct inode *in
392
393 mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
394
395 - if (is_bad_inode(inode)) {
396 + /* When we fail in read_inode() we mark inode as bad. The second test
397 + * catches the case when inode allocation fails before allocating
398 + * a block for inode. */
399 + if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) {
400 mlog(0, "Skipping delete of bad inode\n");
401 goto bail;
402 }
403 --- a/fs/ocfs2/journal.h
404 +++ b/fs/ocfs2/journal.h
405 @@ -293,6 +293,37 @@ int ocfs2_journal_dirty
406 /* extended attribute block update */
407 #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
408
409 +/* global quotafile inode update, data block */
410 +#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
411 +
412 +/*
413 + * The two writes below can accidentally see global info dirty due
414 + * to set_info() quotactl so make them prepared for the writes.
415 + */
416 +/* quota data block, global info */
417 +/* Write to local quota file */
418 +#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
419 +
420 +/* global quota data block, local quota data block, global quota inode,
421 + * global quota info */
422 +#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
423 +
424 +static inline int ocfs2_quota_trans_credits(struct super_block *sb)
425 +{
426 + int credits = 0;
427 +
428 + if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA))
429 + credits += OCFS2_QWRITE_CREDITS;
430 + if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA))
431 + credits += OCFS2_QWRITE_CREDITS;
432 + return credits;
433 +}
434 +
435 +/* Number of credits needed for removing quota structure from file */
436 +int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
437 +/* Number of credits needed for initialization of new quota structure */
438 +int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
439 +
440 /* group extend. inode update and last group update. */
441 #define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
442
443 @@ -303,8 +334,11 @@ int ocfs2_journal_dirty
444 * prev. group desc. if we relink. */
445 #define OCFS2_SUBALLOC_ALLOC (3)
446
447 -#define OCFS2_INLINE_TO_EXTENTS_CREDITS (OCFS2_SUBALLOC_ALLOC \
448 - + OCFS2_INODE_UPDATE_CREDITS)
449 +static inline int ocfs2_inline_to_extents_credits(struct super_block *sb)
450 +{
451 + return OCFS2_SUBALLOC_ALLOC + OCFS2_INODE_UPDATE_CREDITS +
452 + ocfs2_quota_trans_credits(sb);
453 +}
454
455 /* dinode + group descriptor update. We don't relink on free yet. */
456 #define OCFS2_SUBALLOC_FREE (2)
457 @@ -313,16 +347,23 @@ int ocfs2_journal_dirty
458 #define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE \
459 + OCFS2_TRUNCATE_LOG_UPDATE)
460
461 -#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
462 +static inline int ocfs2_remove_extent_credits(struct super_block *sb)
463 +{
464 + return OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS +
465 + ocfs2_quota_trans_credits(sb);
466 +}
467
468 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
469 * bitmap block for the new bit) */
470 #define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
471
472 /* parent fe, parent block, new file entry, inode alloc fe, inode alloc
473 - * group descriptor + mkdir/symlink blocks */
474 -#define OCFS2_MKNOD_CREDITS (3 + OCFS2_SUBALLOC_ALLOC \
475 - + OCFS2_DIR_LINK_ADDITIONAL_CREDITS)
476 + * group descriptor + mkdir/symlink blocks + quota update */
477 +static inline int ocfs2_mknod_credits(struct super_block *sb)
478 +{
479 + return 3 + OCFS2_SUBALLOC_ALLOC + OCFS2_DIR_LINK_ADDITIONAL_CREDITS +
480 + ocfs2_quota_trans_credits(sb);
481 +}
482
483 /* local alloc metadata change + main bitmap updates */
484 #define OCFS2_WINDOW_MOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS \
485 @@ -332,13 +373,21 @@ int ocfs2_journal_dirty
486 * for the dinode, one for the new block. */
487 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
488
489 -/* file update (nlink, etc) + directory mtime/ctime + dir entry block */
490 -#define OCFS2_LINK_CREDITS (2*OCFS2_INODE_UPDATE_CREDITS + 1)
491 +/* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
492 + * update on dir */
493 +static inline int ocfs2_link_credits(struct super_block *sb)
494 +{
495 + return 2*OCFS2_INODE_UPDATE_CREDITS + 1 +
496 + ocfs2_quota_trans_credits(sb);
497 +}
498
499 /* inode + dir inode (if we unlink a dir), + dir entry block + orphan
500 * dir inode link */
501 -#define OCFS2_UNLINK_CREDITS (2 * OCFS2_INODE_UPDATE_CREDITS + 1 \
502 - + OCFS2_LINK_CREDITS)
503 +static inline int ocfs2_unlink_credits(struct super_block *sb)
504 +{
505 + /* The quota update from ocfs2_link_credits is unused here... */
506 + return 2 * OCFS2_INODE_UPDATE_CREDITS + 1 + ocfs2_link_credits(sb);
507 +}
508
509 /* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
510 * inode alloc group descriptor */
511 @@ -347,8 +396,10 @@ int ocfs2_journal_dirty
512 /* dinode update, old dir dinode update, new dir dinode update, old
513 * dir dir entry, new dir dir entry, dir entry update for renaming
514 * directory + target unlink */
515 -#define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3 \
516 - + OCFS2_UNLINK_CREDITS)
517 +static inline int ocfs2_rename_credits(struct super_block *sb)
518 +{
519 + return 3 * OCFS2_INODE_UPDATE_CREDITS + 3 + ocfs2_unlink_credits(sb);
520 +}
521
522 /* global bitmap dinode, group desc., relinked group,
523 * suballocator dinode, group desc., relinked group,
524 @@ -357,21 +408,6 @@ int ocfs2_journal_dirty
525 + OCFS2_INODE_UPDATE_CREDITS \
526 + OCFS2_XATTR_BLOCK_UPDATE_CREDITS)
527
528 -/* global quotafile inode update, data block */
529 -#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
530 -
531 -/*
532 - * The two writes below can accidentally see global info dirty due
533 - * to set_info() quotactl so make them prepared for the writes.
534 - */
535 -/* quota data block, global info */
536 -/* Write to local quota file */
537 -#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
538 -
539 -/* global quota data block, local quota data block, global quota inode,
540 - * global quota info */
541 -#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
542 -
543 /*
544 * Please note that the caller must make sure that root_el is the root
545 * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
546 @@ -401,18 +437,19 @@ static inline int ocfs2_calc_extend_cred
547 * credit for the dinode there. */
548 extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
549
550 - return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks;
551 + return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks +
552 + ocfs2_quota_trans_credits(sb);
553 }
554
555 static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
556 {
557 - int blocks = OCFS2_MKNOD_CREDITS;
558 + int blocks = ocfs2_mknod_credits(sb);
559
560 /* links can be longer than one block so we may update many
561 * within our single allocated extent. */
562 blocks += ocfs2_clusters_to_blocks(sb, 1);
563
564 - return blocks;
565 + return blocks + ocfs2_quota_trans_credits(sb);
566 }
567
568 static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
569 @@ -449,6 +486,8 @@ static inline int ocfs2_calc_tree_trunc_
570 /* update to the truncate log. */
571 credits += OCFS2_TRUNCATE_LOG_UPDATE;
572
573 + credits += ocfs2_quota_trans_credits(sb);
574 +
575 return credits;
576 }
577
578 --- a/fs/ocfs2/namei.c
579 +++ b/fs/ocfs2/namei.c
580 @@ -40,6 +40,7 @@
581 #include <linux/types.h>
582 #include <linux/slab.h>
583 #include <linux/highmem.h>
584 +#include <linux/quotaops.h>
585
586 #define MLOG_MASK_PREFIX ML_NAMEI
587 #include <cluster/masklog.h>
588 @@ -212,6 +213,7 @@ static struct inode *ocfs2_get_init_inod
589 } else
590 inode->i_gid = current->fsgid;
591 inode->i_mode = mode;
592 + vfs_dq_init(inode);
593 return inode;
594 }
595
596 @@ -233,6 +235,7 @@ static int ocfs2_mknod(struct inode *dir
597 struct ocfs2_alloc_context *xattr_ac = NULL;
598 int want_clusters = 0;
599 int xattr_credits = 0;
600 + int did_quota_inode = 0;
601 struct ocfs2_security_xattr_info si = {
602 .enable = 1,
603 };
604 @@ -323,7 +326,8 @@ static int ocfs2_mknod(struct inode *dir
605 goto leave;
606 }
607
608 - handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS + xattr_credits);
609 + handle = ocfs2_start_trans(osb,
610 + ocfs2_mknod_credits(dir->i_sb) + xattr_credits);
611 if (IS_ERR(handle)) {
612 status = PTR_ERR(handle);
613 handle = NULL;
614 @@ -331,6 +335,15 @@ static int ocfs2_mknod(struct inode *dir
615 goto leave;
616 }
617
618 + /* We don't use standard VFS wrapper because we don't want vfs_dq_init
619 + * to be called. */
620 + if (sb_any_quota_active(osb->sb) &&
621 + osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
622 + status = -EDQUOT;
623 + goto leave;
624 + }
625 + did_quota_inode = 1;
626 +
627 /* do the real work now. */
628 status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
629 &new_fe_bh, parent_fe_bh, handle,
630 @@ -399,6 +412,8 @@ static int ocfs2_mknod(struct inode *dir
631 d_instantiate(dentry, inode);
632 status = 0;
633 leave:
634 + if (status < 0 && did_quota_inode)
635 + vfs_dq_free_inode(inode);
636 if (handle)
637 ocfs2_commit_trans(osb, handle);
638
639 @@ -649,7 +664,7 @@ static int ocfs2_link(struct dentry *old
640 goto out_unlock_inode;
641 }
642
643 - handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
644 + handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb));
645 if (IS_ERR(handle)) {
646 err = PTR_ERR(handle);
647 handle = NULL;
648 @@ -836,7 +851,7 @@ static int ocfs2_unlink(struct inode *di
649 }
650 }
651
652 - handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
653 + handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb));
654 if (IS_ERR(handle)) {
655 status = PTR_ERR(handle);
656 handle = NULL;
657 @@ -1242,7 +1257,7 @@ static int ocfs2_rename(struct inode *ol
658 }
659 }
660
661 - handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
662 + handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb));
663 if (IS_ERR(handle)) {
664 status = PTR_ERR(handle);
665 handle = NULL;
666 @@ -1560,6 +1575,7 @@ static int ocfs2_symlink(struct inode *d
667 struct ocfs2_alloc_context *xattr_ac = NULL;
668 int want_clusters = 0;
669 int xattr_credits = 0;
670 + int did_quota = 0, did_quota_inode = 0;
671 struct ocfs2_security_xattr_info si = {
672 .enable = 1,
673 };
674 @@ -1656,6 +1672,15 @@ static int ocfs2_symlink(struct inode *d
675 goto bail;
676 }
677
678 + /* We don't use standard VFS wrapper because we don't want vfs_dq_init
679 + * to be called. */
680 + if (sb_any_quota_active(osb->sb) &&
681 + osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
682 + status = -EDQUOT;
683 + goto bail;
684 + }
685 + did_quota_inode = 1;
686 +
687 status = ocfs2_mknod_locked(osb, dir, inode, dentry,
688 0, &new_fe_bh, parent_fe_bh, handle,
689 inode_ac);
690 @@ -1671,6 +1696,12 @@ static int ocfs2_symlink(struct inode *d
691 u32 offset = 0;
692
693 inode->i_op = &ocfs2_symlink_inode_operations;
694 + if (vfs_dq_alloc_space_nodirty(inode,
695 + ocfs2_clusters_to_bytes(osb->sb, 1))) {
696 + status = -EDQUOT;
697 + goto bail;
698 + }
699 + did_quota = 1;
700 status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
701 new_fe_bh,
702 handle, data_ac, NULL,
703 @@ -1736,6 +1767,11 @@ static int ocfs2_symlink(struct inode *d
704 dentry->d_op = &ocfs2_dentry_ops;
705 d_instantiate(dentry, inode);
706 bail:
707 + if (status < 0 && did_quota)
708 + vfs_dq_free_space_nodirty(inode,
709 + ocfs2_clusters_to_bytes(osb->sb, 1));
710 + if (status < 0 && did_quota_inode)
711 + vfs_dq_free_inode(inode);
712 if (handle)
713 ocfs2_commit_trans(osb, handle);
714
715 --- a/fs/ocfs2/xattr.c
716 +++ b/fs/ocfs2/xattr.c
717 @@ -1613,7 +1613,7 @@ static int ocfs2_remove_value_outside(st
718
719 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
720
721 - ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
722 + ctxt.handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
723 if (IS_ERR(ctxt.handle)) {
724 ret = PTR_ERR(ctxt.handle);
725 mlog_errno(ret);
726 @@ -2190,7 +2190,7 @@ static int ocfs2_calc_xattr_set_need(str
727 */
728 if (!xi->value) {
729 if (!ocfs2_xattr_is_local(xe))
730 - credits += OCFS2_REMOVE_EXTENT_CREDITS;
731 + credits += ocfs2_remove_extent_credits(inode->i_sb);
732
733 goto out;
734 }
735 @@ -2207,7 +2207,7 @@ static int ocfs2_calc_xattr_set_need(str
736 */
737 if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) {
738 clusters_add += new_clusters;
739 - credits += OCFS2_REMOVE_EXTENT_CREDITS +
740 + credits += ocfs2_remove_extent_credits(inode->i_sb) +
741 OCFS2_INODE_UPDATE_CREDITS;
742 if (!ocfs2_xattr_is_local(xe))
743 credits += ocfs2_calc_extend_credits(
744 @@ -2231,7 +2231,7 @@ static int ocfs2_calc_xattr_set_need(str
745 xv = &def_xv.xv;
746
747 if (old_clusters >= new_clusters) {
748 - credits += OCFS2_REMOVE_EXTENT_CREDITS;
749 + credits += ocfs2_remove_extent_credits(inode->i_sb);
750 goto out;
751 } else {
752 meta_add += ocfs2_extend_meta_needed(&xv->xr_list);
753 @@ -4700,7 +4700,7 @@ static int ocfs2_rm_xattr_cluster(struct
754 }
755 }
756
757 - handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
758 + handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
759 if (IS_ERR(handle)) {
760 ret = -ENOMEM;
761 mlog_errno(ret);
762 @@ -5059,7 +5059,7 @@ static int ocfs2_delete_xattr_in_bucket(
763
764 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
765
766 - ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
767 + ctxt.handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
768 if (IS_ERR(ctxt.handle)) {
769 ret = PTR_ERR(ctxt.handle);
770 mlog_errno(ret);