summaryrefslogtreecommitdiff
path: root/include/linux/quota.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/quota.h')
-rw-r--r--include/linux/quota.h65
1 files changed, 32 insertions, 33 deletions
diff --git a/include/linux/quota.h b/include/linux/quota.h
index bfd077ca6ac3..89a0d83ddad0 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -91,7 +91,7 @@ extern bool qid_valid(struct kqid qid);
*
* When there is no mapping defined for the user-namespace, type,
* qid tuple an invalid kqid is returned. Callers are expected to
- * test for and handle handle invalid kqids being returned.
+ * test for and handle invalid kqids being returned.
* Invalid kqids may be tested for using qid_valid().
*/
static inline struct kqid make_kqid(struct user_namespace *from,
@@ -223,12 +223,12 @@ struct mem_dqinfo {
struct quota_format_type *dqi_format;
int dqi_fmt_id; /* Id of the dqi_format - used when turning
* quotas on after remount RW */
- struct list_head dqi_dirty_list; /* List of dirty dquots */
- unsigned long dqi_flags;
- unsigned int dqi_bgrace;
- unsigned int dqi_igrace;
- qsize_t dqi_max_spc_limit;
- qsize_t dqi_max_ino_limit;
+ struct list_head dqi_dirty_list; /* List of dirty dquots [dq_list_lock] */
+ unsigned long dqi_flags; /* DFQ_ flags [dq_data_lock] */
+ unsigned int dqi_bgrace; /* Space grace time [dq_data_lock] */
+ unsigned int dqi_igrace; /* Inode grace time [dq_data_lock] */
+ qsize_t dqi_max_spc_limit; /* Maximum space limit [static] */
+ qsize_t dqi_max_ino_limit; /* Maximum inode limit [static] */
void *dqi_priv;
};
@@ -263,11 +263,10 @@ enum {
};
struct dqstats {
- int stat[_DQST_DQSTAT_LAST];
+ unsigned long stat[_DQST_DQSTAT_LAST];
struct percpu_counter counter[_DQST_DQSTAT_LAST];
};
-extern struct dqstats *dqstats_pcpu;
extern struct dqstats dqstats;
static inline void dqstats_inc(unsigned int type)
@@ -286,25 +285,27 @@ static inline void dqstats_dec(unsigned int type)
#define DQ_FAKE_B 3 /* no limits only usage */
#define DQ_READ_B 4 /* dquot was read into memory */
#define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */
-#define DQ_LASTSET_B 6 /* Following 6 bits (see QIF_) are reserved\
+#define DQ_RELEASING_B 6 /* dquot is in releasing_dquots list waiting
+ * to be cleaned up */
+#define DQ_LASTSET_B 7 /* Following 6 bits (see QIF_) are reserved\
* for the mask of entries set via SETQUOTA\
* quotactl. They are set under dq_data_lock\
* and the quota format handling dquot can\
* clear them when it sees fit. */
struct dquot {
- struct hlist_node dq_hash; /* Hash list in memory */
- struct list_head dq_inuse; /* List of all quotas */
- struct list_head dq_free; /* Free list element */
- struct list_head dq_dirty; /* List of dirty dquots */
+ struct hlist_node dq_hash; /* Hash list in memory [dq_list_lock] */
+ struct list_head dq_inuse; /* List of all quotas [dq_list_lock] */
+ struct list_head dq_free; /* Free list element [dq_list_lock] */
+ struct list_head dq_dirty; /* List of dirty dquots [dq_list_lock] */
struct mutex dq_lock; /* dquot IO lock */
+ spinlock_t dq_dqb_lock; /* Lock protecting dq_dqb changes */
atomic_t dq_count; /* Use count */
- wait_queue_head_t dq_wait_unused; /* Wait queue for dquot to become unused */
struct super_block *dq_sb; /* superblock this applies to */
struct kqid dq_id; /* ID this applies to (uid, gid, projid) */
- loff_t dq_off; /* Offset of dquot on disk */
+ loff_t dq_off; /* Offset of dquot on disk [dq_lock, stable once set] */
unsigned long dq_flags; /* See DQ_* */
- struct mem_dqblk dq_dqb; /* Diskquota usage */
+ struct mem_dqblk dq_dqb; /* Diskquota usage [dq_dqb_lock] */
};
/* Operations which must be implemented by each quota format */
@@ -409,13 +410,7 @@ struct qc_type_state {
struct qc_state {
unsigned int s_incoredqs; /* Number of dquots in core */
- /*
- * Per quota type information. The array should really have
- * max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in
- * quota_getinfo() makes sure XQM_MAXQUOTAS is large enough. Once VFS
- * supports project quotas, this can be changed to MAXQUOTAS
- */
- struct qc_type_state s_state[XQM_MAXQUOTAS];
+ struct qc_type_state s_state[MAXQUOTAS]; /* Per quota type information */
};
/* Structure for communicating via ->set_info */
@@ -455,17 +450,18 @@ struct quota_format_type {
};
/**
- * Quota state flags - they actually come in two flavors - for users and groups.
+ * Quota state flags - they come in three flavors - for users, groups and projects.
*
* Actual typed flags layout:
- * USRQUOTA GRPQUOTA
- * DQUOT_USAGE_ENABLED 0x0001 0x0002
- * DQUOT_LIMITS_ENABLED 0x0004 0x0008
- * DQUOT_SUSPENDED 0x0010 0x0020
+ * USRQUOTA GRPQUOTA PRJQUOTA
+ * DQUOT_USAGE_ENABLED 0x0001 0x0002 0x0004
+ * DQUOT_LIMITS_ENABLED 0x0008 0x0010 0x0020
+ * DQUOT_SUSPENDED 0x0040 0x0080 0x0100
*
* Following bits are used for non-typed flags:
- * DQUOT_QUOTA_SYS_FILE 0x0040
- * DQUOT_NEGATIVE_USAGE 0x0080
+ * DQUOT_QUOTA_SYS_FILE 0x0200
+ * DQUOT_NEGATIVE_USAGE 0x0400
+ * DQUOT_NOLIST_DIRTY 0x0800
*/
enum {
_DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
@@ -491,6 +487,9 @@ enum {
*/
#define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1))
/* Allow negative quota usage */
+/* Do not track dirty dquots in a list */
+#define DQUOT_NOLIST_DIRTY (1 << (DQUOT_STATE_LAST + 2))
+
static inline unsigned int dquot_state_flag(unsigned int flags, int type)
{
return flags << type;
@@ -521,13 +520,13 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev,
struct quota_info {
unsigned int flags; /* Flags for diskquotas on this device */
- struct mutex dqio_mutex; /* lock device while I/O in progress */
+ struct rw_semaphore dqio_sem; /* Lock quota file while I/O in progress */
struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
};
-int register_quota_format(struct quota_format_type *fmt);
+void register_quota_format(struct quota_format_type *fmt);
void unregister_quota_format(struct quota_format_type *fmt);
struct quota_module_name {