2 * Copyright (c) 2002, Stockholms universitet
3 * (Stockholm University, Stockholm Sweden)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the university nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include "arla_local.h"
40 struct transform_fid
{
41 VenusFid dfid
; /* disconnected fid */
42 VenusFid cfid
; /* connecteted fid */
49 static Hashtab
*transform_htab
;
52 * Transaction fid related functions
56 * Find disconnected fid `dfid' in the transaction database.
59 static struct transform_fid
*
60 find_fid_transform(VenusFid
*dfid
)
62 struct transform_fid key
;
64 return hashtabsearch(transform_htab
, &key
);
68 * Transform the `fid` to a connected fid, return the pointer to `fid'
69 * so it can be used in a paramater to a function call.
73 transform_fid(VenusFid
*fid
)
75 struct transform_fid
*t
= find_fid_transform(fid
);
82 * Add a mapping between the disconnected fid `dfid' and the connected
83 * fid `cfid' in the transaction database.
87 add_fid_transform(VenusFid
*dfid
, VenusFid
*cfid
)
89 struct transform_fid
*f
= find_fid_transform(dfid
);
93 f
= malloc(sizeof(*f
));
100 hashtabadd(transform_htab
, f
);
104 * Help function for hashtable, compare `p1' and `p2'.
108 tfid_cmp(void *p1
, void *p2
)
110 struct transform_fid
*t1
= (struct transform_fid
*)p1
;
111 struct transform_fid
*t2
= (struct transform_fid
*)p2
;
112 return VenusFid_cmp(&t1
->dfid
, &t2
->dfid
);
116 * Help function for hashtable, calculate hash for `p'.
122 struct transform_fid
*t
= (struct transform_fid
*)p
;
123 return t
->dfid
.Cell
+ t
->dfid
.fid
.Volume
+ t
->dfid
.fid
.Vnode
124 + t
->dfid
.fid
.Unique
;
128 tfid_free(void *p
, void *arg
)
130 struct transform_fid
*t
= (struct transform_fid
*)p
;
131 memset(t
, 0, sizeof(*t
));
138 * Reintegrate the log
142 disco_reintegrate(nnpfs_pag_t pag
)
144 struct disco_play_context
*c
;
145 char buf
[DISCO_MAX_BUF_SZ
];
147 FCacheEntry
*dir_entry
, *child_entry
;
152 AFSStoreStatus store_status
;
153 AFSFetchStatus fetch_status
;
155 int old_conn_mode
= connected_mode
;
157 transform_htab
= hashtabnewf(0, tfid_cmp
, tfid_hash
, HASHTAB_GROW
);
158 if (transform_htab
== NULL
)
162 modified_log
= 0; /* XXX */
167 connected_mode
= CONNECTED
;
169 disco_init_context(&c
);
171 while(disco_next_entry(c
, buf
, sizeof(buf
)) == 0) {
172 struct disco_header
*h
= (struct disco_header
*)buf
;
174 if (h
->opcode
>= DISCO_OP_MAX_OPCODE
)
181 if (h
->flags
& DISCO_HEADER_NOP
)
185 case DISCO_OP_UNLINK
:
187 case DISCO_OP_REMOVE_DIR
:
189 case DISCO_OP_CREATE_FILE
: {
190 struct disco_create_file
*f
= (struct disco_create_file
*)buf
;
194 transform_fid(&f
->parentfid
);
196 ce
= cred_get(f
->parentfid
.Cell
, pag
, CRED_ANY
);
199 ret
= fcache_find(&dir_entry
, f
->parentfid
);
201 arla_warnx(ADEBERROR
, "create failed: (parent)"
202 "parent fid %d.%d.%d.%d name %s",
203 f
->parentfid
.Cell
, f
->parentfid
.fid
.Volume
,
204 f
->parentfid
.fid
.Vnode
, f
->parentfid
.fid
.Unique
,
209 transform_fid(&f
->fid
);
211 ret
= fcache_find(&child_entry
, f
->fid
);
213 arla_warnx(ADEBERROR
, "create failed (child): "
214 "parent fid %d.%d.%d.%d name %s",
215 f
->parentfid
.Cell
, f
->parentfid
.fid
.Volume
,
216 f
->parentfid
.fid
.Vnode
, f
->parentfid
.fid
.Unique
,
222 /* XXX make summery of chain */
223 store_status
= f
->storestatus
; /* XXX */
225 ret
= create_file(dir_entry
, f
->name
, &store_status
, &child_fid
,
229 if (VenusFid_cmp(&f
->fid
, &child_fid
) != 0) {
230 add_fid_transform(&f
->fid
, &child_fid
);
232 recon_hashtabdel(child_entry
);
233 child_entry
->fid
= child_fid
;
234 update_fid (f
->fid
, NULL
, child_fid
, child_entry
);
235 recon_hashtabadd(child_entry
);
237 adir_changefid(&dir_entry
, f
->name
, &child_fid
, &ce
);
244 /* XXX invalidate name cache */
245 arla_warn(ADEBWARN
, ret
, "create failed (create_file): "
246 "parent fid %d.%d.%d.%d name %s",
247 f
->parentfid
.Cell
, f
->parentfid
.fid
.Volume
,
248 f
->parentfid
.fid
.Vnode
, f
->parentfid
.fid
.Unique
,
252 /* XXX invalidate the parent's name cache */
253 break_callback(dir_entry
);
257 case DISCO_OP_CREATE_SYMLINK
:
258 case DISCO_OP_CREATE_LINK
:
260 case DISCO_OP_STOREDATA
:
267 fcache_release(dir_entry
);
269 fcache_release(child_entry
);
273 arla_warnx(ADEBWARN
, "next reintegrate entry");
276 disco_close_context(c
);
281 hashtabcleantab(transform_htab
, tfid_free
, NULL
);
282 hashtabrelease(transform_htab
);
283 transform_htab
= NULL
;
285 connected_mode
= old_conn_mode
;