2 * Copyright (c) 1995-2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "arla_local.h"
37 #include <nnpfs/nnpfs_message.h>
42 nnpfs_message_getroot (int, struct nnpfs_message_getroot
*, u_int
);
45 nnpfs_message_getnode (int, struct nnpfs_message_getnode
*, u_int
);
48 nnpfs_message_getattr (int, struct nnpfs_message_getattr
*, u_int
);
51 nnpfs_message_open (int, struct nnpfs_message_open
*, u_int
);
54 nnpfs_message_getdata (int, struct nnpfs_message_getdata
*, u_int
);
57 nnpfs_message_inactivenode (int,struct nnpfs_message_inactivenode
*,u_int
);
60 nnpfs_message_putdata (int fd
, struct nnpfs_message_putdata
*h
, u_int size
);
63 nnpfs_message_putattr (int fd
, struct nnpfs_message_putattr
*h
, u_int size
);
66 nnpfs_message_create (int fd
, struct nnpfs_message_create
*h
, u_int size
);
69 nnpfs_message_mkdir (int fd
, struct nnpfs_message_mkdir
*h
, u_int size
);
72 nnpfs_message_link (int fd
, struct nnpfs_message_link
*h
, u_int size
);
75 nnpfs_message_symlink (int fd
, struct nnpfs_message_symlink
*h
, u_int size
);
78 nnpfs_message_remove (int fd
, struct nnpfs_message_remove
*h
, u_int size
);
81 nnpfs_message_rmdir (int fd
, struct nnpfs_message_rmdir
*h
, u_int size
);
84 nnpfs_message_rename (int fd
, struct nnpfs_message_rename
*h
, u_int size
);
87 nnpfs_message_pioctl (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
) ;
90 nnpfs_message_appenddata (int,struct nnpfs_message_appenddata
*h
, u_int size
);
93 nnpfs_message_deletedata (int,struct nnpfs_message_deletedata
*h
, u_int size
);
96 nnpfs_message_accesses (int,struct nnpfs_message_accesses
*h
, u_int size
);
99 afsrights2nnpfsrights(u_long
, uint32_t, uint32_t);
102 possibly_have_network(void);
108 nnpfs_message_function rcvfuncs
[] = {
110 (nnpfs_message_function
)nnpfs_message_wakeup
, /* wakeup */
111 (nnpfs_message_function
)nnpfs_message_getroot
, /* getroot */
112 NULL
, /* installroot */
113 (nnpfs_message_function
)nnpfs_message_getnode
, /* getnode */
114 NULL
, /* installnode */
115 (nnpfs_message_function
)nnpfs_message_getattr
, /* getattr */
116 NULL
, /* installattr */
117 (nnpfs_message_function
)nnpfs_message_getdata
, /* getdata */
118 NULL
, /* installdata */
119 (nnpfs_message_function
)nnpfs_message_inactivenode
, /* inactivenode */
120 NULL
, /* invalidnode */
121 (nnpfs_message_function
)nnpfs_message_open
, /* open */
122 (nnpfs_message_function
)nnpfs_message_putdata
, /* put_data */
123 (nnpfs_message_function
)nnpfs_message_putattr
, /* put attr */
124 (nnpfs_message_function
)nnpfs_message_create
, /* create */
125 (nnpfs_message_function
)nnpfs_message_mkdir
, /* mkdir */
126 (nnpfs_message_function
)nnpfs_message_link
, /* link */
127 (nnpfs_message_function
)nnpfs_message_symlink
, /* symlink */
128 (nnpfs_message_function
)nnpfs_message_remove
, /* remove */
129 (nnpfs_message_function
)nnpfs_message_rmdir
, /* rmdir */
130 (nnpfs_message_function
)nnpfs_message_rename
, /* rename */
131 (nnpfs_message_function
)nnpfs_message_pioctl
, /* pioctl */
132 NULL
, /* updatefid */
135 NULL
, /* delete node */
136 (nnpfs_message_function
)nnpfs_message_appenddata
, /* appenddata */
137 (nnpfs_message_function
)nnpfs_message_deletedata
, /* deletedata */
138 (nnpfs_message_function
)nnpfs_message_accesses
/* accesses */
143 /* number of prefetches currently in progress */
144 static int num_prefetches
= 0;
147 /* maximum number of concurrent prefetches */
148 static int max_prefetches
;
157 max_prefetches
= kernel_highworkers() - 2; /* XXX should be configurable */
165 afsfid2inode (const VenusFid
*fid
)
167 return ((fid
->fid
.Volume
& 0x7FFF) << 16 | (fid
->fid
.Vnode
& 0xFFFFFFFF));
171 * AFSFetchStatus -> nnpfs_attr
172 * Setting everything except for length and mode.
176 afsstatus2nnpfs_attr (AFSFetchStatus
*status
,
178 struct nnpfs_attr
*attr
,
183 attr
->valid
= XA_V_NONE
;
184 switch (status
->FileType
) {
187 XA_SET_TYPE(attr
, NNPFS_FILE_REG
);
191 XA_SET_TYPE(attr
, NNPFS_FILE_DIR
);
195 XA_SET_TYPE(attr
, NNPFS_FILE_LNK
);
198 arla_warnx (ADEBMSG
, "afsstatus2nnpfs_attr: default");
201 XA_SET_NLINK(attr
, status
->LinkCount
);
202 if (flags
& FCACHE2NNPFSNODE_LENGTH
)
203 XA_SET_SIZE(attr
, fcache_get_status_length(status
));
204 XA_SET_UID(attr
,status
->Owner
);
205 XA_SET_GID(attr
, status
->Group
);
206 XA_SET_ATIME(attr
, status
->ClientModTime
);
207 XA_SET_MTIME(attr
, status
->ClientModTime
);
208 XA_SET_CTIME(attr
, status
->ClientModTime
);
209 XA_SET_FILEID(attr
, afsfid2inode(fid
));
211 /* XXX this is wrong, need to keep track of `our` ae for this req */
215 rights
= afsrights2nnpfsrights(status
->CallerAccess
,
217 status
->UnixModeBits
);
219 if (rights
& NNPFS_RIGHT_R
)
221 if (rights
& NNPFS_RIGHT_W
)
223 if (rights
& NNPFS_RIGHT_X
)
226 mode
|= status
->UnixModeBits
;
228 XA_SET_MODE(attr
, mode
);
232 * Transform `access', `FileType' and `UnixModeBits' into rights.
234 * There are different transformations for directories and files to be
235 * compatible with the Transarc client.
239 afsrights2nnpfsrights(u_long ar
, uint32_t FileType
, uint32_t UnixModeBits
)
241 nnpfs_rights ret
= 0;
243 if (FileType
== TYPE_DIR
) {
245 ret
|= NNPFS_RIGHT_R
| NNPFS_RIGHT_X
;
246 if (ar
& (AINSERT
| ADELETE
))
247 ret
|= NNPFS_RIGHT_W
;
250 * If its a file, and the AADMIN bit is set, we are the owner
251 * of the file. Now we really want to know if we had AINSERT
252 * the bits on the directory, but since we don't know that
253 * here, lets just punt and let the fileserver tell us later
254 * if we guess right. Give read and write to ourself for now.
256 if (FileType
== TYPE_FILE
&& (ar
& AADMIN
))
257 ret
|= NNPFS_RIGHT_R
|NNPFS_RIGHT_W
;
259 * Clients can read symlink in directories where they only
260 * have ALIST (l) rights.
262 if (FileType
== TYPE_LINK
&& (ar
& ALIST
))
263 ret
|= NNPFS_RIGHT_R
;
265 * Match RWX to AREAD+R, AWRITE+W, AREAD+X
267 if ((ar
& AREAD
) && (UnixModeBits
& S_IRUSR
))
268 ret
|= NNPFS_RIGHT_R
;
269 if ((ar
& AWRITE
) && (UnixModeBits
& S_IWUSR
))
270 ret
|= NNPFS_RIGHT_W
;
271 if ((ar
& AREAD
) && (UnixModeBits
& S_IXUSR
))
272 ret
|= NNPFS_RIGHT_X
;
276 ret
|= NNPFS_RIGHT_AR
;
278 ret
|= NNPFS_RIGHT_AW
;
280 ret
|= NNPFS_RIGHT_AL
;
282 ret
|= NNPFS_RIGHT_AI
;
284 ret
|= NNPFS_RIGHT_AD
;
286 ret
|= NNPFS_RIGHT_AK
;
288 ret
|= NNPFS_RIGHT_AA
;
294 fcacheentry2nnpfsnode (const VenusFid
*fid
,
295 const VenusFid
*statfid
,
296 AFSFetchStatus
*status
,
297 struct nnpfs_msg_node
*node
,
303 memcpy (&node
->handle
, fid
, sizeof(*fid
));
305 afsstatus2nnpfs_attr (status
, statfid
, &node
->attr
, flags
);
307 node
->anonrights
= afsrights2nnpfsrights(status
->AnonymousAccess
,
309 status
->UnixModeBits
);
310 for (i
= 0; i
< NACCESS
; i
++) {
311 node
->id
[i
] = ae
[i
].cred
;
312 node
->rights
[i
] = afsrights2nnpfsrights(ae
[i
].access
,
314 status
->UnixModeBits
);
319 * convert `xa' into `storestatus'
323 nnpfs_attr2afsstorestatus(struct nnpfs_attr
*xa
,
324 AFSStoreStatus
*storestatus
)
328 if (XA_VALID_MODE(xa
)) {
329 storestatus
->UnixModeBits
= xa
->xa_mode
;
332 if (XA_VALID_UID(xa
)) {
333 storestatus
->Owner
= xa
->xa_uid
;
336 if (XA_VALID_GID(xa
)) {
337 storestatus
->Group
= xa
->xa_gid
;
340 if (XA_VALID_MTIME(xa
)) {
341 storestatus
->ClientModTime
= xa
->xa_mtime
;
344 storestatus
->Mask
= mask
;
347 storestatus
->SegSize
= 0;
352 * Convert an AFSFetchStatus to AFSStoreStatus
356 afsstatus2afsstorestatus(AFSFetchStatus
*fetchstatus
,
357 AFSStoreStatus
*storestatus
)
359 storestatus
->UnixModeBits
= fetchstatus
->UnixModeBits
;
360 storestatus
->Owner
= fetchstatus
->Owner
;
361 storestatus
->Group
= fetchstatus
->Group
;
362 storestatus
->ClientModTime
= fetchstatus
->ClientModTime
;
364 storestatus
->Mask
= SS_MODEBITS
| SS_OWNER
| SS_GROUP
| SS_MODTIME
;
366 storestatus
->SegSize
= 0;
370 * get new CredCacheEntry, for bad connections.
374 retry_cred(CredCacheEntry
**ce
, nnpfs_cred
*cred
)
376 int32_t cell
= (*ce
)->cell
;
378 conn_clearcred(CONN_CS_CRED
|CONN_CS_SECIDX
, 0, cred
->pag
, 2);
381 *ce
= cred_get(cell
, cred
->pag
, CRED_ANY
);
386 * Return true iff we should retry the operation.
387 * Also replace `ce' with anonymous creds in case it has expired.
389 * There must not be passed in any NULL pointers.
393 try_again (int *ret
, CredCacheEntry
**ce
, nnpfs_cred
*cred
, const VenusFid
*fid
)
400 case RXKADUNKNOWNKEY
:
401 retry_cred(ce
, cred
);
403 case RXKADSEALEDINCON
:
404 arla_warnx_with_fid (ADEBWARN
, fid
,
417 if (fid
&& !volcache_reliablep (fid
->fid
.Volume
, fid
->Cell
)) {
426 case ARLA_VDISKFULL
:
429 case ARLA_VOVERQUOTA
:
437 arla_warnx_with_fid (ADEBWARN
, fid
,
438 "Waiting for busy volume...");
439 IOMGR_Sleep (afs_BusyWaitPeriod
);
441 case ARLA_VRESTARTING
:
442 arla_warnx_with_fid (ADEBWARN
, fid
,
443 "Waiting for fileserver to restart...");
444 IOMGR_Sleep (afs_BusyWaitPeriod
);
455 * try_again() for cross cell operations
459 try_again_crosscell(int *ret
, CredCacheEntry
**ce
, CredCacheEntry
**ce2
,
460 nnpfs_cred
*cred
, const VenusFid
*fid
)
467 case RXKADUNKNOWNKEY
:
468 retry_cred(ce
, cred
);
469 retry_cred(ce2
, cred
);
473 return try_again(ret
, ce
, cred
, fid
);
478 * Do some basic setup and paranoia for installattr messages.
479 * Note that we grant the node NNPFS_ATTR_R tokens here...
484 static struct nnpfs_message_header
*
485 make_installattr(struct nnpfs_message_installattr
*msg
,
489 if (!entry
->flags
.datausedp
)
490 assert((entry
->tokens
& NNPFS_DATA_MASK
) == 0);
492 entry
->tokens
|= NNPFS_ATTR_R
;
494 fcacheentry2nnpfsnode(&entry
->fid
, fcache_realfid(entry
),
495 &entry
->status
, &msg
->node
,
496 entry
->acccache
, flags
);
498 msg
->header
.opcode
= NNPFS_MSG_INSTALLATTR
;
499 msg
->node
.tokens
= (entry
->tokens
& NNPFS_ATTR_MASK
);
502 return (struct nnpfs_message_header
*)msg
;
507 * Do some basic setup and paranoia for installnode messages.
508 * Note that we grant the node NNPFS_ATTR_R tokens here...
513 static struct nnpfs_message_header
*
514 make_installnode(struct nnpfs_message_installnode
*msg
,
516 const VenusFid
*parent
,
519 fcacheentry2nnpfsnode(&entry
->fid
, fcache_realfid(entry
),
520 &entry
->status
, &msg
->node
,
521 entry
->acccache
, FCACHE2NNPFSNODE_ALL
);
523 msg
->header
.opcode
= NNPFS_MSG_INSTALLNODE
;
524 /* msg->node.tokens = entry->tokens; */
525 msg
->parent_handle
= *parent
;
526 strlcpy(msg
->name
, name
, sizeof(msg
->name
));
528 return (struct nnpfs_message_header
*)msg
;
533 * Do some basic setup and paranoia for installdata messages.
535 * This could be extended to do more of the message setup.
537 * XXX I'd like some node/block flags handling (kernelp, ...) in here,
538 * but maybe they should be taken care of after the actuall install
539 * operation has completed successfully.
542 static struct nnpfs_message_header
*
543 make_installdata(struct nnpfs_message_installdata
*msg
,
548 entry
->tokens
|= NNPFS_ATTR_R
|NNPFS_DATA_R
;
549 msg
->node
.tokens
= (entry
->tokens
& (NNPFS_DATA_MASK
| NNPFS_OPEN_MASK
));
550 entry
->flags
.attrusedp
= TRUE
;
551 entry
->flags
.datausedp
= TRUE
;
553 fcacheentry2nnpfsnode(&entry
->fid
, fcache_realfid(entry
),
554 &entry
->status
, &msg
->node
,
555 entry
->acccache
, FCACHE2NNPFSNODE_ALL
);
557 msg
->offset
= offset
;
558 msg
->cache_id
= entry
->index
;
560 msg
->header
.opcode
= NNPFS_MSG_INSTALLDATA
;
562 /* XXX we shouldn't do this until operation was successful */
563 if (offset
!= NNPFS_NO_OFFSET
)
564 fcache_data_setkernelp(entry
, offset
, TRUE
, FALSE
);
566 return (struct nnpfs_message_header
*)msg
;
570 * Fetch data and retry if failing
574 message_get_data (FCacheEntry
**entry
,
575 struct nnpfs_cred
*cred
,
577 uint64_t wanted_length
)
581 ret
= fcache_get_data (entry
, ce
, 0, wanted_length
);
582 } while (try_again (&ret
, ce
, cred
, &(*entry
)->fid
));
591 nnpfs_message_getroot (int fd
, struct nnpfs_message_getroot
*h
, u_int size
)
593 struct nnpfs_message_installroot msg
;
597 FCacheEntry
*entry
= NULL
;
598 struct nnpfs_message_header
*h0
= NULL
;
600 int32_t cell_id
= cell_name2num(cell_getthiscell());
602 ce
= cred_get (cell_id
, h
->cred
.pag
, CRED_ANY
);
605 ret
= getroot (&root_fid
, ce
);
606 } while (try_again (&ret
, &ce
, &h
->cred
, &root_fid
));
611 ret
= fcache_get(&entry
, root_fid
, ce
);
616 ret
= cm_getattr(entry
, ce
);
617 } while (try_again (&ret
, &ce
, &h
->cred
, &root_fid
));
620 fcacheentry2nnpfsnode (&root_fid
, fcache_realfid(entry
),
621 &entry
->status
, &msg
.node
, entry
->acccache
,
622 FCACHE2NNPFSNODE_ALL
);
624 entry
->tokens
|= NNPFS_ATTR_R
;
625 msg
.node
.tokens
= entry
->tokens
& ~NNPFS_DATA_MASK
;
626 msg
.header
.opcode
= NNPFS_MSG_INSTALLROOT
;
627 h0
= (struct nnpfs_message_header
*)&msg
;
628 h0_len
= sizeof(msg
);
632 nnpfs_send_message_wakeup_multiple (fd
,
633 h
->header
.sequence_num
,
638 fcache_release(entry
);
645 nnpfs_message_getnode (int fd
, struct nnpfs_message_getnode
*h
, u_int size
)
647 struct nnpfs_message_installnode msg
;
648 VenusFid
*dirfid
= (VenusFid
*)&h
->parent_handle
;
651 AFSFetchStatus status
;
653 FCacheEntry
*entry
= NULL
;
654 FCacheEntry
*dentry
= NULL
;
655 struct nnpfs_message_header
*h0
= NULL
;
659 arla_warnx (ADEBMSG
, "getnode (%ld.%lu.%lu.%lu) \"%s\"",
660 (long)dirfid
->Cell
, (unsigned long)dirfid
->fid
.Volume
,
661 (unsigned long)dirfid
->fid
.Vnode
,
662 (unsigned long)dirfid
->fid
.Unique
, h
->name
);
664 ce
= cred_get (dirfid
->Cell
, h
->cred
.pag
, CRED_ANY
);
667 ret
= fcache_get(&dentry
, *dirfid
, ce
);
671 assert_flag(dentry
,kernelp
);
674 ret
= cm_lookup (&dentry
, h
->name
, &fid
, &ce
, TRUE
);
675 *dirfid
= dentry
->fid
;
676 } while (try_again (&ret
, &ce
, &h
->cred
, dirfid
));
681 fcache_release(dentry
);
684 ret
= fcache_get(&entry
, fid
, ce
);
689 ret
= cm_getattr(entry
, ce
);
690 status
= entry
->status
;
691 real_fid
= *fcache_realfid(entry
);
692 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
695 fcacheentry2nnpfsnode (&fid
, &real_fid
, &status
, &msg
.node
,
696 entry
->acccache
, FCACHE2NNPFSNODE_ALL
);
698 entry
->tokens
|= NNPFS_ATTR_R
;
699 msg
.node
.tokens
= entry
->tokens
;
700 msg
.parent_handle
= h
->parent_handle
;
701 strlcpy (msg
.name
, h
->name
, sizeof(msg
.name
));
703 msg
.header
.opcode
= NNPFS_MSG_INSTALLNODE
;
704 h0
= (struct nnpfs_message_header
*)&msg
;
705 h0_len
= sizeof(msg
);
708 nnpfs_send_message_wakeup_multiple (fd
,
709 h
->header
.sequence_num
,
714 fcache_release(entry
);
716 fcache_release(dentry
);
723 nnpfs_message_getattr (int fd
, struct nnpfs_message_getattr
*h
, u_int size
)
725 struct nnpfs_message_installattr msg
;
728 FCacheEntry
*entry
= NULL
;
729 struct nnpfs_message_header
*h0
= NULL
;
733 fid
= *(VenusFid
*)&h
->handle
;
734 arla_warnx (ADEBMSG
, "getattr (%ld.%lu.%lu.%lu)",
735 (long)fid
.Cell
, (unsigned long)fid
.fid
.Volume
,
736 (unsigned long)fid
.fid
.Vnode
,
737 (unsigned long)fid
.fid
.Unique
);
738 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
741 ret
= fcache_get(&entry
, fid
, ce
);
745 assert_flag(entry
,kernelp
);
748 ret
= cm_getattr(entry
, ce
);
749 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
754 h0
= make_installattr(&msg
, entry
, FCACHE2NNPFSNODE_ALL
);
755 h0_len
= sizeof(msg
);
758 nnpfs_send_message_wakeup_multiple (fd
,
759 h
->header
.sequence_num
,
764 fcache_release(entry
);
771 nnpfs_message_putattr (int fd
, struct nnpfs_message_putattr
*h
, u_int size
)
773 struct nnpfs_message_installattr msg
;
775 AFSStoreStatus status
;
777 struct nnpfs_message_header
*h0
= NULL
;
781 FCacheEntry
*entry
= NULL
;
783 fid
= *(VenusFid
*)&h
->handle
;
784 arla_warnx (ADEBMSG
, "putattr (%ld.%lu.%lu.%lu)",
785 (long)fid
.Cell
, (unsigned long)fid
.fid
.Volume
,
786 (unsigned long)fid
.fid
.Vnode
,
787 (unsigned long)fid
.fid
.Unique
);
788 nnpfs_attr2afsstorestatus(&h
->attr
, &status
);
789 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
792 if (connected_mode
!= CONNECTED
) {
793 entry
= fcache_find(fid
);
799 ret
= fcache_get(&entry
, fid
, ce
);
804 assert_flag(entry
,kernelp
);
806 if (XA_VALID_SIZE(&h
->attr
)) {
807 /* Bits update may fail on old servers, fixed in openafs-1.2.7 */
809 ret
= cm_ftruncate (entry
, h
->attr
.xa_size
, &status
, ce
);
810 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
814 entry
->flags
.appended
= FALSE
;
817 /* XXX this is redundant on XA_VALID_SIZE(&h->attr), right? */
820 ret
= cm_setattr(entry
, &status
, ce
);
821 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
828 ret
= cm_getattr(entry
, ce
);
829 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
835 h0
= make_installattr(&msg
, entry
, FCACHE2NNPFSNODE_ALL
);
836 h0_len
= sizeof(msg
);
837 msg
.flag
= NNPFS_PUTATTR_REPLY
;
839 if (connected_mode
!= CONNECTED
)
840 entry
->disco_id
= disco_store_status(&fid
, &status
, entry
->disco_id
);
843 nnpfs_send_message_wakeup_multiple (fd
,
844 h
->header
.sequence_num
,
849 fcache_release(entry
);
856 nnpfs_message_create (int fd
, struct nnpfs_message_create
*h
, u_int size
)
858 VenusFid parent_fid
, child_fid
;
859 AFSStoreStatus store_status
;
862 struct nnpfs_message_installdata msg1
;
863 struct nnpfs_message_installnode msg2
;
864 struct nnpfs_message_installdata msg3
;
865 struct nnpfs_message_header
*h0
= NULL
;
867 struct nnpfs_message_header
*h1
= NULL
;
869 struct nnpfs_message_header
*h2
= NULL
;
871 FCacheEntry
*dir_entry
= NULL
;
872 FCacheEntry
*child_entry
= NULL
;
874 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
875 arla_warnx (ADEBMSG
, "create (%ld.%lu.%lu.%lu) \"%s\"",
876 (long)parent_fid
.Cell
,
877 (unsigned long)parent_fid
.fid
.Volume
,
878 (unsigned long)parent_fid
.fid
.Vnode
,
879 (unsigned long)parent_fid
.fid
.Unique
, h
->name
);
881 nnpfs_attr2afsstorestatus(&h
->attr
, &store_status
);
882 if (connected_mode
!= CONNECTED
) {
883 if (!(store_status
.Mask
& SS_OWNER
)) {
884 store_status
.Owner
= h
->cred
.uid
;
885 store_status
.Mask
|= SS_OWNER
;
887 if (!(store_status
.Mask
& SS_GROUP
)) {
888 store_status
.Group
= 0;
889 store_status
.Mask
|= SS_GROUP
;
891 if (!(store_status
.Mask
& SS_MODTIME
)) {
894 gettimeofday (&now
, NULL
);
896 store_status
.ClientModTime
= now
.tv_sec
;
897 store_status
.Mask
|= SS_MODTIME
;
900 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
903 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
907 assert_flag(dir_entry
,kernelp
);
910 ret
= cm_create(&dir_entry
, h
->name
, &store_status
,
912 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
917 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
921 ret
= conv_dir(dir_entry
, ce
, 0);
925 /* XXX remove this, we don't want to fetch data from the fileserver
926 ret = message_get_data (&child_entry, &h->cred, &ce, 0); */
927 ret
= fcache_verify_attr (child_entry
, dir_entry
, h
->name
, ce
); /* better? */
931 child_fid
= child_entry
->fid
;
933 assert_flag(dir_entry
,kernelp
);
934 assert_flag(dir_entry
,attrusedp
);
936 h0
= make_installdata(&msg1
, dir_entry
, 0, 0);
937 h0_len
= sizeof(msg1
);
939 fcacheentry2nnpfsnode (&child_fid
, &child_fid
,
940 &child_entry
->status
, &msg2
.node
, dir_entry
->acccache
,
941 FCACHE2NNPFSNODE_ALL
);
943 fcache_node_setkernelp(child_entry
, TRUE
);
945 child_entry
->tokens
|= NNPFS_ATTR_R
| NNPFS_DATA_R
| NNPFS_DATA_W
;
946 msg2
.node
.tokens
= child_entry
->tokens
& ~(NNPFS_DATA_MASK
);
947 child_entry
->flags
.attrusedp
= TRUE
;
948 child_entry
->flags
.datausedp
= TRUE
;
950 msg2
.parent_handle
= h
->parent_handle
;
951 strlcpy (msg2
.name
, h
->name
, sizeof(msg2
.name
));
953 msg2
.header
.opcode
= NNPFS_MSG_INSTALLNODE
;
954 h1
= (struct nnpfs_message_header
*)&msg2
;
955 h1_len
= sizeof(msg2
);
957 /* msg3.node = msg2.node; */
959 h2
= make_installdata(&msg3
, child_entry
, 0, 0);
960 h2_len
= sizeof(msg3
);
962 if (connected_mode
!= CONNECTED
)
963 child_entry
->disco_id
= disco_create_file(&parent_fid
, &child_fid
,
964 h
->name
, &store_status
);
967 nnpfs_send_message_wakeup_multiple (fd
,
968 h
->header
.sequence_num
,
975 fcache_release(dir_entry
);
977 fcache_release(child_entry
);
984 nnpfs_message_mkdir (int fd
, struct nnpfs_message_mkdir
*h
, u_int size
)
986 VenusFid parent_fid
, child_fid
;
987 AFSStoreStatus store_status
;
988 AFSFetchStatus fetch_status
;
991 struct nnpfs_message_installdata msg1
;
992 struct nnpfs_message_installnode msg2
;
993 struct nnpfs_message_installdata msg3
;
994 FCacheEntry
*dir_entry
= NULL
;
995 FCacheEntry
*child_entry
= NULL
;
997 struct nnpfs_message_header
*h0
= NULL
;
999 struct nnpfs_message_header
*h1
= NULL
;
1001 struct nnpfs_message_header
*h2
= NULL
;
1005 parent_fid
= *fid_translate((VenusFid
*)&h
->parent_handle
);
1007 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
1009 arla_warnx (ADEBMSG
, "mkdir (%ld.%lu.%lu.%lu) \"%s\"",
1010 (long)parent_fid
.Cell
, (unsigned long)parent_fid
.fid
.Volume
,
1011 (unsigned long)parent_fid
.fid
.Vnode
,
1012 (unsigned long)parent_fid
.fid
.Unique
, h
->name
);
1014 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1015 assert (ce
!= NULL
);
1017 nnpfs_attr2afsstorestatus(&h
->attr
, &store_status
);
1018 if (connected_mode
!= CONNECTED
) {
1019 if (!(store_status
.Mask
& SS_OWNER
)) {
1020 store_status
.Owner
= h
->cred
.uid
;
1021 store_status
.Mask
|= SS_OWNER
;
1023 if (!(store_status
.Mask
& SS_MODTIME
)) {
1026 gettimeofday (&now
, NULL
);
1028 store_status
.ClientModTime
= now
.tv_sec
;
1029 store_status
.Mask
|= SS_MODTIME
;
1033 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
1037 assert_flag(dir_entry
,kernelp
);
1040 ret
= cm_mkdir(&dir_entry
, h
->name
, &store_status
,
1041 &child_fid
, &fetch_status
, &ce
);
1042 } while(try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1047 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
1051 ret
= conv_dir(dir_entry
, ce
, 0);
1055 assert_flag(dir_entry
,kernelp
);
1056 assert_flag(dir_entry
,attrusedp
);
1058 h0
= make_installdata(&msg1
, dir_entry
, 0, 0);
1059 h0_len
= sizeof(msg1
);
1061 ret
= fcache_get(&child_entry
, child_fid
, ce
);
1064 ret
= message_get_data (&child_entry
, &h
->cred
, &ce
, 0);
1068 child_fid
= child_entry
->fid
;
1070 ret
= conv_dir(child_entry
, ce
, 0);
1074 fcache_node_setkernelp(child_entry
, TRUE
);
1075 child_entry
->flags
.attrusedp
= TRUE
;
1076 child_entry
->flags
.datausedp
= TRUE
;
1077 child_entry
->tokens
|= NNPFS_ATTR_R
;
1078 msg2
.node
.tokens
= child_entry
->tokens
& ~(NNPFS_DATA_MASK
);
1080 fcacheentry2nnpfsnode (&child_fid
, &child_fid
,
1081 &child_entry
->status
, &msg2
.node
,
1082 dir_entry
->acccache
,
1083 FCACHE2NNPFSNODE_ALL
);
1085 msg2
.parent_handle
= h
->parent_handle
;
1086 strlcpy (msg2
.name
, h
->name
, sizeof(msg2
.name
));
1088 msg2
.header
.opcode
= NNPFS_MSG_INSTALLNODE
;
1089 h1
= (struct nnpfs_message_header
*)&msg2
;
1090 h1_len
= sizeof(msg2
);
1092 /* msg3.node = msg2.node; */
1094 h2
= make_installdata(&msg3
, child_entry
, 0, 0);
1095 h2_len
= sizeof(msg3
);
1097 if (connected_mode
!= CONNECTED
)
1098 child_entry
->disco_id
= disco_create_dir(&parent_fid
, &child_fid
,
1099 h
->name
, &store_status
);
1102 nnpfs_send_message_wakeup_multiple (fd
,
1103 h
->header
.sequence_num
,
1110 fcache_release(child_entry
);
1112 fcache_release(dir_entry
);
1119 nnpfs_message_link (int fd
, struct nnpfs_message_link
*h
, u_int size
)
1121 VenusFid parent_fid
, existing_fid
;
1124 struct nnpfs_message_installdata msg1
;
1125 struct nnpfs_message_installnode msg2
;
1126 struct nnpfs_message_header
*h0
= NULL
;
1128 struct nnpfs_message_header
*h1
= NULL
;
1130 FCacheEntry
*dir_entry
= NULL
;
1131 FCacheEntry
*child_entry
= NULL
;
1133 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
1134 existing_fid
= *(VenusFid
*)&h
->from_handle
;
1135 arla_warnx (ADEBMSG
, "link (%ld.%lu.%lu.%lu) (%ld.%lu.%lu.%lu) \"%s\"",
1136 (long)parent_fid
.Cell
, (unsigned long)parent_fid
.fid
.Volume
,
1137 (unsigned long)parent_fid
.fid
.Vnode
,
1138 (unsigned long)parent_fid
.fid
.Unique
,
1139 (long)existing_fid
.Cell
,
1140 (unsigned long)existing_fid
.fid
.Volume
,
1141 (unsigned long)existing_fid
.fid
.Vnode
,
1142 (unsigned long)existing_fid
.fid
.Unique
,
1145 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1146 assert (ce
!= NULL
);
1148 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
1152 ret
= fcache_get(&child_entry
, existing_fid
, ce
);
1156 assert_flag(dir_entry
,kernelp
);
1157 assert_flag(child_entry
,kernelp
);
1160 ret
= cm_link(&dir_entry
, h
->name
, child_entry
, &ce
);
1161 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1166 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
1170 ret
= conv_dir(dir_entry
, ce
, 0);
1174 assert_flag(dir_entry
,kernelp
);
1175 assert_flag(dir_entry
,attrusedp
);
1177 h0
= make_installdata(&msg1
, dir_entry
, 0, 0);
1178 h0_len
= sizeof(msg1
);
1180 fcacheentry2nnpfsnode(&existing_fid
, &existing_fid
, /* &child_entry->fid ? */
1181 &child_entry
->status
, &msg2
.node
,
1182 child_entry
->acccache
,
1183 FCACHE2NNPFSNODE_ALL
);
1185 child_entry
->flags
.attrp
= TRUE
;
1186 child_entry
->tokens
|= NNPFS_ATTR_R
;
1188 msg2
.node
.tokens
= child_entry
->tokens
;
1189 msg2
.parent_handle
= h
->parent_handle
;
1190 strlcpy (msg2
.name
, h
->name
, sizeof(msg2
.name
));
1192 msg2
.header
.opcode
= NNPFS_MSG_INSTALLNODE
;
1193 h1
= (struct nnpfs_message_header
*)&msg2
;
1194 h1_len
= sizeof(msg2
);
1197 nnpfs_send_message_wakeup_multiple (fd
,
1198 h
->header
.sequence_num
,
1204 fcache_release(dir_entry
);
1206 fcache_release(child_entry
);
1213 nnpfs_message_symlink (int fd
, struct nnpfs_message_symlink
*h
, u_int size
)
1215 VenusFid parent_fid
, child_fid
, real_fid
;
1216 AFSStoreStatus store_status
;
1217 AFSFetchStatus fetch_status
;
1221 struct nnpfs_message_installdata msg1
;
1222 struct nnpfs_message_installnode msg2
;
1223 struct nnpfs_message_header
*h0
= NULL
;
1225 struct nnpfs_message_header
*h1
= NULL
;
1227 FCacheEntry
*dir_entry
= NULL
;
1229 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
1230 arla_warnx (ADEBMSG
, "symlink (%ld.%lu.%lu.%lu) \"%s\"",
1231 (long)parent_fid
.Cell
, (unsigned long)parent_fid
.fid
.Volume
,
1232 (unsigned long)parent_fid
.fid
.Vnode
,
1233 (unsigned long)parent_fid
.fid
.Unique
, h
->name
);
1235 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1236 assert (ce
!= NULL
);
1238 nnpfs_attr2afsstorestatus(&h
->attr
, &store_status
);
1240 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
1244 assert_flag(dir_entry
,kernelp
);
1247 ret
= cm_symlink(&dir_entry
, h
->name
, &store_status
,
1248 &child_fid
, &real_fid
,
1251 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1254 ce
= cred_get (dir_entry
->fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1255 assert (ce
!= NULL
);
1258 * Mountpoints can be created even when the target volume doesn't
1259 * exist, and other things may happen. Always update the directory
1260 * just to be on the safe side.
1264 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
1268 ret
= conv_dir(dir_entry
, ce
, 0);
1272 assert_flag(dir_entry
,kernelp
);
1273 assert_flag(dir_entry
,attrusedp
);
1275 h0
= make_installdata(&msg1
, dir_entry
, 0, 0);
1276 h0_len
= sizeof(msg1
);
1283 fcacheentry2nnpfsnode (&child_fid
, &real_fid
,
1284 &fetch_status
, &msg2
.node
,
1285 dir_entry
->acccache
,
1286 FCACHE2NNPFSNODE_ALL
);
1288 msg2
.node
.tokens
= NNPFS_ATTR_R
; /* XXX */
1289 msg2
.parent_handle
= h
->parent_handle
;
1290 strlcpy (msg2
.name
, h
->name
, sizeof(msg2
.name
));
1292 msg2
.header
.opcode
= NNPFS_MSG_INSTALLNODE
;
1293 h1
= (struct nnpfs_message_header
*)&msg2
;
1294 h1_len
= sizeof(msg2
);
1297 nnpfs_send_message_wakeup_multiple (fd
,
1298 h
->header
.sequence_num
,
1304 fcache_release(dir_entry
);
1311 * Handle the NNPFS remove message in `h', that is, remove name
1312 * `h->name' in directory `h->parent' with the creds from `h->cred'.
1316 nnpfs_message_remove (int fd
, struct nnpfs_message_remove
*h
, u_int size
)
1318 VenusFid parent_fid
;
1322 struct nnpfs_message_installdata msg1
;
1323 struct nnpfs_message_installattr msg2
;
1324 struct nnpfs_message_header
*h0
= NULL
;
1326 struct nnpfs_message_header
*h1
= NULL
;
1328 FCacheEntry
*limbo_entry
= NULL
;
1329 FCacheEntry
*dir_entry
= NULL
;
1331 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
1332 arla_warnx (ADEBMSG
, "remove (%ld.%lu.%lu.%lu) \"%s\"",
1333 (long)parent_fid
.Cell
, (unsigned long)parent_fid
.fid
.Volume
,
1334 (unsigned long)parent_fid
.fid
.Vnode
,
1335 (unsigned long)parent_fid
.fid
.Unique
, h
->name
);
1337 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1338 assert (ce
!= NULL
);
1340 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
1344 assert_flag(dir_entry
,kernelp
);
1347 ret
= cm_lookup (&dir_entry
, h
->name
, &fid
, &ce
, FALSE
);
1348 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1354 * Fetch the linkcount of the to be removed node
1357 ret
= fcache_get (&limbo_entry
, fid
, ce
);
1361 ret
= fcache_verify_attr (limbo_entry
, dir_entry
, h
->name
, ce
);
1366 * Do the actual work
1370 ret
= cm_remove(&dir_entry
, h
->name
, &limbo_entry
, &ce
);
1371 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1376 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
1380 if (!dir_entry
->flags
.extradirp
1381 || dir_remove_name (dir_entry
, h
->name
)) {
1382 ret
= conv_dir(dir_entry
, ce
, 0);
1387 assert(dir_entry
->flags
.attrusedp
);
1389 h0
= make_installdata(&msg1
, dir_entry
, 0, NNPFS_ID_INVALID_DNLC
);
1390 h0_len
= sizeof(msg1
);
1393 * Make sure that if the removed node is in the kernel it has the
1394 * right linkcount since some might hold a reference to it.
1397 if (limbo_entry
->flags
.kernelp
) {
1399 * Now insert the limbo entry to get right linkcount
1401 h1
= make_installattr(&msg2
, limbo_entry
, FCACHE2NNPFSNODE_ALL
);
1402 h1_len
= sizeof(msg2
);
1406 nnpfs_send_message_wakeup_multiple (fd
,
1407 h
->header
.sequence_num
,
1413 fcache_release(dir_entry
);
1415 fcache_release (limbo_entry
);
1422 nnpfs_message_rmdir (int fd
, struct nnpfs_message_rmdir
*h
, u_int size
)
1424 VenusFid parent_fid
, fid
;
1427 struct nnpfs_message_installdata msg0
;
1428 struct nnpfs_message_header
*h0
= NULL
;
1430 struct nnpfs_message_installattr msg1
;
1431 struct nnpfs_message_header
*h1
= NULL
;
1433 FCacheEntry
*limbo_entry
= NULL
;
1434 FCacheEntry
*dir_entry
= NULL
;
1436 parent_fid
= *(VenusFid
*)&h
->parent_handle
;
1437 arla_warnx (ADEBMSG
, "rmdir (%ld.%lu.%lu.%lu) \"%s\"",
1438 (long)parent_fid
.Cell
, (unsigned long)parent_fid
.fid
.Volume
,
1439 (unsigned long)parent_fid
.fid
.Vnode
,
1440 (unsigned long)parent_fid
.fid
.Unique
, h
->name
);
1442 ce
= cred_get (parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1443 assert (ce
!= NULL
);
1446 * Fetch the child-entry fid.
1449 ret
= fcache_get(&dir_entry
, parent_fid
, ce
);
1453 assert_flag(dir_entry
,kernelp
);
1456 ret
= cm_lookup (&dir_entry
, h
->name
, &fid
, &ce
, FALSE
);
1457 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1462 if (VenusFid_cmp(&dir_entry
->fid
, &fid
) == 0) {
1468 * Need to get linkcount for silly rename.
1471 ret
= fcache_get (&limbo_entry
, fid
, ce
);
1475 ret
= fcache_verify_attr (limbo_entry
, dir_entry
, h
->name
, ce
);
1480 * Do the actual work
1484 ret
= cm_rmdir(&dir_entry
, h
->name
, &limbo_entry
, &ce
);
1485 } while (try_again (&ret
, &ce
, &h
->cred
, &dir_entry
->fid
));
1490 ret
= message_get_data (&dir_entry
, &h
->cred
, &ce
, 0);
1494 if (!dir_entry
->flags
.extradirp
1495 || dir_remove_name (dir_entry
, h
->name
)) {
1496 ret
= conv_dir(dir_entry
, ce
, 0);
1501 h0
= make_installdata(&msg0
, dir_entry
, 0, NNPFS_ID_INVALID_DNLC
);
1502 h0_len
= sizeof(msg0
);
1504 if (limbo_entry
->flags
.kernelp
) {
1505 h1
= make_installattr(&msg1
, limbo_entry
, FCACHE2NNPFSNODE_ALL
);
1506 h1_len
= sizeof(msg1
);
1508 assert_flag(dir_entry
,kernelp
);
1509 assert_flag(dir_entry
,attrusedp
);
1512 nnpfs_send_message_wakeup_multiple (fd
,
1513 h
->header
.sequence_num
,
1519 fcache_release(dir_entry
);
1521 fcache_release (limbo_entry
);
1529 nnpfs_message_rename (int fd
, struct nnpfs_message_rename
*h
, u_int size
)
1531 VenusFid old_parent_fid
;
1532 VenusFid new_parent_fid
;
1535 CredCacheEntry
*ce2
;
1537 struct nnpfs_message_installdata msg1
;
1538 struct nnpfs_message_installdata msg2
;
1539 struct nnpfs_message_installdata msg3
;
1540 struct nnpfs_message_header
*h0
= NULL
;
1542 struct nnpfs_message_header
*h1
= NULL
;
1544 struct nnpfs_message_header
*h2
= NULL
;
1546 FCacheEntry
*old_entry
= NULL
;
1547 FCacheEntry
*new_entry
= NULL
;
1548 FCacheEntry
*child_entry
= NULL
;
1549 int update_child
= 0;
1552 old_parent_fid
= *(VenusFid
*)&h
->old_parent_handle
;
1553 new_parent_fid
= *(VenusFid
*)&h
->new_parent_handle
;
1554 arla_warnx (ADEBMSG
,
1555 "rename (%ld.%lu.%lu.%lu) (%ld.%lu.%lu.%lu) \"%s\" \"%s\"",
1556 (long)old_parent_fid
.Cell
,
1557 (unsigned long)old_parent_fid
.fid
.Volume
,
1558 (unsigned long)old_parent_fid
.fid
.Vnode
,
1559 (unsigned long)old_parent_fid
.fid
.Unique
,
1560 (long)new_parent_fid
.Cell
,
1561 (unsigned long)new_parent_fid
.fid
.Volume
,
1562 (unsigned long)new_parent_fid
.fid
.Vnode
,
1563 (unsigned long)new_parent_fid
.fid
.Unique
,
1567 ce
= cred_get (old_parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1568 assert (ce
!= NULL
);
1570 if (new_parent_fid
.Cell
== old_parent_fid
.Cell
) {
1574 ce2
= cred_get(new_parent_fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1578 diff_dir
= VenusFid_cmp (&old_parent_fid
, &new_parent_fid
);
1580 ret
= fcache_get(&old_entry
, old_parent_fid
, ce
);
1584 assert_flag(old_entry
,kernelp
);
1587 ret
= fcache_get(&new_entry
, new_parent_fid
, ce2
);
1591 new_entry
= old_entry
;
1595 assert_flag(new_entry
,kernelp
);
1598 ret
= cm_rename(&old_entry
, h
->old_name
,
1599 &new_entry
, h
->new_name
,
1600 &child_fid
, &update_child
, &ce
, &ce2
);
1601 } while (try_again_crosscell(&ret
, &ce
, &ce2
, &h
->cred
, &old_entry
->fid
));
1606 ret
= message_get_data (&old_entry
, &h
->cred
, &ce
, 0);
1610 if (!old_entry
->flags
.extradirp
1611 || dir_remove_name (old_entry
, h
->old_name
)) {
1612 ret
= conv_dir(old_entry
, ce
, 0);
1617 assert_flag(old_entry
,kernelp
);
1618 assert_flag(old_entry
,attrusedp
);
1620 h0
= make_installdata(&msg1
, old_entry
, 0, NNPFS_ID_INVALID_DNLC
);
1621 h0_len
= sizeof(msg1
);
1623 ret
= fcache_get_data (&new_entry
, &ce2
, 0, 0); /* XXX - fake_mp? */
1627 ret
= conv_dir(new_entry
, ce2
, 0);
1631 assert_flag(new_entry
,kernelp
);
1632 assert_flag(new_entry
,attrusedp
);
1634 h1
= make_installdata(&msg2
, new_entry
, 0, NNPFS_ID_INVALID_DNLC
);
1635 h1_len
= sizeof(msg2
);
1638 ret
= fcache_get(&child_entry
, child_fid
, ce2
);
1641 ret
= message_get_data (&child_entry
, &h
->cred
, &ce2
, 0);
1643 fcache_release(child_entry
);
1646 child_fid
= child_entry
->fid
;
1648 ret
= conv_dir(child_entry
, ce2
, 0);
1652 h2
= make_installdata(&msg3
, child_entry
, 0, NNPFS_ID_INVALID_DNLC
);
1653 h2_len
= sizeof(msg3
);
1657 nnpfs_send_message_wakeup_multiple (fd
,
1658 h
->header
.sequence_num
,
1663 if (old_entry
) fcache_release(old_entry
);
1664 if (new_entry
&& diff_dir
) fcache_release(new_entry
);
1665 if (child_entry
) fcache_release(child_entry
);
1674 nnpfs_message_putdata (int fd
, struct nnpfs_message_putdata
*h
, u_int size
)
1679 AFSStoreStatus status
;
1680 FCacheEntry
*entry
= NULL
;
1683 worker_setdebuginfo("message putdata");
1685 if (h
->flag
& NNPFS_GC
)
1686 fcache_cleaner_ref();
1688 fid
= *(VenusFid
*)&h
->handle
;
1689 arla_warnx (ADEBMSG
, "putdata (%ld.%lu.%lu.%lu)",
1690 (long)fid
.Cell
, (unsigned long)fid
.fid
.Volume
,
1691 (unsigned long)fid
.fid
.Vnode
,
1692 (unsigned long)fid
.fid
.Unique
);
1694 nnpfs_attr2afsstorestatus(&h
->attr
, &status
);
1696 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1697 assert (ce
!= NULL
);
1699 if (connected_mode
!= CONNECTED
) {
1700 entry
= fcache_find(fid
); /* XXX gcp? */
1706 if (h
->flag
& NNPFS_GC
)
1707 ret
= fcache_get_gc(&entry
, fid
, ce
);
1709 ret
= fcache_get(&entry
, fid
, ce
);
1714 assert_flag(entry
,kernelp
);
1715 assert(XA_VALID_SIZE(&h
->attr
));
1716 assert(h
->attr
.xa_size
>= h
->offset
);
1718 len
= h
->attr
.xa_size
;
1720 if (fcache_get_status_length(&entry
->status
) < len
)
1721 fcache_set_status_length(&entry
->status
, len
);
1723 end
= h
->offset
+ h
->len
;
1727 worker_setdebuginfo("putdata have");
1729 /* XXX this is not a good place to be picky about cache usage */
1730 ret
= fcache_set_have(entry
, h
->offset
, end
);
1732 arla_warn(ADEBMSG
, ret
, "nnpfs_message_putdata: set_have");
1737 worker_setdebuginfo("putdata write");
1740 ret
= cm_write(entry
, h
->flag
, h
->offset
, h
->len
, &status
, ce
);
1741 } while (try_again (&ret
, &ce
, &h
->cred
, &fid
));
1744 arla_warn (ADEBMSG
, ret
, "nnpfs_message_putdata: cm_write");
1748 entry
->flags
.appended
= FALSE
;
1750 if (connected_mode
!= CONNECTED
)
1751 entry
->disco_id
= disco_store_data(&fid
, &status
, entry
->disco_id
);
1753 if (h
->flag
& NNPFS_GC
) {
1754 uint64_t blocksize
= fcache_getblocksize();
1756 for (off
= h
->offset
; off
< end
; off
+= blocksize
)
1757 fcache_data_setkernelp(entry
, off
, FALSE
, FALSE
);
1759 /* XXX do this on GC too? */
1761 entry
->flags
.dirtied
= FALSE
;
1762 entry
->flags
.stale
= FALSE
;
1764 /* XXX argh. if this was a partial write we may still have
1770 worker_setdebuginfo("putdata done");
1772 if (h
->flag
& NNPFS_GC
)
1773 fcache_cleaner_deref();
1776 entry
->flags
.dirtied
= TRUE
; /* break_callback(entry); */
1779 fcache_release(entry
);
1781 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ret
);
1786 prefetch_data(FCacheEntry
**e
, CredCacheEntry
**ce
)
1788 #if 0 /* XXX no prefetch for now */
1789 FCacheEntry
*entry
= *e
;
1793 if (entry
->status
.FileType
!= TYPE_FILE
)
1796 /* always leave a few threads for synchronous work */
1797 if (num_prefetches
>= max_prefetches
)
1802 length
= fcache_get_status_length(&entry
->status
);
1804 if (length
> entry
->fetched_length
) {
1807 offset
= entry
->fetched_length
+ stats_prefetch(NULL
, -1);
1808 if (offset
> length
)
1810 arla_warnx (ADEBMSG
, " prefetching to %lu", (unsigned long)offset
);
1811 ret
= fcache_get_data (e
, ce
, 0, offset
);
1812 arla_warnx (ADEBMSG
, " prefetched returned %d", ret
);
1822 nnpfs_message_open (int fd
, struct nnpfs_message_open
*h
, u_int size
)
1824 struct nnpfs_message_installdata msg
;
1825 struct nnpfs_message_header
*h0
;
1826 FCacheEntry
*entry
= NULL
;
1831 fid
= *(VenusFid
*)&h
->handle
;
1832 arla_warnx (ADEBMSG
, "open (%ld.%lu.%lu.%lu)",
1833 (long)fid
.Cell
, (unsigned long)fid
.fid
.Volume
,
1834 (unsigned long)fid
.fid
.Vnode
,
1835 (unsigned long)fid
.fid
.Unique
);
1837 worker_setdebuginfo("message open");
1839 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
1840 assert (ce
!= NULL
);
1842 worker_setdebuginfo("message open fcache_get");
1844 ret
= fcache_get(&entry
, fid
, ce
);
1848 assert_flag(entry
,kernelp
);
1852 worker_setdebuginfo("message open cm_getattr");
1854 ret
= cm_getattr(entry
, ce
);
1856 if (try_again (&ret
, &ce
, &h
->cred
, &fid
))
1861 if (entry
->status
.FileType
== TYPE_DIR
) {
1862 if (h
->tokens
& NNPFS_DATA_W
) {
1867 worker_setdebuginfo("message open fcache_get_data");
1869 ret
= fcache_get_data (&entry
, &ce
, 0,
1870 fcache_get_status_length(&entry
->status
));
1871 if (try_again (&ret
, &ce
, &h
->cred
, &fid
))
1877 ret
= conv_dir(entry
, ce
, h
->tokens
);
1881 entry
->tokens
|= h
->tokens
;
1882 assert_flag(entry
,kernelp
);
1884 h0
= make_installdata(&msg
, entry
, 0, 0);
1886 worker_setdebuginfo("message open cm_open");
1887 ret
= cm_open (entry
, ce
, h
->tokens
);
1888 if (try_again (&ret
, &ce
, &h
->cred
, &fid
))
1893 h0
= make_installdata(&msg
, entry
, NNPFS_NO_OFFSET
, 0);
1896 worker_setdebuginfo("message open wakeup");
1898 nnpfs_send_message_wakeup_multiple (fd
,
1899 h
->header
.sequence_num
,
1904 worker_setdebuginfo("message open prefetching");
1906 prefetch_data(&entry
, &ce
);
1908 fcache_release(entry
);
1915 fcache_release(entry
);
1917 nnpfs_send_message_wakeup_multiple (fd
,
1918 h
->header
.sequence_num
,
1924 #define NUM_INSTALLDATA 10
1927 send_installdata_range(int fd
, FCacheEntry
*node
,
1928 uint64_t offset
, uint64_t end
,
1929 struct nnpfs_message_installdata
*proto
)
1931 struct nnpfs_message_installdata n_msg
[NUM_INSTALLDATA
];
1932 struct nnpfs_message_installdata
*msg
= &n_msg
[0];
1933 uint64_t blocksize
= fcache_getblocksize();
1935 Bool kernelp
= TRUE
;
1941 n
= (end
- offset
- 1) / blocksize
+ 1;
1943 if (n
> NUM_INSTALLDATA
) {
1944 void *tmp
= malloc(n
* sizeof(msg
[0]));
1948 /* oh well, maybe we can add a few at least */
1949 n
= NUM_INSTALLDATA
;
1953 for (i
= 0, off
= offset
; i
< n
; i
++, off
+= blocksize
) {
1955 msg
[i
].offset
= off
;
1957 fcache_data_setbusy(node
, offset
, off
, TRUE
);
1959 if (node
->flags
.appended
) {
1960 uint64_t length
= fcache_get_status_length(&node
->status
);
1961 uint64_t lastoff
= off
- blocksize
;
1962 if (block_end_offset(length
) == lastoff
) {
1963 ret
= abuf_truncate_block(node
, lastoff
, blocksize
);
1965 arla_warn(ADEBWARN
, ret
,
1966 "block truncate failed for (%ld.%lu.%lu.%lu) @%llu",
1967 (long)node
->fid
.Cell
,
1968 (unsigned long)node
->fid
.fid
.Volume
,
1969 (unsigned long)node
->fid
.fid
.Vnode
,
1970 (unsigned long)node
->fid
.fid
.Unique
,
1971 (unsigned long long)lastoff
);
1975 arla_warnx(ADEBMSG
, " sending %llu installdata from %llu to %llu",
1976 (unsigned long long)n
,
1977 (unsigned long long)offset
, (unsigned long long)end
);
1980 ret
= nnpfs_send_message_multiple_list(fd
,
1981 (struct nnpfs_message_header
*)msg
,
1984 if (msg
!= &n_msg
[0])
1990 for (i
= 0, off
= offset
; i
< n
; i
++, off
+= blocksize
)
1991 fcache_data_setkernelp(node
, off
, kernelp
, TRUE
);
1997 nnpfs_message_getdata (int fd
, struct nnpfs_message_getdata
*h
, u_int size
)
1999 struct nnpfs_message_installdata msg
;
2003 uint64_t offset
, end
, length
;
2004 FCacheEntry
*entry
= NULL
;
2006 worker_setdebuginfo("message getdata");
2008 fid
= *(VenusFid
*)&h
->handle
;
2009 arla_warnx (ADEBMSG
, "getdata (%ld.%lu.%lu.%lu)",
2010 (long)fid
.Cell
, (unsigned long)fid
.fid
.Volume
,
2011 (unsigned long)fid
.fid
.Vnode
,
2012 (unsigned long)fid
.fid
.Unique
);
2014 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2015 assert (ce
!= NULL
);
2017 ret
= fcache_get(&entry
, fid
, ce
);
2021 assert_flag(entry
,kernelp
);
2025 worker_setdebuginfo("getdata getattr");
2027 ret
= cm_getattr(entry
, ce
);
2029 if (try_again (&ret
, &ce
, &h
->cred
, &fid
))
2034 length
= fcache_get_status_length(&entry
->status
);
2038 assert(offset
% fcache_getblocksize() == 0);
2039 assert(offset
< length
|| (offset
== length
&& length
== 0));
2041 if (entry
->status
.FileType
== TYPE_DIR
) {
2044 end
= block_next_offset(h
->offset
+ h
->len
);
2049 /* The first block is always there. */
2051 ret
= fcache_set_have(entry
, end
, end
);
2053 arla_warn(ADEBMSG
, ret
, "nnpfs_message_getdata: set_have");
2058 arla_warnx (ADEBMSG
, " requested block at %lu fetching to byte %lu",
2059 (unsigned long)h
->offset
, (unsigned long)end
);
2061 worker_setdebuginfo("getdata getdata");
2063 ret
= fcache_get_data(&entry
, &ce
, offset
, end
);
2064 if (try_again (&ret
, &ce
, &h
->cred
, &fid
))
2069 worker_setdebuginfo("getdata done");
2071 if (entry
->status
.FileType
== TYPE_DIR
) {
2072 ret
= conv_dir(entry
, ce
, h
->tokens
);
2076 msg
.flag
= NNPFS_ID_INVALID_DNLC
; /* paranoia */
2080 if (h
->tokens
& NNPFS_DATA_W
)
2081 entry
->tokens
|= NNPFS_DATA_W
;
2082 arla_warnx (ADEBMSG
, " got %lu", (unsigned long)end
);
2084 make_installdata(&msg
, entry
, NNPFS_NO_OFFSET
, 0);
2086 send_installdata_range(fd
, entry
, offset
, end
, &msg
);
2087 nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, ret
);
2089 prefetch_data(&entry
, &ce
);
2091 fcache_release(entry
);
2097 fcache_release(entry
);
2099 nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, ret
);
2105 * Send a invalid node to the kernel to invalidate `entry'
2106 * and record that it's not being used in the kernel.
2110 break_callback (FCacheEntry
*entry
)
2112 struct nnpfs_message_invalidnode msg
;
2113 enum { CALLBACK_BREAK_WARN
= 100 };
2114 static int failed_callbacks_break
= 0;
2117 assert_flag(entry
,kernelp
);
2120 * Throw away tokens for all directories and unused entries.
2121 * needs to be same as NNPFS_MSG_INVALIDNODE processing in
2124 if (entry
->status
.FileType
== TYPE_DIR
|| !entry
->flags
.datausedp
)
2127 msg
.header
.opcode
= NNPFS_MSG_INVALIDNODE
;
2128 memcpy (&msg
.handle
, &entry
->fid
, sizeof(entry
->fid
));
2129 ret
= nnpfs_message_send (kernel_fd
, (struct nnpfs_message_header
*)&msg
,
2131 if (ret
== EISDIR
) {
2133 * Ignore EISDIR for invalidnode since that means that a
2134 * message is on route to arlad to tell it the node is on the
2135 * way out from the cache.
2138 arla_warnx (ADEBMSG
, "break_callback: (%ld.%lu.%lu.%lu) failed",
2139 (long)entry
->fid
.Cell
,
2140 (unsigned long)entry
->fid
.fid
.Volume
,
2141 (unsigned long)entry
->fid
.fid
.Vnode
,
2142 (unsigned long)entry
->fid
.fid
.Unique
);
2143 ++failed_callbacks_break
;
2144 if (failed_callbacks_break
> CALLBACK_BREAK_WARN
) {
2145 arla_warnx (ADEBWARN
, "break_callback: have failed %d times",
2146 failed_callbacks_break
);
2147 failed_callbacks_break
= 0;
2153 * Send an unsolicited install-attr for the node in `e'
2157 install_attr (FCacheEntry
*e
, int flags
)
2159 struct nnpfs_message_installattr msg
;
2160 struct nnpfs_message_header
*h
;
2162 memset (&msg
, 0, sizeof(msg
));
2163 h
= make_installattr(&msg
, e
, flags
);
2165 nnpfs_message_send(kernel_fd
, h
, sizeof(msg
));
2169 update_fid(VenusFid oldfid
, FCacheEntry
*old_entry
,
2170 VenusFid newfid
, FCacheEntry
*new_entry
)
2172 struct nnpfs_message_updatefid msg
;
2174 msg
.header
.opcode
= NNPFS_MSG_UPDATEFID
;
2175 memcpy (&msg
.old_handle
, &oldfid
, sizeof(oldfid
));
2176 memcpy (&msg
.new_handle
, &newfid
, sizeof(newfid
));
2177 nnpfs_message_send (kernel_fd
, (struct nnpfs_message_header
*)&msg
,
2179 if (new_entry
!= NULL
) {
2180 fcache_node_setkernelp(new_entry
, TRUE
);
2181 new_entry
->flags
.attrusedp
= TRUE
;
2183 if (old_entry
!= NULL
) {
2184 fcache_node_setkernelp(old_entry
, FALSE
);
2185 old_entry
->flags
.attrusedp
= FALSE
;
2186 old_entry
->flags
.datausedp
= FALSE
;
2187 old_entry
->tokens
&= ~NNPFS_DATA_MASK
;
2192 * Currently kernel never sends inactivenode w/o NNPFS_DELETE set, and
2193 * we don't handle that case properly (it's ignored).
2197 nnpfs_message_inactivenode (int fd
, struct nnpfs_message_inactivenode
*h
,
2203 if (h
->flag
& NNPFS_DELETE
)
2204 fcache_cleaner_ref();
2206 fid
= (VenusFid
*)&h
->handle
;
2207 arla_warnx (ADEBMSG
, "inactivenode (%ld.%lu.%lu.%lu)",
2208 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2209 (unsigned long)fid
->fid
.Vnode
,
2210 (unsigned long)fid
->fid
.Unique
);
2212 entry
= fcache_find(*fid
);
2214 arla_warnx (ADEBWARN
, "nnpfs_message_inactivenode: node not found "
2215 "(%ld.%lu.%lu.%lu)",
2216 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2217 (unsigned long)fid
->fid
.Vnode
,
2218 (unsigned long)fid
->fid
.Unique
);
2222 /* non-delete messages may arrive out of order w/ no harm */
2223 if ((h
->flag
& NNPFS_DELETE
) == 0 && entry
->flags
.kernelp
== 0)
2226 assert_flag(entry
,kernelp
);
2228 if (h
->flag
& NNPFS_DELETE
) {
2229 struct nnpfs_message_delete_node msg
;
2231 fcache_node_setkernelp(entry
, FALSE
);
2233 msg
.handle
= h
->handle
;
2234 msg
.header
.opcode
= NNPFS_MSG_DELETE_NODE
;
2235 nnpfs_message_send (kernel_fd
,
2236 (struct nnpfs_message_header
*)&msg
,
2238 fcache_unused(entry
);
2242 if (h
->flag
& NNPFS_DELETE
)
2243 fcache_cleaner_deref();
2246 fcache_release(entry
);
2252 install_appendquota(int64_t diff
)
2254 struct nnpfs_message_installquota msg
;
2257 msg
.header
.opcode
= NNPFS_MSG_INSTALLQUOTA
;
2258 msg
.appendbytes
= diff
;
2260 ret
= nnpfs_message_send(kernel_fd
, &msg
.header
, sizeof(msg
));
2262 arla_warnx(ADEBWARN
, "install_appendquota returned %d", ret
);
2268 set_data_kernelp(VenusFid
*fid
, uint64_t offset
, Bool kernelp
)
2274 worker_setdebuginfo("setkernelp find");
2275 entry
= fcache_find(*fid
);
2277 worker_setdebuginfo("unsetkernelp find");
2278 entry
= fcache_find_gcp(*fid
, TRUE
);
2282 arla_warnx(ADEBWARN
, "set_data_kernelp: node not found "
2283 "(%ld.%lu.%lu.%lu)",
2284 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2285 (unsigned long)fid
->fid
.Vnode
,
2286 (unsigned long)fid
->fid
.Unique
);
2290 /* messages may arrive out of order? */
2291 if (entry
->flags
.kernelp
) {
2293 Bool exists
= fcache_block_exists(entry
, offset
);
2295 arla_warnx(ADEBWARN
, "set_data_kernelp: append on existing block"
2296 "(%ld.%lu.%lu.%lu)@%llu",
2297 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2298 (unsigned long)fid
->fid
.Vnode
,
2299 (unsigned long)fid
->fid
.Unique
,
2300 (unsigned long long)offset
);
2302 worker_setdebuginfo("setkernelp");
2303 fcache_data_setkernelp(entry
, offset
, kernelp
, FALSE
);
2304 ret
= install_appendquota(fcache_getblocksize());
2306 ret
= fcache_append_block(entry
, offset
);
2308 arla_warnx(ADEBWARN
, "set_data_kernelp: "
2309 "create (%ld.%lu.%lu.%lu)@%llu returned %d",
2310 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2311 (unsigned long)fid
->fid
.Vnode
,
2312 (unsigned long)fid
->fid
.Unique
,
2313 (unsigned long long)offset
,
2316 ret
= fcache_update_appendquota(entry
);
2318 entry
->flags
.appended
= TRUE
;
2321 worker_setdebuginfo("setkernelp");
2322 fcache_data_setkernelp(entry
, offset
, kernelp
, FALSE
);
2325 arla_warnx(ADEBWARN
, "set_data_kernelp: node not in kernel "
2326 "(%ld.%lu.%lu.%lu)",
2327 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2328 (unsigned long)fid
->fid
.Vnode
,
2329 (unsigned long)fid
->fid
.Unique
);
2332 worker_setdebuginfo("release");
2333 fcache_release(entry
);
2338 nnpfs_message_appenddata(int fd
,struct nnpfs_message_appenddata
*h
, u_int size
)
2340 VenusFid
*fid
= (VenusFid
*)&h
->handle
;
2342 arla_warnx(ADEBMSG
, "nnpfs_message_appenddata (%ld.%lu.%lu.%lu), offset %llu",
2343 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2344 (unsigned long)fid
->fid
.Vnode
,
2345 (unsigned long)fid
->fid
.Unique
,
2346 (unsigned long long)h
->offset
);
2348 set_data_kernelp(fid
, h
->offset
, TRUE
);
2354 * Block has been dropped from kernel.
2358 nnpfs_message_deletedata (int fd
,struct nnpfs_message_deletedata
*h
, u_int size
)
2360 VenusFid
*fid
= (VenusFid
*)&h
->handle
;
2362 arla_warnx(ADEBMSG
, "nnpfs_message_deletedata (%ld.%lu.%lu.%lu), offset %llu",
2363 (long)fid
->Cell
, (unsigned long)fid
->fid
.Volume
,
2364 (unsigned long)fid
->fid
.Vnode
,
2365 (unsigned long)fid
->fid
.Unique
,
2366 (unsigned long long)h
->offset
);
2368 fcache_cleaner_ref();
2369 set_data_kernelp(fid
, h
->offset
, FALSE
);
2370 fcache_cleaner_deref();
2376 nnpfs_message_accesses (int fd
,struct nnpfs_message_accesses
*h
, u_int size
)
2378 arla_warnx(ADEBWARN
, "accesses not implemented");
2385 * Do we have powers for changing stuff?
2389 all_powerful_p (const nnpfs_cred
*cred
)
2391 return cred
->uid
== 0;
2395 * Flush the contents of a volume
2399 viocflushvolume (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2403 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2406 fid
.Cell
= h
->handle
.a
;
2407 fid
.fid
.Volume
= h
->handle
.b
;
2412 "flushing volume (%d, %u)",
2413 fid
.Cell
, fid
.fid
.Volume
);
2415 fcache_purge_volume(fid
);
2416 volcache_invalidate (fid
.fid
.Volume
, fid
.Cell
);
2421 * Get an ACL for a directory
2425 viocgetacl(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2432 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2433 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2435 fid
.Cell
= h
->handle
.a
;
2436 fid
.fid
.Volume
= h
->handle
.b
;
2437 fid
.fid
.Vnode
= h
->handle
.c
;
2438 fid
.fid
.Unique
= h
->handle
.d
;
2440 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2441 assert (ce
!= NULL
);
2444 error
= getacl (fid
, ce
, &opaque
);
2445 } while (try_again (&error
, &ce
, &h
->cred
, &fid
));
2447 if (error
!= 0 && error
!= EACCES
)
2452 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
2453 opaque
.val
, opaque
.len
);
2460 * Set an ACL for a directory
2464 viocsetacl(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2472 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2473 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2475 if (h
->insize
> AFSOPAQUEMAX
|| h
->insize
== 0)
2476 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2478 opaque
.val
= malloc(h
->insize
);
2479 if(opaque
.val
== NULL
)
2480 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOMEM
);
2482 fid
.Cell
= h
->handle
.a
;
2483 fid
.fid
.Volume
= h
->handle
.b
;
2484 fid
.fid
.Vnode
= h
->handle
.c
;
2485 fid
.fid
.Unique
= h
->handle
.d
;
2487 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2488 assert (ce
!= NULL
);
2490 opaque
.len
= h
->insize
;
2491 memcpy(opaque
.val
, h
->msg
, h
->insize
);
2494 error
= setacl (fid
, ce
, &opaque
, &e
);
2495 } while (try_again (&error
, &ce
, &h
->cred
, &fid
));
2498 install_attr (e
, FCACHE2NNPFSNODE_ALL
);
2500 } else if (error
!= EACCES
)
2506 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
, NULL
, 0);
2515 viocgetvolstat(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2519 AFSFetchVolumeStatus volstat
;
2520 char volumename
[AFSNAMEMAX
];
2521 char offlinemsg
[AFSOPAQUEMAX
];
2522 char motd
[AFSOPAQUEMAX
];
2523 char out
[SYSNAMEMAXLEN
];
2524 int32_t outsize
= 0;
2527 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2528 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2530 fid
.Cell
= h
->handle
.a
;
2531 fid
.fid
.Volume
= h
->handle
.b
;
2535 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2536 assert (ce
!= NULL
);
2538 memset (volumename
, 0, AFSNAMEMAX
);
2539 memset (offlinemsg
, 0, AFSOPAQUEMAX
);
2540 memset (motd
, 0, AFSOPAQUEMAX
);
2541 memset (out
, 0, SYSNAMEMAXLEN
);
2544 error
= getvolstat (fid
, ce
, &volstat
,
2545 volumename
, sizeof(volumename
),
2548 } while (try_again (&error
, &ce
, &h
->cred
, &fid
));
2552 if (error
!= 0 && error
!= EACCES
)
2555 memcpy (out
, (char *) &volstat
, sizeof (AFSFetchVolumeStatus
));
2556 outsize
= sizeof (AFSFetchVolumeStatus
);
2558 if (volumename
[0]) {
2559 strncpy (out
+outsize
, volumename
, AFSNAMEMAX
);
2560 outsize
+= strlen (volumename
);
2567 if (offlinemsg
[0]) {
2568 strncpy (out
+outsize
, offlinemsg
, AFSOPAQUEMAX
);
2569 outsize
+= strlen (offlinemsg
);
2577 strncpy (out
+outsize
, motd
, AFSOPAQUEMAX
);
2578 outsize
+= strlen (motd
);
2585 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
2595 viocsetvolstat(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2599 AFSFetchVolumeStatus
*involstat
;
2600 AFSStoreVolumeStatus outvolstat
;
2601 char volumename
[AFSNAMEMAX
];
2602 char offlinemsg
[AFSOPAQUEMAX
];
2603 char motd
[AFSOPAQUEMAX
];
2607 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2610 fid
.Cell
= h
->handle
.a
;
2611 fid
.fid
.Volume
= h
->handle
.b
;
2615 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2616 assert (ce
!= NULL
);
2618 involstat
= (AFSFetchVolumeStatus
*) h
->msg
;
2619 outvolstat
.Mask
= 0x3; /* Store both the next fields */
2620 outvolstat
.MinQuota
= involstat
->MinQuota
;
2621 outvolstat
.MaxQuota
= involstat
->MaxQuota
;
2623 ptr
= h
->msg
+ sizeof (AFSFetchVolumeStatus
);
2627 strncpy (volumename
, ptr
, AFSNAMEMAX
);
2628 ptr
+= strlen (ptr
);
2631 memset (volumename
, 0, AFSNAMEMAX
);
2632 ptr
++; /* skip 0 character */
2636 strncpy (offlinemsg
, ptr
, AFSOPAQUEMAX
);
2637 ptr
+= strlen (ptr
);
2640 memset (offlinemsg
, 0, AFSOPAQUEMAX
);
2644 strncpy (motd
, ptr
, AFSOPAQUEMAX
);
2646 volumename
[0] = '\0';
2647 offlinemsg
[0] = '\0';
2652 error
= setvolstat (fid
, ce
, &outvolstat
, volumename
,
2654 } while (try_again (&error
, &ce
, &h
->cred
, &fid
));
2656 if (error
!= 0 && error
!= EACCES
)
2661 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
2667 * Get the mount point at (`fid', `filename') using the cred in `ce'
2668 * and returning the fcache entry in `ret_mp_entry'
2669 * Return 0 or an error.
2673 get_mount_point (VenusFid fid
,
2674 const char *filename
,
2675 CredCacheEntry
**ce
,
2676 FCacheEntry
**ret_mp_entry
)
2678 FCacheEntry
*mp_entry
;
2679 FCacheEntry
*dentry
;
2683 if (fid
.fid
.Volume
== 0 && fid
.fid
.Vnode
== 0 && fid
.fid
.Unique
== 0)
2686 error
= fcache_get(&dentry
, fid
, *ce
);
2690 error
= fcache_get_data(&dentry
, ce
, 0, 0);
2692 fcache_release(dentry
);
2696 error
= adir_lookup(dentry
, filename
, &mp_fid
);
2698 fcache_release(dentry
);
2702 if (VenusFid_cmp(&dentry
->fid
, &mp_fid
) == 0) {
2705 error
= fcache_get(&mp_entry
, mp_fid
, *ce
);
2707 fcache_release(dentry
);
2712 error
= fcache_verify_attr (mp_entry
, dentry
, filename
, *ce
);
2713 if (mp_entry
!= dentry
)
2714 fcache_release(dentry
);
2716 fcache_release(mp_entry
);
2720 if ((mp_entry
->status
.FileType
!= TYPE_LINK
2721 && !mp_entry
->flags
.fake_mp
)
2722 || fcache_get_status_length(&mp_entry
->status
) == 0) { /* Is not a mount point */
2723 fcache_release(mp_entry
);
2726 *ret_mp_entry
= mp_entry
;
2731 * Read the contents of the mount point in `mp_entry' into `buf',
2732 * check they look valid and null-terminate.
2733 * Return 0 or an error
2737 read_mount_point (FCacheEntry
**mp_entry
, CredCacheEntry
**ce
,
2738 char *buf
, int buflen
, int *outlen
)
2744 error
= fcache_get_data (mp_entry
, ce
, 0, 0);
2748 error
= fcache_get_fbuf(*mp_entry
, &f
, FBUF_READ
);
2753 if (len
>= buflen
|| len
<= 0) {
2755 arla_warnx(ADEBWARN
, "mountpoint with bad length: %d", len
);
2759 memcpy(buf
, fbuf_buf(&f
), buflen
);
2762 if (buf
[0] != '#' && buf
[0] != '%') /* Is not a mount point */
2766 * To confuse us, the volume is passed up w/o the ending
2767 * dot. It's not even mentioned in the ``VIOC_AFS_STAT_MT_PT''
2771 buf
[len
- 1] = '\0';
2778 * Get info for a mount point.
2782 vioc_afs_stat_mt_pt(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2788 char buf
[MAXPATHLEN
]; /* AFSNAMEMAX would suffice */
2791 fid
.Cell
= h
->handle
.a
;
2792 fid
.fid
.Volume
= h
->handle
.b
;
2793 fid
.fid
.Vnode
= h
->handle
.c
;
2794 fid
.fid
.Unique
= h
->handle
.d
;
2796 h
->msg
[min(h
->insize
, sizeof(h
->msg
)-1)] = '\0';
2798 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2799 assert (ce
!= NULL
);
2801 error
= get_mount_point (fid
, h
->msg
, &ce
, &e
);
2804 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
2807 error
= read_mount_point(&e
, &ce
, buf
, sizeof(buf
), &len
);
2811 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
2814 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
2823 * Handle the VIOC_AFS_DELETE_MT_PT message in `h' by deleting the
2828 vioc_afs_delete_mt_pt(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2833 struct nnpfs_message_remove remove_msg
;
2836 h
->msg
[min(h
->insize
, sizeof(h
->msg
)-1)] = '\0';
2838 fid
.Cell
= h
->handle
.a
;
2839 fid
.fid
.Volume
= h
->handle
.b
;
2840 fid
.fid
.Vnode
= h
->handle
.c
;
2841 fid
.fid
.Unique
= h
->handle
.d
;
2843 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2844 assert (ce
!= NULL
);
2846 error
= get_mount_point (fid
, h
->msg
, &ce
, &entry
);
2849 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
2850 fcache_release(entry
);
2852 remove_msg
.header
= h
->header
;
2853 remove_msg
.header
.size
= sizeof(remove_msg
);
2854 remove_msg
.parent_handle
= h
->handle
;
2855 strlcpy(remove_msg
.name
, h
->msg
, sizeof(remove_msg
.name
));
2856 remove_msg
.cred
= h
->cred
;
2858 return nnpfs_message_remove (fd
, &remove_msg
, sizeof(remove_msg
));
2862 viocwhereis(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2869 int32_t addresses
[8];
2872 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
2873 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2875 fid
.Cell
= h
->handle
.a
;
2876 fid
.fid
.Volume
= h
->handle
.b
;
2877 fid
.fid
.Vnode
= h
->handle
.c
;
2878 fid
.fid
.Unique
= h
->handle
.d
;
2880 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
2881 assert (ce
!= NULL
);
2883 error
= fcache_get(&e
, fid
, ce
);
2886 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
2888 error
= fcache_verify_attr (e
, NULL
, NULL
, ce
);
2892 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
2895 bit
= volcache_volid2bit (e
->volume
, fid
.fid
.Volume
);
2900 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
2903 memset(addresses
, 0, sizeof(addresses
));
2904 for (i
= 0, j
= 0; i
< min(e
->volume
->entry
.nServers
, MAXNSERVERS
); i
++) {
2905 u_long addr
= htonl(e
->volume
->entry
.serverNumber
[i
]);
2907 if ((e
->volume
->entry
.serverFlags
[i
] & bit
) && addr
!= 0)
2908 addresses
[j
++] = addr
;
2910 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
2911 addresses
, sizeof(long) * j
);
2920 * Return all db servers for a particular cell.
2924 vioc_get_cell(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2928 const char *cellname
;
2931 char out
[8 * sizeof(int32_t) + MAXPATHLEN
]; /* XXX */
2932 const cell_db_entry
*dbservers
;
2935 index
= *((int32_t *) h
->msg
);
2936 cellname
= cell_num2name(index
);
2937 if (cellname
== NULL
)
2938 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EDOM
);
2940 dbservers
= cell_dbservers_by_id (index
, &num_dbservers
);
2942 if (dbservers
== NULL
)
2943 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EDOM
);
2945 memset(out
, 0, sizeof(out
));
2946 cellname_len
= min(strlen(cellname
), MAXPATHLEN
- 1);
2947 memcpy(out
+ 8 * sizeof(int32_t), cellname
, cellname_len
);
2948 out
[8 * sizeof(int32_t) + cellname_len
] = '\0';
2949 outsize
= 8 * sizeof(int32_t) + cellname_len
+ 1;
2950 for (i
= 0; i
< min(num_dbservers
, 8); ++i
) {
2951 uint32_t addr
= dbservers
[i
].addr
.s_addr
;
2952 memcpy (&out
[i
* sizeof(int32_t)], &addr
, sizeof(int32_t));
2955 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
2962 * Return status information about a cell.
2966 vioc_get_cellstatus(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
2973 cellname
[h
->insize
-1] = '\0';
2975 cellid
= cell_name2num (cellname
);
2977 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOENT
);
2980 out
|= arla_CELLSTATUS_PRIMARY
;
2981 if (cell_issuid_by_num (cellid
))
2982 out
|= arla_CELLSTATUS_SETUID
;
2984 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
2991 * Set status information about a cell.
2995 vioc_set_cellstatus(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3002 if (!all_powerful_p (&h
->cred
))
3003 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EACCES
);
3005 if (h
->insize
< sizeof (in
) + 2) /* terminating NUL and one char */
3006 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3008 cellname
= h
->msg
+ sizeof (in
);
3009 cellname
[h
->insize
-1-sizeof(in
)] = '\0';
3011 cellid
= cell_name2num (cellname
);
3013 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOENT
);
3015 if (in
& arla_CELLSTATUS_SETUID
) {
3016 ret
= cell_setsuid_by_num (cellid
);
3018 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,EINVAL
);
3021 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, 0);
3027 * Set information about a cell or add a new one.
3031 vioc_new_cell(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3033 const char *cellname
;
3039 if (!all_powerful_p (&h
->cred
))
3040 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EPERM
);
3043 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3045 hp
= (uint32_t *)h
->msg
;
3046 for (count
= 0; *hp
!= 0; ++hp
)
3049 dbs
= malloc (count
* sizeof(*dbs
));
3051 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOMEM
);
3053 memset(dbs
, 0, count
* sizeof(*dbs
));
3055 hp
= (uint32_t *)h
->msg
;
3056 for (i
= 0; i
< count
; ++i
) {
3058 dbs
[i
].addr
.s_addr
= hp
[i
];
3062 cellname
= h
->msg
+ 8 * sizeof(uint32_t);
3063 ce
= cell_get_by_name (cellname
);
3065 ce
= cell_new_dynamic (cellname
);
3069 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
3073 free (ce
->dbservers
);
3076 ce
->ndbservers
= count
;
3077 ce
->dbservers
= dbs
;
3079 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, 0);
3085 * Return the token for the cell in `ce'
3089 token_for_cell (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
,
3092 char buf
[NNPFS_MSG_MAX_DATASIZE
];
3093 size_t len
, cell_len
;
3096 struct cred_rxkad
*cred
= (struct cred_rxkad
*)ce
->cred_data
;
3097 const char *cell
= cell_num2name (ce
->cell
);
3099 cell_len
= strlen(cell
);
3101 len
= 4 + cred
->ticket_len
+ 4 + sizeof(cred
->ct
) + 4 + cell_len
;
3102 if (len
> sizeof(buf
))
3103 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3105 tmp
= cred
->ticket_len
;
3106 memcpy (p
, &tmp
, sizeof(tmp
));
3108 memcpy (p
, cred
->ticket
, tmp
);
3110 tmp
= sizeof(cred
->ct
);
3111 memcpy (p
, &tmp
, sizeof(tmp
));
3113 memcpy (p
, &cred
->ct
, sizeof(cred
->ct
));
3114 p
+= sizeof(cred
->ct
);
3116 memcpy (p
, &tmp
, sizeof(tmp
));
3119 p
+= strlen(cell
) + 1;
3125 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
3136 gettok_func(CredCacheEntry
*ce
, void *ptr
)
3138 struct get_tok
*gt
= ptr
;
3140 if (gt
->counter
== 0) {
3141 gt
->cell
= ce
->cell
;
3151 * Handle the GETTOK message in `h'
3155 viocgettok (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3160 if (h
->insize
== 0) {
3161 cell_id
= cell_name2num(cell_getthiscell());
3162 } else if (h
->insize
== sizeof(uint32_t)) {
3166 memcpy (&n
, h
->msg
, sizeof(n
));
3169 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3176 cred_list_pag(h
->cred
.pag
, CRED_KRB4
, gettok_func
, >
);
3178 if (gt
.cell
== -1) {
3179 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EDOM
);
3185 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3189 ce
= cred_get (cell_id
, h
->cred
.pag
, CRED_KRB4
);
3191 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOTCONN
);
3195 return token_for_cell (fd
, h
, size
, ce
);
3199 * Handle the SETTOK message in `h'
3203 viocsettok (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3205 struct cred_rxkad cred
;
3211 /* someone probed us */
3218 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
)) ;
3219 cred
.ticket_len
= sizeof_x
;
3220 arla_warnx (ADEBMSG
, "ticket_st has size %d", sizeof_x
);
3221 t
+= sizeof(sizeof_x
) ;
3223 /* data used + datalen + cleartoken's length field */
3224 if ((t
- (char *)h
->msg
) + sizeof_x
+ 4 > h
->insize
)
3226 if (sizeof_x
> sizeof(cred
.ticket
))
3229 memcpy(cred
.ticket
, t
, sizeof_x
) ;
3232 /* Get ClearToken */
3233 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
)) ;
3234 t
+= sizeof(sizeof_x
) ;
3236 /* data used + datalen + cell's length field */
3237 if ((t
- (char *)h
->msg
) + sizeof_x
+ 4 > h
->insize
)
3240 memcpy(&cred
.ct
, t
, sizeof_x
) ;
3243 /* Get primary cell ? */
3244 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
)) ;
3245 t
+= sizeof(sizeof_x
) ;
3248 strlcpy(realm
, t
, min(h
->insize
- (t
- (char *)h
->msg
), sizeof(realm
)));
3251 cell
= cell_name2num(realm
);
3256 conn_clearcred (CONN_CS_ALL
, cell
, h
->cred
.pag
, 2);
3257 fcache_purge_cred(h
->cred
.pag
, cell
);
3258 cred_add (h
->cred
.pag
, CRED_KRB4
, 2, cell
, cred
.ct
.EndTimestamp
,
3259 &cred
, sizeof(cred
), cred
.ct
.ViceId
);
3264 viocunlog (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3266 nnpfs_pag_t cred
= h
->cred
.pag
;
3269 fcache_purge_cred(cred
, -1);
3273 #if defined(HAVE_KRB5) && defined(WITH_RXGK)
3276 * handle rxgk kerberos 5 authenticator
3279 * int32_t ticket_len
3280 * char krb5_ticket[];
3282 * int32_t krb5_enctype;
3284 * int32_t sessionkey_len;
3285 * char sessionkey[];
3286 * int64_t start_time;
3287 * int64_t expiration_time;
3291 size_t k5ticket_limit_size
= 40 * 1024;
3294 k5settok (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3303 int insize
= h
->insize
;
3308 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
)) ;
3309 arla_warnx (ADEBMSG
, "ticket has size %d", sizeof_x
);
3310 t
+= sizeof(sizeof_x
) ;
3312 if (sizeof_x
< k5ticket_limit_size
|| sizeof_x
> insize
)
3315 c
.type
= CRED_GK_K5
;
3317 c
.t
.k5
.ticket
= malloc(sizeof_x
);
3318 if (c
.t
.k5
.ticket
== NULL
)
3321 memcpy(c
.t
.k5
.ticket
, t
, sizeof_x
);
3325 if (h
->insize
< 4 + 4 + 4 + 4) {
3326 free(c
.t
.k5
.ticket
);
3330 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
));
3331 t
+= sizeof(sizeof_x
); insize
-= sizeof(sizeof_x
);
3332 c
.t
.k5
.enctype
= sizeof_x
;
3334 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
));
3335 t
+= sizeof(sizeof_x
); insize
-= sizeof(sizeof_x
);
3336 c
.t
.k5
.kvno
= sizeof_x
;
3338 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
));
3339 t
+= sizeof(sizeof_x
); insize
-= sizeof(sizeof_x
);
3342 memcpy(&sizeof_x
, t
, sizeof(sizeof_x
));
3343 t
+= sizeof(sizeof_x
); insize
-= sizeof(sizeof_x
);
3344 c
.t
.k5
.sessionkey_len
= sizeof_x
;
3346 if (sizeof_x
< k5ticket_limit_size
|| sizeof_x
> insize
) {
3347 free(c
.t
.k5
.ticket
);
3351 c
.t
.k5
.sessionkey
= malloc(c
.t
.k5
.sessionkey_len
);
3352 if (c
.t
.k5
.sessionkey
== NULL
) {
3353 free(c
.t
.k5
.ticket
);
3357 memcpy(c
.t
.k5
.sessionkey
, t
, c
.t
.k5
.sessionkey_len
);
3358 t
+= c
.t
.k5
.sessionkey_len
;
3359 insize
-= c
.t
.k5
.sessionkey_len
;
3362 if (insize
< 8 + 8 + 1) {
3363 free(c
.t
.k5
.sessionkey
);
3364 free(c
.t
.k5
.ticket
);
3371 memcpy(&endtime
, t
, sizeof(endtime
));
3375 if (insize
> sizeof(cellname
) || t
[insize
- 1] != '\0') {
3376 free(c
.t
.k5
.sessionkey
);
3377 free(c
.t
.k5
.ticket
);
3381 strlcpy(cellname
, t
, sizeof(cellname
));
3383 cell
= cell_name2num(strlwr(cellname
));
3386 free(c
.t
.k5
.sessionkey
);
3387 free(c
.t
.k5
.ticket
);
3391 conn_clearcred (CONN_CS_ALL
, cell
, h
->cred
.pag
, 2);
3392 fcache_purge_cred(h
->cred
.pag
, cell
);
3393 cred_add (h
->cred
.pag
, CRED_GK_K5
, 2, cell
, (time_t)endtime
,
3394 &c
, sizeof(c
), viceid
);
3398 #endif /* HAVE_KRB5 && WITH_RXGK */
3400 #endif /* KERBEROS */
3403 * Flush the fid in `h->handle' from the cache.
3407 viocflush (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3410 AFSCallBack broken_callback
= {0, 0, CBDROPPED
};
3412 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
3415 fid
.Cell
= h
->handle
.a
;
3416 fid
.fid
.Volume
= h
->handle
.b
;
3417 fid
.fid
.Vnode
= h
->handle
.c
;
3418 fid
.fid
.Unique
= h
->handle
.d
;
3421 "flushing (%d, %u, %u, %u)",
3422 fid
.Cell
, fid
.fid
.Volume
, fid
.fid
.Vnode
, fid
.fid
.Unique
);
3424 fcache_stale_entry(fid
, broken_callback
);
3429 get_connmode(int32_t *mode
)
3431 switch(connected_mode
) {
3433 *mode
= arla_CONNMODE_CONN
; break;
3435 *mode
= arla_CONNMODE_FETCH
; break;
3437 *mode
= arla_CONNMODE_DISCONN
; break;
3446 set_connmode(int32_t mode
, nnpfs_cred
*cred
)
3449 case arla_CONNMODE_CONN
:
3450 case arla_CONNMODE_CONN_WITHCALLBACKS
:
3451 if (connected_mode
== CONNECTED
)
3458 if (connected_mode
== DISCONNECTED
)
3459 fcache_discard_attrs();
3461 if (disco_need_integrate())
3462 disco_reintegrate(cred
->pag
);
3464 if (mode
== arla_CONNMODE_CONN_WITHCALLBACKS
)
3465 fcache_reobtain_callbacks (cred
);
3467 connected_mode
= CONNECTED
;
3469 case arla_CONNMODE_FETCH
:
3470 if (connected_mode
== CONNECTED
)
3473 if (connected_mode
== DISCONNECTED
)
3474 fcache_discard_attrs();
3476 connected_mode
= FETCH_ONLY
;
3478 case arla_CONNMODE_DISCONN
:
3479 if (connected_mode
== CONNECTED
)
3482 if (possibly_have_network())
3483 fcache_giveup_all_callbacks();
3485 connected_mode
= DISCONNECTED
;
3495 viocconnect(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3502 if (h
->insize
!= sizeof(int32_t) ||
3503 h
->outsize
!= sizeof(int32_t)) {
3508 memcpy(&tmp
, h
->msg
, sizeof(tmp
));
3513 /* check permission */
3515 case arla_CONNMODE_PROBE
:
3518 if (!all_powerful_p(&h
->cred
))
3524 case arla_CONNMODE_PROBE
:
3525 error
= get_connmode(&ret
);
3528 error
= set_connmode(tmp
, &h
->cred
);
3533 nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, error
,
3539 getrxkcrypt(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3541 if (h
->outsize
== sizeof(uint32_t)) {
3545 if (conn_rxkad_level
== rxkad_crypt
)
3551 return nnpfs_send_message_wakeup_data (fd
,
3552 h
->header
.sequence_num
,
3557 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3561 setrxkcrypt(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3566 if (!all_powerful_p(&h
->cred
))
3569 if (h
->insize
== sizeof(uint32_t)) {
3572 memcpy (&n
, h
->msg
, sizeof(n
));
3575 conn_rxkad_level
= rxkad_auth
;
3577 conn_rxkad_level
= rxkad_crypt
;
3581 conn_clearcred (CONN_CS_SECIDX
, 0, -1, 2);
3591 * XXX - this function sometimes does a wakeup_data and then an ordinary wakeup is sent in nnpfs_message_pioctl
3595 vioc_fpriostatus (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3597 struct arla_vioc_fprio
*fprio
;
3601 if (h
->insize
!= sizeof(struct arla_vioc_fprio
))
3604 fprio
= (struct arla_vioc_fprio
*) h
->msg
;
3606 fid
.Cell
= fprio
->Cell
;
3607 fid
.fid
.Volume
= fprio
->Volume
;
3608 fid
.fid
.Vnode
= fprio
->Vnode
;
3609 fid
.fid
.Unique
= fprio
->Unique
;
3611 if (!all_powerful_p(&h
->cred
))
3615 switch(fprio
->cmd
) {
3619 if (h
->outsize
!= sizeof(unsigned)) {
3624 prio
= fprio_get(fid
);
3625 nnpfs_send_message_wakeup_data (fd
,
3626 h
->header
.sequence_num
,
3634 if (fprio
->prio
== 0) {
3637 } else if (fprio
->prio
< FPRIO_MIN
||
3638 fprio
->prio
> FPRIO_MAX
)
3641 fprio_set(fid
, fprio
->prio
);
3646 if (h
->outsize
!= sizeof(unsigned)) {
3651 nnpfs_send_message_wakeup_data (fd
,
3652 h
->header
.sequence_num
,
3655 sizeof(fprioritylevel
));
3659 if (fprio
->prio
< FPRIO_MIN
||
3660 fprio
->prio
> FPRIO_MAX
)
3663 fprioritylevel
= fprio
->prio
;
3676 viocgetfid (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3678 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
3679 &h
->handle
, sizeof(VenusFid
));
3683 viocvenuslog (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3685 if (!all_powerful_p(&h
->cred
))
3692 cell_status (stderr
);
3696 rx_PrintStats(stderr
);
3697 worker_printstatus();
3702 * Set or get the sysname
3706 vioc_afs_sysname (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3709 int32_t parm
= *((int32_t *)t
);
3712 char t_sysname
[SYSNAMEMAXLEN
];
3715 if (!all_powerful_p (&h
->cred
))
3716 return nnpfs_send_message_wakeup (fd
,
3717 h
->header
.sequence_num
,
3719 t
+= sizeof(int32_t);
3720 arla_warnx (ADEBMSG
, "VIOC_AFS_SYSNAME: setting sysname: %s", t
);
3722 size
= min(h
->insize
, SYSNAMEMAXLEN
);
3724 memcpy(t_sysname
, t
, size
);
3725 t_sysname
[size
- 1] = '\0';
3727 fcache_setdefsysname (t_sysname
);
3729 return nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, 0);
3732 const char *sysname
= fcache_getdefsysname ();
3733 size_t sysname_len
= strlen (sysname
);
3736 buf
= malloc (sysname_len
+ 4 + 1);
3738 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
3740 /* Return always 1 as we do not support sysname lists. */
3741 /* Historically the value of this uint32 has been success/failure. */
3742 /* OpenAFS' utilities treat this value as the number of elements */
3743 /* in a list of returned sysnames. It was never meant to be buflen.*/
3744 *((uint32_t *)buf
) = 1;
3745 memcpy (buf
+ 4, sysname
, sysname_len
);
3746 buf
[sysname_len
+ 4] = '\0';
3748 ret
= nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
3749 buf
, sysname_len
+ 5);
3756 viocfilecellname (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3760 cellname
= (char *) cell_num2name(h
->handle
.a
);
3763 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
3764 cellname
, strlen(cellname
)+1);
3766 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, EINVAL
,
3771 viocgetwscell (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3775 cellname
= (char*) cell_getthiscell();
3776 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
3777 cellname
, strlen(cellname
)+1);
3781 viocsetcachesize (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3783 uint32_t *s
= (uint32_t *)h
->msg
;
3785 if (!all_powerful_p (&h
->cred
))
3788 if (h
->insize
>= sizeof(int32_t) * 4)
3789 return fcache_reinit(s
[0], s
[1], s
[2], s
[3]);
3791 return fcache_reinit(*s
/2, *s
, *s
*500, *s
*1000);
3797 * in: flags - bitmask (1 - dont ping, use cached data, 2 - check fsservers only)
3798 * cell - string (optional)
3799 * out: hosts - uint32_t number of hosts, followed by list of hosts being down.
3803 viocckserv (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3805 int32_t cell
= cell_name2num (cell_getthiscell());
3808 uint32_t hosts
[arla_CKSERV_MAXSERVERS
+ 1];
3811 if (h
->insize
< sizeof(int32_t))
3812 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, EINVAL
);
3814 memset (hosts
, 0, sizeof(hosts
));
3816 flags
= *(uint32_t *)h
->msg
;
3817 flags
&= arla_CKSERV_DONTPING
|arla_CKSERV_FSONLY
;
3819 if (h
->insize
> sizeof(int32_t)) {
3820 h
->msg
[min(h
->insize
, sizeof(h
->msg
)-1)] = '\0';
3822 cell
= cell_name2num (((char *)h
->msg
) + sizeof(int32_t));
3824 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, ENOENT
);
3827 num_entries
= arla_CKSERV_MAXSERVERS
;
3829 conn_downhosts(cell
, hosts
+ 1, &num_entries
, flags
);
3831 hosts
[0] = num_entries
;
3832 msg_size
= sizeof(hosts
[0]) * (num_entries
+ 1);
3833 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
3839 * Return the number of used KBs and reserved KBs
3843 viocgetcacheparms (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3847 memset(parms
, 0, sizeof(parms
));
3848 parms
[0] = fcache_highbytes() / 1024;
3849 parms
[1] = fcache_usedbytes() / 1024;
3850 parms
[2] = fcache_highvnodes();
3851 parms
[3] = fcache_usedvnodes();
3852 parms
[4] = fcache_highbytes();
3853 parms
[5] = fcache_usedbytes();
3854 parms
[6] = fcache_lowbytes();
3855 parms
[7] = fcache_lowvnodes();
3857 h
->outsize
= sizeof(parms
);
3858 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
3859 parms
, sizeof(parms
));
3863 * debugging interface to give out statistics of the cache
3867 viocaviator (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3871 memset(parms
, 0, sizeof(parms
));
3872 parms
[0] = kernel_highworkers();
3873 parms
[1] = kernel_usedworkers();
3875 h
->outsize
= sizeof(parms
);
3876 return nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
3877 parms
, sizeof(parms
));
3881 * Get/set arla debug level
3885 vioc_arladebug (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3887 if (h
->insize
!= 0) {
3888 if (h
->insize
< sizeof(int32_t))
3889 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
3891 if (!all_powerful_p (&h
->cred
))
3892 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
3894 arla_log_set_level_num (*((int32_t *)h
->msg
));
3896 if (h
->outsize
!= 0) {
3897 int32_t debug_level
;
3899 if (h
->outsize
< sizeof(int32_t))
3900 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
3903 debug_level
= arla_log_get_level_num ();
3904 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
,
3906 sizeof(debug_level
));
3908 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, 0);
3912 * GC pags --- there shouldn't be any need to do anything here.
3916 vioc_gcpags (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3922 * Break the callback of the specified fid
3926 vioc_calculate_cache (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3930 memset(parms
, 0, sizeof(parms
));
3932 if (!all_powerful_p(&h
->cred
))
3935 h
->outsize
= sizeof(parms
);
3937 parms
[0] = fcache_calculate_usage();
3938 parms
[1] = fcache_usedbytes();
3940 arla_warnx (ADEBMISC
,
3941 "diskusage = %d, usedbytes = %d",
3942 parms
[0], parms
[1]);
3944 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
3945 &parms
, sizeof(parms
));
3953 vioc_breakcallback(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3960 if (!all_powerful_p(&h
->cred
))
3963 if (!h
->handle
.a
&& !h
->handle
.b
&& !h
->handle
.c
&& !h
->handle
.d
)
3966 fid
.Cell
= h
->handle
.a
;
3967 fid
.fid
.Volume
= h
->handle
.b
;
3968 fid
.fid
.Vnode
= h
->handle
.c
;
3969 fid
.fid
.Unique
= h
->handle
.d
;
3971 ce
= cred_get (fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
3972 assert (ce
!= NULL
);
3974 error
= fcache_get(&e
, fid
, ce
);
3978 if (!e
->flags
.kernelp
) {
3992 * check volume mappings
3996 vioc_ckback(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
3998 volcache_invalidate_all ();
3999 fcache_invalidate_mp ();
4004 * checks if caller has the rights in h->msg
4008 viocaccess(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4013 FCacheEntry
*entry
= NULL
;
4014 int32_t *rights
= (int32_t *) h
->msg
;
4016 if (h
->insize
!= sizeof(int32_t)) {
4021 fid
.Cell
= h
->handle
.a
;
4022 fid
.fid
.Volume
= h
->handle
.b
;
4023 fid
.fid
.Vnode
= h
->handle
.c
;
4024 fid
.fid
.Unique
= h
->handle
.d
;
4026 ce
= cred_get(fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
4029 ret
= fcache_get (&entry
, fid
, ce
);
4033 /* Two reasons for calling read_attr explicitly:
4034 1. To get our hands on any error code.
4035 2. To make sure the server is asked, since
4036 you don't get callback for change of ACL.
4038 Still, it is inefficient...
4040 ret = read_attr(entry, ce);
4046 ret
= cm_checkright(entry
, *rights
, ce
);
4049 nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, ret
);
4051 fcache_release(entry
);
4058 vioc_getvcxstatus2(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4063 FCacheEntry
*entry
= NULL
;
4064 struct afs_vcxstat2 stat
;
4066 fid
.Cell
= h
->handle
.a
;
4067 fid
.fid
.Volume
= h
->handle
.b
;
4068 fid
.fid
.Vnode
= h
->handle
.c
;
4069 fid
.fid
.Unique
= h
->handle
.d
;
4071 ce
= cred_get(fid
.Cell
, h
->cred
.pag
, CRED_ANY
);
4074 ret
= fcache_get(&entry
, fid
, ce
);
4078 /* ret = read_attr(entry, ce);
4080 * You don't get callback for change of ACL. So you would need
4081 * to explicitly ask server to make sure you get correct
4082 * access-fields. But it is to inefficient...
4085 ret
= fcache_verify_attr(entry
, NULL
, NULL
, ce
);
4089 stat
.callerAccess
= entry
->status
.CallerAccess
;
4090 stat
.cbExpires
= entry
->callback
.ExpirationTime
;
4091 stat
.anyAccess
= entry
->anonaccess
;
4093 if (entry
->flags
.mountp
)
4095 else if (entry
->flags
.vol_root
)
4102 nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, ret
);
4104 nnpfs_send_message_wakeup_data(fd
, h
->header
.sequence_num
, 0,
4105 (char *) &stat
, sizeof(stat
));
4108 fcache_release(entry
);
4115 statistics_hostpart(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4119 uint32_t outparms
[512];
4125 if (h
->outsize
< sizeof(uint32_t))
4126 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4130 collectstats_hostpart(host
, part
, &n
);
4131 maxslots
= (h
->outsize
/ sizeof(uint32_t) - 1) / 2;
4135 outsize
= (n
* 2 + 1) * sizeof(uint32_t);
4138 for (i
= 0; i
< n
; i
++) {
4139 outparms
[i
*2 + 1] = host
[i
];
4140 outparms
[i
*2 + 2] = part
[i
];
4143 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
4144 (char *) &outparms
, outsize
);
4148 statistics_entry(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4150 uint32_t *request
= (uint32_t *) h
->msg
;
4154 uint32_t items_slot
;
4156 int64_t items_total
[32];
4157 int64_t total_time
[32];
4158 uint32_t outparms
[160];
4162 if (h
->insize
< sizeof(uint32_t) * 5) {
4163 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4167 if (h
->outsize
< sizeof(uint32_t) * 160) {
4168 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4175 items_slot
= request
[4];
4177 collectstats_getentry(host
, part
, type
, items_slot
,
4178 count
, items_total
, total_time
);
4181 for (i
= 0; i
< 32; i
++) {
4182 outparms
[j
++] = count
[i
];
4184 for (i
= 0; i
< 32; i
++) {
4185 memcpy(&outparms
[j
], &items_total
[i
], 8);
4188 for (i
= 0; i
< 32; i
++) {
4189 memcpy(&outparms
[j
], &total_time
[i
], 8);
4192 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
4193 (char *) &outparms
, sizeof(outparms
));
4197 aioc_statistics(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4201 if (!all_powerful_p (&h
->cred
))
4202 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4205 if (h
->insize
< sizeof(opcode
))
4206 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4209 memcpy(&opcode
, &h
->msg
, sizeof(opcode
));
4212 case arla_STATISTICS_OPCODE_LIST
:
4213 return statistics_hostpart(fd
, h
, size
);
4214 case arla_STATISTICS_OPCODE_GETENTRY
:
4215 return statistics_entry(fd
, h
, size
);
4217 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4224 aioc_getcacheparam(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4230 if (h
->insize
< sizeof(opcode
) || h
->outsize
< sizeof(int64_t))
4231 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4234 memcpy(&opcode
, &h
->msg
, sizeof(opcode
));
4237 case arla_GETCACHEPARAMS_OPCODE_HIGHBYTES
:
4238 val
= fcache_highbytes();
4240 case arla_GETCACHEPARAMS_OPCODE_USEDBYTES
:
4241 val
= fcache_usedbytes();
4243 case arla_GETCACHEPARAMS_OPCODE_LOWBYTES
:
4244 val
= fcache_lowbytes();
4246 case arla_GETCACHEPARAMS_OPCODE_HIGHVNODES
:
4247 val
= fcache_highvnodes();
4249 case arla_GETCACHEPARAMS_OPCODE_USEDVNODES
:
4250 val
= fcache_usedvnodes();
4252 case arla_GETCACHEPARAMS_OPCODE_LOWVNODES
:
4253 val
= fcache_lowvnodes();
4260 return nnpfs_send_message_wakeup_data (fd
, h
->header
.sequence_num
, 0,
4261 (char *) &val
, sizeof(val
));
4265 aioc_setcacheparam(int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4267 char *p
= (char*)&h
->msg
;
4273 if (!all_powerful_p(&h
->cred
))
4274 return nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
,
4277 if (h
->insize
< (sizeof(opcode
) + sizeof(high
) + sizeof(low
)))
4278 return nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
,
4281 memcpy(&opcode
, p
, sizeof(opcode
));
4282 p
+= sizeof(opcode
);
4284 memcpy(&high
, p
, sizeof(high
));
4287 memcpy(&low
, p
, sizeof(low
));
4290 case arla_SETCACHEPARAMS_OPCODE_BYTES
:
4291 error
= fcache_reinit(0, 0, low
, high
);
4293 case arla_SETCACHEPARAMS_OPCODE_VNODES
:
4294 error
= fcache_reinit(low
, high
, 0, 0);
4301 return nnpfs_send_message_wakeup(fd
, h
->header
.sequence_num
, error
);
4306 * Handle a pioctl message in `h'
4310 nnpfs_message_pioctl (int fd
, struct nnpfs_message_pioctl
*h
, u_int size
)
4316 case ARLA_VIOCSETTOK
:
4317 error
= viocsettok (fd
, h
, size
);
4320 #if defined(HAVE_KRB5) && defined(WITH_RXGK)
4321 case AFSCOMMONIOC_GKK5SETTOK
:
4322 error
= k5settok(fd
, h
, size
);
4324 #endif /* HAVE_KRB5 && WITH_RXGK */
4326 case ARLA_VIOCGETTOK
:
4327 return viocgettok (fd
, h
, size
);
4328 case ARLA_VIOCUNPAG
:
4329 case ARLA_VIOCUNLOG
:
4330 error
= viocunlog (fd
, h
, size
);
4332 #endif /* KERBEROS */
4333 case ARLA_AIOC_CONNECTMODE
:
4334 return viocconnect(fd
, h
, size
);
4335 case ARLA_VIOCFLUSH
:
4336 error
= viocflush(fd
, h
, size
);
4338 case ARLA_VIOC_FLUSHVOLUME
:
4339 error
= viocflushvolume(fd
, h
, size
);
4341 case ARLA_VIOCGETFID
:
4342 return viocgetfid (fd
, h
, size
);
4343 case ARLA_VIOCGETAL
:
4344 return viocgetacl(fd
, h
, size
);
4345 case ARLA_VIOCSETAL
:
4346 return viocsetacl(fd
, h
, size
);
4347 case ARLA_VIOCGETVOLSTAT
:
4348 return viocgetvolstat(fd
, h
, size
);
4349 case ARLA_VIOCSETVOLSTAT
:
4350 error
= viocsetvolstat(fd
, h
, size
);
4352 case ARLA_VIOC_AFS_STAT_MT_PT
:
4353 return vioc_afs_stat_mt_pt(fd
, h
, size
);
4354 case ARLA_VIOC_AFS_DELETE_MT_PT
:
4355 return vioc_afs_delete_mt_pt(fd
, h
, size
);
4356 case ARLA_VIOCWHEREIS
:
4357 return viocwhereis(fd
, h
, size
);
4361 case ARLA_VIOCGETCELL
:
4362 return vioc_get_cell(fd
, h
, size
);
4363 case ARLA_VIOC_GETCELLSTATUS
:
4364 return vioc_get_cellstatus(fd
, h
, size
);
4365 case ARLA_VIOC_SETCELLSTATUS
:
4366 return vioc_set_cellstatus(fd
, h
, size
);
4367 case ARLA_VIOCNEWCELL
:
4368 return vioc_new_cell(fd
, h
, size
);
4369 case ARLA_VIOC_VENUSLOG
:
4370 error
= viocvenuslog (fd
, h
, size
);
4372 case ARLA_VIOC_AFS_SYSNAME
:
4373 return vioc_afs_sysname (fd
, h
, size
);
4374 case ARLA_VIOC_FILE_CELL_NAME
:
4375 return viocfilecellname (fd
, h
, size
);
4376 case ARLA_VIOC_GET_WS_CELL
:
4377 return viocgetwscell (fd
, h
, size
);
4378 case ARLA_VIOCSETCACHESIZE
:
4379 error
= viocsetcachesize (fd
, h
, size
);
4381 case ARLA_VIOCCKSERV
:
4382 return viocckserv (fd
, h
, size
);
4383 case ARLA_VIOCGETCACHEPARAMS
:
4384 return viocgetcacheparms (fd
, h
, size
);
4385 case ARLA_VIOC_GETRXKCRYPT
:
4386 return getrxkcrypt(fd
, h
, size
);
4387 case ARLA_VIOC_SETRXKCRYPT
:
4388 error
= setrxkcrypt(fd
, h
, size
);
4390 case ARLA_VIOC_FPRIOSTATUS
:
4391 error
= vioc_fpriostatus(fd
, h
, size
);
4393 case ARLA_VIOC_AVIATOR
:
4394 return viocaviator (fd
, h
, size
);
4395 case ARLA_VIOC_ARLADEBUG
:
4396 return vioc_arladebug (fd
, h
, size
);
4397 case ARLA_VIOC_GCPAGS
:
4398 error
= vioc_gcpags (fd
, h
, size
);
4400 case ARLA_VIOC_CALCULATE_CACHE
:
4401 return vioc_calculate_cache (fd
, h
, size
);
4402 case ARLA_VIOC_BREAKCALLBACK
:
4403 error
= vioc_breakcallback (fd
, h
, size
);
4405 case ARLA_VIOCACCESS
:
4406 return viocaccess(fd
, h
, size
);
4407 case ARLA_VIOC_GETVCXSTATUS2
:
4408 return vioc_getvcxstatus2(fd
, h
, size
);
4409 case ARLA_VIOCCKBACK
:
4410 error
= vioc_ckback (fd
, h
, size
);
4412 case ARLA_AIOC_STATISTICS
:
4413 return aioc_statistics (fd
, h
, size
);
4414 case ARLA_AIOC_GETCACHEPARAMS
:
4415 return aioc_getcacheparam(fd
, h
, size
);
4416 case ARLA_AIOC_SETCACHEPARAMS
:
4417 return aioc_setcacheparam(fd
, h
, size
);
4419 arla_warnx (ADEBMSG
, "unknown pioctl call %d", h
->opcode
);
4423 nnpfs_send_message_wakeup (fd
, h
->header
.sequence_num
, error
);
4430 * Return non-zero if there is a possibility that we have a network
4431 * connectivity. Can't tell the existence of network, just the lack of.
4433 * Ignore lookback interfaces and known loopback addresses.
4437 possibly_have_network(void)
4439 struct ifaddrs
*ifa
, *ifa0
;
4442 if (getifaddrs(&ifa0
) != 0)
4443 return 1; /* well we don't really have a clue, do we ? */
4445 for (ifa
= ifa0
; ifa
!= NULL
&& !found_addr
; ifa
= ifa
->ifa_next
) {
4446 if (ifa
->ifa_addr
== NULL
)
4450 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
4454 switch (ifa
->ifa_addr
->sa_family
) {
4456 struct sockaddr_in
*sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
4457 if (sin
->sin_addr
.s_addr
== htonl(0x7f000001))
4459 if (sin
->sin_addr
.s_addr
== htonl(0))
4464 #ifdef RX_SUPPORT_INET6
4467 * XXX avoid link local and local loopback addresses since
4468 * those are not allowed in VLDB
4479 /* if we found an acceptable address, good for us */