Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
7a9df5e2
Commit
7a9df5e2
authored
Sep 08, 2003
by
David Howells
Committed by
Linus Torvalds
Sep 08, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] AFS update
parent
d2a65691
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1413 additions
and
814 deletions
+1413
-814
fs/afs/Makefile
fs/afs/Makefile
+2
-0
fs/afs/cache-layout.h
fs/afs/cache-layout.h
+0
-224
fs/afs/cache.h
fs/afs/cache.h
+27
-0
fs/afs/callback.c
fs/afs/callback.c
+1
-1
fs/afs/cell.c
fs/afs/cell.c
+93
-15
fs/afs/cell.h
fs/afs/cell.h
+21
-6
fs/afs/cmservice.c
fs/afs/cmservice.c
+25
-11
fs/afs/dir.c
fs/afs/dir.c
+17
-13
fs/afs/file.c
fs/afs/file.c
+190
-21
fs/afs/inode.c
fs/afs/inode.c
+44
-26
fs/afs/internal.h
fs/afs/internal.h
+20
-1
fs/afs/kafsasyncd.c
fs/afs/kafsasyncd.c
+6
-3
fs/afs/kafstimod.c
fs/afs/kafstimod.c
+10
-10
fs/afs/main.c
fs/afs/main.c
+81
-9
fs/afs/mntpt.c
fs/afs/mntpt.c
+180
-2
fs/afs/mount.h
fs/afs/mount.h
+1
-1
fs/afs/server.c
fs/afs/server.c
+3
-0
fs/afs/super.c
fs/afs/super.c
+164
-228
fs/afs/super.h
fs/afs/super.h
+1
-1
fs/afs/types.h
fs/afs/types.h
+1
-14
fs/afs/vlclient.c
fs/afs/vlclient.c
+49
-48
fs/afs/vlclient.h
fs/afs/vlclient.h
+5
-4
fs/afs/vlocation.c
fs/afs/vlocation.c
+189
-91
fs/afs/vnode.c
fs/afs/vnode.c
+69
-5
fs/afs/vnode.h
fs/afs/vnode.h
+24
-6
fs/afs/volume.c
fs/afs/volume.c
+121
-56
fs/afs/volume.h
fs/afs/volume.h
+69
-18
No files found.
fs/afs/Makefile
View file @
7a9df5e2
...
...
@@ -2,6 +2,8 @@
# Makefile for Red Hat Linux AFS client.
#
#CFLAGS += -finstrument-functions
kafs-objs
:=
\
callback.o
\
cell.o
\
...
...
fs/afs/cache-layout.h
deleted
100644 → 0
View file @
d2a65691
/* cache-layout.h: AFS cache layout
*
* 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 cache is stored on a block device and is laid out as:
*
* 0 +------------------------------------------------
* |
* | SuperBlock
* |
* 1 +------------------------------------------------
* |
* | file-meta-data File: Data block #0
* | - file-meta-data file (volix #0 file #0) : Meta-data block
* | - contains direct pointers to first 64 file data blocks
* | - Cached cell catalogue file (volix #0 file #1) file: Meta-data block
* | - Cached volume location catalogue file (volix #0 file #2): Meta-data block
* | - Vnode catalogue hash bucket #n file: Meta-data block
* |
* 2 +------------------------------------------------
* |
* | Bitmap Block Allocation Bitmap
* | - 1 bit per block in the bitmap block
* | - bit 0 of dword 0 refers to the bitmap block 0
* | - set if the bitmap block is full
* | - 32768 bits per block, requiring 4 blocks for a 16Tb cache
* | - bitmap bitmap blocks are cleared initially
* | - not present if <4 bitmap blocks
* |
* +------------------------------------------------
* |
* | File Block Allocation Bitmap
* | - 1 bit per block in the cache
* | - bit 0 of dword 0 refers to the first block of the data cache
* | - set if block is allocated
* | - 32768 bits per block, requiring 131072 blocks for a 16Tb cache
* | - bitmap blocks are cleared lazily (sb->bix_bitmap_unready)
* |
* +------------------------------------------------
* |
* | Data Cache
* |
* End +------------------------------------------------
*
* Blocks are indexed by an unsigned 32-bit word, meaning that the cache can hold up to 2^32 pages,
* or 16Tb in total.
*
* Credentials will be cached in memory, since they are subject to change without notice, and are
* difficult to derive manually, being constructed from the following information:
* - per vnode user ID and mode mask
* - parent directory ACL
* - directory ACL (dirs only)
* - group lists from ptserver
*/
#ifndef _LINUX_AFS_CACHE_LAYOUT_H
#define _LINUX_AFS_CACHE_LAYOUT_H
#include "types.h"
typedef
u32
afsc_blockix_t
;
typedef
u32
afsc_cellix_t
;
/* Cached volume index
* - afsc_volix_t/4 is the index into the volume cache
* - afsc_volix_t%4 is 0 for R/W, 1 for R/O and 2 for Bak (3 is not used)
* - afsc_volix_t==0-3 refers to a "virtual" volume that stores meta-data about the cache
*/
typedef
struct
{
u32
index
;
}
afsc_volix_t
;
#define AFSC_VNCAT_HASH_NBUCKETS 128
/* special meta file IDs (all cell 0 vol 0) */
enum
afsc_meta_fids
{
AFSC_META_FID_METADATA
=
0
,
AFSC_META_FID_CELL_CATALOGUE
=
1
,
AFSC_META_FID_VLDB_CATALOGUE
=
2
,
AFSC_META_FID_VNODE_CATALOGUE0
=
3
,
AFSC_META_FID__COUNT
=
AFSC_VNCAT_HASH_NBUCKETS
+
3
};
/*****************************************************************************/
/*
* cache superblock block layout
* - the blockdev is prepared for initialisation by 'echo "kafsuninit" >/dev/hdaXX' before mounting
* - when initialised, the magic number is changed to "kafs-cache"
*/
struct
afsc_super_block
{
char
magic
[
10
];
/* magic number */
#define AFSC_SUPER_MAGIC "kafs-cache"
#define AFSC_SUPER_MAGIC_NEEDS_INIT "kafsuninit"
#define AFSC_SUPER_MAGIC_SIZE 10
unsigned
short
endian
;
/* 0x1234 stored CPU-normal order */
#define AFSC_SUPER_ENDIAN 0x1234
unsigned
version
;
/* format version */
#define AFSC_SUPER_VERSION 1
/* layout */
unsigned
bsize
;
/* cache block size */
afsc_blockix_t
bix_bitmap_fullmap
;
/* block ix of bitmap full bitmap */
afsc_blockix_t
bix_bitmap
;
/* block ix of alloc bitmap */
afsc_blockix_t
bix_bitmap_unready
;
/* block ix of unready area of bitmap */
afsc_blockix_t
bix_cache
;
/* block ix of data cache */
afsc_blockix_t
bix_end
;
/* block ix of end of cache */
};
/*****************************************************************************/
/*
* vnode (inode) metadata cache record
* - padded out to 512 bytes and stored eight to a page
* - only the data version is necessary
* - disconnected operation is not supported
* - afs_iget() contacts the server to get the meta-data _anyway_ when an inode is first brought
* into memory
* - at least 64 direct block pointers will be available (a directory is max 256Kb)
* - any block pointer which is 0 indicates an uncached page
*/
struct
afsc_vnode_meta
{
/* file ID */
afsc_volix_t
volume_ix
;
/* volume catalogue index */
unsigned
vnode
;
/* vnode number */
unsigned
unique
;
/* FID unique */
unsigned
size
;
/* size of file */
time_t
mtime
;
/* last modification time */
/* file status */
afs_dataversion_t
version
;
/* current data version */
/* file contents */
afsc_blockix_t
dbl_indirect
;
/* double indirect block index */
afsc_blockix_t
indirect
;
/* single indirect block 0 index */
afsc_blockix_t
direct
[
0
];
/* direct block index (#AFSC_VNODE_META_DIRECT) */
};
#define AFSC_VNODE_META_RECSIZE 512
/* record size */
#define AFSC_VNODE_META_DIRECT \
((AFSC_VNODE_META_RECSIZE-sizeof(struct afsc_vnode_meta))/sizeof(afsc_blockix_t))
#define AFSC_VNODE_META_PER_PAGE (PAGE_SIZE / AFSC_VNODE_META_RECSIZE)
/*****************************************************************************/
/*
* entry in the cached cell catalogue
*/
struct
afsc_cell_record
{
char
name
[
64
];
/* cell name (padded with NULs) */
struct
in_addr
servers
[
16
];
/* cached cell servers */
};
/*****************************************************************************/
/*
* entry in the cached volume location catalogue
* - indexed by afsc_volix_t/4
*/
struct
afsc_vldb_record
{
char
name
[
64
];
/* volume name (padded with NULs) */
afs_volid_t
vid
[
3
];
/* volume IDs for R/W, R/O and Bak volumes */
unsigned
char
vidmask
;
/* voltype mask for vid[] */
unsigned
char
_pad
[
1
];
unsigned
short
nservers
;
/* number of entries used in servers[] */
struct
in_addr
servers
[
8
];
/* fileserver addresses */
unsigned
char
srvtmask
[
8
];
/* voltype masks for servers[] */
#define AFSC_VOL_STM_RW 0x01
/* server holds a R/W version of the volume */
#define AFSC_VOL_STM_RO 0x02
/* server holds a R/O version of the volume */
#define AFSC_VOL_STM_BAK 0x04
/* server holds a backup version of the volume */
afsc_cellix_t
cell_ix
;
/* cell catalogue index (MAX_UINT if unused) */
time_t
ctime
;
/* time at which cached */
};
/*****************************************************************************/
/*
* vnode catalogue entry
* - must be 2^x size so that do_generic_file_read doesn't present them split across pages
*/
struct
afsc_vnode_catalogue
{
afsc_volix_t
volume_ix
;
/* volume catalogue index */
afs_vnodeid_t
vnode
;
/* vnode ID */
u32
meta_ix
;
/* metadata file index */
u32
atime
;
/* last time entry accessed */
}
__attribute__
((
packed
));
#define AFSC_VNODE_CATALOGUE_PER_BLOCK ((size_t)(PAGE_SIZE/sizeof(struct afsc_vnode_catalogue)))
/*****************************************************************************/
/*
* vnode data "page directory" block
* - first 1024 pages don't map through here
* - PAGE_SIZE in size
*/
struct
afsc_indirect_block
{
afsc_blockix_t
pt_bix
[
1024
];
/* "page table" block indices */
};
/*****************************************************************************/
/*
* vnode data "page table" block
* - PAGE_SIZE in size
*/
struct
afsc_dbl_indirect_block
{
afsc_blockix_t
page_bix
[
1024
];
/* "page" block indices */
};
#endif
/* _LINUX_AFS_CACHE_LAYOUT_H */
fs/afs/cache.h
0 → 100644
View file @
7a9df5e2
/* cache.h: AFS local cache management interface
*
* 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 _LINUX_AFS_CACHE_H
#define _LINUX_AFS_CACHE_H
#undef AFS_CACHING_SUPPORT
#include <linux/mm.h>
#ifdef AFS_CACHING_SUPPORT
#include <linux/cachefs.h>
#endif
#include "types.h"
#ifdef __KERNEL__
#endif
/* __KERNEL__ */
#endif
/* _LINUX_AFS_CACHE_H */
fs/afs/callback.c
View file @
7a9df5e2
...
...
@@ -68,7 +68,7 @@ int SRXAFSCM_InitCallBackState(afs_server_t *server)
spin_unlock
(
&
vnode
->
lock
);
iput
(
inode
);
if
(
release
)
afs_put_server
(
server
);
afs_put_server
(
server
);
spin_lock
(
&
server
->
cb_lock
);
}
...
...
fs/afs/cell.c
View file @
7a9df5e2
...
...
@@ -36,6 +36,19 @@ static char *rootcell;
MODULE_PARM
(
rootcell
,
"s"
);
MODULE_PARM_DESC
(
rootcell
,
"root AFS cell name and VL server IP addr list"
);
#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
(
afs_cell_t
),
.
keys
[
0
]
=
{
CACHEFS_INDEX_KEYS_ASCIIZ
,
64
},
.
match
=
afs_cell_cache_match
,
.
update
=
afs_cell_cache_update
,
};
#endif
/*****************************************************************************/
/*
* create a cell record
...
...
@@ -65,7 +78,6 @@ int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell)
atomic_set
(
&
cell
->
usage
,
0
);
INIT_LIST_HEAD
(
&
cell
->
link
);
INIT_LIST_HEAD
(
&
cell
->
caches
);
rwlock_init
(
&
cell
->
sv_lock
);
INIT_LIST_HEAD
(
&
cell
->
sv_list
);
...
...
@@ -96,7 +108,7 @@ int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell)
cell
->
vl_addrs
[
cell
->
vl_naddrs
++
].
s_addr
=
htonl
((
a
<<
24
)
|
(
b
<<
16
)
|
(
c
<<
8
)
|
d
);
if
(
cell
->
vl_naddrs
>=
16
)
if
(
cell
->
vl_naddrs
>=
AFS_CELL_MAX_ADDRS
)
break
;
}
while
(
vllist
=
next
,
vllist
);
...
...
@@ -106,6 +118,14 @@ int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell)
if
(
ret
<
0
)
goto
error
;
#ifdef AFS_CACHING_SUPPORT
/* put it up for caching */
cachefs_acquire_cookie
(
afs_cache_netfs
.
primary_index
,
&
afs_vlocation_cache_index_def
,
cell
,
&
cell
->
cache
);
#endif
/* add to the cell lists */
write_lock
(
&
afs_cells_lock
);
list_add_tail
(
&
cell
->
link
,
&
afs_cells
);
...
...
@@ -166,36 +186,45 @@ int afs_cell_init(void)
/*
* lookup a cell record
*/
int
afs_cell_lookup
(
const
char
*
name
,
afs_cell_t
**
_cell
)
int
afs_cell_lookup
(
const
char
*
name
,
unsigned
namesz
,
struct
afs_cell
**
_cell
)
{
struct
list_head
*
_p
;
afs_cell_t
*
cell
;
int
ret
;
_enter
(
"
\"
%
s
\"
,"
,
name
?
name
:
"*thiscell*
"
);
_enter
(
"
\"
%
*.*s
\"
,"
,
namesz
,
namesz
,
name
?
name
:
"
"
);
cell
=
afs_cell_root
;
*
_cell
=
NULL
;
if
(
name
)
{
/* if the cell was named, look for it in the cell record list */
ret
=
-
ENOENT
;
cell
=
NULL
;
read_lock
(
&
afs_cells_lock
);
list_for_each
(
_p
,
&
afs_cells
)
{
cell
=
list_entry
(
_p
,
afs_cell_t
,
link
);
if
(
strcmp
(
cell
->
name
,
name
)
==
0
)
cell
=
list_entry
(
_p
,
struct
afs_cell
,
link
);
if
(
strncmp
(
cell
->
name
,
name
,
namesz
)
==
0
)
{
afs_get_cell
(
cell
);
break
;
}
cell
=
NULL
;
}
read_unlock
(
&
afs_cells_lock
);
}
if
(
cell
)
if
(
cell
)
ret
=
0
;
}
else
{
cell
=
afs_cell_root
;
afs_get_cell
(
cell
);
ret
=
0
;
}
*
_cell
=
cell
;
_leave
(
" = %d (%p)"
,
cell
?
0
:-
ENOENT
,
cell
);
return
cell
?
0
:
-
ENOENT
;
_leave
(
" = %d (%p)"
,
ret
,
cell
);
return
ret
;
}
/* end afs_cell_lookup() */
...
...
@@ -211,8 +240,8 @@ afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell)
cell
=
*
_cell
;
if
(
cell
&&
!
list_empty
(
&
cell
->
link
))
a
tomic_inc
(
&
cell
->
usage
);
else
a
fs_get_cell
(
cell
);
else
cell
=
NULL
;
write_unlock
(
&
afs_cells_lock
);
...
...
@@ -226,6 +255,9 @@ afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell)
*/
void
afs_put_cell
(
afs_cell_t
*
cell
)
{
if
(
!
cell
)
return
;
_enter
(
"%p{%d,%s}"
,
cell
,
atomic_read
(
&
cell
->
usage
),
cell
->
name
);
/* sanity check */
...
...
@@ -278,6 +310,10 @@ static void afs_cell_destroy(afs_cell_t *cell)
list_del_init
(
&
cell
->
proc_link
);
up_write
(
&
afs_proc_cells_sem
);
#ifdef AFS_CACHING_SUPPORT
cachefs_relinquish_cookie
(
cell
->
cache
,
0
);
#endif
up_write
(
&
afs_cells_sem
);
if
(
!
list_empty
(
&
cell
->
sv_list
))
BUG
();
...
...
@@ -377,8 +413,7 @@ void afs_cell_purge(void)
_enter
(
""
);
if
(
afs_cell_root
)
afs_put_cell
(
afs_cell_root
);
afs_put_cell
(
afs_cell_root
);
while
(
!
list_empty
(
&
afs_cells
))
{
cell
=
NULL
;
...
...
@@ -450,3 +485,46 @@ void afs_cell_purge(void)
_leave
(
""
);
}
/* end afs_cell_purge() */
/*****************************************************************************/
/*
* 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
;
}
/* end afs_cell_cache_match() */
#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
)));
}
/* end afs_cell_cache_update() */
#endif
fs/afs/cell.h
View file @
7a9df5e2
...
...
@@ -13,9 +13,22 @@
#define _LINUX_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
...
...
@@ -26,7 +39,9 @@ struct afs_cell
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 */
struct
list_head
caches
;
/* list of caches currently backing this cell */
#ifdef AFS_CACHING_SUPPORT
struct
cachefs_cookie
*
cache
;
/* caching cookie */
#endif
/* server record management */
rwlock_t
sv_lock
;
/* active server list lock */
...
...
@@ -41,22 +56,22 @@ struct afs_cell
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
[
16
];
/* cell VL server addresses */
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
(
void
);
extern
int
afs_cell_create
(
const
char
*
name
,
char
*
vllist
,
afs_cell_t
**
_cell
);
extern
int
afs_cell_create
(
const
char
*
name
,
char
*
vllist
,
struct
afs_cell
**
_cell
);
extern
int
afs_cell_lookup
(
const
char
*
name
,
afs_cell_t
**
_cell
);
extern
int
afs_cell_lookup
(
const
char
*
name
,
unsigned
nmsize
,
struct
afs_cell
**
_cell
);
#define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
extern
afs_cell_t
*
afs_get_cell_maybe
(
afs_cell_t
**
_cell
);
extern
struct
afs_cell
*
afs_get_cell_maybe
(
struct
afs_cell
**
_cell
);
extern
void
afs_put_cell
(
afs_cell_t
*
cell
);
extern
void
afs_put_cell
(
struct
afs_cell
*
cell
);
extern
void
afs_cell_purge
(
void
);
...
...
fs/afs/cmservice.c
View file @
7a9df5e2
...
...
@@ -119,6 +119,7 @@ static int kafscmd(void *arg)
int
die
;
printk
(
"kAFS: Started kafscmd %d
\n
"
,
current
->
pid
);
daemonize
(
"kafscmd"
);
complete
(
&
kafscmd_alive
);
...
...
@@ -293,15 +294,20 @@ int afscm_start(void)
down_write
(
&
afscm_sem
);
if
(
!
afscm_usage
)
{
ret
=
kernel_thread
(
kafscmd
,
NULL
,
0
);
if
(
ret
<
0
)
ret
=
kernel_thread
(
kafscmd
,
NULL
,
0
);
if
(
ret
<
0
)
goto
out
;
wait_for_completion
(
&
kafscmd_alive
);
ret
=
rxrpc_add_service
(
afs_transport
,
&
AFSCM_service
);
ret
=
rxrpc_add_service
(
afs_transport
,
&
AFSCM_service
);
if
(
ret
<
0
)
goto
kill
;
#ifdef AFS_AUTOMOUNT_SUPPORT
afs_kafstimod_add_timer
(
&
afs_mntpt_expiry_timer
,
afs_mntpt_expiry_timeout
*
HZ
);
#endif
}
afscm_usage
++
;
...
...
@@ -330,17 +336,20 @@ void afscm_stop(void)
down_write
(
&
afscm_sem
);
if
(
afscm_usage
==
0
)
BUG
();
if
(
afscm_usage
==
0
)
BUG
();
afscm_usage
--
;
if
(
afscm_usage
==
0
)
{
if
(
afscm_usage
==
0
)
{
/* don't want more incoming calls */
rxrpc_del_service
(
afs_transport
,
&
AFSCM_service
);
rxrpc_del_service
(
afs_transport
,
&
AFSCM_service
);
/* abort any calls I've still got open (the afscm_error() will dequeue them) */
spin_lock
(
&
afscm_calls_lock
);
while
(
!
list_empty
(
&
afscm_calls
))
{
call
=
list_entry
(
afscm_calls
.
next
,
struct
rxrpc_call
,
app_link
);
call
=
list_entry
(
afscm_calls
.
next
,
struct
rxrpc_call
,
app_link
);
list_del_init
(
&
call
->
app_link
);
rxrpc_get_call
(
call
);
spin_unlock
(
&
afscm_calls_lock
);
...
...
@@ -348,7 +357,8 @@ void afscm_stop(void)
rxrpc_call_abort
(
call
,
-
ESRCH
);
/* abort, dequeue and put */
_debug
(
"nuking active call %08x.%d"
,
ntohl
(
call
->
conn
->
conn_id
),
ntohl
(
call
->
call_id
));
ntohl
(
call
->
conn
->
conn_id
),
ntohl
(
call
->
call_id
));
rxrpc_put_call
(
call
);
rxrpc_put_call
(
call
);
...
...
@@ -376,6 +386,10 @@ void afscm_stop(void)
spin_lock
(
&
kafscmd_attention_lock
);
}
spin_unlock
(
&
kafscmd_attention_lock
);
#ifdef AFS_AUTOMOUNT_SUPPORT
afs_kafstimod_del_timer
(
&
afs_mntpt_expiry_timer
);
#endif
}
up_write
(
&
afscm_sem
);
...
...
@@ -490,7 +504,7 @@ static void _SRXAFSCM_CallBack(struct rxrpc_call *call)
if
(
ret
<
0
)
rxrpc_call_abort
(
call
,
ret
);
if
(
server
)
afs_put_server
(
server
);
afs_put_server
(
server
);
_leave
(
" = %d"
,
ret
);
...
...
@@ -556,7 +570,7 @@ static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call)
if
(
ret
<
0
)
rxrpc_call_abort
(
call
,
ret
);
if
(
server
)
afs_put_server
(
server
);
afs_put_server
(
server
);
_leave
(
" = %d"
,
ret
);
...
...
@@ -622,7 +636,7 @@ static void _SRXAFSCM_Probe(struct rxrpc_call *call)
if
(
ret
<
0
)
rxrpc_call_abort
(
call
,
ret
);
if
(
server
)
afs_put_server
(
server
);
afs_put_server
(
server
);
_leave
(
" = %d"
,
ret
);
...
...
fs/afs/dir.c
View file @
7a9df5e2
...
...
@@ -23,10 +23,11 @@
#include "super.h"
#include "internal.h"
static
struct
dentry
*
afs_dir_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
);
static
struct
dentry
*
afs_dir_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
);
static
int
afs_dir_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
afs_dir_readdir
(
struct
file
*
file
,
void
*
dirent
,
filldir_t
filldir
);
static
int
afs_d_revalidate
(
struct
dentry
*
dentry
,
struct
nameidata
*
);
static
int
afs_d_revalidate
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
);
static
int
afs_d_delete
(
struct
dentry
*
dentry
);
static
int
afs_dir_lookup_filldir
(
void
*
_cookie
,
const
char
*
name
,
int
nlen
,
loff_t
fpos
,
ino_t
ino
,
unsigned
dtype
);
...
...
@@ -70,7 +71,7 @@ typedef union afs_dirent {
u8
name
[
16
];
u8
overflow
[
4
];
/* if any char of the name (inc NUL) reaches here, consume
* the next dirent too */
}
parts
;
}
u
;
u8
extended_name
[
32
];
}
afs_dirent_t
;
...
...
@@ -256,7 +257,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
/* got a valid entry */
dire
=
&
block
->
dirents
[
offset
];
nlen
=
strnlen
(
dire
->
parts
.
name
,
sizeof
(
*
block
)
-
offset
*
sizeof
(
afs_dirent_t
));
nlen
=
strnlen
(
dire
->
u
.
name
,
sizeof
(
*
block
)
-
offset
*
sizeof
(
afs_dirent_t
));
_debug
(
"ENT[%Zu.%u]: %s %Zu
\"
%s
\"\n
"
,
blkoff
/
sizeof
(
afs_dir_block_t
),
offset
,
...
...
@@ -288,11 +289,11 @@ static int afs_dir_iterate_block(unsigned *fpos,
/* found the next entry */
ret
=
filldir
(
cookie
,
dire
->
parts
.
name
,
dire
->
u
.
name
,
nlen
,
blkoff
+
offset
*
sizeof
(
afs_dirent_t
),
ntohl
(
dire
->
parts
.
vnode
),
filldir
==
afs_dir_lookup_filldir
?
dire
->
parts
.
unique
:
DT_UNKNOWN
);
ntohl
(
dire
->
u
.
vnode
),
filldir
==
afs_dir_lookup_filldir
?
dire
->
u
.
unique
:
DT_UNKNOWN
);
if
(
ret
<
0
)
{
_leave
(
" = 0 [full]"
);
return
0
;
...
...
@@ -414,7 +415,8 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, lof
/*
* look up an entry in a directory
*/
static
struct
dentry
*
afs_dir_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
static
struct
dentry
*
afs_dir_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
afs_dir_lookup_cookie
cookie
;
struct
afs_super_info
*
as
;
...
...
@@ -423,11 +425,11 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, s
unsigned
fpos
;
int
ret
;
_enter
(
"{%lu},
{%s}"
,
dir
->
i_ino
,
dentry
->
d_name
.
name
);
_enter
(
"{%lu},
%p{%s}"
,
dir
->
i_ino
,
dentry
,
dentry
->
d_name
.
name
);
/* insanity checks first */
if
(
sizeof
(
afs_dir_block_t
)
!=
2048
)
BUG
(
);
if
(
sizeof
(
afs_dirent_t
)
!=
32
)
BUG
(
);
BUG_ON
(
sizeof
(
afs_dir_block_t
)
!=
2048
);
BUG_ON
(
sizeof
(
afs_dirent_t
)
!=
32
);
if
(
dentry
->
d_name
.
len
>
255
)
{
_leave
(
" = -ENAMETOOLONG"
);
...
...
@@ -495,9 +497,11 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
unsigned
fpos
;
int
ret
;
_enter
(
"%s,%p"
,
dentry
->
d_name
.
name
,
nd
);
_enter
(
"{sb=%p n=%s},"
,
dentry
->
d_sb
,
dentry
->
d_name
.
name
);
/* 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
;
...
...
fs/afs/file.c
View file @
7a9df5e2
...
...
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include "volume.h"
#include "vnode.h"
#include <rxrpc/call.h>
...
...
@@ -27,6 +28,8 @@ static int afs_file_release(struct inode *inode, struct file *file);
#endif
static
int
afs_file_readpage
(
struct
file
*
file
,
struct
page
*
page
);
static
int
afs_file_invalidatepage
(
struct
page
*
page
,
unsigned
long
offset
);
static
int
afs_file_releasepage
(
struct
page
*
page
,
int
gfp_flags
);
static
ssize_t
afs_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
size
,
loff_t
*
off
);
...
...
@@ -37,7 +40,7 @@ struct inode_operations afs_file_inode_operations = {
struct
file_operations
afs_file_file_operations
=
{
.
read
=
generic_file_read
,
.
write
=
afs_file_write
,
.
mmap
=
generic_file_
readonly_
mmap
,
.
mmap
=
generic_file_mmap
,
#if 0
.open = afs_file_open,
.release = afs_file_release,
...
...
@@ -47,6 +50,10 @@ struct file_operations afs_file_file_operations = {
struct
address_space_operations
afs_fs_aops
=
{
.
readpage
=
afs_file_readpage
,
.
sync_page
=
block_sync_page
,
.
set_page_dirty
=
__set_page_dirty_nobuffers
,
.
releasepage
=
afs_file_releasepage
,
.
invalidatepage
=
afs_file_invalidatepage
,
};
/*****************************************************************************/
...
...
@@ -64,6 +71,40 @@ static ssize_t afs_file_write(struct file *file, const char *buf, size_t size, l
return
-
EIO
;
}
/* end afs_file_write() */
/*****************************************************************************/
/*
* deal with notification that a page was read from the cache
*/
#ifdef AFS_CACHING_SUPPORT
static
void
afs_file_readpage_read_complete
(
void
*
cookie_data
,
struct
page
*
page
,
void
*
data
,
int
error
)
{
_enter
(
"%p,%p,%p,%d"
,
cookie_data
,
page
,
data
,
error
);
if
(
error
)
SetPageError
(
page
);
else
SetPageUptodate
(
page
);
unlock_page
(
page
);
}
/* end afs_file_readpage_read_complete() */
#endif
/*****************************************************************************/
/*
* deal with notification that a page was written to the cache
*/
#ifdef AFS_CACHING_SUPPORT
static
void
afs_file_readpage_write_complete
(
void
*
cookie_data
,
struct
page
*
page
,
void
*
data
,
int
error
)
{
_enter
(
"%p,%p,%p,%d"
,
cookie_data
,
page
,
data
,
error
);
unlock_page
(
page
);
}
/* end afs_file_readpage_write_complete() */
#endif
/*****************************************************************************/
/*
* AFS read page from file (or symlink)
...
...
@@ -71,6 +112,9 @@ static ssize_t afs_file_write(struct file *file, const char *buf, size_t size, l
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
inode
*
inode
;
afs_vnode_t
*
vnode
;
int
ret
;
...
...
@@ -88,28 +132,73 @@ static int afs_file_readpage(struct file *file, struct page *page)
if
(
vnode
->
flags
&
AFS_VNODE_DELETED
)
goto
error
;
/* work out how much to get and from where */
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
);
/* read the contents of the file from the server into the page */
ret
=
afs_vnode_fetch_data
(
vnode
,
&
desc
);
kunmap
(
page
);
if
(
ret
<
0
)
{
if
(
ret
==-
ENOENT
)
{
_debug
(
"got NOENT from server - marking file deleted and stale"
);
vnode
->
flags
|=
AFS_VNODE_DELETED
;
ret
=
-
ESTALE
;
}
#ifdef AFS_CACHING_SUPPORT
ret
=
cachefs_page_get_private
(
page
,
&
pageio
,
GFP_NOIO
);
if
(
ret
<
0
)
goto
error
;
}
SetPageUptodate
(
page
);
unlock_page
(
page
);
/* is it cached? */
ret
=
cachefs_read_or_alloc_page
(
vnode
->
cache
,
page
,
afs_file_readpage_read_complete
,
NULL
,
GFP_KERNEL
);
#else
ret
=
-
ENOBUFS
;
#endif
switch
(
ret
)
{
/* read BIO submitted and wb-journal entry found */
case
1
:
BUG
();
// TODO - handle wb-journal match
/* read BIO submitted (page in cache) */
case
0
:
break
;
/* no page available in cache */
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
);
/* read the contents of the file from the server into the page */
ret
=
afs_vnode_fetch_data
(
vnode
,
&
desc
);
kunmap
(
page
);
if
(
ret
<
0
)
{
if
(
ret
==-
ENOENT
)
{
_debug
(
"got NOENT from server - marking file deleted and stale"
);
vnode
->
flags
|=
AFS_VNODE_DELETED
;
ret
=
-
ESTALE
;
}
#ifdef AFS_CACHING_SUPPORT
cachefs_uncache_page
(
vnode
->
cache
,
page
);
#endif
goto
error
;
}
SetPageUptodate
(
page
);
#ifdef AFS_CACHING_SUPPORT
if
(
cachefs_write_page
(
vnode
->
cache
,
page
,
afs_file_readpage_write_complete
,
NULL
,
GFP_KERNEL
)
!=
0
)
{
cachefs_uncache_page
(
vnode
->
cache
,
page
);
unlock_page
(
page
);
}
#else
unlock_page
(
page
);
#endif
}
_leave
(
" = 0"
);
return
0
;
...
...
@@ -122,3 +211,83 @@ static int afs_file_readpage(struct file *file, struct page *page)
return
ret
;
}
/* end afs_file_readpage() */
/*****************************************************************************/
/*
* get a page cookie for the specified page
*/
#ifdef AFS_CACHING_SUPPORT
int
afs_cache_get_page_cookie
(
struct
page
*
page
,
struct
cachefs_page
**
_page_cookie
)
{
int
ret
;
_enter
(
""
);
ret
=
cachefs_page_get_private
(
page
,
_page_cookie
,
GFP_NOIO
);
_leave
(
" = %d"
,
ret
);
return
ret
;
}
/* end afs_cache_get_page_cookie() */
#endif
/*****************************************************************************/
/*
* invalidate part or all of a page
*/
static
int
afs_file_invalidatepage
(
struct
page
*
page
,
unsigned
long
offset
)
{
int
ret
=
1
;
_enter
(
"{%lu},%lu"
,
page
->
index
,
offset
);
BUG_ON
(
!
PageLocked
(
page
));
if
(
PagePrivate
(
page
))
{
#ifdef AFS_CACHING_SUPPORT
struct
afs_vnode
*
vnode
=
AFS_FS_I
(
page
->
mapping
->
host
);
cachefs_uncache_page
(
vnode
->
cache
,
page
);
#endif
/*
* We release buffers only if the entire page is being invalidated.
* The get_block cached value has been unconditionally invalidated,
* so real IO is not possible anymore.
*/
if
(
offset
==
0
)
{
BUG_ON
(
!
PageLocked
(
page
));
ret
=
0
;
if
(
!
PageWriteback
(
page
))
ret
=
page
->
mapping
->
a_ops
->
releasepage
(
page
,
0
);
}
}
_leave
(
" = %d"
,
ret
);
return
ret
;
}
/* end afs_file_invalidatepage() */
/*****************************************************************************/
/*
* release a page and cleanup its private data
*/
static
int
afs_file_releasepage
(
struct
page
*
page
,
int
gfp_flags
)
{
struct
cachefs_page
*
pageio
;
_enter
(
"{%lu},%x"
,
page
->
index
,
gfp_flags
);
if
(
PagePrivate
(
page
))
{
#ifdef AFS_CACHING_SUPPORT
struct
afs_vnode
*
vnode
=
AFS_FS_I
(
page
->
mapping
->
host
);
cachefs_uncache_page
(
vnode
->
cache
,
page
);
#endif
pageio
=
(
struct
cachefs_page
*
)
page
->
private
;
page
->
private
=
0
;
ClearPagePrivate
(
page
);
if
(
pageio
)
kfree
(
pageio
);
}
_leave
(
" = 0"
);
return
0
;
}
/* end afs_file_releasepage() */
fs/afs/inode.c
View file @
7a9df5e2
...
...
@@ -69,17 +69,16 @@ static int afs_inode_map_status(afs_vnode_t *vnode)
inode
->
i_uid
=
vnode
->
status
.
owner
;
inode
->
i_gid
=
0
;
inode
->
i_size
=
vnode
->
status
.
size
;
inode
->
i_atime
.
tv_sec
=
inode
->
i_mtime
.
tv_sec
=
inode
->
i_ctime
.
tv_sec
=
vnode
->
status
.
mtime_server
;
inode
->
i_atime
.
tv_nsec
=
inode
->
i_mtime
.
tv_nsec
=
inode
->
i_ctime
.
tv_nsec
=
0
;
inode
->
i_ctime
.
tv_sec
=
vnode
->
status
.
mtime_server
;
inode
->
i_ctime
.
tv_nsec
=
0
;
inode
->
i_atime
=
inode
->
i_mtime
=
inode
->
i_ctime
;
inode
->
i_blksize
=
PAGE_CACHE_SIZE
;
inode
->
i_blocks
=
0
;
inode
->
i_version
=
vnode
->
fid
.
unique
;
inode
->
i_mapping
->
a_ops
=
&
afs_fs_aops
;
/* check to see whether a symbolic link is really a mountpoint */
if
(
vnode
->
status
.
type
==
AFS_FTYPE_SYMLINK
)
{
if
(
vnode
->
status
.
type
==
AFS_FTYPE_SYMLINK
)
{
afs_mntpt_check_symlink
(
vnode
);
if
(
vnode
->
flags
&
AFS_VNODE_MOUNTPOINT
)
{
...
...
@@ -105,7 +104,7 @@ int afs_inode_fetch_status(struct inode *inode)
ret
=
afs_vnode_fetch_status
(
vnode
);
if
(
ret
==
0
)
if
(
ret
==
0
)
ret
=
afs_inode_map_status
(
vnode
);
return
ret
;
...
...
@@ -120,8 +119,8 @@ static int afs_iget5_test(struct inode *inode, void *opaque)
{
struct
afs_iget_data
*
data
=
opaque
;
/* only match inodes with the same version number */
return
inode
->
i_ino
==
data
->
fid
.
vnode
&&
inode
->
i_version
==
data
->
fid
.
unique
;
return
inode
->
i_ino
==
data
->
fid
.
vnode
&&
inode
->
i_version
==
data
->
fid
.
unique
;
}
/* end afs_iget5_test() */
/*****************************************************************************/
...
...
@@ -145,20 +144,22 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
/*
* inode retrieval
*/
inline
int
afs_iget
(
struct
super_block
*
sb
,
afs_fid_t
*
fid
,
struct
inode
**
_inode
)
inline
int
afs_iget
(
struct
super_block
*
sb
,
afs_fid_t
*
fid
,
struct
inode
**
_inode
)
{
struct
afs_iget_data
data
=
{
.
fid
=
*
fid
};
struct
afs_iget_data
data
=
{
fid
:
*
fid
};
struct
afs_super_info
*
as
;
struct
afs_vnode
*
vnode
;
struct
inode
*
inode
;
afs_vnode_t
*
vnode
;
int
ret
;
_enter
(
",{%u,%u,%u},,"
,
fid
->
vid
,
fid
->
vnode
,
fid
->
unique
);
_enter
(
",{%u,%u,%u},,"
,
fid
->
vid
,
fid
->
vnode
,
fid
->
unique
);
as
=
sb
->
s_fs_info
;
data
.
volume
=
as
->
volume
;
inode
=
iget5_locked
(
sb
,
fid
->
vnode
,
afs_iget5_test
,
afs_iget5_set
,
&
data
);
inode
=
iget5_locked
(
sb
,
fid
->
vnode
,
afs_iget5_test
,
afs_iget5_set
,
&
data
);
if
(
!
inode
)
{
_leave
(
" = -ENOMEM"
);
return
-
ENOMEM
;
...
...
@@ -173,10 +174,19 @@ inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inod
*
_inode
=
inode
;
else
iput
(
inode
);
_leave
(
" = %d"
,
ret
);
_leave
(
" = %d"
,
ret
);
return
ret
;
}
#ifdef AFS_CACHING_SUPPORT
/* set up caching before reading the status, as fetch-status reads the
* first page of symlinks to see if they're really mntpts */
cachefs_acquire_cookie
(
vnode
->
volume
->
cache
,
NULL
,
vnode
,
&
vnode
->
cache
);
#endif
/* okay... it's a new inode */
vnode
->
flags
|=
AFS_VNODE_CHANGED
;
ret
=
afs_inode_fetch_status
(
inode
);
...
...
@@ -187,11 +197,11 @@ inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inod
unlock_new_inode
(
inode
);
*
_inode
=
inode
;
_leave
(
" = 0 [CB { v=%u x=%lu t=%u
nix=%u }
]"
,
_leave
(
" = 0 [CB { v=%u x=%lu t=%u
} c=%p
]"
,
vnode
->
cb_version
,
vnode
->
cb_timeout
.
timo_jif
,
vnode
->
cb_type
,
vnode
->
nix
vnode
->
cache
);
return
0
;
...
...
@@ -201,7 +211,7 @@ inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inod
unlock_new_inode
(
inode
);
iput
(
inode
);
_leave
(
" = %d [bad]"
,
ret
);
_leave
(
" = %d [bad]"
,
ret
);
return
ret
;
}
/* end afs_iget() */
...
...
@@ -209,7 +219,8 @@ inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inod
/*
* read the attributes of an inode
*/
int
afs_inode_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
)
int
afs_inode_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
)
{
struct
inode
*
inode
;
afs_vnode_t
*
vnode
;
...
...
@@ -217,23 +228,25 @@ int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
inode
=
dentry
->
d_inode
;
_enter
(
"{ ino=%lu v=%lu }"
,
inode
->
i_ino
,
inode
->
i_version
);
_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
);
if
(
ret
==
-
ENOENT
)
{
_leave
(
" = %d [%d %p]"
,
ret
,
atomic_read
(
&
dentry
->
d_count
),
dentry
->
d_inode
);
return
ret
;
}
else
if
(
ret
<
0
)
{
else
if
(
ret
<
0
)
{
make_bad_inode
(
inode
);
_leave
(
" = %d"
,
ret
);
_leave
(
" = %d"
,
ret
);
return
ret
;
}
/* transfer attributes from the inode structure to the stat structure */
generic_fillattr
(
inode
,
stat
);
/* 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
,
...
...
@@ -261,9 +274,14 @@ void afs_clear_inode(struct inode *inode)
vnode
->
cb_type
);
if
(
inode
->
i_ino
!=
vnode
->
fid
.
vnode
)
BUG
(
);
BUG_ON
(
inode
->
i_ino
!=
vnode
->
fid
.
vnode
);
afs_vnode_give_up_callback
(
vnode
);
#ifdef AFS_CACHING_SUPPORT
cachefs_relinquish_cookie
(
vnode
->
cache
,
0
);
vnode
->
cache
=
NULL
;
#endif
_leave
(
""
);
}
/* end afs_clear_inode() */
fs/afs/internal.h
View file @
7a9df5e2
...
...
@@ -26,7 +26,7 @@
#define kproto(FMT, a...) printk("### "FMT"\n" , ## a)
#define knet(FMT, a...) printk(FMT"\n" , ## a)
#if
0
#if
def __KDEBUG
#define _enter(FMT, a...) kenter(FMT , ## a)
#define _leave(FMT, a...) kleave(FMT , ## a)
#define _debug(FMT, a...) kdebug(FMT , ## a)
...
...
@@ -56,6 +56,9 @@ static inline void afs_discard_my_signals(void)
*/
extern
struct
rw_semaphore
afs_proc_cells_sem
;
extern
struct
list_head
afs_proc_cells
;
#ifdef AFS_CACHING_SUPPORT
extern
struct
cachefs_index_def
afs_cache_cell_index_def
;
#endif
/*
* dir.c
...
...
@@ -70,6 +73,10 @@ extern struct address_space_operations afs_fs_aops;
extern
struct
inode_operations
afs_file_inode_operations
;
extern
struct
file_operations
afs_file_file_operations
;
#ifdef AFS_CACHING_SUPPORT
extern
int
afs_cache_get_page_cookie
(
struct
page
*
page
,
struct
cachefs_page
**
_page_cookie
);
#endif
/*
* inode.c
*/
...
...
@@ -77,11 +84,23 @@ extern int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inod
extern
int
afs_inode_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
);
extern
void
afs_clear_inode
(
struct
inode
*
inode
);
/*
* main.c
*/
#ifdef AFS_CACHING_SUPPORT
extern
struct
cachefs_netfs
afs_cache_netfs
;
#endif
/*
* mntpt.c
*/
extern
struct
inode_operations
afs_mntpt_inode_operations
;
extern
struct
file_operations
afs_mntpt_file_operations
;
#ifdef AFS_AUTOMOUNT_SUPPORT
extern
struct
afs_timer
afs_mntpt_expiry_timer
;
extern
struct
afs_timer_ops
afs_mntpt_expiry_timer_ops
;
extern
unsigned
long
afs_mntpt_expiry_timeout
;
#endif
extern
int
afs_mntpt_check_symlink
(
afs_vnode_t
*
vnode
);
...
...
fs/afs/kafsasyncd.c
View file @
7a9df5e2
...
...
@@ -153,8 +153,7 @@ static int kafsasyncd(void *arg)
spin_lock
(
&
kafsasyncd_async_lock
);
/* fold the busy and attention queues together */
list_splice
(
&
kafsasyncd_async_busyq
,
&
kafsasyncd_async_attnq
);
list_del_init
(
&
kafsasyncd_async_busyq
);
list_splice_init
(
&
kafsasyncd_async_busyq
,
&
kafsasyncd_async_attnq
);
/* dequeue kafsasyncd from all their wait queues */
list_for_each
(
_p
,
&
kafsasyncd_async_attnq
)
{
...
...
@@ -197,6 +196,7 @@ void afs_kafsasyncd_begin_op(afs_async_op_t *op)
spin_lock
(
&
kafsasyncd_async_lock
);
init_waitqueue_entry
(
&
op
->
waiter
,
kafsasyncd_task
);
add_wait_queue
(
&
op
->
call
->
waitq
,
&
op
->
waiter
);
list_del
(
&
op
->
link
);
list_add_tail
(
&
op
->
link
,
&
kafsasyncd_async_busyq
);
...
...
@@ -238,7 +238,10 @@ void afs_kafsasyncd_terminate_op(afs_async_op_t *op)
spin_lock
(
&
kafsasyncd_async_lock
);
list_del_init
(
&
op
->
link
);
if
(
!
list_empty
(
&
op
->
link
))
{
list_del_init
(
&
op
->
link
);
remove_wait_queue
(
&
op
->
call
->
waitq
,
&
op
->
waiter
);
}
spin_unlock
(
&
kafsasyncd_async_lock
);
...
...
fs/afs/kafstimod.c
View file @
7a9df5e2
...
...
@@ -82,7 +82,7 @@ static int kafstimod(void *arg)
for
(;;)
{
unsigned
long
jif
;
un
signed
long
timeout
;
signed
long
timeout
;
/* deal with the server being asked to die */
if
(
kafstimod_die
)
{
...
...
@@ -98,18 +98,18 @@ static int kafstimod(void *arg)
spin_lock
(
&
kafstimod_lock
);
if
(
list_empty
(
&
kafstimod_list
))
{
timeout
=
MAX_SCHEDULE_TIMEOUT
;
}
else
{
unsigned
long
tmo
;
timer
=
list_entry
(
kafstimod_list
.
next
,
afs_timer_t
,
link
);
tmo
=
timer
->
timo_jif
;
}
else
{
timer
=
list_entry
(
kafstimod_list
.
next
,
afs_timer_t
,
link
);
timeout
=
timer
->
timo_jif
;
jif
=
jiffies
;
if
(
time_before_eq
(
tmo
,
jif
))
if
(
time_before_eq
(
(
unsigned
long
)
timeout
,
jif
))
goto
immediate
;
timeout
=
(
long
)
tmo
-
(
long
)
jiffies
;
else
{
timeout
=
(
long
)
timeout
-
(
long
)
jiffies
;
}
}
spin_unlock
(
&
kafstimod_lock
);
...
...
@@ -170,7 +170,7 @@ void afs_kafstimod_add_timer(afs_timer_t *timer, unsigned long timeout)
wake_up
(
&
kafstimod_sleepq
);
_leave
(
""
);
}
/* end afs_kafstimod_
queue_vlocation
() */
}
/* end afs_kafstimod_
add_timer
() */
/*****************************************************************************/
/*
...
...
fs/afs/main.c
View file @
7a9df5e2
...
...
@@ -17,6 +17,7 @@
#include <rxrpc/transport.h>
#include <rxrpc/call.h>
#include <rxrpc/peer.h>
#include "cache.h"
#include "cell.h"
#include "server.h"
#include "fsclient.h"
...
...
@@ -47,6 +48,18 @@ static struct rxrpc_peer_ops afs_peer_ops = {
struct
list_head
afs_cb_hash_tbl
[
AFS_CB_HASH_COUNT
];
spinlock_t
afs_cb_hash_lock
=
SPIN_LOCK_UNLOCKED
;
#ifdef AFS_CACHING_SUPPORT
static
struct
cachefs_netfs_operations
afs_cache_ops
=
{
.
get_page_cookie
=
afs_cache_get_page_cookie
,
};
struct
cachefs_netfs
afs_cache_netfs
=
{
.
name
=
"afs"
,
.
version
=
0
,
.
ops
=
&
afs_cache_ops
,
};
#endif
/*****************************************************************************/
/*
* initialise the AFS client FS module
...
...
@@ -64,34 +77,41 @@ static int afs_init(void)
/* register the /proc stuff */
ret
=
afs_proc_init
();
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
#ifdef AFS_CACHING_SUPPORT
/* we want to be able to cache */
ret
=
cachefs_register_netfs
(
&
afs_cache_netfs
,
&
afs_cache_cell_index_def
);
if
(
ret
<
0
)
goto
error
;
#endif
/* initialise the cell DB */
ret
=
afs_cell_init
();
if
(
ret
<
0
)
goto
error
;
if
(
ret
<
0
)
goto
error
_cache
;
/* start the timeout daemon */
ret
=
afs_kafstimod_start
();
if
(
ret
<
0
)
goto
error
;
if
(
ret
<
0
)
goto
error
_cache
;
/* start the async operation daemon */
ret
=
afs_kafsasyncd_start
();
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
error_kafstimod
;
/* create the RxRPC transport */
ret
=
rxrpc_create_transport
(
7001
,
&
afs_transport
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
error_kafsasyncd
;
afs_transport
->
peer_ops
=
&
afs_peer_ops
;
/* register the filesystems */
ret
=
afs_fs_init
();
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
error_transport
;
return
ret
;
...
...
@@ -102,7 +122,11 @@ static int afs_init(void)
afs_kafsasyncd_stop
();
error_kafstimod:
afs_kafstimod_stop
();
error_cache:
#ifdef AFS_CACHING_SUPPORT
cachefs_unregister_netfs
(
&
afs_cache_netfs
);
error:
#endif
afs_cell_purge
();
afs_proc_cleanup
();
printk
(
KERN_ERR
"kAFS: failed to register: %d
\n
"
,
ret
);
...
...
@@ -122,6 +146,9 @@ static void __exit afs_exit(void)
afs_kafstimod_stop
();
afs_kafsasyncd_stop
();
afs_cell_purge
();
#ifdef AFS_CACHING_SUPPORT
cachefs_unregister_netfs
(
&
afs_cache_netfs
);
#endif
afs_proc_cleanup
();
}
/* end afs_exit() */
...
...
@@ -142,7 +169,7 @@ static int afs_adding_peer(struct rxrpc_peer *peer)
/* determine which server the peer resides in (if any) */
ret
=
afs_server_find_by_peer
(
peer
,
&
server
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
/* none that we recognise, so abort */
_debug
(
"Server %p{u=%d}
\n
"
,
server
,
atomic_read
(
&
server
->
usage
));
...
...
@@ -191,3 +218,48 @@ static void afs_discarding_peer(struct rxrpc_peer *peer)
_leave
(
""
);
}
/* end afs_discarding_peer() */
/*****************************************************************************/
/*
* clear the dead space between task_struct and kernel stack
* - called by supplying -finstrument-functions to gcc
*/
#if 0
void __cyg_profile_func_enter (void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_enter (void *this_fn, void *call_site)
{
asm volatile(" movl %%esp,%%edi \n"
" andl %0,%%edi \n"
" addl %1,%%edi \n"
" movl %%esp,%%ecx \n"
" subl %%edi,%%ecx \n"
" shrl $2,%%ecx \n"
" movl $0xedededed,%%eax \n"
" rep stosl \n"
:
: "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
: "eax", "ecx", "edi", "memory", "cc"
);
}
void __cyg_profile_func_exit(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site)
{
asm volatile(" movl %%esp,%%edi \n"
" andl %0,%%edi \n"
" addl %1,%%edi \n"
" movl %%esp,%%ecx \n"
" subl %%edi,%%ecx \n"
" shrl $2,%%ecx \n"
" movl $0xdadadada,%%eax \n"
" rep stosl \n"
:
: "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
: "eax", "ecx", "edi", "memory", "cc"
);
}
#endif
fs/afs/mntpt.c
View file @
7a9df5e2
...
...
@@ -16,24 +16,52 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/namespace.h>
#include "super.h"
#include "cell.h"
#include "volume.h"
#include "vnode.h"
#include "internal.h"
static
struct
dentry
*
afs_mntpt_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
);
static
struct
dentry
*
afs_mntpt_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
);
static
int
afs_mntpt_open
(
struct
inode
*
inode
,
struct
file
*
file
);
#ifdef AFS_AUTOMOUNT_SUPPORT
static
int
afs_mntpt_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
);
#endif
struct
file_operations
afs_mntpt_file_operations
=
{
.
open
=
afs_mntpt_open
,
};
struct
inode_operations
afs_mntpt_inode_operations
=
{
.
lookup
=
afs_mntpt_lookup
,
#ifdef AFS_AUTOMOUNT_SUPPORT
.
follow_link
=
afs_mntpt_follow_link
,
#endif
.
readlink
=
page_readlink
,
.
getattr
=
afs_inode_getattr
,
};
#ifdef AFS_AUTOMOUNT_SUPPORT
static
LIST_HEAD
(
afs_vfsmounts
);
static
void
afs_mntpt_expiry_timed_out
(
struct
afs_timer
*
timer
);
struct
afs_timer_ops
afs_mntpt_expiry_timer_ops
=
{
.
timed_out
=
afs_mntpt_expiry_timed_out
,
};
struct
afs_timer
afs_mntpt_expiry_timer
;
unsigned
long
afs_mntpt_expiry_timeout
=
20
;
#endif
/*****************************************************************************/
/*
* check a symbolic link to see whether it actually encodes a mountpoint
...
...
@@ -93,8 +121,17 @@ int afs_mntpt_check_symlink(afs_vnode_t *vnode)
/*
* no valid lookup procedure on this sort of dir
*/
static
struct
dentry
*
afs_mntpt_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
static
struct
dentry
*
afs_mntpt_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
kenter
(
"%p,%p{%p{%s},%s}"
,
dir
,
dentry
,
dentry
->
d_parent
,
dentry
->
d_parent
?
dentry
->
d_parent
->
d_name
.
name
:
(
const
unsigned
char
*
)
""
,
dentry
->
d_name
.
name
);
return
ERR_PTR
(
-
EREMOTE
);
}
/* end afs_mntpt_lookup() */
...
...
@@ -104,5 +141,146 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry,
*/
static
int
afs_mntpt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
kenter
(
"%p,%p{%p{%s},%s}"
,
inode
,
file
,
file
->
f_dentry
->
d_parent
,
file
->
f_dentry
->
d_parent
?
file
->
f_dentry
->
d_parent
->
d_name
.
name
:
(
const
unsigned
char
*
)
""
,
file
->
f_dentry
->
d_name
.
name
);
return
-
EREMOTE
;
}
/* end afs_mntpt_open() */
#ifdef AFS_AUTOMOUNT_SUPPORT
/*****************************************************************************/
/*
* create a vfsmount to be automounted
*/
static
struct
vfsmount
*
afs_mntpt_do_automount
(
struct
dentry
*
mntpt
)
{
struct
afs_super_info
*
super
;
struct
vfsmount
*
mnt
;
struct
page
*
page
=
NULL
;
size_t
size
;
char
*
buf
,
*
devname
=
NULL
,
*
options
=
NULL
;
int
ret
;
kenter
(
"{%s}"
,
mntpt
->
d_name
.
name
);
BUG_ON
(
!
mntpt
->
d_inode
);
ret
=
-
EINVAL
;
size
=
mntpt
->
d_inode
->
i_size
;
if
(
size
>
PAGE_SIZE
-
1
)
goto
error
;
ret
=
-
ENOMEM
;
devname
=
(
char
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
devname
)
goto
error
;
options
=
(
char
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
options
)
goto
error
;
/* read the contents of the AFS special symlink */
page
=
read_cache_page
(
mntpt
->
d_inode
->
i_mapping
,
0
,
(
filler_t
*
)
mntpt
->
d_inode
->
i_mapping
->
a_ops
->
readpage
,
NULL
);
if
(
IS_ERR
(
page
))
{
ret
=
PTR_ERR
(
page
);
goto
error
;
}
ret
=
-
EIO
;
wait_on_page_locked
(
page
);
if
(
!
PageUptodate
(
page
)
||
PageError
(
page
))
goto
error
;
buf
=
kmap
(
page
);
memcpy
(
devname
,
buf
,
size
);
kunmap
(
page
);
page_cache_release
(
page
);
page
=
NULL
;
/* work out what options we want */
super
=
AFS_FS_S
(
mntpt
->
d_sb
);
memcpy
(
options
,
"cell="
,
5
);
strcpy
(
options
+
5
,
super
->
volume
->
cell
->
name
);
if
(
super
->
volume
->
type
==
AFSVL_RWVOL
)
strcat
(
options
,
",rwpath"
);
/* try and do the mount */
kdebug
(
"--- attempting mount %s -o %s ---"
,
devname
,
options
);
mnt
=
do_kern_mount
(
"afs"
,
0
,
devname
,
options
);
kdebug
(
"--- mount result %p ---"
,
mnt
);
free_page
((
unsigned
long
)
devname
);
free_page
((
unsigned
long
)
options
);
kleave
(
" = %p"
,
mnt
);
return
mnt
;
error:
if
(
page
)
page_cache_release
(
page
);
if
(
devname
)
free_page
((
unsigned
long
)
devname
);
if
(
options
)
free_page
((
unsigned
long
)
options
);
kleave
(
" = %d"
,
ret
);
return
ERR_PTR
(
ret
);
}
/* end afs_mntpt_do_automount() */
/*****************************************************************************/
/*
* follow a link from a mountpoint directory, thus causing it to be mounted
*/
static
int
afs_mntpt_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
nameidata
newnd
;
struct
vfsmount
*
newmnt
;
int
err
;
kenter
(
"%p{%s},{%s:%p{%s}}"
,
dentry
,
dentry
->
d_name
.
name
,
nd
->
mnt
->
mnt_devname
,
dentry
,
nd
->
dentry
->
d_name
.
name
);
newmnt
=
afs_mntpt_do_automount
(
dentry
);
if
(
IS_ERR
(
newmnt
))
return
PTR_ERR
(
newmnt
);
struct_cpy
(
&
newnd
,
nd
);
newnd
.
dentry
=
dentry
;
err
=
do_add_mount
(
newmnt
,
&
newnd
,
0
,
&
afs_vfsmounts
);
if
(
!
err
)
{
path_release
(
nd
);
mntget
(
newmnt
);
nd
->
mnt
=
newmnt
;
dget
(
newmnt
->
mnt_root
);
nd
->
dentry
=
newmnt
->
mnt_root
;
}
kleave
(
" = %d"
,
err
);
return
err
;
}
/* end afs_mntpt_follow_link() */
/*****************************************************************************/
/*
* handle mountpoint expiry timer going off
*/
static
void
afs_mntpt_expiry_timed_out
(
struct
afs_timer
*
timer
)
{
kenter
(
""
);
mark_mounts_for_expiry
(
&
afs_vfsmounts
);
afs_kafstimod_add_timer
(
&
afs_mntpt_expiry_timer
,
afs_mntpt_expiry_timeout
*
HZ
);
kleave
(
""
);
}
/* end afs_mntpt_expiry_timed_out() */
#endif
fs/afs/mount.h
View file @
7a9df5e2
...
...
@@ -17,7 +17,7 @@ struct afs_mountdata {
const
char
*
cell
;
/* name of cell containing volume */
const
char
*
cache
;
/* name of cache block device */
size_t
nservers
;
/* number of server addresses listed */
u
_
int32_t
servers
[
10
];
/* IP addresses of servers in this cell */
uint32_t
servers
[
10
];
/* IP addresses of servers in this cell */
};
#endif
/* _LINUX_AFS_MOUNT_H */
fs/afs/server.c
View file @
7a9df5e2
...
...
@@ -148,6 +148,9 @@ void afs_put_server(afs_server_t *server)
{
afs_cell_t
*
cell
;
if
(
!
server
)
return
;
_enter
(
"%p"
,
server
);
cell
=
server
->
cell
;
...
...
fs/afs/super.c
View file @
7a9df5e2
...
...
@@ -29,15 +29,22 @@
#define AFS_FS_MAGIC 0x6B414653
/* 'kAFS' */
struct
afs_mount_params
{
int
rwpath
;
struct
afs_cell
*
default_cell
;
struct
afs_volume
*
volume
;
};
static
inline
char
*
strdup
(
const
char
*
s
)
{
char
*
ns
=
kmalloc
(
strlen
(
s
)
+
1
,
GFP_KERNEL
);
char
*
ns
=
kmalloc
(
strlen
(
s
)
+
1
,
GFP_KERNEL
);
if
(
ns
)
strcpy
(
ns
,
s
);
strcpy
(
ns
,
s
);
return
ns
;
}
static
void
afs_i_init_once
(
void
*
foo
,
kmem_cache_t
*
cachep
,
unsigned
long
flags
);
static
void
afs_i_init_once
(
void
*
foo
,
kmem_cache_t
*
cachep
,
unsigned
long
flags
);
static
struct
super_block
*
afs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
...
...
@@ -66,6 +73,7 @@ static struct super_operations afs_super_ops = {
};
static
kmem_cache_t
*
afs_inode_cachep
;
static
atomic_t
afs_count_active_inodes
;
/*****************************************************************************/
/*
...
...
@@ -75,16 +83,22 @@ int __init afs_fs_init(void)
{
int
ret
;
kenter
(
""
);
_enter
(
""
);
#ifdef AFS_AUTOMOUNT_SUPPORT
afs_timer_init
(
&
afs_mntpt_expiry_timer
,
&
afs_mntpt_expiry_timer_ops
);
#endif
/* create ourselves an inode cache */
atomic_set
(
&
afs_count_active_inodes
,
0
);
ret
=
-
ENOMEM
;
afs_inode_cachep
=
kmem_cache_create
(
"afs_inode_cache"
,
sizeof
(
afs_vnode_t
),
0
,
SLAB_HWCACHE_ALIGN
|
SLAB_RECLAIM_ACCOUNT
,
afs_i_init_once
,
NULL
);
sizeof
(
afs_vnode_t
),
0
,
SLAB_HWCACHE_ALIGN
,
afs_i_init_once
,
NULL
);
if
(
!
afs_inode_cachep
)
{
printk
(
KERN_NOTICE
"kAFS: Failed to allocate inode cache
\n
"
);
return
ret
;
...
...
@@ -92,9 +106,9 @@ int __init afs_fs_init(void)
/* now export our filesystem to lesser mortals */
ret
=
register_filesystem
(
&
afs_fs_type
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
kmem_cache_destroy
(
afs_inode_cachep
);
kleave
(
" = %d"
,
ret
);
kleave
(
" = %d"
,
ret
);
return
ret
;
}
...
...
@@ -108,11 +122,16 @@ int __init afs_fs_init(void)
*/
void
__exit
afs_fs_exit
(
void
)
{
/* destroy our private inode cache */
kmem_cache_destroy
(
afs_inode_cachep
);
unregister_filesystem
(
&
afs_fs_type
);
if
(
atomic_read
(
&
afs_count_active_inodes
)
!=
0
)
{
printk
(
"kAFS: %d active inode objects still present
\n
"
,
atomic_read
(
&
afs_count_active_inodes
));
BUG
();
}
kmem_cache_destroy
(
afs_inode_cachep
);
}
/* end afs_fs_exit() */
/*****************************************************************************/
...
...
@@ -122,27 +141,12 @@ void __exit afs_fs_exit(void)
static
int
want_arg
(
char
**
_value
,
const
char
*
option
)
{
if
(
!
_value
||
!*
_value
||
!**
_value
)
{
printk
(
KERN_NOTICE
"kAFS: %s: argument missing
\n
"
,
option
);
printk
(
KERN_NOTICE
"kAFS: %s: argument missing
\n
"
,
option
);
return
0
;
}
return
1
;
}
/* end want_arg() */
/*****************************************************************************/
/*
* check that there is a value
*/
#if 0
static int want_value(char **_value, const char *option)
{
if (!_value || !*_value || !**_value) {
printk(KERN_NOTICE "kAFS: %s: argument incomplete\n",option);
return 0;
}
return 1;
} /* end want_value() */
#endif
/*****************************************************************************/
/*
* check that there's no subsequent value
...
...
@@ -150,158 +154,64 @@ static int want_value(char **_value, const char *option)
static
int
want_no_value
(
char
*
const
*
_value
,
const
char
*
option
)
{
if
(
*
_value
&&
**
_value
)
{
printk
(
KERN_NOTICE
"kAFS: %s: Invalid argument: %s
\n
"
,
option
,
*
_value
);
printk
(
KERN_NOTICE
"kAFS: %s: Invalid argument: %s
\n
"
,
option
,
*
_value
);
return
0
;
}
return
1
;
}
/* end want_no_value() */
/*****************************************************************************/
/*
* extract a number from an option string value
*/
#if 0
static int want_number(char **_value, const char *option, unsigned long *number,
unsigned long limit)
{
char *value = *_value;
if (!want_value(_value,option))
return 0;
*number = simple_strtoul(value,_value,0);
if (value==*_value) {
printk(KERN_NOTICE "kAFS: %s: Invalid number: %s\n",option,value);
return 0;
}
if (*number>limit) {
printk(KERN_NOTICE "kAFS: %s: numeric value %lu > %lu\n",option,*number,limit);
return 0;
}
return 1;
} /* end want_number() */
#endif
/*****************************************************************************/
/*
* extract a separator from an option string value
*/
#if 0
static int want_sep(char **_value, const char *option, char sep)
{
if (!want_value(_value,option))
return 0;
if (*(*_value)++ != sep) {
printk(KERN_NOTICE "kAFS: %s: '%c' expected: %s\n",option,sep,*_value-1);
return 0;
}
return 1;
} /* end want_number() */
#endif
/*****************************************************************************/
/*
* extract an IP address from an option string value
*/
#if 0
static int want_ipaddr(char **_value, const char *option, struct in_addr *addr)
{
unsigned long number[4];
if (!want_value(_value,option))
return 0;
if (!want_number(_value,option,&number[0],255) ||
!want_sep(_value,option,'.') ||
!want_number(_value,option,&number[1],255) ||
!want_sep(_value,option,'.') ||
!want_number(_value,option,&number[2],255) ||
!want_sep(_value,option,'.') ||
!want_number(_value,option,&number[3],255))
return 0;
((u8*)addr)[0] = number[0];
((u8*)addr)[1] = number[1];
((u8*)addr)[2] = number[2];
((u8*)addr)[3] = number[3];
return 1;
} /* end want_numeric() */
#endif
/*****************************************************************************/
/*
* parse the mount options
* - this function has been shamelessly adapted from the ext3 fs which shamelessly adapted it from
* the msdos fs
*/
static
int
afs_super_parse_options
(
struct
afs_super_info
*
as
,
char
*
options
,
const
char
**
devname
)
static
int
afs_super_parse_options
(
struct
afs_mount_params
*
params
,
char
*
options
,
const
char
**
devname
)
{
char
*
key
,
*
value
;
int
ret
;
_enter
(
"%s"
,
options
);
_enter
(
"%s"
,
options
);
options
[
PAGE_SIZE
-
1
]
=
0
;
ret
=
0
;
while
((
key
=
strsep
(
&
options
,
","
)))
while
((
key
=
strsep
(
&
options
,
","
)))
{
value
=
strchr
(
key
,
'='
);
value
=
strchr
(
key
,
'='
);
if
(
value
)
*
value
++
=
0
;
printk
(
"kAFS: KEY: %s, VAL:%s
\n
"
,
key
,
value
?:
"-"
);
printk
(
"kAFS: KEY: %s, VAL:%s
\n
"
,
key
,
value
?:
"-"
);
if
(
strcmp
(
key
,
"rwpath"
)
==
0
)
{
if
(
!
want_no_value
(
&
value
,
"rwpath"
))
return
-
EINVAL
;
as
->
rwparent
=
1
;
if
(
strcmp
(
key
,
"rwpath"
)
==
0
)
{
if
(
!
want_no_value
(
&
value
,
"rwpath"
))
return
-
EINVAL
;
params
->
rwpath
=
1
;
continue
;
}
else
if
(
strcmp
(
key
,
"vol"
)
==
0
)
{
if
(
!
want_arg
(
&
value
,
"vol"
))
return
-
EINVAL
;
else
if
(
strcmp
(
key
,
"vol"
)
==
0
)
{
if
(
!
want_arg
(
&
value
,
"vol"
))
return
-
EINVAL
;
*
devname
=
value
;
continue
;
}
#if 0
if (strcmp(key,"servers")==0) {
if (!want_arg(&value,"servers")) return -EINVAL;
_debug("servers=%s",value);
for (;;) {
struct in_addr addr;
if (!want_ipaddr(&value,"servers",&addr))
return -EINVAL;
ret = afs_create_server(as->cell,&addr,&as->server);
if (ret<0) {
printk("kAFS: unable to create server: %d\n",ret);
return ret;
}
if (!*value)
break;
if (as->server) {
printk(KERN_NOTICE
"kAFS: only one server can be specified\n");
return -EINVAL;
}
if (!want_sep(&value,"servers",':'))
return -EINVAL;
}
else
if
(
strcmp
(
key
,
"cell"
)
==
0
)
{
if
(
!
want_arg
(
&
value
,
"cell"
))
return
-
EINVAL
;
afs_put_cell
(
params
->
default_cell
);
ret
=
afs_cell_lookup
(
value
,
strlen
(
value
),
&
params
->
default_cell
);
if
(
ret
<
0
)
return
-
EINVAL
;
continue
;
}
#endif
printk
(
"kAFS: Unknown mount option: '%s'
\n
"
,
key
);
printk
(
"kAFS: Unknown mount option: '%s'
\n
"
,
key
);
ret
=
-
EINVAL
;
goto
error
;
}
...
...
@@ -309,67 +219,48 @@ static int afs_super_parse_options(struct afs_super_info *as, char *options, con
ret
=
0
;
error:
_leave
(
" = %d"
,
ret
);
_leave
(
" = %d"
,
ret
);
return
ret
;
}
/* end afs_super_parse_options() */
struct
fill_super_options
{
const
char
*
dev_name
;
void
*
options
;
};
/*****************************************************************************/
/*
* check a superblock to see if it's the one we're looking for
*/
static
int
afs_test_super
(
struct
super_block
*
sb
,
void
*
data
)
{
struct
afs_mount_params
*
params
=
data
;
struct
afs_super_info
*
as
=
sb
->
s_fs_info
;
return
as
->
volume
==
params
->
volume
;
}
/* end afs_test_super() */
/*****************************************************************************/
/*
* fill in the superblock
*/
static
int
afs_fill_super
(
struct
super_block
*
sb
,
void
*
_
data
,
int
silent
)
static
int
afs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
afs_mount_params
*
params
=
data
;
struct
afs_super_info
*
as
=
NULL
;
struct
dentry
*
root
=
NULL
;
struct
inode
*
inode
=
NULL
;
afs_fid_t
fid
;
struct
fill_super_options
*
data
=
_data
;
const
char
*
devname
;
char
*
options
;
int
ret
;
_enter
(
""
);
if
(
!
data
)
{
_leave
(
" = -EINVAL"
);
return
-
EINVAL
;
}
devname
=
data
->
dev_name
;
options
=
data
->
options
;
if
(
options
)
options
[
PAGE_SIZE
-
1
]
=
0
;
kenter
(
""
);
/* allocate a superblock info record */
as
=
kmalloc
(
sizeof
(
struct
afs_super_info
),
GFP_KERNEL
);
as
=
kmalloc
(
sizeof
(
struct
afs_super_info
),
GFP_KERNEL
);
if
(
!
as
)
{
_leave
(
" = -ENOMEM"
);
return
-
ENOMEM
;
}
memset
(
as
,
0
,
sizeof
(
struct
afs_super_info
));
/* parse the options */
if
(
options
)
{
ret
=
afs_super_parse_options
(
as
,
options
,
&
devname
);
if
(
ret
<
0
)
goto
error
;
if
(
!
devname
)
{
printk
(
"kAFS: no volume name specified
\n
"
);
ret
=
-
EINVAL
;
goto
error
;
}
}
memset
(
as
,
0
,
sizeof
(
struct
afs_super_info
));
/* parse the device name */
ret
=
afs_volume_lookup
(
devname
,
as
->
rwparent
,
&
as
->
volume
);
if
(
ret
<
0
)
goto
error
;
afs_get_volume
(
params
->
volume
);
as
->
volume
=
params
->
volume
;
/* fill in the superblock */
sb
->
s_blocksize
=
PAGE_CACHE_SIZE
;
...
...
@@ -382,8 +273,8 @@ static int afs_fill_super(struct super_block *sb, void *_data, int silent)
fid
.
vid
=
as
->
volume
->
vid
;
fid
.
vnode
=
1
;
fid
.
unique
=
1
;
ret
=
afs_iget
(
sb
,
&
fid
,
&
inode
);
if
(
ret
<
0
)
ret
=
afs_iget
(
sb
,
&
fid
,
&
inode
);
if
(
ret
<
0
)
goto
error
;
ret
=
-
ENOMEM
;
...
...
@@ -393,19 +284,18 @@ static int afs_fill_super(struct super_block *sb, void *_data, int silent)
sb
->
s_root
=
root
;
_
leave
(
" = 0"
);
k
leave
(
" = 0"
);
return
0
;
error:
if
(
root
)
dput
(
root
);
if
(
inode
)
iput
(
inode
);
if
(
as
)
{
if
(
as
->
volume
)
afs_put_volume
(
as
->
volume
);
kfree
(
as
);
}
dput
(
root
);
iput
(
inode
);
afs_put_volume
(
as
->
volume
);
kfree
(
as
);
sb
->
s_fs_info
=
NULL
;
_leave
(
" = %d"
,
ret
);
kleave
(
" = %d"
,
ret
);
return
ret
;
}
/* end afs_fill_super() */
...
...
@@ -414,32 +304,72 @@ static int afs_fill_super(struct super_block *sb, void *_data, int silent)
* get an AFS superblock
* - TODO: don't use get_sb_nodev(), but rather call sget() directly
*/
static
struct
super_block
*
afs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
options
)
static
struct
super_block
*
afs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
options
)
{
struct
afs_mount_params
params
;
struct
super_block
*
sb
;
struct
fill_super_options
data
=
{
dev_name
,
options
};
int
ret
;
_enter
(
",,%s,%p"
,
dev_name
,
options
);
_enter
(
",,%s,%p"
,
dev_name
,
options
);
memset
(
&
params
,
0
,
sizeof
(
params
));
/* start the cache manager */
ret
=
afscm_start
();
if
(
ret
<
0
)
{
_leave
(
" = %d"
,
ret
);
if
(
ret
<
0
)
{
_leave
(
" = %d"
,
ret
);
return
ERR_PTR
(
ret
);
}
/* parse the options */
if
(
options
)
{
ret
=
afs_super_parse_options
(
&
params
,
options
,
&
dev_name
);
if
(
ret
<
0
)
goto
error
;
if
(
!
dev_name
)
{
printk
(
"kAFS: no volume name specified
\n
"
);
ret
=
-
EINVAL
;
goto
error
;
}
}
/* parse the device name */
ret
=
afs_volume_lookup
(
dev_name
,
params
.
default_cell
,
params
.
rwpath
,
&
params
.
volume
);
if
(
ret
<
0
)
goto
error
;
/* allocate a deviceless superblock */
sb
=
get_sb_nodev
(
fs_type
,
flags
,
&
data
,
afs_fill_super
);
if
(
IS_ERR
(
sb
))
{
afscm_stop
();
return
sb
;
sb
=
sget
(
fs_type
,
afs_test_super
,
set_anon_super
,
&
params
);
if
(
IS_ERR
(
sb
))
goto
error
;
sb
->
s_flags
=
flags
;
ret
=
afs_fill_super
(
sb
,
&
params
,
flags
&
MS_VERBOSE
?
1
:
0
);
if
(
ret
<
0
)
{
up_write
(
&
sb
->
s_umount
);
deactivate_super
(
sb
);
goto
error
;
}
sb
->
s_flags
|=
MS_ACTIVE
;
_leave
(
""
);
afs_put_volume
(
params
.
volume
);
afs_put_cell
(
params
.
default_cell
);
_leave
(
" = %p"
,
sb
);
return
sb
;
error:
afs_put_volume
(
params
.
volume
);
afs_put_cell
(
params
.
default_cell
);
afscm_stop
();
_leave
(
" = %d"
,
ret
);
return
ERR_PTR
(
ret
);
}
/* end afs_get_sb() */
/*****************************************************************************/
...
...
@@ -452,11 +382,7 @@ static void afs_put_super(struct super_block *sb)
_enter
(
""
);
if
(
as
)
{
if
(
as
->
volume
)
afs_put_volume
(
as
->
volume
);
}
/* stop the cache manager */
afs_put_volume
(
as
->
volume
);
afscm_stop
();
_leave
(
""
);
...
...
@@ -466,18 +392,21 @@ static void afs_put_super(struct super_block *sb)
/*
* initialise an inode cache slab element prior to any use
*/
static
void
afs_i_init_once
(
void
*
_vnode
,
kmem_cache_t
*
cachep
,
unsigned
long
flags
)
static
void
afs_i_init_once
(
void
*
_vnode
,
kmem_cache_t
*
cachep
,
unsigned
long
flags
)
{
afs_vnode_t
*
vnode
=
(
afs_vnode_t
*
)
_vnode
;
if
((
flags
&
(
SLAB_CTOR_VERIFY
|
SLAB_CTOR_CONSTRUCTOR
))
==
SLAB_CTOR_CONSTRUCTOR
)
{
memset
(
vnode
,
0
,
sizeof
(
*
vnode
));
if
((
flags
&
(
SLAB_CTOR_VERIFY
|
SLAB_CTOR_CONSTRUCTOR
))
==
SLAB_CTOR_CONSTRUCTOR
)
{
memset
(
vnode
,
0
,
sizeof
(
*
vnode
));
inode_init_once
(
&
vnode
->
vfs_inode
);
init_waitqueue_head
(
&
vnode
->
update_waitq
);
spin_lock_init
(
&
vnode
->
lock
);
INIT_LIST_HEAD
(
&
vnode
->
cb_link
);
INIT_LIST_HEAD
(
&
vnode
->
cb_hash_link
);
afs_timer_init
(
&
vnode
->
cb_timeout
,
&
afs_vnode_cb_timed_out_ops
);
afs_timer_init
(
&
vnode
->
cb_timeout
,
&
afs_vnode_cb_timed_out_ops
);
}
}
/* end afs_i_init_once() */
...
...
@@ -490,16 +419,19 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
{
afs_vnode_t
*
vnode
;
vnode
=
(
afs_vnode_t
*
)
kmem_cache_alloc
(
afs_inode_cachep
,
SLAB_KERNEL
);
vnode
=
(
afs_vnode_t
*
)
kmem_cache_alloc
(
afs_inode_cachep
,
SLAB_KERNEL
);
if
(
!
vnode
)
return
NULL
;
memset
(
&
vnode
->
fid
,
0
,
sizeof
(
vnode
->
fid
));
memset
(
&
vnode
->
status
,
0
,
sizeof
(
vnode
->
status
));
atomic_inc
(
&
afs_count_active_inodes
);
vnode
->
volume
=
NULL
;
vnode
->
update_cnt
=
0
;
vnode
->
flags
=
0
;
memset
(
&
vnode
->
fid
,
0
,
sizeof
(
vnode
->
fid
));
memset
(
&
vnode
->
status
,
0
,
sizeof
(
vnode
->
status
));
vnode
->
volume
=
NULL
;
vnode
->
update_cnt
=
0
;
vnode
->
flags
=
0
;
return
&
vnode
->
vfs_inode
;
}
/* end afs_alloc_inode() */
...
...
@@ -510,6 +442,10 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
*/
static
void
afs_destroy_inode
(
struct
inode
*
inode
)
{
_enter
(
"{%lu}"
,
inode
->
i_ino
);
_enter
(
"{%lu}"
,
inode
->
i_ino
);
kmem_cache_free
(
afs_inode_cachep
,
AFS_FS_I
(
inode
));
atomic_dec
(
&
afs_count_active_inodes
);
}
/* end afs_destroy_inode() */
fs/afs/super.h
View file @
7a9df5e2
...
...
@@ -29,7 +29,7 @@
*/
struct
afs_super_info
{
afs_volume_t
*
volume
;
/* volume record */
struct
afs_volume
*
volume
;
/* volume record */
char
rwparent
;
/* T if parent is R/W AFS volume */
};
...
...
fs/afs/types.h
View file @
7a9df5e2
...
...
@@ -33,26 +33,13 @@ typedef struct afs_volsync afs_volsync_t;
typedef
struct
afs_volume
afs_volume_t
;
typedef
struct
afs_volume_info
afs_volume_info_t
;
typedef
struct
afsc_cache
afsc_cache_t
;
typedef
struct
afsc_cache_cell
afsc_cache_cell_t
;
typedef
struct
afsc_cache_vldb
afsc_cache_vldb_t
;
typedef
struct
afsc_cell_record
afsc_cell_record_t
;
typedef
struct
afsc_inode
afsc_inode_t
;
typedef
struct
afsc_io
afsc_io_t
;
typedef
struct
afsc_io_subop
afsc_io_subop_t
;
typedef
struct
afsc_io_queue
afsc_io_queue_t
;
typedef
struct
afsc_super_block
afsc_super_block_t
;
typedef
struct
afsc_vldb_record
afsc_vldb_record_t
;
typedef
struct
afsc_vnode_catalogue
afsc_vnode_catalogue_t
;
typedef
struct
afsc_vnode_meta
afsc_vnode_meta_t
;
typedef
struct
afsvl_dbentry
afsvl_dbentry_t
;
typedef
enum
{
AFSVL_RWVOL
,
/* read/write volume */
AFSVL_ROVOL
,
/* read-only volume */
AFSVL_BACKVOL
,
/* backup volume */
}
afs_voltype_t
;
}
__attribute__
((
packed
))
afs_voltype_t
;
extern
const
char
*
afs_voltypes
[];
...
...
fs/afs/vlclient.c
View file @
7a9df5e2
...
...
@@ -176,8 +176,8 @@ int afs_rxvl_probe(afs_server_t *server, int alloc_flags)
/*
* look up a volume location database entry by name
*/
int
afs_rxvl_get_entry_by_name
(
afs_server_t
*
server
,
const
char
*
volname
,
afsc_vldb_record_t
*
entry
)
int
afs_rxvl_get_entry_by_name
(
afs_server_t
*
server
,
const
char
*
volname
,
unsigned
volnamesz
,
struct
afs_cache_vlocation
*
entry
)
{
DECLARE_WAITQUEUE
(
myself
,
current
);
...
...
@@ -189,29 +189,29 @@ int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
int
ret
,
loop
;
u32
*
bp
,
param
[
2
],
zero
;
_enter
(
",%
s,"
,
volname
);
_enter
(
",%
*.*s,%u,"
,
volnamesz
,
volnamesz
,
volname
,
volnamesz
);
memset
(
entry
,
0
,
sizeof
(
*
entry
));
memset
(
entry
,
0
,
sizeof
(
*
entry
));
/* get hold of the vlserver connection */
ret
=
afs_server_get_vlconn
(
server
,
&
conn
);
ret
=
afs_server_get_vlconn
(
server
,
&
conn
);
if
(
ret
<
0
)
goto
out
;
/* create a call through that connection */
ret
=
rxrpc_create_call
(
conn
,
NULL
,
NULL
,
afs_rxvl_aemap
,
&
call
);
if
(
ret
<
0
)
{
printk
(
"kAFS: Unable to create call: %d
\n
"
,
ret
);
ret
=
rxrpc_create_call
(
conn
,
NULL
,
NULL
,
afs_rxvl_aemap
,
&
call
);
if
(
ret
<
0
)
{
printk
(
"kAFS: Unable to create call: %d
\n
"
,
ret
);
goto
out_put_conn
;
}
call
->
app_opcode
=
VLGETENTRYBYNAME
;
/* we want to get event notifications from the call */
add_wait_queue
(
&
call
->
waitq
,
&
myself
);
add_wait_queue
(
&
call
->
waitq
,
&
myself
);
/* marshall the parameters */
piov
[
1
].
iov_len
=
strlen
(
volname
)
;
piov
[
1
].
iov_base
=
(
char
*
)
volname
;
piov
[
1
].
iov_len
=
volnamesz
;
piov
[
1
].
iov_base
=
(
char
*
)
volname
;
zero
=
0
;
piov
[
2
].
iov_len
=
(
4
-
(
piov
[
1
].
iov_len
&
3
))
&
3
;
...
...
@@ -224,16 +224,16 @@ int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
piov
[
0
].
iov_base
=
param
;
/* send the parameters to the server */
ret
=
rxrpc_call_write_data
(
call
,
3
,
piov
,
RXRPC_LAST_PACKET
,
GFP_NOFS
,
0
,
&
sent
);
ret
=
rxrpc_call_write_data
(
call
,
3
,
piov
,
RXRPC_LAST_PACKET
,
GFP_NOFS
,
0
,
&
sent
);
if
(
ret
<
0
)
goto
abort
;
/* wait for the reply to completely arrive */
bp
=
rxrpc_call_alloc_scratch
(
call
,
384
);
bp
=
rxrpc_call_alloc_scratch
(
call
,
384
);
ret
=
rxrpc_call_read_data
(
call
,
bp
,
384
,
RXRPC_CALL_READ_BLOCK
|
RXRPC_CALL_READ_ALL
);
if
(
ret
<
0
)
{
if
(
ret
==
-
ECONNABORTED
)
{
ret
=
rxrpc_call_read_data
(
call
,
bp
,
384
,
RXRPC_CALL_READ_BLOCK
|
RXRPC_CALL_READ_ALL
);
if
(
ret
<
0
)
{
if
(
ret
==
-
ECONNABORTED
)
{
ret
=
call
->
app_errno
;
goto
out_unwait
;
}
...
...
@@ -255,9 +255,9 @@ int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
for
(
loop
=
0
;
loop
<
8
;
loop
++
)
{
tmp
=
ntohl
(
*
bp
++
);
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_BAK
;
}
entry
->
vid
[
0
]
=
ntohl
(
*
bp
++
);
...
...
@@ -267,26 +267,26 @@ int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
bp
++
;
/* clone ID */
tmp
=
ntohl
(
*
bp
++
);
/* flags */
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_BAK
;
ret
=
-
ENOMEDIUM
;
if
(
!
entry
->
vidmask
)
goto
abort
;
/* success */
entry
->
c
time
=
get_seconds
();
entry
->
r
time
=
get_seconds
();
ret
=
0
;
out_unwait:
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
call
->
waitq
,
&
myself
);
remove_wait_queue
(
&
call
->
waitq
,
&
myself
);
rxrpc_put_call
(
call
);
out_put_conn:
rxrpc_put_connection
(
conn
);
out:
_leave
(
" = %d"
,
ret
);
_leave
(
" = %d"
,
ret
);
return
ret
;
abort:
...
...
@@ -303,7 +303,7 @@ int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
int
afs_rxvl_get_entry_by_id
(
afs_server_t
*
server
,
afs_volid_t
volid
,
afs_voltype_t
voltype
,
afsc_vldb_record_t
*
entry
)
struct
afs_cache_vlocation
*
entry
)
{
DECLARE_WAITQUEUE
(
myself
,
current
);
...
...
@@ -375,9 +375,9 @@ int afs_rxvl_get_entry_by_id(afs_server_t *server,
for
(
loop
=
0
;
loop
<
8
;
loop
++
)
{
tmp
=
ntohl
(
*
bp
++
);
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_BAK
;
}
entry
->
vid
[
0
]
=
ntohl
(
*
bp
++
);
...
...
@@ -387,9 +387,9 @@ int afs_rxvl_get_entry_by_id(afs_server_t *server,
bp
++
;
/* clone ID */
tmp
=
ntohl
(
*
bp
++
);
/* flags */
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_BAK
;
ret
=
-
ENOMEDIUM
;
if
(
!
entry
->
vidmask
)
...
...
@@ -401,13 +401,13 @@ int afs_rxvl_get_entry_by_id(afs_server_t *server,
entry->servers[1].s_addr = htonl(0xac101243);
entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
entry->srvtmask[0] = AFS
C_VOL_S
TM_RO;
entry->srvtmask[1] = AFS
C_VOL_S
TM_RO;
entry->srvtmask[2] = AFS
C_VOL_STM_RO | AFSC_VOL_S
TM_RW;
entry->srvtmask[0] = AFS
_VOL_V
TM_RO;
entry->srvtmask[1] = AFS
_VOL_V
TM_RO;
entry->srvtmask[2] = AFS
_VOL_VTM_RO | AFS_VOL_V
TM_RW;
#endif
/* success */
entry
->
c
time
=
get_seconds
();
entry
->
r
time
=
get_seconds
();
ret
=
0
;
out_unwait:
...
...
@@ -520,7 +520,7 @@ int afs_rxvl_get_entry_by_id_async(afs_async_op_t *op,
* attend to the asynchronous get VLDB entry by ID
*/
int
afs_rxvl_get_entry_by_id_async2
(
afs_async_op_t
*
op
,
afsc_vldb_record_t
*
entry
)
struct
afs_cache_vlocation
*
entry
)
{
unsigned
*
bp
,
tmp
;
int
loop
,
ret
;
...
...
@@ -550,9 +550,9 @@ int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op,
for
(
loop
=
0
;
loop
<
8
;
loop
++
)
{
tmp
=
ntohl
(
*
bp
++
);
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLSF_RWVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLSF_ROVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLSF_BACKVOL
)
entry
->
srvtmask
[
loop
]
|=
AFS
_VOL_V
TM_BAK
;
}
entry
->
vid
[
0
]
=
ntohl
(
*
bp
++
);
...
...
@@ -562,9 +562,9 @@ int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op,
bp
++
;
/* clone ID */
tmp
=
ntohl
(
*
bp
++
);
/* flags */
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
C_VOL_S
TM_BAK
;
if
(
tmp
&
AFS_VLF_RWEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RW
;
if
(
tmp
&
AFS_VLF_ROEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_RO
;
if
(
tmp
&
AFS_VLF_BACKEXISTS
)
entry
->
vidmask
|=
AFS
_VOL_V
TM_BAK
;
ret
=
-
ENOMEDIUM
;
if
(
!
entry
->
vidmask
)
{
...
...
@@ -578,13 +578,13 @@ int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op,
entry->servers[1].s_addr = htonl(0xac101243);
entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
entry->srvtmask[0] = AFS
C_VOL_S
TM_RO;
entry->srvtmask[1] = AFS
C_VOL_S
TM_RO;
entry->srvtmask[2] = AFS
C_VOL_STM_RO | AFSC_VOL_S
TM_RW;
entry->srvtmask[0] = AFS
_VOL_V
TM_RO;
entry->srvtmask[1] = AFS
_VOL_V
TM_RO;
entry->srvtmask[2] = AFS
_VOL_VTM_RO | AFS_VOL_V
TM_RW;
#endif
/* success */
entry
->
c
time
=
get_seconds
();
entry
->
r
time
=
get_seconds
();
ret
=
0
;
goto
done
;
}
...
...
@@ -626,7 +626,8 @@ static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call)
case
RXRPC_CSTATE_CLNT_GOT_REPLY
:
if
(
call
->
app_read_count
==
0
)
break
;
printk
(
"kAFS: Reply bigger than expected {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}"
,
printk
(
"kAFS: Reply bigger than expected"
" {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}"
,
call
->
app_call_state
,
call
->
app_async_read
,
call
->
app_mark
,
...
...
fs/afs/vlclient.h
View file @
7a9df5e2
...
...
@@ -46,7 +46,7 @@ enum AFSVL_Errors {
};
/* maps to "struct vldbentry" in vvl-spec.pdf */
struct
afsvl_
dbentry
{
struct
afs_vl
dbentry
{
char
name
[
65
];
/* name of volume (including NUL char) */
afs_voltype_t
type
;
/* volume type */
unsigned
num_servers
;
/* num servers that hold instances of this vol */
...
...
@@ -77,19 +77,20 @@ extern int afs_rxvl_probe(afs_server_t *server, int alloc_flags);
/* look up a volume location database entry by name */
extern
int
afs_rxvl_get_entry_by_name
(
afs_server_t
*
server
,
const
char
*
volname
,
afsc_vldb_record_t
*
entry
);
unsigned
volnamesz
,
struct
afs_cache_vlocation
*
entry
);
/* look up a volume location database entry by ID */
extern
int
afs_rxvl_get_entry_by_id
(
afs_server_t
*
server
,
afs_volid_t
volid
,
afs_voltype_t
voltype
,
afsc_vldb_record_t
*
entry
);
struct
afs_cache_vlocation
*
entry
);
extern
int
afs_rxvl_get_entry_by_id_async
(
afs_async_op_t
*
op
,
afs_volid_t
volid
,
afs_voltype_t
voltype
);
extern
int
afs_rxvl_get_entry_by_id_async2
(
afs_async_op_t
*
op
,
afsc_vldb_record_t
*
entry
);
struct
afs_cache_vlocation
*
entry
);
#endif
/* _LINUX_AFS_VLCLIENT_H */
fs/afs/vlocation.c
View file @
7a9df5e2
...
...
@@ -56,6 +56,19 @@ static LIST_HEAD(afs_vlocation_update_pendq); /* queue of VLs awaiting update */
static
afs_vlocation_t
*
afs_vlocation_update
;
/* VL currently being updated */
static
spinlock_t
afs_vlocation_update_lock
=
SPIN_LOCK_UNLOCKED
;
/* lock guarding update queue */
#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
/*****************************************************************************/
/*
* iterate through the VL servers in a cell until one of them admits knowing about the volume in
...
...
@@ -64,21 +77,23 @@ static spinlock_t afs_vlocation_update_lock = SPIN_LOCK_UNLOCKED; /* lock guardi
*/
static
int
afs_vlocation_access_vl_by_name
(
afs_vlocation_t
*
vlocation
,
const
char
*
name
,
afsc_vldb_record_t
*
vldb
)
unsigned
namesz
,
struct
afs_cache_vlocation
*
vldb
)
{
afs_server_t
*
server
=
NULL
;
afs_cell_t
*
cell
=
vlocation
->
cell
;
int
count
,
ret
;
_enter
(
"%s,%
s,"
,
cell
->
name
,
name
);
_enter
(
"%s,%
*.*s,%u"
,
cell
->
name
,
namesz
,
namesz
,
name
,
namesz
);
ret
=
-
ENOMEDIUM
;
for
(
count
=
cell
->
vl_naddrs
;
count
>
0
;
count
--
)
{
_debug
(
"CellServ[%hu]: %08x"
,
cell
->
vl_curr_svix
,
cell
->
vl_addrs
[
cell
->
vl_curr_svix
].
s_addr
);
cell
->
vl_curr_svix
,
cell
->
vl_addrs
[
cell
->
vl_curr_svix
].
s_addr
);
/* try and create a server */
ret
=
afs_server_lookup
(
cell
,
&
cell
->
vl_addrs
[
cell
->
vl_curr_svix
],
&
server
);
ret
=
afs_server_lookup
(
cell
,
&
cell
->
vl_addrs
[
cell
->
vl_curr_svix
],
&
server
);
switch
(
ret
)
{
case
0
:
break
;
...
...
@@ -90,7 +105,7 @@ static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation,
}
/* attempt to access the VL server */
ret
=
afs_rxvl_get_entry_by_name
(
server
,
name
,
vldb
);
ret
=
afs_rxvl_get_entry_by_name
(
server
,
name
,
namesz
,
vldb
);
switch
(
ret
)
{
case
0
:
afs_put_server
(
server
);
...
...
@@ -107,7 +122,7 @@ static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation,
}
up_write
(
&
server
->
sem
);
afs_put_server
(
server
);
if
(
ret
==-
ENOMEM
||
ret
==
-
ENONET
)
if
(
ret
==
-
ENOMEM
||
ret
==
-
ENONET
)
goto
out
;
goto
rotate
;
case
-
ENOMEDIUM
:
...
...
@@ -140,21 +155,22 @@ static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation,
static
int
afs_vlocation_access_vl_by_id
(
afs_vlocation_t
*
vlocation
,
afs_volid_t
volid
,
afs_voltype_t
voltype
,
afsc_vldb_record_t
*
vldb
)
struct
afs_cache_vlocation
*
vldb
)
{
afs_server_t
*
server
=
NULL
;
afs_cell_t
*
cell
=
vlocation
->
cell
;
int
count
,
ret
;
_enter
(
"%s,%x,%d,"
,
cell
->
name
,
volid
,
voltype
);
_enter
(
"%s,%x,%d,"
,
cell
->
name
,
volid
,
voltype
);
ret
=
-
ENOMEDIUM
;
for
(
count
=
cell
->
vl_naddrs
;
count
>
0
;
count
--
)
{
_debug
(
"CellServ[%hu]: %08x"
,
cell
->
vl_curr_svix
,
cell
->
vl_addrs
[
cell
->
vl_curr_svix
].
s_addr
);
cell
->
vl_curr_svix
,
cell
->
vl_addrs
[
cell
->
vl_curr_svix
].
s_addr
);
/* try and create a server */
ret
=
afs_server_lookup
(
cell
,
&
cell
->
vl_addrs
[
cell
->
vl_curr_svix
],
&
server
);
ret
=
afs_server_lookup
(
cell
,
&
cell
->
vl_addrs
[
cell
->
vl_curr_svix
],
&
server
);
switch
(
ret
)
{
case
0
:
break
;
...
...
@@ -166,7 +182,7 @@ static int afs_vlocation_access_vl_by_id(afs_vlocation_t *vlocation,
}
/* attempt to access the VL server */
ret
=
afs_rxvl_get_entry_by_id
(
server
,
volid
,
voltype
,
vldb
);
ret
=
afs_rxvl_get_entry_by_id
(
server
,
volid
,
voltype
,
vldb
);
switch
(
ret
)
{
case
0
:
afs_put_server
(
server
);
...
...
@@ -183,7 +199,7 @@ static int afs_vlocation_access_vl_by_id(afs_vlocation_t *vlocation,
}
up_write
(
&
server
->
sem
);
afs_put_server
(
server
);
if
(
ret
==-
ENOMEM
||
ret
==
-
ENONET
)
if
(
ret
==
-
ENOMEM
||
ret
==
-
ENONET
)
goto
out
;
goto
rotate
;
case
-
ENOMEDIUM
:
...
...
@@ -216,74 +232,83 @@ static int afs_vlocation_access_vl_by_id(afs_vlocation_t *vlocation,
* - lookup in the local cache if not able to find on the VL server
* - insert/update in the local cache if did get a VL response
*/
int
afs_vlocation_lookup
(
afs_cell_t
*
cell
,
const
char
*
name
,
afs_vlocation_t
**
_vlocation
)
int
afs_vlocation_lookup
(
afs_cell_t
*
cell
,
const
char
*
name
,
unsigned
namesz
,
afs_vlocation_t
**
_vlocation
)
{
afsc_vldb_record_t
vldb
;
struct
afs_cache_vlocation
vldb
;
struct
list_head
*
_p
;
afs_vlocation_t
*
vlocation
;
afs_voltype_t
voltype
;
afs_volid_t
vid
;
int
active
=
0
,
ret
;
_enter
(
"
,%s,%s,"
,
cell
->
name
,
name
);
_enter
(
"
{%s},%*.*s,%u,"
,
cell
->
name
,
namesz
,
namesz
,
name
,
namesz
);
if
(
strlen
(
name
)
>
sizeof
(
vlocation
->
vldb
.
name
))
{
if
(
namesz
>
sizeof
(
vlocation
->
vldb
.
name
))
{
_leave
(
" = -ENAMETOOLONG"
);
return
-
ENAMETOOLONG
;
}
/* search the cell's active list first */
list_for_each
(
_p
,
&
cell
->
vl_list
)
{
vlocation
=
list_entry
(
_p
,
afs_vlocation_t
,
link
);
if
(
strncmp
(
vlocation
->
vldb
.
name
,
name
,
sizeof
(
vlocation
->
vldb
.
name
))
==
0
)
list_for_each
(
_p
,
&
cell
->
vl_list
)
{
vlocation
=
list_entry
(
_p
,
afs_vlocation_t
,
link
);
if
(
namesz
<
sizeof
(
vlocation
->
vldb
.
name
)
&&
vlocation
->
vldb
.
name
[
namesz
]
!=
'\0'
)
continue
;
if
(
memcmp
(
vlocation
->
vldb
.
name
,
name
,
namesz
)
==
0
)
goto
found_in_memory
;
}
/* search the cell's graveyard list second */
spin_lock
(
&
cell
->
vl_gylock
);
list_for_each
(
_p
,
&
cell
->
vl_graveyard
)
{
vlocation
=
list_entry
(
_p
,
afs_vlocation_t
,
link
);
if
(
strncmp
(
vlocation
->
vldb
.
name
,
name
,
sizeof
(
vlocation
->
vldb
.
name
))
==
0
)
list_for_each
(
_p
,
&
cell
->
vl_graveyard
)
{
vlocation
=
list_entry
(
_p
,
afs_vlocation_t
,
link
);
if
(
namesz
<
sizeof
(
vlocation
->
vldb
.
name
)
&&
vlocation
->
vldb
.
name
[
namesz
]
!=
'\0'
)
continue
;
if
(
memcmp
(
vlocation
->
vldb
.
name
,
name
,
namesz
)
==
0
)
goto
found_in_graveyard
;
}
spin_unlock
(
&
cell
->
vl_gylock
);
/* not in the cell's in-memory lists - create a new record */
vlocation
=
kmalloc
(
sizeof
(
afs_vlocation_t
),
GFP_KERNEL
);
vlocation
=
kmalloc
(
sizeof
(
afs_vlocation_t
),
GFP_KERNEL
);
if
(
!
vlocation
)
return
-
ENOMEM
;
memset
(
vlocation
,
0
,
sizeof
(
afs_vlocation_t
));
atomic_set
(
&
vlocation
->
usage
,
1
);
memset
(
vlocation
,
0
,
sizeof
(
afs_vlocation_t
));
atomic_set
(
&
vlocation
->
usage
,
1
);
INIT_LIST_HEAD
(
&
vlocation
->
link
);
rwlock_init
(
&
vlocation
->
lock
);
strncpy
(
vlocation
->
vldb
.
name
,
name
,
sizeof
(
vlocation
->
vldb
.
name
));
afs_timer_init
(
&
vlocation
->
timeout
,
&
afs_vlocation_timer_ops
);
afs_timer_init
(
&
vlocation
->
upd_timer
,
&
afs_vlocation_update_timer_ops
);
afs_async_op_init
(
&
vlocation
->
upd_op
,
&
afs_vlocation_update_op_ops
);
memcpy
(
vlocation
->
vldb
.
name
,
name
,
namesz
);
INIT_LIST_HEAD
(
&
vlocation
->
caches
);
afs_timer_init
(
&
vlocation
->
timeout
,
&
afs_vlocation_timer_ops
);
afs_timer_init
(
&
vlocation
->
upd_timer
,
&
afs_vlocation_update_timer_ops
);
afs_async_op_init
(
&
vlocation
->
upd_op
,
&
afs_vlocation_update_op_ops
);
afs_get_cell
(
cell
);
vlocation
->
cell
=
cell
;
list_add_tail
(
&
vlocation
->
link
,
&
cell
->
vl_list
);
list_add_tail
(
&
vlocation
->
link
,
&
cell
->
vl_list
);
#if 0
/* search local cache if wasn't in memory */
ret = afsc_lookup_vlocation(vlocation);
switch (ret) {
default: goto error; /* disk error */
case 0: goto found_in_cache; /* pulled from local cache into memory */
case -ENOENT: break; /* not in local cache */
}
#ifdef AFS_CACHING_SUPPORT
/* we want to store it in the cache, plus it might already be encached */
cachefs_acquire_cookie
(
cell
->
cache
,
&
afs_volume_cache_index_def
,
vlocation
,
&
vlocation
->
cache
);
if
(
vlocation
->
valid
)
goto
found_in_cache
;
#endif
/* try to look up an unknown volume in the cell VL databases by name */
ret
=
afs_vlocation_access_vl_by_name
(
vlocation
,
name
,
&
vldb
);
ret
=
afs_vlocation_access_vl_by_name
(
vlocation
,
name
,
namesz
,
&
vldb
);
if
(
ret
<
0
)
{
printk
(
"kAFS: failed to locate '%s' in cell '%s'
\n
"
,
name
,
cell
->
name
);
printk
(
"kAFS: failed to locate '%*.*s' in cell '%s'
\n
"
,
namesz
,
namesz
,
name
,
cell
->
name
);
goto
error
;
}
...
...
@@ -294,7 +319,7 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
_debug
(
"found in graveyard"
);
atomic_inc
(
&
vlocation
->
usage
);
list_del
(
&
vlocation
->
link
);
list_add_tail
(
&
vlocation
->
link
,
&
cell
->
vl_list
);
list_add_tail
(
&
vlocation
->
link
,
&
cell
->
vl_list
);
spin_unlock
(
&
cell
->
vl_gylock
);
afs_kafstimod_del_timer
(
&
vlocation
->
timeout
);
...
...
@@ -308,30 +333,32 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
active:
active
=
1
;
/* found_in_cache: */
#ifdef AFS_CACHING_SUPPORT
found_in_cache:
#endif
/* try to look up a cached volume in the cell VL databases by ID */
_debug
(
"found in cache"
);
_debug
(
"Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }"
,
vlocation
->
vldb
.
name
,
vlocation
->
vldb
.
vidmask
,
ntohl
(
vlocation
->
vldb
.
servers
[
0
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
0
],
ntohl
(
vlocation
->
vldb
.
servers
[
1
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
1
],
ntohl
(
vlocation
->
vldb
.
servers
[
2
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
2
]
ntohl
(
vlocation
->
vldb
.
servers
[
0
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
0
],
ntohl
(
vlocation
->
vldb
.
servers
[
1
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
1
],
ntohl
(
vlocation
->
vldb
.
servers
[
2
].
s_addr
),
vlocation
->
vldb
.
srvtmask
[
2
]
);
_debug
(
"Vids: %08x %08x %08x"
,
vlocation
->
vldb
.
vid
[
0
],
vlocation
->
vldb
.
vid
[
1
],
vlocation
->
vldb
.
vid
[
2
]);
vlocation
->
vldb
.
vid
[
0
],
vlocation
->
vldb
.
vid
[
1
],
vlocation
->
vldb
.
vid
[
2
]);
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_RW
)
{
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_RW
)
{
vid
=
vlocation
->
vldb
.
vid
[
0
];
voltype
=
AFSVL_RWVOL
;
}
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_RO
)
{
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_RO
)
{
vid
=
vlocation
->
vldb
.
vid
[
1
];
voltype
=
AFSVL_ROVOL
;
}
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_BAK
)
{
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_BAK
)
{
vid
=
vlocation
->
vldb
.
vid
[
2
];
voltype
=
AFSVL_BACKVOL
;
}
...
...
@@ -341,41 +368,44 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
voltype
=
0
;
}
ret
=
afs_vlocation_access_vl_by_id
(
vlocation
,
vid
,
voltype
,
&
vldb
);
ret
=
afs_vlocation_access_vl_by_id
(
vlocation
,
vid
,
voltype
,
&
vldb
);
switch
(
ret
)
{
/* net error */
default:
printk
(
"kAFS: failed to volume '%s' (%x) up in '%s': %d
\n
"
,
name
,
vid
,
cell
->
name
,
ret
);
printk
(
"kAFS: failed to volume '%
*.*
s' (%x) up in '%s': %d
\n
"
,
name
sz
,
namesz
,
name
,
vid
,
cell
->
name
,
ret
);
goto
error
;
/* pulled from local cache into memory */
case
0
:
case
0
:
goto
found_on_vlserver
;
/* uh oh... looks like the volume got deleted */
case
-
ENOMEDIUM
:
printk
(
"kAFS: volume '%s' (%x) does not exist '%s'
\n
"
,
name
,
vid
,
cell
->
name
);
printk
(
"kAFS: volume '%*.*s' (%x) does not exist '%s'
\n
"
,
namesz
,
namesz
,
name
,
vid
,
cell
->
name
);
/* TODO: make existing record unavailable */
goto
error
;
}
found_on_vlserver:
_debug
(
"Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }"
,
name
,
_debug
(
"Done VL Lookup: %
*.*
s %02x { %08x(%x) %08x(%x) %08x(%x) }"
,
name
sz
,
namesz
,
name
,
vldb
.
vidmask
,
ntohl
(
vldb
.
servers
[
0
].
s_addr
),
vldb
.
srvtmask
[
0
],
ntohl
(
vldb
.
servers
[
1
].
s_addr
),
vldb
.
srvtmask
[
1
],
ntohl
(
vldb
.
servers
[
2
].
s_addr
),
vldb
.
srvtmask
[
2
]
ntohl
(
vldb
.
servers
[
0
].
s_addr
),
vldb
.
srvtmask
[
0
],
ntohl
(
vldb
.
servers
[
1
].
s_addr
),
vldb
.
srvtmask
[
1
],
ntohl
(
vldb
.
servers
[
2
].
s_addr
),
vldb
.
srvtmask
[
2
]
);
_debug
(
"Vids: %08x %08x %08x"
,
vldb
.
vid
[
0
],
vldb
.
vid
[
1
],
vldb
.
vid
[
2
]);
_debug
(
"Vids: %08x %08x %08x"
,
vldb
.
vid
[
0
],
vldb
.
vid
[
1
],
vldb
.
vid
[
2
]);
if
(
strncmp
(
vldb
.
name
,
name
,
sizeof
(
vlocation
->
vldb
.
name
))
!=
0
)
printk
(
"kAFS: name of volume '%s' changed to '%s' on server
\n
"
,
name
,
vldb
.
name
);
if
((
namesz
<
sizeof
(
vlocation
->
vldb
.
name
)
&&
vlocation
->
vldb
.
name
[
namesz
]
!=
'\0'
)
||
memcmp
(
vldb
.
name
,
name
,
namesz
)
!=
0
)
printk
(
"kAFS: name of volume '%*.*s' changed to '%s' on server
\n
"
,
namesz
,
namesz
,
name
,
vldb
.
name
);
memcpy
(
&
vlocation
->
vldb
,
&
vldb
,
sizeof
(
vlocation
->
vldb
));
memcpy
(
&
vlocation
->
vldb
,
&
vldb
,
sizeof
(
vlocation
->
vldb
));
#if 0
/* add volume entry to local cache */
...
...
@@ -384,7 +414,7 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
goto error;
#endif
afs_kafstimod_add_timer
(
&
vlocation
->
upd_timer
,
10
*
HZ
);
afs_kafstimod_add_timer
(
&
vlocation
->
upd_timer
,
10
*
HZ
);
*
_vlocation
=
vlocation
;
_leave
(
" = 0 (%p)"
,
vlocation
);
...
...
@@ -397,10 +427,10 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
}
else
{
list_del
(
&
vlocation
->
link
);
afs_put_cell
(
vlocation
->
cell
);
#if 0
afs_put_cache(vlocation->cache);
#ifdef AFS_CACHING_SUPPORT
cachefs_relinquish_cookie
(
vlocation
->
cache
,
0
);
#endif
afs_put_cell
(
vlocation
->
cell
);
kfree
(
vlocation
);
}
}
...
...
@@ -414,12 +444,17 @@ int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_
* finish using a volume location record
* - caller must have cell->vol_sem write-locked
*/
void
__afs_put_vlocation
(
afs_vlocation_t
*
vlocation
)
void
__afs_put_vlocation
(
struct
afs_vlocation
*
vlocation
)
{
afs_cell_t
*
cell
=
vlocation
->
cell
;
struct
afs_cell
*
cell
;
if
(
!
vlocation
)
return
;
_enter
(
"%s"
,
vlocation
->
vldb
.
name
);
cell
=
vlocation
->
cell
;
/* sanity check */
if
(
atomic_read
(
&
vlocation
->
usage
)
<=
0
)
BUG
();
...
...
@@ -453,11 +488,13 @@ void __afs_put_vlocation(afs_vlocation_t *vlocation)
*/
void
afs_put_vlocation
(
afs_vlocation_t
*
vlocation
)
{
afs_cell_t
*
cell
=
vlocation
->
cell
;
if
(
vlocation
)
{
struct
afs_cell
*
cell
=
vlocation
->
cell
;
down_write
(
&
cell
->
vl_sem
);
__afs_put_vlocation
(
vlocation
);
up_write
(
&
cell
->
vl_sem
);
down_write
(
&
cell
->
vl_sem
);
__afs_put_vlocation
(
vlocation
);
up_write
(
&
cell
->
vl_sem
);
}
}
/* end afs_put_vlocation() */
/*****************************************************************************/
...
...
@@ -489,10 +526,10 @@ void afs_vlocation_do_timeout(afs_vlocation_t *vlocation)
}
/* we can now destroy it properly */
afs_put_cell
(
cell
);
#if 0
afs_put_cache(vlocation->cache);
#ifdef AFS_CACHING_SUPPORT
cachefs_relinquish_cookie
(
vlocation
->
cache
,
0
);
#endif
afs_put_cell
(
cell
);
kfree
(
vlocation
);
...
...
@@ -513,15 +550,15 @@ static int afs_vlocation_update_begin(afs_vlocation_t *vlocation)
vlocation
->
vldb
.
name
,
vlocation
->
upd_first_svix
,
vlocation
->
upd_curr_svix
);
/* try to look up a cached volume in the cell VL databases by ID */
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_RW
)
{
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_RW
)
{
vid
=
vlocation
->
vldb
.
vid
[
0
];
voltype
=
AFSVL_RWVOL
;
}
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_RO
)
{
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_RO
)
{
vid
=
vlocation
->
vldb
.
vid
[
1
];
voltype
=
AFSVL_ROVOL
;
}
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
C_VOL_S
TM_BAK
)
{
else
if
(
vlocation
->
vldb
.
vidmask
&
AFS
_VOL_V
TM_BAK
)
{
vid
=
vlocation
->
vldb
.
vid
[
2
];
voltype
=
AFSVL_BACKVOL
;
}
...
...
@@ -571,10 +608,8 @@ static void afs_vlocation_update_abandon(afs_vlocation_t *vlocation,
printk
(
"kAFS: Abandoning VL update '%s': %d
\n
"
,
vlocation
->
vldb
.
name
,
ret
);
/* discard the server record */
if
(
vlocation
->
upd_op
.
server
)
{
afs_put_server
(
vlocation
->
upd_op
.
server
);
vlocation
->
upd_op
.
server
=
NULL
;
}
afs_put_server
(
vlocation
->
upd_op
.
server
);
vlocation
->
upd_op
.
server
=
NULL
;
spin_lock
(
&
afs_vlocation_update_lock
);
afs_vlocation_update
=
NULL
;
...
...
@@ -669,7 +704,7 @@ static void afs_vlocation_update_timer(afs_timer_t *timer)
*/
static
void
afs_vlocation_update_attend
(
afs_async_op_t
*
op
)
{
afsc_vldb_record_t
vldb
;
struct
afs_cache_vlocation
vldb
;
afs_vlocation_t
*
vlocation
=
list_entry
(
op
,
afs_vlocation_t
,
upd_op
);
unsigned
tmp
;
int
ret
;
...
...
@@ -762,11 +797,9 @@ static void afs_vlocation_update_attend(afs_async_op_t *op)
try_next:
vlocation
->
upd_busy_cnt
=
0
;
if
(
vlocation
->
upd_op
.
server
)
{
/* discard the server record */
afs_put_server
(
vlocation
->
upd_op
.
server
);
vlocation
->
upd_op
.
server
=
NULL
;
}
/* discard the server record */
afs_put_server
(
vlocation
->
upd_op
.
server
);
vlocation
->
upd_op
.
server
=
NULL
;
tmp
=
vlocation
->
cell
->
vl_naddrs
;
if
(
tmp
==
0
)
...
...
@@ -822,3 +855,68 @@ static void afs_vlocation_update_discard(afs_async_op_t *op)
_leave
(
""
);
}
/* end afs_vlocation_update_discard() */
/*****************************************************************************/
/*
* 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
)
{
struct_cpy
(
&
vlocation
->
vldb
,
vldb
);
vlocation
->
valid
=
1
;
_leave
(
" = SUCCESS [c->m]"
);
return
CACHEFS_MATCH_SUCCESS
;
}
/* need to update cache if cached info differs */
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
;
}
/* end afs_vlocation_cache_match() */
#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
(
""
);
struct_cpy
(
vldb
,
&
vlocation
->
vldb
);
}
/* end afs_vlocation_cache_update() */
#endif
fs/afs/vnode.c
View file @
7a9df5e2
...
...
@@ -29,6 +29,19 @@ struct afs_timer_ops afs_vnode_cb_timed_out_ops = {
.
timed_out
=
afs_vnode_cb_timed_out
,
};
#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
/*****************************************************************************/
/*
* handle a callback timing out
...
...
@@ -61,8 +74,7 @@ static void afs_vnode_cb_timed_out(struct afs_timer *timer)
spin_unlock
(
&
vnode
->
lock
);
if
(
oldserver
)
afs_put_server
(
oldserver
);
afs_put_server
(
oldserver
);
_leave
(
""
);
}
/* end afs_vnode_cb_timed_out() */
...
...
@@ -126,8 +138,7 @@ void afs_vnode_finalise_status_update(afs_vnode_t *vnode, afs_server_t *server,
wake_up_all
(
&
vnode
->
update_waitq
);
if
(
oldserver
)
afs_put_server
(
oldserver
);
afs_put_server
(
oldserver
);
_leave
(
""
);
...
...
@@ -272,7 +283,7 @@ int afs_vnode_fetch_data(afs_vnode_t *vnode, struct afs_rxfs_fetch_descriptor *d
/*****************************************************************************/
/*
* break any outstanding callback on a vnode
* - only relev
a
nt to server that issued it
* - only relev
e
nt to server that issued it
*/
int
afs_vnode_give_up_callback
(
afs_vnode_t
*
vnode
)
{
...
...
@@ -314,3 +325,56 @@ int afs_vnode_give_up_callback(afs_vnode_t *vnode)
_leave
(
" = %d"
,
ret
);
return
ret
;
}
/* end afs_vnode_give_up_callback() */
/*****************************************************************************/
/*
* 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
;
}
/* end afs_vnode_cache_match() */
#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
;
}
/* end afs_vnode_cache_update() */
#endif
fs/afs/vnode.h
View file @
7a9df5e2
...
...
@@ -15,11 +15,27 @@
#include <linux/fs.h>
#include "server.h"
#include "kafstimod.h"
#include "cache.h"
#ifdef __KERNEL__
struct
afs_rxfs_fetch_descriptor
;
/*****************************************************************************/
/*
* vnode catalogue entry
*/
struct
afs_cache_vnode
{
afs_vnodeid_t
vnode_id
;
/* vnode ID */
unsigned
vnode_unique
;
/* vnode ID uniquifier */
afs_dataversion_t
data_version
;
/* data version */
};
#ifdef AFS_CACHING_SUPPORT
extern
struct
cachefs_index_def
afs_vnode_cache_index_def
;
#endif
/*****************************************************************************/
/*
* AFS inode private data
...
...
@@ -28,10 +44,12 @@ struct afs_vnode
{
struct
inode
vfs_inode
;
/* the VFS's inode record */
afs_volume_t
*
volume
;
/* volume on which vnode resides */
afs_fid_t
fid
;
/* the file identifier for this inode */
afs_file_status_t
status
;
/* AFS status info for this file */
unsigned
nix
;
/* vnode index in cache */
struct
afs_volume
*
volume
;
/* volume on which vnode resides */
struct
afs_fid
fid
;
/* the file identifier for this inode */
struct
afs_file_status
status
;
/* AFS status info for this file */
#ifdef AFS_CACHING_SUPPORT
struct
cachefs_cookie
*
cache
;
/* caching cookie */
#endif
wait_queue_head_t
update_waitq
;
/* status fetch waitqueue */
unsigned
update_cnt
;
/* number of outstanding ops that will update the
...
...
@@ -43,10 +61,10 @@ struct afs_vnode
#define AFS_VNODE_MOUNTPOINT 0x00000004
/* set if vnode is a mountpoint symlink */
/* outstanding callback notification on this file */
afs_server_t
*
cb_server
;
/* server that made the current promise */
struct
afs_server
*
cb_server
;
/* server that made the current promise */
struct
list_head
cb_link
;
/* link in server's promises list */
struct
list_head
cb_hash_link
;
/* link in master callback hash */
afs_timer_t
cb_timeout
;
/* timeout on promise */
struct
afs_timer
cb_timeout
;
/* timeout on promise */
unsigned
cb_version
;
/* callback version */
unsigned
cb_expiry
;
/* callback expiry time */
afs_callback_type_t
cb_type
;
/* type of callback */
...
...
fs/afs/volume.c
View file @
7a9df5e2
...
...
@@ -16,7 +16,9 @@
#include <linux/fs.h>
#include <linux/pagemap.h>
#include "volume.h"
#include "vnode.h"
#include "cell.h"
#include "cache.h"
#include "cmservice.h"
#include "fsclient.h"
#include "vlclient.h"
...
...
@@ -24,6 +26,20 @@
const
char
*
afs_voltypes
[]
=
{
"R/W"
,
"R/O"
,
"BAK"
};
#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
/*****************************************************************************/
/*
* lookup a volume by name
...
...
@@ -43,19 +59,19 @@ const char *afs_voltypes[] = { "R/W", "R/O", "BAK" };
* - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W if not available
* - Rule 3: If parent volume is R/W, then only mount R/W volume unless explicitly told otherwise
*/
int
afs_volume_lookup
(
const
char
*
name
,
int
rwparent
,
afs_volume_t
**
_volume
)
int
afs_volume_lookup
(
const
char
*
name
,
struct
afs_cell
*
cell
,
int
rwpath
,
afs_volume_t
**
_volume
)
{
afs_vlocation_t
*
vlocation
=
NULL
;
struct
afs_vlocation
*
vlocation
=
NULL
;
struct
afs_volume
*
volume
=
NULL
;
afs_voltype_t
type
;
afs_volume_t
*
volume
=
NULL
;
afs_cell_t
*
cell
=
NULL
;
char
*
cellname
,
*
volname
,
*
suffix
;
const
char
*
cellname
,
*
volname
,
*
suffix
;
char
srvtmask
;
int
force
,
ret
,
loop
;
int
force
,
ret
,
loop
,
cellnamesz
,
volnamesz
;
_enter
(
"
,%s,"
,
name
);
_enter
(
"
%s,,%d,"
,
name
,
rwpath
);
if
(
!
name
||
(
name
[
0
]
!=
'%'
&&
name
[
0
]
!=
'#'
)
||
!
name
[
1
])
{
if
(
!
name
||
(
name
[
0
]
!=
'%'
&&
name
[
0
]
!=
'#'
)
||
!
name
[
1
])
{
printk
(
"kAFS: unparsable volume name
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -64,24 +80,22 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
force
=
0
;
type
=
AFSVL_ROVOL
;
if
(
rwpa
rent
||
name
[
0
]
==
'%'
)
{
if
(
rwpa
th
||
name
[
0
]
==
'%'
)
{
type
=
AFSVL_RWVOL
;
force
=
1
;
}
suffix
=
strrchr
(
name
,
'.'
);
suffix
=
strrchr
(
name
,
'.'
);
if
(
suffix
)
{
if
(
strcmp
(
suffix
,
".readonly"
)
==
0
)
{
if
(
strcmp
(
suffix
,
".readonly"
)
==
0
)
{
type
=
AFSVL_ROVOL
;
force
=
1
;
}
else
if
(
strcmp
(
suffix
,
".backup"
)
==
0
)
{
else
if
(
strcmp
(
suffix
,
".backup"
)
==
0
)
{
type
=
AFSVL_BACKVOL
;
force
=
1
;
}
else
if
(
suffix
[
1
]
==
0
)
{
*
suffix
=
0
;
suffix
=
NULL
;
else
if
(
suffix
[
1
]
==
0
)
{
}
else
{
suffix
=
NULL
;
...
...
@@ -90,38 +104,45 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
/* split the cell and volume names */
name
++
;
volname
=
strchr
(
name
,
':'
);
volname
=
strchr
(
name
,
':'
);
if
(
volname
)
{
*
volname
++
=
0
;
cellname
=
name
;
cellnamesz
=
volname
-
name
;
}
else
{
volname
=
name
;
cellname
=
NULL
;
cellnamesz
=
0
;
}
_debug
(
"CELL:%s VOLUME:%s SUFFIX:%s TYPE:%d%s"
,
cellname
,
volname
,
suffix
?:
"-"
,
type
,
force
?
" FORCE"
:
""
);
volnamesz
=
suffix
?
suffix
-
volname
:
strlen
(
volname
);
/* lookup the cell record */
ret
=
afs_cell_lookup
(
cellname
,
&
cell
);
if
(
ret
<
0
)
printk
(
"kAFS: unable to lookup cell '%s'
\n
"
,
cellname
?:
""
);
_debug
(
"CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s"
,
cellnamesz
,
cellnamesz
,
cellname
?:
""
,
cell
,
volnamesz
,
volnamesz
,
volname
,
suffix
?:
"-"
,
type
,
force
?
" FORCE"
:
""
);
if
(
cellname
)
volname
[
-
1
]
=
':'
;
if
(
ret
<
0
)
goto
error
;
/* lookup the cell record */
if
(
cellname
||
!
cell
)
{
ret
=
afs_cell_lookup
(
cellname
,
cellnamesz
,
&
cell
);
if
(
ret
<
0
)
{
printk
(
"kAFS: unable to lookup cell '%s'
\n
"
,
cellname
?:
""
);
goto
error
;
}
}
else
{
afs_get_cell
(
cell
);
}
/* lookup the volume location record */
if
(
suffix
)
*
suffix
=
0
;
ret
=
afs_vlocation_lookup
(
cell
,
volname
,
&
vlocation
);
if
(
suffix
)
*
suffix
=
'.'
;
if
(
ret
<
0
)
ret
=
afs_vlocation_lookup
(
cell
,
volname
,
volnamesz
,
&
vlocation
);
if
(
ret
<
0
)
goto
error
;
/* make the final decision on the type we want */
ret
=
-
ENOMEDIUM
;
if
(
force
&&
!
(
vlocation
->
vldb
.
vidmask
&
(
1
<<
type
)))
if
(
force
&&
!
(
vlocation
->
vldb
.
vidmask
&
(
1
<<
type
)))
goto
error
;
srvtmask
=
0
;
...
...
@@ -129,13 +150,13 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
srvtmask
|=
vlocation
->
vldb
.
srvtmask
[
loop
];
if
(
force
)
{
if
(
!
(
srvtmask
&
(
1
<<
type
)))
if
(
!
(
srvtmask
&
(
1
<<
type
)))
goto
error
;
}
else
if
(
srvtmask
&
AFS
C_VOL_S
TM_RO
)
{
else
if
(
srvtmask
&
AFS
_VOL_V
TM_RO
)
{
type
=
AFSVL_ROVOL
;
}
else
if
(
srvtmask
&
AFS
C_VOL_S
TM_RW
)
{
else
if
(
srvtmask
&
AFS
_VOL_V
TM_RW
)
{
type
=
AFSVL_RWVOL
;
}
else
{
...
...
@@ -156,16 +177,16 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
_debug
(
"creating new volume record"
);
ret
=
-
ENOMEM
;
volume
=
kmalloc
(
sizeof
(
afs_volume_t
),
GFP_KERNEL
);
volume
=
kmalloc
(
sizeof
(
afs_volume_t
),
GFP_KERNEL
);
if
(
!
volume
)
goto
error_up
;
memset
(
volume
,
0
,
sizeof
(
afs_volume_t
));
atomic_set
(
&
volume
->
usage
,
1
);
volume
->
type
=
type
;
volume
->
type_force
=
force
;
volume
->
cell
=
cell
;
volume
->
vid
=
vlocation
->
vldb
.
vid
[
type
];
memset
(
volume
,
0
,
sizeof
(
afs_volume_t
));
atomic_set
(
&
volume
->
usage
,
1
);
volume
->
type
=
type
;
volume
->
type_force
=
force
;
volume
->
cell
=
cell
;
volume
->
vid
=
vlocation
->
vldb
.
vid
[
type
];
init_rwsem
(
&
volume
->
server_sem
);
...
...
@@ -183,15 +204,20 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
}
/* attach the cache and volume location */
#if 0
afs_get_cache(cache); volume->cache = cache;
#ifdef AFS_CACHING_SUPPORT
cachefs_acquire_cookie
(
vlocation
->
cache
,
&
afs_vnode_cache_index_def
,
volume
,
&
volume
->
cache
);
#endif
afs_get_vlocation
(
vlocation
);
volume
->
vlocation
=
vlocation
;
afs_get_vlocation
(
vlocation
);
volume
->
vlocation
=
vlocation
;
vlocation
->
vols
[
type
]
=
volume
;
success:
_debug
(
"kAFS selected %s volume %08x"
,
afs_voltypes
[
volume
->
type
],
volume
->
vid
);
_debug
(
"kAFS selected %s volume %08x"
,
afs_voltypes
[
volume
->
type
],
volume
->
vid
);
*
_volume
=
volume
;
ret
=
0
;
...
...
@@ -199,18 +225,17 @@ int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume)
error_up:
up_write
(
&
cell
->
vl_sem
);
error:
if
(
vlocation
)
afs_put_vlocation
(
vlocation
);
if
(
cell
)
afs_put_cell
(
cell
);
afs_put_vlocation
(
vlocation
);
afs_put_cell
(
cell
);
_leave
(
" = %d (%p)"
,
ret
,
volume
);
_leave
(
" = %d (%p)"
,
ret
,
volume
);
return
ret
;
error_discard:
up_write
(
&
cell
->
vl_sem
);
for
(
loop
=
volume
->
nservers
-
1
;
loop
>=
0
;
loop
--
)
if
(
volume
->
servers
[
loop
])
afs_put_server
(
volume
->
servers
[
loop
]);
afs_put_server
(
volume
->
servers
[
loop
]);
kfree
(
volume
);
goto
error
;
...
...
@@ -225,6 +250,9 @@ void afs_put_volume(afs_volume_t *volume)
afs_vlocation_t
*
vlocation
;
int
loop
;
if
(
!
volume
)
return
;
_enter
(
"%p"
,
volume
);
vlocation
=
volume
->
vlocation
;
...
...
@@ -246,16 +274,14 @@ void afs_put_volume(afs_volume_t *volume)
up_write
(
&
vlocation
->
cell
->
vl_sem
);
afs_put_vlocation
(
vlocation
);
/* finish cleaning up the volume */
#if
0
if (volume->cache) afs_put_cache(volume->cache
);
#if
def AFS_CACHING_SUPPORT
cachefs_relinquish_cookie
(
volume
->
cache
,
0
);
#endif
afs_put_vlocation
(
vlocation
);
for
(
loop
=
volume
->
nservers
-
1
;
loop
>=
0
;
loop
--
)
if
(
volume
->
servers
[
loop
])
afs_put_server
(
volume
->
servers
[
loop
]);
afs_put_server
(
volume
->
servers
[
loop
]);
kfree
(
volume
);
...
...
@@ -428,3 +454,42 @@ int afs_volume_release_fileserver(afs_volume_t *volume, afs_server_t *server, in
return
0
;
}
/* end afs_volume_release_fileserver() */
/*****************************************************************************/
/*
* 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
;
}
/* end afs_volume_cache_match() */
#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
;
}
/* end afs_volume_cache_update() */
#endif
fs/afs/volume.h
View file @
7a9df5e2
...
...
@@ -16,7 +16,7 @@
#include "fsclient.h"
#include "kafstimod.h"
#include "kafsasyncd.h"
#include "cache
-layout
.h"
#include "cache.h"
#define __packed __attribute__((packed))
...
...
@@ -28,6 +28,43 @@ typedef enum {
}
__attribute__
((
packed
))
afs_vlocation_upd_t
;
/*****************************************************************************/
/*
* entry in the cached volume location catalogue
*/
struct
afs_cache_vlocation
{
uint8_t
name
[
64
];
/* volume name (lowercase, padded with NULs) */
uint8_t
nservers
;
/* number of entries used in servers[] */
uint8_t
vidmask
;
/* voltype mask for vid[] */
uint8_t
srvtmask
[
8
];
/* voltype masks for servers[] */
#define AFS_VOL_VTM_RW 0x01
/* R/W version of the volume is available (on this server) */
#define AFS_VOL_VTM_RO 0x02
/* R/O version of the volume is available (on this server) */
#define AFS_VOL_VTM_BAK 0x04
/* backup version of the volume is available (on this server) */
afs_volid_t
vid
[
3
];
/* volume IDs for R/W, R/O and Bak volumes */
struct
in_addr
servers
[
8
];
/* fileserver addresses */
time_t
rtime
;
/* last retrieval time */
};
#ifdef AFS_CACHING_SUPPORT
extern
struct
cachefs_index_def
afs_vlocation_cache_index_def
;
#endif
/*****************************************************************************/
/*
* volume -> vnode hash table entry
*/
struct
afs_cache_vhash
{
afs_voltype_t
vtype
;
/* which volume variation */
uint8_t
hash_bucket
;
/* which hash bucket this represents */
}
__attribute__
((
packed
));
#ifdef AFS_CACHING_SUPPORT
extern
struct
cachefs_index_def
afs_volume_cache_index_def
;
#endif
/*****************************************************************************/
/*
* AFS volume location record
...
...
@@ -36,15 +73,17 @@ struct afs_vlocation
{
atomic_t
usage
;
struct
list_head
link
;
/* link in cell volume location list */
afs_timer_t
timeout
;
/* decaching timer */
afs_cell_t
*
cell
;
/* cell to which volume belongs */
struct
list_head
caches
;
/* backing caches */
afsc_vldb_record_t
vldb
;
/* volume information DB record */
struct
afs_timer
timeout
;
/* decaching timer */
struct
afs_cell
*
cell
;
/* cell to which volume belongs */
#ifdef AFS_CACHING_SUPPORT
struct
cachefs_cookie
*
cache
;
/* caching cookie */
#endif
struct
afs_cache_vlocation
vldb
;
/* volume information DB record */
struct
afs_volume
*
vols
[
3
];
/* volume access record pointer (index by type) */
rwlock_t
lock
;
/* access lock */
unsigned
long
read_jif
;
/* time at which last read from vlserver */
afs_timer_t
upd_timer
;
/* update timer */
afs_async_op_t
upd_op
;
/* update operation */
struct
afs_timer
upd_timer
;
/* update timer */
struct
afs_async_op
upd_op
;
/* update operation */
afs_vlocation_upd_t
upd_state
;
/* update state */
unsigned
short
upd_first_svix
;
/* first server index during update */
unsigned
short
upd_curr_svix
;
/* current server index during update */
...
...
@@ -53,13 +92,16 @@ struct afs_vlocation
unsigned
short
valid
;
/* T if valid */
};
extern
int
afs_vlocation_lookup
(
afs_cell_t
*
cell
,
const
char
*
name
,
afs_vlocation_t
**
_vlocation
);
extern
int
afs_vlocation_lookup
(
struct
afs_cell
*
cell
,
const
char
*
name
,
unsigned
namesz
,
struct
afs_vlocation
**
_vlocation
);
#define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
extern
void
__afs_put_vlocation
(
afs_vlocation_t
*
vlocation
);
extern
void
afs_put_vlocation
(
afs_vlocation_t
*
vlocation
);
extern
void
afs_vlocation_do_timeout
(
afs_vlocation_t
*
vlocation
);
extern
void
__afs_put_vlocation
(
struct
afs_vlocation
*
vlocation
);
extern
void
afs_put_vlocation
(
struct
afs_vlocation
*
vlocation
);
extern
void
afs_vlocation_do_timeout
(
struct
afs_vlocation
*
vlocation
);
/*****************************************************************************/
/*
...
...
@@ -68,25 +110,34 @@ extern void afs_vlocation_do_timeout(afs_vlocation_t *vlocation);
struct
afs_volume
{
atomic_t
usage
;
afs_cell_t
*
cell
;
/* cell to which belongs (unrefd ptr) */
afs_vlocation_t
*
vlocation
;
/* volume location */
struct
afs_cell
*
cell
;
/* cell to which belongs (unrefd ptr) */
struct
afs_vlocation
*
vlocation
;
/* volume location */
#ifdef AFS_CACHING_SUPPORT
struct
cachefs_cookie
*
cache
;
/* caching cookie */
#endif
afs_volid_t
vid
;
/* volume ID */
afs_voltype_t
__packed
type
;
/* type of volume */
char
type_force
;
/* force volume type (suppress R/O -> R/W) */
unsigned
short
nservers
;
/* number of server slots filled */
unsigned
short
rjservers
;
/* number of servers discarded due to -ENOMEDIUM */
afs_server_t
*
servers
[
8
];
/* servers on which volume resides (ordered) */
struct
afs_server
*
servers
[
8
];
/* servers on which volume resides (ordered) */
struct
rw_semaphore
server_sem
;
/* lock for accessing current server */
};
extern
int
afs_volume_lookup
(
const
char
*
name
,
int
ro
,
afs_volume_t
**
_volume
);
extern
int
afs_volume_lookup
(
const
char
*
name
,
struct
afs_cell
*
cell
,
int
rwpath
,
struct
afs_volume
**
_volume
);
#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0)
extern
void
afs_put_volume
(
afs_volume_t
*
volume
);
extern
void
afs_put_volume
(
struct
afs_volume
*
volume
);
extern
int
afs_volume_pick_fileserver
(
afs_volume_t
*
volume
,
afs_server_t
**
_server
);
extern
int
afs_volume_pick_fileserver
(
struct
afs_volume
*
volume
,
struct
afs_server
**
_server
);
extern
int
afs_volume_release_fileserver
(
afs_volume_t
*
volume
,
afs_server_t
*
server
,
int
result
);
extern
int
afs_volume_release_fileserver
(
struct
afs_volume
*
volume
,
struct
afs_server
*
server
,
int
result
);
#endif
/* _LINUX_AFS_VOLUME_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment