linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups"
       [not found] <1351700061-7203-1-git-send-email-james.hogan@imgtec.com>
@ 2012-10-31 16:13 ` James Hogan
  2012-11-01 13:25   ` Mikael Pettersson
  2012-10-31 16:14 ` [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag James Hogan
  1 sibling, 1 reply; 9+ messages in thread
From: James Hogan @ 2012-10-31 16:13 UTC (permalink / raw)
  To: linux-arch; +Cc: James Hogan, Mikael Pettersson, Alexander Viro, linux-fsdevel

The commit "binfmt_elf: cleanups"
(f670d0ecda73b7438eec9ed108680bc5f5362ad8) removed an ifndef elf_map but
this breaks compilation on metag architecture which does define elf_map.

This adds the ifndef back in as it was before, but does not affect the
other cleanups made by that patch.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mikael Pettersson <mikpe@it.uu.se>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
---
 fs/binfmt_elf.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 1b52956..14d1fbd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -314,6 +314,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	return 0;
 }
 
+#ifndef elf_map
+
 static unsigned long elf_map(struct file *filep, unsigned long addr,
 		struct elf_phdr *eppnt, int prot, int type,
 		unsigned long total_size)
@@ -348,6 +350,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
 	return(map_addr);
 }
 
+#endif /* !elf_map */
+
 static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
 {
 	int i, first_idx = -1, last_idx = -1;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
       [not found] <1351700061-7203-1-git-send-email-james.hogan@imgtec.com>
  2012-10-31 16:13 ` [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups" James Hogan
@ 2012-10-31 16:14 ` James Hogan
  2012-10-31 16:42   ` Al Viro
  2012-10-31 19:55   ` Myklebust, Trond
  1 sibling, 2 replies; 9+ messages in thread
From: James Hogan @ 2012-10-31 16:14 UTC (permalink / raw)
  To: linux-arch; +Cc: James Hogan, Alexander Viro, linux-fsdevel

Add the Metag Debug Adapter File System (DAFS), which uses Meta SWITCH
operations to communicate with a file server on a host computer via a
JTAG debug adapter.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
---
 MAINTAINERS        |    1 +
 arch/metag/Kconfig |    1 +
 fs/Kconfig         |    1 +
 fs/Makefile        |    1 +
 fs/dafs/Kconfig    |    6 +
 fs/dafs/Makefile   |    7 +
 fs/dafs/dafs.h     |   80 +++++
 fs/dafs/inode.c    |  830 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 927 insertions(+), 0 deletions(-)
 create mode 100644 fs/dafs/Kconfig
 create mode 100644 fs/dafs/Makefile
 create mode 100644 fs/dafs/dafs.h
 create mode 100644 fs/dafs/inode.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1e55a5e..02e9d3e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4538,6 +4538,7 @@ F:	arch/metag/
 F:	Documentation/metag/
 F:	Documentation/devicetree/bindings/metag/
 F:	drivers/tty/metag_da.c
+F:	fs/dafs/
 
 MICROBLAZE ARCHITECTURE
 M:	Michal Simek <monstr@monstr.eu>
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index 96e9fbf..a186f3c 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -224,6 +224,7 @@ config METAG_DA
 	  This enables support for services provided by DA JTAG debug adapters,
 	  such as:
 	  - communication over DA channels (such as the console driver).
+	  - use of the DA filesystem.
 
 menu "Boot options"
 
diff --git a/fs/Kconfig b/fs/Kconfig
index f95ae3a..342cd55 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -220,6 +220,7 @@ source "fs/pstore/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
+source "fs/dafs/Kconfig"
 
 endif # MISC_FILESYSTEMS
 
diff --git a/fs/Makefile b/fs/Makefile
index 2fb9779..e803b53 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -125,3 +125,4 @@ obj-$(CONFIG_GFS2_FS)           += gfs2/
 obj-y				+= exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)		+= ceph/
 obj-$(CONFIG_PSTORE)		+= pstore/
+obj-$(CONFIG_DAFS_FS)           += dafs/
diff --git a/fs/dafs/Kconfig b/fs/dafs/Kconfig
new file mode 100644
index 0000000..2ead46f
--- /dev/null
+++ b/fs/dafs/Kconfig
@@ -0,0 +1,6 @@
+config DAFS_FS
+	bool "Meta DA filesystem support"
+	depends on METAG_DA
+	help
+	  This enables the DA filesystem, which allows Linux to
+	  to access files on a system attached via a debug adapter.
diff --git a/fs/dafs/Makefile b/fs/dafs/Makefile
new file mode 100644
index 0000000..479ce8f
--- /dev/null
+++ b/fs/dafs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for DAfs the Debug Adapter filesystem.
+#
+
+obj-$(CONFIG_DAFS_FS) += dafs.o
+
+dafs-objs := inode.o
diff --git a/fs/dafs/dafs.h b/fs/dafs/dafs.h
new file mode 100644
index 0000000..2352f91
--- /dev/null
+++ b/fs/dafs/dafs.h
@@ -0,0 +1,80 @@
+#ifndef _DAFS_H_
+#define _DAFS_H_
+
+#define DA_OP_OPEN 0
+#define DA_OP_CREAT 1
+#define DA_OP_READ 2
+#define DA_OP_WRITE 3
+#define DA_OP_CLOSE 4
+#define DA_OP_LINK 5
+#define DA_OP_LSEEK 6
+#define DA_OP_UNLINK 7
+#define DA_OP_ISATTY 8
+#define DA_OP_FCNTL 9
+#define DA_OP_STAT 10
+#define DA_OP_FSTAT 11
+#define DA_OP_GETCWD 12
+#define DA_OP_CHDIR 13
+#define DA_OP_MKDIR 14
+#define DA_OP_RMDIR 15
+#define DA_OP_FINDFIRST 16
+#define DA_OP_FINDNEXT 17
+#define DA_OP_FINDCLOSE 18
+#define DA_OP_CHMOD 19
+#define DA_OP_PREAD 20
+#define DA_OP_PWRITE 21
+
+#define OS_TYPE_FILE 1
+#define OS_TYPE_DIR 2
+#define OS_TYPE_SYMLINK 3
+#define OS_TYPE_CHARDEV 4
+#define OS_TYPE_BLOCKDEV 5
+#define OS_TYPE_FIFO 6
+#define OS_TYPE_SOCK 7
+
+#define DA_O_RDONLY 0
+#define DA_O_WRONLY 1
+#define DA_O_RDWR 2
+#define DA_O_APPEND 8
+#define DA_O_CREAT 0x0200
+#define DA_O_TRUNC 0x0400
+#define DA_O_EXCL 0x0800
+
+#define DA_O_AFFINITY_THREAD_0 0x10000
+#define DA_O_AFFINITY_THREAD_1 0x20000
+#define DA_O_AFFINITY_THREAD_2 0x40000
+#define DA_O_AFFINITY_THREAD_3 0x80000
+#define DA_O_AFFINITY_SHIFT 16
+
+#define DA_S_IWUSR	0200	/* 0x80 */
+#define DA_S_IRUSR	0400	/* 0x100 */
+
+struct da_stat {
+	short st_dev;
+	unsigned short st_ino;
+	unsigned st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	short st_rdev;
+	int st_size;
+	int st_atime;
+	int st_spare1;
+	int st_mtime;
+	int st_spare2;
+	int st_ctime;
+	int st_spare3;
+	int st_blksize;
+	int st_blocks;
+	int st_spare4[2];
+};
+
+#define _A_SUBDIR 0x10
+
+struct da_finddata {
+	unsigned long size;
+	unsigned long attrib;
+	char name[260];
+};
+
+#endif
diff --git a/fs/dafs/inode.c b/fs/dafs/inode.c
new file mode 100644
index 0000000..25e0ca8
--- /dev/null
+++ b/fs/dafs/inode.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2008,2009,2010 Imagination Technologies Ltd.
+ * Licensed under the GPL
+ *
+ * Based on hostfs for UML.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+
+#include <asm/da.h>
+#include <asm/hwthread.h>
+
+#include "dafs.h"
+
+static int fserrno;
+
+int fscall(int system_call, int arg1, int arg2, int arg3, int arg4, int arg5)
+{
+	register int arg1_           __asm__("D1Ar1") = arg1;
+	register int arg2_           __asm__("D0Ar2") = arg2;
+	register int arg3_           __asm__("D1Ar3") = arg3;
+	register int arg4_           __asm__("D0Ar4") = arg4;
+	register int arg5_           __asm__("D1Ar5") = arg5;
+	register int system_call_    __asm__("D0Ar6") = system_call;
+	register int result          __asm__("D0Re0");
+	register int errno           __asm__("D1Re0");
+
+	__asm__ volatile (
+		"SETL   [A0StP++], %7,%6\n\t"
+		"SETL   [A0StP++], %5,%4\n\t"
+		"SETL   [A0StP++], %3,%2\n\t"
+		"ADD    A0StP, A0StP, #8\n\t"
+		"SWITCH #0x0C00208\n\t"
+		"GETL   %0, %1, [A0StP+#-8]\n\t"
+		"SUB    A0StP, A0StP, #(4*6)+8\n\t"
+		: "=r" (result), "=r" (errno)
+		: "r" (arg1_), "r" (arg2_), "r" (arg3_),
+		  "r" (arg4_), "r" (arg5_), "r" (system_call_)
+		: "memory");
+
+	fserrno = errno;
+
+	return result;
+}
+
+struct dafs_inode_info {
+	int fd;
+	int mode;
+	struct inode vfs_inode;
+};
+
+static inline struct dafs_inode_info *DAFS_I(struct inode *inode)
+{
+	return container_of(inode, struct dafs_inode_info, vfs_inode);
+}
+
+#define FILE_DAFS_I(file) DAFS_I((file)->f_path.dentry->d_inode)
+
+static int dafs_d_delete(const struct dentry *dentry)
+{
+	return 1;
+}
+
+static const struct dentry_operations dafs_dentry_ops = {
+	.d_delete		= dafs_d_delete,
+};
+
+#define DAFS_SUPER_MAGIC 0xdadadaf5
+
+static const struct inode_operations dafs_iops;
+static const struct inode_operations dafs_dir_iops;
+
+static char *__dentry_name(struct dentry *dentry, char *name)
+{
+	char *p = dentry_path_raw(dentry, name, PATH_MAX);
+	char *root;
+	size_t len;
+
+	root = dentry->d_sb->s_fs_info;
+	len = strlen(root);
+	if (IS_ERR(p)) {
+		__putname(name);
+		return NULL;
+	}
+
+	strlcpy(name, root, PATH_MAX);
+	if (len > p - name) {
+		__putname(name);
+		return NULL;
+	}
+	if (p > name + len) {
+		char *s = name + len;
+		while ((*s++ = *p++) != '\0')
+			;
+	}
+	return name;
+}
+
+static char *dentry_name(struct dentry *dentry)
+{
+	char *name = __getname();
+	if (!name)
+		return NULL;
+
+	return __dentry_name(dentry, name); /* will unlock */
+}
+
+static int stat_file(const char *path, struct da_stat *p, int fd)
+{
+	int ret;
+	memset(p, 0, sizeof(*p));
+
+	if (fd >= 0) {
+		ret = fscall(DA_OP_FSTAT, fd, (int)p, 0, 0, 0);
+		if (ret < 0) {
+			/* Some versions of Codescape do not fill out errno. */
+			if (ret < 0 && fserrno == 0)
+				fserrno = ENOENT;
+			return -fserrno;
+		}
+	} else {
+		ret = fscall(DA_OP_STAT, (int)path, (int)p, strlen(path), 0, 0);
+		if (ret < 0) {
+			/* Some versions of Codescape do not fill out errno. */
+			if (ret < 0 && fserrno == 0)
+				fserrno = ENOENT;
+			return -fserrno;
+		}
+	}
+
+	return 0;
+}
+
+static struct inode *dafs_iget(struct super_block *sb)
+{
+	struct inode *inode = new_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	return inode;
+}
+
+static struct inode *dafs_alloc_inode(struct super_block *sb)
+{
+	struct dafs_inode_info *hi;
+
+	hi = kzalloc(sizeof(*hi), GFP_KERNEL);
+	if (hi == NULL)
+		return NULL;
+
+	hi->fd = -1;
+	inode_init_once(&hi->vfs_inode);
+	return &hi->vfs_inode;
+}
+
+static void close_file(void *stream)
+{
+	int fd = *((int *) stream);
+
+	fscall(DA_OP_CLOSE, fd, 0, 0, 0, 0);
+}
+
+static void dafs_evict_inode(struct inode *inode)
+{
+	truncate_inode_pages(&inode->i_data, 0);
+	clear_inode(inode);
+	if (DAFS_I(inode)->fd != -1) {
+		close_file(&DAFS_I(inode)->fd);
+		DAFS_I(inode)->fd = -1;
+	}
+}
+
+static void dafs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	kfree(DAFS_I(inode));
+}
+
+static void dafs_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, dafs_i_callback);
+}
+
+static const struct super_operations dafs_sbops = {
+	.alloc_inode	= dafs_alloc_inode,
+	.drop_inode	= generic_delete_inode,
+	.evict_inode	= dafs_evict_inode,
+	.destroy_inode	= dafs_destroy_inode,
+};
+
+static int open_dir(char *path, struct da_finddata *finddata)
+{
+	int len = strlen(path);
+	char buf[len + 3];
+
+	strcpy(buf, path);
+	if (buf[len - 1] != '/')
+		strcat(buf, "/*");
+	else
+		strcat(buf, "*");
+
+	return fscall(DA_OP_FINDFIRST, (int)buf, (int)finddata, 0, 0, 0);
+}
+
+static void close_dir(int handle)
+{
+	fscall(DA_OP_FINDCLOSE, handle, 0, 0, 0, 0);
+}
+
+static int read_dir(int handle, struct da_finddata *finddata)
+{
+	return fscall(DA_OP_FINDNEXT, handle, (int)finddata, 0, 0, 0);
+}
+
+static int dafs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	char *name;
+	int handle;
+	unsigned long long next, ino;
+	int error = 0;
+	struct da_finddata finddata;
+
+	name = dentry_name(file->f_path.dentry);
+	if (name == NULL)
+		return -ENOMEM;
+	handle = open_dir(name, &finddata);
+	__putname(name);
+	if (handle == -1)
+		return -fserrno;
+
+	next = 1;
+
+	if (file->f_pos == 0) {
+		error = (*filldir)(ent, ".", file->f_pos + 1,
+				   file->f_pos, inode->i_ino,
+				   DT_DIR);
+		if (error < 0)
+			goto out;
+		file->f_pos++;
+	}
+
+	while (1) {
+		error = read_dir(handle, &finddata);
+		if (error)
+			break;
+
+		if (next >= file->f_pos) {
+			size_t len = strlen(finddata.name);
+			ino = iunique(sb, 100);
+			error = (*filldir)(ent, finddata.name, len,
+					   file->f_pos, ino,
+					   (finddata.attrib & _A_SUBDIR) ?
+					    DT_DIR : DT_REG);
+			if (error)
+				break;
+			file->f_pos++;
+		}
+		next++;
+	}
+out:
+	close_dir(handle);
+	return 0;
+}
+
+static int dafs_file_open(struct inode *ino, struct file *file)
+{
+	static DEFINE_MUTEX(open_mutex);
+	char *name;
+	int mode, fmode, flags = 0, r = 0, w = 0, fd;
+	int i;
+
+	fmode = file->f_mode & (FMODE_READ | FMODE_WRITE);
+	if ((fmode & DAFS_I(ino)->mode) == fmode)
+		return 0;
+
+	mode = ino->i_mode & (DA_S_IWUSR | DA_S_IRUSR);
+
+	mode |= DAFS_I(ino)->mode;
+
+	DAFS_I(ino)->mode |= fmode;
+	if (DAFS_I(ino)->mode & FMODE_READ)
+		r = 1;
+	if (DAFS_I(ino)->mode & FMODE_WRITE) {
+		w = 1;
+		r = 1;
+	}
+
+retry:
+	if (r && !w)
+		flags |= DA_O_RDONLY;
+	else if (!r && w)
+		flags |= DA_O_WRONLY;
+	else if (r && w)
+		flags |= DA_O_RDWR;
+
+	if (file->f_flags & O_CREAT)
+		flags |= DA_O_CREAT;
+
+	if (file->f_flags & O_TRUNC)
+		flags |= DA_O_TRUNC;
+
+	/*
+	 * Set the affinity for this file handle to all CPUs. If we
+	 * don't do this then, if the process that opened the file
+	 * migrates to a different cpu, the FileServer will not accept
+	 * the file handle.
+	 */
+	for (i = 0; i < NR_CPUS; i++) {
+		u8 hwthread = cpu_2_hwthread_id[i];
+		flags |= (1 << (DA_O_AFFINITY_SHIFT + hwthread));
+	}
+
+	name = dentry_name(file->f_path.dentry);
+	if (name == NULL)
+		return -ENOMEM;
+
+	fd = fscall(DA_OP_OPEN, (int)name, flags, mode, strlen(name), 0);
+	__putname(name);
+	if (fd < 0)
+		return fd;
+
+	mutex_lock(&open_mutex);
+	/* somebody else had handled it first? */
+	if ((mode & DAFS_I(ino)->mode) == mode) {
+		mutex_unlock(&open_mutex);
+		return 0;
+	}
+	if ((mode | DAFS_I(ino)->mode) != mode) {
+		mode |= DAFS_I(ino)->mode;
+		mutex_unlock(&open_mutex);
+		close_file(&fd);
+		goto retry;
+	}
+	DAFS_I(ino)->fd = fd;
+	DAFS_I(ino)->mode = mode;
+	mutex_unlock(&open_mutex);
+
+	return 0;
+}
+
+static const struct file_operations dafs_file_fops = {
+	.llseek		= generic_file_llseek,
+	.read		= do_sync_read,
+	.splice_read	= generic_file_splice_read,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
+	.write		= do_sync_write,
+	.mmap		= generic_file_mmap,
+	.open		= dafs_file_open,
+	.release	= NULL,
+};
+
+static const struct file_operations dafs_dir_fops = {
+	.llseek		= generic_file_llseek,
+	.readdir	= dafs_readdir,
+	.read		= generic_read_dir,
+};
+
+static int read_file(int fd, unsigned long long *offset, const char *buf,
+		     int len)
+{
+	int n;
+
+	n = fscall(DA_OP_PREAD, fd, (int)buf, len, (int)*offset, 0);
+
+	if (n < 0)
+		return -fserrno;
+
+	return n;
+}
+
+static int write_file(int fd, unsigned long long *offset, const char *buf,
+		      int len)
+{
+	int n;
+
+	n = fscall(DA_OP_PWRITE, fd, (int)buf, len, (int)*offset, 0);
+
+	if (n < 0)
+		return -fserrno;
+
+	return n;
+}
+
+static int dafs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	unsigned long long base;
+	int count = PAGE_CACHE_SIZE;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	int err;
+
+	if (page->index >= end_index)
+		count = inode->i_size & (PAGE_CACHE_SIZE-1);
+
+	buffer = kmap(page);
+	base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
+
+	err = write_file(DAFS_I(inode)->fd, &base, buffer, count);
+	if (err != count) {
+		ClearPageUptodate(page);
+		goto out;
+	}
+
+	if (base > inode->i_size)
+		inode->i_size = base;
+
+	if (PageError(page))
+		ClearPageError(page);
+	err = 0;
+
+ out:
+	kunmap(page);
+
+	unlock_page(page);
+	return err;
+}
+
+static int dafs_readpage(struct file *file, struct page *page)
+{
+	char *buffer;
+	long long start;
+	int err = 0;
+
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	err = read_file(FILE_DAFS_I(file)->fd, &start, buffer,
+			PAGE_CACHE_SIZE);
+	if (err < 0)
+		goto out;
+
+	memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
+
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	if (PageError(page))
+		ClearPageError(page);
+	err = 0;
+ out:
+	kunmap(page);
+	unlock_page(page);
+	return err;
+}
+
+int dafs_write_begin(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned flags,
+			struct page **pagep, void **fsdata)
+{
+	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+
+	*pagep = grab_cache_page_write_begin(mapping, index, flags);
+	if (!*pagep)
+		return -ENOMEM;
+	return 0;
+}
+
+int dafs_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *page, void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	void *buffer;
+	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+	int err;
+
+	buffer = kmap(page);
+	err = write_file(FILE_DAFS_I(file)->fd, &pos, buffer + from, copied);
+	kunmap(page);
+
+	if (!PageUptodate(page) && err == PAGE_CACHE_SIZE)
+		SetPageUptodate(page);
+
+	/*
+	 * If err > 0, write_file has added err to pos, so we are comparing
+	 * i_size against the last byte written.
+	 */
+	if (err > 0 && (pos > inode->i_size))
+		inode->i_size = pos;
+	unlock_page(page);
+	page_cache_release(page);
+
+	return err;
+}
+
+static const struct address_space_operations dafs_aops = {
+	.writepage	= dafs_writepage,
+	.readpage	= dafs_readpage,
+	.set_page_dirty	= __set_page_dirty_nobuffers,
+	.write_begin	= dafs_write_begin,
+	.write_end	= dafs_write_end,
+};
+
+static int read_name(struct inode *ino, char *name)
+{
+	dev_t rdev;
+	struct da_stat st;
+	int err = stat_file(name, &st, -1);
+	if (err)
+		return err;
+
+	/* No valid maj and min from DA.*/
+	rdev = MKDEV(0, 0);
+
+	switch (st.st_mode & S_IFMT) {
+	case S_IFDIR:
+		ino->i_op = &dafs_dir_iops;
+		ino->i_fop = &dafs_dir_fops;
+		break;
+	case S_IFCHR:
+	case S_IFBLK:
+	case S_IFIFO:
+	case S_IFSOCK:
+		init_special_inode(ino, st.st_mode & S_IFMT, rdev);
+		ino->i_op = &dafs_iops;
+		break;
+
+	case S_IFLNK:
+	default:
+		ino->i_op = &dafs_iops;
+		ino->i_fop = &dafs_file_fops;
+		ino->i_mapping->a_ops = &dafs_aops;
+	}
+
+	ino->i_ino = st.st_ino;
+	ino->i_mode = st.st_mode;
+	set_nlink(ino, st.st_nlink);
+
+	ino->i_uid = st.st_uid;
+	ino->i_gid = st.st_gid;
+	ino->i_atime.tv_sec = st.st_atime;
+	ino->i_atime.tv_nsec = 0;
+	ino->i_mtime.tv_sec = st.st_mtime;
+	ino->i_mtime.tv_nsec = 0;
+	ino->i_ctime.tv_sec = st.st_ctime;
+	ino->i_ctime.tv_nsec = 0;
+	ino->i_size = st.st_size;
+	ino->i_blocks = st.st_blocks;
+	return 0;
+}
+
+static int dafs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+		       bool excl)
+{
+	struct inode *inode;
+	char *name;
+	int error, fd;
+	int damode;
+	int creat_flags = DA_O_TRUNC | DA_O_CREAT | DA_O_WRONLY;
+	int i;
+
+	inode = dafs_iget(dir->i_sb);
+	if (IS_ERR(inode)) {
+		error = PTR_ERR(inode);
+		goto out;
+	}
+
+	damode = mode & (DA_S_IWUSR | DA_S_IRUSR);
+
+	error = -ENOMEM;
+	name = dentry_name(dentry);
+	if (name == NULL)
+		goto out_put;
+
+	/*
+	 * creat() will only create text mode files on a Windows host
+	 * at present.  Replicate the creat() functionality with an
+	 * open() call, which always creates binary files. Set the
+	 * affinity to all hardware threads.
+	 */
+	for (i = 0; i < NR_CPUS; i++) {
+		u8 hwthread = cpu_2_hwthread_id[i];
+		creat_flags |= (1 << (DA_O_AFFINITY_SHIFT + hwthread));
+	}
+
+	fd = fscall(DA_OP_OPEN, (int)name, creat_flags, damode, strlen(name),
+		    0);
+	if (fd < 0)
+		error = fd;
+	else
+		error = read_name(inode, name);
+
+	kfree(name);
+	if (error)
+		goto out_put;
+
+	DAFS_I(inode)->fd = fd;
+	DAFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
+	d_instantiate(dentry, inode);
+	return 0;
+
+ out_put:
+	iput(inode);
+ out:
+	return error;
+}
+
+static struct dentry *dafs_lookup(struct inode *ino, struct dentry *dentry,
+				  unsigned int flags)
+{
+	struct inode *inode;
+	char *name;
+	int err;
+
+	inode = dafs_iget(ino->i_sb);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out;
+	}
+
+	err = -ENOMEM;
+	name = dentry_name(dentry);
+	if (name == NULL)
+		goto out_put;
+
+	err = read_name(inode, name);
+
+	__putname(name);
+	if (err == -ENOENT) {
+		iput(inode);
+		inode = NULL;
+	} else if (err)
+		goto out_put;
+
+	d_add(dentry, inode);
+	return NULL;
+
+ out_put:
+	iput(inode);
+ out:
+	return ERR_PTR(err);
+}
+
+int dafs_link(struct dentry *to, struct inode *ino, struct dentry *from)
+{
+	char *from_name, *to_name;
+	int err;
+
+	from_name = dentry_name(from);
+	if (from_name == NULL)
+		return -ENOMEM;
+	to_name = dentry_name(to);
+	if (to_name == NULL) {
+		__putname(from_name);
+		return -ENOMEM;
+	}
+	err = -EINVAL;
+	__putname(from_name);
+	__putname(to_name);
+	return err;
+}
+
+int dafs_unlink(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	file = dentry_name(dentry);
+	if (file == NULL)
+		return -ENOMEM;
+
+	err = fscall(DA_OP_UNLINK, (int)file, 0, 0, 0, 0);
+	__putname(file);
+	if (err)
+		return -fserrno;
+	return 0;
+}
+
+static int do_mkdir(const char *file, int mode)
+{
+	int err;
+
+	err = fscall(DA_OP_MKDIR, (int)file, mode, strlen(file), 0, 0);
+	if (err)
+		return -fserrno;
+	return 0;
+}
+
+int dafs_mkdir(struct inode *ino, struct dentry *dentry, umode_t mode)
+{
+	char *file;
+	int err;
+
+	file = dentry_name(dentry);
+	if (file == NULL)
+		return -ENOMEM;
+	err = do_mkdir(file, mode);
+	__putname(file);
+	return err;
+}
+
+static int do_rmdir(const char *file)
+{
+	int err;
+
+	err = fscall(DA_OP_RMDIR, (int)file, strlen(file), 0, 0, 0);
+	if (err)
+		return -fserrno;
+	return 0;
+}
+
+int dafs_rmdir(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	file = dentry_name(dentry);
+	if (file == NULL)
+		return -ENOMEM;
+	err = do_rmdir(file);
+	__putname(file);
+	return err;
+}
+
+int dafs_rename(struct inode *from_ino, struct dentry *from,
+		  struct inode *to_ino, struct dentry *to)
+{
+	char *from_name, *to_name;
+	int err;
+
+	from_name = dentry_name(from);
+	if (from_name == NULL)
+		return -ENOMEM;
+	to_name = dentry_name(to);
+	if (to_name == NULL) {
+		__putname(from_name);
+		return -ENOMEM;
+	}
+	err = -EINVAL;
+	__putname(from_name);
+	__putname(to_name);
+	return err;
+}
+
+static const struct inode_operations dafs_iops = {
+	.create		= dafs_create,
+	.link		= dafs_link,
+	.unlink		= dafs_unlink,
+	.mkdir		= dafs_mkdir,
+	.rmdir		= dafs_rmdir,
+	.rename		= dafs_rename,
+};
+
+static const struct inode_operations dafs_dir_iops = {
+	.create		= dafs_create,
+	.lookup		= dafs_lookup,
+	.link		= dafs_link,
+	.unlink		= dafs_unlink,
+	.mkdir		= dafs_mkdir,
+	.rmdir		= dafs_rmdir,
+	.rename		= dafs_rename,
+};
+
+static char *host_root_path = ".";
+
+static int dafs_fill_sb_common(struct super_block *sb, void *d, int silent)
+{
+	struct inode *root_inode;
+	int err;
+
+	sb->s_blocksize = 1024;
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = DAFS_SUPER_MAGIC;
+	sb->s_op = &dafs_sbops;
+	sb->s_d_op = &dafs_dentry_ops;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
+
+	err = -ENOMEM;
+
+	root_inode = new_inode(sb);
+	if (!root_inode)
+		goto out;
+
+	err = read_name(root_inode, host_root_path);
+	if (err)
+		goto out_put;
+
+	err = -ENOMEM;
+	sb->s_fs_info = host_root_path;
+	sb->s_root = d_make_root(root_inode);
+	if (sb->s_root == NULL)
+		goto out;
+
+	return 0;
+
+out_put:
+	iput(root_inode);
+out:
+	return err;
+}
+
+static struct dentry *dafs_read_sb(struct file_system_type *type,
+				   int flags, const char *dev_name,
+				   void *data)
+{
+	if (!metag_da_enabled())
+		return ERR_PTR(-ENODEV);
+	return mount_nodev(type, flags, data, dafs_fill_sb_common);
+}
+
+static struct file_system_type dafs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "dafs",
+	.mount		= dafs_read_sb,
+	.kill_sb	= kill_anon_super,
+	.fs_flags	= 0,
+};
+
+static int __init init_dafs(void)
+{
+	return register_filesystem(&dafs_type);
+}
+
+static void __exit exit_dafs(void)
+{
+	unregister_filesystem(&dafs_type);
+}
+
+module_init(init_dafs)
+module_exit(exit_dafs)
+MODULE_LICENSE("GPL");
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
  2012-10-31 16:14 ` [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag James Hogan
@ 2012-10-31 16:42   ` Al Viro
  2012-10-31 19:39     ` James Hogan
  2012-10-31 19:55   ` Myklebust, Trond
  1 sibling, 1 reply; 9+ messages in thread
From: Al Viro @ 2012-10-31 16:42 UTC (permalink / raw)
  To: James Hogan; +Cc: linux-arch, linux-fsdevel

On Wed, Oct 31, 2012 at 04:14:21PM +0000, James Hogan wrote:
> +static int fserrno;

... and nothing visible serializing its users.  AFAICS, there's nothing
stopping one thread from doing this fscall thing, then deciding to check
what's in fserrno only to find that *another* thread has also done
fscall - a different one, with different results and different value
stored in fserrno.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
  2012-10-31 16:42   ` Al Viro
@ 2012-10-31 19:39     ` James Hogan
  0 siblings, 0 replies; 9+ messages in thread
From: James Hogan @ 2012-10-31 19:39 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-arch, linux-fsdevel

On 31/10/12 16:42, Al Viro wrote:
> On Wed, Oct 31, 2012 at 04:14:21PM +0000, James Hogan wrote:
>> +static int fserrno;
> 
> ... and nothing visible serializing its users.  AFAICS, there's nothing
> stopping one thread from doing this fscall thing, then deciding to check
> what's in fserrno only to find that *another* thread has also done
> fscall - a different one, with different results and different value
> stored in fserrno.

Yep, I'll fix that.

Thanks for taking a look

James


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
  2012-10-31 16:14 ` [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag James Hogan
  2012-10-31 16:42   ` Al Viro
@ 2012-10-31 19:55   ` Myklebust, Trond
  2012-10-31 21:39     ` James Hogan
  2012-11-02  9:33     ` James Hogan
  1 sibling, 2 replies; 9+ messages in thread
From: Myklebust, Trond @ 2012-10-31 19:55 UTC (permalink / raw)
  To: James Hogan
  Cc: linux-arch@vger.kernel.org, Alexander Viro,
	linux-fsdevel@vger.kernel.org

On Wed, 2012-10-31 at 16:14 +0000, James Hogan wrote:
> Add the Metag Debug Adapter File System (DAFS), which uses Meta SWITCH
> operations to communicate with a file server on a host computer via a
> JTAG debug adapter.
> 
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> Cc: linux-fsdevel@vger.kernel.org

You might want to note that DAFS as a name for a remote filesystem is
already taken:

  http://en.wikipedia.org/wiki/Direct_Access_File_System

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
  2012-10-31 19:55   ` Myklebust, Trond
@ 2012-10-31 21:39     ` James Hogan
  2012-11-02  9:33     ` James Hogan
  1 sibling, 0 replies; 9+ messages in thread
From: James Hogan @ 2012-10-31 21:39 UTC (permalink / raw)
  To: Myklebust, Trond
  Cc: linux-arch@vger.kernel.org, Alexander Viro,
	linux-fsdevel@vger.kernel.org

Hi,

On 31/10/12 19:55, Myklebust, Trond wrote:
> On Wed, 2012-10-31 at 16:14 +0000, James Hogan wrote:
>> Add the Metag Debug Adapter File System (DAFS), which uses Meta SWITCH
>> operations to communicate with a file server on a host computer via a
>> JTAG debug adapter.
>>
>> Signed-off-by: James Hogan <james.hogan@imgtec.com>
>> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
>> Cc: linux-fsdevel@vger.kernel.org
> 
> You might want to note that DAFS as a name for a remote filesystem is
> already taken:
> 
>   http://en.wikipedia.org/wiki/Direct_Access_File_System
> 

Hmm, thanks for pointing that out :-)

Cheers
James


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups"
  2012-10-31 16:13 ` [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups" James Hogan
@ 2012-11-01 13:25   ` Mikael Pettersson
  2012-11-01 13:52     ` James Hogan
  0 siblings, 1 reply; 9+ messages in thread
From: Mikael Pettersson @ 2012-11-01 13:25 UTC (permalink / raw)
  To: James Hogan; +Cc: linux-arch, Mikael Pettersson, Alexander Viro, linux-fsdevel

James Hogan writes:
 > The commit "binfmt_elf: cleanups"
 > (f670d0ecda73b7438eec9ed108680bc5f5362ad8) removed an ifndef elf_map but
 > this breaks compilation on metag architecture which does define elf_map.
 > 
 > This adds the ifndef back in as it was before, but does not affect the
 > other cleanups made by that patch.

Since this is part of your patch submission to upstream the metag
kernel support, I have no objection to reverting this fragment of
my patch if/when the metag code gets upstreamed.

Acked-by: Mikael Pettersson <mikpe@it.uu.se>

 > 
 > Signed-off-by: James Hogan <james.hogan@imgtec.com>
 > Cc: Mikael Pettersson <mikpe@it.uu.se>
 > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
 > Cc: linux-fsdevel@vger.kernel.org
 > ---
 >  fs/binfmt_elf.c |    4 ++++
 >  1 files changed, 4 insertions(+), 0 deletions(-)
 > 
 > diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
 > index 1b52956..14d1fbd 100644
 > --- a/fs/binfmt_elf.c
 > +++ b/fs/binfmt_elf.c
 > @@ -314,6 +314,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 >  	return 0;
 >  }
 >  
 > +#ifndef elf_map
 > +
 >  static unsigned long elf_map(struct file *filep, unsigned long addr,
 >  		struct elf_phdr *eppnt, int prot, int type,
 >  		unsigned long total_size)
 > @@ -348,6 +350,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
 >  	return(map_addr);
 >  }
 >  
 > +#endif /* !elf_map */
 > +
 >  static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
 >  {
 >  	int i, first_idx = -1, last_idx = -1;
 > -- 
 > 1.7.7.6
 > 
 > 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups"
  2012-11-01 13:25   ` Mikael Pettersson
@ 2012-11-01 13:52     ` James Hogan
  0 siblings, 0 replies; 9+ messages in thread
From: James Hogan @ 2012-11-01 13:52 UTC (permalink / raw)
  To: Mikael Pettersson; +Cc: linux-arch, Alexander Viro, linux-fsdevel

On 01/11/12 13:25, Mikael Pettersson wrote:
> James Hogan writes:
>  > The commit "binfmt_elf: cleanups"
>  > (f670d0ecda73b7438eec9ed108680bc5f5362ad8) removed an ifndef elf_map but
>  > this breaks compilation on metag architecture which does define elf_map.
>  > 
>  > This adds the ifndef back in as it was before, but does not affect the
>  > other cleanups made by that patch.
> 
> Since this is part of your patch submission to upstream the metag
> kernel support, I have no objection to reverting this fragment of
> my patch if/when the metag code gets upstreamed.
> 
> Acked-by: Mikael Pettersson <mikpe@it.uu.se>

Thanks Mikael, I'll keep it as part of the metag patch series so that
they go in together.

Cheers
James

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag
  2012-10-31 19:55   ` Myklebust, Trond
  2012-10-31 21:39     ` James Hogan
@ 2012-11-02  9:33     ` James Hogan
  1 sibling, 0 replies; 9+ messages in thread
From: James Hogan @ 2012-11-02  9:33 UTC (permalink / raw)
  To: Myklebust, Trond
  Cc: linux-arch@vger.kernel.org, Alexander Viro,
	linux-fsdevel@vger.kernel.org

On 31/10/12 19:55, Myklebust, Trond wrote:
> On Wed, 2012-10-31 at 16:14 +0000, James Hogan wrote:
>> Add the Metag Debug Adapter File System (DAFS), which uses Meta SWITCH
>> operations to communicate with a file server on a host computer via a
>> JTAG debug adapter.
>>
>> Signed-off-by: James Hogan <james.hogan@imgtec.com>
>> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
>> Cc: linux-fsdevel@vger.kernel.org
> 
> You might want to note that DAFS as a name for a remote filesystem is
> already taken:
> 
>   http://en.wikipedia.org/wiki/Direct_Access_File_System

Hi,

Unless there are objections we'll probably rename it to imgdafs in the
next version to disambiguate with Direct Access File System.

Thanks
James


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-11-02  9:33 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1351700061-7203-1-git-send-email-james.hogan@imgtec.com>
2012-10-31 16:13 ` [RFC PATCH v1 05/40] Revert some of "binfmt_elf: cleanups" James Hogan
2012-11-01 13:25   ` Mikael Pettersson
2012-11-01 13:52     ` James Hogan
2012-10-31 16:14 ` [RFC PATCH v1 40/40] fs: dafs: Add DAFS filesystem for metag James Hogan
2012-10-31 16:42   ` Al Viro
2012-10-31 19:39     ` James Hogan
2012-10-31 19:55   ` Myklebust, Trond
2012-10-31 21:39     ` James Hogan
2012-11-02  9:33     ` James Hogan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).