@database "Professional File System 3 documentation" @author "Michiel Pelt" @(c) "Copyright 1999 by Great Effects Development" @$VER: pfs3packets.guide 1.2 (8/6/1999) @master pfs3packets.guide @node "Main" "PFS3 Custom Packets" @{jcenter}@{b}Professional File System 3 Custom Packet Documentation@{ub} Copyright (c) 1998 by Great Effects Development for PFS3 Version 5.1 This document provides information for developers. PFS3 defines some custom packets to make sleepmode and rollover files possible. All these packets have as first argument ID_PFS2_DISK which is 0x50465302L as defined in @{"pfs3.h" link pfs3.h/main}. These packets are: @{"ACTION_IS_PFS2" link "ACTION_IS_PFS2"} @{"ACTION_SLEEP" link "ACTION_SLEEP"} @{"ACTION_UPDATE_ANODE" link "ACTION_UPDATE_ANODE"} @{"ACTION_CREATE_ROLLOVER" link "ACTION_CREATE_ROLLOVER"} @{"ACTION_SET_ROLLOVER" link "ACTION_SET_ROLLOVER"} @{"ACTION_ADD_IDLE_SIGNAL" link "ACTION_ADD_IDLE_SIGNAL"} @{"ACTION_REMOVE_DIRENTRY" link "ACTION_REMOVE_DIRENTRY"} @{"ACTION_SET_DELDIR" link "ACTION_SET_DELDIR"} @{"ACTION_SET_FNSIZE" link "ACTION_SET_FNSIZE"} How to use sleepmode is explained in @{"sleepmode" link sleepmode} @endnode @rem -------------------------------------------------------------------- @node "ACTION_IS_PFS2" "ACTION_IS_PFS2" @{jcenter}@{b}ACTION_IS_PFS2@{ub} @{jleft} ARG1 = ID_PFS2_DISK (= 'PFS\\02') RES1 = DOSTRUE if PFS2 or PFS3 volume RES2 = Version (upper word) and revision (lower word) Check if partition is a PFS2 or PFS3 partition. If it is, it returns DOSTRUE in dp_Res1. The version and revision of PFS is returned in dp_Res2. @endnode @rem -------------------------------------------------------------------- @node "ACTION_SLEEP" "ACTION_SLEEP" @{jcenter}@{b}ACTION_SLEEP@{ub} @{jleft} ARG1 = ID_PFS2_DISK (= 'PFS\\02') ARG2 = on/off (DOSTRUE for on, DOSFALSE for off) ARG3 = ULONG signalnr ARG4 = struct Task *task RES1 = struct MsgPort *sleepport or NULL for failure RES2 = failurecode if RES1==NULL Enter or leave sleep mode. See @{"sleepmode" link sleepmode} for details. If sleep mode is entered (dp_Arg2 == DOSTRUE), dp_Arg3 and dp_Arg4 specify where PFS3 will sent the wakeup signal to if PFS3 needs to regain control of the disk. If sleep mode is successfully entered, the sleepport will be returned in dp_Res1. @endnode @rem -------------------------------------------------------------------- @node "ACTION_UPDATE_ANODE" "ACTION_UPDATE_ANODE" @{jcenter}@{b}ACTION_UPDATE_ANODE@{ub} @{jleft} ARG1 = ID_PFS2_DISK (= 'PFS\\02') ARG2 = old anodenr ARG3 = new anodenr (0 = invalidate references) RES1 = updatecount or -1 for failure RES2 = failurecode if Res1 = -1 This packet is only valid during sleepmode. The optimiser has to sent this packet to the sleepport for each anode it reassigns to another anodenumber. This packet is necessary because PFS3 identifies objects by anode number. Only anode numbers are cached during sleepmode, not the anodes themselves. These cached anode numbers are updated by this function. If dp_Arg3 is 0 all references to the anode in question are invalidated. This means locks on the object become invalid. This packet does not access the disk in any way. It doesn't matter when or in which order the packets are sent, as long as all changes are passed before the filesystem leaves sleepmode. @endnode @rem -------------------------------------------------------------------- @node "ACTION_CREATE_ROLLOVER" "ACTION_CREATE_ROLLOVER" @{jcenter}@{b}ACTION_CREATE ROLLOVER@{ub} @{jleft} ARG1 = ID_PFS2_DISK (= 'PFS\\02') ARG2 = BPTR LOCK on directory ARG3 is relative to ARG3 = APTR name of rollover file ARG4 = WORD desired rollover size in blocks RES1 = success RES2 = failure code Creates a rollover file with the specified size. This packet cannot convert a normal file to a rollover file. If a file by the specified name already exists, an ERROR_OBJECT_EXISTS will be returned. @endnode @rem -------------------------------------------------------------------- @node "ACTION_SET_ROLLOVER" "ACTION_SET_ROLLOVER" @{jcenter}@{b}ACTION_SET_ROLLOVER@{ub} @{jleft} ARG1 = ID_PFS2_DISK (= 'PFS\\02') ARG2 = APTR fileentry (filled in by Open()) ARG3 = APTR struct rolloverinfo RES1 = success RES2 = failure code Changes the attributes of a rolloverfile. In dp_Arg2 an APTR to the rolloverfile is expected. This is can be obtained by converting the BPTR returned by Open() to an APTR using the macro BADDR(). The rolloverinfo structure passed in dp_arg3 looks like this: struct rolloverinfo { BOOL set; /* 0 -> read; 1 -> write */ ULONG realsize; /* Space rolloverfile takes on disk */ ULONG virtualsize; /* How much is stored in file */ ULONG rollpointer; /* Start of file offset */ }; @endnode @rem -------------------------------------------------------------------- @node "ACTION_ADD_IDLE_SIGNAL" "ACTION_ADD_IDLE_SIGNAL" @{jcenter}@{b}ACTION_IDLE_SIGNAL@{ub} @{jleft} ARG1 = ID_PFS2_DISK ARG2 = add/remove (DOSTRUE = add; DOSFALSE = remove) ARG3 = ULONG signal number (UPPER = read, LOWER = write) remove: handle to remove ARG4 = struct Task *task RES1 = Idlehandle or DOSFALSE for failure RES2 = errorcode Add or remove a task from the idle signal chain. All tasks in the idle signal chain are notified when PFS3 is idle. To add a task, set dp_Arg2 to DOSTRUE and a pointer to the task in dp_Arg4. Argument dp_Arg3 specifies which signals PFS3 will set when it becomes idle. If it has written to the disk it will send the signal specified in the lower word, if it has only read from the disk it will send the signal specified by the upper word. Your 'idlehandle' is returned in dp_Res1. To remove a task from the idle signal chain set dp_Arg2 to DOSFALSE and pass your idlehandle in dp_Arg3. @endnode @rem -------------------------------------------------------------------- @node "ACTION_REMOVE_DIRENTRY" "ACTION_REMOVE_DIRENTRY" @{jcenter}@{b}ACTION_REMOVE_DIRENTRY@{ub} @{jleft} ARG1 = ID_PFS2_DISK ARG2 = Lock to which ARG2 is relative (BPTR) ARG3 = STRPTR Name of object to be deleted RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE) RES2 = failurecode (if res1 = DOSFALSE) Removes a directory entry (file, directory, link) without taking any action regarding the object in question. Storage taken by the object is not freed. This packet is a patch that makes it possible to circumvent an illegal object. @endnode @rem -------------------------------------------------------------------- @node "ACTION_SET_DELDIR" "ACTION_SET_DELDIR" @{jcenter}@{b}ACTION_SET_DELDIR@{ub} @{jleft} ARG1 = MODE_PFS2_DISK ARG2 = number of deldirblocks wanted (0 = disable, -1 = check) RES1 = success RES2 = failure code Sets the number of deldir blocks. To disable the deldir, set Arg2 to 0. To get the current number of deldirblocks set Arg2 to -1 and it will be returned in Res2. @endnode @rem -------------------------------------------------------------------- @node "ACTION_SET_FNSIZE" "ACTION_SET_FNSIZE" @{jcenter}@{b}ACTION_SET_FNSIZE@{ub} @{jleft} ARG1 = MODE_PFS2_DISK ARG2 = New maximum filename size (0 = read) RES1 = success RES2 = failure code / current or new fnsize Set the maximum filename size. If the new size is illegal, an error will be returned. If operation is successful or Arg2 is NULL, the new filename size will be returned in Res2. @endnode @rem -------------------------------------------------------------------- @node "Sleepmode" "Sleep Mode" @{jcenter}@{b}Sleep Mode@{ub} @{jleft} This document assumes some knowledge of the structure of a PFS volume. See the supplied include file for details. Even AFS volumes can get fragmented and therefore can benefit from occasional optimization by a disk optimiser. It would be ideal if this reorganisation process could be performed transparently, without the disk becoming inaccessible while the optimiser is busy. For this purpose AFS has a special mode of operation, the sleep mode. In sleep mode the filesystem has no blocks of the volume cached and doesn't access the volume, like during inhibit mode. The difference with inhibit is that the filesystem does accept all packets when in sleep mode. If the filesystem needs access to the disk to perform a packet it will start the wakeup protocol. After completion of the wakeup protocol the filesystem is back in normal operating mode and can perform the packet. @endnode @rem -------------------------------------------------------------------- @node "SM_Protocol" "Sleep Mode Protocol" @{jcenter}@{b}Sleep Mode Protocol Overview@{ub} @{jleft} Suppose an optimiser process is started. It has to initiate the sleep protocol to get access to the disk. It does this by requesting the filesystem to enter sleep mode. If the request is granted it can then access the disk. The optimiser also gets access to a special messageport, the @{i}sleepport@{ui}, for communication with the filesystem during sleep mode. When the optimiser is finished with the disk it has to exit sleep mode by sending a release message to this messageport. Sleep mode is not limited to optimisers. Many other applications are conceivable, like a diskrepair tool or analyser. In the rest of this chapter the application will be called the @{i}client@{ui}. During sleep mode the client is allowed to change filesystem structures on the disk. The filesystem therefore flushes all caches before it grants a sleep mode request. The filesystem does keep all locks on the volume, since the volume has to remain accessible by the user. Each file locked is identified by an anodenumber, which refers to the anodes on disk. If the client moves anodes around it has to notify the filesystem about this in order to keep the locks valid. If the filesystem gets a user request for which it needs access to the disk it will request the client to finish disk access and release sleep mode. During this wakeup protocol the client has to clean up the disk during which it can send messages to the sleepport (like anode update messages). The client completes the wakeup protocol by sending a release message to the sleep port. The filesystem is then back in the normal mode of operation and can perform the user's request. @endnode @rem -------------------------------------------------------------------- @node "SM_Enter" "Entering Sleep Mode" @{jcenter}@{b}Entering Sleep Mode@{ub} @{jleft} Sleepmode is requested by sending an ACTION_SLEEP packet with dp_Arg2 == DOSTRUE. If the request is granted, the client can begin its work. For every anodenumber it changes it has to send an ACTION_UPDATE_ANODE to the sleepport. Changes to anodes themselves, without changing their number, don't have to be reported. @endnode @rem -------------------------------------------------------------------- @node "SM_Wakeup" "The wakeup protocol" @{jcenter}@{b}The wakeup protocol@{ub} @{jleft} Sleep mode is left by using the wakeup protocol. The wakeup protocol can be initiated by either the client or the filesystem. If the client is finished with whatever it was doing with the disk it will take the initiative. It will flush all blocks it has cached and send all outstanding ACTION_UPDATE_ANODE packets. After that it sends the ACTION_SLEEP message causing the filesystem to exit sleep mode. The filesystem will initiate the wakeup protocol if it needs access to the disk during sleep mode. It will sent a signal to the optimiser, using the signal number and messageport specified in the original ACTION_SLEEP packet. The client should respond by finishing disk activity and sending all outstanding ACTION_UPDATE_ANODE packets to the sleepport. The filesystem will leave sleep mode and continue normal operation as soon as it receives the MODE_SLEEP message with dp_Arg2 == DOSFALSE. @endnode