aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-08-25 13:56:50 -0400
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:40:23 -0500
commit9e33d69f553aaf11377307e8d6f82deb3385e351 (patch)
treeded5f48f6cf82db976f30d5f0f4d44b941f60f44 /fs
parentbbbd0eb34bf801dee01e345785959a75258f6567 (diff)
ocfs2: Implementation of local and global quota file handling
For each quota type each node has local quota file. In this file it stores changes users have made to disk usage via this node. Once in a while this information is synced to global file (and thus with other nodes) so that limits enforcement at least aproximately works. Global quota files contain all the information about usage and limits. It's mostly handled by the generic VFS code (which implements a trie of structures inside a quota file). We only have to provide functions to convert structures from on-disk format to in-memory one. We also have to provide wrappers for various quota functions starting transactions and acquiring necessary cluster locks before the actual IO is really started. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/Makefile2
-rw-r--r--fs/ocfs2/cluster/masklog.h1
-rw-r--r--fs/ocfs2/dlmglue.c146
-rw-r--r--fs/ocfs2/dlmglue.h19
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/file.h3
-rw-r--r--fs/ocfs2/inode.h2
-rw-r--r--fs/ocfs2/ocfs2_fs.h103
-rw-r--r--fs/ocfs2/ocfs2_lockid.h5
-rw-r--r--fs/ocfs2/quota.h93
-rw-r--r--fs/ocfs2/quota_global.c919
-rw-r--r--fs/ocfs2/quota_local.c833
-rw-r--r--fs/ocfs2/super.c38
13 files changed, 2165 insertions, 5 deletions
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index e9ef5d162db1..7e4b361b755c 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -35,6 +35,8 @@ ocfs2-objs := \
35 sysfile.o \ 35 sysfile.o \
36 uptodate.o \ 36 uptodate.o \
37 ver.o \ 37 ver.o \
38 quota_local.o \
39 quota_global.o \
38 xattr.o 40 xattr.o
39 41
40ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y) 42ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y)
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 57670c680471..7e72a81bc2d4 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -113,6 +113,7 @@
113#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ 113#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
114#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ 114#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
115#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ 115#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
116#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
116/* bits that are infrequently given and frequently matched in the high word */ 117/* bits that are infrequently given and frequently matched in the high word */
117#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */ 118#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
118#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */ 119#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 9f2a7f75d1b3..058aa86490ae 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -32,6 +32,7 @@
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/time.h> 34#include <linux/time.h>
35#include <linux/quotaops.h>
35 36
36#define MLOG_MASK_PREFIX ML_DLM_GLUE 37#define MLOG_MASK_PREFIX ML_DLM_GLUE
37#include <cluster/masklog.h> 38#include <cluster/masklog.h>
@@ -51,6 +52,7 @@
51#include "slot_map.h" 52#include "slot_map.h"
52#include "super.h" 53#include "super.h"
53#include "uptodate.h" 54#include "uptodate.h"
55#include "quota.h"
54 56
55#include "buffer_head_io.h" 57#include "buffer_head_io.h"
56 58
@@ -68,6 +70,7 @@ struct ocfs2_mask_waiter {
68static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); 70static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres);
69static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); 71static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres);
70static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres); 72static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres);
73static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres);
71 74
72/* 75/*
73 * Return value from ->downconvert_worker functions. 76 * Return value from ->downconvert_worker functions.
@@ -102,6 +105,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
102static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, 105static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
103 struct ocfs2_lock_res *lockres); 106 struct ocfs2_lock_res *lockres);
104 107
108static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
105 109
106#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) 110#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
107 111
@@ -258,6 +262,12 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = {
258 .flags = 0, 262 .flags = 0,
259}; 263};
260 264
265static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
266 .set_lvb = ocfs2_set_qinfo_lvb,
267 .get_osb = ocfs2_get_qinfo_osb,
268 .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
269};
270
261static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) 271static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
262{ 272{
263 return lockres->l_type == OCFS2_LOCK_TYPE_META || 273 return lockres->l_type == OCFS2_LOCK_TYPE_META ||
@@ -279,6 +289,13 @@ static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res
279 return (struct ocfs2_dentry_lock *)lockres->l_priv; 289 return (struct ocfs2_dentry_lock *)lockres->l_priv;
280} 290}
281 291
292static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_res *lockres)
293{
294 BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO);
295
296 return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
297}
298
282static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) 299static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
283{ 300{
284 if (lockres->l_ops->get_osb) 301 if (lockres->l_ops->get_osb)
@@ -507,6 +524,13 @@ static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres)
507 return OCFS2_SB(inode->i_sb); 524 return OCFS2_SB(inode->i_sb);
508} 525}
509 526
527static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres)
528{
529 struct ocfs2_mem_dqinfo *info = lockres->l_priv;
530
531 return OCFS2_SB(info->dqi_gi.dqi_sb);
532}
533
510static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres) 534static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres)
511{ 535{
512 struct ocfs2_file_private *fp = lockres->l_priv; 536 struct ocfs2_file_private *fp = lockres->l_priv;
@@ -609,6 +633,17 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
609 lockres->l_flags |= OCFS2_LOCK_NOCACHE; 633 lockres->l_flags |= OCFS2_LOCK_NOCACHE;
610} 634}
611 635
636void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
637 struct ocfs2_mem_dqinfo *info)
638{
639 ocfs2_lock_res_init_once(lockres);
640 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_QINFO, info->dqi_gi.dqi_type,
641 0, lockres->l_name);
642 ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres,
643 OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops,
644 info);
645}
646
612void ocfs2_lock_res_free(struct ocfs2_lock_res *res) 647void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
613{ 648{
614 mlog_entry_void(); 649 mlog_entry_void();
@@ -3445,6 +3480,117 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
3445 return UNBLOCK_CONTINUE_POST; 3480 return UNBLOCK_CONTINUE_POST;
3446} 3481}
3447 3482
3483static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
3484{
3485 struct ocfs2_qinfo_lvb *lvb;
3486 struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
3487 struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
3488 oinfo->dqi_gi.dqi_type);
3489
3490 mlog_entry_void();
3491
3492 lvb = (struct ocfs2_qinfo_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
3493 lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
3494 lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
3495 lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
3496 lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
3497 lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
3498 lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
3499 lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
3500
3501 mlog_exit_void();
3502}
3503
3504void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
3505{
3506 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3507 struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
3508 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
3509
3510 mlog_entry_void();
3511 if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
3512 ocfs2_cluster_unlock(osb, lockres, level);
3513 mlog_exit_void();
3514}
3515
3516static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
3517{
3518 struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
3519 oinfo->dqi_gi.dqi_type);
3520 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3521 struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
3522 struct buffer_head *bh;
3523 struct ocfs2_global_disk_dqinfo *gdinfo;
3524 int status = 0;
3525
3526 if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
3527 info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
3528 info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
3529 oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
3530 oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
3531 oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
3532 oinfo->dqi_gi.dqi_free_entry =
3533 be32_to_cpu(lvb->lvb_free_entry);
3534 } else {
3535 bh = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &status);
3536 if (!bh) {
3537 mlog_errno(status);
3538 goto bail;
3539 }
3540 gdinfo = (struct ocfs2_global_disk_dqinfo *)
3541 (bh->b_data + OCFS2_GLOBAL_INFO_OFF);
3542 info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
3543 info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
3544 oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
3545 oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
3546 oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
3547 oinfo->dqi_gi.dqi_free_entry =
3548 le32_to_cpu(gdinfo->dqi_free_entry);
3549 brelse(bh);
3550 ocfs2_track_lock_refresh(lockres);
3551 }
3552
3553bail:
3554 return status;
3555}
3556
3557/* Lock quota info, this function expects at least shared lock on the quota file
3558 * so that we can safely refresh quota info from disk. */
3559int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
3560{
3561 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3562 struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
3563 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
3564 int status = 0;
3565
3566 mlog_entry_void();
3567
3568 /* On RO devices, locking really isn't needed... */
3569 if (ocfs2_is_hard_readonly(osb)) {
3570 if (ex)
3571 status = -EROFS;
3572 goto bail;
3573 }
3574 if (ocfs2_mount_local(osb))
3575 goto bail;
3576
3577 status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
3578 if (status < 0) {
3579 mlog_errno(status);
3580 goto bail;
3581 }
3582 if (!ocfs2_should_refresh_lock_res(lockres))
3583 goto bail;
3584 /* OK, we have the lock but we need to refresh the quota info */
3585 status = ocfs2_refresh_qinfo(oinfo);
3586 if (status)
3587 ocfs2_qinfo_unlock(oinfo, ex);
3588 ocfs2_complete_lock_res_refresh(lockres, status);
3589bail:
3590 mlog_exit(status);
3591 return status;
3592}
3593
3448/* 3594/*
3449 * This is the filesystem locking protocol. It provides the lock handling 3595 * This is the filesystem locking protocol. It provides the lock handling
3450 * hooks for the underlying DLM. It has a maximum version number. 3596 * hooks for the underlying DLM. It has a maximum version number.
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 2bb01f09c1b1..3f8d9986b8e0 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -49,6 +49,19 @@ struct ocfs2_meta_lvb {
49 __be32 lvb_reserved2; 49 __be32 lvb_reserved2;
50}; 50};
51 51
52#define OCFS2_QINFO_LVB_VERSION 1
53
54struct ocfs2_qinfo_lvb {
55 __u8 lvb_version;
56 __u8 lvb_reserved[3];
57 __be32 lvb_bgrace;
58 __be32 lvb_igrace;
59 __be32 lvb_syncms;
60 __be32 lvb_blocks;
61 __be32 lvb_free_blk;
62 __be32 lvb_free_entry;
63};
64
52/* ocfs2_inode_lock_full() 'arg_flags' flags */ 65/* ocfs2_inode_lock_full() 'arg_flags' flags */
53/* don't wait on recovery. */ 66/* don't wait on recovery. */
54#define OCFS2_META_LOCK_RECOVERY (0x01) 67#define OCFS2_META_LOCK_RECOVERY (0x01)
@@ -69,6 +82,9 @@ void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
69struct ocfs2_file_private; 82struct ocfs2_file_private;
70void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, 83void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
71 struct ocfs2_file_private *fp); 84 struct ocfs2_file_private *fp);
85struct ocfs2_mem_dqinfo;
86void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
87 struct ocfs2_mem_dqinfo *info);
72void ocfs2_lock_res_free(struct ocfs2_lock_res *res); 88void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
73int ocfs2_create_new_inode_locks(struct inode *inode); 89int ocfs2_create_new_inode_locks(struct inode *inode);
74int ocfs2_drop_inode_locks(struct inode *inode); 90int ocfs2_drop_inode_locks(struct inode *inode);
@@ -103,6 +119,9 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex);
103void ocfs2_dentry_unlock(struct dentry *dentry, int ex); 119void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
104int ocfs2_file_lock(struct file *file, int ex, int trylock); 120int ocfs2_file_lock(struct file *file, int ex, int trylock);
105void ocfs2_file_unlock(struct file *file); 121void ocfs2_file_unlock(struct file *file);
122int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex);
123void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex);
124
106 125
107void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres); 126void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
108void ocfs2_simple_drop_lockres(struct ocfs2_super *osb, 127void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 41001d515fae..372d96505a79 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -304,9 +304,9 @@ bail:
304 return status; 304 return status;
305} 305}
306 306
307static int ocfs2_simple_size_update(struct inode *inode, 307int ocfs2_simple_size_update(struct inode *inode,
308 struct buffer_head *di_bh, 308 struct buffer_head *di_bh,
309 u64 new_i_size) 309 u64 new_i_size)
310{ 310{
311 int ret; 311 int ret;
312 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 312 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index e92382cbca5f..172f9fbc9fc7 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -51,6 +51,9 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
51 struct ocfs2_alloc_context *data_ac, 51 struct ocfs2_alloc_context *data_ac,
52 struct ocfs2_alloc_context *meta_ac, 52 struct ocfs2_alloc_context *meta_ac,
53 enum ocfs2_alloc_restarted *reason_ret); 53 enum ocfs2_alloc_restarted *reason_ret);
54int ocfs2_simple_size_update(struct inode *inode,
55 struct buffer_head *di_bh,
56 u64 new_i_size);
54int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, 57int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
55 u64 zero_to); 58 u64 zero_to);
56int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); 59int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index b79c371a9d27..eb3c302b38d3 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -142,6 +142,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
142 struct buffer_head *bh); 142 struct buffer_head *bh);
143int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); 143int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
144int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); 144int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
145struct buffer_head *ocfs2_bread(struct inode *inode,
146 int block, int *err, int reada);
145 147
146void ocfs2_set_inode_flags(struct inode *inode); 148void ocfs2_set_inode_flags(struct inode *inode);
147void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi); 149void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 06e3bd632ff3..0a5ac790a628 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -883,6 +883,109 @@ static inline int ocfs2_xattr_get_type(struct ocfs2_xattr_entry *xe)
883 return xe->xe_type & OCFS2_XATTR_TYPE_MASK; 883 return xe->xe_type & OCFS2_XATTR_TYPE_MASK;
884} 884}
885 885
886/*
887 * On disk structures for global quota file
888 */
889
890/* Magic numbers and known versions for global quota files */
891#define OCFS2_GLOBAL_QMAGICS {\
892 0x0cf52470, /* USRQUOTA */ \
893 0x0cf52471 /* GRPQUOTA */ \
894}
895
896#define OCFS2_GLOBAL_QVERSIONS {\
897 0, \
898 0, \
899}
900
901
902/* Each block of each quota file has a certain fixed number of bytes reserved
903 * for OCFS2 internal use at its end. OCFS2 can use it for things like
904 * checksums, etc. */
905#define OCFS2_QBLK_RESERVED_SPACE 8
906
907/* Generic header of all quota files */
908struct ocfs2_disk_dqheader {
909 __le32 dqh_magic; /* Magic number identifying file */
910 __le32 dqh_version; /* Quota format version */
911};
912
913#define OCFS2_GLOBAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
914
915/* Information header of global quota file (immediately follows the generic
916 * header) */
917struct ocfs2_global_disk_dqinfo {
918/*00*/ __le32 dqi_bgrace; /* Grace time for space softlimit excess */
919 __le32 dqi_igrace; /* Grace time for inode softlimit excess */
920 __le32 dqi_syncms; /* Time after which we sync local changes to
921 * global quota file */
922 __le32 dqi_blocks; /* Number of blocks in quota file */
923/*10*/ __le32 dqi_free_blk; /* First free block in quota file */
924 __le32 dqi_free_entry; /* First block with free dquot entry in quota
925 * file */
926};
927
928/* Structure with global user / group information. We reserve some space
929 * for future use. */
930struct ocfs2_global_disk_dqblk {
931/*00*/ __le32 dqb_id; /* ID the structure belongs to */
932 __le32 dqb_use_count; /* Number of nodes having reference to this structure */
933 __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
934/*10*/ __le64 dqb_isoftlimit; /* preferred inode limit */
935 __le64 dqb_curinodes; /* current # allocated inodes */
936/*20*/ __le64 dqb_bhardlimit; /* absolute limit on disk space */
937 __le64 dqb_bsoftlimit; /* preferred limit on disk space */
938/*30*/ __le64 dqb_curspace; /* current space occupied */
939 __le64 dqb_btime; /* time limit for excessive disk use */
940/*40*/ __le64 dqb_itime; /* time limit for excessive inode use */
941 __le64 dqb_pad1;
942/*50*/ __le64 dqb_pad2;
943};
944
945/*
946 * On-disk structures for local quota file
947 */
948
949/* Magic numbers and known versions for local quota files */
950#define OCFS2_LOCAL_QMAGICS {\
951 0x0cf524c0, /* USRQUOTA */ \
952 0x0cf524c1 /* GRPQUOTA */ \
953}
954
955#define OCFS2_LOCAL_QVERSIONS {\
956 0, \
957 0, \
958}
959
960/* Quota flags in dqinfo header */
961#define OLQF_CLEAN 0x0001 /* Quota file is empty (this should be after\
962 * quota has been cleanly turned off) */
963
964#define OCFS2_LOCAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
965
966/* Information header of local quota file (immediately follows the generic
967 * header) */
968struct ocfs2_local_disk_dqinfo {
969 __le32 dqi_flags; /* Flags for quota file */
970 __le32 dqi_chunks; /* Number of chunks of quota structures
971 * with a bitmap */
972 __le32 dqi_blocks; /* Number of blocks allocated for quota file */
973};
974
975/* Header of one chunk of a quota file */
976struct ocfs2_local_disk_chunk {
977 __le32 dqc_free; /* Number of free entries in the bitmap */
978 u8 dqc_bitmap[0]; /* Bitmap of entries in the corresponding
979 * chunk of quota file */
980};
981
982/* One entry in local quota file */
983struct ocfs2_local_disk_dqblk {
984/*00*/ __le64 dqb_id; /* id this quota applies to */
985 __le64 dqb_spacemod; /* Change in the amount of used space */
986/*10*/ __le64 dqb_inodemod; /* Change in the amount of used inodes */
987};
988
886#ifdef __KERNEL__ 989#ifdef __KERNEL__
887static inline int ocfs2_fast_symlink_chars(struct super_block *sb) 990static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
888{ 991{
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index 82c200f7a8f1..eb6f50c9ceca 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -46,6 +46,7 @@ enum ocfs2_lock_type {
46 OCFS2_LOCK_TYPE_DENTRY, 46 OCFS2_LOCK_TYPE_DENTRY,
47 OCFS2_LOCK_TYPE_OPEN, 47 OCFS2_LOCK_TYPE_OPEN,
48 OCFS2_LOCK_TYPE_FLOCK, 48 OCFS2_LOCK_TYPE_FLOCK,
49 OCFS2_LOCK_TYPE_QINFO,
49 OCFS2_NUM_LOCK_TYPES 50 OCFS2_NUM_LOCK_TYPES
50}; 51};
51 52
@@ -77,6 +78,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
77 case OCFS2_LOCK_TYPE_FLOCK: 78 case OCFS2_LOCK_TYPE_FLOCK:
78 c = 'F'; 79 c = 'F';
79 break; 80 break;
81 case OCFS2_LOCK_TYPE_QINFO:
82 c = 'Q';
83 break;
80 default: 84 default:
81 c = '\0'; 85 c = '\0';
82 } 86 }
@@ -95,6 +99,7 @@ static char *ocfs2_lock_type_strings[] = {
95 [OCFS2_LOCK_TYPE_DENTRY] = "Dentry", 99 [OCFS2_LOCK_TYPE_DENTRY] = "Dentry",
96 [OCFS2_LOCK_TYPE_OPEN] = "Open", 100 [OCFS2_LOCK_TYPE_OPEN] = "Open",
97 [OCFS2_LOCK_TYPE_FLOCK] = "Flock", 101 [OCFS2_LOCK_TYPE_FLOCK] = "Flock",
102 [OCFS2_LOCK_TYPE_QINFO] = "Quota",
98}; 103};
99 104
100static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) 105static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h
new file mode 100644
index 000000000000..1f1c86311b32
--- /dev/null
+++ b/fs/ocfs2/quota.h
@@ -0,0 +1,93 @@
1/*
2 * quota.h for OCFS2
3 *
4 * On disk quota structures for local and global quota file, in-memory
5 * structures.
6 *
7 */
8
9#ifndef _OCFS2_QUOTA_H
10#define _OCFS2_QUOTA_H
11
12#include <linux/types.h>
13#include <linux/slab.h>
14#include <linux/quota.h>
15#include <linux/list.h>
16#include <linux/dqblk_qtree.h>
17
18#include "ocfs2.h"
19
20/* Common stuff */
21/* id number of quota format */
22#define QFMT_OCFS2 3
23
24/*
25 * In-memory structures
26 */
27struct ocfs2_dquot {
28 struct dquot dq_dquot; /* Generic VFS dquot */
29 loff_t dq_local_off; /* Offset in the local quota file */
30 struct ocfs2_quota_chunk *dq_chunk; /* Chunk dquot is in */
31 unsigned int dq_use_count; /* Number of nodes having reference to this entry in global quota file */
32 s64 dq_origspace; /* Last globally synced space usage */
33 s64 dq_originodes; /* Last globally synced inode usage */
34};
35
36/* In-memory structure with quota header information */
37struct ocfs2_mem_dqinfo {
38 unsigned int dqi_type; /* Quota type this structure describes */
39 unsigned int dqi_chunks; /* Number of chunks in local quota file */
40 unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
41 unsigned int dqi_syncms; /* How often should we sync with other nodes */
42 struct list_head dqi_chunk; /* List of chunks */
43 struct inode *dqi_gqinode; /* Global quota file inode */
44 struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
45 struct buffer_head *dqi_gqi_bh; /* Buffer head with global quota file inode - set only if inode lock is obtained */
46 int dqi_gqi_count; /* Number of holders of dqi_gqi_bh */
47 struct buffer_head *dqi_lqi_bh; /* Buffer head with local quota file inode */
48 struct buffer_head *dqi_ibh; /* Buffer with information header */
49 struct qtree_mem_dqinfo dqi_gi; /* Info about global file */
50};
51
52static inline struct ocfs2_dquot *OCFS2_DQUOT(struct dquot *dquot)
53{
54 return container_of(dquot, struct ocfs2_dquot, dq_dquot);
55}
56
57struct ocfs2_quota_chunk {
58 struct list_head qc_chunk; /* List of quotafile chunks */
59 int qc_num; /* Number of quota chunk */
60 struct buffer_head *qc_headerbh; /* Buffer head with chunk header */
61};
62
63extern struct kmem_cache *ocfs2_dquot_cachep;
64extern struct kmem_cache *ocfs2_qf_chunk_cachep;
65
66extern struct qtree_fmt_operations ocfs2_global_ops;
67
68ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
69 size_t len, loff_t off);
70ssize_t ocfs2_quota_write(struct super_block *sb, int type,
71 const char *data, size_t len, loff_t off);
72int ocfs2_global_read_info(struct super_block *sb, int type);
73int ocfs2_global_write_info(struct super_block *sb, int type);
74int ocfs2_global_read_dquot(struct dquot *dquot);
75int __ocfs2_sync_dquot(struct dquot *dquot, int freeing);
76static inline int ocfs2_sync_dquot(struct dquot *dquot)
77{
78 return __ocfs2_sync_dquot(dquot, 0);
79}
80static inline int ocfs2_global_release_dquot(struct dquot *dquot)
81{
82 return __ocfs2_sync_dquot(dquot, 1);
83}
84
85int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
86void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
87struct buffer_head *ocfs2_read_quota_block(struct inode *inode,
88 int block, int *err);
89
90extern struct dquot_operations ocfs2_quota_operations;
91extern struct quota_format_type ocfs2_quota_format;
92
93#endif /* _OCFS2_QUOTA_H */
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
new file mode 100644
index 000000000000..af8340c45367
--- /dev/null
+++ b/fs/ocfs2/quota_global.c
@@ -0,0 +1,919 @@
1/*
2 * Implementation of operations over global quota file
3 */
4#include <linux/fs.h>
5#include <linux/quota.h>
6#include <linux/quotaops.h>
7#include <linux/dqblk_qtree.h>
8
9#define MLOG_MASK_PREFIX ML_QUOTA
10#include <cluster/masklog.h>
11
12#include "ocfs2_fs.h"
13#include "ocfs2.h"
14#include "alloc.h"
15#include "inode.h"
16#include "journal.h"
17#include "file.h"
18#include "sysfile.h"
19#include "dlmglue.h"
20#include "uptodate.h"
21#include "quota.h"
22
23static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
24{
25 struct ocfs2_global_disk_dqblk *d = dp;
26 struct mem_dqblk *m = &dquot->dq_dqb;
27
28 /* Update from disk only entries not set by the admin */
29 if (!test_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags)) {
30 m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
31 m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
32 }
33 if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
34 m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
35 if (!test_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags)) {
36 m->dqb_bhardlimit = le64_to_cpu(d->dqb_bhardlimit);
37 m->dqb_bsoftlimit = le64_to_cpu(d->dqb_bsoftlimit);
38 }
39 if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
40 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
41 if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags))
42 m->dqb_btime = le64_to_cpu(d->dqb_btime);
43 if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags))
44 m->dqb_itime = le64_to_cpu(d->dqb_itime);
45 OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count);
46}
47
48static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
49{
50 struct ocfs2_global_disk_dqblk *d = dp;
51 struct mem_dqblk *m = &dquot->dq_dqb;
52
53 d->dqb_id = cpu_to_le32(dquot->dq_id);
54 d->dqb_use_count = cpu_to_le32(OCFS2_DQUOT(dquot)->dq_use_count);
55 d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
56 d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
57 d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
58 d->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
59 d->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
60 d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
61 d->dqb_btime = cpu_to_le64(m->dqb_btime);
62 d->dqb_itime = cpu_to_le64(m->dqb_itime);
63}
64
65static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
66{
67 struct ocfs2_global_disk_dqblk *d = dp;
68 struct ocfs2_mem_dqinfo *oinfo =
69 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
70
71 if (qtree_entry_unused(&oinfo->dqi_gi, dp))
72 return 0;
73 return le32_to_cpu(d->dqb_id) == dquot->dq_id;
74}
75
76struct qtree_fmt_operations ocfs2_global_ops = {
77 .mem2disk_dqblk = ocfs2_global_mem2diskdqb,
78 .disk2mem_dqblk = ocfs2_global_disk2memdqb,
79 .is_id = ocfs2_global_is_id,
80};
81
82
83struct buffer_head *ocfs2_read_quota_block(struct inode *inode,
84 int block, int *err)
85{
86 struct buffer_head *tmp = NULL;
87
88 *err = ocfs2_read_virt_blocks(inode, block, 1, &tmp, 0, NULL);
89 if (*err)
90 mlog_errno(*err);
91
92 return tmp;
93}
94
95static struct buffer_head *ocfs2_get_quota_block(struct inode *inode,
96 int block, int *err)
97{
98 u64 pblock, pcount;
99 struct buffer_head *bh;
100
101 down_read(&OCFS2_I(inode)->ip_alloc_sem);
102 *err = ocfs2_extent_map_get_blocks(inode, block, &pblock, &pcount,
103 NULL);
104 up_read(&OCFS2_I(inode)->ip_alloc_sem);
105 if (*err) {
106 mlog_errno(*err);
107 return NULL;
108 }
109 bh = sb_getblk(inode->i_sb, pblock);
110 if (!bh) {
111 *err = -EIO;
112 mlog_errno(*err);
113 }
114 return bh;
115}
116
117/* Read data from global quotafile - avoid pagecache and such because we cannot
118 * afford acquiring the locks... We use quota cluster lock to serialize
119 * operations. Caller is responsible for acquiring it. */
120ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
121 size_t len, loff_t off)
122{
123 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
124 struct inode *gqinode = oinfo->dqi_gqinode;
125 loff_t i_size = i_size_read(gqinode);
126 int offset = off & (sb->s_blocksize - 1);
127 sector_t blk = off >> sb->s_blocksize_bits;
128 int err = 0;
129 struct buffer_head *bh;
130 size_t toread, tocopy;
131
132 if (off > i_size)
133 return 0;
134 if (off + len > i_size)
135 len = i_size - off;
136 toread = len;
137 while (toread > 0) {
138 tocopy = min((size_t)(sb->s_blocksize - offset), toread);
139 bh = ocfs2_read_quota_block(gqinode, blk, &err);
140 if (!bh) {
141 mlog_errno(err);
142 return err;
143 }
144 memcpy(data, bh->b_data + offset, tocopy);
145 brelse(bh);
146 offset = 0;
147 toread -= tocopy;
148 data += tocopy;
149 blk++;
150 }
151 return len;
152}
153
154/* Write to quotafile (we know the transaction is already started and has
155 * enough credits) */
156ssize_t ocfs2_quota_write(struct super_block *sb, int type,
157 const char *data, size_t len, loff_t off)
158{
159 struct mem_dqinfo *info = sb_dqinfo(sb, type);
160 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
161 struct inode *gqinode = oinfo->dqi_gqinode;
162 int offset = off & (sb->s_blocksize - 1);
163 sector_t blk = off >> sb->s_blocksize_bits;
164 int err = 0, new = 0;
165 struct buffer_head *bh;
166 handle_t *handle = journal_current_handle();
167
168 if (!handle) {
169 mlog(ML_ERROR, "Quota write (off=%llu, len=%llu) cancelled "
170 "because transaction was not started.\n",
171 (unsigned long long)off, (unsigned long long)len);
172 return -EIO;
173 }
174 if (len > sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset) {
175 WARN_ON(1);
176 len = sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset;
177 }
178
179 mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
180 if (gqinode->i_size < off + len) {
181 down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
182 err = ocfs2_extend_no_holes(gqinode, off + len, off);
183 up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
184 if (err < 0)
185 goto out;
186 err = ocfs2_simple_size_update(gqinode,
187 oinfo->dqi_gqi_bh,
188 off + len);
189 if (err < 0)
190 goto out;
191 new = 1;
192 }
193 /* Not rewriting whole block? */
194 if ((offset || len < sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) &&
195 !new) {
196 bh = ocfs2_read_quota_block(gqinode, blk, &err);
197 if (!bh) {
198 mlog_errno(err);
199 return err;
200 }
201 err = ocfs2_journal_access(handle, gqinode, bh,
202 OCFS2_JOURNAL_ACCESS_WRITE);
203 } else {
204 bh = ocfs2_get_quota_block(gqinode, blk, &err);
205 if (!bh) {
206 mlog_errno(err);
207 return err;
208 }
209 err = ocfs2_journal_access(handle, gqinode, bh,
210 OCFS2_JOURNAL_ACCESS_CREATE);
211 }
212 if (err < 0) {
213 brelse(bh);
214 goto out;
215 }
216 lock_buffer(bh);
217 if (new)
218 memset(bh->b_data, 0, sb->s_blocksize);
219 memcpy(bh->b_data + offset, data, len);
220 flush_dcache_page(bh->b_page);
221 unlock_buffer(bh);
222 ocfs2_set_buffer_uptodate(gqinode, bh);
223 err = ocfs2_journal_dirty(handle, bh);
224 brelse(bh);
225 if (err < 0)
226 goto out;
227out:
228 if (err) {
229 mutex_unlock(&gqinode->i_mutex);
230 mlog_errno(err);
231 return err;
232 }
233 gqinode->i_version++;
234 ocfs2_mark_inode_dirty(handle, gqinode, oinfo->dqi_gqi_bh);
235 mutex_unlock(&gqinode->i_mutex);
236 return len;
237}
238
239int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
240{
241 int status;
242 struct buffer_head *bh = NULL;
243
244 status = ocfs2_inode_lock(oinfo->dqi_gqinode, &bh, ex);
245 if (status < 0)
246 return status;
247 spin_lock(&dq_data_lock);
248 if (!oinfo->dqi_gqi_count++)
249 oinfo->dqi_gqi_bh = bh;
250 else
251 WARN_ON(bh != oinfo->dqi_gqi_bh);
252 spin_unlock(&dq_data_lock);
253 return 0;
254}
255
256void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
257{
258 ocfs2_inode_unlock(oinfo->dqi_gqinode, ex);
259 brelse(oinfo->dqi_gqi_bh);
260 spin_lock(&dq_data_lock);
261 if (!--oinfo->dqi_gqi_count)
262 oinfo->dqi_gqi_bh = NULL;
263 spin_unlock(&dq_data_lock);
264}
265
266/* Read information header from global quota file */
267int ocfs2_global_read_info(struct super_block *sb, int type)
268{
269 struct inode *gqinode = NULL;
270 unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
271 GROUP_QUOTA_SYSTEM_INODE };
272 struct ocfs2_global_disk_dqinfo dinfo;
273 struct mem_dqinfo *info = sb_dqinfo(sb, type);
274 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
275 int status;
276
277 mlog_entry_void();
278
279 /* Read global header */
280 gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
281 OCFS2_INVALID_SLOT);
282 if (!gqinode) {
283 mlog(ML_ERROR, "failed to get global quota inode (type=%d)\n",
284 type);
285 status = -EINVAL;
286 goto out_err;
287 }
288 oinfo->dqi_gi.dqi_sb = sb;
289 oinfo->dqi_gi.dqi_type = type;
290 ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
291 oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
292 oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
293 oinfo->dqi_gqi_bh = NULL;
294 oinfo->dqi_gqi_count = 0;
295 oinfo->dqi_gqinode = gqinode;
296 status = ocfs2_lock_global_qf(oinfo, 0);
297 if (status < 0) {
298 mlog_errno(status);
299 goto out_err;
300 }
301 status = sb->s_op->quota_read(sb, type, (char *)&dinfo,
302 sizeof(struct ocfs2_global_disk_dqinfo),
303 OCFS2_GLOBAL_INFO_OFF);
304 ocfs2_unlock_global_qf(oinfo, 0);
305 if (status != sizeof(struct ocfs2_global_disk_dqinfo)) {
306 mlog(ML_ERROR, "Cannot read global quota info (%d).\n",
307 status);
308 if (status >= 0)
309 status = -EIO;
310 mlog_errno(status);
311 goto out_err;
312 }
313 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
314 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
315 oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
316 oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
317 oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
318 oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
319 oinfo->dqi_gi.dqi_blocksize_bits = sb->s_blocksize_bits;
320 oinfo->dqi_gi.dqi_usable_bs = sb->s_blocksize -
321 OCFS2_QBLK_RESERVED_SPACE;
322 oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
323out_err:
324 mlog_exit(status);
325 return status;
326}
327
328/* Write information to global quota file. Expects exlusive lock on quota
329 * file inode and quota info */
330static int __ocfs2_global_write_info(struct super_block *sb, int type)
331{
332 struct mem_dqinfo *info = sb_dqinfo(sb, type);
333 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
334 struct ocfs2_global_disk_dqinfo dinfo;
335 ssize_t size;
336
337 spin_lock(&dq_data_lock);
338 info->dqi_flags &= ~DQF_INFO_DIRTY;
339 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
340 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
341 spin_unlock(&dq_data_lock);
342 dinfo.dqi_syncms = cpu_to_le32(oinfo->dqi_syncms);
343 dinfo.dqi_blocks = cpu_to_le32(oinfo->dqi_gi.dqi_blocks);
344 dinfo.dqi_free_blk = cpu_to_le32(oinfo->dqi_gi.dqi_free_blk);
345 dinfo.dqi_free_entry = cpu_to_le32(oinfo->dqi_gi.dqi_free_entry);
346 size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
347 sizeof(struct ocfs2_global_disk_dqinfo),
348 OCFS2_GLOBAL_INFO_OFF);
349 if (size != sizeof(struct ocfs2_global_disk_dqinfo)) {
350 mlog(ML_ERROR, "Cannot write global quota info structure\n");
351 if (size >= 0)
352 size = -EIO;
353 return size;
354 }
355 return 0;
356}
357
358int ocfs2_global_write_info(struct super_block *sb, int type)
359{
360 int err;
361 struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
362
363 err = ocfs2_qinfo_lock(info, 1);
364 if (err < 0)
365 return err;
366 err = __ocfs2_global_write_info(sb, type);
367 ocfs2_qinfo_unlock(info, 1);
368 return err;
369}
370
371/* Read in information from global quota file and acquire a reference to it.
372 * dquot_acquire() has already started the transaction and locked quota file */
373int ocfs2_global_read_dquot(struct dquot *dquot)
374{
375 int err, err2, ex = 0;
376 struct ocfs2_mem_dqinfo *info =
377 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
378
379 err = ocfs2_qinfo_lock(info, 0);
380 if (err < 0)
381 goto out;
382 err = qtree_read_dquot(&info->dqi_gi, dquot);
383 if (err < 0)
384 goto out_qlock;
385 OCFS2_DQUOT(dquot)->dq_use_count++;
386 OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
387 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
388 if (!dquot->dq_off) { /* No real quota entry? */
389 /* Upgrade to exclusive lock for allocation */
390 err = ocfs2_qinfo_lock(info, 1);
391 if (err < 0)
392 goto out_qlock;
393 ex = 1;
394 }
395 err = qtree_write_dquot(&info->dqi_gi, dquot);
396 if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
397 err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
398 if (!err)
399 err = err2;
400 }
401out_qlock:
402 if (ex)
403 ocfs2_qinfo_unlock(info, 1);
404 ocfs2_qinfo_unlock(info, 0);
405out:
406 if (err < 0)
407 mlog_errno(err);
408 return err;
409}
410
411/* Sync local information about quota modifications with global quota file.
412 * Caller must have started the transaction and obtained exclusive lock for
413 * global quota file inode */
414int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
415{
416 int err, err2;
417 struct super_block *sb = dquot->dq_sb;
418 int type = dquot->dq_type;
419 struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
420 struct ocfs2_global_disk_dqblk dqblk;
421 s64 spacechange, inodechange;
422 time_t olditime, oldbtime;
423
424 err = sb->s_op->quota_read(sb, type, (char *)&dqblk,
425 sizeof(struct ocfs2_global_disk_dqblk),
426 dquot->dq_off);
427 if (err != sizeof(struct ocfs2_global_disk_dqblk)) {
428 if (err >= 0) {
429 mlog(ML_ERROR, "Short read from global quota file "
430 "(%u read)\n", err);
431 err = -EIO;
432 }
433 goto out;
434 }
435
436 /* Update space and inode usage. Get also other information from
437 * global quota file so that we don't overwrite any changes there.
438 * We are */
439 spin_lock(&dq_data_lock);
440 spacechange = dquot->dq_dqb.dqb_curspace -
441 OCFS2_DQUOT(dquot)->dq_origspace;
442 inodechange = dquot->dq_dqb.dqb_curinodes -
443 OCFS2_DQUOT(dquot)->dq_originodes;
444 olditime = dquot->dq_dqb.dqb_itime;
445 oldbtime = dquot->dq_dqb.dqb_btime;
446 ocfs2_global_disk2memdqb(dquot, &dqblk);
447 mlog(0, "Syncing global dquot %d space %lld+%lld, inodes %lld+%lld\n",
448 dquot->dq_id, dquot->dq_dqb.dqb_curspace, spacechange,
449 dquot->dq_dqb.dqb_curinodes, inodechange);
450 if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
451 dquot->dq_dqb.dqb_curspace += spacechange;
452 if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
453 dquot->dq_dqb.dqb_curinodes += inodechange;
454 /* Set properly space grace time... */
455 if (dquot->dq_dqb.dqb_bsoftlimit &&
456 dquot->dq_dqb.dqb_curspace > dquot->dq_dqb.dqb_bsoftlimit) {
457 if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags) &&
458 oldbtime > 0) {
459 if (dquot->dq_dqb.dqb_btime > 0)
460 dquot->dq_dqb.dqb_btime =
461 min(dquot->dq_dqb.dqb_btime, oldbtime);
462 else
463 dquot->dq_dqb.dqb_btime = oldbtime;
464 }
465 } else {
466 dquot->dq_dqb.dqb_btime = 0;
467 clear_bit(DQ_BLKS_B, &dquot->dq_flags);
468 }
469 /* Set properly inode grace time... */
470 if (dquot->dq_dqb.dqb_isoftlimit &&
471 dquot->dq_dqb.dqb_curinodes > dquot->dq_dqb.dqb_isoftlimit) {
472 if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags) &&
473 olditime > 0) {
474 if (dquot->dq_dqb.dqb_itime > 0)
475 dquot->dq_dqb.dqb_itime =
476 min(dquot->dq_dqb.dqb_itime, olditime);
477 else
478 dquot->dq_dqb.dqb_itime = olditime;
479 }
480 } else {
481 dquot->dq_dqb.dqb_itime = 0;
482 clear_bit(DQ_INODES_B, &dquot->dq_flags);
483 }
484 /* All information is properly updated, clear the flags */
485 __clear_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
486 __clear_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
487 __clear_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
488 __clear_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
489 __clear_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
490 __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
491 OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
492 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
493 spin_unlock(&dq_data_lock);
494 err = ocfs2_qinfo_lock(info, freeing);
495 if (err < 0) {
496 mlog(ML_ERROR, "Failed to lock quota info, loosing quota write"
497 " (type=%d, id=%u)\n", dquot->dq_type,
498 (unsigned)dquot->dq_id);
499 goto out;
500 }
501 if (freeing)
502 OCFS2_DQUOT(dquot)->dq_use_count--;
503 err = qtree_write_dquot(&info->dqi_gi, dquot);
504 if (err < 0)
505 goto out_qlock;
506 if (freeing && !OCFS2_DQUOT(dquot)->dq_use_count) {
507 err = qtree_release_dquot(&info->dqi_gi, dquot);
508 if (info_dirty(sb_dqinfo(sb, type))) {
509 err2 = __ocfs2_global_write_info(sb, type);
510 if (!err)
511 err = err2;
512 }
513 }
514out_qlock:
515 ocfs2_qinfo_unlock(info, freeing);
516out:
517 if (err < 0)
518 mlog_errno(err);
519 return err;
520}
521
522/*
523 * Wrappers for generic quota functions
524 */
525
526static int ocfs2_write_dquot(struct dquot *dquot)
527{
528 handle_t *handle;
529 struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
530 int status = 0;
531
532 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
533
534 handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS);
535 if (IS_ERR(handle)) {
536 status = PTR_ERR(handle);
537 mlog_errno(status);
538 goto out;
539 }
540 status = dquot_commit(dquot);
541 ocfs2_commit_trans(osb, handle);
542out:
543 mlog_exit(status);
544 return status;
545}
546
547int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
548{
549 struct ocfs2_mem_dqinfo *oinfo;
550 int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
551 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
552
553 if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
554 return 0;
555
556 oinfo = sb_dqinfo(sb, type)->dqi_priv;
557 /* We modify tree, leaf block, global info, local chunk header,
558 * global and local inode */
559 return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
560 2 * OCFS2_INODE_UPDATE_CREDITS;
561}
562
563static int ocfs2_release_dquot(struct dquot *dquot)
564{
565 handle_t *handle;
566 struct ocfs2_mem_dqinfo *oinfo =
567 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
568 struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
569 int status = 0;
570
571 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
572
573 status = ocfs2_lock_global_qf(oinfo, 1);
574 if (status < 0)
575 goto out;
576 handle = ocfs2_start_trans(osb,
577 ocfs2_calc_qdel_credits(dquot->dq_sb, dquot->dq_type));
578 if (IS_ERR(handle)) {
579 status = PTR_ERR(handle);
580 mlog_errno(status);
581 goto out_ilock;
582 }
583 status = dquot_release(dquot);
584 ocfs2_commit_trans(osb, handle);
585out_ilock:
586 ocfs2_unlock_global_qf(oinfo, 1);
587out:
588 mlog_exit(status);
589 return status;
590}
591
592int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
593{
594 struct ocfs2_mem_dqinfo *oinfo;
595 int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
596 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
597 struct ocfs2_dinode *lfe, *gfe;
598
599 if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
600 return 0;
601
602 oinfo = sb_dqinfo(sb, type)->dqi_priv;
603 gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
604 lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
605 /* We can extend local file + global file. In local file we
606 * can modify info, chunk header block and dquot block. In
607 * global file we can modify info, tree and leaf block */
608 return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
609 ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
610 3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
611}
612
613static int ocfs2_acquire_dquot(struct dquot *dquot)
614{
615 handle_t *handle;
616 struct ocfs2_mem_dqinfo *oinfo =
617 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
618 struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
619 int status = 0;
620
621 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
622 /* We need an exclusive lock, because we're going to update use count
623 * and instantiate possibly new dquot structure */
624 status = ocfs2_lock_global_qf(oinfo, 1);
625 if (status < 0)
626 goto out;
627 handle = ocfs2_start_trans(osb,
628 ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
629 if (IS_ERR(handle)) {
630 status = PTR_ERR(handle);
631 mlog_errno(status);
632 goto out_ilock;
633 }
634 status = dquot_acquire(dquot);
635 ocfs2_commit_trans(osb, handle);
636out_ilock:
637 ocfs2_unlock_global_qf(oinfo, 1);
638out:
639 mlog_exit(status);
640 return status;
641}
642
643static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
644{
645 unsigned long mask = (1 << (DQ_LASTSET_B + QIF_ILIMITS_B)) |
646 (1 << (DQ_LASTSET_B + QIF_BLIMITS_B)) |
647 (1 << (DQ_LASTSET_B + QIF_INODES_B)) |
648 (1 << (DQ_LASTSET_B + QIF_SPACE_B)) |
649 (1 << (DQ_LASTSET_B + QIF_BTIME_B)) |
650 (1 << (DQ_LASTSET_B + QIF_ITIME_B));
651 int sync = 0;
652 int status;
653 struct super_block *sb = dquot->dq_sb;
654 int type = dquot->dq_type;
655 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
656 handle_t *handle;
657 struct ocfs2_super *osb = OCFS2_SB(sb);
658
659 mlog_entry("id=%u, type=%d", dquot->dq_id, type);
660 dquot_mark_dquot_dirty(dquot);
661
662 /* In case user set some limits, sync dquot immediately to global
663 * quota file so that information propagates quicker */
664 spin_lock(&dq_data_lock);
665 if (dquot->dq_flags & mask)
666 sync = 1;
667 spin_unlock(&dq_data_lock);
668 if (!sync) {
669 status = ocfs2_write_dquot(dquot);
670 goto out;
671 }
672 status = ocfs2_lock_global_qf(oinfo, 1);
673 if (status < 0)
674 goto out;
675 handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
676 if (IS_ERR(handle)) {
677 status = PTR_ERR(handle);
678 mlog_errno(status);
679 goto out_ilock;
680 }
681 status = ocfs2_sync_dquot(dquot);
682 if (status < 0) {
683 mlog_errno(status);
684 goto out_trans;
685 }
686 /* Now write updated local dquot structure */
687 status = dquot_commit(dquot);
688out_trans:
689 ocfs2_commit_trans(osb, handle);
690out_ilock:
691 ocfs2_unlock_global_qf(oinfo, 1);
692out:
693 mlog_exit(status);
694 return status;
695}
696
697/* This should happen only after set_dqinfo(). */
698static int ocfs2_write_info(struct super_block *sb, int type)
699{
700 handle_t *handle;
701 int status = 0;
702 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
703
704 mlog_entry_void();
705
706 status = ocfs2_lock_global_qf(oinfo, 1);
707 if (status < 0)
708 goto out;
709 handle = ocfs2_start_trans(OCFS2_SB(sb), OCFS2_QINFO_WRITE_CREDITS);
710 if (IS_ERR(handle)) {
711 status = PTR_ERR(handle);
712 mlog_errno(status);
713 goto out_ilock;
714 }
715 status = dquot_commit_info(sb, type);
716 ocfs2_commit_trans(OCFS2_SB(sb), handle);
717out_ilock:
718 ocfs2_unlock_global_qf(oinfo, 1);
719out:
720 mlog_exit(status);
721 return status;
722}
723
724/* This is difficult. We have to lock quota inode and start transaction
725 * in this function but we don't want to take the penalty of exlusive
726 * quota file lock when we are just going to use cached structures. So
727 * we just take read lock check whether we have dquot cached and if so,
728 * we don't have to take the write lock... */
729static int ocfs2_dquot_initialize(struct inode *inode, int type)
730{
731 handle_t *handle = NULL;
732 int status = 0;
733 struct super_block *sb = inode->i_sb;
734 struct ocfs2_mem_dqinfo *oinfo;
735 int exclusive = 0;
736 int cnt;
737 qid_t id;
738
739 mlog_entry_void();
740
741 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
742 if (type != -1 && cnt != type)
743 continue;
744 if (!sb_has_quota_active(sb, cnt))
745 continue;
746 oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
747 status = ocfs2_lock_global_qf(oinfo, 0);
748 if (status < 0)
749 goto out;
750 /* This is just a performance optimization not a reliable test.
751 * Since we hold an inode lock, noone can actually release
752 * the structure until we are finished with initialization. */
753 if (inode->i_dquot[cnt] != NODQUOT) {
754 ocfs2_unlock_global_qf(oinfo, 0);
755 continue;
756 }
757 /* When we have inode lock, we know that no dquot_release() can
758 * run and thus we can safely check whether we need to
759 * read+modify global file to get quota information or whether
760 * our node already has it. */
761 if (cnt == USRQUOTA)
762 id = inode->i_uid;
763 else if (cnt == GRPQUOTA)
764 id = inode->i_gid;
765 else
766 BUG();
767 /* Obtain exclusion from quota off... */
768 down_write(&sb_dqopt(sb)->dqptr_sem);
769 exclusive = !dquot_is_cached(sb, id, cnt);
770 up_write(&sb_dqopt(sb)->dqptr_sem);
771 if (exclusive) {
772 status = ocfs2_lock_global_qf(oinfo, 1);
773 if (status < 0) {
774 exclusive = 0;
775 mlog_errno(status);
776 goto out_ilock;
777 }
778 handle = ocfs2_start_trans(OCFS2_SB(sb),
779 ocfs2_calc_qinit_credits(sb, cnt));
780 if (IS_ERR(handle)) {
781 status = PTR_ERR(handle);
782 mlog_errno(status);
783 goto out_ilock;
784 }
785 }
786 dquot_initialize(inode, cnt);
787 if (exclusive) {
788 ocfs2_commit_trans(OCFS2_SB(sb), handle);
789 ocfs2_unlock_global_qf(oinfo, 1);
790 }
791 ocfs2_unlock_global_qf(oinfo, 0);
792 }
793 mlog_exit(0);
794 return 0;
795out_ilock:
796 if (exclusive)
797 ocfs2_unlock_global_qf(oinfo, 1);
798 ocfs2_unlock_global_qf(oinfo, 0);
799out:
800 mlog_exit(status);
801 return status;
802}
803
804static int ocfs2_dquot_drop_slow(struct inode *inode)
805{
806 int status;
807 int cnt;
808 int got_lock[MAXQUOTAS] = {0, 0};
809 handle_t *handle;
810 struct super_block *sb = inode->i_sb;
811 struct ocfs2_mem_dqinfo *oinfo;
812
813 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
814 if (!sb_has_quota_active(sb, cnt))
815 continue;
816 oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
817 status = ocfs2_lock_global_qf(oinfo, 1);
818 if (status < 0)
819 goto out;
820 got_lock[cnt] = 1;
821 }
822 handle = ocfs2_start_trans(OCFS2_SB(sb),
823 ocfs2_calc_qinit_credits(sb, USRQUOTA) +
824 ocfs2_calc_qinit_credits(sb, GRPQUOTA));
825 if (IS_ERR(handle)) {
826 status = PTR_ERR(handle);
827 mlog_errno(status);
828 goto out;
829 }
830 dquot_drop(inode);
831 ocfs2_commit_trans(OCFS2_SB(sb), handle);
832out:
833 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
834 if (got_lock[cnt]) {
835 oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
836 ocfs2_unlock_global_qf(oinfo, 1);
837 }
838 return status;
839}
840
841/* See the comment before ocfs2_dquot_initialize. */
842static int ocfs2_dquot_drop(struct inode *inode)
843{
844 int status = 0;
845 struct super_block *sb = inode->i_sb;
846 struct ocfs2_mem_dqinfo *oinfo;
847 int exclusive = 0;
848 int cnt;
849 int got_lock[MAXQUOTAS] = {0, 0};
850
851 mlog_entry_void();
852 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
853 if (!sb_has_quota_active(sb, cnt))
854 continue;
855 oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
856 status = ocfs2_lock_global_qf(oinfo, 0);
857 if (status < 0)
858 goto out;
859 got_lock[cnt] = 1;
860 }
861 /* Lock against anyone releasing references so that when when we check
862 * we know we are not going to be last ones to release dquot */
863 down_write(&sb_dqopt(sb)->dqptr_sem);
864 /* Urgh, this is a terrible hack :( */
865 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
866 if (inode->i_dquot[cnt] != NODQUOT &&
867 atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) {
868 exclusive = 1;
869 break;
870 }
871 }
872 if (!exclusive)
873 dquot_drop_locked(inode);
874 up_write(&sb_dqopt(sb)->dqptr_sem);
875out:
876 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
877 if (got_lock[cnt]) {
878 oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
879 ocfs2_unlock_global_qf(oinfo, 0);
880 }
881 /* In case we bailed out because we had to do expensive locking
882 * do it now... */
883 if (exclusive)
884 status = ocfs2_dquot_drop_slow(inode);
885 mlog_exit(status);
886 return status;
887}
888
889static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
890{
891 struct ocfs2_dquot *dquot =
892 kmem_cache_zalloc(ocfs2_dquot_cachep, GFP_NOFS);
893
894 if (!dquot)
895 return NULL;
896 return &dquot->dq_dquot;
897}
898
899static void ocfs2_destroy_dquot(struct dquot *dquot)
900{
901 kmem_cache_free(ocfs2_dquot_cachep, dquot);
902}
903
904struct dquot_operations ocfs2_quota_operations = {
905 .initialize = ocfs2_dquot_initialize,
906 .drop = ocfs2_dquot_drop,
907 .alloc_space = dquot_alloc_space,
908 .alloc_inode = dquot_alloc_inode,
909 .free_space = dquot_free_space,
910 .free_inode = dquot_free_inode,
911 .transfer = dquot_transfer,
912 .write_dquot = ocfs2_write_dquot,
913 .acquire_dquot = ocfs2_acquire_dquot,
914 .release_dquot = ocfs2_release_dquot,
915 .mark_dirty = ocfs2_mark_dquot_dirty,
916 .write_info = ocfs2_write_info,
917 .alloc_dquot = ocfs2_alloc_dquot,
918 .destroy_dquot = ocfs2_destroy_dquot,
919};
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
new file mode 100644
index 000000000000..55c3f2f98dcd
--- /dev/null
+++ b/fs/ocfs2/quota_local.c
@@ -0,0 +1,833 @@
1/*
2 * Implementation of operations over local quota file
3 */
4
5#include <linux/fs.h>
6#include <linux/quota.h>
7#include <linux/quotaops.h>
8#include <linux/module.h>
9
10#define MLOG_MASK_PREFIX ML_QUOTA
11#include <cluster/masklog.h>
12
13#include "ocfs2_fs.h"
14#include "ocfs2.h"
15#include "inode.h"
16#include "alloc.h"
17#include "file.h"
18#include "buffer_head_io.h"
19#include "journal.h"
20#include "sysfile.h"
21#include "dlmglue.h"
22#include "quota.h"
23
24/* Number of local quota structures per block */
25static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
26{
27 return ((sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) /
28 sizeof(struct ocfs2_local_disk_dqblk));
29}
30
31/* Number of blocks with entries in one chunk */
32static inline unsigned int ol_chunk_blocks(struct super_block *sb)
33{
34 return ((sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
35 OCFS2_QBLK_RESERVED_SPACE) << 3) /
36 ol_quota_entries_per_block(sb);
37}
38
39/* Number of entries in a chunk bitmap */
40static unsigned int ol_chunk_entries(struct super_block *sb)
41{
42 return ol_chunk_blocks(sb) * ol_quota_entries_per_block(sb);
43}
44
45/* Offset of the chunk in quota file */
46static unsigned int ol_quota_chunk_block(struct super_block *sb, int c)
47{
48 /* 1 block for local quota file info, 1 block per chunk for chunk info */
49 return 1 + (ol_chunk_blocks(sb) + 1) * c;
50}
51
52/* Offset of the dquot structure in the quota file */
53static loff_t ol_dqblk_off(struct super_block *sb, int c, int off)
54{
55 int epb = ol_quota_entries_per_block(sb);
56
57 return ((ol_quota_chunk_block(sb, c) + 1 + off / epb)
58 << sb->s_blocksize_bits) +
59 (off % epb) * sizeof(struct ocfs2_local_disk_dqblk);
60}
61
62/* Compute block number from given offset */
63static inline unsigned int ol_dqblk_file_block(struct super_block *sb, loff_t off)
64{
65 return off >> sb->s_blocksize_bits;
66}
67
68static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off)
69{
70 return off & ((1 << sb->s_blocksize_bits) - 1);
71}
72
73/* Compute offset in the chunk of a structure with the given offset */
74static int ol_dqblk_chunk_off(struct super_block *sb, int c, loff_t off)
75{
76 int epb = ol_quota_entries_per_block(sb);
77
78 return ((off >> sb->s_blocksize_bits) -
79 ol_quota_chunk_block(sb, c) - 1) * epb
80 + ((unsigned int)(off & ((1 << sb->s_blocksize_bits) - 1))) /
81 sizeof(struct ocfs2_local_disk_dqblk);
82}
83
84/* Write bufferhead into the fs */
85static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
86 void (*modify)(struct buffer_head *, void *), void *private)
87{
88 struct super_block *sb = inode->i_sb;
89 handle_t *handle;
90 int status;
91
92 handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
93 if (IS_ERR(handle)) {
94 status = PTR_ERR(handle);
95 mlog_errno(status);
96 return status;
97 }
98 status = ocfs2_journal_access(handle, inode, bh,
99 OCFS2_JOURNAL_ACCESS_WRITE);
100 if (status < 0) {
101 mlog_errno(status);
102 ocfs2_commit_trans(OCFS2_SB(sb), handle);
103 return status;
104 }
105 lock_buffer(bh);
106 modify(bh, private);
107 unlock_buffer(bh);
108 status = ocfs2_journal_dirty(handle, bh);
109 if (status < 0) {
110 mlog_errno(status);
111 ocfs2_commit_trans(OCFS2_SB(sb), handle);
112 return status;
113 }
114 status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
115 if (status < 0) {
116 mlog_errno(status);
117 return status;
118 }
119 return 0;
120}
121
122/* Check whether we understand format of quota files */
123static int ocfs2_local_check_quota_file(struct super_block *sb, int type)
124{
125 unsigned int lmagics[MAXQUOTAS] = OCFS2_LOCAL_QMAGICS;
126 unsigned int lversions[MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS;
127 unsigned int gmagics[MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS;
128 unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS;
129 unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
130 GROUP_QUOTA_SYSTEM_INODE };
131 struct buffer_head *bh;
132 struct inode *linode = sb_dqopt(sb)->files[type];
133 struct inode *ginode = NULL;
134 struct ocfs2_disk_dqheader *dqhead;
135 int status, ret = 0;
136
137 /* First check whether we understand local quota file */
138 bh = ocfs2_read_quota_block(linode, 0, &status);
139 if (!bh) {
140 mlog_errno(status);
141 mlog(ML_ERROR, "failed to read quota file header (type=%d)\n",
142 type);
143 goto out_err;
144 }
145 dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
146 if (le32_to_cpu(dqhead->dqh_magic) != lmagics[type]) {
147 mlog(ML_ERROR, "quota file magic does not match (%u != %u),"
148 " type=%d\n", le32_to_cpu(dqhead->dqh_magic),
149 lmagics[type], type);
150 goto out_err;
151 }
152 if (le32_to_cpu(dqhead->dqh_version) != lversions[type]) {
153 mlog(ML_ERROR, "quota file version does not match (%u != %u),"
154 " type=%d\n", le32_to_cpu(dqhead->dqh_version),
155 lversions[type], type);
156 goto out_err;
157 }
158 brelse(bh);
159 bh = NULL;
160
161 /* Next check whether we understand global quota file */
162 ginode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
163 OCFS2_INVALID_SLOT);
164 if (!ginode) {
165 mlog(ML_ERROR, "cannot get global quota file inode "
166 "(type=%d)\n", type);
167 goto out_err;
168 }
169 /* Since the header is read only, we don't care about locking */
170 bh = ocfs2_read_quota_block(ginode, 0, &status);
171 if (!bh) {
172 mlog_errno(status);
173 mlog(ML_ERROR, "failed to read global quota file header "
174 "(type=%d)\n", type);
175 goto out_err;
176 }
177 dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
178 if (le32_to_cpu(dqhead->dqh_magic) != gmagics[type]) {
179 mlog(ML_ERROR, "global quota file magic does not match "
180 "(%u != %u), type=%d\n",
181 le32_to_cpu(dqhead->dqh_magic), gmagics[type], type);
182 goto out_err;
183 }
184 if (le32_to_cpu(dqhead->dqh_version) != gversions[type]) {
185 mlog(ML_ERROR, "global quota file version does not match "
186 "(%u != %u), type=%d\n",
187 le32_to_cpu(dqhead->dqh_version), gversions[type],
188 type);
189 goto out_err;
190 }
191
192 ret = 1;
193out_err:
194 brelse(bh);
195 iput(ginode);
196 return ret;
197}
198
199/* Release given list of quota file chunks */
200static void ocfs2_release_local_quota_bitmaps(struct list_head *head)
201{
202 struct ocfs2_quota_chunk *pos, *next;
203
204 list_for_each_entry_safe(pos, next, head, qc_chunk) {
205 list_del(&pos->qc_chunk);
206 brelse(pos->qc_headerbh);
207 kmem_cache_free(ocfs2_qf_chunk_cachep, pos);
208 }
209}
210
211/* Load quota bitmaps into memory */
212static int ocfs2_load_local_quota_bitmaps(struct inode *inode,
213 struct ocfs2_local_disk_dqinfo *ldinfo,
214 struct list_head *head)
215{
216 struct ocfs2_quota_chunk *newchunk;
217 int i, status;
218
219 INIT_LIST_HEAD(head);
220 for (i = 0; i < le32_to_cpu(ldinfo->dqi_chunks); i++) {
221 newchunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
222 if (!newchunk) {
223 ocfs2_release_local_quota_bitmaps(head);
224 return -ENOMEM;
225 }
226 newchunk->qc_num = i;
227 newchunk->qc_headerbh = ocfs2_read_quota_block(inode,
228 ol_quota_chunk_block(inode->i_sb, i),
229 &status);
230 if (!newchunk->qc_headerbh) {
231 mlog_errno(status);
232 kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk);
233 ocfs2_release_local_quota_bitmaps(head);
234 return status;
235 }
236 list_add_tail(&newchunk->qc_chunk, head);
237 }
238 return 0;
239}
240
241static void olq_update_info(struct buffer_head *bh, void *private)
242{
243 struct mem_dqinfo *info = private;
244 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
245 struct ocfs2_local_disk_dqinfo *ldinfo;
246
247 ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
248 OCFS2_LOCAL_INFO_OFF);
249 spin_lock(&dq_data_lock);
250 ldinfo->dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
251 ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks);
252 ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks);
253 spin_unlock(&dq_data_lock);
254}
255
256/* Read information header from quota file */
257static int ocfs2_local_read_info(struct super_block *sb, int type)
258{
259 struct ocfs2_local_disk_dqinfo *ldinfo;
260 struct mem_dqinfo *info = sb_dqinfo(sb, type);
261 struct ocfs2_mem_dqinfo *oinfo;
262 struct inode *lqinode = sb_dqopt(sb)->files[type];
263 int status;
264 struct buffer_head *bh = NULL;
265 int locked = 0;
266
267 info->dqi_maxblimit = 0x7fffffffffffffffLL;
268 info->dqi_maxilimit = 0x7fffffffffffffffLL;
269 oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
270 if (!oinfo) {
271 mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
272 " info.");
273 goto out_err;
274 }
275 info->dqi_priv = oinfo;
276 oinfo->dqi_type = type;
277 INIT_LIST_HEAD(&oinfo->dqi_chunk);
278 oinfo->dqi_lqi_bh = NULL;
279 oinfo->dqi_ibh = NULL;
280
281 status = ocfs2_global_read_info(sb, type);
282 if (status < 0)
283 goto out_err;
284
285 status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1);
286 if (status < 0) {
287 mlog_errno(status);
288 goto out_err;
289 }
290 locked = 1;
291
292 /* Now read local header */
293 bh = ocfs2_read_quota_block(lqinode, 0, &status);
294 if (!bh) {
295 mlog_errno(status);
296 mlog(ML_ERROR, "failed to read quota file info header "
297 "(type=%d)\n", type);
298 goto out_err;
299 }
300 ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
301 OCFS2_LOCAL_INFO_OFF);
302 info->dqi_flags = le32_to_cpu(ldinfo->dqi_flags);
303 oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks);
304 oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks);
305 oinfo->dqi_ibh = bh;
306
307 /* We crashed when using local quota file? */
308 if (!(info->dqi_flags & OLQF_CLEAN))
309 goto out_err; /* So far we just bail out. Later we should resync here */
310
311 status = ocfs2_load_local_quota_bitmaps(sb_dqopt(sb)->files[type],
312 ldinfo,
313 &oinfo->dqi_chunk);
314 if (status < 0) {
315 mlog_errno(status);
316 goto out_err;
317 }
318
319 /* Now mark quota file as used */
320 info->dqi_flags &= ~OLQF_CLEAN;
321 status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info);
322 if (status < 0) {
323 mlog_errno(status);
324 goto out_err;
325 }
326
327 return 0;
328out_err:
329 if (oinfo) {
330 iput(oinfo->dqi_gqinode);
331 ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
332 ocfs2_lock_res_free(&oinfo->dqi_gqlock);
333 brelse(oinfo->dqi_lqi_bh);
334 if (locked)
335 ocfs2_inode_unlock(lqinode, 1);
336 ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
337 kfree(oinfo);
338 }
339 brelse(bh);
340 return -1;
341}
342
343/* Write local info to quota file */
344static int ocfs2_local_write_info(struct super_block *sb, int type)
345{
346 struct mem_dqinfo *info = sb_dqinfo(sb, type);
347 struct buffer_head *bh = ((struct ocfs2_mem_dqinfo *)info->dqi_priv)
348 ->dqi_ibh;
349 int status;
350
351 status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], bh, olq_update_info,
352 info);
353 if (status < 0) {
354 mlog_errno(status);
355 return -1;
356 }
357
358 return 0;
359}
360
361/* Release info from memory */
362static int ocfs2_local_free_info(struct super_block *sb, int type)
363{
364 struct mem_dqinfo *info = sb_dqinfo(sb, type);
365 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
366 struct ocfs2_quota_chunk *chunk;
367 struct ocfs2_local_disk_chunk *dchunk;
368 int mark_clean = 1, len;
369 int status;
370
371 iput(oinfo->dqi_gqinode);
372 ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
373 ocfs2_lock_res_free(&oinfo->dqi_gqlock);
374 list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
375 dchunk = (struct ocfs2_local_disk_chunk *)
376 (chunk->qc_headerbh->b_data);
377 if (chunk->qc_num < oinfo->dqi_chunks - 1) {
378 len = ol_chunk_entries(sb);
379 } else {
380 len = (oinfo->dqi_blocks -
381 ol_quota_chunk_block(sb, chunk->qc_num) - 1)
382 * ol_quota_entries_per_block(sb);
383 }
384 /* Not all entries free? Bug! */
385 if (le32_to_cpu(dchunk->dqc_free) != len) {
386 mlog(ML_ERROR, "releasing quota file with used "
387 "entries (type=%d)\n", type);
388 mark_clean = 0;
389 }
390 }
391 ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
392
393 if (!mark_clean)
394 goto out;
395
396 /* Mark local file as clean */
397 info->dqi_flags |= OLQF_CLEAN;
398 status = ocfs2_modify_bh(sb_dqopt(sb)->files[type],
399 oinfo->dqi_ibh,
400 olq_update_info,
401 info);
402 if (status < 0) {
403 mlog_errno(status);
404 goto out;
405 }
406
407out:
408 ocfs2_inode_unlock(sb_dqopt(sb)->files[type], 1);
409 brelse(oinfo->dqi_ibh);
410 brelse(oinfo->dqi_lqi_bh);
411 kfree(oinfo);
412 return 0;
413}
414
415static void olq_set_dquot(struct buffer_head *bh, void *private)
416{
417 struct ocfs2_dquot *od = private;
418 struct ocfs2_local_disk_dqblk *dqblk;
419 struct super_block *sb = od->dq_dquot.dq_sb;
420
421 dqblk = (struct ocfs2_local_disk_dqblk *)(bh->b_data
422 + ol_dqblk_block_offset(sb, od->dq_local_off));
423
424 dqblk->dqb_id = cpu_to_le64(od->dq_dquot.dq_id);
425 spin_lock(&dq_data_lock);
426 dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace -
427 od->dq_origspace);
428 dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes -
429 od->dq_originodes);
430 spin_unlock(&dq_data_lock);
431 mlog(0, "Writing local dquot %u space %lld inodes %lld\n",
432 od->dq_dquot.dq_id, dqblk->dqb_spacemod, dqblk->dqb_inodemod);
433}
434
435/* Write dquot to local quota file */
436static int ocfs2_local_write_dquot(struct dquot *dquot)
437{
438 struct super_block *sb = dquot->dq_sb;
439 struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
440 struct buffer_head *bh;
441 int status;
442
443 bh = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type],
444 ol_dqblk_file_block(sb, od->dq_local_off),
445 &status);
446 if (!bh) {
447 mlog_errno(status);
448 goto out;
449 }
450 status = ocfs2_modify_bh(sb_dqopt(sb)->files[dquot->dq_type], bh,
451 olq_set_dquot, od);
452 if (status < 0) {
453 mlog_errno(status);
454 goto out;
455 }
456out:
457 brelse(bh);
458 return status;
459}
460
461/* Find free entry in local quota file */
462static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb,
463 int type,
464 int *offset)
465{
466 struct mem_dqinfo *info = sb_dqinfo(sb, type);
467 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
468 struct ocfs2_quota_chunk *chunk;
469 struct ocfs2_local_disk_chunk *dchunk;
470 int found = 0, len;
471
472 list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
473 dchunk = (struct ocfs2_local_disk_chunk *)
474 chunk->qc_headerbh->b_data;
475 if (le32_to_cpu(dchunk->dqc_free) > 0) {
476 found = 1;
477 break;
478 }
479 }
480 if (!found)
481 return NULL;
482
483 if (chunk->qc_num < oinfo->dqi_chunks - 1) {
484 len = ol_chunk_entries(sb);
485 } else {
486 len = (oinfo->dqi_blocks -
487 ol_quota_chunk_block(sb, chunk->qc_num) - 1)
488 * ol_quota_entries_per_block(sb);
489 }
490
491 found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0);
492 /* We failed? */
493 if (found == len) {
494 mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u"
495 " entries free (type=%d)\n", chunk->qc_num,
496 le32_to_cpu(dchunk->dqc_free), type);
497 return ERR_PTR(-EIO);
498 }
499 *offset = found;
500 return chunk;
501}
502
503/* Add new chunk to the local quota file */
504static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
505 struct super_block *sb,
506 int type,
507 int *offset)
508{
509 struct mem_dqinfo *info = sb_dqinfo(sb, type);
510 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
511 struct inode *lqinode = sb_dqopt(sb)->files[type];
512 struct ocfs2_quota_chunk *chunk = NULL;
513 struct ocfs2_local_disk_chunk *dchunk;
514 int status;
515 handle_t *handle;
516 struct buffer_head *bh = NULL;
517 u64 p_blkno;
518
519 /* We are protected by dqio_sem so no locking needed */
520 status = ocfs2_extend_no_holes(lqinode,
521 lqinode->i_size + 2 * sb->s_blocksize,
522 lqinode->i_size);
523 if (status < 0) {
524 mlog_errno(status);
525 goto out;
526 }
527 status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
528 lqinode->i_size + 2 * sb->s_blocksize);
529 if (status < 0) {
530 mlog_errno(status);
531 goto out;
532 }
533
534 chunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
535 if (!chunk) {
536 status = -ENOMEM;
537 mlog_errno(status);
538 goto out;
539 }
540
541 down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
542 status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
543 &p_blkno, NULL, NULL);
544 up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
545 if (status < 0) {
546 mlog_errno(status);
547 goto out;
548 }
549 bh = sb_getblk(sb, p_blkno);
550 if (!bh) {
551 status = -ENOMEM;
552 mlog_errno(status);
553 goto out;
554 }
555 dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
556
557 handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
558 if (IS_ERR(handle)) {
559 status = PTR_ERR(handle);
560 mlog_errno(status);
561 goto out;
562 }
563
564 status = ocfs2_journal_access(handle, lqinode, bh,
565 OCFS2_JOURNAL_ACCESS_WRITE);
566 if (status < 0) {
567 mlog_errno(status);
568 goto out_trans;
569 }
570 lock_buffer(bh);
571 dchunk->dqc_free = ol_quota_entries_per_block(sb);
572 memset(dchunk->dqc_bitmap, 0,
573 sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
574 OCFS2_QBLK_RESERVED_SPACE);
575 set_buffer_uptodate(bh);
576 unlock_buffer(bh);
577 status = ocfs2_journal_dirty(handle, bh);
578 if (status < 0) {
579 mlog_errno(status);
580 goto out_trans;
581 }
582
583 oinfo->dqi_blocks += 2;
584 oinfo->dqi_chunks++;
585 status = ocfs2_local_write_info(sb, type);
586 if (status < 0) {
587 mlog_errno(status);
588 goto out_trans;
589 }
590 status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
591 if (status < 0) {
592 mlog_errno(status);
593 goto out;
594 }
595
596 list_add_tail(&chunk->qc_chunk, &oinfo->dqi_chunk);
597 chunk->qc_num = list_entry(chunk->qc_chunk.prev,
598 struct ocfs2_quota_chunk,
599 qc_chunk)->qc_num + 1;
600 chunk->qc_headerbh = bh;
601 *offset = 0;
602 return chunk;
603out_trans:
604 ocfs2_commit_trans(OCFS2_SB(sb), handle);
605out:
606 brelse(bh);
607 kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
608 return ERR_PTR(status);
609}
610
611/* Find free entry in local quota file */
612static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
613 struct super_block *sb,
614 int type,
615 int *offset)
616{
617 struct mem_dqinfo *info = sb_dqinfo(sb, type);
618 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
619 struct ocfs2_quota_chunk *chunk;
620 struct inode *lqinode = sb_dqopt(sb)->files[type];
621 struct ocfs2_local_disk_chunk *dchunk;
622 int epb = ol_quota_entries_per_block(sb);
623 unsigned int chunk_blocks;
624 int status;
625 handle_t *handle;
626
627 if (list_empty(&oinfo->dqi_chunk))
628 return ocfs2_local_quota_add_chunk(sb, type, offset);
629 /* Is the last chunk full? */
630 chunk = list_entry(oinfo->dqi_chunk.prev,
631 struct ocfs2_quota_chunk, qc_chunk);
632 chunk_blocks = oinfo->dqi_blocks -
633 ol_quota_chunk_block(sb, chunk->qc_num) - 1;
634 if (ol_chunk_blocks(sb) == chunk_blocks)
635 return ocfs2_local_quota_add_chunk(sb, type, offset);
636
637 /* We are protected by dqio_sem so no locking needed */
638 status = ocfs2_extend_no_holes(lqinode,
639 lqinode->i_size + sb->s_blocksize,
640 lqinode->i_size);
641 if (status < 0) {
642 mlog_errno(status);
643 goto out;
644 }
645 status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
646 lqinode->i_size + sb->s_blocksize);
647 if (status < 0) {
648 mlog_errno(status);
649 goto out;
650 }
651 handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
652 if (IS_ERR(handle)) {
653 status = PTR_ERR(handle);
654 mlog_errno(status);
655 goto out;
656 }
657 status = ocfs2_journal_access(handle, lqinode, chunk->qc_headerbh,
658 OCFS2_JOURNAL_ACCESS_WRITE);
659 if (status < 0) {
660 mlog_errno(status);
661 goto out_trans;
662 }
663
664 dchunk = (struct ocfs2_local_disk_chunk *)chunk->qc_headerbh->b_data;
665 lock_buffer(chunk->qc_headerbh);
666 le32_add_cpu(&dchunk->dqc_free, ol_quota_entries_per_block(sb));
667 unlock_buffer(chunk->qc_headerbh);
668 status = ocfs2_journal_dirty(handle, chunk->qc_headerbh);
669 if (status < 0) {
670 mlog_errno(status);
671 goto out_trans;
672 }
673 oinfo->dqi_blocks++;
674 status = ocfs2_local_write_info(sb, type);
675 if (status < 0) {
676 mlog_errno(status);
677 goto out_trans;
678 }
679
680 status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
681 if (status < 0) {
682 mlog_errno(status);
683 goto out;
684 }
685 *offset = chunk_blocks * epb;
686 return chunk;
687out_trans:
688 ocfs2_commit_trans(OCFS2_SB(sb), handle);
689out:
690 return ERR_PTR(status);
691}
692
693void olq_alloc_dquot(struct buffer_head *bh, void *private)
694{
695 int *offset = private;
696 struct ocfs2_local_disk_chunk *dchunk;
697
698 dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
699 ocfs2_set_bit(*offset, dchunk->dqc_bitmap);
700 le32_add_cpu(&dchunk->dqc_free, -1);
701}
702
703/* Create dquot in the local file for given id */
704static int ocfs2_create_local_dquot(struct dquot *dquot)
705{
706 struct super_block *sb = dquot->dq_sb;
707 int type = dquot->dq_type;
708 struct inode *lqinode = sb_dqopt(sb)->files[type];
709 struct ocfs2_quota_chunk *chunk;
710 struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
711 int offset;
712 int status;
713
714 chunk = ocfs2_find_free_entry(sb, type, &offset);
715 if (!chunk) {
716 chunk = ocfs2_extend_local_quota_file(sb, type, &offset);
717 if (IS_ERR(chunk))
718 return PTR_ERR(chunk);
719 } else if (IS_ERR(chunk)) {
720 return PTR_ERR(chunk);
721 }
722 od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset);
723 od->dq_chunk = chunk;
724
725 /* Initialize dquot structure on disk */
726 status = ocfs2_local_write_dquot(dquot);
727 if (status < 0) {
728 mlog_errno(status);
729 goto out;
730 }
731
732 /* Mark structure as allocated */
733 status = ocfs2_modify_bh(lqinode, chunk->qc_headerbh, olq_alloc_dquot,
734 &offset);
735 if (status < 0) {
736 mlog_errno(status);
737 goto out;
738 }
739out:
740 return status;
741}
742
743/* Create entry in local file for dquot, load data from the global file */
744static int ocfs2_local_read_dquot(struct dquot *dquot)
745{
746 int status;
747
748 mlog_entry("id=%u, type=%d\n", dquot->dq_id, dquot->dq_type);
749
750 status = ocfs2_global_read_dquot(dquot);
751 if (status < 0) {
752 mlog_errno(status);
753 goto out_err;
754 }
755
756 /* Now create entry in the local quota file */
757 status = ocfs2_create_local_dquot(dquot);
758 if (status < 0) {
759 mlog_errno(status);
760 goto out_err;
761 }
762 mlog_exit(0);
763 return 0;
764out_err:
765 mlog_exit(status);
766 return status;
767}
768
769/* Release dquot structure from local quota file. ocfs2_release_dquot() has
770 * already started a transaction and obtained exclusive lock for global
771 * quota file. */
772static int ocfs2_local_release_dquot(struct dquot *dquot)
773{
774 int status;
775 int type = dquot->dq_type;
776 struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
777 struct super_block *sb = dquot->dq_sb;
778 struct ocfs2_local_disk_chunk *dchunk;
779 int offset;
780 handle_t *handle = journal_current_handle();
781
782 BUG_ON(!handle);
783 /* First write all local changes to global file */
784 status = ocfs2_global_release_dquot(dquot);
785 if (status < 0) {
786 mlog_errno(status);
787 goto out;
788 }
789
790 status = ocfs2_journal_access(handle, sb_dqopt(sb)->files[type],
791 od->dq_chunk->qc_headerbh, OCFS2_JOURNAL_ACCESS_WRITE);
792 if (status < 0) {
793 mlog_errno(status);
794 goto out;
795 }
796 offset = ol_dqblk_chunk_off(sb, od->dq_chunk->qc_num,
797 od->dq_local_off);
798 dchunk = (struct ocfs2_local_disk_chunk *)
799 (od->dq_chunk->qc_headerbh->b_data);
800 /* Mark structure as freed */
801 lock_buffer(od->dq_chunk->qc_headerbh);
802 ocfs2_clear_bit(offset, dchunk->dqc_bitmap);
803 le32_add_cpu(&dchunk->dqc_free, 1);
804 unlock_buffer(od->dq_chunk->qc_headerbh);
805 status = ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
806 if (status < 0) {
807 mlog_errno(status);
808 goto out;
809 }
810 status = 0;
811out:
812 /* Clear the read bit so that next time someone uses this
813 * dquot he reads fresh info from disk and allocates local
814 * dquot structure */
815 clear_bit(DQ_READ_B, &dquot->dq_flags);
816 return status;
817}
818
819static struct quota_format_ops ocfs2_format_ops = {
820 .check_quota_file = ocfs2_local_check_quota_file,
821 .read_file_info = ocfs2_local_read_info,
822 .write_file_info = ocfs2_global_write_info,
823 .free_file_info = ocfs2_local_free_info,
824 .read_dqblk = ocfs2_local_read_dquot,
825 .commit_dqblk = ocfs2_local_write_dquot,
826 .release_dqblk = ocfs2_local_release_dquot,
827};
828
829struct quota_format_type ocfs2_quota_format = {
830 .qf_fmt_id = QFMT_OCFS2,
831 .qf_ops = &ocfs2_format_ops,
832 .qf_owner = THIS_MODULE
833};
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 41bb0197cf4c..7bb83e41581e 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -65,10 +65,13 @@
65#include "uptodate.h" 65#include "uptodate.h"
66#include "ver.h" 66#include "ver.h"
67#include "xattr.h" 67#include "xattr.h"
68#include "quota.h"
68 69
69#include "buffer_head_io.h" 70#include "buffer_head_io.h"
70 71
71static struct kmem_cache *ocfs2_inode_cachep = NULL; 72static struct kmem_cache *ocfs2_inode_cachep = NULL;
73struct kmem_cache *ocfs2_dquot_cachep;
74struct kmem_cache *ocfs2_qf_chunk_cachep;
72 75
73/* OCFS2 needs to schedule several differnt types of work which 76/* OCFS2 needs to schedule several differnt types of work which
74 * require cluster locking, disk I/O, recovery waits, etc. Since these 77 * require cluster locking, disk I/O, recovery waits, etc. Since these
@@ -137,6 +140,8 @@ static const struct super_operations ocfs2_sops = {
137 .put_super = ocfs2_put_super, 140 .put_super = ocfs2_put_super,
138 .remount_fs = ocfs2_remount, 141 .remount_fs = ocfs2_remount,
139 .show_options = ocfs2_show_options, 142 .show_options = ocfs2_show_options,
143 .quota_read = ocfs2_quota_read,
144 .quota_write = ocfs2_quota_write,
140}; 145};
141 146
142enum { 147enum {
@@ -1104,6 +1109,7 @@ static int __init ocfs2_init(void)
1104 1109
1105 ocfs2_set_locking_protocol(); 1110 ocfs2_set_locking_protocol();
1106 1111
1112 status = register_quota_format(&ocfs2_quota_format);
1107leave: 1113leave:
1108 if (status < 0) { 1114 if (status < 0) {
1109 ocfs2_free_mem_caches(); 1115 ocfs2_free_mem_caches();
@@ -1127,6 +1133,8 @@ static void __exit ocfs2_exit(void)
1127 destroy_workqueue(ocfs2_wq); 1133 destroy_workqueue(ocfs2_wq);
1128 } 1134 }
1129 1135
1136 unregister_quota_format(&ocfs2_quota_format);
1137
1130 debugfs_remove(ocfs2_debugfs_root); 1138 debugfs_remove(ocfs2_debugfs_root);
1131 1139
1132 ocfs2_free_mem_caches(); 1140 ocfs2_free_mem_caches();
@@ -1242,8 +1250,27 @@ static int ocfs2_initialize_mem_caches(void)
1242 (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 1250 (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
1243 SLAB_MEM_SPREAD), 1251 SLAB_MEM_SPREAD),
1244 ocfs2_inode_init_once); 1252 ocfs2_inode_init_once);
1245 if (!ocfs2_inode_cachep) 1253 ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
1254 sizeof(struct ocfs2_dquot),
1255 0,
1256 (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
1257 SLAB_MEM_SPREAD),
1258 NULL);
1259 ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
1260 sizeof(struct ocfs2_quota_chunk),
1261 0,
1262 (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
1263 NULL);
1264 if (!ocfs2_inode_cachep || !ocfs2_dquot_cachep ||
1265 !ocfs2_qf_chunk_cachep) {
1266 if (ocfs2_inode_cachep)
1267 kmem_cache_destroy(ocfs2_inode_cachep);
1268 if (ocfs2_dquot_cachep)
1269 kmem_cache_destroy(ocfs2_dquot_cachep);
1270 if (ocfs2_qf_chunk_cachep)
1271 kmem_cache_destroy(ocfs2_qf_chunk_cachep);
1246 return -ENOMEM; 1272 return -ENOMEM;
1273 }
1247 1274
1248 return 0; 1275 return 0;
1249} 1276}
@@ -1252,8 +1279,15 @@ static void ocfs2_free_mem_caches(void)
1252{ 1279{
1253 if (ocfs2_inode_cachep) 1280 if (ocfs2_inode_cachep)
1254 kmem_cache_destroy(ocfs2_inode_cachep); 1281 kmem_cache_destroy(ocfs2_inode_cachep);
1255
1256 ocfs2_inode_cachep = NULL; 1282 ocfs2_inode_cachep = NULL;
1283
1284 if (ocfs2_dquot_cachep)
1285 kmem_cache_destroy(ocfs2_dquot_cachep);
1286 ocfs2_dquot_cachep = NULL;
1287
1288 if (ocfs2_qf_chunk_cachep)
1289 kmem_cache_destroy(ocfs2_qf_chunk_cachep);
1290 ocfs2_qf_chunk_cachep = NULL;
1257} 1291}
1258 1292
1259static int ocfs2_get_sector(struct super_block *sb, 1293static int ocfs2_get_sector(struct super_block *sb,