1 From: Jan Kara <jack@suse.cz>
2 References: fate#302681
3 Subject: [PATCH 24/28] ocfs2: Implementation of local and global quota file handling
4 Patch-mainline: 2.6.29?
6 For each quota type each node has local quota file. In this file it stores
7 changes users have made to disk usage via this node. Once in a while this
8 information is synced to global file (and thus with other nodes) so that
9 limits enforcement at least aproximately works.
11 Global quota files contain all the information about usage and limits. It's
12 mostly handled by the generic VFS code (which implements a trie of structures
13 inside a quota file). We only have to provide functions to convert structures
14 from on-disk format to in-memory one. We also have to provide wrappers for
15 various quota functions starting transactions and acquiring necessary cluster
16 locks before the actual IO is really started.
18 Signed-off-by: Jan Kara <jack@suse.cz>
20 fs/ocfs2/Makefile | 2 +
21 fs/ocfs2/cluster/masklog.h | 1 +
22 fs/ocfs2/dlmglue.c | 137 +++++++
23 fs/ocfs2/dlmglue.h | 17 +
24 fs/ocfs2/file.c | 6 +-
26 fs/ocfs2/journal.h | 15 +
27 fs/ocfs2/ocfs2_fs.h | 95 +++++
28 fs/ocfs2/ocfs2_lockid.h | 5 +
29 fs/ocfs2/quota.h | 94 +++++
30 fs/ocfs2/quota_global.c | 855 ++++++++++++++++++++++++++++++++++++++++++++
31 fs/ocfs2/quota_local.c | 846 +++++++++++++++++++++++++++++++++++++++++++
32 fs/ocfs2/super.c | 35 ++-
33 13 files changed, 2107 insertions(+), 5 deletions(-)
34 create mode 100644 fs/ocfs2/quota.h
35 create mode 100644 fs/ocfs2/quota_global.c
36 create mode 100644 fs/ocfs2/quota_local.c
38 Index: linux-2.6.27-ocfs2/fs/ocfs2/Makefile
39 ===================================================================
40 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/Makefile
41 +++ linux-2.6.27-ocfs2/fs/ocfs2/Makefile
42 @@ -35,6 +35,8 @@ ocfs2-objs := \
50 ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y)
51 Index: linux-2.6.27-ocfs2/fs/ocfs2/cluster/masklog.h
52 ===================================================================
53 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/cluster/masklog.h
54 +++ linux-2.6.27-ocfs2/fs/ocfs2/cluster/masklog.h
56 #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
57 #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
58 #define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
59 +#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
60 /* bits that are infrequently given and frequently matched in the high word */
61 #define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
62 #define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
63 Index: linux-2.6.27-ocfs2/fs/ocfs2/dlmglue.c
64 ===================================================================
65 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/dlmglue.c
66 +++ linux-2.6.27-ocfs2/fs/ocfs2/dlmglue.c
68 #include <linux/debugfs.h>
69 #include <linux/seq_file.h>
70 #include <linux/time.h>
71 +#include <linux/quotaops.h>
73 #define MLOG_MASK_PREFIX ML_DLM_GLUE
74 #include <cluster/masklog.h>
81 #include "buffer_head_io.h"
83 @@ -68,6 +70,7 @@ struct ocfs2_mask_waiter {
84 static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres);
85 static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres);
86 static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres);
87 +static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres);
90 * Return value from ->downconvert_worker functions.
91 @@ -102,6 +105,7 @@ static int ocfs2_dentry_convert_worker(s
92 static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
93 struct ocfs2_lock_res *lockres);
95 +static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
97 #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
99 @@ -258,6 +262,12 @@ static struct ocfs2_lock_res_ops ocfs2_f
103 +static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
104 + .set_lvb = ocfs2_set_qinfo_lvb,
105 + .get_osb = ocfs2_get_qinfo_osb,
106 + .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
109 static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
111 return lockres->l_type == OCFS2_LOCK_TYPE_META ||
112 @@ -279,6 +289,13 @@ static inline struct ocfs2_dentry_lock *
113 return (struct ocfs2_dentry_lock *)lockres->l_priv;
116 +static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_res *lockres)
118 + BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO);
120 + return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
123 static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
125 if (lockres->l_ops->get_osb)
126 @@ -507,6 +524,13 @@ static struct ocfs2_super *ocfs2_get_ino
127 return OCFS2_SB(inode->i_sb);
130 +static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres)
132 + struct ocfs2_mem_dqinfo *info = lockres->l_priv;
134 + return OCFS2_SB(info->dqi_gi.dqi_sb);
137 static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres)
139 struct ocfs2_file_private *fp = lockres->l_priv;
140 @@ -609,6 +633,17 @@ void ocfs2_file_lock_res_init(struct ocf
141 lockres->l_flags |= OCFS2_LOCK_NOCACHE;
144 +void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
145 + struct ocfs2_mem_dqinfo *info)
147 + ocfs2_lock_res_init_once(lockres);
148 + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_QINFO, info->dqi_gi.dqi_type,
149 + 0, lockres->l_name);
150 + ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres,
151 + OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops,
155 void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
158 @@ -3449,6 +3484,108 @@ static int ocfs2_dentry_convert_worker(s
159 return UNBLOCK_CONTINUE_POST;
162 +static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
164 + struct ocfs2_qinfo_lvb *lvb;
165 + struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
166 + struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
167 + oinfo->dqi_gi.dqi_type);
171 + lvb = (struct ocfs2_qinfo_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
172 + lvb->lvb_version = OCFS2_LVB_VERSION;
173 + lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
174 + lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
175 + lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
176 + lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
177 + lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
178 + lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
183 +void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
185 + struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
186 + struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
187 + int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
190 + if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
191 + ocfs2_cluster_unlock(osb, lockres, level);
195 +/* Lock quota info, this function expects at least shared lock on the quota file
196 + * so that we can safely refresh quota info from disk. */
197 +int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
199 + struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
200 + oinfo->dqi_gi.dqi_type);
201 + struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
202 + struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
203 + struct ocfs2_qinfo_lvb *lvb;
204 + int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
206 + struct buffer_head *bh;
207 + struct ocfs2_global_disk_dqinfo *gdinfo;
211 + /* We'll allow faking a readonly metadata lock for
213 + if (ocfs2_is_hard_readonly(osb)) {
218 + if (ocfs2_mount_local(osb))
221 + status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
223 + mlog_errno(status);
226 + if (!ocfs2_should_refresh_lock_res(lockres))
228 + /* OK, we have the lock but we need to refresh the quota info */
229 + lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
230 + if (lvb->lvb_version == OCFS2_LVB_VERSION) {
231 + info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
232 + info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
233 + oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
234 + oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
235 + oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
236 + oinfo->dqi_gi.dqi_free_entry =
237 + be32_to_cpu(lvb->lvb_free_entry);
239 + bh = ocfs2_bread(oinfo->dqi_gqinode, 0, &status, 0);
241 + ocfs2_qinfo_unlock(oinfo, ex);
242 + mlog_errno(status);
245 + gdinfo = (struct ocfs2_global_disk_dqinfo *)
246 + (bh->b_data + OCFS2_GLOBAL_INFO_OFF);
247 + info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
248 + info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
249 + oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
250 + oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
251 + oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
252 + oinfo->dqi_gi.dqi_free_entry =
253 + le32_to_cpu(gdinfo->dqi_free_entry);
255 + ocfs2_track_lock_refresh(lockres);
258 + ocfs2_complete_lock_res_refresh(lockres, status);
265 * This is the filesystem locking protocol. It provides the lock handling
266 * hooks for the underlying DLM. It has a maximum version number.
267 Index: linux-2.6.27-ocfs2/fs/ocfs2/dlmglue.h
268 ===================================================================
269 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/dlmglue.h
270 +++ linux-2.6.27-ocfs2/fs/ocfs2/dlmglue.h
271 @@ -49,6 +49,17 @@ struct ocfs2_meta_lvb {
272 __be32 lvb_reserved2;
275 +struct ocfs2_qinfo_lvb {
277 + __u8 lvb_reserved[3];
282 + __be32 lvb_free_blk;
283 + __be32 lvb_free_entry;
286 /* ocfs2_inode_lock_full() 'arg_flags' flags */
287 /* don't wait on recovery. */
288 #define OCFS2_META_LOCK_RECOVERY (0x01)
289 @@ -69,6 +80,9 @@ void ocfs2_dentry_lock_res_init(struct o
290 struct ocfs2_file_private;
291 void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
292 struct ocfs2_file_private *fp);
293 +struct ocfs2_mem_dqinfo;
294 +void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
295 + struct ocfs2_mem_dqinfo *info);
296 void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
297 int ocfs2_create_new_inode_locks(struct inode *inode);
298 int ocfs2_drop_inode_locks(struct inode *inode);
299 @@ -103,6 +117,9 @@ int ocfs2_dentry_lock(struct dentry *den
300 void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
301 int ocfs2_file_lock(struct file *file, int ex, int trylock);
302 void ocfs2_file_unlock(struct file *file);
303 +int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex);
304 +void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex);
307 void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
308 void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
309 Index: linux-2.6.27-ocfs2/fs/ocfs2/file.c
310 ===================================================================
311 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/file.c
312 +++ linux-2.6.27-ocfs2/fs/ocfs2/file.c
313 @@ -304,9 +304,9 @@ bail:
317 -static int ocfs2_simple_size_update(struct inode *inode,
318 - struct buffer_head *di_bh,
320 +int ocfs2_simple_size_update(struct inode *inode,
321 + struct buffer_head *di_bh,
325 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
326 Index: linux-2.6.27-ocfs2/fs/ocfs2/file.h
327 ===================================================================
328 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/file.h
329 +++ linux-2.6.27-ocfs2/fs/ocfs2/file.h
330 @@ -51,6 +51,9 @@ int ocfs2_add_inode_data(struct ocfs2_su
331 struct ocfs2_alloc_context *data_ac,
332 struct ocfs2_alloc_context *meta_ac,
333 enum ocfs2_alloc_restarted *reason_ret);
334 +int ocfs2_simple_size_update(struct inode *inode,
335 + struct buffer_head *di_bh,
337 int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
339 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
340 Index: linux-2.6.27-ocfs2/fs/ocfs2/journal.h
341 ===================================================================
342 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/journal.h
343 +++ linux-2.6.27-ocfs2/fs/ocfs2/journal.h
344 @@ -357,6 +357,21 @@ int ocfs2_journal_dirty
345 + OCFS2_INODE_UPDATE_CREDITS \
346 + OCFS2_XATTR_BLOCK_UPDATE_CREDITS)
348 +/* global quotafile inode update, data block */
349 +#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
352 + * The two writes below can accidentally see global info dirty due
353 + * to set_info() quotactl so make them prepared for the writes.
355 +/* quota data block, global info */
356 +/* Write to local quota file */
357 +#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
359 +/* global quota data block, local quota data block, global quota inode,
360 + * global quota info */
361 +#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
364 * Please note that the caller must make sure that root_el is the root
365 * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
366 Index: linux-2.6.27-ocfs2/fs/ocfs2/ocfs2_fs.h
367 ===================================================================
368 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/ocfs2_fs.h
369 +++ linux-2.6.27-ocfs2/fs/ocfs2/ocfs2_fs.h
370 @@ -859,6 +859,101 @@ struct ocfs2_xattr_block {
375 + * On disk structures for global quota file
378 +/* Magic numbers and known versions for global quota files */
379 +#define OCFS2_GLOBAL_QMAGICS {\
380 + 0x0cf52470, /* USRQUOTA */ \
381 + 0x0cf52471 /* GRPQUOTA */ \
384 +#define OCFS2_GLOBAL_QVERSIONS {\
389 +/* Generic header of all quota files */
390 +struct ocfs2_disk_dqheader {
391 + __le32 dqh_magic; /* Magic number identifying file */
392 + __le32 dqh_version; /* Quota format version */
395 +#define OCFS2_GLOBAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
397 +/* Information header of global quota file (immediately follows the generic
399 +struct ocfs2_global_disk_dqinfo {
400 +/*00*/ __le32 dqi_bgrace;
404 +/*10*/ __le32 dqi_free_blk;
405 + __le32 dqi_free_entry;
408 +/* Structure with global user / group information. We reserve some space
409 + * for future use. */
410 +struct ocfs2_global_disk_dqblk {
411 +/*00*/ __le32 dqb_id; /* ID the structure belongs to */
412 + __le32 dqb_use_count; /* Number of nodes having reference to this structure */
413 + __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
414 +/*10*/ __le64 dqb_isoftlimit; /* preferred inode limit */
415 + __le64 dqb_curinodes; /* current # allocated inodes */
416 +/*20*/ __le64 dqb_bhardlimit; /* absolute limit on disk space */
417 + __le64 dqb_bsoftlimit; /* preferred limit on disk space */
418 +/*30*/ __le64 dqb_curspace; /* current space occupied */
419 + __le64 dqb_btime; /* time limit for excessive disk use */
420 +/*40*/ __le64 dqb_itime; /* time limit for excessive inode use */
422 +/*50*/ __le64 dqb_pad2;
426 + * On-disk structures for local quota file
429 +/* Magic numbers and known versions for local quota files */
430 +#define OCFS2_LOCAL_QMAGICS {\
431 + 0x0cf524c0, /* USRQUOTA */ \
432 + 0x0cf524c1 /* GRPQUOTA */ \
435 +#define OCFS2_LOCAL_QVERSIONS {\
440 +/* Quota flags in dqinfo header */
441 +#define OLQF_CLEAN 0x0001 /* Quota file is empty (this should be after\
442 + * quota has been cleanly turned off) */
444 +#define OCFS2_LOCAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
446 +/* Information header of local quota file (immediately follows the generic
448 +struct ocfs2_local_disk_dqinfo {
449 + __le32 dqi_flags; /* Flags for quota file */
450 + __le32 dqi_chunks; /* Number of chunks of quota structures
452 + __le32 dqi_blocks; /* Number of blocks allocated for quota file */
455 +/* Header of one chunk of a quota file */
456 +struct ocfs2_local_disk_chunk {
457 + __le32 dqc_free; /* Number of free entries in the bitmap */
458 + u8 dqc_bitmap[0]; /* Bitmap of entries in the corresponding
459 + * chunk of quota file */
462 +/* One entry in local quota file */
463 +struct ocfs2_local_disk_dqblk {
464 +/*00*/ __le64 dqb_id; /* id this quota applies to */
465 + __le64 dqb_spacemod; /* Change in the amount of used space */
466 +/*10*/ __le64 dqb_inodemod; /* Change in the amount of used inodes */
469 #define OCFS2_XATTR_ENTRY_LOCAL 0x80
470 #define OCFS2_XATTR_TYPE_MASK 0x7F
471 static inline void ocfs2_xattr_set_local(struct ocfs2_xattr_entry *xe,
472 Index: linux-2.6.27-ocfs2/fs/ocfs2/ocfs2_lockid.h
473 ===================================================================
474 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/ocfs2_lockid.h
475 +++ linux-2.6.27-ocfs2/fs/ocfs2/ocfs2_lockid.h
476 @@ -46,6 +46,7 @@ enum ocfs2_lock_type {
477 OCFS2_LOCK_TYPE_DENTRY,
478 OCFS2_LOCK_TYPE_OPEN,
479 OCFS2_LOCK_TYPE_FLOCK,
480 + OCFS2_LOCK_TYPE_QINFO,
484 @@ -77,6 +78,9 @@ static inline char ocfs2_lock_type_char(
485 case OCFS2_LOCK_TYPE_FLOCK:
488 + case OCFS2_LOCK_TYPE_QINFO:
494 @@ -95,6 +99,7 @@ static char *ocfs2_lock_type_strings[] =
495 [OCFS2_LOCK_TYPE_DENTRY] = "Dentry",
496 [OCFS2_LOCK_TYPE_OPEN] = "Open",
497 [OCFS2_LOCK_TYPE_FLOCK] = "Flock",
498 + [OCFS2_LOCK_TYPE_QINFO] = "Quota",
501 static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
502 Index: linux-2.6.27-ocfs2/fs/ocfs2/quota.h
503 ===================================================================
505 +++ linux-2.6.27-ocfs2/fs/ocfs2/quota.h
508 + * quota.h for OCFS2
510 + * On disk quota structures for local and global quota file, in-memory
515 +#ifndef _OCFS2_QUOTA_H
516 +#define _OCFS2_QUOTA_H
518 +#include <linux/types.h>
519 +#include <linux/slab.h>
520 +#include <linux/quota.h>
521 +#include <linux/list.h>
522 +#include <linux/dqblk_qtree.h>
527 +/* id number of quota format */
528 +#define QFMT_OCFS2 3
530 +/* How many bytes to we reserve in each quota file block for our internal
531 + * purposes? E.g. checksums... */
532 +#define OCFS2_QBLK_RESERVED_SPACE 8
535 + * In-memory structures
537 +struct ocfs2_dquot {
538 + struct dquot dq_dquot; /* Generic VFS dquot */
539 + loff_t dq_local_off; /* Offset in the local quota file */
540 + struct ocfs2_quota_chunk *dq_chunk; /* Chunk dquot is in */
541 + unsigned int dq_use_count; /* Number of nodes having reference to this entry in global quota file */
542 + s64 dq_origspace; /* Last globally synced space usage */
543 + s64 dq_originodes; /* Last globally synced inode usage */
546 +/* In-memory structure with quota header information */
547 +struct ocfs2_mem_dqinfo {
548 + unsigned int dqi_type; /* Quota type this structure describes */
549 + unsigned int dqi_chunks; /* Number of chunks in local quota file */
550 + unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
551 + unsigned int dqi_syncms; /* How often should we sync with other nodes */
552 + struct list_head dqi_chunk; /* List of chunks */
553 + struct inode *dqi_gqinode; /* Global quota file inode */
554 + struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
555 + struct buffer_head *dqi_gqi_bh; /* Buffer head with global quota file inode - set only if inode lock is obtained */
556 + int dqi_gqi_count; /* Number of holders of dqi_gqi_bh */
557 + struct buffer_head *dqi_lqi_bh; /* Buffer head with local quota file inode */
558 + struct buffer_head *dqi_ibh; /* Buffer with information header */
559 + struct qtree_mem_dqinfo dqi_gi; /* Info about global file */
562 +static inline struct ocfs2_dquot *OCFS2_DQUOT(struct dquot *dquot)
564 + return container_of(dquot, struct ocfs2_dquot, dq_dquot);
567 +struct ocfs2_quota_chunk {
568 + struct list_head qc_chunk; /* List of quotafile chunks */
569 + int qc_num; /* Number of quota chunk */
570 + struct buffer_head *qc_headerbh; /* Buffer head with chunk header */
573 +extern struct kmem_cache *ocfs2_dquot_cachep;
574 +extern struct kmem_cache *ocfs2_qf_chunk_cachep;
576 +extern struct qtree_fmt_operations ocfs2_global_ops;
578 +ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
579 + size_t len, loff_t off);
580 +ssize_t ocfs2_quota_write(struct super_block *sb, int type,
581 + const char *data, size_t len, loff_t off);
582 +int ocfs2_global_read_info(struct super_block *sb, int type);
583 +int ocfs2_global_write_info(struct super_block *sb, int type);
584 +int ocfs2_global_read_dquot(struct dquot *dquot);
585 +int __ocfs2_sync_dquot(struct dquot *dquot, int freeing);
586 +static inline int ocfs2_sync_dquot(struct dquot *dquot)
588 + return __ocfs2_sync_dquot(dquot, 0);
590 +static inline int ocfs2_global_release_dquot(struct dquot *dquot)
592 + return __ocfs2_sync_dquot(dquot, 1);
595 +int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
596 +void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
598 +int init_ocfs2_quota_format(void);
599 +void exit_ocfs2_quota_format(void);
601 +extern struct dquot_operations ocfs2_quota_operations;
603 +#endif /* _OCFS2_QUOTA_H */
604 Index: linux-2.6.27-ocfs2/fs/ocfs2/quota_global.c
605 ===================================================================
607 +++ linux-2.6.27-ocfs2/fs/ocfs2/quota_global.c
610 + * Implementation of operations over global quota file
612 +#include <linux/fs.h>
613 +#include <linux/quota.h>
614 +#include <linux/quotaops.h>
615 +#include <linux/dqblk_qtree.h>
617 +#define MLOG_MASK_PREFIX ML_QUOTA
618 +#include <cluster/masklog.h>
620 +#include "ocfs2_fs.h"
624 +#include "journal.h"
626 +#include "sysfile.h"
627 +#include "dlmglue.h"
630 +static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
632 + struct ocfs2_global_disk_dqblk *d = dp;
633 + struct mem_dqblk *m = &dquot->dq_dqb;
635 + /* Update from disk only entries not set by the admin */
636 + if (!test_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags)) {
637 + m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
638 + m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
640 + if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
641 + m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
642 + if (!test_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags)) {
643 + m->dqb_bhardlimit = le64_to_cpu(d->dqb_bhardlimit);
644 + m->dqb_bsoftlimit = le64_to_cpu(d->dqb_bsoftlimit);
646 + if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
647 + m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
648 + if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags))
649 + m->dqb_btime = le64_to_cpu(d->dqb_btime);
650 + if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags))
651 + m->dqb_itime = le64_to_cpu(d->dqb_itime);
652 + OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count);
655 +static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
657 + struct ocfs2_global_disk_dqblk *d = dp;
658 + struct mem_dqblk *m = &dquot->dq_dqb;
660 + d->dqb_id = cpu_to_le32(dquot->dq_id);
661 + d->dqb_use_count = cpu_to_le32(OCFS2_DQUOT(dquot)->dq_use_count);
662 + d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
663 + d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
664 + d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
665 + d->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
666 + d->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
667 + d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
668 + d->dqb_btime = cpu_to_le64(m->dqb_btime);
669 + d->dqb_itime = cpu_to_le64(m->dqb_itime);
670 + d->dqb_pad1 = d->dqb_pad2 = 0;
673 +static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
675 + struct ocfs2_global_disk_dqblk *d = dp;
676 + struct ocfs2_mem_dqinfo *oinfo =
677 + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
679 + if (qtree_entry_unused(&oinfo->dqi_gi, dp))
681 + return le32_to_cpu(d->dqb_id) == dquot->dq_id;
684 +struct qtree_fmt_operations ocfs2_global_ops = {
685 + .mem2disk_dqblk = ocfs2_global_mem2diskdqb,
686 + .disk2mem_dqblk = ocfs2_global_disk2memdqb,
687 + .is_id = ocfs2_global_is_id,
690 +/* Read data from global quotafile - avoid pagecache and such because we cannot
691 + * afford acquiring the locks... We use quota cluster lock to serialize
692 + * operations. Caller is responsible for acquiring it. */
693 +ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
694 + size_t len, loff_t off)
696 + struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
697 + struct inode *gqinode = oinfo->dqi_gqinode;
698 + loff_t i_size = i_size_read(gqinode);
699 + int offset = off & (sb->s_blocksize - 1);
700 + sector_t blk = off >> sb->s_blocksize_bits;
702 + struct buffer_head *bh;
703 + size_t toread, tocopy;
707 + if (off + len > i_size)
708 + len = i_size - off;
710 + while (toread > 0) {
711 + tocopy = min(sb->s_blocksize - offset, toread);
712 + bh = ocfs2_bread(gqinode, blk, &err, 0);
717 + memcpy(data, bh->b_data + offset, tocopy);
727 +/* Write to quotafile (we know the transaction is already started and has
728 + * enough credits) */
729 +ssize_t ocfs2_quota_write(struct super_block *sb, int type,
730 + const char *data, size_t len, loff_t off)
732 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
733 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
734 + struct inode *gqinode = oinfo->dqi_gqinode;
735 + int offset = off & (sb->s_blocksize - 1);
736 + sector_t blk = off >> sb->s_blocksize_bits;
738 + struct buffer_head *bh;
739 + handle_t *handle = journal_current_handle();
740 + size_t tocopy, towrite = len;
743 + mlog(ML_ERROR, "Quota write (off=%llu, len=%llu) cancelled "
744 + "because transaction was not started.\n",
745 + (unsigned long long)off, (unsigned long long)len);
748 + mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
749 + if (gqinode->i_size < off + len) {
750 + down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
751 + err = ocfs2_extend_no_holes(gqinode, off + len, off);
752 + up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
755 + err = ocfs2_simple_size_update(gqinode,
761 + WARN_ON(off >> sb->s_blocksize_bits != \
762 + (off + len) >> sb->s_blocksize_bits);
763 + WARN_ON(((off + len) & ((1 << sb->s_blocksize_bits) - 1)) >
764 + sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE);
765 + for (towrite = len; towrite > 0; towrite -= tocopy) {
766 + tocopy = min(towrite, sb->s_blocksize - offset);
767 + bh = ocfs2_bread(gqinode, blk, &err, 0);
772 + err = ocfs2_journal_access(handle, gqinode, bh,
773 + OCFS2_JOURNAL_ACCESS_WRITE);
779 + memcpy(bh->b_data + offset, data, tocopy);
780 + flush_dcache_page(bh->b_page);
782 + err = ocfs2_journal_dirty(handle, bh);
791 + /* Nothing written? */
792 + if (len == towrite) {
793 + mutex_unlock(&gqinode->i_mutex);
797 + gqinode->i_version++;
798 + ocfs2_mark_inode_dirty(handle, gqinode, oinfo->dqi_gqi_bh);
799 + mutex_unlock(&gqinode->i_mutex);
800 + return len - towrite;
803 +int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
806 + struct buffer_head *bh = NULL;
808 + status = ocfs2_inode_lock(oinfo->dqi_gqinode, &bh, ex);
811 + spin_lock(&dq_data_lock);
812 + if (!oinfo->dqi_gqi_count++)
813 + oinfo->dqi_gqi_bh = bh;
815 + WARN_ON(bh != oinfo->dqi_gqi_bh);
816 + spin_unlock(&dq_data_lock);
820 +void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
822 + ocfs2_inode_unlock(oinfo->dqi_gqinode, ex);
823 + brelse(oinfo->dqi_gqi_bh);
824 + spin_lock(&dq_data_lock);
825 + if (!--oinfo->dqi_gqi_count)
826 + oinfo->dqi_gqi_bh = NULL;
827 + spin_unlock(&dq_data_lock);
830 +/* Read information header from global quota file */
831 +int ocfs2_global_read_info(struct super_block *sb, int type)
833 + struct inode *gqinode = NULL;
834 + unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
835 + GROUP_QUOTA_SYSTEM_INODE };
836 + struct ocfs2_global_disk_dqinfo dinfo;
837 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
838 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
843 + /* Read global header */
844 + gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
845 + OCFS2_INVALID_SLOT);
847 + mlog(ML_ERROR, "failed to get global quota inode (type=%d)\n",
852 + oinfo->dqi_gi.dqi_sb = sb;
853 + oinfo->dqi_gi.dqi_type = type;
854 + ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
855 + oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
856 + oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
857 + oinfo->dqi_gqi_bh = NULL;
858 + oinfo->dqi_gqi_count = 0;
859 + oinfo->dqi_gqinode = gqinode;
860 + status = ocfs2_lock_global_qf(oinfo, 0);
862 + mlog_errno(status);
865 + status = sb->s_op->quota_read(sb, type, (char *)&dinfo,
866 + sizeof(struct ocfs2_global_disk_dqinfo),
867 + OCFS2_GLOBAL_INFO_OFF);
868 + ocfs2_unlock_global_qf(oinfo, 0);
869 + if (status != sizeof(struct ocfs2_global_disk_dqinfo)) {
870 + mlog(ML_ERROR, "Cannot read global quota info (%d).\n",
874 + mlog_errno(status);
877 + info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
878 + info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
879 + oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
880 + oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
881 + oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
882 + oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
883 + oinfo->dqi_gi.dqi_blocksize_bits = sb->s_blocksize_bits;
884 + oinfo->dqi_gi.dqi_usable_bs = sb->s_blocksize -
885 + OCFS2_QBLK_RESERVED_SPACE;
886 + oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
892 +/* Write information to global quota file. Expects exlusive lock on quota
893 + * file inode and quota info */
894 +static int __ocfs2_global_write_info(struct super_block *sb, int type)
896 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
897 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
898 + struct ocfs2_global_disk_dqinfo dinfo;
901 + spin_lock(&dq_data_lock);
902 + info->dqi_flags &= ~DQF_INFO_DIRTY;
903 + dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
904 + dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
905 + spin_unlock(&dq_data_lock);
906 + dinfo.dqi_syncms = cpu_to_le32(oinfo->dqi_syncms);
907 + dinfo.dqi_blocks = cpu_to_le32(oinfo->dqi_gi.dqi_blocks);
908 + dinfo.dqi_free_blk = cpu_to_le32(oinfo->dqi_gi.dqi_free_blk);
909 + dinfo.dqi_free_entry = cpu_to_le32(oinfo->dqi_gi.dqi_free_entry);
910 + size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
911 + sizeof(struct ocfs2_global_disk_dqinfo),
912 + OCFS2_GLOBAL_INFO_OFF);
913 + if (size != sizeof(struct ocfs2_global_disk_dqinfo)) {
914 + mlog(ML_ERROR, "Cannot write global quota info structure\n");
922 +int ocfs2_global_write_info(struct super_block *sb, int type)
925 + struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
927 + err = ocfs2_qinfo_lock(info, 1);
930 + err = __ocfs2_global_write_info(sb, type);
931 + ocfs2_qinfo_unlock(info, 1);
935 +/* Read in information from global quota file and acquire a reference to it.
936 + * dquot_acquire() has already started the transaction and locked quota file */
937 +int ocfs2_global_read_dquot(struct dquot *dquot)
939 + int err, err2, ex = 0;
940 + struct ocfs2_mem_dqinfo *info =
941 + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
943 + err = ocfs2_qinfo_lock(info, 0);
946 + err = qtree_read_dquot(&info->dqi_gi, dquot);
949 + OCFS2_DQUOT(dquot)->dq_use_count++;
950 + OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
951 + OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
952 + if (!dquot->dq_off) { /* No real quota entry? */
953 + /* Upgrade to exclusive lock for allocation */
954 + err = ocfs2_qinfo_lock(info, 1);
959 + err = qtree_write_dquot(&info->dqi_gi, dquot);
960 + if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
961 + err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
967 + ocfs2_qinfo_unlock(info, 1);
968 + ocfs2_qinfo_unlock(info, 0);
975 +/* Sync local information about quota modifications with global quota file.
976 + * Caller must have started the transaction and obtained exclusive lock for
977 + * global quota file inode */
978 +int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
981 + struct super_block *sb = dquot->dq_sb;
982 + int type = dquot->dq_type;
983 + struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
984 + struct ocfs2_global_disk_dqblk dqblk;
985 + s64 spacechange, inodechange;
986 + time_t olditime, oldbtime;
988 + err = sb->s_op->quota_read(sb, type, (char *)&dqblk,
989 + sizeof(struct ocfs2_global_disk_dqblk),
991 + if (err != sizeof(struct ocfs2_global_disk_dqblk)) {
993 + mlog(ML_ERROR, "Short read from global quota file "
994 + "(%u read)\n", err);
1000 + /* Update space and inode usage. Get also other information from
1001 + * global quota file so that we don't overwrite any changes there.
1003 + spin_lock(&dq_data_lock);
1004 + spacechange = dquot->dq_dqb.dqb_curspace -
1005 + OCFS2_DQUOT(dquot)->dq_origspace;
1006 + inodechange = dquot->dq_dqb.dqb_curinodes -
1007 + OCFS2_DQUOT(dquot)->dq_originodes;
1008 + olditime = dquot->dq_dqb.dqb_itime;
1009 + oldbtime = dquot->dq_dqb.dqb_btime;
1010 + ocfs2_global_disk2memdqb(dquot, &dqblk);
1011 + mlog(0, "Syncing global dquot %d space %lld+%lld, inodes %lld+%lld\n",
1012 + dquot->dq_id, dquot->dq_dqb.dqb_curspace, spacechange,
1013 + dquot->dq_dqb.dqb_curinodes, inodechange);
1014 + if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
1015 + dquot->dq_dqb.dqb_curspace += spacechange;
1016 + if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
1017 + dquot->dq_dqb.dqb_curinodes += inodechange;
1018 + /* Now merge grace time changes... */
1019 + if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags) &&
1021 + if (dquot->dq_dqb.dqb_btime > 0)
1022 + dquot->dq_dqb.dqb_btime =
1023 + min(dquot->dq_dqb.dqb_btime, oldbtime);
1025 + dquot->dq_dqb.dqb_btime = oldbtime;
1027 + if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags) &&
1029 + if (dquot->dq_dqb.dqb_itime > 0)
1030 + dquot->dq_dqb.dqb_itime =
1031 + min(dquot->dq_dqb.dqb_itime, olditime);
1033 + dquot->dq_dqb.dqb_itime = olditime;
1035 + /* All information is properly updated, clear the flags */
1036 + __clear_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
1037 + __clear_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
1038 + __clear_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
1039 + __clear_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
1040 + __clear_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
1041 + __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
1042 + OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
1043 + OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
1044 + spin_unlock(&dq_data_lock);
1045 + err = ocfs2_qinfo_lock(info, freeing);
1047 + mlog(ML_ERROR, "Failed to lock quota info, loosing quota write"
1048 + " (type=%d, id=%u)\n", dquot->dq_type,
1049 + (unsigned)dquot->dq_id);
1053 + OCFS2_DQUOT(dquot)->dq_use_count--;
1054 + err = qtree_write_dquot(&info->dqi_gi, dquot);
1057 + if (freeing && !OCFS2_DQUOT(dquot)->dq_use_count) {
1058 + err = qtree_release_dquot(&info->dqi_gi, dquot);
1059 + if (info_dirty(sb_dqinfo(sb, type))) {
1060 + err2 = __ocfs2_global_write_info(sb, type);
1066 + ocfs2_qinfo_unlock(info, freeing);
1074 + * Wrappers for generic quota functions
1077 +static int ocfs2_write_dquot(struct dquot *dquot)
1080 + struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
1083 + mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
1085 + handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS);
1086 + if (IS_ERR(handle)) {
1087 + status = PTR_ERR(handle);
1088 + mlog_errno(status);
1091 + status = dquot_commit(dquot);
1092 + ocfs2_commit_trans(osb, handle);
1094 + mlog_exit(status);
1098 +int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
1100 + struct ocfs2_mem_dqinfo *oinfo;
1101 + int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
1102 + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
1104 + if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
1107 + oinfo = sb_dqinfo(sb, type)->dqi_priv;
1108 + /* We modify tree, leaf block, global info, local chunk header,
1109 + * global and local inode */
1110 + return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
1111 + 2 * OCFS2_INODE_UPDATE_CREDITS;
1114 +static int ocfs2_release_dquot(struct dquot *dquot)
1117 + struct ocfs2_mem_dqinfo *oinfo =
1118 + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
1119 + struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
1122 + mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
1124 + status = ocfs2_lock_global_qf(oinfo, 1);
1127 + handle = ocfs2_start_trans(osb,
1128 + ocfs2_calc_qdel_credits(dquot->dq_sb, dquot->dq_type));
1129 + if (IS_ERR(handle)) {
1130 + status = PTR_ERR(handle);
1131 + mlog_errno(status);
1134 + status = dquot_release(dquot);
1135 + ocfs2_commit_trans(osb, handle);
1137 + ocfs2_unlock_global_qf(oinfo, 1);
1139 + mlog_exit(status);
1143 +int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
1145 + struct ocfs2_mem_dqinfo *oinfo;
1146 + struct ocfs2_dinode *lfe, *gfe;
1147 + int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
1148 + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
1150 + if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
1153 + oinfo = sb_dqinfo(sb, type)->dqi_priv;
1154 + gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
1155 + lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
1156 + /* We can extend local file + global file. In local file we
1157 + * can modify info, chunk header block and dquot block. In
1158 + * global file we can modify info, tree and leaf block */
1159 + return ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
1160 + ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
1161 + 3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
1164 +static int ocfs2_acquire_dquot(struct dquot *dquot)
1167 + struct ocfs2_mem_dqinfo *oinfo =
1168 + sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
1169 + struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
1172 + mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
1173 + /* We need an exclusive lock, because we're going to update use count
1174 + * and instantiate possibly new dquot structure */
1175 + status = ocfs2_lock_global_qf(oinfo, 1);
1178 + handle = ocfs2_start_trans(osb,
1179 + ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
1180 + if (IS_ERR(handle)) {
1181 + status = PTR_ERR(handle);
1182 + mlog_errno(status);
1185 + status = dquot_acquire(dquot);
1186 + ocfs2_commit_trans(osb, handle);
1188 + ocfs2_unlock_global_qf(oinfo, 1);
1190 + mlog_exit(status);
1194 +static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
1196 + unsigned long mask = (1 << (DQ_LASTSET_B + QIF_ILIMITS_B)) |
1197 + (1 << (DQ_LASTSET_B + QIF_BLIMITS_B)) |
1198 + (1 << (DQ_LASTSET_B + QIF_INODES_B)) |
1199 + (1 << (DQ_LASTSET_B + QIF_SPACE_B)) |
1200 + (1 << (DQ_LASTSET_B + QIF_BTIME_B)) |
1201 + (1 << (DQ_LASTSET_B + QIF_ITIME_B));
1204 + struct super_block *sb = dquot->dq_sb;
1205 + int type = dquot->dq_type;
1206 + struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
1208 + struct ocfs2_super *osb = OCFS2_SB(sb);
1210 + mlog_entry("id=%u, type=%d", dquot->dq_id, type);
1211 + dquot_mark_dquot_dirty(dquot);
1213 + /* In case user set some limits, sync dquot immediately to global
1214 + * quota file so that information propagates quicker */
1215 + spin_lock(&dq_data_lock);
1216 + if (dquot->dq_flags & mask)
1218 + spin_unlock(&dq_data_lock);
1220 + status = ocfs2_write_dquot(dquot);
1223 + status = ocfs2_lock_global_qf(oinfo, 1);
1226 + handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
1227 + if (IS_ERR(handle)) {
1228 + status = PTR_ERR(handle);
1229 + mlog_errno(status);
1232 + status = ocfs2_sync_dquot(dquot);
1234 + mlog_errno(status);
1237 + /* Now write updated local dquot structure */
1238 + status = dquot_commit(dquot);
1240 + ocfs2_commit_trans(osb, handle);
1242 + ocfs2_unlock_global_qf(oinfo, 1);
1244 + mlog_exit(status);
1248 +/* This should happen only after set_dqinfo(). */
1249 +static int ocfs2_write_info(struct super_block *sb, int type)
1253 + struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
1255 + mlog_entry_void();
1257 + status = ocfs2_lock_global_qf(oinfo, 1);
1260 + handle = ocfs2_start_trans(OCFS2_SB(sb), OCFS2_QINFO_WRITE_CREDITS);
1261 + if (IS_ERR(handle)) {
1262 + status = PTR_ERR(handle);
1263 + mlog_errno(status);
1266 + status = dquot_commit_info(sb, type);
1267 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
1269 + ocfs2_unlock_global_qf(oinfo, 1);
1271 + mlog_exit(status);
1275 +/* This is difficult. We have to lock quota inode and start transaction
1276 + * in this function but we don't want to take the penalty of exlusive
1277 + * quota file lock when we are just going to use cached structures. So
1278 + * we just take read lock check whether we have dquot cached and if so,
1279 + * we don't have to take the write lock... */
1280 +static int ocfs2_dquot_initialize(struct inode *inode, int type)
1282 + handle_t *handle = NULL;
1284 + struct super_block *sb = inode->i_sb;
1285 + struct ocfs2_mem_dqinfo *oinfo;
1286 + int exclusive = 0;
1290 + mlog_entry_void();
1292 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1293 + if (type != -1 && cnt != type)
1295 + oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
1296 + status = ocfs2_lock_global_qf(oinfo, 0);
1299 + /* This is just a performance optimization not a reliable test.
1300 + * Since we hold an inode lock, noone can actually release
1301 + * the structure until we are finished with initialization. */
1302 + if (inode->i_dquot[cnt] != NODQUOT) {
1303 + ocfs2_unlock_global_qf(oinfo, 0);
1306 + /* When we have inode lock, we know that no dquot_release() can
1307 + * run and thus we can safely check whether we need to
1308 + * read+modify global file to get quota information or whether
1309 + * our node already has it. */
1310 + if (cnt == USRQUOTA)
1311 + id = inode->i_uid;
1312 + else if (cnt == GRPQUOTA)
1313 + id = inode->i_gid;
1316 + /* Obtain exclusion from quota off... */
1317 + down_write(&sb_dqopt(sb)->dqptr_sem);
1318 + exclusive = !dquot_is_cached(sb, id, cnt);
1319 + up_write(&sb_dqopt(sb)->dqptr_sem);
1321 + status = ocfs2_lock_global_qf(oinfo, 1);
1324 + mlog_errno(status);
1327 + handle = ocfs2_start_trans(OCFS2_SB(sb),
1328 + ocfs2_calc_qinit_credits(sb, cnt));
1329 + if (IS_ERR(handle)) {
1330 + status = PTR_ERR(handle);
1331 + mlog_errno(status);
1335 + dquot_initialize(inode, cnt);
1337 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
1338 + ocfs2_unlock_global_qf(oinfo, 1);
1340 + ocfs2_unlock_global_qf(oinfo, 0);
1346 + ocfs2_unlock_global_qf(oinfo, 1);
1347 + ocfs2_unlock_global_qf(oinfo, 0);
1349 + mlog_exit(status);
1353 +static int ocfs2_dquot_drop_slow(struct inode *inode)
1357 + int got_lock[MAXQUOTAS] = {0, 0};
1359 + struct super_block *sb = inode->i_sb;
1360 + struct ocfs2_mem_dqinfo *oinfo;
1362 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1363 + oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
1364 + status = ocfs2_lock_global_qf(oinfo, 1);
1367 + got_lock[cnt] = 1;
1369 + handle = ocfs2_start_trans(OCFS2_SB(sb),
1370 + ocfs2_calc_qinit_credits(sb, USRQUOTA) +
1371 + ocfs2_calc_qinit_credits(sb, GRPQUOTA));
1372 + if (IS_ERR(handle)) {
1373 + status = PTR_ERR(handle);
1374 + mlog_errno(status);
1377 + dquot_drop(inode);
1378 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
1380 + for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1381 + if (got_lock[cnt]) {
1382 + oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
1383 + ocfs2_unlock_global_qf(oinfo, 1);
1388 +/* See the comment before ocfs2_dquot_initialize. */
1389 +static int ocfs2_dquot_drop(struct inode *inode)
1392 + struct super_block *sb = inode->i_sb;
1393 + struct ocfs2_mem_dqinfo *oinfo;
1394 + int exclusive = 0;
1396 + int got_lock[MAXQUOTAS] = {0, 0};
1398 + mlog_entry_void();
1399 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1400 + oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
1401 + status = ocfs2_lock_global_qf(oinfo, 0);
1404 + got_lock[cnt] = 1;
1406 + /* Lock against anyone releasing references so that when when we check
1407 + * we know we are not going to be last ones to release dquot */
1408 + down_write(&sb_dqopt(sb)->dqptr_sem);
1409 + /* Urgh, this is a terrible hack :( */
1410 + for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1411 + if (inode->i_dquot[cnt] != NODQUOT &&
1412 + atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) {
1418 + dquot_drop_locked(inode);
1419 + up_write(&sb_dqopt(sb)->dqptr_sem);
1421 + for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1422 + if (got_lock[cnt]) {
1423 + oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
1424 + ocfs2_unlock_global_qf(oinfo, 0);
1426 + /* In case we bailed out because we had to do expensive locking
1429 + status = ocfs2_dquot_drop_slow(inode);
1430 + mlog_exit(status);
1434 +static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
1436 + struct ocfs2_dquot *dquot =
1437 + kmem_cache_zalloc(ocfs2_dquot_cachep, GFP_NOFS);
1441 + return &dquot->dq_dquot;
1444 +static void ocfs2_destroy_dquot(struct dquot *dquot)
1446 + kmem_cache_free(ocfs2_dquot_cachep, dquot);
1449 +struct dquot_operations ocfs2_quota_operations = {
1450 + .initialize = ocfs2_dquot_initialize,
1451 + .drop = ocfs2_dquot_drop,
1452 + .alloc_space = dquot_alloc_space,
1453 + .alloc_inode = dquot_alloc_inode,
1454 + .free_space = dquot_free_space,
1455 + .free_inode = dquot_free_inode,
1456 + .transfer = dquot_transfer,
1457 + .write_dquot = ocfs2_write_dquot,
1458 + .acquire_dquot = ocfs2_acquire_dquot,
1459 + .release_dquot = ocfs2_release_dquot,
1460 + .mark_dirty = ocfs2_mark_dquot_dirty,
1461 + .write_info = ocfs2_write_info,
1462 + .alloc_dquot = ocfs2_alloc_dquot,
1463 + .destroy_dquot = ocfs2_destroy_dquot,
1465 Index: linux-2.6.27-ocfs2/fs/ocfs2/quota_local.c
1466 ===================================================================
1468 +++ linux-2.6.27-ocfs2/fs/ocfs2/quota_local.c
1471 + * Implementation of operations over local quota file
1474 +#include <linux/fs.h>
1475 +#include <linux/quota.h>
1476 +#include <linux/quotaops.h>
1477 +#include <linux/module.h>
1479 +#define MLOG_MASK_PREFIX ML_QUOTA
1480 +#include <cluster/masklog.h>
1482 +#include "ocfs2_fs.h"
1487 +#include "buffer_head_io.h"
1488 +#include "journal.h"
1489 +#include "sysfile.h"
1490 +#include "dlmglue.h"
1493 +/* Number of local quota structures per block */
1494 +static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
1496 + return ((sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) /
1497 + sizeof(struct ocfs2_local_disk_dqblk));
1500 +/* Number of blocks with entries in one chunk */
1501 +static inline unsigned int ol_chunk_blocks(struct super_block *sb)
1503 + return ((sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
1504 + OCFS2_QBLK_RESERVED_SPACE) << 3) /
1505 + ol_quota_entries_per_block(sb);
1508 +/* Number of entries in a chunk bitmap */
1509 +static unsigned int ol_chunk_entries(struct super_block *sb)
1511 + return ol_chunk_blocks(sb) * ol_quota_entries_per_block(sb);
1514 +/* Offset of the chunk in quota file */
1515 +static unsigned int ol_quota_chunk_block(struct super_block *sb, int c)
1517 + /* 1 block for local quota file info, 1 block per chunk for chunk info */
1518 + return 1 + (ol_chunk_blocks(sb) + 1) * c;
1521 +/* Offset of the dquot structure in the quota file */
1522 +static loff_t ol_dqblk_off(struct super_block *sb, int c, int off)
1524 + int epb = ol_quota_entries_per_block(sb);
1526 + return ((ol_quota_chunk_block(sb, c) + 1 + off / epb)
1527 + << sb->s_blocksize_bits) +
1528 + (off % epb) * sizeof(struct ocfs2_local_disk_dqblk);
1531 +/* Compute block number from given offset */
1532 +static inline unsigned int ol_dqblk_file_block(struct super_block *sb, loff_t off)
1534 + return off >> sb->s_blocksize_bits;
1537 +static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off)
1539 + return off & ((1 << sb->s_blocksize_bits) - 1);
1542 +/* Compute offset in the chunk of a structure with the given offset */
1543 +static int ol_dqblk_chunk_off(struct super_block *sb, int c, loff_t off)
1545 + int epb = ol_quota_entries_per_block(sb);
1547 + return ((off >> sb->s_blocksize_bits) -
1548 + ol_quota_chunk_block(sb, c) - 1) * epb
1549 + + ((unsigned int)(off & ((1 << sb->s_blocksize_bits) - 1))) /
1550 + sizeof(struct ocfs2_local_disk_dqblk);
1553 +/* Write bufferhead into the fs */
1554 +static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
1555 + void (*modify)(struct buffer_head *, void *), void *private)
1557 + struct super_block *sb = inode->i_sb;
1561 + handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
1562 + if (IS_ERR(handle)) {
1563 + status = PTR_ERR(handle);
1564 + mlog_errno(status);
1567 + status = ocfs2_journal_access(handle, inode, bh,
1568 + OCFS2_JOURNAL_ACCESS_WRITE);
1570 + mlog_errno(status);
1571 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
1575 + modify(bh, private);
1576 + unlock_buffer(bh);
1577 + status = ocfs2_journal_dirty(handle, bh);
1579 + mlog_errno(status);
1580 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
1583 + status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
1585 + mlog_errno(status);
1591 +/* Check whether we understand format of quota files */
1592 +static int ocfs2_local_check_quota_file(struct super_block *sb, int type)
1594 + unsigned int lmagics[MAXQUOTAS] = OCFS2_LOCAL_QMAGICS;
1595 + unsigned int lversions[MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS;
1596 + unsigned int gmagics[MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS;
1597 + unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS;
1598 + unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
1599 + GROUP_QUOTA_SYSTEM_INODE };
1600 + struct buffer_head *bh;
1601 + struct inode *linode = sb_dqopt(sb)->files[type];
1602 + struct inode *ginode = NULL;
1603 + struct ocfs2_disk_dqheader *dqhead;
1604 + int status, ret = 0;
1606 + /* First check whether we understand local quota file */
1607 + bh = ocfs2_bread(linode, 0, &status, 0);
1609 + mlog_errno(status);
1610 + mlog(ML_ERROR, "failed to read quota file header (type=%d)\n",
1614 + dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
1615 + if (le32_to_cpu(dqhead->dqh_magic) != lmagics[type]) {
1616 + mlog(ML_ERROR, "quota file magic does not match (%u != %u),"
1617 + " type=%d\n", le32_to_cpu(dqhead->dqh_magic),
1618 + lmagics[type], type);
1621 + if (le32_to_cpu(dqhead->dqh_version) != lversions[type]) {
1622 + mlog(ML_ERROR, "quota file version does not match (%u != %u),"
1623 + " type=%d\n", le32_to_cpu(dqhead->dqh_version),
1624 + lversions[type], type);
1630 + /* Next check whether we understand global quota file */
1631 + ginode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
1632 + OCFS2_INVALID_SLOT);
1634 + mlog(ML_ERROR, "cannot get global quota file inode "
1635 + "(type=%d)\n", type);
1638 + /* Since the header is read only, we don't care about locking */
1639 + bh = ocfs2_bread(ginode, 0, &status, 0);
1641 + mlog_errno(status);
1642 + mlog(ML_ERROR, "failed to read global quota file header "
1643 + "(type=%d)\n", type);
1646 + dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
1647 + if (le32_to_cpu(dqhead->dqh_magic) != gmagics[type]) {
1648 + mlog(ML_ERROR, "global quota file magic does not match "
1649 + "(%u != %u), type=%d\n",
1650 + le32_to_cpu(dqhead->dqh_magic), gmagics[type], type);
1653 + if (le32_to_cpu(dqhead->dqh_version) != gversions[type]) {
1654 + mlog(ML_ERROR, "global quota file version does not match "
1655 + "(%u != %u), type=%d\n",
1656 + le32_to_cpu(dqhead->dqh_version), gversions[type],
1668 +/* Release given list of quota file chunks */
1669 +static void ocfs2_release_local_quota_bitmaps(struct list_head *head)
1671 + struct ocfs2_quota_chunk *pos, *next;
1673 + list_for_each_entry_safe(pos, next, head, qc_chunk) {
1674 + list_del(&pos->qc_chunk);
1675 + brelse(pos->qc_headerbh);
1676 + kmem_cache_free(ocfs2_qf_chunk_cachep, pos);
1680 +/* Load quota bitmaps into memory */
1681 +static int ocfs2_load_local_quota_bitmaps(struct inode *inode,
1682 + struct ocfs2_local_disk_dqinfo *ldinfo,
1683 + struct list_head *head)
1685 + struct ocfs2_quota_chunk *newchunk;
1688 + INIT_LIST_HEAD(head);
1689 + for (i = 0; i < le32_to_cpu(ldinfo->dqi_chunks); i++) {
1690 + newchunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
1692 + ocfs2_release_local_quota_bitmaps(head);
1695 + newchunk->qc_num = i;
1696 + newchunk->qc_headerbh = ocfs2_bread(inode,
1697 + ol_quota_chunk_block(inode->i_sb, i),
1699 + if (!newchunk->qc_headerbh) {
1700 + mlog_errno(status);
1701 + kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk);
1702 + ocfs2_release_local_quota_bitmaps(head);
1705 + list_add_tail(&newchunk->qc_chunk, head);
1710 +static void olq_update_info(struct buffer_head *bh, void *private)
1712 + struct mem_dqinfo *info = private;
1713 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
1714 + struct ocfs2_local_disk_dqinfo *ldinfo;
1716 + ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
1717 + OCFS2_LOCAL_INFO_OFF);
1718 + spin_lock(&dq_data_lock);
1719 + ldinfo->dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
1720 + ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks);
1721 + ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks);
1722 + spin_unlock(&dq_data_lock);
1725 +/* Read information header from quota file */
1726 +static int ocfs2_local_read_info(struct super_block *sb, int type)
1728 + struct ocfs2_local_disk_dqinfo *ldinfo;
1729 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1730 + struct ocfs2_mem_dqinfo *oinfo;
1731 + struct inode *lqinode = sb_dqopt(sb)->files[type];
1733 + struct buffer_head *bh = NULL;
1736 + info->dqi_maxblimit = 0x7fffffffffffffffLL;
1737 + info->dqi_maxilimit = 0x7fffffffffffffffLL;
1738 + oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
1740 + mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
1744 + info->dqi_priv = oinfo;
1745 + oinfo->dqi_type = type;
1746 + INIT_LIST_HEAD(&oinfo->dqi_chunk);
1747 + oinfo->dqi_lqi_bh = NULL;
1748 + oinfo->dqi_ibh = NULL;
1750 + status = ocfs2_global_read_info(sb, type);
1754 + status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1);
1756 + mlog_errno(status);
1761 + /* Now read local header */
1762 + bh = ocfs2_bread(lqinode, 0, &status, 0);
1764 + mlog_errno(status);
1765 + mlog(ML_ERROR, "failed to read quota file info header "
1766 + "(type=%d)\n", type);
1769 + ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
1770 + OCFS2_LOCAL_INFO_OFF);
1771 + info->dqi_flags = le32_to_cpu(ldinfo->dqi_flags);
1772 + oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks);
1773 + oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks);
1774 + oinfo->dqi_ibh = bh;
1776 + /* We crashed when using local quota file? */
1777 + if (!(info->dqi_flags & OLQF_CLEAN))
1778 + goto out_err; /* So far we just bail out. Later we should resync here */
1780 + status = ocfs2_load_local_quota_bitmaps(sb_dqopt(sb)->files[type],
1782 + &oinfo->dqi_chunk);
1784 + mlog_errno(status);
1788 + /* Now mark quota file as used */
1789 + info->dqi_flags &= ~OLQF_CLEAN;
1790 + status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info);
1792 + mlog_errno(status);
1799 + iput(oinfo->dqi_gqinode);
1800 + ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
1801 + ocfs2_lock_res_free(&oinfo->dqi_gqlock);
1802 + brelse(oinfo->dqi_lqi_bh);
1804 + ocfs2_inode_unlock(lqinode, 1);
1805 + ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
1812 +/* Write local info to quota file */
1813 +static int ocfs2_local_write_info(struct super_block *sb, int type)
1815 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1816 + struct buffer_head *bh = ((struct ocfs2_mem_dqinfo *)info->dqi_priv)
1820 + status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], bh, olq_update_info,
1823 + mlog_errno(status);
1830 +/* Release info from memory */
1831 +static int ocfs2_local_free_info(struct super_block *sb, int type)
1833 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1834 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
1835 + struct ocfs2_quota_chunk *chunk;
1836 + struct ocfs2_local_disk_chunk *dchunk;
1837 + int mark_clean = 1, len;
1840 + iput(oinfo->dqi_gqinode);
1841 + ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
1842 + ocfs2_lock_res_free(&oinfo->dqi_gqlock);
1843 + list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
1844 + dchunk = (struct ocfs2_local_disk_chunk *)
1845 + (chunk->qc_headerbh->b_data);
1846 + if (chunk->qc_num < oinfo->dqi_chunks - 1) {
1847 + len = ol_chunk_entries(sb);
1849 + len = (oinfo->dqi_blocks -
1850 + ol_quota_chunk_block(sb, chunk->qc_num) - 1)
1851 + * ol_quota_entries_per_block(sb);
1853 + /* Not all entries free? Bug! */
1854 + if (le32_to_cpu(dchunk->dqc_free) != len) {
1855 + mlog(ML_ERROR, "releasing quota file with used "
1856 + "entries (type=%d)\n", type);
1860 + ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
1865 + /* Mark local file as clean */
1866 + info->dqi_flags |= OLQF_CLEAN;
1867 + status = ocfs2_modify_bh(sb_dqopt(sb)->files[type],
1872 + mlog_errno(status);
1877 + ocfs2_inode_unlock(sb_dqopt(sb)->files[type], 1);
1878 + brelse(oinfo->dqi_ibh);
1879 + brelse(oinfo->dqi_lqi_bh);
1884 +static void olq_set_dquot(struct buffer_head *bh, void *private)
1886 + struct ocfs2_dquot *od = private;
1887 + struct ocfs2_local_disk_dqblk *dqblk;
1888 + struct super_block *sb = od->dq_dquot.dq_sb;
1890 + dqblk = (struct ocfs2_local_disk_dqblk *)(bh->b_data
1891 + + ol_dqblk_block_offset(sb, od->dq_local_off));
1893 + dqblk->dqb_id = cpu_to_le64(od->dq_dquot.dq_id);
1894 + spin_lock(&dq_data_lock);
1895 + dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace -
1896 + od->dq_origspace);
1897 + dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes -
1898 + od->dq_originodes);
1899 + spin_unlock(&dq_data_lock);
1900 + mlog(0, "Writing local dquot %u space %lld inodes %lld\n",
1901 + od->dq_dquot.dq_id, dqblk->dqb_spacemod, dqblk->dqb_inodemod);
1904 +/* Write dquot to local quota file */
1905 +static int ocfs2_local_write_dquot(struct dquot *dquot)
1907 + struct super_block *sb = dquot->dq_sb;
1908 + struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
1909 + struct buffer_head *bh;
1912 + bh = ocfs2_bread(sb_dqopt(sb)->files[dquot->dq_type],
1913 + ol_dqblk_file_block(sb, od->dq_local_off),
1916 + mlog_errno(status);
1919 + status = ocfs2_modify_bh(sb_dqopt(sb)->files[dquot->dq_type], bh,
1920 + olq_set_dquot, od);
1922 + mlog_errno(status);
1930 +/* Find free entry in local quota file */
1931 +static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb,
1935 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1936 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
1937 + struct ocfs2_quota_chunk *chunk;
1938 + struct ocfs2_local_disk_chunk *dchunk;
1939 + int found = 0, len;
1941 + list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
1942 + dchunk = (struct ocfs2_local_disk_chunk *)
1943 + chunk->qc_headerbh->b_data;
1944 + if (le32_to_cpu(dchunk->dqc_free) > 0) {
1952 + if (chunk->qc_num < oinfo->dqi_chunks - 1) {
1953 + len = ol_chunk_entries(sb);
1955 + len = (oinfo->dqi_blocks -
1956 + ol_quota_chunk_block(sb, chunk->qc_num) - 1)
1957 + * ol_quota_entries_per_block(sb);
1960 + found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0);
1962 + if (found == len) {
1963 + mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u"
1964 + " entries free (type=%d)\n", chunk->qc_num,
1965 + le32_to_cpu(dchunk->dqc_free), type);
1966 + return ERR_PTR(-EIO);
1972 +/* Add new chunk to the local quota file */
1973 +static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
1974 + struct super_block *sb,
1978 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
1979 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
1980 + struct inode *lqinode = sb_dqopt(sb)->files[type];
1981 + struct ocfs2_quota_chunk *chunk = NULL;
1982 + struct ocfs2_local_disk_chunk *dchunk;
1985 + struct buffer_head *bh = NULL;
1988 + /* We are protected by dqio_sem so no locking needed */
1989 + status = ocfs2_extend_no_holes(lqinode,
1990 + lqinode->i_size + 2 * sb->s_blocksize,
1993 + mlog_errno(status);
1996 + status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
1997 + lqinode->i_size + 2 * sb->s_blocksize);
1999 + mlog_errno(status);
2003 + chunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
2006 + mlog_errno(status);
2010 + down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
2011 + status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
2012 + &p_blkno, NULL, NULL);
2013 + up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
2015 + mlog_errno(status);
2018 + bh = sb_getblk(sb, p_blkno);
2021 + mlog_errno(status);
2024 + dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
2026 + handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
2027 + if (IS_ERR(handle)) {
2028 + status = PTR_ERR(handle);
2029 + mlog_errno(status);
2033 + status = ocfs2_journal_access(handle, lqinode, bh,
2034 + OCFS2_JOURNAL_ACCESS_WRITE);
2036 + mlog_errno(status);
2040 + dchunk->dqc_free = ol_quota_entries_per_block(sb);
2041 + memset(dchunk->dqc_bitmap, 0,
2042 + sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
2043 + OCFS2_QBLK_RESERVED_SPACE);
2044 + set_buffer_uptodate(bh);
2045 + unlock_buffer(bh);
2046 + status = ocfs2_journal_dirty(handle, bh);
2048 + mlog_errno(status);
2052 + oinfo->dqi_blocks += 2;
2053 + oinfo->dqi_chunks++;
2054 + status = ocfs2_local_write_info(sb, type);
2056 + mlog_errno(status);
2059 + status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
2061 + mlog_errno(status);
2065 + list_add_tail(&chunk->qc_chunk, &oinfo->dqi_chunk);
2066 + chunk->qc_num = list_entry(chunk->qc_chunk.prev,
2067 + struct ocfs2_quota_chunk,
2068 + qc_chunk)->qc_num + 1;
2069 + chunk->qc_headerbh = bh;
2073 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
2076 + kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
2077 + return ERR_PTR(status);
2080 +/* Find free entry in local quota file */
2081 +static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
2082 + struct super_block *sb,
2086 + struct mem_dqinfo *info = sb_dqinfo(sb, type);
2087 + struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
2088 + struct ocfs2_quota_chunk *chunk;
2089 + struct inode *lqinode = sb_dqopt(sb)->files[type];
2090 + struct ocfs2_local_disk_chunk *dchunk;
2091 + int epb = ol_quota_entries_per_block(sb);
2092 + unsigned int chunk_blocks;
2096 + if (list_empty(&oinfo->dqi_chunk))
2097 + return ocfs2_local_quota_add_chunk(sb, type, offset);
2098 + /* Is the last chunk full? */
2099 + chunk = list_entry(oinfo->dqi_chunk.prev,
2100 + struct ocfs2_quota_chunk, qc_chunk);
2101 + chunk_blocks = oinfo->dqi_blocks -
2102 + ol_quota_chunk_block(sb, chunk->qc_num) - 1;
2103 + if (ol_chunk_blocks(sb) == chunk_blocks)
2104 + return ocfs2_local_quota_add_chunk(sb, type, offset);
2106 + /* We are protected by dqio_sem so no locking needed */
2107 + status = ocfs2_extend_no_holes(lqinode,
2108 + lqinode->i_size + sb->s_blocksize,
2111 + mlog_errno(status);
2114 + status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
2115 + lqinode->i_size + sb->s_blocksize);
2117 + mlog_errno(status);
2120 + handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
2121 + if (IS_ERR(handle)) {
2122 + status = PTR_ERR(handle);
2123 + mlog_errno(status);
2126 + status = ocfs2_journal_access(handle, lqinode, chunk->qc_headerbh,
2127 + OCFS2_JOURNAL_ACCESS_WRITE);
2129 + mlog_errno(status);
2133 + dchunk = (struct ocfs2_local_disk_chunk *)chunk->qc_headerbh->b_data;
2134 + lock_buffer(chunk->qc_headerbh);
2135 + le32_add_cpu(&dchunk->dqc_free, ol_quota_entries_per_block(sb));
2136 + unlock_buffer(chunk->qc_headerbh);
2137 + status = ocfs2_journal_dirty(handle, chunk->qc_headerbh);
2139 + mlog_errno(status);
2142 + oinfo->dqi_blocks++;
2143 + status = ocfs2_local_write_info(sb, type);
2145 + mlog_errno(status);
2149 + status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
2151 + mlog_errno(status);
2154 + *offset = chunk_blocks * epb;
2157 + ocfs2_commit_trans(OCFS2_SB(sb), handle);
2159 + return ERR_PTR(status);
2162 +void olq_alloc_dquot(struct buffer_head *bh, void *private)
2164 + int *offset = private;
2165 + struct ocfs2_local_disk_chunk *dchunk;
2167 + dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
2168 + ocfs2_set_bit(*offset, dchunk->dqc_bitmap);
2169 + le32_add_cpu(&dchunk->dqc_free, -1);
2172 +/* Create dquot in the local file for given id */
2173 +static int ocfs2_create_local_dquot(struct dquot *dquot)
2175 + struct super_block *sb = dquot->dq_sb;
2176 + int type = dquot->dq_type;
2177 + struct inode *lqinode = sb_dqopt(sb)->files[type];
2178 + struct ocfs2_quota_chunk *chunk;
2179 + struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
2183 + chunk = ocfs2_find_free_entry(sb, type, &offset);
2185 + chunk = ocfs2_extend_local_quota_file(sb, type, &offset);
2186 + if (IS_ERR(chunk))
2187 + return PTR_ERR(chunk);
2188 + } else if (IS_ERR(chunk)) {
2189 + return PTR_ERR(chunk);
2191 + od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset);
2192 + od->dq_chunk = chunk;
2194 + /* Initialize dquot structure on disk */
2195 + status = ocfs2_local_write_dquot(dquot);
2197 + mlog_errno(status);
2201 + /* Mark structure as allocated */
2202 + status = ocfs2_modify_bh(lqinode, chunk->qc_headerbh, olq_alloc_dquot,
2205 + mlog_errno(status);
2212 +/* Create entry in local file for dquot, load data from the global file */
2213 +static int ocfs2_local_read_dquot(struct dquot *dquot)
2217 + mlog_entry("id=%u, type=%d\n", dquot->dq_id, dquot->dq_type);
2219 + status = ocfs2_global_read_dquot(dquot);
2221 + mlog_errno(status);
2225 + /* Now create entry in the local quota file */
2226 + status = ocfs2_create_local_dquot(dquot);
2228 + mlog_errno(status);
2234 + mlog_exit(status);
2238 +/* Release dquot structure from local quota file. ocfs2_release_dquot() has
2239 + * already started a transaction and obtained exclusive lock for global
2241 +static int ocfs2_local_release_dquot(struct dquot *dquot)
2244 + int type = dquot->dq_type;
2245 + struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
2246 + struct super_block *sb = dquot->dq_sb;
2247 + struct ocfs2_local_disk_chunk *dchunk;
2249 + handle_t *handle = journal_current_handle();
2252 + /* First write all local changes to global file */
2253 + status = ocfs2_global_release_dquot(dquot);
2255 + mlog_errno(status);
2259 + status = ocfs2_journal_access(handle, sb_dqopt(sb)->files[type],
2260 + od->dq_chunk->qc_headerbh, OCFS2_JOURNAL_ACCESS_WRITE);
2262 + mlog_errno(status);
2265 + offset = ol_dqblk_chunk_off(sb, od->dq_chunk->qc_num,
2266 + od->dq_local_off);
2267 + dchunk = (struct ocfs2_local_disk_chunk *)
2268 + (od->dq_chunk->qc_headerbh->b_data);
2269 + /* Mark structure as freed */
2270 + lock_buffer(od->dq_chunk->qc_headerbh);
2271 + ocfs2_clear_bit(offset, dchunk->dqc_bitmap);
2272 + le32_add_cpu(&dchunk->dqc_free, 1);
2273 + unlock_buffer(od->dq_chunk->qc_headerbh);
2274 + status = ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
2276 + mlog_errno(status);
2281 + /* Clear the read bit so that next time someone uses this
2282 + * dquot he reads fresh info from disk and allocates local
2283 + * dquot structure */
2284 + clear_bit(DQ_READ_B, &dquot->dq_flags);
2288 +static struct quota_format_ops ocfs2_format_ops = {
2289 + .check_quota_file = ocfs2_local_check_quota_file,
2290 + .read_file_info = ocfs2_local_read_info,
2291 + .write_file_info = ocfs2_global_write_info,
2292 + .free_file_info = ocfs2_local_free_info,
2293 + .read_dqblk = ocfs2_local_read_dquot,
2294 + .commit_dqblk = ocfs2_local_write_dquot,
2295 + .release_dqblk = ocfs2_local_release_dquot,
2298 +static struct quota_format_type ocfs2_quota_format = {
2299 + .qf_fmt_id = QFMT_OCFS2,
2300 + .qf_ops = &ocfs2_format_ops,
2301 + .qf_owner = THIS_MODULE
2304 +int init_ocfs2_quota_format(void)
2306 + return register_quota_format(&ocfs2_quota_format);
2309 +void exit_ocfs2_quota_format(void)
2311 + unregister_quota_format(&ocfs2_quota_format);
2313 Index: linux-2.6.27-ocfs2/fs/ocfs2/super.c
2314 ===================================================================
2315 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/super.c
2316 +++ linux-2.6.27-ocfs2/fs/ocfs2/super.c
2318 #include "uptodate.h"
2323 #include "buffer_head_io.h"
2325 static struct kmem_cache *ocfs2_inode_cachep = NULL;
2326 +struct kmem_cache *ocfs2_dquot_cachep;
2327 +struct kmem_cache *ocfs2_qf_chunk_cachep;
2329 /* OCFS2 needs to schedule several differnt types of work which
2330 * require cluster locking, disk I/O, recovery waits, etc. Since these
2331 @@ -137,6 +140,8 @@ static const struct super_operations ocf
2332 .put_super = ocfs2_put_super,
2333 .remount_fs = ocfs2_remount,
2334 .show_options = ocfs2_show_options,
2335 + .quota_read = ocfs2_quota_read,
2336 + .quota_write = ocfs2_quota_write,
2340 @@ -1073,6 +1078,7 @@ static int ocfs2_show_options(struct seq
2341 static int __init ocfs2_init(void)
2344 + int added_format = 0;
2348 @@ -1090,6 +1096,13 @@ static int __init ocfs2_init(void)
2352 + status = init_ocfs2_quota_format();
2354 + mlog_errno(status);
2359 ocfs2_wq = create_singlethread_workqueue("ocfs2_wq");
2362 @@ -1108,6 +1121,8 @@ leave:
2364 ocfs2_free_mem_caches();
2365 exit_ocfs2_uptodate_cache();
2367 + exit_ocfs2_quota_format();
2371 @@ -1127,6 +1142,8 @@ static void __exit ocfs2_exit(void)
2372 destroy_workqueue(ocfs2_wq);
2375 + exit_ocfs2_quota_format();
2377 debugfs_remove(ocfs2_debugfs_root);
2379 ocfs2_free_mem_caches();
2380 @@ -1242,8 +1259,27 @@ static int ocfs2_initialize_mem_caches(v
2381 (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
2383 ocfs2_inode_init_once);
2384 - if (!ocfs2_inode_cachep)
2385 + ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
2386 + sizeof(struct ocfs2_dquot),
2388 + (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
2391 + ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
2392 + sizeof(struct ocfs2_quota_chunk),
2394 + (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
2396 + if (!ocfs2_inode_cachep || !ocfs2_dquot_cachep ||
2397 + !ocfs2_qf_chunk_cachep) {
2398 + if (ocfs2_inode_cachep)
2399 + kmem_cache_destroy(ocfs2_inode_cachep);
2400 + if (ocfs2_dquot_cachep)
2401 + kmem_cache_destroy(ocfs2_dquot_cachep);
2402 + if (ocfs2_qf_chunk_cachep)
2403 + kmem_cache_destroy(ocfs2_qf_chunk_cachep);
2409 @@ -1252,8 +1288,15 @@ static void ocfs2_free_mem_caches(void)
2411 if (ocfs2_inode_cachep)
2412 kmem_cache_destroy(ocfs2_inode_cachep);
2414 ocfs2_inode_cachep = NULL;
2416 + if (ocfs2_dquot_cachep)
2417 + kmem_cache_destroy(ocfs2_dquot_cachep);
2418 + ocfs2_dquot_cachep = NULL;
2420 + if (ocfs2_qf_chunk_cachep)
2421 + kmem_cache_destroy(ocfs2_qf_chunk_cachep);
2422 + ocfs2_qf_chunk_cachep = NULL;
2425 static int ocfs2_get_sector(struct super_block *sb,
2426 Index: linux-2.6.27-ocfs2/fs/ocfs2/dir.c
2427 ===================================================================
2428 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/dir.c
2429 +++ linux-2.6.27-ocfs2/fs/ocfs2/dir.c
2430 @@ -82,8 +82,8 @@ static int ocfs2_do_extend_dir(struct su
2431 struct ocfs2_alloc_context *meta_ac,
2432 struct buffer_head **new_bh);
2434 -static struct buffer_head *ocfs2_bread(struct inode *inode,
2435 - int block, int *err, int reada)
2436 +struct buffer_head *ocfs2_bread(struct inode *inode,
2437 + int block, int *err, int reada)
2439 struct buffer_head *bh = NULL;
2441 Index: linux-2.6.27-ocfs2/fs/ocfs2/inode.h
2442 ===================================================================
2443 --- linux-2.6.27-ocfs2.orig/fs/ocfs2/inode.h
2444 +++ linux-2.6.27-ocfs2/fs/ocfs2/inode.h
2445 @@ -142,6 +142,8 @@ int ocfs2_mark_inode_dirty(handle_t *han
2446 struct buffer_head *bh);
2447 int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
2448 int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
2449 +struct buffer_head *ocfs2_bread(struct inode *inode,
2450 + int block, int *err, int reada);
2452 void ocfs2_set_inode_flags(struct inode *inode);
2453 void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);