2 * Copyright (C) 1997,98,2002 Free Software Foundation, Inc.
3 * Copyright (C) 2013 Steven McDonald <steven@steven-mcdonald.id.au>
5 * ftpfs translator written by Miles Bader <miles@gnu.org>
6 * Modified for trovefs by Steven McDonald <steven@steven-mcdonald.id.au>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This software is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 #include <hurd/netfs.h>
28 #define INIT_HTABLE_LEN 5
30 struct dir_fetch_state
32 struct trovefs_dir *dir;
33 struct trovefs_dir_entry **prev_entry_next_p;
37 insert (struct trovefs_dir_entry *e, struct trovefs_dir_entry **htable, size_t htable_len)
39 struct trovefs_dir_entry **t = &htable[e->hv % htable_len];
41 (*t)->self_p = &e->next;
48 rehash (struct trovefs_dir *dir, size_t new_len)
51 size_t old_len = dir->htable_len;
52 struct trovefs_dir_entry **old_htable = dir->htable;
53 struct trovefs_dir_entry **new_htable = malloc (new_len * sizeof (struct trovefs_dir_entry *));
58 bzero (new_htable, new_len * sizeof (struct trovefs_dir_entry *));
60 for (i = 0; i < old_len; i++)
63 struct trovefs_dir_entry *e = old_htable[i];
64 old_htable[i] = e->next;
65 insert (e, new_htable, new_len);
70 dir->htable = new_htable;
71 dir->htable_len = new_len;
77 hash (const char *name)
81 hv = ((hv << 5) + *name++) & 0xFFFFFF;
85 struct trovefs_dir_entry *
86 lookup (struct trovefs_dir *dir, const char *name, int add)
88 size_t hv = hash (name);
89 struct trovefs_dir_entry *h = dir->htable[hv % dir->htable_len], *e = h;
91 while (e && strcmp (name, e->name) != 0)
96 if (dir->num_entries > dir->htable_len)
97 if (rehash(dir, (dir->htable_len + 1) * 2 - 1) != 0)
100 e = malloc (sizeof *e);
104 e->name = strdup (name);
107 e->stat_timestamp = 0;
108 bzero (&e->stat, sizeof (e->stat));
111 e->name_timestamp = e->stat_timestamp = 0;
113 e->ordered_self_p = 0;
116 insert (e, dir->htable, dir->htable_len);
125 trovefs_dir_create (struct trovefs *fs, struct node *node, const char *rmt_path, struct trovefs_dir **dir)
127 struct trovefs_dir *new = malloc (sizeof (struct trovefs_dir));
128 struct trovefs_dir_entry **htable = calloc (INIT_HTABLE_LEN, sizeof (struct trovefs_dir_entry *));
139 pthread_spin_lock (&netfs_node_refcnt_lock);
141 pthread_spin_unlock (&netfs_node_refcnt_lock);
143 new->num_entries = 0;
144 new->num_live_entries = 0;
145 new->htable_len = INIT_HTABLE_LEN;
146 new->htable = htable;
148 new->rmt_path = rmt_path;
151 new->stat_timestamp = 0;
152 new->name_timestamp = 0;
153 new->bulk_stat_base_stamp = 0;
154 new->bulk_stat_count_first_half = 0;
155 new->bulk_stat_count_second_half = 0;
163 trovefs_dir_null_lookup (struct trovefs_dir *dir, struct node **node)
165 struct trovefs_dir_entry *e;
168 e = lookup (dir, "", 1);
174 pthread_spin_lock (&netfs_node_refcnt_lock);
176 e->node->references++;
177 pthread_spin_unlock (&netfs_node_refcnt_lock);
181 err = trovefs_create_node (e, dir->rmt_path, &e->node);
183 if (!err && dir->num_live_entries++ == 0)
185 pthread_spin_lock (&netfs_node_refcnt_lock);
186 dir->node->references++;
187 pthread_spin_unlock (&netfs_node_refcnt_lock);
201 trovefs_refresh_node (struct node *node)
204 struct netnode *nn = node->nn;
205 struct trovefs_dir_entry *entry = nn->dir_entry;
211 pthread_mutex_lock (&entry->dir->node->lock);
217 pthread_mutex_unlock (&entry->dir->node->lock);
222 err = trovefs_s3_get_names (entry->dir);
223 if (!err && entry->noent)
232 pthread_mutex_unlock (&entry->dir->node->lock);
239 free_entry (struct trovefs_dir_entry *e)
241 assert (! e->self_p);