Whamcloud - gitweb
LU-8054 lfsck: enhance lfsck notify API
[fs/lustre-release.git] / lustre / include / lustre / lustre_ostid.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, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2014, Intel Corporation.
27  *
28  * Copyright 2015 Cray Inc, all rights reserved.
29  * Author: Ben Evans.
30  *
31  * Define ost_id  associated functions
32  */
33
34 #ifndef _LUSTRE_OSTID_H_
35 #define _LUSTRE_OSTID_H_
36
37 #include <libcfs/libcfs.h>
38 #include <lustre/lustre_fid.h>
39
40 static inline __u64 lmm_oi_id(const struct ost_id *oi)
41 {
42         return oi->oi.oi_id;
43 }
44
45 static inline __u64 lmm_oi_seq(const struct ost_id *oi)
46 {
47         return oi->oi.oi_seq;
48 }
49
50 static inline void lmm_oi_set_seq(struct ost_id *oi, __u64 seq)
51 {
52         oi->oi.oi_seq = seq;
53 }
54
55 static inline void lmm_oi_set_id(struct ost_id *oi, __u64 oid)
56 {
57         oi->oi.oi_id = oid;
58 }
59
60 static inline void lmm_oi_le_to_cpu(struct ost_id *dst_oi,
61                                     const struct ost_id *src_oi)
62 {
63         dst_oi->oi.oi_id = __le64_to_cpu(src_oi->oi.oi_id);
64         dst_oi->oi.oi_seq = __le64_to_cpu(src_oi->oi.oi_seq);
65 }
66
67 static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi,
68                                     const struct ost_id *src_oi)
69 {
70         dst_oi->oi.oi_id = __cpu_to_le64(src_oi->oi.oi_id);
71         dst_oi->oi.oi_seq = __cpu_to_le64(src_oi->oi.oi_seq);
72 }
73
74 /* extract OST sequence (group) from a wire ost_id (id/seq) pair */
75 static inline __u64 ostid_seq(const struct ost_id *ostid)
76 {
77         if (fid_seq_is_mdt0(ostid->oi.oi_seq))
78                 return FID_SEQ_OST_MDT0;
79
80         if (fid_seq_is_default(ostid->oi.oi_seq))
81                 return FID_SEQ_LOV_DEFAULT;
82
83         if (fid_is_idif(&ostid->oi_fid))
84                 return FID_SEQ_OST_MDT0;
85
86         return fid_seq(&ostid->oi_fid);
87 }
88
89 /* extract OST objid from a wire ost_id (id/seq) pair */
90 static inline __u64 ostid_id(const struct ost_id *ostid)
91 {
92         if (fid_seq_is_mdt0(ostid->oi.oi_seq))
93                 return ostid->oi.oi_id & IDIF_OID_MASK;
94
95         if (fid_seq_is_default(ostid->oi.oi_seq))
96                 return ostid->oi.oi_id;
97
98         if (fid_is_idif(&ostid->oi_fid))
99                 return fid_idif_id(fid_seq(&ostid->oi_fid),
100                                    fid_oid(&ostid->oi_fid), 0);
101
102         return fid_oid(&ostid->oi_fid);
103 }
104
105 static inline void ostid_set_seq(struct ost_id *oi, __u64 seq)
106 {
107         if (fid_seq_is_mdt0(seq) || fid_seq_is_default(seq)) {
108                 oi->oi.oi_seq = seq;
109         } else {
110                 oi->oi_fid.f_seq = seq;
111                 /*
112                  * Note: if f_oid + f_ver is zero, we need init it
113                  * to be 1, otherwise, ostid_seq will treat this
114                  * as old ostid (oi_seq == 0)
115                  */
116                 if (!oi->oi_fid.f_oid && !oi->oi_fid.f_ver)
117                         oi->oi_fid.f_oid = LUSTRE_FID_INIT_OID;
118         }
119 }
120
121 static inline void ostid_set_seq_mdt0(struct ost_id *oi)
122 {
123         ostid_set_seq(oi, FID_SEQ_OST_MDT0);
124 }
125
126 static inline void ostid_set_seq_echo(struct ost_id *oi)
127 {
128         ostid_set_seq(oi, FID_SEQ_ECHO);
129 }
130
131 static inline void ostid_set_seq_llog(struct ost_id *oi)
132 {
133         ostid_set_seq(oi, FID_SEQ_LLOG);
134 }
135
136 /**
137  * Note: we need check oi_seq to decide where to set oi_id,
138  * so oi_seq should always be set ahead of oi_id.
139  */
140 static inline void ostid_set_id(struct ost_id *oi, __u64 oid)
141 {
142         if (fid_seq_is_mdt0(oi->oi.oi_seq)) {
143                 if (oid >= IDIF_MAX_OID) {
144                         CERROR("Bad %llu to set "DOSTID"\n",
145                                 (unsigned long long)oid, POSTID(oi));
146                         return;
147                 }
148                 oi->oi.oi_id = oid;
149         } else if (fid_is_idif(&oi->oi_fid)) {
150                 if (oid >= IDIF_MAX_OID) {
151                         CERROR("Bad %llu to set "DOSTID"\n",
152                                 (unsigned long long)oid, POSTID(oi));
153                         return;
154                 }
155                 oi->oi_fid.f_seq = fid_idif_seq(oid,
156                                                 fid_idif_ost_idx(&oi->oi_fid));
157                 oi->oi_fid.f_oid = oid;
158                 oi->oi_fid.f_ver = oid >> 48;
159         } else {
160                 if (oid > OBIF_MAX_OID) {
161                         CERROR("Bad %llu to set "DOSTID"\n",
162                                 (unsigned long long)oid, POSTID(oi));
163                         return;
164                 }
165                 oi->oi_fid.f_oid = oid;
166         }
167 }
168
169 static inline void ostid_cpu_to_le(const struct ost_id *src_oi,
170                                    struct ost_id *dst_oi)
171 {
172         if (fid_seq_is_mdt0(src_oi->oi.oi_seq)) {
173                 dst_oi->oi.oi_id = __cpu_to_le64(src_oi->oi.oi_id);
174                 dst_oi->oi.oi_seq = __cpu_to_le64(src_oi->oi.oi_seq);
175         } else {
176                 fid_cpu_to_le(&dst_oi->oi_fid, &src_oi->oi_fid);
177         }
178 }
179
180 static inline void ostid_le_to_cpu(const struct ost_id *src_oi,
181                                    struct ost_id *dst_oi)
182 {
183         if (fid_seq_is_mdt0(src_oi->oi.oi_seq)) {
184                 dst_oi->oi.oi_id = __le64_to_cpu(src_oi->oi.oi_id);
185                 dst_oi->oi.oi_seq = __le64_to_cpu(src_oi->oi.oi_seq);
186         } else {
187                 fid_le_to_cpu(&dst_oi->oi_fid, &src_oi->oi_fid);
188         }
189 }
190
191 /* pack any OST FID into an ostid (id/seq) for the wire/disk */
192 static inline int fid_to_ostid(const struct lu_fid *fid, struct ost_id *ostid)
193 {
194         if (fid_seq_is_igif(fid->f_seq)) {
195                 CERROR("bad IGIF, "DFID"\n", PFID(fid));
196                 return -EBADF;
197         }
198
199         if (fid_is_idif(fid)) {
200                 ostid_set_seq_mdt0(ostid);
201                 ostid_set_id(ostid, fid_idif_id(fid_seq(fid), fid_oid(fid),
202                                                 fid_ver(fid)));
203         } else {
204                 ostid->oi_fid = *fid;
205         }
206
207         return 0;
208 }
209
210 /**
211  * Sigh, because pre-2.4 uses
212  * struct lov_mds_md_v1 {
213  *      ........
214  *      __u64 lmm_object_id;
215  *      __u64 lmm_object_seq;
216  *      ......
217  *      }
218  * to identify the LOV(MDT) object, and lmm_object_seq will
219  * be normal_fid, which make it hard to combine these conversion
220  * to ostid_to FID. so we will do lmm_oi/fid conversion separately
221  *
222  * We can tell the lmm_oi by this way,
223  * 1.8: lmm_object_id = {inode}, lmm_object_gr = 0
224  * 2.1: lmm_object_id = {oid < 128k}, lmm_object_seq = FID_SEQ_NORMAL
225  * 2.4: lmm_oi.f_seq = FID_SEQ_NORMAL, lmm_oi.f_oid = {oid < 128k},
226  *      lmm_oi.f_ver = 0
227  *
228  * But currently lmm_oi/lsm_oi does not have any "real" usages,
229  * except for printing some information, and the user can always
230  * get the real FID from LMA, besides this multiple case check might
231  * make swab more complicate. So we will keep using id/seq for lmm_oi.
232  */
233
234 static inline void fid_to_lmm_oi(const struct lu_fid *fid,
235                                  struct ost_id *oi)
236 {
237         oi->oi.oi_id = fid_oid(fid);
238         oi->oi.oi_seq = fid_seq(fid);
239 }
240
241 /**
242  * Unpack an OST object id/seq (group) into a FID.  This is needed for
243  * converting all obdo, lmm, lsm, etc. 64-bit id/seq pairs into proper
244  * FIDs.  Note that if an id/seq is already in FID/IDIF format it will
245  * be passed through unchanged.  Only legacy OST objects in "group 0"
246  * will be mapped into the IDIF namespace so that they can fit into the
247  * struct lu_fid fields without loss.
248  */
249 static inline int ostid_to_fid(struct lu_fid *fid, const struct ost_id *ostid,
250                                __u32 ost_idx)
251 {
252         __u64 seq = ostid_seq(ostid);
253
254         if (ost_idx > 0xffff) {
255                 CERROR("bad ost_idx, "DOSTID" ost_idx:%u\n", POSTID(ostid),
256                        ost_idx);
257                 return -EBADF;
258         }
259
260         if (fid_seq_is_mdt0(seq)) {
261                 __u64 oid = ostid_id(ostid);
262
263                 /* This is a "legacy" (old 1.x/2.early) OST object in "group 0"
264                  * that we map into the IDIF namespace.  It allows up to 2^48
265                  * objects per OST, as this is the object namespace that has
266                  * been in production for years.  This can handle create rates
267                  * of 1M objects/s/OST for 9 years, or combinations thereof.
268                  */
269                 if (oid >= IDIF_MAX_OID) {
270                         CERROR("bad MDT0 id(1), "DOSTID" ost_idx:%u\n",
271                                POSTID(ostid), ost_idx);
272                         return -EBADF;
273                 }
274                 fid->f_seq = fid_idif_seq(oid, ost_idx);
275                 /* truncate to 32 bits by assignment */
276                 fid->f_oid = oid;
277                 /* in theory, not currently used */
278                 fid->f_ver = oid >> 48;
279         } else if (!fid_seq_is_default(seq)) {
280                 /* This is either an IDIF object, which identifies objects
281                  * across all OSTs, or a regular FID.  The IDIF namespace
282                  * maps legacy OST objects into the FID namespace.  In both
283                  * cases, we just pass the FID through, no conversion needed.
284                  */
285                 if (ostid->oi_fid.f_ver) {
286                         CERROR("bad MDT0 id(2), "DOSTID" ost_idx:%u\n",
287                                POSTID(ostid), ost_idx);
288                         return -EBADF;
289                 }
290                 *fid = ostid->oi_fid;
291         }
292
293         return 0;
294 }
295 #endif