00001
00012 #include <linux/proc_fs.h>
00013 #include <asm/uaccess.h>
00014
00015
00016 #include "procfs.h"
00017 #include "mountdata.h"
00018
00019
00020 #ifndef CONFIG_PROC_FS
00021 #error The module must be compiled with the /proc filesystem configured
00022 #endif
00023
00024
00025
00027 static const char * mumufs_proc_entry_point = "mumu";
00028
00030 static const char * mumufs_version = "0.1.1";
00031
00033 static struct proc_dir_entry * mumufs_main_proc_entry = NULL;
00034
00035
00036
00037 static int mumufs_read_version( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00038 static int mumufs_read_max_block_size( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00039 static int mumufs_read_entries( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00040 static int mumufs_read_max_entries( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00041 static int mumufs_read_mount_point( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00042
00043
00044 #ifdef DEBUG
00045 static int mumufs_read_debug( char * page, char ** start, off_t offset, int count, int * eof, void * data );
00046 #endif
00047
00048
00049
00050
00051
00056 int mumufs_initialise_proc_entries( void )
00057 {
00058 struct proc_dir_entry * entry;
00059 int flags;
00060
00061 mumufs_main_proc_entry = proc_mkdir( mumufs_proc_entry_point, NULL );
00062 if ( mumufs_main_proc_entry == NULL )
00063 {
00064 return -ENOMEM;
00065 }
00066
00067 flags = S_IFREG | S_IRUGO;
00068 entry = create_proc_entry( "version", flags, mumufs_main_proc_entry );
00069 entry->read_proc = mumufs_read_version;
00070
00071 return 0;
00072 }
00073
00074
00075
00080 int mumufs_remove_proc_entries( void )
00081 {
00082 remove_proc_entry( "version", mumufs_main_proc_entry );
00083 remove_proc_entry( mumufs_proc_entry_point, NULL );
00084
00085 return 0;
00086 }
00087
00088
00089
00095 int mumufs_create_mount_info( struct super_block * sb )
00096 {
00097 struct proc_dir_entry * mount_entry = NULL;
00098 struct proc_dir_entry * entry = NULL;
00099 char buffer[16];
00100
00101 if ( mumufs_main_proc_entry == NULL )
00102 {
00103 return -EINVAL;
00104 }
00105
00106 sprintf( buffer, "0x%p", sb );
00107 mount_entry = proc_mkdir( buffer, mumufs_main_proc_entry );
00108 if ( mount_entry == NULL )
00109 {
00110 return -ENOMEM;
00111 }
00112 ((struct mumu_mount_data *)(sb->s_fs_info))->parent = mount_entry;
00113
00114 entry = create_proc_entry( "maxblocksize", S_IFREG | S_IRUGO | S_IWUGO, mount_entry );
00115 if ( entry == NULL )
00116 {
00117 remove_proc_entry( buffer, mumufs_main_proc_entry );
00118 return -ENOMEM;
00119 }
00120 entry->read_proc = mumufs_read_max_block_size;
00121 entry->data = sb->s_fs_info;
00122
00123 entry = create_proc_entry( "maxentries", S_IFREG | S_IRUGO | S_IWUGO, mount_entry );
00124 if ( entry == NULL )
00125 {
00126 remove_proc_entry( "maxblocksize", mount_entry );
00127 remove_proc_entry( buffer, mumufs_main_proc_entry );
00128 return -ENOMEM;
00129 }
00130 entry->read_proc = mumufs_read_max_entries;
00131 entry->data = sb->s_fs_info;
00132
00133 entry = create_proc_entry( "entries", S_IFREG | S_IRUGO | S_IWUGO, mount_entry );
00134 if ( entry == NULL )
00135 {
00136 remove_proc_entry( "maxentries", mount_entry );
00137 remove_proc_entry( "maxblocksize", mount_entry );
00138 remove_proc_entry( buffer, mumufs_main_proc_entry );
00139 return -ENOMEM;
00140 }
00141 entry->read_proc = mumufs_read_entries;
00142 entry->data = sb->s_fs_info;
00143
00144 entry = create_proc_entry( "mountpoint", S_IFREG | S_IRUGO | S_IWUGO, mount_entry );
00145 if ( entry == NULL )
00146 {
00147 remove_proc_entry( "entries", mount_entry );
00148 remove_proc_entry( "maxentries", mount_entry );
00149 remove_proc_entry( "maxblocksize", mount_entry );
00150 remove_proc_entry( buffer, mumufs_main_proc_entry );
00151 return -ENOMEM;
00152 }
00153 entry->read_proc = mumufs_read_mount_point;
00154 entry->data = sb->s_fs_info;
00155
00156 #ifdef DEBUG
00157 entry = create_proc_entry( "debug", S_IFREG | S_IRUGO | S_IWUGO, mount_entry );
00158 if ( entry == NULL )
00159 {
00160 remove_proc_entry( "mountpoint", mount_entry );
00161 remove_proc_entry( "entries", mount_entry );
00162 remove_proc_entry( "maxentries", mount_entry );
00163 remove_proc_entry( "maxblocksize", mount_entry );
00164 remove_proc_entry( buffer, mumufs_main_proc_entry );
00165 return -ENOMEM;
00166 }
00167 entry->read_proc = mumufs_read_debug;
00168 entry->data = sb->s_fs_info;
00169 #endif
00170
00171 return 0;
00172 }
00173
00174
00180 int mumufs_remove_mount_info( struct super_block * sb )
00181 {
00182 char buffer[16];
00183
00184 if ( mumufs_main_proc_entry == NULL )
00185 {
00186 return 1;
00187 }
00188
00189 #ifdef DEBUG
00190 remove_proc_entry( "debug", ((struct mumu_mount_data *)(sb->s_fs_info))->parent );
00191 #endif
00192
00193 remove_proc_entry( "entries", ((struct mumu_mount_data *)(sb->s_fs_info))->parent );
00194 remove_proc_entry( "maxentries", ((struct mumu_mount_data *)(sb->s_fs_info))->parent );
00195 remove_proc_entry( "maxblocksize", ((struct mumu_mount_data *)(sb->s_fs_info))->parent );
00196 remove_proc_entry( "mountpoint", ((struct mumu_mount_data *)(sb->s_fs_info))->parent );
00197
00198 sprintf( buffer, "0x%p", sb );
00199 remove_proc_entry( buffer, mumufs_main_proc_entry );
00200 return 0;
00201 }
00202
00203
00214 static int mumufs_read_version( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00215 {
00216 return snprintf( page, count - 1, "%s\n", mumufs_version ) + 1;
00217 }
00218
00219
00220
00221 static int mumufs_read_max_block_size( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00222 {
00223 return snprintf( page, count - 1, "%u\n", ((struct mumu_mount_data *)data)->max_block_size ) + 1;
00224 }
00225
00226
00227
00228 static int mumufs_read_entries( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00229 {
00230 int val = atomic_read( & ((struct mumu_mount_data *)data)->number_of_entries );
00231 return snprintf( page, count - 1, "%d\n", val ) + 1;
00232 }
00233
00234
00235
00236 static int mumufs_read_max_entries( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00237 {
00238 return snprintf( page, count - 1, "%u\n", ((struct mumu_mount_data *)data)->max_entries ) + 1;
00239 }
00240
00241
00242 static int mumufs_read_mount_point( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00243 {
00244 char buf[ NAME_MAX*2 ];
00245 struct vfsmount * mount = ((struct mumu_mount_data *)data)->mount;
00246 struct path p;
00247
00248 if ( mount != NULL )
00249 {
00250
00251 p.mnt = mount->mnt_parent;
00252 p.dentry = mount->mnt_mountpoint;
00253
00254 return snprintf( page, count - 1, "%s\n", d_path( &p, buf, 512 ) ) + 1;
00255 }
00256
00257 return snprintf( page, count - 1, "Unknown\n" ) + 1;
00258 }
00259
00260
00261 #ifdef DEBUG
00262 int mumufs_read_debug( char * page, char ** start, off_t offset, int count, int * eof, void * data )
00263 {
00264 struct mumu_mount_data * d = (struct mumu_mount_data *)data;
00265 switch ( d->last_op )
00266 {
00267 case 1:
00268 return snprintf( page, count - 1,
00269 "Last operation: READ\n"
00270 "Bytes: %d\n"
00271 "Offset: %lld\n", d->last_bytes, d->last_offset ) + 1;
00272 case 2:
00273 return snprintf( page, count - 1,
00274 "Last operation: WRITE\n"
00275 "Bytes: %d\n"
00276 "Offset: %lld\n", d->last_bytes, d->last_offset ) + 1;
00277 }
00278
00279 return snprintf( page, count - 1, "Unknown last operation.\n" ) + 1;
00280 }
00281 #endif
00282
00283