Commit 8dda9957 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'afs-next-20190628' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

Pull afs updates from David Howells:
 "A set of minor changes for AFS:

   - Remove an unnecessary check in afs_unlink()

   - Add a tracepoint for tracking callback management

   - Add a tracepoint for afs_server object usage

   - Use struct_size()

   - Add mappings for AFS UAE abort codes to Linux error codes, using
     symbolic names rather than hex numbers in the .c file"

* tag 'afs-next-20190628' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  afs: Add support for the UAE error table
  fs/afs: use struct_size() in kzalloc()
  afs: Trace afs_server usage
  afs: Add some callback management tracepoints
  afs: afs_unlink() doesn't need to check dentry->d_inode
parents 25cd6f35 1eda8bab
...@@ -48,7 +48,7 @@ static struct afs_cb_interest *afs_create_interest(struct afs_server *server, ...@@ -48,7 +48,7 @@ static struct afs_cb_interest *afs_create_interest(struct afs_server *server,
refcount_set(&new->usage, 1); refcount_set(&new->usage, 1);
new->sb = vnode->vfs_inode.i_sb; new->sb = vnode->vfs_inode.i_sb;
new->vid = vnode->volume->vid; new->vid = vnode->volume->vid;
new->server = afs_get_server(server); new->server = afs_get_server(server, afs_server_trace_get_new_cbi);
INIT_HLIST_NODE(&new->cb_vlink); INIT_HLIST_NODE(&new->cb_vlink);
write_lock(&server->cb_break_lock); write_lock(&server->cb_break_lock);
...@@ -195,7 +195,7 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi) ...@@ -195,7 +195,7 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
write_unlock(&cbi->server->cb_break_lock); write_unlock(&cbi->server->cb_break_lock);
if (vi) if (vi)
kfree_rcu(vi, rcu); kfree_rcu(vi, rcu);
afs_put_server(net, cbi->server); afs_put_server(net, cbi->server, afs_server_trace_put_cbi);
} }
kfree_rcu(cbi, rcu); kfree_rcu(cbi, rcu);
} }
...@@ -212,7 +212,7 @@ void afs_init_callback_state(struct afs_server *server) ...@@ -212,7 +212,7 @@ void afs_init_callback_state(struct afs_server *server)
/* /*
* actually break a callback * actually break a callback
*/ */
void __afs_break_callback(struct afs_vnode *vnode) void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reason)
{ {
_enter(""); _enter("");
...@@ -223,13 +223,17 @@ void __afs_break_callback(struct afs_vnode *vnode) ...@@ -223,13 +223,17 @@ void __afs_break_callback(struct afs_vnode *vnode)
if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB) if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB)
afs_lock_may_be_available(vnode); afs_lock_may_be_available(vnode);
trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true);
} else {
trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, false);
} }
} }
void afs_break_callback(struct afs_vnode *vnode) void afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reason)
{ {
write_seqlock(&vnode->cb_lock); write_seqlock(&vnode->cb_lock);
__afs_break_callback(vnode); __afs_break_callback(vnode, reason);
write_sequnlock(&vnode->cb_lock); write_sequnlock(&vnode->cb_lock);
} }
...@@ -277,6 +281,8 @@ static void afs_break_one_callback(struct afs_server *server, ...@@ -277,6 +281,8 @@ static void afs_break_one_callback(struct afs_server *server,
write_lock(&volume->cb_v_break_lock); write_lock(&volume->cb_v_break_lock);
volume->cb_v_break++; volume->cb_v_break++;
trace_afs_cb_break(fid, volume->cb_v_break,
afs_cb_break_for_volume_callback, false);
write_unlock(&volume->cb_v_break_lock); write_unlock(&volume->cb_v_break_lock);
} else { } else {
data.volume = NULL; data.volume = NULL;
...@@ -285,8 +291,10 @@ static void afs_break_one_callback(struct afs_server *server, ...@@ -285,8 +291,10 @@ static void afs_break_one_callback(struct afs_server *server,
afs_iget5_test, &data); afs_iget5_test, &data);
if (inode) { if (inode) {
vnode = AFS_FS_I(inode); vnode = AFS_FS_I(inode);
afs_break_callback(vnode); afs_break_callback(vnode, afs_cb_break_for_callback);
iput(inode); iput(inode);
} else {
trace_afs_cb_miss(fid, afs_cb_break_for_callback);
} }
} }
} }
......
...@@ -256,8 +256,11 @@ static void SRXAFSCB_CallBack(struct work_struct *work) ...@@ -256,8 +256,11 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
* server holds up change visibility till it receives our reply so as * server holds up change visibility till it receives our reply so as
* to maintain cache coherency. * to maintain cache coherency.
*/ */
if (call->server) if (call->server) {
trace_afs_server(call->server, atomic_read(&call->server->usage),
afs_server_trace_callback);
afs_break_callbacks(call->server, call->count, call->request); afs_break_callbacks(call->server, call->count, call->request);
}
afs_send_empty_reply(call); afs_send_empty_reply(call);
afs_put_call(call); afs_put_call(call);
......
...@@ -238,8 +238,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) ...@@ -238,8 +238,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *)) if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *))
nr_inline = 0; nr_inline = 0;
req = kzalloc(sizeof(*req) + sizeof(struct page *) * nr_inline, req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL);
GFP_KERNEL);
if (!req) if (!req)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -1363,12 +1362,12 @@ static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry, ...@@ -1363,12 +1362,12 @@ static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
drop_nlink(&vnode->vfs_inode); drop_nlink(&vnode->vfs_inode);
if (vnode->vfs_inode.i_nlink == 0) { if (vnode->vfs_inode.i_nlink == 0) {
set_bit(AFS_VNODE_DELETED, &vnode->flags); set_bit(AFS_VNODE_DELETED, &vnode->flags);
__afs_break_callback(vnode); __afs_break_callback(vnode, afs_cb_break_for_unlink);
} }
write_sequnlock(&vnode->cb_lock); write_sequnlock(&vnode->cb_lock);
ret = 0; ret = 0;
} else { } else {
afs_break_callback(vnode); afs_break_callback(vnode, afs_cb_break_for_unlink);
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
kdebug("AFS_VNODE_DELETED"); kdebug("AFS_VNODE_DELETED");
...@@ -1390,7 +1389,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1390,7 +1389,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct afs_fs_cursor fc; struct afs_fs_cursor fc;
struct afs_status_cb *scb; struct afs_status_cb *scb;
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; struct afs_vnode *dvnode = AFS_FS_I(dir);
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
struct key *key; struct key *key;
bool need_rehash = false; bool need_rehash = false;
int ret; int ret;
...@@ -1413,15 +1413,12 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1413,15 +1413,12 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
} }
/* Try to make sure we have a callback promise on the victim. */ /* Try to make sure we have a callback promise on the victim. */
if (d_really_is_positive(dentry)) { ret = afs_validate(vnode, key);
vnode = AFS_FS_I(d_inode(dentry)); if (ret < 0)
ret = afs_validate(vnode, key); goto error_key;
if (ret < 0)
goto error_key;
}
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
if (vnode && d_count(dentry) > 1) { if (d_count(dentry) > 1) {
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
/* Start asynchronous writeout of the inode */ /* Start asynchronous writeout of the inode */
write_inode_now(d_inode(dentry), 0); write_inode_now(d_inode(dentry), 0);
......
...@@ -310,8 +310,7 @@ int afs_page_filler(void *data, struct page *page) ...@@ -310,8 +310,7 @@ int afs_page_filler(void *data, struct page *page)
/* fall through */ /* fall through */
default: default:
go_on: go_on:
req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), req = kzalloc(struct_size(req, array, 1), GFP_KERNEL);
GFP_KERNEL);
if (!req) if (!req)
goto enomem; goto enomem;
...@@ -461,8 +460,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, ...@@ -461,8 +460,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping,
n++; n++;
} }
req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *) * n, req = kzalloc(struct_size(req, array, n), GFP_NOFS);
GFP_NOFS);
if (!req) if (!req)
return -ENOMEM; return -ENOMEM;
......
...@@ -1911,7 +1911,7 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net, ...@@ -1911,7 +1911,7 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
call->key = key; call->key = key;
call->server = afs_get_server(server); call->server = afs_get_server(server, afs_server_trace_get_caps);
call->server_index = server_index; call->server_index = server_index;
call->upgrade = true; call->upgrade = true;
call->async = true; call->async = true;
......
...@@ -283,7 +283,7 @@ void afs_vnode_commit_status(struct afs_fs_cursor *fc, ...@@ -283,7 +283,7 @@ void afs_vnode_commit_status(struct afs_fs_cursor *fc,
if (scb->status.abort_code == VNOVNODE) { if (scb->status.abort_code == VNOVNODE) {
set_bit(AFS_VNODE_DELETED, &vnode->flags); set_bit(AFS_VNODE_DELETED, &vnode->flags);
clear_nlink(&vnode->vfs_inode); clear_nlink(&vnode->vfs_inode);
__afs_break_callback(vnode); __afs_break_callback(vnode, afs_cb_break_for_deleted);
} }
} else { } else {
if (scb->have_status) if (scb->have_status)
...@@ -594,8 +594,9 @@ bool afs_check_validity(struct afs_vnode *vnode) ...@@ -594,8 +594,9 @@ bool afs_check_validity(struct afs_vnode *vnode)
struct afs_cb_interest *cbi; struct afs_cb_interest *cbi;
struct afs_server *server; struct afs_server *server;
struct afs_volume *volume = vnode->volume; struct afs_volume *volume = vnode->volume;
enum afs_cb_break_reason need_clear = afs_cb_break_no_break;
time64_t now = ktime_get_real_seconds(); time64_t now = ktime_get_real_seconds();
bool valid, need_clear = false; bool valid;
unsigned int cb_break, cb_s_break, cb_v_break; unsigned int cb_break, cb_s_break, cb_v_break;
int seq = 0; int seq = 0;
...@@ -613,13 +614,13 @@ bool afs_check_validity(struct afs_vnode *vnode) ...@@ -613,13 +614,13 @@ bool afs_check_validity(struct afs_vnode *vnode)
vnode->cb_v_break != cb_v_break) { vnode->cb_v_break != cb_v_break) {
vnode->cb_s_break = cb_s_break; vnode->cb_s_break = cb_s_break;
vnode->cb_v_break = cb_v_break; vnode->cb_v_break = cb_v_break;
need_clear = true; need_clear = afs_cb_break_for_vsbreak;
valid = false; valid = false;
} else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
need_clear = true; need_clear = afs_cb_break_for_zap;
valid = false; valid = false;
} else if (vnode->cb_expires_at - 10 <= now) { } else if (vnode->cb_expires_at - 10 <= now) {
need_clear = true; need_clear = afs_cb_break_for_lapsed;
valid = false; valid = false;
} else { } else {
valid = true; valid = true;
...@@ -635,10 +636,12 @@ bool afs_check_validity(struct afs_vnode *vnode) ...@@ -635,10 +636,12 @@ bool afs_check_validity(struct afs_vnode *vnode)
done_seqretry(&vnode->cb_lock, seq); done_seqretry(&vnode->cb_lock, seq);
if (need_clear) { if (need_clear != afs_cb_break_no_break) {
write_seqlock(&vnode->cb_lock); write_seqlock(&vnode->cb_lock);
if (cb_break == vnode->cb_break) if (cb_break == vnode->cb_break)
__afs_break_callback(vnode); __afs_break_callback(vnode, need_clear);
else
trace_afs_cb_miss(&vnode->fid, need_clear);
write_sequnlock(&vnode->cb_lock); write_sequnlock(&vnode->cb_lock);
valid = false; valid = false;
} }
......
...@@ -514,6 +514,7 @@ struct afs_server { ...@@ -514,6 +514,7 @@ struct afs_server {
atomic_t usage; atomic_t usage;
u32 addr_version; /* Address list version */ u32 addr_version; /* Address list version */
u32 cm_epoch; /* Server RxRPC epoch */ u32 cm_epoch; /* Server RxRPC epoch */
unsigned int debug_id; /* Debugging ID for traces */
/* file service access */ /* file service access */
rwlock_t fs_lock; /* access lock */ rwlock_t fs_lock; /* access lock */
...@@ -844,9 +845,9 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def; ...@@ -844,9 +845,9 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def;
* callback.c * callback.c
*/ */
extern void afs_init_callback_state(struct afs_server *); extern void afs_init_callback_state(struct afs_server *);
extern void __afs_break_callback(struct afs_vnode *); extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
extern void afs_break_callback(struct afs_vnode *); extern void afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break *);
extern int afs_register_server_cb_interest(struct afs_vnode *, extern int afs_register_server_cb_interest(struct afs_vnode *,
struct afs_server_list *, unsigned int); struct afs_server_list *, unsigned int);
...@@ -1240,17 +1241,12 @@ extern void __exit afs_clean_up_permit_cache(void); ...@@ -1240,17 +1241,12 @@ extern void __exit afs_clean_up_permit_cache(void);
*/ */
extern spinlock_t afs_server_peer_lock; extern spinlock_t afs_server_peer_lock;
static inline struct afs_server *afs_get_server(struct afs_server *server)
{
atomic_inc(&server->usage);
return server;
}
extern struct afs_server *afs_find_server(struct afs_net *, extern struct afs_server *afs_find_server(struct afs_net *,
const struct sockaddr_rxrpc *); const struct sockaddr_rxrpc *);
extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *); extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *); extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *);
extern void afs_put_server(struct afs_net *, struct afs_server *); extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
extern void afs_put_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
extern void afs_manage_servers(struct work_struct *); extern void afs_manage_servers(struct work_struct *);
extern void afs_servers_timer(struct timer_list *); extern void afs_servers_timer(struct timer_list *);
extern void __net_exit afs_purge_servers(struct afs_net *); extern void __net_exit afs_purge_servers(struct afs_net *);
...@@ -1434,7 +1430,7 @@ static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc, ...@@ -1434,7 +1430,7 @@ static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc,
{ {
if (fc->ac.error == -ENOENT) { if (fc->ac.error == -ENOENT) {
set_bit(AFS_VNODE_DELETED, &vnode->flags); set_bit(AFS_VNODE_DELETED, &vnode->flags);
afs_break_callback(vnode); afs_break_callback(vnode, afs_cb_break_for_deleted);
} }
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include "internal.h" #include "internal.h"
#include "afs_fs.h" #include "afs_fs.h"
#include "protocol_uae.h"
/* /*
* convert an AFS abort code to a Linux error number * convert an AFS abort code to a Linux error number
...@@ -65,34 +66,25 @@ int afs_abort_to_error(u32 abort_code) ...@@ -65,34 +66,25 @@ int afs_abort_to_error(u32 abort_code)
case AFSVL_PERM: return -EACCES; case AFSVL_PERM: return -EACCES;
case AFSVL_NOMEM: return -EREMOTEIO; case AFSVL_NOMEM: return -EREMOTEIO;
/* Unified AFS error table; ET "uae" == 0x2f6df00 */ /* Unified AFS error table */
case 0x2f6df00: return -EPERM; case UAEPERM: return -EPERM;
case 0x2f6df01: return -ENOENT; case UAENOENT: return -ENOENT;
case 0x2f6df04: return -EIO; case UAEACCES: return -EACCES;
case 0x2f6df0a: return -EAGAIN; case UAEBUSY: return -EBUSY;
case 0x2f6df0b: return -ENOMEM; case UAEEXIST: return -EEXIST;
case 0x2f6df0c: return -EACCES; case UAENOTDIR: return -ENOTDIR;
case 0x2f6df0f: return -EBUSY; case UAEISDIR: return -EISDIR;
case 0x2f6df10: return -EEXIST; case UAEFBIG: return -EFBIG;
case 0x2f6df11: return -EXDEV; case UAENOSPC: return -ENOSPC;
case 0x2f6df12: return -ENODEV; case UAEROFS: return -EROFS;
case 0x2f6df13: return -ENOTDIR; case UAEMLINK: return -EMLINK;
case 0x2f6df14: return -EISDIR; case UAEDEADLK: return -EDEADLK;
case 0x2f6df15: return -EINVAL; case UAENAMETOOLONG: return -ENAMETOOLONG;
case 0x2f6df1a: return -EFBIG; case UAENOLCK: return -ENOLCK;
case 0x2f6df1b: return -ENOSPC; case UAENOTEMPTY: return -ENOTEMPTY;
case 0x2f6df1d: return -EROFS; case UAELOOP: return -ELOOP;
case 0x2f6df1e: return -EMLINK; case UAENOMEDIUM: return -ENOMEDIUM;
case 0x2f6df20: return -EDOM; case UAEDQUOT: return -EDQUOT;
case 0x2f6df21: return -ERANGE;
case 0x2f6df22: return -EDEADLK;
case 0x2f6df23: return -ENAMETOOLONG;
case 0x2f6df24: return -ENOLCK;
case 0x2f6df26: return -ENOTEMPTY;
case 0x2f6df28: return -EWOULDBLOCK;
case 0x2f6df69: return -ENOTCONN;
case 0x2f6df6c: return -ETIMEDOUT;
case 0x2f6df78: return -EDQUOT;
/* RXKAD abort codes; from include/rxrpc/packet.h. ET "RXK" == 0x1260B00 */ /* RXKAD abort codes; from include/rxrpc/packet.h. ET "RXK" == 0x1260B00 */
case RXKADINCONSISTENCY: return -EPROTO; case RXKADINCONSISTENCY: return -EPROTO;
......
// SPDX-License-Identifier: GPL-2.0
/* Universal AFS Error codes (UAE).
*
* Copyright (C) 2003, Daria Phoebe Brashear
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
*/
enum {
UAEPERM = 0x2f6df00, /* Operation not permitted */
UAENOENT = 0x2f6df01, /* No such file or directory */
UAESRCH = 0x2f6df02, /* No such process */
UAEINTR = 0x2f6df03, /* Interrupted system call */
UAEIO = 0x2f6df04, /* I/O error */
UAENXIO = 0x2f6df05, /* No such device or address */
UAE2BIG = 0x2f6df06, /* Arg list too long */
UAENOEXEC = 0x2f6df07, /* Exec format error */
UAEBADF = 0x2f6df08, /* Bad file number */
UAECHILD = 0x2f6df09, /* No child processes */
UAEAGAIN = 0x2f6df0a, /* Try again */
UAENOMEM = 0x2f6df0b, /* Out of memory */
UAEACCES = 0x2f6df0c, /* Permission denied */
UAEFAULT = 0x2f6df0d, /* Bad address */
UAENOTBLK = 0x2f6df0e, /* Block device required */
UAEBUSY = 0x2f6df0f, /* Device or resource busy */
UAEEXIST = 0x2f6df10, /* File exists */
UAEXDEV = 0x2f6df11, /* Cross-device link */
UAENODEV = 0x2f6df12, /* No such device */
UAENOTDIR = 0x2f6df13, /* Not a directory */
UAEISDIR = 0x2f6df14, /* Is a directory */
UAEINVAL = 0x2f6df15, /* Invalid argument */
UAENFILE = 0x2f6df16, /* File table overflow */
UAEMFILE = 0x2f6df17, /* Too many open files */
UAENOTTY = 0x2f6df18, /* Not a typewriter */
UAETXTBSY = 0x2f6df19, /* Text file busy */
UAEFBIG = 0x2f6df1a, /* File too large */
UAENOSPC = 0x2f6df1b, /* No space left on device */
UAESPIPE = 0x2f6df1c, /* Illegal seek */
UAEROFS = 0x2f6df1d, /* Read-only file system */
UAEMLINK = 0x2f6df1e, /* Too many links */
UAEPIPE = 0x2f6df1f, /* Broken pipe */
UAEDOM = 0x2f6df20, /* Math argument out of domain of func */
UAERANGE = 0x2f6df21, /* Math result not representable */
UAEDEADLK = 0x2f6df22, /* Resource deadlock would occur */
UAENAMETOOLONG = 0x2f6df23, /* File name too long */
UAENOLCK = 0x2f6df24, /* No record locks available */
UAENOSYS = 0x2f6df25, /* Function not implemented */
UAENOTEMPTY = 0x2f6df26, /* Directory not empty */
UAELOOP = 0x2f6df27, /* Too many symbolic links encountered */
UAEWOULDBLOCK = 0x2f6df28, /* Operation would block */
UAENOMSG = 0x2f6df29, /* No message of desired type */
UAEIDRM = 0x2f6df2a, /* Identifier removed */
UAECHRNG = 0x2f6df2b, /* Channel number out of range */
UAEL2NSYNC = 0x2f6df2c, /* Level 2 not synchronized */
UAEL3HLT = 0x2f6df2d, /* Level 3 halted */
UAEL3RST = 0x2f6df2e, /* Level 3 reset */
UAELNRNG = 0x2f6df2f, /* Link number out of range */
UAEUNATCH = 0x2f6df30, /* Protocol driver not attached */
UAENOCSI = 0x2f6df31, /* No CSI structure available */
UAEL2HLT = 0x2f6df32, /* Level 2 halted */
UAEBADE = 0x2f6df33, /* Invalid exchange */
UAEBADR = 0x2f6df34, /* Invalid request descriptor */
UAEXFULL = 0x2f6df35, /* Exchange full */
UAENOANO = 0x2f6df36, /* No anode */
UAEBADRQC = 0x2f6df37, /* Invalid request code */
UAEBADSLT = 0x2f6df38, /* Invalid slot */
UAEBFONT = 0x2f6df39, /* Bad font file format */
UAENOSTR = 0x2f6df3a, /* Device not a stream */
UAENODATA = 0x2f6df3b, /* No data available */
UAETIME = 0x2f6df3c, /* Timer expired */
UAENOSR = 0x2f6df3d, /* Out of streams resources */
UAENONET = 0x2f6df3e, /* Machine is not on the network */
UAENOPKG = 0x2f6df3f, /* Package not installed */
UAEREMOTE = 0x2f6df40, /* Object is remote */
UAENOLINK = 0x2f6df41, /* Link has been severed */
UAEADV = 0x2f6df42, /* Advertise error */
UAESRMNT = 0x2f6df43, /* Srmount error */
UAECOMM = 0x2f6df44, /* Communication error on send */
UAEPROTO = 0x2f6df45, /* Protocol error */
UAEMULTIHOP = 0x2f6df46, /* Multihop attempted */
UAEDOTDOT = 0x2f6df47, /* RFS specific error */
UAEBADMSG = 0x2f6df48, /* Not a data message */
UAEOVERFLOW = 0x2f6df49, /* Value too large for defined data type */
UAENOTUNIQ = 0x2f6df4a, /* Name not unique on network */
UAEBADFD = 0x2f6df4b, /* File descriptor in bad state */
UAEREMCHG = 0x2f6df4c, /* Remote address changed */
UAELIBACC = 0x2f6df4d, /* Can not access a needed shared library */
UAELIBBAD = 0x2f6df4e, /* Accessing a corrupted shared library */
UAELIBSCN = 0x2f6df4f, /* .lib section in a.out corrupted */
UAELIBMAX = 0x2f6df50, /* Attempting to link in too many shared libraries */
UAELIBEXEC = 0x2f6df51, /* Cannot exec a shared library directly */
UAEILSEQ = 0x2f6df52, /* Illegal byte sequence */
UAERESTART = 0x2f6df53, /* Interrupted system call should be restarted */
UAESTRPIPE = 0x2f6df54, /* Streams pipe error */
UAEUSERS = 0x2f6df55, /* Too many users */
UAENOTSOCK = 0x2f6df56, /* Socket operation on non-socket */
UAEDESTADDRREQ = 0x2f6df57, /* Destination address required */
UAEMSGSIZE = 0x2f6df58, /* Message too long */
UAEPROTOTYPE = 0x2f6df59, /* Protocol wrong type for socket */
UAENOPROTOOPT = 0x2f6df5a, /* Protocol not available */
UAEPROTONOSUPPORT = 0x2f6df5b, /* Protocol not supported */
UAESOCKTNOSUPPORT = 0x2f6df5c, /* Socket type not supported */
UAEOPNOTSUPP = 0x2f6df5d, /* Operation not supported on transport endpoint */
UAEPFNOSUPPORT = 0x2f6df5e, /* Protocol family not supported */
UAEAFNOSUPPORT = 0x2f6df5f, /* Address family not supported by protocol */
UAEADDRINUSE = 0x2f6df60, /* Address already in use */
UAEADDRNOTAVAIL = 0x2f6df61, /* Cannot assign requested address */
UAENETDOWN = 0x2f6df62, /* Network is down */
UAENETUNREACH = 0x2f6df63, /* Network is unreachable */
UAENETRESET = 0x2f6df64, /* Network dropped connection because of reset */
UAECONNABORTED = 0x2f6df65, /* Software caused connection abort */
UAECONNRESET = 0x2f6df66, /* Connection reset by peer */
UAENOBUFS = 0x2f6df67, /* No buffer space available */
UAEISCONN = 0x2f6df68, /* Transport endpoint is already connected */
UAENOTCONN = 0x2f6df69, /* Transport endpoint is not connected */
UAESHUTDOWN = 0x2f6df6a, /* Cannot send after transport endpoint shutdown */
UAETOOMANYREFS = 0x2f6df6b, /* Too many references: cannot splice */
UAETIMEDOUT = 0x2f6df6c, /* Connection timed out */
UAECONNREFUSED = 0x2f6df6d, /* Connection refused */
UAEHOSTDOWN = 0x2f6df6e, /* Host is down */
UAEHOSTUNREACH = 0x2f6df6f, /* No route to host */
UAEALREADY = 0x2f6df70, /* Operation already in progress */
UAEINPROGRESS = 0x2f6df71, /* Operation now in progress */
UAESTALE = 0x2f6df72, /* Stale NFS file handle */
UAEUCLEAN = 0x2f6df73, /* Structure needs cleaning */
UAENOTNAM = 0x2f6df74, /* Not a XENIX named type file */
UAENAVAIL = 0x2f6df75, /* No XENIX semaphores available */
UAEISNAM = 0x2f6df76, /* Is a named type file */
UAEREMOTEIO = 0x2f6df77, /* Remote I/O error */
UAEDQUOT = 0x2f6df78, /* Quota exceeded */
UAENOMEDIUM = 0x2f6df79, /* No medium found */
UAEMEDIUMTYPE = 0x2f6df7a, /* Wrong medium type */
};
...@@ -184,7 +184,7 @@ void afs_put_call(struct afs_call *call) ...@@ -184,7 +184,7 @@ void afs_put_call(struct afs_call *call)
if (call->type->destructor) if (call->type->destructor)
call->type->destructor(call); call->type->destructor(call);
afs_put_server(call->net, call->server); afs_put_server(call->net, call->server, afs_server_trace_put_call);
afs_put_cb_interest(call->net, call->cbi); afs_put_cb_interest(call->net, call->cbi);
afs_put_addrlist(call->alist); afs_put_addrlist(call->alist);
kfree(call->request); kfree(call->request);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */ static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */
static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */ static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */
static atomic_t afs_server_debug_id;
static void afs_inc_servers_outstanding(struct afs_net *net) static void afs_inc_servers_outstanding(struct afs_net *net)
{ {
...@@ -47,7 +48,7 @@ struct afs_server *afs_find_server(struct afs_net *net, ...@@ -47,7 +48,7 @@ struct afs_server *afs_find_server(struct afs_net *net,
do { do {
if (server) if (server)
afs_put_server(net, server); afs_put_server(net, server, afs_server_trace_put_find_rsq);
server = NULL; server = NULL;
read_seqbegin_or_lock(&net->fs_addr_lock, &seq); read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
...@@ -112,7 +113,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu ...@@ -112,7 +113,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu
* changes. * changes.
*/ */
if (server) if (server)
afs_put_server(net, server); afs_put_server(net, server, afs_server_trace_put_uuid_rsq);
server = NULL; server = NULL;
read_seqbegin_or_lock(&net->fs_lock, &seq); read_seqbegin_or_lock(&net->fs_lock, &seq);
...@@ -127,7 +128,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu ...@@ -127,7 +128,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu
} else if (diff > 0) { } else if (diff > 0) {
p = p->rb_right; p = p->rb_right;
} else { } else {
afs_get_server(server); afs_get_server(server, afs_server_trace_get_by_uuid);
break; break;
} }
...@@ -198,7 +199,7 @@ static struct afs_server *afs_install_server(struct afs_net *net, ...@@ -198,7 +199,7 @@ static struct afs_server *afs_install_server(struct afs_net *net,
ret = 0; ret = 0;
exists: exists:
afs_get_server(server); afs_get_server(server, afs_server_trace_get_install);
write_sequnlock(&net->fs_lock); write_sequnlock(&net->fs_lock);
return server; return server;
} }
...@@ -219,6 +220,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net, ...@@ -219,6 +220,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
goto enomem; goto enomem;
atomic_set(&server->usage, 1); atomic_set(&server->usage, 1);
server->debug_id = atomic_inc_return(&afs_server_debug_id);
RCU_INIT_POINTER(server->addresses, alist); RCU_INIT_POINTER(server->addresses, alist);
server->addr_version = alist->version; server->addr_version = alist->version;
server->uuid = *uuid; server->uuid = *uuid;
...@@ -230,6 +232,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net, ...@@ -230,6 +232,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
spin_lock_init(&server->probe_lock); spin_lock_init(&server->probe_lock);
afs_inc_servers_outstanding(net); afs_inc_servers_outstanding(net);
trace_afs_server(server, 1, afs_server_trace_alloc);
_leave(" = %p", server); _leave(" = %p", server);
return server; return server;
...@@ -324,10 +327,23 @@ void afs_servers_timer(struct timer_list *timer) ...@@ -324,10 +327,23 @@ void afs_servers_timer(struct timer_list *timer)
afs_dec_servers_outstanding(net); afs_dec_servers_outstanding(net);
} }
/*
* Get a reference on a server object.
*/
struct afs_server *afs_get_server(struct afs_server *server,
enum afs_server_trace reason)
{
unsigned int u = atomic_inc_return(&server->usage);
trace_afs_server(server, u, reason);
return server;
}
/* /*
* Release a reference on a server record. * Release a reference on a server record.
*/ */
void afs_put_server(struct afs_net *net, struct afs_server *server) void afs_put_server(struct afs_net *net, struct afs_server *server,
enum afs_server_trace reason)
{ {
unsigned int usage; unsigned int usage;
...@@ -338,7 +354,7 @@ void afs_put_server(struct afs_net *net, struct afs_server *server) ...@@ -338,7 +354,7 @@ void afs_put_server(struct afs_net *net, struct afs_server *server)
usage = atomic_dec_return(&server->usage); usage = atomic_dec_return(&server->usage);
_enter("{%u}", usage); trace_afs_server(server, usage, reason);
if (likely(usage > 0)) if (likely(usage > 0))
return; return;
...@@ -350,6 +366,8 @@ static void afs_server_rcu(struct rcu_head *rcu) ...@@ -350,6 +366,8 @@ static void afs_server_rcu(struct rcu_head *rcu)
{ {
struct afs_server *server = container_of(rcu, struct afs_server, rcu); struct afs_server *server = container_of(rcu, struct afs_server, rcu);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_free);
afs_put_addrlist(rcu_access_pointer(server->addresses)); afs_put_addrlist(rcu_access_pointer(server->addresses));
kfree(server); kfree(server);
} }
...@@ -365,7 +383,9 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) ...@@ -365,7 +383,9 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
.index = alist->preferred, .index = alist->preferred,
.error = 0, .error = 0,
}; };
_enter("%p", server);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_give_up_cb);
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
afs_fs_give_up_all_callbacks(net, server, &ac, NULL); afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
...@@ -373,6 +393,8 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) ...@@ -373,6 +393,8 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
wait_var_event(&server->probe_outstanding, wait_var_event(&server->probe_outstanding,
atomic_read(&server->probe_outstanding) == 0); atomic_read(&server->probe_outstanding) == 0);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_destroy);
call_rcu(&server->rcu, afs_server_rcu); call_rcu(&server->rcu, afs_server_rcu);
afs_dec_servers_outstanding(net); afs_dec_servers_outstanding(net);
} }
...@@ -392,6 +414,7 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list) ...@@ -392,6 +414,7 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
write_seqlock(&net->fs_lock); write_seqlock(&net->fs_lock);
usage = 1; usage = 1;
deleted = atomic_try_cmpxchg(&server->usage, &usage, 0); deleted = atomic_try_cmpxchg(&server->usage, &usage, 0);
trace_afs_server(server, usage, afs_server_trace_gc);
if (deleted) { if (deleted) {
rb_erase(&server->uuid_rb, &net->fs_servers); rb_erase(&server->uuid_rb, &net->fs_servers);
hlist_del_rcu(&server->proc_link); hlist_del_rcu(&server->proc_link);
...@@ -514,6 +537,8 @@ static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct a ...@@ -514,6 +537,8 @@ static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct a
_enter(""); _enter("");
trace_afs_server(server, atomic_read(&server->usage), afs_server_trace_update);
alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key, alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key,
&server->uuid); &server->uuid);
if (IS_ERR(alist)) { if (IS_ERR(alist)) {
......
...@@ -16,7 +16,8 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist) ...@@ -16,7 +16,8 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
if (slist && refcount_dec_and_test(&slist->usage)) { if (slist && refcount_dec_and_test(&slist->usage)) {
for (i = 0; i < slist->nr_servers; i++) { for (i = 0; i < slist->nr_servers; i++) {
afs_put_cb_interest(net, slist->servers[i].cb_interest); afs_put_cb_interest(net, slist->servers[i].cb_interest);
afs_put_server(net, slist->servers[i].server); afs_put_server(net, slist->servers[i].server,
afs_server_trace_put_slist);
} }
kfree(slist); kfree(slist);
} }
...@@ -67,7 +68,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, ...@@ -67,7 +68,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
break; break;
if (j < slist->nr_servers) { if (j < slist->nr_servers) {
if (slist->servers[j].server == server) { if (slist->servers[j].server == server) {
afs_put_server(cell->net, server); afs_put_server(cell->net, server,
afs_server_trace_put_slist_isort);
continue; continue;
} }
......
...@@ -44,8 +44,7 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key, ...@@ -44,8 +44,7 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
return 0; return 0;
} }
req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), req = kzalloc(struct_size(req, array, 1), GFP_KERNEL);
GFP_KERNEL);
if (!req) if (!req)
return -ENOMEM; return -ENOMEM;
......
...@@ -27,6 +27,26 @@ enum afs_call_trace { ...@@ -27,6 +27,26 @@ enum afs_call_trace {
afs_call_trace_work, afs_call_trace_work,
}; };
enum afs_server_trace {
afs_server_trace_alloc,
afs_server_trace_callback,
afs_server_trace_destroy,
afs_server_trace_free,
afs_server_trace_gc,
afs_server_trace_get_by_uuid,
afs_server_trace_get_caps,
afs_server_trace_get_install,
afs_server_trace_get_new_cbi,
afs_server_trace_give_up_cb,
afs_server_trace_put_call,
afs_server_trace_put_cbi,
afs_server_trace_put_find_rsq,
afs_server_trace_put_slist,
afs_server_trace_put_slist_isort,
afs_server_trace_put_uuid_rsq,
afs_server_trace_update,
};
enum afs_fs_operation { enum afs_fs_operation {
afs_FS_FetchData = 130, /* AFS Fetch file data */ afs_FS_FetchData = 130, /* AFS Fetch file data */
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */ afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
...@@ -191,6 +211,17 @@ enum afs_flock_operation { ...@@ -191,6 +211,17 @@ enum afs_flock_operation {
afs_flock_op_wake, afs_flock_op_wake,
}; };
enum afs_cb_break_reason {
afs_cb_break_no_break,
afs_cb_break_for_callback,
afs_cb_break_for_deleted,
afs_cb_break_for_lapsed,
afs_cb_break_for_unlink,
afs_cb_break_for_vsbreak,
afs_cb_break_for_volume_callback,
afs_cb_break_for_zap,
};
#endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */ #endif /* end __AFS_DECLARE_TRACE_ENUMS_ONCE_ONLY */
/* /*
...@@ -204,6 +235,25 @@ enum afs_flock_operation { ...@@ -204,6 +235,25 @@ enum afs_flock_operation {
EM(afs_call_trace_wake, "WAKE ") \ EM(afs_call_trace_wake, "WAKE ") \
E_(afs_call_trace_work, "WORK ") E_(afs_call_trace_work, "WORK ")
#define afs_server_traces \
EM(afs_server_trace_alloc, "ALLOC ") \
EM(afs_server_trace_callback, "CALLBACK ") \
EM(afs_server_trace_destroy, "DESTROY ") \
EM(afs_server_trace_free, "FREE ") \
EM(afs_server_trace_gc, "GC ") \
EM(afs_server_trace_get_by_uuid, "GET uuid ") \
EM(afs_server_trace_get_caps, "GET caps ") \
EM(afs_server_trace_get_install, "GET inst ") \
EM(afs_server_trace_get_new_cbi, "GET cbi ") \
EM(afs_server_trace_give_up_cb, "giveup-cb") \
EM(afs_server_trace_put_call, "PUT call ") \
EM(afs_server_trace_put_cbi, "PUT cbi ") \
EM(afs_server_trace_put_find_rsq, "PUT f-rsq") \
EM(afs_server_trace_put_slist, "PUT slist") \
EM(afs_server_trace_put_slist_isort, "PUT isort") \
EM(afs_server_trace_put_uuid_rsq, "PUT u-req") \
E_(afs_server_trace_update, "UPDATE")
#define afs_fs_operations \ #define afs_fs_operations \
EM(afs_FS_FetchData, "FS.FetchData") \ EM(afs_FS_FetchData, "FS.FetchData") \
EM(afs_FS_FetchStatus, "FS.FetchStatus") \ EM(afs_FS_FetchStatus, "FS.FetchStatus") \
...@@ -370,6 +420,16 @@ enum afs_flock_operation { ...@@ -370,6 +420,16 @@ enum afs_flock_operation {
EM(afs_flock_op_unlock, "UNLOCK ") \ EM(afs_flock_op_unlock, "UNLOCK ") \
E_(afs_flock_op_wake, "WAKE ") E_(afs_flock_op_wake, "WAKE ")
#define afs_cb_break_reasons \
EM(afs_cb_break_no_break, "no-break") \
EM(afs_cb_break_for_callback, "break-cb") \
EM(afs_cb_break_for_deleted, "break-del") \
EM(afs_cb_break_for_lapsed, "break-lapsed") \
EM(afs_cb_break_for_unlink, "break-unlink") \
EM(afs_cb_break_for_vsbreak, "break-vs") \
EM(afs_cb_break_for_volume_callback, "break-v-cb") \
E_(afs_cb_break_for_zap, "break-zap")
/* /*
* Export enum symbols via userspace. * Export enum symbols via userspace.
*/ */
...@@ -379,6 +439,7 @@ enum afs_flock_operation { ...@@ -379,6 +439,7 @@ enum afs_flock_operation {
#define E_(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a);
afs_call_traces; afs_call_traces;
afs_server_traces;
afs_fs_operations; afs_fs_operations;
afs_vl_operations; afs_vl_operations;
afs_edit_dir_ops; afs_edit_dir_ops;
...@@ -388,6 +449,7 @@ afs_io_errors; ...@@ -388,6 +449,7 @@ afs_io_errors;
afs_file_errors; afs_file_errors;
afs_flock_types; afs_flock_types;
afs_flock_operations; afs_flock_operations;
afs_cb_break_reasons;
/* /*
* Now redefine the EM() and E_() macros to map the enums to the strings that * Now redefine the EM() and E_() macros to map the enums to the strings that
...@@ -1167,6 +1229,76 @@ TRACE_EVENT(afs_get_tree, ...@@ -1167,6 +1229,76 @@ TRACE_EVENT(afs_get_tree,
__entry->cell, __entry->volume, __entry->vid) __entry->cell, __entry->volume, __entry->vid)
); );
TRACE_EVENT(afs_cb_break,
TP_PROTO(struct afs_fid *fid, unsigned int cb_break,
enum afs_cb_break_reason reason, bool skipped),
TP_ARGS(fid, cb_break, reason, skipped),
TP_STRUCT__entry(
__field_struct(struct afs_fid, fid )
__field(unsigned int, cb_break )
__field(enum afs_cb_break_reason, reason )
__field(bool, skipped )
),
TP_fast_assign(
__entry->fid = *fid;
__entry->cb_break = cb_break;
__entry->reason = reason;
__entry->skipped = skipped;
),
TP_printk("%llx:%llx:%x b=%x s=%u %s",
__entry->fid.vid, __entry->fid.vnode, __entry->fid.unique,
__entry->cb_break,
__entry->skipped,
__print_symbolic(__entry->reason, afs_cb_break_reasons))
);
TRACE_EVENT(afs_cb_miss,
TP_PROTO(struct afs_fid *fid, enum afs_cb_break_reason reason),
TP_ARGS(fid, reason),
TP_STRUCT__entry(
__field_struct(struct afs_fid, fid )
__field(enum afs_cb_break_reason, reason )
),
TP_fast_assign(
__entry->fid = *fid;
__entry->reason = reason;
),
TP_printk(" %llx:%llx:%x %s",
__entry->fid.vid, __entry->fid.vnode, __entry->fid.unique,
__print_symbolic(__entry->reason, afs_cb_break_reasons))
);
TRACE_EVENT(afs_server,
TP_PROTO(struct afs_server *server, int usage, enum afs_server_trace reason),
TP_ARGS(server, usage, reason),
TP_STRUCT__entry(
__field(unsigned int, server )
__field(int, usage )
__field(int, reason )
),
TP_fast_assign(
__entry->server = server->debug_id;
__entry->usage = usage;
__entry->reason = reason;
),
TP_printk("s=%08x %s u=%d",
__entry->server,
__print_symbolic(__entry->reason, afs_server_traces),
__entry->usage)
);
#endif /* _TRACE_AFS_H */ #endif /* _TRACE_AFS_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment