Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ed8491c authored by Eric Van Hensbergen's avatar Eric Van Hensbergen Committed by Linus Torvalds
Browse files

[PATCH] v9fs: debug and support routines



This part of the patch contains debug and other misc routines.

Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 322b329a
Loading
Loading
Loading
Loading

fs/9p/debug.h

0 → 100644
+70 −0
Original line number Diff line number Diff line
/*
 *  linux/fs/9p/debug.h - V9FS Debug Definitions
 *
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#define DEBUG_ERROR		(1<<0)
#define DEBUG_CURRENT		(1<<1)
#define DEBUG_9P	        (1<<2)
#define DEBUG_VFS	        (1<<3)
#define DEBUG_CONV		(1<<4)
#define DEBUG_MUX		(1<<5)
#define DEBUG_TRANS		(1<<6)
#define DEBUG_SLABS	      	(1<<7)

#define DEBUG_DUMP_PKT		0

extern int v9fs_debug_level;

#define dprintk(level, format, arg...) \
do {  \
	if((v9fs_debug_level & level)==level) \
		printk(KERN_NOTICE "-- %s (%d): " \
		format , __FUNCTION__, current->pid , ## arg); \
} while(0)

#define eprintk(level, format, arg...) \
do { \
	printk(level "v9fs: %s (%d): " \
		format , __FUNCTION__, current->pid , ## arg); \
} while(0)

#if DEBUG_DUMP_PKT
static inline void dump_data(const unsigned char *data, unsigned int datalen)
{
	int i, j;
	int len = datalen;

	printk(KERN_DEBUG "data ");
	for (i = 0; i < len; i += 4) {
		for (j = 0; (j < 4) && (i + j < len); j++)
			printk(KERN_DEBUG "%02x", data[i + j]);
		printk(KERN_DEBUG " ");
	}
	printk(KERN_DEBUG "\n");
}
#else				/* DEBUG_DUMP_PKT */
static inline void dump_data(const unsigned char *data, unsigned int datalen)
{

}
#endif				/* DEBUG_DUMP_PKT */

fs/9p/error.c

0 → 100644
+93 −0
Original line number Diff line number Diff line
/*
 * linux/fs/9p/error.c
 *
 * Error string handling
 *
 * Plan 9 uses error strings, Unix uses error numbers.  These functions
 * try to help manage that and provide for dynamically adding error
 * mappings.
 *
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#include <linux/config.h>
#include <linux/module.h>

#include <linux/list.h>
#include <linux/jhash.h>

#include "debug.h"
#include "error.h"

/**
 * v9fs_error_init - preload
 * @errstr: error string
 *
 */

int v9fs_error_init(void)
{
	struct errormap *c;
	int bucket;

	/* initialize hash table */
	for (bucket = 0; bucket < ERRHASHSZ; bucket++)
		INIT_HLIST_HEAD(&hash_errmap[bucket]);

	/* load initial error map into hash table */
	for (c = errmap; c->name != NULL; c++) {
		bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ;
		INIT_HLIST_NODE(&c->list);
		hlist_add_head(&c->list, &hash_errmap[bucket]);
	}

	return 1;
}

/**
 * errstr2errno - convert error string to error number
 * @errstr: error string
 *
 */

int v9fs_errstr2errno(char *errstr)
{
	int errno = 0;
	struct hlist_node *p = NULL;
	struct errormap *c = NULL;
	int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ;

	hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
		if (!strcmp(c->name, errstr)) {
			errno = c->val;
			break;
		}
	}

	if (errno == 0) {
		/* TODO: if error isn't found, add it dynamically */
		printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
		       errstr);
		errno = 1;
	}

	return -errno;
}

fs/9p/error.h

