2007-04-27 02:49:28 +04:00
/* /proc interface for AFS
2005-04-17 02:20:36 +04:00
*
* 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 .
*/
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
they don't need sched.h
b) sched.h stops being dependency for significant number of files:
on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
after patch it's only 3744 (-8.3%).
Cross-compile tested on
all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
alpha alpha-up
arm
i386 i386-up i386-defconfig i386-allnoconfig
ia64 ia64-up
m68k
mips
parisc parisc-up
powerpc powerpc-up
s390 s390-up
sparc sparc-up
sparc64 sparc64-up
um-x86_64
x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-21 01:22:52 +04:00
# include <linux/sched.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
# include "internal.h"
static struct proc_dir_entry * proc_afs ;
static int afs_proc_cells_open ( struct inode * inode , struct file * file ) ;
static void * afs_proc_cells_start ( struct seq_file * p , loff_t * pos ) ;
static void * afs_proc_cells_next ( struct seq_file * p , void * v , loff_t * pos ) ;
static void afs_proc_cells_stop ( struct seq_file * p , void * v ) ;
static int afs_proc_cells_show ( struct seq_file * m , void * v ) ;
static ssize_t afs_proc_cells_write ( struct file * file , const char __user * buf ,
size_t size , loff_t * _pos ) ;
2009-09-23 03:43:43 +04:00
static const struct seq_operations afs_proc_cells_ops = {
2005-04-17 02:20:36 +04:00
. start = afs_proc_cells_start ,
. next = afs_proc_cells_next ,
. stop = afs_proc_cells_stop ,
. show = afs_proc_cells_show ,
} ;
2006-03-28 13:56:42 +04:00
static const struct file_operations afs_proc_cells_fops = {
2005-04-17 02:20:36 +04:00
. open = afs_proc_cells_open ,
. read = seq_read ,
. write = afs_proc_cells_write ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
static ssize_t afs_proc_rootcell_read ( struct file * file , char __user * buf ,
size_t size , loff_t * _pos ) ;
static ssize_t afs_proc_rootcell_write ( struct file * file ,
const char __user * buf ,
size_t size , loff_t * _pos ) ;
2006-03-28 13:56:42 +04:00
static const struct file_operations afs_proc_rootcell_fops = {
2005-04-17 02:20:36 +04:00
. read = afs_proc_rootcell_read ,
. write = afs_proc_rootcell_write ,
. llseek = no_llseek ,
} ;
static int afs_proc_cell_volumes_open ( struct inode * inode , struct file * file ) ;
static void * afs_proc_cell_volumes_start ( struct seq_file * p , loff_t * pos ) ;
static void * afs_proc_cell_volumes_next ( struct seq_file * p , void * v ,
loff_t * pos ) ;
static void afs_proc_cell_volumes_stop ( struct seq_file * p , void * v ) ;
static int afs_proc_cell_volumes_show ( struct seq_file * m , void * v ) ;
2009-09-23 03:43:43 +04:00
static const struct seq_operations afs_proc_cell_volumes_ops = {
2005-04-17 02:20:36 +04:00
. start = afs_proc_cell_volumes_start ,
. next = afs_proc_cell_volumes_next ,
. stop = afs_proc_cell_volumes_stop ,
. show = afs_proc_cell_volumes_show ,
} ;
2006-03-28 13:56:42 +04:00
static const struct file_operations afs_proc_cell_volumes_fops = {
2005-04-17 02:20:36 +04:00
. open = afs_proc_cell_volumes_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2013-11-22 10:53:47 +04:00
. release = seq_release ,
2005-04-17 02:20:36 +04:00
} ;
static int afs_proc_cell_vlservers_open ( struct inode * inode ,
struct file * file ) ;
static void * afs_proc_cell_vlservers_start ( struct seq_file * p , loff_t * pos ) ;
static void * afs_proc_cell_vlservers_next ( struct seq_file * p , void * v ,
loff_t * pos ) ;
static void afs_proc_cell_vlservers_stop ( struct seq_file * p , void * v ) ;
static int afs_proc_cell_vlservers_show ( struct seq_file * m , void * v ) ;
2009-09-23 03:43:43 +04:00
static const struct seq_operations afs_proc_cell_vlservers_ops = {
2005-04-17 02:20:36 +04:00
. start = afs_proc_cell_vlservers_start ,
. next = afs_proc_cell_vlservers_next ,
. stop = afs_proc_cell_vlservers_stop ,
. show = afs_proc_cell_vlservers_show ,
} ;
2006-03-28 13:56:42 +04:00
static const struct file_operations afs_proc_cell_vlservers_fops = {
2005-04-17 02:20:36 +04:00
. open = afs_proc_cell_vlservers_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2013-11-22 10:53:47 +04:00
. release = seq_release ,
2005-04-17 02:20:36 +04:00
} ;
static int afs_proc_cell_servers_open ( struct inode * inode , struct file * file ) ;
static void * afs_proc_cell_servers_start ( struct seq_file * p , loff_t * pos ) ;
static void * afs_proc_cell_servers_next ( struct seq_file * p , void * v ,
loff_t * pos ) ;
static void afs_proc_cell_servers_stop ( struct seq_file * p , void * v ) ;
static int afs_proc_cell_servers_show ( struct seq_file * m , void * v ) ;
2009-09-23 03:43:43 +04:00
static const struct seq_operations afs_proc_cell_servers_ops = {
2005-04-17 02:20:36 +04:00
. start = afs_proc_cell_servers_start ,
. next = afs_proc_cell_servers_next ,
. stop = afs_proc_cell_servers_stop ,
. show = afs_proc_cell_servers_show ,
} ;
2006-03-28 13:56:42 +04:00
static const struct file_operations afs_proc_cell_servers_fops = {
2005-04-17 02:20:36 +04:00
. open = afs_proc_cell_servers_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2013-11-22 10:53:47 +04:00
. release = seq_release ,
2005-04-17 02:20:36 +04:00
} ;
/*
* initialise the / proc / fs / afs / directory
*/
int afs_proc_init ( void )
{
_enter ( " " ) ;
proc_afs = proc_mkdir ( " fs/afs " , NULL ) ;
if ( ! proc_afs )
2007-04-27 02:49:28 +04:00
goto error_dir ;
2005-04-17 02:20:36 +04:00
2014-01-29 00:26:44 +04:00
if ( ! proc_create ( " cells " , 0644 , proc_afs , & afs_proc_cells_fops ) | |
! proc_create ( " rootcell " , 0644 , proc_afs , & afs_proc_rootcell_fops ) )
2013-11-22 10:53:47 +04:00
goto error_tree ;
2005-04-17 02:20:36 +04:00
_leave ( " = 0 " ) ;
return 0 ;
2013-11-22 10:53:47 +04:00
error_tree :
remove_proc_subtree ( " fs/afs " , NULL ) ;
2007-04-27 02:49:28 +04:00
error_dir :
2005-04-17 02:20:36 +04:00
_leave ( " = -ENOMEM " ) ;
return - ENOMEM ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up the / proc / fs / afs / directory
*/
void afs_proc_cleanup ( void )
{
2013-11-22 10:53:47 +04:00
remove_proc_subtree ( " fs/afs " , NULL ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* open " /proc/fs/afs/cells " which provides a summary of extant cells
*/
static int afs_proc_cells_open ( struct inode * inode , struct file * file )
{
struct seq_file * m ;
int ret ;
ret = seq_open ( file , & afs_proc_cells_ops ) ;
if ( ret < 0 )
return ret ;
m = file - > private_data ;
2013-04-01 02:16:14 +04:00
m - > private = PDE_DATA ( inode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* set up the iterator to start reading from the cells list and return the
* first item
*/
static void * afs_proc_cells_start ( struct seq_file * m , loff_t * _pos )
{
/* lock the list against modification */
down_read ( & afs_proc_cells_sem ) ;
2007-07-16 10:39:52 +04:00
return seq_list_start_head ( & afs_proc_cells , * _pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* move to next cell in cells list
*/
static void * afs_proc_cells_next ( struct seq_file * p , void * v , loff_t * pos )
{
2007-07-16 10:39:52 +04:00
return seq_list_next ( v , & afs_proc_cells , pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up after reading from the cells list
*/
static void afs_proc_cells_stop ( struct seq_file * p , void * v )
{
up_read ( & afs_proc_cells_sem ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* display a header line followed by a load of cell lines
*/
static int afs_proc_cells_show ( struct seq_file * m , void * v )
{
struct afs_cell * cell = list_entry ( v , struct afs_cell , proc_link ) ;
2007-07-16 10:39:52 +04:00
if ( v = = & afs_proc_cells ) {
2007-04-27 02:49:28 +04:00
/* display header on line 1 */
2005-04-17 02:20:36 +04:00
seq_puts ( m , " USE NAME \n " ) ;
return 0 ;
}
/* display one cell per line on subsequent lines */
2007-04-27 02:49:28 +04:00
seq_printf ( m , " %3d %s \n " ,
atomic_read ( & cell - > usage ) , cell - > name ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* handle writes to / proc / fs / afs / cells
* - to add cells : echo " add <cellname> <IP>[:<IP>][:<IP>] "
*/
static ssize_t afs_proc_cells_write ( struct file * file , const char __user * buf ,
size_t size , loff_t * _pos )
{
char * kbuf , * name , * args ;
int ret ;
/* start by dragging the command into memory */
if ( size < = 1 | | size > = PAGE_SIZE )
return - EINVAL ;
2015-12-24 08:06:05 +03:00
kbuf = memdup_user_nul ( buf , size ) ;
if ( IS_ERR ( kbuf ) )
return PTR_ERR ( kbuf ) ;
2005-04-17 02:20:36 +04:00
/* trim to first NL */
name = memchr ( kbuf , ' \n ' , size ) ;
if ( name )
* name = 0 ;
/* split into command, name and argslist */
name = strchr ( kbuf , ' ' ) ;
if ( ! name )
goto inval ;
do {
* name + + = 0 ;
} while ( * name = = ' ' ) ;
if ( ! * name )
goto inval ;
args = strchr ( name , ' ' ) ;
if ( ! args )
goto inval ;
do {
* args + + = 0 ;
} while ( * args = = ' ' ) ;
if ( ! * args )
goto inval ;
/* determine command to perform */
_debug ( " cmd=%s name=%s args=%s " , kbuf , name , args ) ;
if ( strcmp ( kbuf , " add " ) = = 0 ) {
struct afs_cell * cell ;
2007-04-27 02:55:03 +04:00
2010-08-11 12:38:04 +04:00
cell = afs_cell_create ( name , strlen ( name ) , args , false ) ;
2007-04-27 02:55:03 +04:00
if ( IS_ERR ( cell ) ) {
ret = PTR_ERR ( cell ) ;
2005-04-17 02:20:36 +04:00
goto done ;
2007-04-27 02:55:03 +04:00
}
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
afs_put_cell ( cell ) ;
2005-04-17 02:20:36 +04:00
printk ( " kAFS: Added new cell '%s' \n " , name ) ;
2007-04-27 02:49:28 +04:00
} else {
2005-04-17 02:20:36 +04:00
goto inval ;
}
ret = size ;
2007-04-27 02:49:28 +04:00
done :
2005-04-17 02:20:36 +04:00
kfree ( kbuf ) ;
_leave ( " = %d " , ret ) ;
return ret ;
2007-04-27 02:49:28 +04:00
inval :
2005-04-17 02:20:36 +04:00
ret = - EINVAL ;
printk ( " kAFS: Invalid Command on /proc/fs/afs/cells file \n " ) ;
goto done ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
static ssize_t afs_proc_rootcell_read ( struct file * file , char __user * buf ,
size_t size , loff_t * _pos )
{
return 0 ;
}
/*
* handle writes to / proc / fs / afs / rootcell
* - to initialize rootcell : echo " cell.name:192.168.231.14 "
*/
static ssize_t afs_proc_rootcell_write ( struct file * file ,
const char __user * buf ,
size_t size , loff_t * _pos )
{
char * kbuf , * s ;
int ret ;
/* start by dragging the command into memory */
if ( size < = 1 | | size > = PAGE_SIZE )
return - EINVAL ;
2015-12-24 08:06:05 +03:00
kbuf = memdup_user_nul ( buf , size ) ;
if ( IS_ERR ( kbuf ) )
return PTR_ERR ( kbuf ) ;
2005-04-17 02:20:36 +04:00
/* trim to first NL */
s = memchr ( kbuf , ' \n ' , size ) ;
if ( s )
* s = 0 ;
/* determine command to perform */
_debug ( " rootcell=%s " , kbuf ) ;
ret = afs_cell_init ( kbuf ) ;
if ( ret > = 0 )
ret = size ; /* consume everything, always */
kfree ( kbuf ) ;
_leave ( " = %d " , ret ) ;
return ret ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* initialise / proc / fs / afs / < cell > /
*/
int afs_proc_cell_setup ( struct afs_cell * cell )
{
2013-11-22 10:53:47 +04:00
struct proc_dir_entry * dir ;
2005-04-17 02:20:36 +04:00
_enter ( " %p{%s} " , cell , cell - > name ) ;
2013-11-22 10:53:47 +04:00
dir = proc_mkdir ( cell - > name , proc_afs ) ;
if ( ! dir )
2007-04-27 02:49:28 +04:00
goto error_dir ;
2005-04-17 02:20:36 +04:00
2013-11-22 10:53:47 +04:00
if ( ! proc_create_data ( " servers " , 0 , dir ,
& afs_proc_cell_servers_fops , cell ) | |
! proc_create_data ( " vlservers " , 0 , dir ,
& afs_proc_cell_vlservers_fops , cell ) | |
! proc_create_data ( " volumes " , 0 , dir ,
& afs_proc_cell_volumes_fops , cell ) )
goto error_tree ;
2005-04-17 02:20:36 +04:00
_leave ( " = 0 " ) ;
return 0 ;
2013-11-22 10:53:47 +04:00
error_tree :
remove_proc_subtree ( cell - > name , proc_afs ) ;
2007-04-27 02:49:28 +04:00
error_dir :
2005-04-17 02:20:36 +04:00
_leave ( " = -ENOMEM " ) ;
return - ENOMEM ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* remove / proc / fs / afs / < cell > /
*/
void afs_proc_cell_remove ( struct afs_cell * cell )
{
_enter ( " " ) ;
2013-11-22 10:53:47 +04:00
remove_proc_subtree ( cell - > name , proc_afs ) ;
2005-04-17 02:20:36 +04:00
_leave ( " " ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* open " /proc/fs/afs/<cell>/volumes " which provides a summary of extant cells
*/
static int afs_proc_cell_volumes_open ( struct inode * inode , struct file * file )
{
struct afs_cell * cell ;
struct seq_file * m ;
int ret ;
2013-04-01 02:16:14 +04:00
cell = PDE_DATA ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( ! cell )
return - ENOENT ;
ret = seq_open ( file , & afs_proc_cell_volumes_ops ) ;
if ( ret < 0 )
return ret ;
m = file - > private_data ;
m - > private = cell ;
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* set up the iterator to start reading from the cells list and return the
* first item
*/
static void * afs_proc_cell_volumes_start ( struct seq_file * m , loff_t * _pos )
{
struct afs_cell * cell = m - > private ;
_enter ( " cell=%p pos=%Ld " , cell , * _pos ) ;
/* lock the list against modification */
down_read ( & cell - > vl_sem ) ;
2007-07-16 10:39:52 +04:00
return seq_list_start_head ( & cell - > vl_list , * _pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* move to next cell in cells list
*/
static void * afs_proc_cell_volumes_next ( struct seq_file * p , void * v ,
loff_t * _pos )
{
struct afs_cell * cell = p - > private ;
_enter ( " cell=%p pos=%Ld " , cell , * _pos ) ;
2007-07-16 10:39:52 +04:00
return seq_list_next ( v , & cell - > vl_list , _pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up after reading from the cells list
*/
static void afs_proc_cell_volumes_stop ( struct seq_file * p , void * v )
{
struct afs_cell * cell = p - > private ;
up_read ( & cell - > vl_sem ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
2007-10-17 10:26:41 +04:00
static const char afs_vlocation_states [ ] [ 4 ] = {
2007-04-27 02:55:03 +04:00
[ AFS_VL_NEW ] = " New " ,
[ AFS_VL_CREATING ] = " Crt " ,
[ AFS_VL_VALID ] = " Val " ,
[ AFS_VL_NO_VOLUME ] = " NoV " ,
[ AFS_VL_UPDATING ] = " Upd " ,
[ AFS_VL_VOLUME_DELETED ] = " Del " ,
[ AFS_VL_UNCERTAIN ] = " Unc " ,
} ;
2005-04-17 02:20:36 +04:00
/*
* display a header line followed by a load of volume lines
*/
static int afs_proc_cell_volumes_show ( struct seq_file * m , void * v )
{
2007-07-16 10:39:52 +04:00
struct afs_cell * cell = m - > private ;
2005-04-17 02:20:36 +04:00
struct afs_vlocation * vlocation =
list_entry ( v , struct afs_vlocation , link ) ;
/* display header on line 1 */
2007-07-16 10:39:52 +04:00
if ( v = = & cell - > vl_list ) {
2007-04-27 02:55:03 +04:00
seq_puts ( m , " USE STT VLID[0] VLID[1] VLID[2] NAME \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/* display one cell per line on subsequent lines */
2007-04-27 02:55:03 +04:00
seq_printf ( m , " %3d %s %08x %08x %08x %s \n " ,
2005-04-17 02:20:36 +04:00
atomic_read ( & vlocation - > usage ) ,
2007-04-27 02:55:03 +04:00
afs_vlocation_states [ vlocation - > state ] ,
2005-04-17 02:20:36 +04:00
vlocation - > vldb . vid [ 0 ] ,
vlocation - > vldb . vid [ 1 ] ,
vlocation - > vldb . vid [ 2 ] ,
2007-04-27 02:49:28 +04:00
vlocation - > vldb . name ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* open " /proc/fs/afs/<cell>/vlservers " which provides a list of volume
* location server
*/
static int afs_proc_cell_vlservers_open ( struct inode * inode , struct file * file )
{
struct afs_cell * cell ;
struct seq_file * m ;
int ret ;
2013-04-01 02:16:14 +04:00
cell = PDE_DATA ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( ! cell )
return - ENOENT ;
2007-04-27 02:55:03 +04:00
ret = seq_open ( file , & afs_proc_cell_vlservers_ops ) ;
2005-04-17 02:20:36 +04:00
if ( ret < 0 )
return ret ;
m = file - > private_data ;
m - > private = cell ;
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* set up the iterator to start reading from the cells list and return the
* first item
*/
static void * afs_proc_cell_vlservers_start ( struct seq_file * m , loff_t * _pos )
{
struct afs_cell * cell = m - > private ;
loff_t pos = * _pos ;
_enter ( " cell=%p pos=%Ld " , cell , * _pos ) ;
/* lock the list against modification */
down_read ( & cell - > vl_sem ) ;
/* allow for the header line */
if ( ! pos )
return ( void * ) 1 ;
pos - - ;
if ( pos > = cell - > vl_naddrs )
return NULL ;
return & cell - > vl_addrs [ pos ] ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* move to next cell in cells list
*/
static void * afs_proc_cell_vlservers_next ( struct seq_file * p , void * v ,
loff_t * _pos )
{
struct afs_cell * cell = p - > private ;
loff_t pos ;
_enter ( " cell=%p{nad=%u} pos=%Ld " , cell , cell - > vl_naddrs , * _pos ) ;
pos = * _pos ;
( * _pos ) + + ;
if ( pos > = cell - > vl_naddrs )
return NULL ;
return & cell - > vl_addrs [ pos ] ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up after reading from the cells list
*/
static void afs_proc_cell_vlservers_stop ( struct seq_file * p , void * v )
{
struct afs_cell * cell = p - > private ;
up_read ( & cell - > vl_sem ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* display a header line followed by a load of volume lines
*/
static int afs_proc_cell_vlservers_show ( struct seq_file * m , void * v )
{
struct in_addr * addr = v ;
/* display header on line 1 */
if ( v = = ( struct in_addr * ) 1 ) {
seq_puts ( m , " ADDRESS \n " ) ;
return 0 ;
}
/* display one cell per line on subsequent lines */
2008-10-31 10:56:28 +03:00
seq_printf ( m , " %pI4 \n " , & addr - > s_addr ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* open " /proc/fs/afs/<cell>/servers " which provides a summary of active
* servers
*/
static int afs_proc_cell_servers_open ( struct inode * inode , struct file * file )
{
struct afs_cell * cell ;
struct seq_file * m ;
int ret ;
2013-04-01 02:16:14 +04:00
cell = PDE_DATA ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( ! cell )
return - ENOENT ;
ret = seq_open ( file , & afs_proc_cell_servers_ops ) ;
if ( ret < 0 )
return ret ;
m = file - > private_data ;
m - > private = cell ;
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* set up the iterator to start reading from the cells list and return the
* first item
*/
static void * afs_proc_cell_servers_start ( struct seq_file * m , loff_t * _pos )
2007-04-27 02:55:03 +04:00
__acquires ( m - > private - > servers_lock )
2005-04-17 02:20:36 +04:00
{
struct afs_cell * cell = m - > private ;
_enter ( " cell=%p pos=%Ld " , cell , * _pos ) ;
/* lock the list against modification */
2007-04-27 02:55:03 +04:00
read_lock ( & cell - > servers_lock ) ;
2007-07-16 10:39:52 +04:00
return seq_list_start_head ( & cell - > servers , * _pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* move to next cell in cells list
*/
static void * afs_proc_cell_servers_next ( struct seq_file * p , void * v ,
loff_t * _pos )
{
struct afs_cell * cell = p - > private ;
_enter ( " cell=%p pos=%Ld " , cell , * _pos ) ;
2007-07-16 10:39:52 +04:00
return seq_list_next ( v , & cell - > servers , _pos ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up after reading from the cells list
*/
static void afs_proc_cell_servers_stop ( struct seq_file * p , void * v )
2007-04-27 02:55:03 +04:00
__releases ( p - > private - > servers_lock )
2005-04-17 02:20:36 +04:00
{
struct afs_cell * cell = p - > private ;
2007-04-27 02:55:03 +04:00
read_unlock ( & cell - > servers_lock ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* display a header line followed by a load of volume lines
*/
static int afs_proc_cell_servers_show ( struct seq_file * m , void * v )
{
2007-07-16 10:39:52 +04:00
struct afs_cell * cell = m - > private ;
2005-04-17 02:20:36 +04:00
struct afs_server * server = list_entry ( v , struct afs_server , link ) ;
char ipaddr [ 20 ] ;
/* display header on line 1 */
2007-07-16 10:39:52 +04:00
if ( v = = & cell - > servers ) {
2005-04-17 02:20:36 +04:00
seq_puts ( m , " USE ADDR STATE \n " ) ;
return 0 ;
}
/* display one cell per line on subsequent lines */
2008-10-31 10:56:28 +03:00
sprintf ( ipaddr , " %pI4 " , & server - > addr ) ;
2005-04-17 02:20:36 +04:00
seq_printf ( m , " %3d %-15.15s %5d \n " ,
2007-04-27 02:49:28 +04:00
atomic_read ( & server - > usage ) , ipaddr , server - > fs_state ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}