1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/class_target.c
38 * Common methods for target devices
40 * Author: Mikhail Pershin
42 #define DEBUG_SUBSYSTEM S_CLASS
44 # define EXPORT_SYMTAB
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>
57 * Initialize trans_table if it is not initialized yet
59 void target_trans_table_init(struct obd_device *obd)
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);
69 EXPORT_SYMBOL(target_trans_table_init);
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
76 __u32 target_trans_table_slot2time(struct obd_device_target *obt, int idx)
78 __u32 time = le32_to_cpu(obt->obt_lsd->lsd_trans_table_time);
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);
87 * Check trans table in server_data to get last time this export was seen
89 __u32 target_trans_table_last_time(struct obd_export *exp)
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();
96 /** return current time */
97 if (obt->obt_stale_export_age == 0)
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]))
106 time = target_trans_table_slot2time(obt, idx);
107 spin_unlock(&obt->obt_trans_table_lock);
110 EXPORT_SYMBOL(target_trans_table_last_time);
113 * Recalculate trans_table slots data if stale_export_age is changed
115 void target_trans_table_recalc(struct obd_device *obd, __u32 new_age)
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;
123 /** there is no old info to recalc */
124 if (obt->obt_stale_export_age == 0)
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 */
139 for (j = slots; j > 0; j--) {
140 i = (j - 1) * new_age / old_age;
144 spin_unlock(&obt->obt_trans_table_lock);
146 EXPORT_SYMBOL(target_trans_table_recalc);
149 * New transno is arrived and it is time for new slot
151 void target_trans_table_update(struct obd_export *exp, __u64 transno)
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);
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 */
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;
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);
177 EXPORT_SYMBOL(target_trans_table_update);
179 int target_fs_version_capable(struct obd_device *obd)
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);
185 EXPORT_SYMBOL(target_fs_version_capable);