]> git.ipfire.org Git - ipfire-2.x.git/blame - 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
CommitLineData
2cb7cef9
BS
1From: Jan Kara <jack@suse.cz>
2References: fate#302681
3Subject: [PATCH 25/28] ocfs2: Add quota calls for allocation and freeing of inodes and space
4Patch-mainline: 2.6.29?
5
6Add quota calls for allocation and freeing of inodes and space, also update
7estimates on number of needed credits for a transaction. Move out inode
8allocation from ocfs2_mknod_locked() because vfs_dq_init() must be called
9outside of a transaction.
10
11Signed-off-by: Jan Kara <jack@suse.cz>
12---
82094b55
AF
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(-)
2cb7cef9 22
82094b55
AF
23--- a/fs/ocfs2/alloc.c
24+++ b/fs/ocfs2/alloc.c
2cb7cef9
BS
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:
82094b55
AF
94--- a/fs/ocfs2/aops.c
95+++ b/fs/ocfs2/aops.c
2cb7cef9
BS
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>
82094b55 104@@ -1780,6 +1781,11 @@ int ocfs2_write_begin_nolock(struct addr
2cb7cef9
BS
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.
82094b55 116@@ -1788,7 +1794,7 @@ int ocfs2_write_begin_nolock(struct addr
2cb7cef9
BS
117 OCFS2_JOURNAL_ACCESS_WRITE);
118 if (ret) {
119 mlog_errno(ret);
120- goto out_commit;
121+ goto out_quota;
122 }
123
124 /*
82094b55
AF
125@@ -1800,14 +1806,14 @@ int ocfs2_write_begin_nolock(struct addr
126 cluster_of_pages, mmap_page);
2cb7cef9
BS
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)
82094b55 142@@ -1819,6 +1825,10 @@ success:
2cb7cef9
BS
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
82094b55
AF
153--- a/fs/ocfs2/dir.c
154+++ b/fs/ocfs2/dir.c
2cb7cef9
BS
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
82094b55
AF
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;
2cb7cef9
BS
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 }
82094b55
AF
237--- a/fs/ocfs2/file.c
238+++ b/fs/ocfs2/file.c
2cb7cef9
BS
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)
82094b55
AF
363--- a/fs/ocfs2/inode.c
364+++ b/fs/ocfs2/inode.c
2cb7cef9
BS
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 }
82094b55
AF
403--- a/fs/ocfs2/journal.h
404+++ b/fs/ocfs2/journal.h
2cb7cef9
BS
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
82094b55
AF
578--- a/fs/ocfs2/namei.c
579+++ b/fs/ocfs2/namei.c
2cb7cef9
BS
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
82094b55
AF
715--- a/fs/ocfs2/xattr.c
716+++ b/fs/ocfs2/xattr.c
2cb7cef9
BS
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);