4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 021110-1307, USA
24 * Copyright (c) 2012 Whamcloud, Inc.
25 * Use is subject to license terms.
31 #ifndef _LQUOTA_INTERNAL_H
32 #define _LQUOTA_INTERNAL_H
34 #define QTYPE_NAME(qtype) ((qtype) == USRQUOTA ? "usr" : "grp")
35 #define RES_NAME(res) ((res) == LQUOTA_RES_MD ? "md" : "dt")
37 #define QIF_IFLAGS (QIF_INODES | QIF_ITIME | QIF_ILIMITS)
38 #define QIF_BFLAGS (QIF_SPACE | QIF_BTIME | QIF_BLIMITS)
40 /* The biggest filename are the one used for slave index which are in the form
41 * of 0x%x-%s,glb_fid.f_oid,slv_uuid, that's to say:
42 * 2(0x) + 8(f_oid) + 1(-) + 40(UUID_MAX) which means 51 chars + '\0' */
43 #define LQUOTA_NAME_MAX 52
45 /* reserved OID in FID_SEQ_QUOTA for local objects */
46 enum lquota_local_oid {
47 LQUOTA_USR_OID = 1UL, /* slave index copy for user quota */
48 LQUOTA_GRP_OID = 2UL, /* slave index copy for group quota */
49 /* all OIDs after this are allocated dynamically by the QMT */
50 LQUOTA_GENERATED_OID = 4096UL,
54 * lquota_entry support
57 /* Common operations supported by a lquota_entry */
58 struct lquota_entry_operations {
59 /* Initialize specific fields of a lquota entry */
60 void (*lqe_init)(struct lquota_entry *, void *arg);
62 /* Read quota settings from disk and update lquota entry */
63 int (*lqe_read)(const struct lu_env *, struct lquota_entry *,
66 /* Print debug information about a given lquota entry */
67 void (*lqe_debug)(struct lquota_entry *, void *,
68 struct libcfs_debug_msg_data *, const char *,
72 /* Per-ID information specific to the quota master target */
73 struct lquota_mst_entry {
74 /* global hard limit, in inodes or kbytes */
77 /* global quota soft limit, in inodes or kbytes */
80 /* grace time, in seconds */
83 /* last time we glimpsed */
84 __u64 lme_revoke_time;
86 /* r/w semaphore used to protect concurrent access to the quota
87 * parameters which are stored on disk */
88 cfs_rw_semaphore_t lme_sem;
90 /* quota space that may be released after glimpse */
94 /* Per-ID information specific to the quota slave */
95 struct lquota_slv_entry {
96 /* [ib]tune size, inodes or kbytes */
99 /* per-ID lock handle */
100 struct lustre_handle lse_lockh;
102 /* pending write which were granted quota space but haven't completed
103 * yet, in inodes or kbytes. */
104 __u64 lse_pending_write;
106 /* writes waiting for quota space, in inodes or kbytes. */
107 __u64 lse_waiting_write;
109 /* pending release, in inodes or kbytes */
110 __u64 lse_pending_rel;
112 /* pending dqacq/dqrel requests. */
113 unsigned int lse_pending_req;
115 /* rw spinlock protecting in-memory counters (i.e. lse_pending*) */
116 cfs_rwlock_t lse_lock;
118 /* waiter for pending request done */
119 cfs_waitq_t lse_waiters;
121 /* hint on current on-disk usage, in inodes or kbytes */
124 /* time to trigger quota adjust */
125 __u64 lse_adjust_time;
128 /* In-memory entry for each enforced quota id
129 * A lquota_entry structure belong to a single lquota_site */
130 struct lquota_entry {
131 /* link to site hash table */
132 cfs_hlist_node_t lqe_hash;
134 /* quota identifier associated with this entry */
135 union lquota_id lqe_id;
137 /* site this quota entry belongs to */
138 struct lquota_site *lqe_site;
140 /* reference counter */
141 cfs_atomic_t lqe_ref;
143 /* linked to list of lqes which:
144 * - need quota space adjustment on slave
145 * - need glimpse to be sent on master */
148 /* current quota settings/usage of this ID */
149 __u64 lqe_granted; /* granted limit, inodes or kbytes */
150 __u64 lqe_qunit; /* [ib]unit size, inodes or kbytes */
152 struct lquota_mst_entry me; /* params specific to QMT */
153 struct lquota_slv_entry se; /* params specific to QSD */
156 /* flags describing the state of the lquota_entry */
157 unsigned long lqe_enforced:1,/* quota enforced or not */
158 lqe_uptodate:1,/* successfully read from disk */
159 lqe_edquot:1, /* id out of quota space on QMT */
160 lqe_gl:1, /* glimpse is in progress */
161 lqe_nopreacq:1;/* pre-acquire disabled */
164 /* Compartment within which lquota_entry are unique.
165 * lquota_entry structures are kept in a hash table and read from disk if not
168 /* Hash table storing lquota_entry structures */
169 cfs_hash_t *lqs_hash;
171 /* Quota type, either user or group. */
174 /* Record whether this site is for a QMT or a slave */
177 /* Vector of operations which can be done on lquota entry belonging to
179 struct lquota_entry_operations *lqs_ops;
181 /* Backpointer to parent structure, either QMT pool info for master or
186 #define lqe_hardlimit u.me.lme_hardlimit
187 #define lqe_softlimit u.me.lme_softlimit
188 #define lqe_gracetime u.me.lme_gracetime
189 #define lqe_revoke_time u.me.lme_revoke_time
190 #define lqe_sem u.me.lme_sem
191 #define lqe_may_rel u.me.lme_may_rel
193 #define lqe_qtune u.se.lse_qtune
194 #define lqe_pending_write u.se.lse_pending_write
195 #define lqe_waiting_write u.se.lse_waiting_write
196 #define lqe_pending_rel u.se.lse_pending_rel
197 #define lqe_pending_req u.se.lse_pending_req
198 #define lqe_waiters u.se.lse_waiters
199 #define lqe_lock u.se.lse_lock
200 #define lqe_usage u.se.lse_usage
201 #define lqe_adjust_time u.se.lse_adjust_time
202 #define lqe_lockh u.se.lse_lockh
204 #define LQUOTA_BUMP_VER 0x1
205 #define LQUOTA_SET_VER 0x2
207 /* helper routine to get/put reference on lquota_entry */
208 static inline void lqe_getref(struct lquota_entry *lqe)
210 cfs_atomic_inc(&lqe->lqe_ref);
213 static inline void lqe_putref(struct lquota_entry *lqe)
215 LASSERT(atomic_read(&lqe->lqe_ref) > 0);
216 if (atomic_dec_and_test(&lqe->lqe_ref))
220 static inline int lqe_is_master(struct lquota_entry *lqe)
222 return lqe->lqe_site->lqs_is_mst;
225 /* lqe locking helpers */
226 static inline void lqe_write_lock(struct lquota_entry *lqe)
228 if (lqe_is_master(lqe))
229 cfs_down_write(&lqe->lqe_sem);
231 cfs_write_lock(&lqe->lqe_lock);
234 static inline void lqe_write_unlock(struct lquota_entry *lqe)
236 if (lqe_is_master(lqe))
237 cfs_up_write(&lqe->lqe_sem);
239 cfs_write_unlock(&lqe->lqe_lock);
242 static inline void lqe_read_lock(struct lquota_entry *lqe)
244 if (lqe_is_master(lqe))
245 cfs_down_read(&lqe->lqe_sem);
247 cfs_read_lock(&lqe->lqe_lock);
250 static inline void lqe_read_unlock(struct lquota_entry *lqe)
252 if (lqe_is_master(lqe))
253 cfs_up_read(&lqe->lqe_sem);
255 cfs_read_unlock(&lqe->lqe_lock);
259 * Helper functions & prototypes
262 /* minimum qunit size, 1K inode for metadata pool and 1MB for data pool */
263 #define LQUOTA_LEAST_QUNIT(type) \
264 (type == LQUOTA_RES_MD ? (1 << 10) : toqb(PTLRPC_MAX_BRW_SIZE))
266 /* Common data shared by quota-level handlers. This is allocated per-thread to
267 * reduce stack consumption */
268 struct lquota_thread_info {
269 union lquota_rec qti_rec;
270 struct lu_buf qti_lb;
271 struct lu_attr qti_attr;
272 struct dt_object_format qti_dof;
273 struct lustre_mdt_attrs qti_lma;
274 struct lu_fid qti_fid;
275 char qti_buf[LQUOTA_NAME_MAX];
278 #define qti_glb_rec qti_rec.lqr_glb_rec
279 #define qti_acct_rec qti_rec.lqr_acct_rec
280 #define qti_slv_rec qti_rec.lqr_slv_rec
282 #define LQUOTA_BUMP_VER 0x1
283 #define LQUOTA_SET_VER 0x2
285 extern struct lu_context_key lquota_thread_key;
287 /* extract lquota_threa_info context from environment */
289 struct lquota_thread_info *lquota_info(const struct lu_env *env)
291 struct lquota_thread_info *info;
293 info = lu_context_key_get(&env->le_ctx, &lquota_thread_key);
295 lu_env_refill((struct lu_env *)env);
296 info = lu_context_key_get(&env->le_ctx, &lquota_thread_key);
302 /* debugging macros */
304 #define lquota_lqe_debug(msgdata, mask, cdls, lqe, fmt, a...) do { \
305 CFS_CHECK_STACK(msgdata, mask, cdls); \
307 if (((mask) & D_CANTMASK) != 0 || \
308 ((libcfs_debug & (mask)) != 0 && \
309 (libcfs_subsystem_debug & DEBUG_SUBSYSTEM) != 0)) \
310 lquota_lqe_debug0(lqe, msgdata, fmt, ##a); \
313 void lquota_lqe_debug0(struct lquota_entry *lqe,
314 struct libcfs_debug_msg_data *data, const char *fmt, ...)
315 __attribute__ ((format (printf, 3, 4)));
317 #define LQUOTA_DEBUG_LIMIT(mask, lqe, fmt, a...) do { \
318 static cfs_debug_limit_state_t _lquota_cdls; \
319 LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_lquota_cdls); \
320 lquota_lqe_debug(&msgdata, mask, &_lquota_cdls, lqe, "$$$ "fmt" ", \
324 #define LQUOTA_ERROR(lqe, fmt, a...) LQUOTA_DEBUG_LIMIT(D_ERROR, lqe, fmt, ## a)
325 #define LQUOTA_WARN(lqe, fmt, a...) \
326 LQUOTA_DEBUG_LIMIT(D_WARNING, lqe, fmt, ## a)
327 #define LQUOTA_CONSOLE(lqe, fmt, a...) \
328 LQUOTA_DEBUG_LIMIT(D_CONSOLE, lqe, fmt, ## a)
330 #define LQUOTA_DEBUG(lock, fmt, a...) do { \
331 LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_QUOTA, NULL); \
332 lquota_lqe_debug(&msgdata, D_QUOTA, NULL, lqe, "$$$ "fmt" ", ##a); \
334 #else /* !LIBCFS_DEBUG */
335 # define LQUOTA_DEBUG(lqe, fmt, a...) ((void)0)
336 # define LQUOTA_ERROR(lqe, fmt, a...) ((void)0)
337 # define LQUOTA_WARN(lqe, fmt, a...) ((void)0)
338 # define LQUOTA_CONSOLE(lqe, fmt, a...) ((void)0)
339 # define lquota_lqe_debug(cdls, level, lqe, file, func, line, fmt, a...) \
344 struct dt_object *acct_obj_lookup(const struct lu_env *, struct dt_device *,
346 void lquota_generate_fid(struct lu_fid *, int, int, int);
347 int lquota_extract_fid(const struct lu_fid *, int *, int *, int *);
348 const struct dt_index_features *glb_idx_feature(struct lu_fid *);
349 extern cfs_mem_cache_t *lqe_kmem;
352 /* site create/destroy */
353 struct lquota_site *lquota_site_alloc(const struct lu_env *, void *, bool,
354 short, struct lquota_entry_operations *);
355 void lquota_site_free(const struct lu_env *, struct lquota_site *);
356 /* quota entry operations */
357 struct lquota_entry *lqe_locate(const struct lu_env *, struct lquota_site *,
361 struct dt_object *lquota_disk_dir_find_create(const struct lu_env *,
363 struct dt_object *, const char *);
364 struct dt_object *lquota_disk_glb_find_create(const struct lu_env *,
367 struct lu_fid *, bool);
368 struct dt_object *lquota_disk_slv_find_create(const struct lu_env *,
372 struct obd_uuid *, bool);
373 typedef int (*lquota_disk_slv_cb_t) (const struct lu_env *, struct lu_fid *,
374 char *, struct lu_fid *, void *);
375 int lquota_disk_for_each_slv(const struct lu_env *, struct dt_object *,
376 struct lu_fid *, lquota_disk_slv_cb_t, void *);
377 struct dt_object *lquota_disk_slv_find(const struct lu_env *,
378 struct dt_device *, struct dt_object *,
379 struct lu_fid *, struct obd_uuid *);
380 int lquota_disk_read(const struct lu_env *, struct dt_object *,
381 union lquota_id *, struct dt_rec *);
382 int lquota_disk_declare_write(const struct lu_env *, struct thandle *,
383 struct dt_object *, union lquota_id *);
384 int lquota_disk_write(const struct lu_env *, struct thandle *,
385 struct dt_object *, union lquota_id *, struct dt_rec *,
387 int lquota_disk_update_ver(const struct lu_env *, struct dt_device *,
388 struct dt_object *, __u64);
391 int qmt_glb_init(void);
392 void qmt_glb_fini(void);
395 extern struct file_operations lprocfs_quota_seq_fops;
398 int qsd_glb_init(void);
399 void qsd_glb_fini(void);
400 #endif /* _LQUOTA_INTERNAL_H */