0 → 100644
+181 −0
Original line number Diff line number Diff line
/*
 * linux/fs/9p/error.h
 *
 * Huge Nasty Error Table
 *
 * Plan 9 uses error strings, Unix uses error numbers.  This table tries to
 * match UNIX strings and Plan 9 strings to unix error numbers.  It is used
 * to preload the dynamic error table which can also track user-specific error
 * strings.
 *
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#include <linux/errno.h>

struct errormap {
	char *name;
	int val;

	struct hlist_node list;
};

#define ERRHASHSZ		32
static struct hlist_head hash_errmap[ERRHASHSZ];

/* FixMe - reduce to a reasonable size */
static struct errormap errmap[] = {
	{"Operation not permitted", 1},
	{"wstat prohibited", 1},
	{"No such file or directory", 2},
	{"file not found", 2},
	{"Interrupted system call", 4},
	{"Input/output error", 5},
	{"No such device or address", 6},
	{"Argument list too long", 7},
	{"Bad file descriptor", 9},
	{"Resource temporarily unavailable", 11},
	{"Cannot allocate memory", 12},
	{"Permission denied", 13},
	{"Bad address", 14},
	{"Block device required", 15},
	{"Device or resource busy", 16},
	{"File exists", 17},
	{"Invalid cross-device link", 18},
	{"No such device", 19},
	{"Not a directory", 20},
	{"Is a directory", 21},
	{"Invalid argument", 22},
	{"Too many open files in system", 23},
	{"Too many open files", 24},
	{"Text file busy", 26},
	{"File too large", 27},
	{"No space left on device", 28},
	{"Illegal seek", 29},
	{"Read-only file system", 30},
	{"Too many links", 31},
	{"Broken pipe", 32},
	{"Numerical argument out of domain", 33},
	{"Numerical result out of range", 34},
	{"Resource deadlock avoided", 35},
	{"File name too long", 36},
	{"No locks available", 37},
	{"Function not implemented", 38},
	{"Directory not empty", 39},
	{"Too many levels of symbolic links", 40},
	{"Unknown error 41", 41},
	{"No message of desired type", 42},
	{"Identifier removed", 43},
	{"File locking deadlock error", 58},
	{"No data available", 61},
	{"Machine is not on the network", 64},
	{"Package not installed", 65},
	{"Object is remote", 66},
	{"Link has been severed", 67},
	{"Communication error on send", 70},
	{"Protocol error", 71},
	{"Bad message", 74},
	{"File descriptor in bad state", 77},
	{"Streams pipe error", 86},
	{"Too many users", 87},
	{"Socket operation on non-socket", 88},
	{"Message too long", 90},
	{"Protocol not available", 92},
	{"Protocol not supported", 93},
	{"Socket type not supported", 94},
	{"Operation not supported", 95},
	{"Protocol family not supported", 96},
	{"Network is down", 100},
	{"Network is unreachable", 101},
	{"Network dropped connection on reset", 102},
	{"Software caused connection abort", 103},
	{"Connection reset by peer", 104},
	{"No buffer space available", 105},
	{"Transport endpoint is already connected", 106},
	{"Transport endpoint is not connected", 107},
	{"Cannot send after transport endpoint shutdown", 108},
	{"Connection timed out", 110},
	{"Connection refused", 111},
	{"Host is down", 112},
	{"No route to host", 113},
	{"Operation already in progress", 114},
	{"Operation now in progress", 115},
	{"Is a named type file", 120},
	{"Remote I/O error", 121},
	{"Disk quota exceeded", 122},
	{"Operation canceled", 125},
	{"Unknown error 126", 126},
	{"Unknown error 127", 127},
/* errors from fossil, vacfs, and u9fs */
	{"fid unknown or out of range", EBADF},
	{"permission denied", EACCES},
	{"file does not exist", ENOENT},
	{"authentication failed", ECONNREFUSED},
	{"bad offset in directory read", ESPIPE},
	{"bad use of fid", EBADF},
	{"wstat can't convert between files and directories", EPERM},
	{"directory is not empty", ENOTEMPTY},
	{"file exists", EEXIST},
	{"file already exists", EEXIST},
	{"file or directory already exists", EEXIST},
	{"fid already in use", EBADF},
	{"file in use", ETXTBSY},
	{"i/o error", EIO},
	{"file already open for I/O", ETXTBSY},
	{"illegal mode", EINVAL},
	{"illegal name", ENAMETOOLONG},
	{"not a directory", ENOTDIR},
	{"not a member of proposed group", EINVAL},
	{"not owner", EACCES},
	{"only owner can change group in wstat", EACCES},
	{"read only file system", EROFS},
	{"no access to special file", EPERM},
	{"i/o count too large", EIO},
	{"unknown group", EINVAL},
	{"unknown user", EINVAL},
	{"bogus wstat buffer", EPROTO},
	{"exclusive use file already open", EAGAIN},
	{"corrupted directory entry", EIO},
	{"corrupted file entry", EIO},
	{"corrupted block label", EIO},
	{"corrupted meta data", EIO},
	{"illegal offset", EINVAL},
	{"illegal path element", ENOENT},
	{"root of file system is corrupted", EIO},
	{"corrupted super block", EIO},
	{"protocol botch", EPROTO},
	{"file system is full", ENOSPC},
	{"file is in use", EAGAIN},
	{"directory entry is not allocated", ENOENT},
	{"file is read only", EROFS},
	{"file has been removed", EIDRM},
	{"only support truncation to zero length", EPERM},
	{"cannot remove root", EPERM},
	{"file too big", EFBIG},
	{"venti i/o error", EIO},
	/* these are not errors */
	{"u9fs rhostsauth: no authentication required", 0},
	{"u9fs authnone: no authentication required", 0},
	{NULL, -1}
};

