Whamcloud - gitweb
LU-1842 quota: qsd request
[fs/lustre-release.git] / lustre / quota / lquota_internal.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2012 Whamcloud, Inc.
25  * Use is subject to license terms.
26  */
27
28 #include <obd.h>
29 #include <lquota.h>
30
31 #ifndef _LQUOTA_INTERNAL_H
32 #define _LQUOTA_INTERNAL_H
33
34 #define QTYPE_NAME(qtype) ((qtype) == USRQUOTA ? "usr" : "grp")
35
36 #define QIF_IFLAGS (QIF_INODES | QIF_ITIME | QIF_ILIMITS)
37 #define QIF_BFLAGS (QIF_SPACE | QIF_BTIME | QIF_BLIMITS)
38
39 /* The biggest filename are the one used for slave index which are in the form
40  * of 0x%x-%s,glb_fid.f_oid,slv_uuid, that's to say:
41  * 2(0x) + 8(f_oid) + 1(-) + 40(UUID_MAX) which means 51 chars + '\0' */
42 #define LQUOTA_NAME_MAX 52
43
44 /* reserved OID in FID_SEQ_QUOTA for local objects */
45 enum lquota_local_oid {
46         LQUOTA_USR_OID          = 1UL, /* slave index copy for user quota */
47         LQUOTA_GRP_OID          = 2UL, /* slave index copy for group quota */
48         /* all OIDs after this are allocated dynamically by the QMT */
49         LQUOTA_GENERATED_OID    = 4096UL,
50 };
51
52 /*
53  * lquota_entry support
54  */
55
56 /* Common operations supported by a lquota_entry */
57 struct lquota_entry_operations {
58         /* Initialize specific fields of a lquota entry */
59         void (*lqe_init)(struct lquota_entry *, void *arg);
60
61         /* Read quota settings from disk and update lquota entry */
62         int (*lqe_read)(const struct lu_env *, struct lquota_entry *,
63                         void *arg);
64
65         /* Print debug information about a given lquota entry */
66         void (*lqe_debug)(struct lquota_entry *, void *,
67                           struct libcfs_debug_msg_data *, const char *,
68                           va_list);
69 };
70
71 /* Per-ID information specific to the quota master target */
72 struct lquota_mst_entry {
73         /* global hard limit, in inodes or kbytes */
74         __u64                   lme_hardlimit;
75
76         /* global quota soft limit, in inodes or kbytes */
77         __u64                   lme_softlimit;
78
79         /* grace time, in seconds */
80         __u64                   lme_gracetime;
81
82         /* last time we glimpsed */
83         __u64                   lme_revoke_time;
84
85         /* r/w semaphore used to protect concurrent access to the quota
86          * parameters which are stored on disk */
87         cfs_rw_semaphore_t      lme_sem;
88
89         /* quota space that may be released after glimpse */
90         __u64                   lme_may_rel;
91 };
92
93 /* Per-ID information specific to the quota slave */
94 struct lquota_slv_entry {
95         /* [ib]tune size, inodes or kbytes */
96         __u64                   lse_qtune;
97
98         /* per-ID lock handle */
99         struct lustre_handle    lse_lockh;
100
101         /* pending write which were granted quota space but haven't completed
102          * yet, in inodes or kbytes. */
103         __u64                   lse_pending_write;
104
105         /* writes waiting for quota space, in inodes or kbytes. */
106         __u64                   lse_waiting_write;
107
108         /* pending release, in inodes or kbytes */
109         __u64                   lse_pending_rel;
110
111         /* pending dqacq/dqrel requests. */
112         unsigned int            lse_pending_req;
113
114         /* rw spinlock protecting in-memory counters (i.e. lse_pending*) */
115         cfs_rwlock_t            lse_lock;
116
117         /* waiter for pending request done */
118         cfs_waitq_t             lse_waiters;
119
120         /* hint on current on-disk usage, in inodes or kbytes */
121         __u64                   lse_usage;
122
123         /* time to trigger quota adjust */
124         __u64                   lse_adjust_time;
125 };
126
127 /* In-memory entry for each enforced quota id
128  * A lquota_entry structure belong to a single lquota_site */
129 struct lquota_entry {
130         /* link to site hash table */
131         cfs_hlist_node_t         lqe_hash;
132
133         /* quota identifier associated with this entry */
134         union lquota_id          lqe_id;
135
136         /* site this quota entry belongs to */
137         struct lquota_site      *lqe_site;
138
139         /* reference counter */
140         cfs_atomic_t             lqe_ref;
141
142         /* linked to list of lqes which:
143          * - need quota space adjustment on slave
144          * - need glimpse to be sent on master */
145         cfs_list_t               lqe_link;
146
147         /* current quota settings/usage of this ID */
148         __u64           lqe_granted; /* granted limit, inodes or kbytes */
149         __u64           lqe_qunit; /* [ib]unit size, inodes or kbytes */
150         union {
151                 struct  lquota_mst_entry me; /* params specific to QMT */
152                 struct  lquota_slv_entry se; /* params specific to QSD */
153         } u;
154
155         /* flags describing the state of the lquota_entry */
156         unsigned long   lqe_enforced:1,/* quota enforced or not */
157                         lqe_uptodate:1,/* successfully read from disk */
158                         lqe_edquot:1,  /* id out of quota space on QMT */
159                         lqe_gl:1,      /* glimpse is in progress */
160                         lqe_nopreacq:1;/* pre-acquire disabled */
161 };
162
163 /* Compartment within which lquota_entry are unique.
164  * lquota_entry structures are kept in a hash table and read from disk if not
165  * present.  */
166 struct lquota_site {
167         /* Hash table storing lquota_entry structures */
168         cfs_hash_t      *lqs_hash;
169
170         /* Quota type, either user or group. */
171         int              lqs_qtype;
172
173         /* Record whether this site is for a QMT or a slave */
174         int              lqs_is_mst;
175
176         /* Vector of operations which can be done on lquota entry belonging to
177          * this quota site */
178         struct lquota_entry_operations  *lqs_ops;
179
180         /* Backpointer to parent structure, either QMT pool info for master or
181          * QSD for slave */
182         void            *lqs_parent;
183 };
184
185 #define lqe_hardlimit           u.me.lme_hardlimit
186 #define lqe_softlimit           u.me.lme_softlimit
187 #define lqe_gracetime           u.me.lme_gracetime
188 #define lqe_revoke_time         u.me.lme_revoke_time
189 #define lqe_sem                 u.me.lme_sem
190 #define lqe_may_rel             u.me.lme_may_rel
191
192 #define lqe_qtune               u.se.lse_qtune
193 #define lqe_pending_write       u.se.lse_pending_write
194 #define lqe_waiting_write       u.se.lse_waiting_write
195 #define lqe_pending_rel         u.se.lse_pending_rel
196 #define lqe_pending_req         u.se.lse_pending_req
197 #define lqe_waiters             u.se.lse_waiters
198 #define lqe_lock                u.se.lse_lock
199 #define lqe_usage               u.se.lse_usage
200 #define lqe_adjust_time         u.se.lse_adjust_time
201 #define lqe_lockh               u.se.lse_lockh
202
203 #define LQUOTA_BUMP_VER 0x1
204 #define LQUOTA_SET_VER  0x2
205
206 /* helper routine to get/put reference on lquota_entry */
207 static inline void lqe_getref(struct lquota_entry *lqe)
208 {
209         cfs_atomic_inc(&lqe->lqe_ref);
210 }
211
212 static inline void lqe_putref(struct lquota_entry *lqe)
213 {
214         LASSERT(atomic_read(&lqe->lqe_ref) > 0);
215         if (atomic_dec_and_test(&lqe->lqe_ref))
216                 OBD_FREE_PTR(lqe);
217 }
218
219 static inline int lqe_is_master(struct lquota_entry *lqe)
220 {
221         return lqe->lqe_site->lqs_is_mst;
222 }
223
224 /* lqe locking helpers */
225 static inline void lqe_write_lock(struct lquota_entry *lqe)
226 {
227         if (lqe_is_master(lqe))
228                 cfs_down_write(&lqe->lqe_sem);
229         else
230                 cfs_write_lock(&lqe->lqe_lock);
231 }
232
233 static inline void lqe_write_unlock(struct lquota_entry *lqe)
234 {
235         if (lqe_is_master(lqe))
236                 cfs_up_write(&lqe->lqe_sem);
237         else
238                 cfs_write_unlock(&lqe->lqe_lock);
239 }
240
241 static inline void lqe_read_lock(struct lquota_entry *lqe)
242 {
243         if (lqe_is_master(lqe))
244                 cfs_down_read(&lqe->lqe_sem);
245         else
246                 cfs_read_lock(&lqe->lqe_lock);
247 }
248
249 static inline void lqe_read_unlock(struct lquota_entry *lqe)
250 {
251         if (lqe_is_master(lqe))
252                 cfs_up_read(&lqe->lqe_sem);
253         else
254                 cfs_read_unlock(&lqe->lqe_lock);
255 }
256
257 /* Common data shared by quota-level handlers. This is allocated per-thread to
258  * reduce stack consumption */
259 struct lquota_thread_info {
260         union  lquota_rec       qti_rec;
261         struct lu_buf           qti_lb;
262         struct lu_attr          qti_attr;
263         struct dt_object_format qti_dof;
264         struct lustre_mdt_attrs qti_lma;
265         struct lu_fid           qti_fid;
266         char                    qti_buf[LQUOTA_NAME_MAX];
267 };
268
269 #define qti_glb_rec     qti_rec.lqr_glb_rec
270 #define qti_acct_rec    qti_rec.lqr_acct_rec
271 #define qti_slv_rec     qti_rec.lqr_slv_rec
272
273 #define LQUOTA_BUMP_VER 0x1
274 #define LQUOTA_SET_VER  0x2
275
276 extern struct lu_context_key lquota_thread_key;
277
278 /* extract lquota_threa_info context from environment */
279 static inline
280 struct lquota_thread_info *lquota_info(const struct lu_env *env)
281 {
282         struct lquota_thread_info       *info;
283
284         info = lu_context_key_get(&env->le_ctx, &lquota_thread_key);
285         if (info == NULL) {
286                 lu_env_refill((struct lu_env *)env);
287                 info = lu_context_key_get(&env->le_ctx, &lquota_thread_key);
288         }
289         LASSERT(info);
290         return info;
291 }
292
293 /* debugging macros */
294 #ifdef LIBCFS_DEBUG
295 #define lquota_lqe_debug(msgdata, mask, cdls, lqe, fmt, a...) do {      \
296         CFS_CHECK_STACK(msgdata, mask, cdls);                           \
297                                                                         \
298         if (((mask) & D_CANTMASK) != 0 ||                               \
299             ((libcfs_debug & (mask)) != 0 &&                            \
300              (libcfs_subsystem_debug & DEBUG_SUBSYSTEM) != 0))          \
301                 lquota_lqe_debug0(lqe, msgdata, fmt, ##a);              \
302 } while(0)
303
304 void lquota_lqe_debug0(struct lquota_entry *lqe,
305                        struct libcfs_debug_msg_data *data, const char *fmt, ...)
306         __attribute__ ((format (printf, 3, 4)));
307
308 #define LQUOTA_DEBUG_LIMIT(mask, lqe, fmt, a...) do {                          \
309         static cfs_debug_limit_state_t _lquota_cdls;                           \
310         LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_lquota_cdls);              \
311         lquota_lqe_debug(&msgdata, mask, &_lquota_cdls, lqe, "$$$ "fmt" ",     \
312                          ##a);                                                 \
313 } while (0)
314
315 #define LQUOTA_ERROR(lqe, fmt, a...) LQUOTA_DEBUG_LIMIT(D_ERROR, lqe, fmt, ## a)
316 #define LQUOTA_WARN(lqe, fmt, a...) \
317         LQUOTA_DEBUG_LIMIT(D_WARNING, lqe, fmt, ## a)
318 #define LQUOTA_CONSOLE(lqe, fmt, a...) \
319         LQUOTA_DEBUG_LIMIT(D_CONSOLE, lqe, fmt, ## a)
320
321 #define LQUOTA_DEBUG(lock, fmt, a...) do {                                 \
322         LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_QUOTA, NULL);                \
323         lquota_lqe_debug(&msgdata, D_QUOTA, NULL, lqe, "$$$ "fmt" ", ##a); \
324 } while (0)
325 #else /* !LIBCFS_DEBUG */
326 # define LQUOTA_DEBUG(lqe, fmt, a...) ((void)0)
327 # define LQUOTA_ERROR(lqe, fmt, a...) ((void)0)
328 # define LQUOTA_WARN(lqe, fmt, a...) ((void)0)
329 # define LQUOTA_CONSOLE(lqe, fmt, a...) ((void)0)
330 # define lquota_lqe_debug(cdls, level, lqe, file, func, line, fmt, a...) \
331                 ((void)0)
332 #endif
333
334 /* lquota_lib.c */
335 struct dt_object *acct_obj_lookup(const struct lu_env *, struct dt_device *,
336                                   int);
337 void lquota_generate_fid(struct lu_fid *, int, int, int);
338 int lquota_extract_fid(struct lu_fid *, int *, int *, int *);
339 const struct dt_index_features *glb_idx_feature(struct lu_fid *);
340
341 /* lquota_entry.c */
342 /* site create/destroy */
343 struct lquota_site *lquota_site_alloc(const struct lu_env *, void *, bool,
344                                       short, struct lquota_entry_operations *);
345 void lquota_site_free(const struct lu_env *, struct lquota_site *);
346 /* quota entry operations */
347 struct lquota_entry *lqe_locate(const struct lu_env *, struct lquota_site *,
348                                 union lquota_id *);
349
350 /* lquota_disk.c */
351 struct dt_object *lquota_disk_dir_find_create(const struct lu_env *,
352                                               struct dt_device *,
353                                               struct dt_object *, const char *);
354 struct dt_object *lquota_disk_glb_find_create(const struct lu_env *,
355                                               struct dt_device *,
356                                               struct dt_object *,
357                                               struct lu_fid *, bool);
358 struct dt_object *lquota_disk_slv_find_create(const struct lu_env *,
359                                               struct dt_device *,
360                                               struct dt_object *,
361                                               struct lu_fid *,
362                                               struct obd_uuid *, bool);
363 typedef int (*lquota_disk_slv_cb_t) (const struct lu_env *, struct lu_fid *,
364                                      char *, struct lu_fid *, void *);
365 int lquota_disk_for_each_slv(const struct lu_env *, struct dt_object *,
366                              struct lu_fid *, lquota_disk_slv_cb_t, void *);
367 struct dt_object *lquota_disk_slv_find(const struct lu_env *,
368                                        struct dt_device *, struct dt_object *,
369                                        struct lu_fid *, struct obd_uuid *);
370 int lquota_disk_read(const struct lu_env *, struct dt_object *,
371                      union lquota_id *, struct dt_rec *);
372 int lquota_disk_declare_write(const struct lu_env *, struct thandle *,
373                               struct dt_object *, union lquota_id *);
374 int lquota_disk_write(const struct lu_env *, struct thandle *,
375                       struct dt_object *, union lquota_id *, struct dt_rec *,
376                       __u32, __u64 *);
377 int lquota_disk_update_ver(const struct lu_env *, struct dt_device *,
378                            struct dt_object *, __u64);
379
380 /* lproc_quota.c */
381 extern struct file_operations lprocfs_quota_seq_fops;
382
383 /* qsd_lib.c */
384 int qsd_glb_init(void);
385 void qsd_glb_fini(void);
386 #endif /* _LQUOTA_INTERNAL_H */