Whamcloud - gitweb
b=23787 make struct lprocfs_percpu definition C99 compliant
[fs/lustre-release.git] / lustre / obdclass / target.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/obdclass/class_target.c
37  *
38  * Common methods for target devices
39  *
40  * Author: Mikhail Pershin
41  */
42 #define DEBUG_SUBSYSTEM S_CLASS
43 #ifndef EXPORT_SYMTAB
44 # define EXPORT_SYMTAB
45 #endif
46
47 #include <obd_class.h>
48 #include <lustre_fsfilt.h>
49 #include <libcfs/list.h>
50 #include <lustre_disk.h>
51 #include <lustre_lib.h>
52 #include <linux/slab.h>
53 #include <lustre_param.h>
54 #include <obd.h>
55
56 /**
57  * Initialize trans_table if it is not initialized yet
58  */
59 void target_trans_table_init(struct obd_device *obd)
60 {
61         struct lr_server_data *lsd = obd->u.obt.obt_lsd;
62         /** new export or from 1.6 fs */
63         if (le32_to_cpu(lsd->lsd_trans_table_time) == 0)
64                 lsd->lsd_trans_table_time = cpu_to_le32(cfs_time_current_sec());
65         /** number of interval changed, write new value */
66         if (le32_to_cpu(lsd->lsd_expire_intervals) == 0)
67                 lsd->lsd_expire_intervals = cpu_to_le32(LR_EXPIRE_INTERVALS);
68 }
69 EXPORT_SYMBOL(target_trans_table_init);
70
71 /**
72  * Calculate time by index. All expiration time is divided by LR_EXPIRE_INTERVALS,
73  * so time of each index is calculated from time of first index
74  */
75 static inline
76 __u32 target_trans_table_slot2time(struct obd_device_target *obt, int idx)
77 {
78         __u32 time = le32_to_cpu(obt->obt_lsd->lsd_trans_table_time);
79         __u32 age;
80
81         age = obt->obt_stale_export_age /
82               le32_to_cpu(obt->obt_lsd->lsd_expire_intervals) * idx;
83         return cfs_time_sub(time, age);
84 }
85
86 /**
87  * Check trans table in server_data to get last time this export was seen
88  */
89 __u32 target_trans_table_last_time(struct obd_export *exp)
90 {
91         struct obd_device_target *obt = &exp->exp_obd->u.obt;
92         const __u32 slots = le32_to_cpu(obt->obt_lsd->lsd_expire_intervals);
93         __u32 time = cfs_time_current_sec();
94         int i, idx = slots;
95
96         /** return current time */
97         if (obt->obt_stale_export_age == 0)
98                 return time;
99
100         spin_lock(&obt->obt_trans_table_lock);
101         for (i = 0; i < slots; i++)
102                 if (exp->exp_last_committed <=
103                     le64_to_cpu(obt->obt_lsd->lsd_trans_table[i]))
104                         idx = i;
105         if (idx < slots)
106                 time = target_trans_table_slot2time(obt, idx);
107         spin_unlock(&obt->obt_trans_table_lock);
108         return time;
109 }
110 EXPORT_SYMBOL(target_trans_table_last_time);
111
112 /**
113  * Recalculate trans_table slots data if stale_export_age is changed
114  */
115 void target_trans_table_recalc(struct obd_device *obd, __u32 new_age)
116 {
117         struct obd_device_target *obt = &obd->u.obt;
118         __u32 old_age = obt->obt_stale_export_age;
119         const __u32 slots = le32_to_cpu(obt->obt_lsd->lsd_expire_intervals);
120         __u64 *table = obt->obt_lsd->lsd_trans_table;
121         int i, j;
122
123         /** there is no old info to recalc */
124         if (obt->obt_stale_export_age == 0)
125                 return;
126
127         /** Expand table */
128         spin_lock(&obt->obt_trans_table_lock);
129         if (old_age < new_age) {
130                 for (j = 0; j < slots; j++) {
131                         i = j * new_age / old_age;
132                         /** no more data for new age */
133                         if (i >= slots)
134                                 table[j] = 0;
135                         else
136                                 table[j] = table[i];
137                 }
138         } else {
139                 for (j = slots; j > 0; j--) {
140                         i = (j - 1) * new_age / old_age;
141                         table[j] = table[i];
142                 }
143         }
144         spin_unlock(&obt->obt_trans_table_lock);
145 }
146 EXPORT_SYMBOL(target_trans_table_recalc);
147
148 /**
149  * New transno is arrived and it is time for new slot
150  */
151 void target_trans_table_update(struct obd_export *exp, __u64 transno)
152 {
153         struct obd_device_target *obt = &exp->exp_obd->u.obt;
154         __u32 shift = cfs_time_sub(cfs_time_current_sec(),
155                               le32_to_cpu(obt->obt_lsd->lsd_trans_table_time));
156         __u64 *table = obt->obt_lsd->lsd_trans_table;
157         const __u32 slots = le32_to_cpu(obt->obt_lsd->lsd_expire_intervals);
158         int n = 0, i, j;
159
160         /** how many slots are in shift */
161         if (obt->obt_stale_export_age > 0)
162                 n = shift * slots / obt->obt_stale_export_age;
163         /** it is not time to update */
164         if (n == 0)
165                 return;
166         spin_lock(&obt->obt_trans_table_lock);
167         /** shift table if there is overlapping or fill with latest transno */
168         for (i = slots - 1; i >= 1; i--) {
169                 j = i > n ? i - n : 0;
170                 table[i] = table[j];
171         }
172         /** now update first slot with new data */
173         obt->obt_lsd->lsd_trans_table_time = cpu_to_le32(cfs_time_current_sec());
174         obt->obt_lsd->lsd_trans_table[0] = cpu_to_le64(transno);
175         spin_unlock(&obt->obt_trans_table_lock);
176 }
177 EXPORT_SYMBOL(target_trans_table_update);
178
179 int target_fs_version_capable(struct obd_device *obd)
180 {
181         struct inode * inode = obd->u.obt.obt_rcvd_filp->f_dentry->d_inode;
182         /** check inode has version */
183         return (fsfilt_get_version(obd, inode) != -EOPNOTSUPP);
184 }
185 EXPORT_SYMBOL(target_fs_version_capable);
186