Skip to content

Commit

Permalink
afs: Build an abstraction around an "operation" concept
Browse files Browse the repository at this point in the history
Turn the afs_operation struct into the main way that most fileserver
operations are managed.  Various things are added to the struct, including
the following:

 (1) All the parameters and results of the relevant operations are moved
     into it, removing corresponding fields from the afs_call struct.
     afs_call gets a pointer to the op.

 (2) The target volume is made the main focus of the operation, rather than
     the target vnode(s), and a bunch of op->vnode->volume are made
     op->volume instead.

 (3) Two vnode records are defined (op->file[]) for the vnode(s) involved
     in most operations.  The vnode record (struct afs_vnode_param)
     contains:

	- The vnode pointer.

	- The fid of the vnode to be included in the parameters or that was
          returned in the reply (eg. FS.MakeDir).

	- The status and callback information that may be returned in the
     	  reply about the vnode.

	- Callback break and data version tracking for detecting
          simultaneous third-parth changes.

 (4) Pointers to dentries to be updated with new inodes.

 (5) An operations table pointer.  The table includes pointers to functions
     for issuing AFS and YFS-variant RPCs, handling the success and abort
     of an operation and handling post-I/O-lock local editing of a
     directory.

To make this work, the following function restructuring is made:

 (A) The rotation loop that issues calls to fileservers that can be found
     in each function that wants to issue an RPC (such as afs_mkdir()) is
     extracted out into common code, in a new file called fs_operation.c.

 (B) The rotation loops, such as the one in afs_mkdir(), are replaced with
     a much smaller piece of code that allocates an operation, sets the
     parameters and then calls out to the common code to do the actual
     work.

 (C) The code for handling the success and failure of an operation are
     moved into operation functions (as (5) above) and these are called
     from the core code at appropriate times.

 (D) The pseudo inode getting stuff used by the dynamic root code is moved
     over into dynroot.c.

 (E) struct afs_iget_data is absorbed into the operation struct and
     afs_iget() expects to be given an op pointer and a vnode record.

 (F) Point (E) doesn't work for the root dir of a volume, but we know the
     FID in advance (it's always vnode 1, unique 1), so a separate inode
     getter, afs_root_iget(), is provided to special-case that.

 (G) The inode status init/update functions now also take an op and a vnode
     record.

 (H) The RPC marshalling functions now, for the most part, just take an
     afs_operation struct as their only argument.  All the data they need
     is held there.  The result delivery functions write their answers
     there as well.

 (I) The call is attached to the operation and then the operation core does
     the waiting.

And then the new operation code is, for the moment, made to just initialise
the operation, get the appropriate vnode I/O locks and do the same rotation
loop as before.

This lays the foundation for the following changes in the future:

 (*) Overhauling the rotation (again).

 (*) Support for asynchronous I/O, where the fileserver rotation must be
     done asynchronously also.

Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed Jun 4, 2020
1 parent a310082 commit e49c7b2
Show file tree
Hide file tree
Showing 21 changed files with 2,648 additions and 2,832 deletions.
1 change: 1 addition & 0 deletions fs/afs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ kafs-y := \
file.o \
flock.o \
fsclient.o \
fs_operation.o \
fs_probe.o \
inode.o \
main.o \
Expand Down
1 change: 0 additions & 1 deletion fs/afs/afs.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ struct afs_file_status {
struct afs_status_cb {
struct afs_file_status status;
struct afs_callback callback;
unsigned int cb_break; /* Pre-op callback break counter */
bool have_status; /* True if status record was retrieved */
bool have_cb; /* True if cb record was retrieved */
bool have_error; /* True if status.abort_code indicates an error */
Expand Down
7 changes: 1 addition & 6 deletions fs/afs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ static struct afs_cb_interest *afs_create_interest(struct afs_server *server,

refcount_set(&new->usage, 1);
new->sb = vnode->vfs_inode.i_sb;
new->vid = vnode->volume->vid;
new->server = afs_get_server(server, afs_server_trace_get_new_cbi);
INIT_HLIST_NODE(&new->cb_vlink);

Expand Down Expand Up @@ -286,7 +285,6 @@ static void afs_break_one_callback(struct afs_server *server,
struct afs_vol_interest *vi)
{
struct afs_cb_interest *cbi;
struct afs_iget_data data;
struct afs_vnode *vnode;
struct inode *inode;

Expand All @@ -305,15 +303,12 @@ static void afs_break_one_callback(struct afs_server *server,
afs_cb_break_for_volume_callback, false);
write_unlock(&volume->cb_v_break_lock);
} else {
data.volume = NULL;
data.fid = *fid;

/* See if we can find a matching inode - even an I_NEW
* inode needs to be marked as it can have its callback
* broken before we finish setting up the local inode.
*/
inode = find_inode_rcu(cbi->sb, fid->vnode,
afs_iget5_test, &data);
afs_ilookup5_test_by_fid, fid);
if (inode) {
vnode = AFS_FS_I(inode);
afs_break_callback(vnode, afs_cb_break_for_callback);
Expand Down
Loading

0 comments on commit e49c7b2

Please sign in to comment.