Whamcloud - gitweb
Land b_smallfix onto HEAD (20040512_1806)
[fs/lustre-release.git] / lustre / include / linux / lustre_log.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * Generic infrastructure for managing a collection of logs.
22  *
23  * These logs are used for:
24  *
25  * - orphan recovery: OST adds record on create
26  * - mtime/size consistency: the OST adds a record on first write
27  * - open/unlinked objects: OST adds a record on destroy
28  *
29  * - mds unlink log: the MDS adds an entry upon delete
30  *
31  * - raid1 replication log between OST's
32  * - MDS replication logs
33  */
34
35 #ifndef _LUSTRE_LOG_H
36 #define _LUSTRE_LOG_H
37
38 #include <linux/obd.h>
39 #include <linux/lustre_idl.h>
40
41 #define LOG_NAME_LIMIT(logname, name)                   \
42         snprintf(logname, sizeof(logname), "LOGS/%s", name)
43 #define LLOG_EEMPTY 4711
44
45 struct plain_handle_data {
46         struct list_head    phd_entry;
47         struct llog_handle *phd_cat_handle;
48         struct llog_cookie  phd_cookie; /* cookie of this log in its cat */
49         int                 phd_last_idx;
50 };
51
52 struct cat_handle_data {
53         struct list_head        chd_head;
54         struct llog_handle     *chd_current_log; /* currently open log */
55 };
56
57 /* In-memory descriptor for a log object or log catalog */
58 struct llog_handle {
59         struct rw_semaphore     lgh_lock;
60         struct llog_logid       lgh_id;              /* id of this log */
61         struct llog_log_hdr    *lgh_hdr;
62         struct file            *lgh_file;
63         int                     lgh_last_idx;
64         struct llog_ctxt       *lgh_ctxt;
65         union {
66                 struct plain_handle_data phd;
67                 struct cat_handle_data   chd;
68         } u;
69 };
70
71 /* got from mds_update_record.
72  * FIXME: maybe some attribute in reint_record and update_record will be
73  * changed later. */
74 /* XXX BUG 3188 -- must return to one set of structures. */
75 /* XXX use fixed-sized fields (__u32) instead of dev_t and iattr->gid_t, etc */
76
77 struct update_record {
78         __u32 ur_opcode;
79         __u32 ur_fsuid;
80         __u32 ur_fsgid;
81         dev_t ur_rdev;
82         struct iattr ur_iattr;
83         struct iattr ur_pattr;
84         __u32 ur_flags;
85         __u32 ur_len;
86 };
87
88 struct reint_record {
89        struct update_record u_rec;
90        char *rec_data1;
91        int rec1_size;
92        char *rec_data2;
93        int rec2_size;
94 };
95
96 struct llog_smfs_rec {
97         struct llog_rec_hdr     lsr_hdr;
98         struct update_record    lsr_rec;
99         struct llog_rec_tail    lsr_tail;
100 };
101
102 /* llog.c  -  general API */
103 typedef int (*llog_cb_t)(struct llog_handle *, struct llog_rec_hdr *, void *);
104 struct llog_handle *llog_alloc_handle(void);
105 void llog_free_handle(struct llog_handle *handle);
106 int llog_cancel_rec(struct llog_handle *loghandle, int index);
107 int llog_init_handle(struct llog_handle *handle, int flags,
108                      struct obd_uuid *uuid);
109 int llog_close(struct llog_handle *cathandle);
110 int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
111                  void *data, void *catdata);
112 int llog_reverse_process(struct llog_handle *loghandle, llog_cb_t cb,
113                          void *data, void *catdata);
114
115 /* llog_cat.c   -  catalog api */
116 struct llog_process_data {
117         void *lpd_data;
118         llog_cb_t lpd_cb;
119 };
120
121 struct llog_process_cat_data {
122         int     first_idx;
123         int     last_idx;
124         /* to process catalog across zero record */
125 };
126
127 int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
128                        struct llog_logid *logid);
129 int llog_cat_put(struct llog_handle *cathandle);
130 int llog_cat_add_rec(struct llog_handle *cathandle, struct llog_rec_hdr *rec,
131                      struct llog_cookie *reccookie, void *buf);
132 int llog_cat_cancel_records(struct llog_handle *cathandle, int count,
133                             struct llog_cookie *cookies);
134 int llog_cat_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data);
135 int llog_cat_reverse_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data);
136 int llog_cat_set_first_idx(struct llog_handle *cathandle, int index);
137
138 int llog_catalog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
139                      void *buf, struct llog_cookie *reccookie, int, void *data);
140 int llog_catalog_cancel(struct llog_ctxt *ctxt, int count, struct llog_cookie *,
141                         int flags, void *data);
142 int llog_catalog_setup(struct llog_ctxt **res, char *name, struct lvfs_run_ctxt *,
143                        struct fsfilt_operations *fsops, struct dentry *logs_de,
144                        struct dentry *objects_de);
145 int llog_catalog_cleanup(struct llog_ctxt *ctxt);
146 int llog_cat_half_bottom(struct llog_cookie *, struct llog_handle *);
147
148 /* llog_lvfs.c */
149 int llog_get_cat_list(struct lvfs_run_ctxt *, struct fsfilt_operations *,
150                       char *name, int count, struct llog_catid *idarray);
151 int llog_put_cat_list(struct lvfs_run_ctxt *, struct fsfilt_operations *, 
152                       char *name, int count, struct llog_catid *idarray);
153 extern struct llog_operations llog_lvfs_ops;
154
155 /* llog_obd.c - obd llog api */
156 int obd_llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
157                    int count,  struct llog_logid *logid,struct llog_operations *op);
158 int obd_llog_cleanup(struct llog_ctxt *);
159 int llog_obd_origin_setup(struct obd_device *obd, int index,
160                           struct obd_device *disk_obd, int count,
161                           struct llog_logid *logid);
162 int obd_llog_cat_initialize(struct obd_device *obd, int count, char *name);
163 int obd_llog_init(struct obd_device *obd, struct obd_device *disk_obd,
164                   int count, struct llog_catid *logid);
165
166 int obd_llog_finish(struct obd_device *obd, int count);
167
168 /* llog_ioctl.c */
169 int llog_ioctl(struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data);
170 int llog_catalog_list(struct obd_device *obd, int count,
171                      struct obd_ioctl_data *data);
172
173 /* llog_net.c */
174 int llog_initiator_connect(struct llog_ctxt *ctxt);
175 int llog_receptor_accept(struct llog_ctxt *ctxt, struct obd_import *imp);
176 int llog_origin_connect(struct llog_ctxt *ctxt, int count,
177                         struct llog_logid *logid, struct llog_gen *gen,
178                         struct obd_uuid *uuid);
179 int llog_handle_connect(struct ptlrpc_request *req);
180
181 /* recov_thread.c */
182 int llog_obd_repl_cancel(struct llog_ctxt *ctxt, int count,
183                          struct llog_cookie *cookies, int flags, void *data);
184                          
185 int llog_obd_repl_sync(struct llog_ctxt *ctxt, struct obd_export *exp);
186 int llog_repl_connect(struct llog_ctxt *ctxt, int count,
187                       struct llog_logid *logid, struct llog_gen *gen,
188                       struct obd_uuid *uuid);
189
190 struct llog_operations {
191         int (*lop_setup)(struct obd_device *obd, int ctxt_idx,
192                          struct obd_device *disk_obd, int count,
193                          struct llog_logid *logid);
194         int (*lop_cleanup)(struct llog_ctxt *ctxt);
195         int (*lop_create)(struct llog_ctxt *ctxt, struct llog_handle **,
196                           struct llog_logid *logid, char *name);
197         int (*lop_destroy)(struct llog_handle *handle);
198         int (*lop_close)(struct llog_handle *handle);
199
200         int (*lop_read_header)(struct llog_handle *handle);
201         int (*lop_add)(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
202                        void *buf, struct llog_cookie *logcookies,
203                        int numcookies, void *data);
204         int (*lop_cancel)(struct llog_ctxt *ctxt, int count,
205                           struct llog_cookie *cookies, int flags, void *data);
206         int (*lop_write_rec)(struct llog_handle *loghandle,
207                              struct llog_rec_hdr *rec,
208                              struct llog_cookie *logcookies, int numcookies,
209                              void *, int idx);
210         int (*lop_next_block)(struct llog_handle *h, int *curr_idx,
211                               int next_idx, __u64 *offset, void *buf, int len);
212         int (*lop_prev_block)(struct llog_handle *h,
213                               int prev_idx, void *buf, int len);
214
215         /* XXX add 2 more: commit callbacks and llog recovery functions */
216         int (*lop_sync)(struct llog_ctxt *ctxt, struct obd_export *exp);
217         int (*lop_connect)(struct llog_ctxt *ctxt, int count,
218                            struct llog_logid *logid, struct llog_gen *gen,
219                            struct obd_uuid *uuid);
220 };
221
222 struct llog_ctxt {
223         /* needed for lvfs based log */
224         struct llog_handle      *loc_handle;
225         struct llog_operations  *loc_logops;
226         struct fsfilt_operations *loc_fsops;
227         struct dentry           *loc_logs_dir;
228         struct dentry           *loc_objects_dir;
229         struct lvfs_run_ctxt    *loc_lvfs_ctxt;
230
231         struct obd_device       *loc_obd; /* points back to the containing obd*/
232         struct llog_gen          loc_gen;
233         int                      loc_idx; /* my index the obd array of ctxt's */
234
235         struct obd_export       *loc_exp;
236         struct obd_import       *loc_imp; /* to use in RPC's: can be backward
237                                              pointing import */
238         struct llog_canceld_ctxt *loc_llcd;
239         struct semaphore         loc_sem; /* protects loc_llcd */
240         void                    *loc_proc_cb; /* cb for recovery */
241 };
242
243 static inline void llog_gen_init(struct llog_ctxt *ctxt)
244 {
245         struct obd_device *obd = ctxt->loc_exp->exp_obd;
246
247         if (!strcmp(obd->obd_type->typ_name, "mds"))
248                 ctxt->loc_gen.mnt_cnt = obd->u.mds.mds_mount_count;
249         else if (!strstr(obd->obd_type->typ_name, "filter"))
250                 ctxt->loc_gen.mnt_cnt = obd->u.filter.fo_mount_count;
251         else
252                 ctxt->loc_gen.mnt_cnt = 0;
253 }
254
255 static inline int llog_gen_lt(struct llog_gen a, struct llog_gen b)
256 {
257         if (a.mnt_cnt < b.mnt_cnt)
258                 return 1;
259         if (a.mnt_cnt > b.mnt_cnt)
260                 return 0;
261         return(a.conn_cnt < b.conn_cnt ? 1 : 0);
262 }
263
264 #define LLOG_GEN_INC(gen)  ((gen).conn_cnt) ++
265 #define LLOG_PROC_BREAK 0x0001
266
267 static inline int llog_ctxt2ops(struct llog_ctxt *ctxt,
268                                struct llog_operations **lop)
269 {
270         if (ctxt == NULL)
271                 return -ENOTCONN;
272
273         *lop = ctxt->loc_logops;
274         if (*lop == NULL)
275                 return -EOPNOTSUPP;
276
277         return 0;
278 }
279
280 static inline int llog_handle2ops(struct llog_handle *loghandle,
281                                   struct llog_operations **lop)
282 {
283         if (loghandle == NULL)
284                 return -EINVAL;
285
286         return llog_ctxt2ops(loghandle->lgh_ctxt, lop);
287 }
288
289 static inline int llog_data_len(int len)
290 {
291         return size_round(len);
292 }
293
294 static inline struct llog_ctxt *llog_get_context(struct obd_device *obd,
295                                                  int index)
296 {
297         if (index < 0 || index >= LLOG_MAX_CTXTS)
298                 return NULL;
299
300         return obd->obd_llog_ctxt[index];
301 }
302
303 static inline int llog_create(struct llog_ctxt *ctxt, struct llog_handle **res,
304                               struct llog_logid *logid, char *name)
305 {
306         struct llog_operations *lop;
307         int rc;
308         ENTRY;
309
310         rc = llog_ctxt2ops(ctxt, &lop);
311         if (rc)
312                 RETURN(rc);
313         if (lop->lop_create == NULL)
314                 RETURN(-EOPNOTSUPP);
315
316         rc = lop->lop_create(ctxt, res, logid, name);
317         RETURN(rc);
318 }
319
320 static inline int llog_destroy(struct llog_handle *handle)
321 {
322         struct llog_operations *lop;
323         int rc;
324         ENTRY;
325
326         rc = llog_handle2ops(handle, &lop);
327         if (rc)
328                 RETURN(rc);
329         if (lop->lop_destroy == NULL)
330                 RETURN(-EOPNOTSUPP);
331
332         rc = lop->lop_destroy(handle);
333         RETURN(rc);
334 }
335
336 static inline int llog_read_header(struct llog_handle *handle)
337 {
338         struct llog_operations *lop;
339         int rc;
340         ENTRY;
341
342         rc = llog_handle2ops(handle, &lop);
343         if (rc)
344                 RETURN(rc);
345         if (lop->lop_read_header == NULL)
346                 RETURN(-EOPNOTSUPP);
347
348         rc = lop->lop_read_header(handle);
349         RETURN(rc);
350 }
351
352 static inline int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
353                            void *buf, struct llog_cookie *logcookies,
354                            int numcookies, void *data)
355 {
356         struct llog_operations *lop;
357         int rc;
358         ENTRY;
359
360         rc = llog_ctxt2ops(ctxt, &lop);
361         if (rc)
362                 RETURN(rc);
363         if (lop->lop_add == NULL)
364                 RETURN(-EOPNOTSUPP);
365
366         rc = lop->lop_add(ctxt, rec, buf, logcookies, numcookies, data);
367         RETURN(rc);
368 }
369
370 static inline int llog_cancel(struct llog_ctxt *ctxt, int count,
371                               struct llog_cookie *cookies, int flags, void *data)
372 {
373         struct llog_operations *lop;
374         int rc;
375         ENTRY;
376
377         rc = llog_ctxt2ops(ctxt, &lop);
378         if (rc)
379                 RETURN(rc);
380         if (lop->lop_cancel == NULL)
381                 RETURN(-EOPNOTSUPP);
382
383         rc = lop->lop_cancel(ctxt, count, cookies, flags, data);
384         RETURN(rc);
385 }
386
387 static inline int llog_write_rec(struct llog_handle *handle,
388                                  struct llog_rec_hdr *rec,
389                                  struct llog_cookie *logcookies,
390                                  int numcookies, void *buf, int idx)
391 {
392         struct llog_operations *lop;
393         int rc, buflen;
394         ENTRY;
395
396         rc = llog_handle2ops(handle, &lop);
397         if (rc)
398                 RETURN(rc);
399         if (lop->lop_write_rec == NULL)
400                 RETURN(-EOPNOTSUPP);
401
402         if (buf)
403                 buflen = le32_to_cpu(rec->lrh_len) + sizeof(struct llog_rec_hdr)
404                                 + sizeof(struct llog_rec_tail);
405         else
406                 buflen = le32_to_cpu(rec->lrh_len);
407         LASSERT(size_round(buflen) == buflen);
408
409         rc = lop->lop_write_rec(handle, rec, logcookies, numcookies, buf, idx);
410         RETURN(rc);
411 }
412
413 static inline int llog_next_block(struct llog_handle *loghandle, int *curr_idx,
414                                   int next_idx, __u64 *curr_offset, void *buf,
415                                   int len)
416 {
417         struct llog_operations *lop;
418         int rc;
419         ENTRY;
420
421         rc = llog_handle2ops(loghandle, &lop);
422         if (rc)
423                 RETURN(rc);
424         if (lop->lop_next_block == NULL)
425                 RETURN(-EOPNOTSUPP);
426
427         rc = lop->lop_next_block(loghandle, curr_idx, next_idx, curr_offset, buf,
428                                  len);
429         RETURN(rc);
430 }
431
432 static inline int llog_prev_block(struct llog_handle *loghandle,
433                                   int prev_idx, void *buf, int len)
434 {
435         struct llog_operations *lop;
436         int rc;
437         ENTRY;
438
439         rc = llog_handle2ops(loghandle, &lop);
440         if (rc)
441                 RETURN(rc);
442         if (lop->lop_prev_block == NULL)
443                 RETURN(-EOPNOTSUPP);
444
445         rc = lop->lop_prev_block(loghandle, prev_idx, buf, len);
446         RETURN(rc);
447 }
448
449 static inline int llog_connect(struct llog_ctxt *ctxt, int count,
450                                struct llog_logid *logid, struct llog_gen *gen,
451                                struct obd_uuid *uuid)
452 {
453         struct llog_operations *lop;
454         int rc;
455         ENTRY;
456
457         rc = llog_ctxt2ops(ctxt, &lop);
458         if (rc)
459                 RETURN(rc);
460         if (lop->lop_connect == NULL)
461                 RETURN(-EOPNOTSUPP);
462
463         rc = lop->lop_connect(ctxt, count, logid, gen, uuid);
464         RETURN(rc);
465 }
466
467 static inline int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp)
468 {
469         struct llog_operations *lop;
470         int rc;
471         ENTRY;
472
473         rc = llog_ctxt2ops(ctxt, &lop);
474         if (rc)
475                 RETURN(rc);
476         if (lop->lop_sync == NULL)
477                 RETURN(-EOPNOTSUPP);
478
479         rc = lop->lop_sync(ctxt, exp);
480         RETURN(rc);
481 }
482
483 #endif