aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,