summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/quota.h71
-rw-r--r--include/linux/quotaops.h55
2 files changed, 49 insertions, 77 deletions
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 02bf7c53a6d4..e5b1e2187156 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -37,6 +37,7 @@
#include <linux/errno.h>
#include <linux/types.h>
+#include <linux/spinlock.h>
#define __DQUOT_VERSION__ "dquot_6.5.1"
#define __DQUOT_NUM_VERSION__ 6*10000+5*100+1
@@ -44,6 +45,9 @@
typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
typedef __u64 qsize_t; /* Type in which we store sizes */
+extern spinlock_t dq_list_lock;
+extern spinlock_t dq_data_lock;
+
/* Size of blocks in which are counted size limits */
#define QUOTABLOCK_BITS 10
#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
@@ -155,7 +159,7 @@ struct quota_format_type;
struct mem_dqinfo {
struct quota_format_type *dqi_format;
- int dqi_flags;
+ unsigned long dqi_flags;
unsigned int dqi_bgrace;
unsigned int dqi_igrace;
union {
@@ -165,18 +169,19 @@ struct mem_dqinfo {
};
#define DQF_MASK 0xffff /* Mask for format specific flags */
-#define DQF_INFO_DIRTY 0x10000 /* Is info dirty? */
-#define DQF_ANY_DQUOT_DIRTY 0x20000 /* Is any dquot dirty? */
+#define DQF_INFO_DIRTY_B 16
+#define DQF_ANY_DQUOT_DIRTY_B 17
+#define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
+#define DQF_ANY_DQUOT_DIRTY (1 << DQF_ANY_DQUOT_DIRTY B) /* Is any dquot dirty? */
extern inline void mark_info_dirty(struct mem_dqinfo *info)
{
- info->dqi_flags |= DQF_INFO_DIRTY;
+ set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
}
-#define info_dirty(info) ((info)->dqi_flags & DQF_INFO_DIRTY)
-
-#define info_any_dirty(info) ((info)->dqi_flags & DQF_INFO_DIRTY ||\
- (info)->dqi_flags & DQF_ANY_DQUOT_DIRTY)
+#define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
+#define info_any_dquot_dirty(info) test_bit(DQF_ANY_DQUOT_DIRTY_B, &(info)->dqi_flags)
+#define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
#define sb_dqopt(sb) (&(sb)->s_dquot)
@@ -195,30 +200,29 @@ extern struct dqstats dqstats;
#define NR_DQHASH 43 /* Just an arbitrary number */
-#define DQ_LOCKED 0x01 /* dquot under IO */
-#define DQ_MOD 0x02 /* dquot modified since read */
-#define DQ_BLKS 0x10 /* uid/gid has been warned about blk limit */
-#define DQ_INODES 0x20 /* uid/gid has been warned about inode limit */
-#define DQ_FAKE 0x40 /* no limits only usage */
-#define DQ_INVAL 0x80 /* dquot is going to be invalidated */
+#define DQ_MOD_B 0
+#define DQ_BLKS_B 1
+#define DQ_INODES_B 2
+#define DQ_FAKE_B 3
+
+#define DQ_MOD (1 << DQ_MOD_B) /* dquot modified since read */
+#define DQ_BLKS (1 << DQ_BLKS_B) /* uid/gid has been warned about blk limit */
+#define DQ_INODES (1 << DQ_INODES_B) /* uid/gid has been warned about inode limit */
+#define DQ_FAKE (1 << DQ_FAKE_B) /* no limits only usage */
struct dquot {
struct list_head dq_hash; /* Hash list in memory */
struct list_head dq_inuse; /* List of all quotas */
struct list_head dq_free; /* Free list element */
- wait_queue_head_t dq_wait_lock; /* Pointer to waitqueue on dquot lock */
- wait_queue_head_t dq_wait_free; /* Pointer to waitqueue for quota to be unused */
- int dq_count; /* Use count */
- int dq_dup_ref; /* Number of duplicated refences */
+ struct semaphore dq_lock; /* dquot IO lock */
+ atomic_t dq_count; /* Use count */
/* fields after this point are cleared when invalidating */
struct super_block *dq_sb; /* superblock this applies to */
unsigned int dq_id; /* ID this applies to (uid, gid) */
loff_t dq_off; /* Offset of dquot on disk */
+ unsigned long dq_flags; /* See DQ_* */
short dq_type; /* Type of quota */
- short dq_flags; /* See DQ_* */
- unsigned long dq_referenced; /* Number of times this dquot was
- referenced during its lifetime */
struct mem_dqblk dq_dqb; /* Diskquota usage */
};
@@ -276,7 +280,7 @@ struct quota_format_type {
struct quota_info {
unsigned int flags; /* Flags for diskquotas on this device */
struct semaphore dqio_sem; /* lock device while I/O in progress */
- struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */
+ struct rw_semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device and ops using quota_info struct, pointers from inode to dquots */
struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
@@ -284,26 +288,17 @@ struct quota_info {
/* Inline would be better but we need to dereference super_block which is not defined yet */
#define mark_dquot_dirty(dquot) do {\
- dquot->dq_flags |= DQ_MOD;\
- sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_flags |= DQF_ANY_DQUOT_DIRTY;\
+ set_bit(DQF_ANY_DQUOT_DIRTY_B, &(sb_dqopt((dquot)->dq_sb)->info[(dquot)->dq_type].dqi_flags));\
+ set_bit(DQ_MOD_B, &(dquot)->dq_flags);\
} while (0)
-#define dquot_dirty(dquot) ((dquot)->dq_flags & DQ_MOD)
-
-static inline int is_enabled(struct quota_info *dqopt, int type)
-{
- switch (type) {
- case USRQUOTA:
- return dqopt->flags & DQUOT_USR_ENABLED;
- case GRPQUOTA:
- return dqopt->flags & DQUOT_GRP_ENABLED;
- }
- return 0;
-}
+#define dquot_dirty(dquot) test_bit(DQ_MOD_B, &(dquot)->dq_flags)
-#define sb_any_quota_enabled(sb) (is_enabled(sb_dqopt(sb), USRQUOTA) | is_enabled(sb_dqopt(sb), GRPQUOTA))
+#define sb_has_quota_enabled(sb, type) ((type)==USRQUOTA ? \
+ (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) : (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED))
-#define sb_has_quota_enabled(sb, type) (is_enabled(sb_dqopt(sb), type))
+#define sb_any_quota_enabled(sb) (sb_has_quota_enabled(sb, USRQUOTA) | \
+ sb_has_quota_enabled(sb, GRPQUOTA))
int register_quota_format(struct quota_format_type *fmt);
void unregister_quota_format(struct quota_format_type *fmt);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 31b24e37c159..e1c502012025 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -46,36 +46,31 @@ static __inline__ void DQUOT_INIT(struct inode *inode)
{
if (!inode->i_sb)
BUG();
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
inode->i_sb->dq_op->initialize(inode, -1);
- unlock_kernel();
}
static __inline__ void DQUOT_DROP(struct inode *inode)
{
- lock_kernel();
if (IS_QUOTAINIT(inode)) {
if (!inode->i_sb)
BUG();
inode->i_sb->dq_op->drop(inode); /* Ops must be set when there's any quota... */
}
- unlock_kernel();
}
static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb)) {
/* Used space is updated in alloc_space() */
- if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA) {
- unlock_kernel();
+ if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
return 1;
- }
}
- else
+ else {
+ spin_lock(&dq_data_lock);
inode_add_bytes(inode, nr);
- unlock_kernel();
+ spin_unlock(&dq_data_lock);
+ }
return 0;
}
@@ -89,17 +84,16 @@ static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb)) {
/* Used space is updated in alloc_space() */
- if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA) {
- unlock_kernel();
+ if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
return 1;
- }
}
- else
+ else {
+ spin_lock(&dq_data_lock);
inode_add_bytes(inode, nr);
- unlock_kernel();
+ spin_unlock(&dq_data_lock);
+ }
return 0;
}
@@ -113,26 +107,23 @@ static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb)) {
DQUOT_INIT(inode);
- if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
- unlock_kernel();
+ if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
return 1;
- }
}
- unlock_kernel();
return 0;
}
static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb))
inode->i_sb->dq_op->free_space(inode, nr);
- else
+ else {
+ spin_lock(&dq_data_lock);
inode_sub_bytes(inode, nr);
- unlock_kernel();
+ spin_unlock(&dq_data_lock);
+ }
}
static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
@@ -143,23 +134,17 @@ static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
static __inline__ void DQUOT_FREE_INODE(struct inode *inode)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb))
inode->i_sb->dq_op->free_inode(inode, 1);
- unlock_kernel();
}
static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
{
- lock_kernel();
if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
DQUOT_INIT(inode);
- if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) {
- unlock_kernel();
+ if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
return 1;
- }
}
- unlock_kernel();
return 0;
}
@@ -169,10 +154,8 @@ static __inline__ int DQUOT_OFF(struct super_block *sb)
{
int ret = -ENOSYS;
- lock_kernel();
if (sb->s_qcop && sb->s_qcop->quota_off)
ret = sb->s_qcop->quota_off(sb, -1);
- unlock_kernel();
return ret;
}
@@ -192,9 +175,7 @@ static __inline__ int DQUOT_OFF(struct super_block *sb)
#define DQUOT_TRANSFER(inode, iattr) (0)
extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
inode_add_bytes(inode, nr);
- unlock_kernel();
return 0;
}
@@ -207,9 +188,7 @@ extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
inode_add_bytes(inode, nr);
- unlock_kernel();
return 0;
}
@@ -222,9 +201,7 @@ extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
- lock_kernel();
inode_sub_bytes(inode, nr);
- unlock_kernel();
}
extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)