Ping. Any chance of an Ack from somebody on this patch? I'm currently holding off including it in the arch/metag tree. Thanks James On 29/01/13 14:15, James Hogan wrote: > Add the IMG Debug Adapter File System (DAFS) for metag, which uses > SWITCH operations to communicate with a file server on a host computer > via a JTAG debug adapter. > > Signed-off-by: James Hogan <james.hogan@xxxxxxxxxx> > Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> > Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > Cc: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> > Cc: Cesar Eduardo Barros <cesarb@xxxxxxxxxx> > Cc: Joe Perches <joe@xxxxxxxxxxx> > Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> > Cc: linux-fsdevel@xxxxxxxxxxxxxxx > --- > v4: > * clean up fscall similarly to chancall in tty/metag_da > > v2: > * fixed fserrno problem (Al Viro) > * renamed to imgdafs > > MAINTAINERS | 1 + > arch/metag/Kconfig | 1 + > fs/Kconfig | 1 + > fs/Makefile | 1 + > fs/imgdafs/Kconfig | 6 + > fs/imgdafs/Makefile | 7 + > fs/imgdafs/imgdafs.h | 80 +++++ > fs/imgdafs/inode.c | 843 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 8 files changed, 940 insertions(+), 0 deletions(-) > create mode 100644 fs/imgdafs/Kconfig > create mode 100644 fs/imgdafs/Makefile > create mode 100644 fs/imgdafs/imgdafs.h > create mode 100644 fs/imgdafs/inode.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index cb89fe3..6b02aea 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -5044,6 +5044,7 @@ F: drivers/clocksource/metag_generic.c > F: drivers/irqchip/irq-metag.c > F: drivers/irqchip/irq-metag-ext.c > F: drivers/tty/metag_da.c > +F: fs/imgdafs/ > > MICROBLAZE ARCHITECTURE > M: Michal Simek <monstr@xxxxxxxxx> > diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig > index 9cba2f9..30adc78 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 780725a..6deefc1 100644 > --- a/fs/Kconfig > +++ b/fs/Kconfig > @@ -211,6 +211,7 @@ source "fs/sysv/Kconfig" > source "fs/ufs/Kconfig" > source "fs/exofs/Kconfig" > source "fs/f2fs/Kconfig" > +source "fs/imgdafs/Kconfig" > > endif # MISC_FILESYSTEMS > > diff --git a/fs/Makefile b/fs/Makefile > index 9d53192..b070fca 100644 > --- a/fs/Makefile > +++ b/fs/Makefile > @@ -127,3 +127,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/ > obj-y += exofs/ # Multiple modules > obj-$(CONFIG_CEPH_FS) += ceph/ > obj-$(CONFIG_PSTORE) += pstore/ > +obj-$(CONFIG_IMGDAFS_FS) += imgdafs/ > diff --git a/fs/imgdafs/Kconfig b/fs/imgdafs/Kconfig > new file mode 100644 > index 0000000..5293adb > --- /dev/null > +++ b/fs/imgdafs/Kconfig > @@ -0,0 +1,6 @@ > +config IMGDAFS_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/imgdafs/Makefile b/fs/imgdafs/Makefile > new file mode 100644 > index 0000000..169a3c6 > --- /dev/null > +++ b/fs/imgdafs/Makefile > @@ -0,0 +1,7 @@ > +# > +# Makefile for DAfs the Debug Adapter filesystem. > +# > + > +obj-$(CONFIG_IMGDAFS_FS) += imgdafs.o > + > +imgdafs-objs := inode.o > diff --git a/fs/imgdafs/imgdafs.h b/fs/imgdafs/imgdafs.h > new file mode 100644 > index 0000000..6c1da13 > --- /dev/null > +++ b/fs/imgdafs/imgdafs.h > @@ -0,0 +1,80 @@ > +#ifndef _IMGDAFS_H_ > +#define _IMGDAFS_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/imgdafs/inode.c b/fs/imgdafs/inode.c > new file mode 100644 > index 0000000..5808d90 > --- /dev/null > +++ b/fs/imgdafs/inode.c > @@ -0,0 +1,843 @@ > +/* > + * 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 "imgdafs.h" > + > +static int fscall(int in_system_call, int in_arg1, int in_arg2, int in_arg3, > + int in_arg4, int in_arg5, int *fserrno) > +{ > + register int arg1 asm("D1Ar1") = in_arg1; > + register int arg2 asm("D0Ar2") = in_arg2; > + register int arg3 asm("D1Ar3") = in_arg3; > + register int arg4 asm("D0Ar4") = in_arg4; > + register int arg5 asm("D1Ar5") = in_arg5; > + register int system_call asm("D0Ar6") = in_system_call; > + register int result asm("D0Re0"); > + register int errno asm("D1Re0"); > + > + asm volatile ( > + "MSETL [A0StP++], %7,%5,%3\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"); > + > + if (fserrno) > + *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; > + int fserrno; > + memset(p, 0, sizeof(*p)); > + > + if (fd >= 0) { > + ret = fscall(DA_OP_FSTAT, fd, (int)p, 0, 0, 0, &fserrno); > + 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, > + &fserrno); > + 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, NULL); > +} > + > +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 *fserrno) > +{ > + 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, > + fserrno); > +} > + > +static void close_dir(int handle) > +{ > + fscall(DA_OP_FINDCLOSE, handle, 0, 0, 0, 0, NULL); > +} > + > +static int read_dir(int handle, struct da_finddata *finddata) > +{ > + return fscall(DA_OP_FINDNEXT, handle, (int)finddata, 0, 0, 0, NULL); > +} > + > +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; > + int fserrno; > + 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, &fserrno); > + __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 cpu; > + > + 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_each_possible_cpu(cpu) { > + u8 hwthread = cpu_2_hwthread_id[cpu]; > + 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, NULL); > + __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; > + int fserrno; > + > + n = fscall(DA_OP_PREAD, fd, (int)buf, len, (int)*offset, 0, &fserrno); > + > + if (n < 0) > + return -fserrno; > + > + return n; > +} > + > +static int write_file(int fd, unsigned long long *offset, const char *buf, > + int len) > +{ > + int n; > + int fserrno; > + > + n = fscall(DA_OP_PWRITE, fd, (int)buf, len, (int)*offset, 0, &fserrno); > + > + 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; > +} > + > +static 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; > +} > + > +static 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); > + > + i_uid_write(ino, st.st_uid); > + i_gid_write(ino, 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 cpu; > + > + 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_each_possible_cpu(cpu) { > + u8 hwthread = cpu_2_hwthread_id[cpu]; > + creat_flags |= (1 << (DA_O_AFFINITY_SHIFT + hwthread)); > + } > + > + fd = fscall(DA_OP_OPEN, (int)name, creat_flags, damode, strlen(name), > + 0, NULL); > + 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); > +} > + > +static 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; > +} > + > +static int dafs_unlink(struct inode *ino, struct dentry *dentry) > +{ > + char *file; > + int err; > + int fserrno; > + > + file = dentry_name(dentry); > + if (file == NULL) > + return -ENOMEM; > + > + err = fscall(DA_OP_UNLINK, (int)file, 0, 0, 0, 0, &fserrno); > + __putname(file); > + if (err) > + return -fserrno; > + return 0; > +} > + > +static int do_mkdir(const char *file, int mode) > +{ > + int err; > + int fserrno; > + > + err = fscall(DA_OP_MKDIR, (int)file, mode, strlen(file), 0, 0, > + &fserrno); > + if (err) > + return -fserrno; > + return 0; > +} > + > +static 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; > + int fserrno; > + > + err = fscall(DA_OP_RMDIR, (int)file, strlen(file), 0, 0, 0, &fserrno); > + if (err) > + return -fserrno; > + return 0; > +} > + > +static 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; > +} > + > +static 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 = "imgdafs", > + .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"); > -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html