You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
Make the in-kernel AFS filesystem use AF_RXRPC instead of the old RxRPC code. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
651350d10f
commit
08e0e7c82e
13
fs/Kconfig
13
fs/Kconfig
@@ -2019,7 +2019,7 @@ config CODA_FS_OLD_API
|
||||
config AFS_FS
|
||||
tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
|
||||
depends on INET && EXPERIMENTAL
|
||||
select RXRPC
|
||||
select AF_RXRPC
|
||||
help
|
||||
If you say Y here, you will get an experimental Andrew File System
|
||||
driver. It currently only supports unsecured read-only AFS access.
|
||||
@@ -2028,6 +2028,17 @@ config AFS_FS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config AFS_DEBUG
|
||||
bool "AFS dynamic debugging"
|
||||
depends on AFS_FS
|
||||
help
|
||||
Say Y here to make runtime controllable debugging messages appear.
|
||||
|
||||
See <file:Documentation/filesystems/afs.txt> for more information.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
||||
config RXRPC
|
||||
tristate
|
||||
|
||||
|
||||
@@ -10,12 +10,11 @@ kafs-objs := \
|
||||
file.o \
|
||||
fsclient.o \
|
||||
inode.o \
|
||||
kafsasyncd.o \
|
||||
kafstimod.o \
|
||||
main.o \
|
||||
misc.o \
|
||||
mntpt.o \
|
||||
proc.o \
|
||||
rxrpc.o \
|
||||
server.o \
|
||||
super.o \
|
||||
vlclient.o \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* AFS types
|
||||
/* AFS common types
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -9,10 +9,10 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_TYPES_H
|
||||
#define AFS_TYPES_H
|
||||
#ifndef AFS_H
|
||||
#define AFS_H
|
||||
|
||||
#include <rxrpc/types.h>
|
||||
#include <linux/in.h>
|
||||
|
||||
typedef unsigned afs_volid_t;
|
||||
typedef unsigned afs_vnodeid_t;
|
||||
@@ -31,9 +31,6 @@ typedef enum {
|
||||
AFS_FTYPE_SYMLINK = 3,
|
||||
} afs_file_type_t;
|
||||
|
||||
struct afs_cell;
|
||||
struct afs_vnode;
|
||||
|
||||
/*
|
||||
* AFS file identifier
|
||||
*/
|
||||
@@ -54,14 +51,13 @@ typedef enum {
|
||||
} afs_callback_type_t;
|
||||
|
||||
struct afs_callback {
|
||||
struct afs_server *server; /* server that made the promise */
|
||||
struct afs_fid fid; /* file identifier */
|
||||
unsigned version; /* callback version */
|
||||
unsigned expiry; /* time at which expires */
|
||||
afs_callback_type_t type; /* type of callback */
|
||||
};
|
||||
|
||||
#define AFSCBMAX 50
|
||||
#define AFSCBMAX 50 /* maximum callbacks transferred per bulk op */
|
||||
|
||||
/*
|
||||
* AFS volume information
|
||||
@@ -70,7 +66,7 @@ struct afs_volume_info {
|
||||
afs_volid_t vid; /* volume ID */
|
||||
afs_voltype_t type; /* type of this volume */
|
||||
afs_volid_t type_vids[5]; /* volume ID's for possible types for this vol */
|
||||
|
||||
|
||||
/* list of fileservers serving this volume */
|
||||
size_t nservers; /* number of entries used in servers[] */
|
||||
struct {
|
||||
@@ -88,7 +84,7 @@ struct afs_file_status {
|
||||
afs_file_type_t type; /* file type */
|
||||
unsigned nlink; /* link count */
|
||||
size_t size; /* file size */
|
||||
afs_dataversion_t version; /* current data version */
|
||||
afs_dataversion_t data_version; /* current data version */
|
||||
unsigned author; /* author ID */
|
||||
unsigned owner; /* owner ID */
|
||||
unsigned caller_access; /* access rights for authenticated caller */
|
||||
@@ -106,4 +102,4 @@ struct afs_volsync {
|
||||
time_t creation; /* volume creation time */
|
||||
};
|
||||
|
||||
#endif /* AFS_TYPES_H */
|
||||
#endif /* AFS_H */
|
||||
28
fs/afs/afs_cm.h
Normal file
28
fs/afs/afs_cm.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* AFS Cache Manager definitions
|
||||
*
|
||||
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_CM_H
|
||||
#define AFS_CM_H
|
||||
|
||||
#define AFS_CM_PORT 7001 /* AFS file server port */
|
||||
#define CM_SERVICE 1 /* AFS File Service ID */
|
||||
|
||||
enum AFS_CM_Operations {
|
||||
CBCallBack = 204, /* break callback promises */
|
||||
CBInitCallBackState = 205, /* initialise callback state */
|
||||
CBProbe = 206, /* probe client */
|
||||
CBGetLock = 207, /* get contents of CM lock table */
|
||||
CBGetCE = 208, /* get cache file description */
|
||||
CBGetXStatsVersion = 209, /* get version of extended statistics */
|
||||
CBGetXStats = 210, /* get contents of extended statistics data */
|
||||
};
|
||||
|
||||
#endif /* AFS_FS_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/* AFS abort/error codes
|
||||
/* AFS File Service definitions
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -9,15 +9,22 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_ERRORS_H
|
||||
#define AFS_ERRORS_H
|
||||
#ifndef AFS_FS_H
|
||||
#define AFS_FS_H
|
||||
|
||||
#include "types.h"
|
||||
#define AFS_FS_PORT 7000 /* AFS file server port */
|
||||
#define FS_SERVICE 1 /* AFS File Service ID */
|
||||
|
||||
/*
|
||||
* file server abort codes
|
||||
*/
|
||||
typedef enum {
|
||||
enum AFS_FS_Operations {
|
||||
FSFETCHSTATUS = 132, /* AFS Fetch file status */
|
||||
FSFETCHDATA = 130, /* AFS Fetch file data */
|
||||
FSGIVEUPCALLBACKS = 147, /* AFS Discard callback promises */
|
||||
FSGETVOLUMEINFO = 148, /* AFS Get root volume information */
|
||||
FSGETROOTVOLUME = 151, /* AFS Get root volume name */
|
||||
FSLOOKUP = 161 /* AFS lookup file in directory */
|
||||
};
|
||||
|
||||
enum AFS_FS_Errors {
|
||||
VSALVAGE = 101, /* volume needs salvaging */
|
||||
VNOVNODE = 102, /* no such file/dir (vnode) */
|
||||
VNOVOL = 103, /* no such volume or volume unavailable */
|
||||
@@ -29,8 +36,6 @@ typedef enum {
|
||||
VOVERQUOTA = 109, /* volume's maximum quota exceeded */
|
||||
VBUSY = 110, /* volume is temporarily unavailable */
|
||||
VMOVED = 111, /* volume moved to new server - ask this FS where */
|
||||
} afs_rxfs_abort_t;
|
||||
};
|
||||
|
||||
extern int afs_abort_to_error(int);
|
||||
|
||||
#endif /* AFS_ERRORS_H */
|
||||
#endif /* AFS_FS_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Volume Location Service client interface
|
||||
/* AFS Volume Location Service client interface
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -9,10 +9,19 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_VLCLIENT_H
|
||||
#define AFS_VLCLIENT_H
|
||||
#ifndef AFS_VL_H
|
||||
#define AFS_VL_H
|
||||
|
||||
#include "types.h"
|
||||
#include "afs.h"
|
||||
|
||||
#define AFS_VL_PORT 7003 /* volume location service port */
|
||||
#define VL_SERVICE 52 /* RxRPC service ID for the Volume Location service */
|
||||
|
||||
enum AFSVL_Operations {
|
||||
VLGETENTRYBYID = 503, /* AFS Get Cache Entry By ID operation ID */
|
||||
VLGETENTRYBYNAME = 504, /* AFS Get Cache Entry By Name operation ID */
|
||||
VLPROBE = 514, /* AFS Probe Volume Location Service operation ID */
|
||||
};
|
||||
|
||||
enum AFSVL_Errors {
|
||||
AFSVL_IDEXIST = 363520, /* Volume Id entry exists in vl database */
|
||||
@@ -40,14 +49,16 @@ enum AFSVL_Errors {
|
||||
AFSVL_BADVOLOPER = 363542, /* Bad volume operation code */
|
||||
AFSVL_BADRELLOCKTYPE = 363543, /* Bad release lock type */
|
||||
AFSVL_RERELEASE = 363544, /* Status report: last release was aborted */
|
||||
AFSVL_BADSERVERFLAG = 363545, /* Invalid replication site server °ag */
|
||||
AFSVL_BADSERVERFLAG = 363545, /* Invalid replication site server °ag */
|
||||
AFSVL_PERM = 363546, /* No permission access */
|
||||
AFSVL_NOMEM = 363547, /* malloc/realloc failed to alloc enough memory */
|
||||
};
|
||||
|
||||
/* maps to "struct vldbentry" in vvl-spec.pdf */
|
||||
/*
|
||||
* maps to "struct vldbentry" in vvl-spec.pdf
|
||||
*/
|
||||
struct afs_vldbentry {
|
||||
char name[65]; /* name of volume (including NUL char) */
|
||||
char name[65]; /* name of volume (with NUL char) */
|
||||
afs_voltype_t type; /* volume type */
|
||||
unsigned num_servers; /* num servers that hold instances of this vol */
|
||||
unsigned clone_id; /* cloning ID */
|
||||
@@ -70,16 +81,4 @@ struct afs_vldbentry {
|
||||
} servers[8];
|
||||
};
|
||||
|
||||
extern int afs_rxvl_get_entry_by_name(struct afs_server *, const char *,
|
||||
unsigned, struct afs_cache_vlocation *);
|
||||
extern int afs_rxvl_get_entry_by_id(struct afs_server *, afs_volid_t,
|
||||
afs_voltype_t,
|
||||
struct afs_cache_vlocation *);
|
||||
|
||||
extern int afs_rxvl_get_entry_by_id_async(struct afs_async_op *,
|
||||
afs_volid_t, afs_voltype_t);
|
||||
|
||||
extern int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *,
|
||||
struct afs_cache_vlocation *);
|
||||
|
||||
#endif /* AFS_VLCLIENT_H */
|
||||
#endif /* AFS_VL_H */
|
||||
256
fs/afs/cache.c
Normal file
256
fs/afs/cache.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* AFS caching stuff
|
||||
*
|
||||
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_cell_cache_match(void *target,
|
||||
const void *entry);
|
||||
static void afs_cell_cache_update(void *source, void *entry);
|
||||
|
||||
struct cachefs_index_def afs_cache_cell_index_def = {
|
||||
.name = "cell_ix",
|
||||
.data_size = sizeof(struct afs_cache_cell),
|
||||
.keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
|
||||
.match = afs_cell_cache_match,
|
||||
.update = afs_cell_cache_update,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* match a cell record obtained from the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_cell_cache_match(void *target,
|
||||
const void *entry)
|
||||
{
|
||||
const struct afs_cache_cell *ccell = entry;
|
||||
struct afs_cell *cell = target;
|
||||
|
||||
_enter("{%s},{%s}", ccell->name, cell->name);
|
||||
|
||||
if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) {
|
||||
_leave(" = SUCCESS");
|
||||
return CACHEFS_MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
_leave(" = FAILED");
|
||||
return CACHEFS_MATCH_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update a cell record in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static void afs_cell_cache_update(void *source, void *entry)
|
||||
{
|
||||
struct afs_cache_cell *ccell = entry;
|
||||
struct afs_cell *cell = source;
|
||||
|
||||
_enter("%p,%p", source, entry);
|
||||
|
||||
strncpy(ccell->name, cell->name, sizeof(ccell->name));
|
||||
|
||||
memcpy(ccell->vl_servers,
|
||||
cell->vl_addrs,
|
||||
min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs)));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_vlocation_cache_match(void *target,
|
||||
const void *entry);
|
||||
static void afs_vlocation_cache_update(void *source, void *entry);
|
||||
|
||||
struct cachefs_index_def afs_vlocation_cache_index_def = {
|
||||
.name = "vldb",
|
||||
.data_size = sizeof(struct afs_cache_vlocation),
|
||||
.keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
|
||||
.match = afs_vlocation_cache_match,
|
||||
.update = afs_vlocation_cache_update,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* match a VLDB record stored in the cache
|
||||
* - may also load target from entry
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_vlocation_cache_match(void *target,
|
||||
const void *entry)
|
||||
{
|
||||
const struct afs_cache_vlocation *vldb = entry;
|
||||
struct afs_vlocation *vlocation = target;
|
||||
|
||||
_enter("{%s},{%s}", vlocation->vldb.name, vldb->name);
|
||||
|
||||
if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0
|
||||
) {
|
||||
if (!vlocation->valid ||
|
||||
vlocation->vldb.rtime == vldb->rtime
|
||||
) {
|
||||
vlocation->vldb = *vldb;
|
||||
vlocation->valid = 1;
|
||||
_leave(" = SUCCESS [c->m]");
|
||||
return CACHEFS_MATCH_SUCCESS;
|
||||
} else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) {
|
||||
/* delete if VIDs for this name differ */
|
||||
if (memcmp(&vlocation->vldb.vid,
|
||||
&vldb->vid,
|
||||
sizeof(vldb->vid)) != 0) {
|
||||
_leave(" = DELETE");
|
||||
return CACHEFS_MATCH_SUCCESS_DELETE;
|
||||
}
|
||||
|
||||
_leave(" = UPDATE");
|
||||
return CACHEFS_MATCH_SUCCESS_UPDATE;
|
||||
} else {
|
||||
_leave(" = SUCCESS");
|
||||
return CACHEFS_MATCH_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
_leave(" = FAILED");
|
||||
return CACHEFS_MATCH_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update a VLDB record stored in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static void afs_vlocation_cache_update(void *source, void *entry)
|
||||
{
|
||||
struct afs_cache_vlocation *vldb = entry;
|
||||
struct afs_vlocation *vlocation = source;
|
||||
|
||||
_enter("");
|
||||
|
||||
*vldb = vlocation->vldb;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_volume_cache_match(void *target,
|
||||
const void *entry);
|
||||
static void afs_volume_cache_update(void *source, void *entry);
|
||||
|
||||
struct cachefs_index_def afs_volume_cache_index_def = {
|
||||
.name = "volume",
|
||||
.data_size = sizeof(struct afs_cache_vhash),
|
||||
.keys[0] = { CACHEFS_INDEX_KEYS_BIN, 1 },
|
||||
.keys[1] = { CACHEFS_INDEX_KEYS_BIN, 1 },
|
||||
.match = afs_volume_cache_match,
|
||||
.update = afs_volume_cache_update,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* match a volume hash record stored in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_volume_cache_match(void *target,
|
||||
const void *entry)
|
||||
{
|
||||
const struct afs_cache_vhash *vhash = entry;
|
||||
struct afs_volume *volume = target;
|
||||
|
||||
_enter("{%u},{%u}", volume->type, vhash->vtype);
|
||||
|
||||
if (volume->type == vhash->vtype) {
|
||||
_leave(" = SUCCESS");
|
||||
return CACHEFS_MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
_leave(" = FAILED");
|
||||
return CACHEFS_MATCH_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update a volume hash record stored in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static void afs_volume_cache_update(void *source, void *entry)
|
||||
{
|
||||
struct afs_cache_vhash *vhash = entry;
|
||||
struct afs_volume *volume = source;
|
||||
|
||||
_enter("");
|
||||
|
||||
vhash->vtype = volume->type;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_vnode_cache_match(void *target,
|
||||
const void *entry);
|
||||
static void afs_vnode_cache_update(void *source, void *entry);
|
||||
|
||||
struct cachefs_index_def afs_vnode_cache_index_def = {
|
||||
.name = "vnode",
|
||||
.data_size = sizeof(struct afs_cache_vnode),
|
||||
.keys[0] = { CACHEFS_INDEX_KEYS_BIN, 4 },
|
||||
.match = afs_vnode_cache_match,
|
||||
.update = afs_vnode_cache_update,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* match a vnode record stored in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static cachefs_match_val_t afs_vnode_cache_match(void *target,
|
||||
const void *entry)
|
||||
{
|
||||
const struct afs_cache_vnode *cvnode = entry;
|
||||
struct afs_vnode *vnode = target;
|
||||
|
||||
_enter("{%x,%x,%Lx},{%x,%x,%Lx}",
|
||||
vnode->fid.vnode,
|
||||
vnode->fid.unique,
|
||||
vnode->status.version,
|
||||
cvnode->vnode_id,
|
||||
cvnode->vnode_unique,
|
||||
cvnode->data_version);
|
||||
|
||||
if (vnode->fid.vnode != cvnode->vnode_id) {
|
||||
_leave(" = FAILED");
|
||||
return CACHEFS_MATCH_FAILED;
|
||||
}
|
||||
|
||||
if (vnode->fid.unique != cvnode->vnode_unique ||
|
||||
vnode->status.version != cvnode->data_version) {
|
||||
_leave(" = DELETE");
|
||||
return CACHEFS_MATCH_SUCCESS_DELETE;
|
||||
}
|
||||
|
||||
_leave(" = SUCCESS");
|
||||
return CACHEFS_MATCH_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update a vnode record stored in the cache
|
||||
*/
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
static void afs_vnode_cache_update(void *source, void *entry)
|
||||
{
|
||||
struct afs_cache_vnode *cvnode = entry;
|
||||
struct afs_vnode *vnode = source;
|
||||
|
||||
_enter("");
|
||||
|
||||
cvnode->vnode_id = vnode->fid.vnode;
|
||||
cvnode->vnode_unique = vnode->fid.unique;
|
||||
cvnode->data_version = vnode->status.version;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
344
fs/afs/cell.c
344
fs/afs/cell.c
File diff suppressed because it is too large
Load Diff
@@ -1,70 +0,0 @@
|
||||
/* AFS cell record
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_CELL_H
|
||||
#define AFS_CELL_H
|
||||
|
||||
#include "types.h"
|
||||
#include "cache.h"
|
||||
|
||||
#define AFS_CELL_MAX_ADDRS 15
|
||||
|
||||
extern volatile int afs_cells_being_purged; /* T when cells are being purged by rmmod */
|
||||
|
||||
/*
|
||||
* entry in the cached cell catalogue
|
||||
*/
|
||||
struct afs_cache_cell {
|
||||
char name[64]; /* cell name (padded with NULs) */
|
||||
struct in_addr vl_servers[15]; /* cached cell VL servers */
|
||||
};
|
||||
|
||||
/*
|
||||
* AFS cell record
|
||||
*/
|
||||
struct afs_cell {
|
||||
atomic_t usage;
|
||||
struct list_head link; /* main cell list link */
|
||||
struct list_head proc_link; /* /proc cell list link */
|
||||
struct proc_dir_entry *proc_dir; /* /proc dir for this cell */
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
struct cachefs_cookie *cache; /* caching cookie */
|
||||
#endif
|
||||
|
||||
/* server record management */
|
||||
rwlock_t sv_lock; /* active server list lock */
|
||||
struct list_head sv_list; /* active server list */
|
||||
struct list_head sv_graveyard; /* inactive server list */
|
||||
spinlock_t sv_gylock; /* inactive server list lock */
|
||||
|
||||
/* volume location record management */
|
||||
struct rw_semaphore vl_sem; /* volume management serialisation semaphore */
|
||||
struct list_head vl_list; /* cell's active VL record list */
|
||||
struct list_head vl_graveyard; /* cell's inactive VL record list */
|
||||
spinlock_t vl_gylock; /* graveyard lock */
|
||||
unsigned short vl_naddrs; /* number of VL servers in addr list */
|
||||
unsigned short vl_curr_svix; /* current server index */
|
||||
struct in_addr vl_addrs[AFS_CELL_MAX_ADDRS]; /* cell VL server addresses */
|
||||
|
||||
char name[0]; /* cell name - must go last */
|
||||
};
|
||||
|
||||
extern int afs_cell_init(char *);
|
||||
extern int afs_cell_create(const char *, char *, struct afs_cell **);
|
||||
extern int afs_cell_lookup(const char *, unsigned, struct afs_cell **);
|
||||
|
||||
#define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
|
||||
|
||||
extern struct afs_cell *afs_get_cell_maybe(struct afs_cell **);
|
||||
extern void afs_put_cell(struct afs_cell *);
|
||||
extern void afs_cell_purge(void);
|
||||
|
||||
#endif /* AFS_CELL_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
||||
/* AFS Cache Manager Service declarations
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_CMSERVICE_H
|
||||
#define AFS_CMSERVICE_H
|
||||
|
||||
#include <rxrpc/transport.h>
|
||||
#include "types.h"
|
||||
|
||||
/* cache manager start/stop */
|
||||
extern int afscm_start(void);
|
||||
extern void afscm_stop(void);
|
||||
|
||||
/* cache manager server functions */
|
||||
extern int SRXAFSCM_InitCallBackState(struct afs_server *);
|
||||
extern int SRXAFSCM_CallBack(struct afs_server *, size_t,
|
||||
struct afs_callback[]);
|
||||
extern int SRXAFSCM_Probe(struct afs_server *);
|
||||
|
||||
#endif /* AFS_CMSERVICE_H */
|
||||
288
fs/afs/dir.c
288
fs/afs/dir.c
@@ -15,11 +15,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include "vnode.h"
|
||||
#include "volume.h"
|
||||
#include <rxrpc/call.h>
|
||||
#include "super.h"
|
||||
#include "internal.h"
|
||||
|
||||
static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
|
||||
@@ -127,9 +122,10 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
|
||||
if (qty == 0)
|
||||
goto error;
|
||||
|
||||
if (page->index==0 && qty!=ntohs(dbuf->blocks[0].pagehdr.npages)) {
|
||||
if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
|
||||
printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
|
||||
__FUNCTION__,dir->i_ino,qty,ntohs(dbuf->blocks[0].pagehdr.npages));
|
||||
__FUNCTION__, dir->i_ino, qty,
|
||||
ntohs(dbuf->blocks[0].pagehdr.npages));
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
@@ -194,6 +190,7 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index)
|
||||
|
||||
fail:
|
||||
afs_dir_put_page(page);
|
||||
_leave(" = -EIO");
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
@@ -207,7 +204,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
|
||||
BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
|
||||
BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
|
||||
|
||||
if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED)
|
||||
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
|
||||
return -ENOENT;
|
||||
|
||||
_leave(" = 0");
|
||||
@@ -242,7 +239,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
|
||||
/* skip entries marked unused in the bitmap */
|
||||
if (!(block->pagehdr.bitmap[offset / 8] &
|
||||
(1 << (offset % 8)))) {
|
||||
_debug("ENT[%Zu.%u]: unused\n",
|
||||
_debug("ENT[%Zu.%u]: unused",
|
||||
blkoff / sizeof(union afs_dir_block), offset);
|
||||
if (offset >= curr)
|
||||
*fpos = blkoff +
|
||||
@@ -256,7 +253,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
|
||||
sizeof(*block) -
|
||||
offset * sizeof(union afs_dirent));
|
||||
|
||||
_debug("ENT[%Zu.%u]: %s %Zu \"%s\"\n",
|
||||
_debug("ENT[%Zu.%u]: %s %Zu \"%s\"",
|
||||
blkoff / sizeof(union afs_dir_block), offset,
|
||||
(offset < curr ? "skip" : "fill"),
|
||||
nlen, dire->u.name);
|
||||
@@ -266,7 +263,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
|
||||
if (next >= AFS_DIRENT_PER_BLOCK) {
|
||||
_debug("ENT[%Zu.%u]:"
|
||||
" %u travelled beyond end dir block"
|
||||
" (len %u/%Zu)\n",
|
||||
" (len %u/%Zu)",
|
||||
blkoff / sizeof(union afs_dir_block),
|
||||
offset, next, tmp, nlen);
|
||||
return -EIO;
|
||||
@@ -274,13 +271,13 @@ static int afs_dir_iterate_block(unsigned *fpos,
|
||||
if (!(block->pagehdr.bitmap[next / 8] &
|
||||
(1 << (next % 8)))) {
|
||||
_debug("ENT[%Zu.%u]:"
|
||||
" %u unmarked extension (len %u/%Zu)\n",
|
||||
" %u unmarked extension (len %u/%Zu)",
|
||||
blkoff / sizeof(union afs_dir_block),
|
||||
offset, next, tmp, nlen);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_debug("ENT[%Zu.%u]: ext %u/%Zu\n",
|
||||
_debug("ENT[%Zu.%u]: ext %u/%Zu",
|
||||
blkoff / sizeof(union afs_dir_block),
|
||||
next, tmp, nlen);
|
||||
next++;
|
||||
@@ -311,12 +308,12 @@ static int afs_dir_iterate_block(unsigned *fpos,
|
||||
}
|
||||
|
||||
/*
|
||||
* read an AFS directory
|
||||
* iterate through the data blob that lists the contents of an AFS directory
|
||||
*/
|
||||
static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
|
||||
filldir_t filldir)
|
||||
{
|
||||
union afs_dir_block *dblock;
|
||||
union afs_dir_block *dblock;
|
||||
struct afs_dir_page *dbuf;
|
||||
struct page *page;
|
||||
unsigned blkoff, limit;
|
||||
@@ -324,7 +321,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
|
||||
|
||||
_enter("{%lu},%u,,", dir->i_ino, *fpos);
|
||||
|
||||
if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {
|
||||
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
|
||||
_leave(" = -ESTALE");
|
||||
return -ESTALE;
|
||||
}
|
||||
@@ -381,10 +378,12 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
|
||||
unsigned fpos;
|
||||
int ret;
|
||||
|
||||
_enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino);
|
||||
_enter("{%Ld,{%lu}}",
|
||||
file->f_pos, file->f_path.dentry->d_inode->i_ino);
|
||||
|
||||
fpos = file->f_pos;
|
||||
ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir);
|
||||
ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos,
|
||||
cookie, filldir);
|
||||
file->f_pos = fpos;
|
||||
|
||||
_leave(" = %d", ret);
|
||||
@@ -401,9 +400,13 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
|
||||
{
|
||||
struct afs_dir_lookup_cookie *cookie = _cookie;
|
||||
|
||||
_enter("{%s,%Zu},%s,%u,,%lu,%u",
|
||||
_enter("{%s,%Zu},%s,%u,,%llu,%u",
|
||||
cookie->name, cookie->nlen, name, nlen, ino, dtype);
|
||||
|
||||
/* insanity checks first */
|
||||
BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
|
||||
BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
|
||||
|
||||
if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
|
||||
_leave(" = 0 [no]");
|
||||
return 0;
|
||||
@@ -418,34 +421,17 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
|
||||
}
|
||||
|
||||
/*
|
||||
* look up an entry in a directory
|
||||
* do a lookup in a directory
|
||||
*/
|
||||
static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd)
|
||||
static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct afs_fid *fid)
|
||||
{
|
||||
struct afs_dir_lookup_cookie cookie;
|
||||
struct afs_super_info *as;
|
||||
struct afs_vnode *vnode;
|
||||
struct inode *inode;
|
||||
unsigned fpos;
|
||||
int ret;
|
||||
|
||||
_enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);
|
||||
|
||||
/* insanity checks first */
|
||||
BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
|
||||
BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
|
||||
|
||||
if (dentry->d_name.len > 255) {
|
||||
_leave(" = -ENAMETOOLONG");
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
vnode = AFS_FS_I(dir);
|
||||
if (vnode->flags & AFS_VNODE_DELETED) {
|
||||
_leave(" = -ESTALE");
|
||||
return ERR_PTR(-ESTALE);
|
||||
}
|
||||
_enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name);
|
||||
|
||||
as = dir->i_sb->s_fs_info;
|
||||
|
||||
@@ -458,54 +444,130 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
|
||||
fpos = 0;
|
||||
ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir);
|
||||
if (ret < 0) {
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
_leave(" = %d [iter]", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = -ENOENT;
|
||||
if (!cookie.found) {
|
||||
_leave(" = %d", ret);
|
||||
_leave(" = -ENOENT [not found]");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*fid = cookie.fid;
|
||||
_leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* look up an entry in a directory
|
||||
*/
|
||||
static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd)
|
||||
{
|
||||
struct afs_vnode *vnode;
|
||||
struct afs_fid fid;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
_enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);
|
||||
|
||||
if (dentry->d_name.len > 255) {
|
||||
_leave(" = -ENAMETOOLONG");
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
vnode = AFS_FS_I(dir);
|
||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
|
||||
_leave(" = -ESTALE");
|
||||
return ERR_PTR(-ESTALE);
|
||||
}
|
||||
|
||||
ret = afs_do_lookup(dir, dentry, &fid);
|
||||
if (ret < 0) {
|
||||
_leave(" = %d [do]", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/* instantiate the dentry */
|
||||
ret = afs_iget(dir->i_sb, &cookie.fid, &inode);
|
||||
if (ret < 0) {
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
inode = afs_iget(dir->i_sb, &fid);
|
||||
if (IS_ERR(inode)) {
|
||||
_leave(" = %ld", PTR_ERR(inode));
|
||||
return ERR_PTR(PTR_ERR(inode));
|
||||
}
|
||||
|
||||
dentry->d_op = &afs_fs_dentry_operations;
|
||||
dentry->d_fsdata = (void *) (unsigned long) vnode->status.version;
|
||||
|
||||
d_add(dentry, inode);
|
||||
_leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }",
|
||||
cookie.fid.vnode,
|
||||
cookie.fid.unique,
|
||||
fid.vnode,
|
||||
fid.unique,
|
||||
dentry->d_inode->i_ino,
|
||||
dentry->d_inode->i_version);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* propagate changed and modified flags on a directory to all the children of
|
||||
* that directory as they may indicate that the ACL on the dir has changed,
|
||||
* potentially rendering the child inaccessible or that a file has been deleted
|
||||
* or renamed
|
||||
*/
|
||||
static void afs_propagate_dir_changes(struct dentry *dir)
|
||||
{
|
||||
struct dentry *child;
|
||||
bool c, m;
|
||||
|
||||
c = test_bit(AFS_VNODE_CHANGED, &AFS_FS_I(dir->d_inode)->flags);
|
||||
m = test_bit(AFS_VNODE_MODIFIED, &AFS_FS_I(dir->d_inode)->flags);
|
||||
|
||||
_enter("{%d,%d}", c, m);
|
||||
|
||||
spin_lock(&dir->d_lock);
|
||||
|
||||
list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
|
||||
if (child->d_inode) {
|
||||
struct afs_vnode *vnode;
|
||||
|
||||
_debug("tag %s", child->d_name.name);
|
||||
vnode = AFS_FS_I(child->d_inode);
|
||||
if (c)
|
||||
set_bit(AFS_VNODE_DIR_CHANGED, &vnode->flags);
|
||||
if (m)
|
||||
set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&dir->d_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* check that a dentry lookup hit has found a valid entry
|
||||
* - NOTE! the hit can be a negative hit too, so we can't assume we have an
|
||||
* inode
|
||||
* (derived from nfs_lookup_revalidate)
|
||||
* - there are several things we need to check
|
||||
* - parent dir data changes (rm, rmdir, rename, mkdir, create, link,
|
||||
* symlink)
|
||||
* - parent dir metadata changed (security changes)
|
||||
* - dentry data changed (write, truncate)
|
||||
* - dentry metadata changed (security changes)
|
||||
*/
|
||||
static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
struct afs_dir_lookup_cookie cookie;
|
||||
struct afs_vnode *vnode;
|
||||
struct afs_fid fid;
|
||||
struct dentry *parent;
|
||||
struct inode *inode, *dir;
|
||||
unsigned fpos;
|
||||
int ret;
|
||||
|
||||
_enter("{sb=%p n=%s},", dentry->d_sb, dentry->d_name.name);
|
||||
vnode = AFS_FS_I(dentry->d_inode);
|
||||
|
||||
_enter("{sb=%p n=%s fl=%lx},",
|
||||
dentry->d_sb, dentry->d_name.name, vnode->flags);
|
||||
|
||||
/* lock down the parent dentry so we can peer at it */
|
||||
parent = dget_parent(dentry->d_parent);
|
||||
parent = dget_parent(dentry);
|
||||
|
||||
dir = parent->d_inode;
|
||||
inode = dentry->d_inode;
|
||||
@@ -517,81 +579,92 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
/* handle a bad inode */
|
||||
if (is_bad_inode(inode)) {
|
||||
printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
|
||||
dentry->d_parent->d_name.name, dentry->d_name.name);
|
||||
parent->d_name.name, dentry->d_name.name);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
/* force a full look up if the parent directory changed since last the
|
||||
* server was consulted
|
||||
* - otherwise this inode must still exist, even if the inode details
|
||||
* themselves have changed
|
||||
*/
|
||||
if (AFS_FS_I(dir)->flags & AFS_VNODE_CHANGED)
|
||||
afs_vnode_fetch_status(AFS_FS_I(dir));
|
||||
|
||||
if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {
|
||||
/* check that this dirent still exists if the directory's contents were
|
||||
* modified */
|
||||
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
|
||||
_debug("%s: parent dir deleted", dentry->d_name.name);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED) {
|
||||
_debug("%s: file already deleted", dentry->d_name.name);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if ((unsigned long) dentry->d_fsdata !=
|
||||
(unsigned long) AFS_FS_I(dir)->status.version) {
|
||||
_debug("%s: parent changed %lu -> %u",
|
||||
dentry->d_name.name,
|
||||
(unsigned long) dentry->d_fsdata,
|
||||
(unsigned) AFS_FS_I(dir)->status.version);
|
||||
if (test_and_clear_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags)) {
|
||||
/* rm/rmdir/rename may have occurred */
|
||||
_debug("dir modified");
|
||||
|
||||
/* search the directory for this vnode */
|
||||
cookie.name = dentry->d_name.name;
|
||||
cookie.nlen = dentry->d_name.len;
|
||||
cookie.fid.vid = AFS_FS_I(inode)->volume->vid;
|
||||
cookie.found = 0;
|
||||
|
||||
fpos = 0;
|
||||
ret = afs_dir_iterate(dir, &fpos, &cookie,
|
||||
afs_dir_lookup_filldir);
|
||||
ret = afs_do_lookup(dir, dentry, &fid);
|
||||
if (ret == -ENOENT) {
|
||||
_debug("%s: dirent not found", dentry->d_name.name);
|
||||
goto not_found;
|
||||
}
|
||||
if (ret < 0) {
|
||||
_debug("failed to iterate dir %s: %d",
|
||||
parent->d_name.name, ret);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if (!cookie.found) {
|
||||
_debug("%s: dirent not found", dentry->d_name.name);
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
/* if the vnode ID has changed, then the dirent points to a
|
||||
* different file */
|
||||
if (cookie.fid.vnode != AFS_FS_I(inode)->fid.vnode) {
|
||||
_debug("%s: dirent changed", dentry->d_name.name);
|
||||
if (fid.vnode != vnode->fid.vnode) {
|
||||
_debug("%s: dirent changed [%u != %u]",
|
||||
dentry->d_name.name, fid.vnode,
|
||||
vnode->fid.vnode);
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
/* if the vnode ID uniqifier has changed, then the file has
|
||||
* been deleted */
|
||||
if (cookie.fid.unique != AFS_FS_I(inode)->fid.unique) {
|
||||
if (fid.unique != vnode->fid.unique) {
|
||||
_debug("%s: file deleted (uq %u -> %u I:%lu)",
|
||||
dentry->d_name.name,
|
||||
cookie.fid.unique,
|
||||
AFS_FS_I(inode)->fid.unique,
|
||||
inode->i_version);
|
||||
spin_lock(&AFS_FS_I(inode)->lock);
|
||||
AFS_FS_I(inode)->flags |= AFS_VNODE_DELETED;
|
||||
spin_unlock(&AFS_FS_I(inode)->lock);
|
||||
dentry->d_name.name, fid.unique,
|
||||
vnode->fid.unique, inode->i_version);
|
||||
spin_lock(&vnode->lock);
|
||||
set_bit(AFS_VNODE_DELETED, &vnode->flags);
|
||||
spin_unlock(&vnode->lock);
|
||||
invalidate_remote_inode(inode);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
dentry->d_fsdata =
|
||||
(void *) (unsigned long) AFS_FS_I(dir)->status.version;
|
||||
}
|
||||
|
||||
/* if the directory's metadata were changed then the security may be
|
||||
* different and we may no longer have access */
|
||||
mutex_lock(&vnode->cb_broken_lock);
|
||||
|
||||
if (test_and_clear_bit(AFS_VNODE_DIR_CHANGED, &vnode->flags) ||
|
||||
test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
|
||||
_debug("%s: changed", dentry->d_name.name);
|
||||
set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
|
||||
if (afs_vnode_fetch_status(vnode) < 0) {
|
||||
mutex_unlock(&vnode->cb_broken_lock);
|
||||
goto out_bad;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
|
||||
_debug("%s: file already deleted", dentry->d_name.name);
|
||||
mutex_unlock(&vnode->cb_broken_lock);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
/* if the vnode's data version number changed then its contents are
|
||||
* different */
|
||||
if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
|
||||
_debug("zap data");
|
||||
invalidate_remote_inode(inode);
|
||||
}
|
||||
|
||||
if (S_ISDIR(inode->i_mode) &&
|
||||
(test_bit(AFS_VNODE_CHANGED, &vnode->flags) ||
|
||||
test_bit(AFS_VNODE_MODIFIED, &vnode->flags)))
|
||||
afs_propagate_dir_changes(dentry);
|
||||
|
||||
clear_bit(AFS_VNODE_CHANGED, &vnode->flags);
|
||||
clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
|
||||
mutex_unlock(&vnode->cb_broken_lock);
|
||||
|
||||
out_valid:
|
||||
dput(parent);
|
||||
_leave(" = 1 [valid]");
|
||||
@@ -610,12 +683,10 @@ out_bad:
|
||||
goto out_valid;
|
||||
}
|
||||
|
||||
shrink_dcache_parent(dentry);
|
||||
|
||||
_debug("dropping dentry %s/%s",
|
||||
dentry->d_parent->d_name.name, dentry->d_name.name);
|
||||
parent->d_name.name, dentry->d_name.name);
|
||||
shrink_dcache_parent(dentry);
|
||||
d_drop(dentry);
|
||||
|
||||
dput(parent);
|
||||
|
||||
_leave(" = 0 [bad]");
|
||||
@@ -635,10 +706,9 @@ static int afs_d_delete(struct dentry *dentry)
|
||||
if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
|
||||
goto zap;
|
||||
|
||||
if (dentry->d_inode) {
|
||||
if (AFS_FS_I(dentry->d_inode)->flags & AFS_VNODE_DELETED)
|
||||
if (dentry->d_inode &&
|
||||
test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags))
|
||||
goto zap;
|
||||
}
|
||||
|
||||
_leave(" = 0 [keep]");
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* file.c: AFS filesystem file handling
|
||||
/* AFS filesystem file handling
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -15,9 +15,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include "volume.h"
|
||||
#include "vnode.h"
|
||||
#include <rxrpc/call.h>
|
||||
#include "internal.h"
|
||||
|
||||
#if 0
|
||||
@@ -80,12 +77,10 @@ static void afs_file_readpage_write_complete(void *cookie_data,
|
||||
*/
|
||||
static int afs_file_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
struct afs_rxfs_fetch_descriptor desc;
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
struct cachefs_page *pageio;
|
||||
#endif
|
||||
struct afs_vnode *vnode;
|
||||
struct inode *inode;
|
||||
size_t len;
|
||||
off_t offset;
|
||||
int ret;
|
||||
|
||||
inode = page->mapping->host;
|
||||
@@ -97,14 +92,10 @@ static int afs_file_readpage(struct file *file, struct page *page)
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
ret = -ESTALE;
|
||||
if (vnode->flags & AFS_VNODE_DELETED)
|
||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
||||
goto error;
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
ret = cachefs_page_get_private(page, &pageio, GFP_NOIO);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/* is it cached? */
|
||||
ret = cachefs_read_or_alloc_page(vnode->cache,
|
||||
page,
|
||||
@@ -128,26 +119,19 @@ static int afs_file_readpage(struct file *file, struct page *page)
|
||||
case -ENOBUFS:
|
||||
case -ENODATA:
|
||||
default:
|
||||
desc.fid = vnode->fid;
|
||||
desc.offset = page->index << PAGE_CACHE_SHIFT;
|
||||
desc.size = min((size_t) (inode->i_size - desc.offset),
|
||||
(size_t) PAGE_SIZE);
|
||||
desc.buffer = kmap(page);
|
||||
|
||||
clear_page(desc.buffer);
|
||||
offset = page->index << PAGE_CACHE_SHIFT;
|
||||
len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE);
|
||||
|
||||
/* read the contents of the file from the server into the
|
||||
* page */
|
||||
ret = afs_vnode_fetch_data(vnode, &desc);
|
||||
kunmap(page);
|
||||
ret = afs_vnode_fetch_data(vnode, offset, len, page);
|
||||
if (ret < 0) {
|
||||
if (ret==-ENOENT) {
|
||||
if (ret == -ENOENT) {
|
||||
_debug("got NOENT from server"
|
||||
" - marking file deleted and stale");
|
||||
vnode->flags |= AFS_VNODE_DELETED;
|
||||
set_bit(AFS_VNODE_DELETED, &vnode->flags);
|
||||
ret = -ESTALE;
|
||||
}
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
cachefs_uncache_page(vnode->cache, page);
|
||||
#endif
|
||||
@@ -174,10 +158,9 @@ static int afs_file_readpage(struct file *file, struct page *page)
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
error:
|
||||
SetPageError(page);
|
||||
unlock_page(page);
|
||||
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
1076
fs/afs/fsclient.c
1076
fs/afs/fsclient.c
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
/* AFS File Server client stub declarations
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_FSCLIENT_H
|
||||
#define AFS_FSCLIENT_H
|
||||
|
||||
#include "server.h"
|
||||
|
||||
extern int afs_rxfs_get_volume_info(struct afs_server *,
|
||||
const char *,
|
||||
struct afs_volume_info *);
|
||||
|
||||
extern int afs_rxfs_fetch_file_status(struct afs_server *,
|
||||
struct afs_vnode *,
|
||||
struct afs_volsync *);
|
||||
|
||||
struct afs_rxfs_fetch_descriptor {
|
||||
struct afs_fid fid; /* file ID to fetch */
|
||||
size_t size; /* total number of bytes to fetch */
|
||||
off_t offset; /* offset in file to start from */
|
||||
void *buffer; /* read buffer */
|
||||
size_t actual; /* actual size sent back by server */
|
||||
};
|
||||
|
||||
extern int afs_rxfs_fetch_file_data(struct afs_server *,
|
||||
struct afs_vnode *,
|
||||
struct afs_rxfs_fetch_descriptor *,
|
||||
struct afs_volsync *);
|
||||
|
||||
extern int afs_rxfs_give_up_callback(struct afs_server *,
|
||||
struct afs_vnode *);
|
||||
|
||||
/* this doesn't appear to work in OpenAFS server */
|
||||
extern int afs_rxfs_lookup(struct afs_server *,
|
||||
struct afs_vnode *,
|
||||
const char *,
|
||||
struct afs_vnode *,
|
||||
struct afs_volsync *);
|
||||
|
||||
/* this is apparently mis-implemented in OpenAFS server */
|
||||
extern int afs_rxfs_get_root_volume(struct afs_server *,
|
||||
char *,
|
||||
size_t *);
|
||||
|
||||
|
||||
#endif /* AFS_FSCLIENT_H */
|
||||
107
fs/afs/inode.c
107
fs/afs/inode.c
@@ -19,9 +19,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include "volume.h"
|
||||
#include "vnode.h"
|
||||
#include "super.h"
|
||||
#include "internal.h"
|
||||
|
||||
struct afs_iget_data {
|
||||
@@ -40,7 +37,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
|
||||
vnode->status.type,
|
||||
vnode->status.nlink,
|
||||
vnode->status.size,
|
||||
vnode->status.version,
|
||||
vnode->status.data_version,
|
||||
vnode->status.mode);
|
||||
|
||||
switch (vnode->status.type) {
|
||||
@@ -78,7 +75,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
|
||||
if (vnode->status.type == AFS_FTYPE_SYMLINK) {
|
||||
afs_mntpt_check_symlink(vnode);
|
||||
|
||||
if (vnode->flags & AFS_VNODE_MOUNTPOINT) {
|
||||
if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) {
|
||||
inode->i_mode = S_IFDIR | vnode->status.mode;
|
||||
inode->i_op = &afs_mntpt_inode_operations;
|
||||
inode->i_fop = &afs_mntpt_file_operations;
|
||||
@@ -88,25 +85,6 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* attempt to fetch the status of an inode, coelescing multiple simultaneous
|
||||
* fetches
|
||||
*/
|
||||
static int afs_inode_fetch_status(struct inode *inode)
|
||||
{
|
||||
struct afs_vnode *vnode;
|
||||
int ret;
|
||||
|
||||
vnode = AFS_FS_I(inode);
|
||||
|
||||
ret = afs_vnode_fetch_status(vnode);
|
||||
|
||||
if (ret == 0)
|
||||
ret = afs_inode_map_status(vnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* iget5() comparator
|
||||
*/
|
||||
@@ -137,8 +115,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
|
||||
/*
|
||||
* inode retrieval
|
||||
*/
|
||||
inline int afs_iget(struct super_block *sb, struct afs_fid *fid,
|
||||
struct inode **_inode)
|
||||
inline struct inode *afs_iget(struct super_block *sb, struct afs_fid *fid)
|
||||
{
|
||||
struct afs_iget_data data = { .fid = *fid };
|
||||
struct afs_super_info *as;
|
||||
@@ -155,20 +132,18 @@ inline int afs_iget(struct super_block *sb, struct afs_fid *fid,
|
||||
&data);
|
||||
if (!inode) {
|
||||
_leave(" = -ENOMEM");
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
_debug("GOT INODE %p { vl=%x vn=%x, u=%x }",
|
||||
inode, fid->vid, fid->vnode, fid->unique);
|
||||
|
||||
vnode = AFS_FS_I(inode);
|
||||
|
||||
/* deal with an existing inode */
|
||||
if (!(inode->i_state & I_NEW)) {
|
||||
ret = afs_vnode_fetch_status(vnode);
|
||||
if (ret == 0)
|
||||
*_inode = inode;
|
||||
else
|
||||
iput(inode);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
_leave(" = %p", inode);
|
||||
return inode;
|
||||
}
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
@@ -181,21 +156,19 @@ inline int afs_iget(struct super_block *sb, struct afs_fid *fid,
|
||||
#endif
|
||||
|
||||
/* okay... it's a new inode */
|
||||
inode->i_flags |= S_NOATIME;
|
||||
vnode->flags |= AFS_VNODE_CHANGED;
|
||||
ret = afs_inode_fetch_status(inode);
|
||||
if (ret<0)
|
||||
set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
|
||||
ret = afs_vnode_fetch_status(vnode);
|
||||
if (ret < 0)
|
||||
goto bad_inode;
|
||||
ret = afs_inode_map_status(vnode);
|
||||
if (ret < 0)
|
||||
goto bad_inode;
|
||||
|
||||
/* success */
|
||||
inode->i_flags |= S_NOATIME;
|
||||
unlock_new_inode(inode);
|
||||
|
||||
*_inode = inode;
|
||||
_leave(" = 0 [CB { v=%u x=%lu t=%u }]",
|
||||
vnode->cb_version,
|
||||
vnode->cb_timeout.timo_jif,
|
||||
vnode->cb_type);
|
||||
return 0;
|
||||
_leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type);
|
||||
return inode;
|
||||
|
||||
/* failure */
|
||||
bad_inode:
|
||||
@@ -204,7 +177,7 @@ bad_inode:
|
||||
iput(inode);
|
||||
|
||||
_leave(" = %d [bad]", ret);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -213,36 +186,13 @@ bad_inode:
|
||||
int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat)
|
||||
{
|
||||
struct afs_vnode *vnode;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
inode = dentry->d_inode;
|
||||
|
||||
_enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version);
|
||||
|
||||
vnode = AFS_FS_I(inode);
|
||||
|
||||
ret = afs_inode_fetch_status(inode);
|
||||
if (ret == -ENOENT) {
|
||||
_leave(" = %d [%d %p]",
|
||||
ret, atomic_read(&dentry->d_count), dentry->d_inode);
|
||||
return ret;
|
||||
} else if (ret < 0) {
|
||||
make_bad_inode(inode);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* transfer attributes from the inode structure to the stat
|
||||
* structure */
|
||||
generic_fillattr(inode, stat);
|
||||
|
||||
_leave(" = 0 CB { v=%u x=%u t=%u }",
|
||||
vnode->cb_version,
|
||||
vnode->cb_expiry,
|
||||
vnode->cb_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -260,12 +210,23 @@ void afs_clear_inode(struct inode *inode)
|
||||
vnode->fid.vnode,
|
||||
vnode->cb_version,
|
||||
vnode->cb_expiry,
|
||||
vnode->cb_type
|
||||
);
|
||||
vnode->cb_type);
|
||||
|
||||
BUG_ON(inode->i_ino != vnode->fid.vnode);
|
||||
_debug("CLEAR INODE %p", inode);
|
||||
|
||||
afs_vnode_give_up_callback(vnode);
|
||||
ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode);
|
||||
|
||||
afs_give_up_callback(vnode);
|
||||
|
||||
if (vnode->server) {
|
||||
spin_lock(&vnode->server->fs_lock);
|
||||
rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
|
||||
spin_unlock(&vnode->server->fs_lock);
|
||||
afs_put_server(vnode->server);
|
||||
vnode->server = NULL;
|
||||
}
|
||||
|
||||
ASSERT(!vnode->cb_promised);
|
||||
|
||||
#ifdef AFS_CACHING_SUPPORT
|
||||
cachefs_relinquish_cookie(vnode->cache, 0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,247 +0,0 @@
|
||||
/* AFS asynchronous operation daemon
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* The AFS async daemon is used to the following:
|
||||
* - probe "dead" servers to see whether they've come back to life yet.
|
||||
* - probe "live" servers that we haven't talked to for a while to see if they are better
|
||||
* candidates for serving than what we're currently using
|
||||
* - poll volume location servers to keep up to date volume location lists
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/freezer.h>
|
||||
#include "cell.h"
|
||||
#include "server.h"
|
||||
#include "volume.h"
|
||||
#include "kafsasyncd.h"
|
||||
#include "kafstimod.h"
|
||||
#include <rxrpc/call.h>
|
||||
#include <asm/errno.h>
|
||||
#include "internal.h"
|
||||
|
||||
static DECLARE_COMPLETION(kafsasyncd_alive);
|
||||
static DECLARE_COMPLETION(kafsasyncd_dead);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(kafsasyncd_sleepq);
|
||||
static struct task_struct *kafsasyncd_task;
|
||||
static int kafsasyncd_die;
|
||||
|
||||
static int kafsasyncd(void *arg);
|
||||
|
||||
static LIST_HEAD(kafsasyncd_async_attnq);
|
||||
static LIST_HEAD(kafsasyncd_async_busyq);
|
||||
static DEFINE_SPINLOCK(kafsasyncd_async_lock);
|
||||
|
||||
static void kafsasyncd_null_call_attn_func(struct rxrpc_call *call)
|
||||
{
|
||||
}
|
||||
|
||||
static void kafsasyncd_null_call_error_func(struct rxrpc_call *call)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* start the async daemon
|
||||
*/
|
||||
int afs_kafsasyncd_start(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kernel_thread(kafsasyncd, NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wait_for_completion(&kafsasyncd_alive);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* stop the async daemon
|
||||
*/
|
||||
void afs_kafsasyncd_stop(void)
|
||||
{
|
||||
/* get rid of my daemon */
|
||||
kafsasyncd_die = 1;
|
||||
wake_up(&kafsasyncd_sleepq);
|
||||
wait_for_completion(&kafsasyncd_dead);
|
||||
}
|
||||
|
||||
/*
|
||||
* probing daemon
|
||||
*/
|
||||
static int kafsasyncd(void *arg)
|
||||
{
|
||||
struct afs_async_op *op;
|
||||
int die;
|
||||
|
||||
DECLARE_WAITQUEUE(myself, current);
|
||||
|
||||
kafsasyncd_task = current;
|
||||
|
||||
printk("kAFS: Started kafsasyncd %d\n", current->pid);
|
||||
|
||||
daemonize("kafsasyncd");
|
||||
|
||||
complete(&kafsasyncd_alive);
|
||||
|
||||
/* loop around looking for things to attend to */
|
||||
do {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
add_wait_queue(&kafsasyncd_sleepq, &myself);
|
||||
|
||||
for (;;) {
|
||||
if (!list_empty(&kafsasyncd_async_attnq) ||
|
||||
signal_pending(current) ||
|
||||
kafsasyncd_die)
|
||||
break;
|
||||
|
||||
schedule();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
|
||||
remove_wait_queue(&kafsasyncd_sleepq, &myself);
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
try_to_freeze();
|
||||
|
||||
/* discard pending signals */
|
||||
afs_discard_my_signals();
|
||||
|
||||
die = kafsasyncd_die;
|
||||
|
||||
/* deal with the next asynchronous operation requiring
|
||||
* attention */
|
||||
if (!list_empty(&kafsasyncd_async_attnq)) {
|
||||
struct afs_async_op *op;
|
||||
|
||||
_debug("@@@ Begin Asynchronous Operation");
|
||||
|
||||
op = NULL;
|
||||
spin_lock(&kafsasyncd_async_lock);
|
||||
|
||||
if (!list_empty(&kafsasyncd_async_attnq)) {
|
||||
op = list_entry(kafsasyncd_async_attnq.next,
|
||||
struct afs_async_op, link);
|
||||
list_move_tail(&op->link,
|
||||
&kafsasyncd_async_busyq);
|
||||
}
|
||||
|
||||
spin_unlock(&kafsasyncd_async_lock);
|
||||
|
||||
_debug("@@@ Operation %p {%p}\n",
|
||||
op, op ? op->ops : NULL);
|
||||
|
||||
if (op)
|
||||
op->ops->attend(op);
|
||||
|
||||
_debug("@@@ End Asynchronous Operation");
|
||||
}
|
||||
|
||||
} while(!die);
|
||||
|
||||
/* need to kill all outstanding asynchronous operations before
|
||||
* exiting */
|
||||
kafsasyncd_task = NULL;
|
||||
spin_lock(&kafsasyncd_async_lock);
|
||||
|
||||
/* fold the busy and attention queues together */
|
||||
list_splice_init(&kafsasyncd_async_busyq,
|
||||
&kafsasyncd_async_attnq);
|
||||
|
||||
/* dequeue kafsasyncd from all their wait queues */
|
||||
list_for_each_entry(op, &kafsasyncd_async_attnq, link) {
|
||||
op->call->app_attn_func = kafsasyncd_null_call_attn_func;
|
||||
op->call->app_error_func = kafsasyncd_null_call_error_func;
|
||||
remove_wait_queue(&op->call->waitq, &op->waiter);
|
||||
}
|
||||
|
||||
spin_unlock(&kafsasyncd_async_lock);
|
||||
|
||||
/* abort all the operations */
|
||||
while (!list_empty(&kafsasyncd_async_attnq)) {
|
||||
op = list_entry(kafsasyncd_async_attnq.next, struct afs_async_op, link);
|
||||
list_del_init(&op->link);
|
||||
|
||||
rxrpc_call_abort(op->call, -EIO);
|
||||
rxrpc_put_call(op->call);
|
||||
op->call = NULL;
|
||||
|
||||
op->ops->discard(op);
|
||||
}
|
||||
|
||||
/* and that's all */
|
||||
_leave("");
|
||||
complete_and_exit(&kafsasyncd_dead, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* begin an operation
|
||||
* - place operation on busy queue
|
||||
*/
|
||||
void afs_kafsasyncd_begin_op(struct afs_async_op *op)
|
||||
{
|
||||
_enter("");
|
||||
|
||||
spin_lock(&kafsasyncd_async_lock);
|
||||
|
||||
init_waitqueue_entry(&op->waiter, kafsasyncd_task);
|
||||
add_wait_queue(&op->call->waitq, &op->waiter);
|
||||
|
||||
list_move_tail(&op->link, &kafsasyncd_async_busyq);
|
||||
|
||||
spin_unlock(&kafsasyncd_async_lock);
|
||||
|
||||
_leave("");
|
||||
}
|
||||
|
||||
/*
|
||||
* request attention for an operation
|
||||
* - move to attention queue
|
||||
*/
|
||||
void afs_kafsasyncd_attend_op(struct afs_async_op *op)
|
||||
{
|
||||
_enter("");
|
||||
|
||||
spin_lock(&kafsasyncd_async_lock);
|
||||
|
||||
list_move_tail(&op->link, &kafsasyncd_async_attnq);
|
||||
|
||||
spin_unlock(&kafsasyncd_async_lock);
|
||||
|
||||
wake_up(&kafsasyncd_sleepq);
|
||||
|
||||
_leave("");
|
||||
}
|
||||
|
||||
/*
|
||||
* terminate an operation
|
||||
* - remove from either queue
|
||||
*/
|
||||
void afs_kafsasyncd_terminate_op(struct afs_async_op *op)
|
||||
{
|
||||
_enter("");
|
||||
|
||||
spin_lock(&kafsasyncd_async_lock);
|
||||
|
||||
if (!list_empty(&op->link)) {
|
||||
list_del_init(&op->link);
|
||||
remove_wait_queue(&op->call->waitq, &op->waiter);
|
||||
}
|
||||
|
||||
spin_unlock(&kafsasyncd_async_lock);
|
||||
|
||||
wake_up(&kafsasyncd_sleepq);
|
||||
|
||||
_leave("");
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/* AFS asynchronous operation daemon
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef AFS_KAFSASYNCD_H
|
||||
#define AFS_KAFSASYNCD_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct afs_async_op;
|
||||
|
||||
struct afs_async_op_ops {
|
||||
void (*attend)(struct afs_async_op *);
|
||||
void (*discard)(struct afs_async_op *);
|
||||
};
|
||||
|
||||
/*
|
||||
* asynchronous operation record
|
||||
*/
|
||||
struct afs_async_op {
|
||||
struct list_head link;
|
||||
struct afs_server *server; /* server being contacted */
|
||||
struct rxrpc_call *call; /* RxRPC call performing op */
|
||||
wait_queue_t waiter; /* wait queue for kafsasyncd */
|
||||
const struct afs_async_op_ops *ops; /* operations */
|
||||
};
|
||||
|
||||
static inline void afs_async_op_init(struct afs_async_op *op,
|
||||
const struct afs_async_op_ops *ops)
|
||||
{
|
||||
INIT_LIST_HEAD(&op->link);
|
||||
op->call = NULL;
|
||||
op->ops = ops;
|
||||
}
|
||||
|
||||
extern int afs_kafsasyncd_start(void);
|
||||
extern void afs_kafsasyncd_stop(void);
|
||||
|
||||
extern void afs_kafsasyncd_begin_op(struct afs_async_op *);
|
||||
extern void afs_kafsasyncd_attend_op(struct afs_async_op *);
|
||||
extern void afs_kafsasyncd_terminate_op(struct afs_async_op *);
|
||||
|
||||
#endif /* AFS_KAFSASYNCD_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user