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?
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.
11 Signed-off-by: Jan Kara <jack@suse.cz>
13 fs/ocfs2/alloc.c | 18 ++++++-
14 fs/ocfs2/aops.c | 16 +++++-
15 fs/ocfs2/dir.c | 24 ++++++++-
16 fs/ocfs2/file.c | 70 ++++++++++++++++++++++--
17 fs/ocfs2/inode.c | 10 +++-
18 fs/ocfs2/journal.h | 99 ++++++++++++++++++++++++----------
19 fs/ocfs2/namei.c | 151 +++++++++++++++++++++++++++++++++++----------------
20 7 files changed, 296 insertions(+), 92 deletions(-)
22 Index: linux-2.6.27-ocfs2/fs/ocfs2/alloc.c
23 ===================================================================
24 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/alloc.c
25 +++ linux-2.6.27-ocfs2/fs/ocfs2/alloc.c
27 #include <linux/slab.h>
28 #include <linux/highmem.h>
29 #include <linux/swap.h>
30 +#include <linux/quotaops.h>
32 #define MLOG_MASK_PREFIX ML_DISK_ALLOC
33 #include <cluster/masklog.h>
34 @@ -5292,7 +5293,7 @@ int ocfs2_remove_btree_range(struct inod
38 - handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
39 + handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
41 ret = PTR_ERR(handle);
43 @@ -6523,6 +6524,8 @@ static int ocfs2_do_truncate(struct ocfs
47 + vfs_dq_free_space_nodirty(inode,
48 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
49 spin_lock(&OCFS2_I(inode)->ip_lock);
50 OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
52 @@ -6836,6 +6839,7 @@ int ocfs2_convert_inline_data_to_extents
53 struct page **pages = NULL;
54 loff_t end = osb->s_clustersize;
55 struct ocfs2_extent_tree et;
58 has_data = i_size_read(inode) ? 1 : 0;
60 @@ -6855,7 +6859,8 @@ int ocfs2_convert_inline_data_to_extents
64 - handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS);
65 + handle = ocfs2_start_trans(osb,
66 + ocfs2_inline_to_extents_credits(osb->sb));
68 ret = PTR_ERR(handle);
70 @@ -6874,6 +6879,13 @@ int ocfs2_convert_inline_data_to_extents
71 unsigned int page_end;
74 + if (vfs_dq_alloc_space_nodirty(inode,
75 + ocfs2_clusters_to_bytes(osb->sb, 1))) {
81 ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
84 @@ -6947,6 +6959,10 @@ int ocfs2_convert_inline_data_to_extents
88 + if (ret < 0 && did_quota)
89 + vfs_dq_free_space_nodirty(inode,
90 + ocfs2_clusters_to_bytes(osb->sb, 1));
92 ocfs2_commit_trans(osb, handle);
95 Index: linux-2.6.27-ocfs2/fs/ocfs2/aops.c
96 ===================================================================
97 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/aops.c
98 +++ linux-2.6.27-ocfs2/fs/ocfs2/aops.c
100 #include <linux/swap.h>
101 #include <linux/pipe_fs_i.h>
102 #include <linux/mpage.h>
103 +#include <linux/quotaops.h>
105 #define MLOG_MASK_PREFIX ML_FILE_IO
106 #include <cluster/masklog.h>
107 @@ -1750,6 +1751,11 @@ int ocfs2_write_begin_nolock(struct addr
109 wc->w_handle = handle;
111 + if (clusters_to_alloc && vfs_dq_alloc_space_nodirty(inode,
112 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc))) {
117 * We don't want this to fail in ocfs2_write_end(), so do it
119 @@ -1758,7 +1764,7 @@ int ocfs2_write_begin_nolock(struct addr
120 OCFS2_JOURNAL_ACCESS_WRITE);
128 @@ -1771,14 +1777,14 @@ int ocfs2_write_begin_nolock(struct addr
136 ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
145 @@ -1790,6 +1796,10 @@ success:
146 *pagep = wc->w_target_page;
150 + if (clusters_to_alloc)
151 + vfs_dq_free_space(inode,
152 + ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
154 ocfs2_commit_trans(osb, handle);
156 Index: linux-2.6.27-ocfs2/fs/ocfs2/dir.c
157 ===================================================================
158 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/dir.c
159 +++ linux-2.6.27-ocfs2/fs/ocfs2/dir.c
161 #include <linux/types.h>
162 #include <linux/slab.h>
163 #include <linux/highmem.h>
164 +#include <linux/quotaops.h>
166 #define MLOG_MASK_PREFIX ML_NAMEI
167 #include <cluster/masklog.h>
168 @@ -1216,9 +1217,9 @@ static int ocfs2_expand_inline_dir(struc
169 unsigned int blocks_wanted,
170 struct buffer_head **first_block_bh)
172 - int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS;
173 u32 alloc, bit_off, len;
174 struct super_block *sb = dir->i_sb;
175 + int ret, credits = ocfs2_inline_to_extents_credits(sb);
176 u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits;
177 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
178 struct ocfs2_inode_info *oi = OCFS2_I(dir);
179 @@ -1227,6 +1228,7 @@ static int ocfs2_expand_inline_dir(struc
180 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
182 struct ocfs2_extent_tree et;
185 ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
187 @@ -1264,6 +1266,12 @@ static int ocfs2_expand_inline_dir(struc
191 + if (vfs_dq_alloc_space_nodirty(dir,
192 + ocfs2_clusters_to_bytes(osb->sb, alloc))) {
198 * Try to claim as many clusters as the bitmap can give though
199 * if we only get one now, that's enough to continue. The rest
200 @@ -1386,6 +1394,9 @@ static int ocfs2_expand_inline_dir(struc
204 + if (ret < 0 && did_quota)
205 + vfs_dq_free_space_nodirty(dir,
206 + ocfs2_clusters_to_bytes(osb->sb, 2));
207 ocfs2_commit_trans(osb, handle);
210 @@ -1410,7 +1421,7 @@ static int ocfs2_do_extend_dir(struct su
211 struct buffer_head **new_bh)
215 + int extend, did_quota = 0;
216 u64 p_blkno, v_blkno;
218 spin_lock(&OCFS2_I(dir)->ip_lock);
219 @@ -1420,6 +1431,13 @@ static int ocfs2_do_extend_dir(struct su
221 u32 offset = OCFS2_I(dir)->ip_clusters;
223 + if (vfs_dq_alloc_space_nodirty(dir,
224 + ocfs2_clusters_to_bytes(sb, 1))) {
230 status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
231 1, 0, parent_fe_bh, handle,
232 data_ac, meta_ac, NULL);
233 @@ -1445,6 +1463,8 @@ static int ocfs2_do_extend_dir(struct su
237 + if (did_quota && status < 0)
238 + vfs_dq_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
242 Index: linux-2.6.27-ocfs2/fs/ocfs2/file.c
243 ===================================================================
244 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/file.c
245 +++ linux-2.6.27-ocfs2/fs/ocfs2/file.c
247 #include <linux/mount.h>
248 #include <linux/writeback.h>
249 #include <linux/falloc.h>
250 +#include <linux/quotaops.h>
252 #define MLOG_MASK_PREFIX ML_INODE
253 #include <cluster/masklog.h>
260 #include "buffer_head_io.h"
262 @@ -537,6 +539,8 @@ static int __ocfs2_extend_allocation(str
263 enum ocfs2_alloc_restarted why;
264 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
265 struct ocfs2_extent_tree et;
266 + u32 total_clusters = clusters_to_add;
269 mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
271 @@ -585,6 +589,12 @@ restart_all:
275 + if (!did_quota && vfs_dq_alloc_space_nodirty(inode,
276 + ocfs2_clusters_to_bytes(osb->sb, total_clusters))) {
281 restarted_transaction:
282 /* reserve a write to the file entry early on - that we if we
283 * run out of credits in the allocation path, we can still
284 @@ -655,6 +665,9 @@ restarted_transaction:
285 OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode));
288 + if (status < 0 && did_quota)
289 + vfs_dq_free_space(inode,
290 + ocfs2_clusters_to_bytes(osb->sb, total_clusters));
292 ocfs2_commit_trans(osb, handle);
294 @@ -886,6 +899,9 @@ int ocfs2_setattr(struct dentry *dentry,
295 struct ocfs2_super *osb = OCFS2_SB(sb);
296 struct buffer_head *bh = NULL;
297 handle_t *handle = NULL;
298 + int locked[MAXQUOTAS] = {0, 0};
299 + int credits, qtype;
300 + struct ocfs2_mem_dqinfo *oinfo;
302 mlog_entry("(0x%p, '%.*s')\n", dentry,
303 dentry->d_name.len, dentry->d_name.name);
304 @@ -956,11 +972,47 @@ int ocfs2_setattr(struct dentry *dentry,
308 - handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
309 - if (IS_ERR(handle)) {
310 - status = PTR_ERR(handle);
311 - mlog_errno(status);
313 + if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
314 + (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
315 + credits = OCFS2_INODE_UPDATE_CREDITS;
316 + if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
317 + && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
318 + OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
319 + oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv;
320 + status = ocfs2_lock_global_qf(oinfo, 1);
323 + credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) +
324 + ocfs2_calc_qdel_credits(sb, USRQUOTA);
325 + locked[USRQUOTA] = 1;
327 + if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
328 + && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
329 + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
330 + oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv;
331 + status = ocfs2_lock_global_qf(oinfo, 1);
334 + credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) +
335 + ocfs2_calc_qdel_credits(sb, GRPQUOTA);
336 + locked[GRPQUOTA] = 1;
338 + handle = ocfs2_start_trans(osb, credits);
339 + if (IS_ERR(handle)) {
340 + status = PTR_ERR(handle);
341 + mlog_errno(status);
344 + status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
348 + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
349 + if (IS_ERR(handle)) {
350 + status = PTR_ERR(handle);
351 + mlog_errno(status);
357 @@ -983,6 +1035,12 @@ int ocfs2_setattr(struct dentry *dentry,
359 ocfs2_commit_trans(osb, handle);
361 + for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
362 + if (!locked[qtype])
364 + oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
365 + ocfs2_unlock_global_qf(oinfo, 1);
367 ocfs2_inode_unlock(inode, 1);
370 Index: linux-2.6.27-ocfs2/fs/ocfs2/inode.c
371 ===================================================================
372 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/inode.c
373 +++ linux-2.6.27-ocfs2/fs/ocfs2/inode.c
375 #include <linux/slab.h>
376 #include <linux/highmem.h>
377 #include <linux/pagemap.h>
378 +#include <linux/quotaops.h>
380 #include <asm/byteorder.h>
382 @@ -619,7 +620,8 @@ static int ocfs2_remove_inode(struct ino
386 - handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS);
387 + handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS +
388 + ocfs2_quota_trans_credits(inode->i_sb));
389 if (IS_ERR(handle)) {
390 status = PTR_ERR(handle);
392 @@ -651,6 +653,7 @@ static int ocfs2_remove_inode(struct ino
395 ocfs2_remove_from_cache(inode, di_bh);
396 + vfs_dq_free_inode(inode);
398 status = ocfs2_free_dinode(handle, inode_alloc_inode,
400 @@ -933,7 +936,10 @@ void ocfs2_delete_inode(struct inode *in
402 mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
404 - if (is_bad_inode(inode)) {
405 + /* When we fail in read_inode() we mark inode as bad. The second test
406 + * catches the case when inode allocation fails before allocating
407 + * a block for inode. */
408 + if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) {
409 mlog(0, "Skipping delete of bad inode\n");
412 Index: linux-2.6.27-ocfs2/fs/ocfs2/journal.h
413 ===================================================================
414 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/journal.h
415 +++ linux-2.6.27-ocfs2/fs/ocfs2/journal.h
416 @@ -293,6 +293,37 @@ int ocfs2_journal_dirty
417 /* extended attribute block update */
418 #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
420 +/* global quotafile inode update, data block */
421 +#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
424 + * The two writes below can accidentally see global info dirty due
425 + * to set_info() quotactl so make them prepared for the writes.
427 +/* quota data block, global info */
428 +/* Write to local quota file */
429 +#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
431 +/* global quota data block, local quota data block, global quota inode,
432 + * global quota info */
433 +#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
435 +static inline int ocfs2_quota_trans_credits(struct super_block *sb)
439 + if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA))
440 + credits += OCFS2_QWRITE_CREDITS;
441 + if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA))
442 + credits += OCFS2_QWRITE_CREDITS;
446 +/* Number of credits needed for removing quota structure from file */
447 +int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
448 +/* Number of credits needed for initialization of new quota structure */
449 +int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
451 /* group extend. inode update and last group update. */
452 #define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
454 @@ -303,8 +334,11 @@ int ocfs2_journal_dirty
455 * prev. group desc. if we relink. */
456 #define OCFS2_SUBALLOC_ALLOC (3)
458 -#define OCFS2_INLINE_TO_EXTENTS_CREDITS (OCFS2_SUBALLOC_ALLOC \
459 - + OCFS2_INODE_UPDATE_CREDITS)
460 +static inline int ocfs2_inline_to_extents_credits(struct super_block *sb)
462 + return OCFS2_SUBALLOC_ALLOC + OCFS2_INODE_UPDATE_CREDITS +
463 + ocfs2_quota_trans_credits(sb);
466 /* dinode + group descriptor update. We don't relink on free yet. */
467 #define OCFS2_SUBALLOC_FREE (2)
468 @@ -313,16 +347,23 @@ int ocfs2_journal_dirty
469 #define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE \
470 + OCFS2_TRUNCATE_LOG_UPDATE)
472 -#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
473 +static inline int ocfs2_remove_extent_credits(struct super_block *sb)
475 + return OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS +
476 + ocfs2_quota_trans_credits(sb);
479 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
480 * bitmap block for the new bit) */
481 #define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
483 /* parent fe, parent block, new file entry, inode alloc fe, inode alloc
484 - * group descriptor + mkdir/symlink blocks */
485 -#define OCFS2_MKNOD_CREDITS (3 + OCFS2_SUBALLOC_ALLOC \
486 - + OCFS2_DIR_LINK_ADDITIONAL_CREDITS)
487 + * group descriptor + mkdir/symlink blocks + quota update */
488 +static inline int ocfs2_mknod_credits(struct super_block *sb)
490 + return 3 + OCFS2_SUBALLOC_ALLOC + OCFS2_DIR_LINK_ADDITIONAL_CREDITS +
491 + ocfs2_quota_trans_credits(sb);
494 /* local alloc metadata change + main bitmap updates */
495 #define OCFS2_WINDOW_MOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS \
496 @@ -332,13 +373,21 @@ int ocfs2_journal_dirty
497 * for the dinode, one for the new block. */
498 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
500 -/* file update (nlink, etc) + directory mtime/ctime + dir entry block */
501 -#define OCFS2_LINK_CREDITS (2*OCFS2_INODE_UPDATE_CREDITS + 1)
502 +/* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
504 +static inline int ocfs2_link_credits(struct super_block *sb)
506 + return 2*OCFS2_INODE_UPDATE_CREDITS + 1 +
507 + ocfs2_quota_trans_credits(sb);
510 /* inode + dir inode (if we unlink a dir), + dir entry block + orphan
512 -#define OCFS2_UNLINK_CREDITS (2 * OCFS2_INODE_UPDATE_CREDITS + 1 \
513 - + OCFS2_LINK_CREDITS)
514 +static inline int ocfs2_unlink_credits(struct super_block *sb)
516 + /* The quota update from ocfs2_link_credits is unused here... */
517 + return 2 * OCFS2_INODE_UPDATE_CREDITS + 1 + ocfs2_link_credits(sb);
520 /* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
521 * inode alloc group descriptor */
522 @@ -347,8 +396,10 @@ int ocfs2_journal_dirty
523 /* dinode update, old dir dinode update, new dir dinode update, old
524 * dir dir entry, new dir dir entry, dir entry update for renaming
525 * directory + target unlink */
526 -#define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3 \
527 - + OCFS2_UNLINK_CREDITS)
528 +static inline int ocfs2_rename_credits(struct super_block *sb)
530 + return 3 * OCFS2_INODE_UPDATE_CREDITS + 3 + ocfs2_unlink_credits(sb);
533 /* global bitmap dinode, group desc., relinked group,
534 * suballocator dinode, group desc., relinked group,
535 @@ -357,21 +408,6 @@ int ocfs2_journal_dirty
536 + OCFS2_INODE_UPDATE_CREDITS \
537 + OCFS2_XATTR_BLOCK_UPDATE_CREDITS)
539 -/* global quotafile inode update, data block */
540 -#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
543 - * The two writes below can accidentally see global info dirty due
544 - * to set_info() quotactl so make them prepared for the writes.
546 -/* quota data block, global info */
547 -/* Write to local quota file */
548 -#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
550 -/* global quota data block, local quota data block, global quota inode,
551 - * global quota info */
552 -#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
555 * Please note that the caller must make sure that root_el is the root
556 * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
557 @@ -401,18 +437,19 @@ static inline int ocfs2_calc_extend_cred
558 * credit for the dinode there. */
559 extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
561 - return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks;
562 + return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks +
563 + ocfs2_quota_trans_credits(sb);
566 static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
568 - int blocks = OCFS2_MKNOD_CREDITS;
569 + int blocks = ocfs2_mknod_credits(sb);
571 /* links can be longer than one block so we may update many
572 * within our single allocated extent. */
573 blocks += ocfs2_clusters_to_blocks(sb, 1);
576 + return blocks + ocfs2_quota_trans_credits(sb);
579 static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
580 @@ -449,6 +486,8 @@ static inline int ocfs2_calc_tree_trunc_
581 /* update to the truncate log. */
582 credits += OCFS2_TRUNCATE_LOG_UPDATE;
584 + credits += ocfs2_quota_trans_credits(sb);
589 Index: linux-2.6.27-ocfs2/fs/ocfs2/namei.c
590 ===================================================================
591 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/namei.c
592 +++ linux-2.6.27-ocfs2/fs/ocfs2/namei.c
594 #include <linux/types.h>
595 #include <linux/slab.h>
596 #include <linux/highmem.h>
597 +#include <linux/quotaops.h>
599 #define MLOG_MASK_PREFIX ML_NAMEI
600 #include <cluster/masklog.h>
601 @@ -212,6 +213,7 @@ static struct inode *ocfs2_get_init_inod
603 inode->i_gid = current->fsgid;
604 inode->i_mode = mode;
605 + vfs_dq_init(inode);
609 @@ -233,6 +235,7 @@ static int ocfs2_mknod(struct inode *dir
610 struct ocfs2_alloc_context *xattr_ac = NULL;
611 int want_clusters = 0;
612 int xattr_credits = 0;
613 + int did_quota_inode = 0;
614 struct ocfs2_security_xattr_info si = {
617 @@ -323,7 +326,8 @@ static int ocfs2_mknod(struct inode *dir
621 - handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS + xattr_credits);
622 + handle = ocfs2_start_trans(osb,
623 + ocfs2_mknod_credits(dir->i_sb) + xattr_credits);
624 if (IS_ERR(handle)) {
625 status = PTR_ERR(handle);
627 @@ -331,6 +335,15 @@ static int ocfs2_mknod(struct inode *dir
631 + /* We don't use standard VFS wrapper because we don't want vfs_dq_init
633 + if (sb_any_quota_active(osb->sb) &&
634 + osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
638 + did_quota_inode = 1;
640 /* do the real work now. */
641 status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
642 &new_fe_bh, parent_fe_bh, handle,
643 @@ -399,6 +412,8 @@ static int ocfs2_mknod(struct inode *dir
644 d_instantiate(dentry, inode);
647 + if (status < 0 && did_quota_inode)
648 + vfs_dq_free_inode(inode);
650 ocfs2_commit_trans(osb, handle);
652 @@ -649,7 +664,7 @@ static int ocfs2_link(struct dentry *old
653 goto out_unlock_inode;
656 - handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
657 + handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb));
658 if (IS_ERR(handle)) {
659 err = PTR_ERR(handle);
661 @@ -836,7 +851,7 @@ static int ocfs2_unlink(struct inode *di
665 - handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
666 + handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb));
667 if (IS_ERR(handle)) {
668 status = PTR_ERR(handle);
670 @@ -1242,7 +1257,7 @@ static int ocfs2_rename(struct inode *ol
674 - handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
675 + handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb));
676 if (IS_ERR(handle)) {
677 status = PTR_ERR(handle);
679 @@ -1560,6 +1575,7 @@ static int ocfs2_symlink(struct inode *d
680 struct ocfs2_alloc_context *xattr_ac = NULL;
681 int want_clusters = 0;
682 int xattr_credits = 0;
683 + int did_quota = 0, did_quota_inode = 0;
684 struct ocfs2_security_xattr_info si = {
687 @@ -1656,6 +1672,15 @@ static int ocfs2_symlink(struct inode *d
691 + /* We don't use standard VFS wrapper because we don't want vfs_dq_init
693 + if (sb_any_quota_active(osb->sb) &&
694 + osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
698 + did_quota_inode = 1;
700 status = ocfs2_mknod_locked(osb, dir, inode, dentry,
701 0, &new_fe_bh, parent_fe_bh, handle,
703 @@ -1671,6 +1696,12 @@ static int ocfs2_symlink(struct inode *d
706 inode->i_op = &ocfs2_symlink_inode_operations;
707 + if (vfs_dq_alloc_space_nodirty(inode,
708 + ocfs2_clusters_to_bytes(osb->sb, 1))) {
713 status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
715 handle, data_ac, NULL,
716 @@ -1736,6 +1767,11 @@ static int ocfs2_symlink(struct inode *d
717 dentry->d_op = &ocfs2_dentry_ops;
718 d_instantiate(dentry, inode);
720 + if (status < 0 && did_quota)
721 + vfs_dq_free_space_nodirty(inode,
722 + ocfs2_clusters_to_bytes(osb->sb, 1));
723 + if (status < 0 && did_quota_inode)
724 + vfs_dq_free_inode(inode);
726 ocfs2_commit_trans(osb, handle);
728 Index: linux-2.6.27-ocfs2/fs/ocfs2/xattr.c
729 ===================================================================
730 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/xattr.c
731 +++ linux-2.6.27-ocfs2/fs/ocfs2/xattr.c
732 @@ -1613,7 +1613,7 @@ static int ocfs2_remove_value_outside(st
734 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
736 - ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
737 + ctxt.handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
738 if (IS_ERR(ctxt.handle)) {
739 ret = PTR_ERR(ctxt.handle);
741 @@ -2190,7 +2190,7 @@ static int ocfs2_calc_xattr_set_need(str
744 if (!ocfs2_xattr_is_local(xe))
745 - credits += OCFS2_REMOVE_EXTENT_CREDITS;
746 + credits += ocfs2_remove_extent_credits(inode->i_sb);
750 @@ -2207,7 +2207,7 @@ static int ocfs2_calc_xattr_set_need(str
752 if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) {
753 clusters_add += new_clusters;
754 - credits += OCFS2_REMOVE_EXTENT_CREDITS +
755 + credits += ocfs2_remove_extent_credits(inode->i_sb) +
756 OCFS2_INODE_UPDATE_CREDITS;
757 if (!ocfs2_xattr_is_local(xe))
758 credits += ocfs2_calc_extend_credits(
759 @@ -2231,7 +2231,7 @@ static int ocfs2_calc_xattr_set_need(str
762 if (old_clusters >= new_clusters) {
763 - credits += OCFS2_REMOVE_EXTENT_CREDITS;
764 + credits += ocfs2_remove_extent_credits(inode->i_sb);
767 meta_add += ocfs2_extend_meta_needed(&xv->xr_list);
768 @@ -4700,7 +4700,7 @@ static int ocfs2_rm_xattr_cluster(struct
772 - handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
773 + handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
774 if (IS_ERR(handle)) {
777 @@ -5059,7 +5059,7 @@ static int ocfs2_delete_xattr_in_bucket(
779 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
781 - ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
782 + ctxt.handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(inode->i_sb));
783 if (IS_ERR(ctxt.handle)) {
784 ret = PTR_ERR(ctxt.handle);