extern int v9fs_error_init(void);
extern int v9fs_errstr2errno(char *errstr);

fs/9p/fid.c

0 → 100644
+241 −0
Original line number Diff line number Diff line
/*
 * V9FS FID Management
 *
 *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/idr.h>

#include "debug.h"
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
#include "transport.h"
#include "mux.h"
#include "conv.h"
#include "fid.h"

/**
 * v9fs_fid_insert - add a fid to a dentry
 * @fid: fid to add
 * @dentry: dentry that it is being added to
 *
 */

static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
{
	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
	dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
		dentry->d_iname, dentry);
	if (dentry->d_fsdata == NULL) {
		dentry->d_fsdata =
		    kmalloc(sizeof(struct list_head), GFP_KERNEL);
		if (dentry->d_fsdata == NULL) {
			dprintk(DEBUG_ERROR, "Out of memory\n");
			return -ENOMEM;
		}
		fid_list = (struct list_head *)dentry->d_fsdata;
		INIT_LIST_HEAD(fid_list);	/* Initialize list head */
	}

	fid->uid = current->uid;
	fid->pid = current->pid;
	list_add(&fid->list, fid_list);
	return 0;
}

/**
 * v9fs_fid_create - allocate a FID structure
 * @dentry - dentry to link newly created fid to
 *
 */

struct v9fs_fid *v9fs_fid_create(struct dentry *dentry)
{
	struct v9fs_fid *new;

	new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
	if (new == NULL) {
		dprintk(DEBUG_ERROR, "Out of Memory\n");
		return ERR_PTR(-ENOMEM);
	}

	new->fid = -1;
	new->fidopen = 0;
	new->fidcreate = 0;
	new->fidclunked = 0;
	new->iounit = 0;

	if (v9fs_fid_insert(new, dentry) == 0)
		return new;
	else {
		dprintk(DEBUG_ERROR, "Problems inserting to dentry\n");
		kfree(new);
		return NULL;
	}
}

/**
 * v9fs_fid_destroy - deallocate a FID structure
 * @fid: fid to destroy
 *
 */

void v9fs_fid_destroy(struct v9fs_fid *fid)
{
	list_del(&fid->list);
	kfree(fid);
}

/**
 * v9fs_fid_lookup - retrieve the right fid from a  particular dentry
 * @dentry: dentry to look for fid in
 * @type: intent of lookup (operation or traversal)
 *
 * search list of fids associated with a dentry for a fid with a matching
 * thread id or uid.  If that fails, look up the dentry's parents to see if you
 * can find a matching fid.
 *
 */

struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type)
{
	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
	struct v9fs_fid *current_fid = NULL;
	struct v9fs_fid *temp = NULL;
	struct v9fs_fid *return_fid = NULL;
	int found_parent = 0;
	int found_user = 0;

	dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry,
		type);

	if (fid_list && !list_empty(fid_list)) {
		list_for_each_entry_safe(current_fid, temp, fid_list, list) {
			if (current_fid->uid == current->uid) {
				if (return_fid == NULL) {
					if ((type == FID_OP)
					    || (!current_fid->fidopen)) {
						return_fid = current_fid;
						found_user = 1;
					}
				}
			}
			if (current_fid->pid == current->real_parent->pid) {
				if ((return_fid == NULL) || (found_parent)
				    || (found_user)) {
					if ((type == FID_OP)
					    || (!current_fid->fidopen)) {
						return_fid = current_fid;
						found_parent = 1;
						found_user = 0;
					}
				}
			}
			if (current_fid->pid == current->pid) {
				if ((type == FID_OP) ||
				    (!current_fid->fidopen)) {
					return_fid = current_fid;
					found_parent = 0;
					found_user = 0;
				}
			}
		}
	}

	/* we are at the root but didn't match */
	if ((!return_fid) && (dentry->d_parent == dentry)) {
		/* TODO: clone attach with new uid */
		return_fid = current_fid;
	}

	if (!return_fid) {
		struct dentry *par = current->fs->pwd->d_parent;
		int count = 1;
		while (par != NULL) {
			if (par == dentry)
				break;
			count++;
			if (par == par->d_parent) {
				dprintk(DEBUG_ERROR,
					"got to root without finding dentry\n");
				break;
			}
			par = par->d_parent;
		}

/* XXX - there may be some duplication we can get rid of */
		if (par == dentry) {
			/* we need to fid_lookup the starting point */
			int fidnum = -1;
			int oldfid = -1;
			int result = -1;
			struct v9fs_session_info *v9ses =
			    v9fs_inode2v9ses(current->fs->pwd->d_inode);

			current_fid =
			    v9fs_fid_lookup(current->fs->pwd, FID_WALK);
			if (current_fid == NULL) {
				dprintk(DEBUG_ERROR,
					"process cwd doesn't have a fid\n");
				return return_fid;
			}
			oldfid = current_fid->fid;
			par = current->fs->pwd;
			/* TODO: take advantage of multiwalk */

			fidnum = v9fs_get_idpool(&v9ses->fidpool);
			if (fidnum < 0) {
				dprintk(DEBUG_ERROR,
					"could not get a new fid num\n");
				return return_fid;
			}

			while (par != dentry) {
				result =
				    v9fs_t_walk(v9ses, oldfid, fidnum, "..",
						NULL);
				if (result < 0) {
					dprintk(DEBUG_ERROR,
						"problem walking to parent\n");

					break;
				}
				oldfid = fidnum;
				if (par == par->d_parent) {
					dprintk(DEBUG_ERROR,
						"can't find dentry\n");
					break;
				}
				par = par->d_parent;
			}
			if (par == dentry) {
				return_fid = v9fs_fid_create(dentry);
				return_fid->fid = fidnum;
			}
		}
	}

	return return_fid;
}

fs/9p/fid.h

0 → 100644
+57 −0
Original line number Diff line number Diff line
/*
 * V9FS FID Management
 *
 *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#include <linux/list.h>

#define FID_OP   0
#define FID_WALK 1

struct v9fs_fid {
	struct list_head list;	 /* list of fids associated with a dentry */
	struct list_head active; /* XXX - debug */

	u32 fid;
	unsigned char fidopen;	  /* set when fid is opened */
	unsigned char fidcreate;  /* set when fid was just created */
	unsigned char fidclunked; /* set when fid has already been clunked */

	struct v9fs_qid qid;
	u32 iounit;

	/* readdir stuff */
	int rdir_fpos;
	loff_t rdir_pos;
	struct v9fs_fcall *rdir_fcall;

	/* management stuff */
	pid_t pid;		/* thread associated with this fid */
	uid_t uid;		/* user associated with this fid */

	/* private data */
	struct file *filp;	/* backpointer to File struct for open files */
	struct v9fs_session_info *v9ses;	/* session info for this FID */
};

struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type);
void v9fs_fid_destroy(struct v9fs_fid *fid);
struct v9fs_fid *v9fs_fid_create(struct dentry *);