+struct fidmap_entry {
+ struct hlist_node fm_hash;
+ struct lustre_id fm_id;
+};
+
+int mds_fidmap_init(struct obd_device *obd, int size)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct hlist_head *head;
+ int i = 0;
+ ENTRY;
+
+ LASSERT(size > sizeof(sizeof(struct hlist_head)));
+ mds->mds_fidmap_size = size / sizeof(struct hlist_head);
+
+ CWARN("allocating %lu fid mapping entries\n",
+ (unsigned long)mds->mds_fidmap_size);
+
+ OBD_ALLOC(mds->mds_fidmap_table, size);
+ if (!mds->mds_fidmap_table)
+ RETURN(-ENOMEM);
+
+ i = mds->mds_fidmap_size;
+ head = mds->mds_fidmap_table;
+ do {
+ INIT_HLIST_HEAD(head);
+ head++;
+ i--;
+ } while(i);
+
+ RETURN(0);
+}
+
+int mds_fidmap_cleanup(struct obd_device *obd)
+{
+ struct hlist_node *node = NULL, *tmp = NULL;
+ struct mds_obd *mds = &obd->u.mds;
+ struct fidmap_entry *entry;
+ struct hlist_head *head;
+ int i = 0;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ for (i = 0, head = mds->mds_fidmap_table;
+ i < mds->mds_fidmap_size; i++, head++) {
+ hlist_for_each_safe(node, tmp, head) {
+ entry = hlist_entry(node, struct fidmap_entry, fm_hash);
+ hlist_del_init(&entry->fm_hash);
+ OBD_FREE(entry, sizeof(*entry));
+ }
+ }
+ spin_unlock(&mds->mds_fidmap_lock);
+ OBD_FREE(mds->mds_fidmap_table, mds->mds_fidmap_size *
+ sizeof(struct hlist_head));
+ RETURN(0);
+}
+
+static inline unsigned long
+const hashfn(struct obd_device *obd, __u64 fid)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ return (unsigned long)(fid & (mds->mds_fidmap_size - 1));
+}
+
+static struct fidmap_entry *
+__mds_fidmap_find(struct obd_device *obd, __u64 fid)
+{
+ struct fidmap_entry *entry = NULL;
+ struct mds_obd *mds = &obd->u.mds;
+ struct hlist_node *node = NULL;
+ struct hlist_head *head;
+ ENTRY;
+
+ head = mds->mds_fidmap_table + hashfn(obd, fid);
+ hlist_for_each(node, head) {
+ entry = hlist_entry(node, struct fidmap_entry, fm_hash);
+ if (id_fid(&entry->fm_id) == fid)
+ RETURN(entry);
+ }
+ RETURN(NULL);
+}
+
+struct fidmap_entry *
+mds_fidmap_find(struct obd_device *obd, __u64 fid)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct fidmap_entry *entry;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ entry = __mds_fidmap_find(obd, fid);
+ spin_unlock(&mds->mds_fidmap_lock);
+
+ RETURN(entry);
+}
+
+static void __mds_fidmap_insert(struct obd_device *obd,
+ struct fidmap_entry *entry)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct hlist_head *head;
+ unsigned long idx;
+ ENTRY;
+
+ idx = hashfn(obd, id_fid(&entry->fm_id));
+ head = mds->mds_fidmap_table + idx;
+ hlist_add_head(&entry->fm_hash, head);
+
+ EXIT;
+}
+
+void mds_fidmap_insert(struct obd_device *obd,
+ struct fidmap_entry *entry)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ __mds_fidmap_insert(obd, entry);
+ spin_unlock(&mds->mds_fidmap_lock);
+
+ EXIT;
+}
+
+static void __mds_fidmap_remove(struct obd_device *obd,
+ struct fidmap_entry *entry)
+{
+ ENTRY;
+ hlist_del_init(&entry->fm_hash);
+ EXIT;
+}
+
+void mds_fidmap_remove(struct obd_device *obd,
+ struct fidmap_entry *entry)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ __mds_fidmap_remove(obd, entry);
+ spin_unlock(&mds->mds_fidmap_lock);
+
+ EXIT;
+}
+
+/* creates new mapping remote fid -> local inode store cookie. Both are saved in
+ * lustre_id for better usability, as all mds function use lustre_id as input
+ * params.*/
+int mds_fidmap_add(struct obd_device *obd,
+ struct lustre_id *id)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct fidmap_entry *entry;
+ ENTRY;
+
+ OBD_ALLOC(entry, sizeof(*entry));
+ if (!entry)
+ RETURN(-ENOMEM);
+
+ entry->fm_id = *id;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ if (!__mds_fidmap_find(obd, id_fid(id))) {
+ __mds_fidmap_insert(obd, entry);
+ spin_unlock(&mds->mds_fidmap_lock);
+ CDEBUG(D_INODE, "added mapping to "DLID4"\n",
+ OLID4(id));
+ RETURN(1);
+ }
+ spin_unlock(&mds->mds_fidmap_lock);
+ OBD_FREE(entry, sizeof(*entry));
+
+ RETURN(0);
+}
+
+/* removes mapping using fid component from passed @id */
+void mds_fidmap_del(struct obd_device *obd,
+ struct lustre_id *id)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct fidmap_entry *entry;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ entry = __mds_fidmap_find(obd, id_fid(id));
+ if (entry) {
+ __mds_fidmap_remove(obd, entry);
+ spin_unlock(&mds->mds_fidmap_lock);
+ OBD_FREE(entry, sizeof(*entry));
+ CDEBUG(D_INODE, "removed mapping to "DLID4"\n",
+ OLID4(id));
+ goto out;
+ }
+ spin_unlock(&mds->mds_fidmap_lock);
+out:
+ EXIT;
+}
+
+struct lustre_id *mds_fidmap_lookup(struct obd_device *obd,
+ struct lustre_id *id)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct fidmap_entry *entry;
+ ENTRY;
+
+ spin_lock(&mds->mds_fidmap_lock);
+ entry = __mds_fidmap_find(obd, id_fid(id));
+ spin_unlock(&mds->mds_fidmap_lock);
+
+ if (!entry)
+ RETURN(NULL);
+
+ RETURN(&entry->fm_id);
+}
+