diff -Naur -X exclude-files ac_cur/arch/um/fs/hostfs/Makefile ac/arch/um/fs/hostfs/Makefile --- ac_cur/arch/um/fs/hostfs/Makefile Sat Aug 4 22:01:03 2001 +++ ac/arch/um/fs/hostfs/Makefile Sun Aug 5 12:53:31 2001 @@ -3,23 +3,35 @@ # Licensed under the GPL # +# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino +# to __st_ino. It stayed in the same place, so as long as the correct name +# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa. + +STAT64_INO_FIELD := __st_ino + +HOST_VER := $(shell uname -r | sed 's/^\(2\.[0-9]\)\..*/\1/') + +ifeq ($(HOST_VER), 2.2) + STAT64_INO_FIELD := st_ino +endif + EXTRA_CFLAGS += -I../../include USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) +USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) \ + -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD) O_TARGET := -obj-y := +obj-y = +obj-m = + +CFLAGS_hostfs_kern.o := $(CFLAGS) +CFLAGS_hostfs_user.o := $(USER_CFLAGS) ifneq ($(CONFIG_HOSTFS), n) O_TARGET := hostfs.o - obj-y := hostfs_kern.o hostfs_user.o - CFLAGS_hostfs_kern.o := $(CFLAGS) - CFLAGS_hostfs_user.o := $(USER_CFLAGS) endif -ifeq ($(CONFIG_HOSTFS), m) - obj-m := $(O_TARGET) -endif +obj-$(CONFIG_HOSTFS) += hostfs_kern.o hostfs_user.o override CFLAGS = diff -Naur -X exclude-files ac_cur/arch/um/fs/hostfs/hostfs.h ac/arch/um/fs/hostfs/hostfs.h --- ac_cur/arch/um/fs/hostfs/hostfs.h Sat Aug 4 22:01:03 2001 +++ ac/arch/um/fs/hostfs/hostfs.h Sun Aug 5 12:53:31 2001 @@ -47,7 +47,8 @@ extern int open_file(char *path, int r, int w); extern int file_type(const char *path, int *rdev); extern void *open_dir(char *path, int *err_out); -extern char *read_dir(void *stream, unsigned long long *pos, int *len_out); +extern char *read_dir(void *stream, unsigned long long *pos, + unsigned long long *ino_out, int *len_out); extern void close_file(void *stream); extern void close_dir(void *stream); extern int read_file(int fd, unsigned long long *offset, char *buf, int len); diff -Naur -X exclude-files ac_cur/arch/um/fs/hostfs/hostfs_kern.c ac/arch/um/fs/hostfs/hostfs_kern.c --- ac_cur/arch/um/fs/hostfs/hostfs_kern.c Sat Aug 4 22:01:03 2001 +++ ac/arch/um/fs/hostfs/hostfs_kern.c Sun Aug 5 12:53:31 2001 @@ -17,6 +17,8 @@ #include "kern.h" #include "user_util.h" +#define file_hostfs_i(file) (&(file)->f_dentry->d_inode->u.hostfs_i) + int hostfs_d_delete(struct dentry *dentry) { return(1); @@ -45,7 +47,8 @@ len += parent->d_name.len + 1; parent = parent->d_parent; } - root = parent->d_inode->u.generic_ip; + + root = parent->d_inode->u.hostfs_i.host_filename; len += strlen(root); name = kmalloc(len + extra + 1, GFP_KERNEL); if(name == NULL) return(NULL); @@ -112,8 +115,10 @@ void hostfs_delete_inode(struct inode *ino) { - if(ino->u.generic_ip) kfree(ino->u.generic_ip); - ino->u.generic_ip = NULL; + if(ino->u.hostfs_i.host_filename) kfree(ino->u.hostfs_i.host_filename); + ino->u.hostfs_i.host_filename = NULL; + if(ino->u.hostfs_i.fd != -1) close_file(&ino->u.hostfs_i.fd); + ino->u.hostfs_i.mode = 0; clear_inode(ino); } @@ -130,10 +135,10 @@ long long f_files; long long f_ffree; - err = do_statfs(sb->s_root->d_inode->u.generic_ip, &sf->f_bsize, - &f_blocks, &f_bfree, &f_bavail, &f_files, &f_ffree, - &sf->f_fsid, sizeof(sf->f_fsid), &sf->f_namelen, - sf->f_spare); + err = do_statfs(sb->s_root->d_inode->u.hostfs_i.host_filename, + &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, + &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), + &sf->f_namelen, sf->f_spare); if(err) return(err); sf->f_blocks = f_blocks; sf->f_bfree = f_bfree; @@ -150,39 +155,11 @@ statfs: hostfs_statfs, }; -ssize_t hostfs_write(struct file *file, const char *buf, size_t len, - loff_t *start) -{ - unsigned long page = __get_free_page(GFP_KERNEL); - int ret, one_len, n; - - if(page == 0) return(-ENOMEM); - ret = 0; - while(len > 0){ - one_len = (len < PAGE_SIZE) ? len : PAGE_SIZE; - if(copy_from_user((void *) page, &buf[ret], one_len)){ - ret = -EFAULT; - break; - } - n = write_file((int) file->private_data, start, (void *) page, - one_len, file->f_flags & O_APPEND); - if(n < 0){ - ret = n; - break; - } - ret += n; - len -= n; - if(n < one_len) break; - } - free_page(page); - return(ret); -} - int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) { void *dir; char *name; - unsigned long long next; + unsigned long long next, ino; int error, len; name = dentry_name(file->f_dentry, 0); @@ -191,10 +168,9 @@ kfree(name); if(dir == NULL) return(-error); next = file->f_pos; - while((name = read_dir(dir, &next, &len)) != NULL){ + while((name = read_dir(dir, &next, &ino, &len)) != NULL){ error = (*filldir)(ent, name, len, file->f_pos, - file->f_dentry->d_inode->i_ino, - DT_UNKNOWN); + ino, DT_UNKNOWN); if(error) break; file->f_pos = next; } @@ -218,16 +194,25 @@ int hostfs_file_open(struct inode *ino, struct file *file) { char *name; - int r = 0, w = 0, fd; + int mode = 0, r = 0, w = 0, fd; + + mode = file->f_mode & (FMODE_READ | FMODE_WRITE); + if((mode & ino->u.hostfs_i.mode) == mode) return(0); - if(file->f_mode & FMODE_READ) r = 1; - if(file->f_mode & FMODE_WRITE) w = 1; + if(ino->u.hostfs_i.fd != -1){ + close_file(&ino->u.hostfs_i.fd); + ino->u.hostfs_i.fd = -1; + } + ino->u.hostfs_i.mode |= mode; + if(ino->u.hostfs_i.mode & FMODE_READ) r = 1; + if(ino->u.hostfs_i.mode & FMODE_WRITE) w = 1; + if(w) r = 1; name = dentry_name(file->f_dentry, 0); if(name == NULL) return(-ENOMEM); fd = open_file(name, r, w); kfree(name); if(fd < 0) return(fd); - file->private_data = (void *) fd; + file_hostfs_i(file)->fd = fd; return(0); } @@ -236,12 +221,6 @@ return(0); } -int hostfs_file_release(struct inode *ino, struct file *file) -{ - close_file(file->private_data); - return(0); -} - int hostfs_dir_release(struct inode *ino, struct file *file) { return(0); @@ -258,14 +237,44 @@ return(-EINVAL); } +#ifdef notdef +ssize_t hostfs_write(struct file *file, const char *buf, size_t len, + loff_t *start) +{ + unsigned long page = __get_free_page(GFP_KERNEL); + int ret, one_len, n; + + if(page == 0) return(-ENOMEM); + ret = 0; + while(len > 0){ + one_len = (len < PAGE_SIZE) ? len : PAGE_SIZE; + if(copy_from_user((void *) page, &buf[ret], one_len)){ + ret = -EFAULT; + break; + } + n = write_file(file_hostfs_i(file)->fd, start, (void *) page, + one_len, file->f_flags & O_APPEND); + if(n < 0){ + ret = n; + break; + } + ret += n; + len -= n; + if(n < one_len) break; + } + free_page(page); + return(ret); +} +#endif + static struct file_operations hostfs_file_fops = { owner: NULL, read: generic_file_read, - write: hostfs_write, + write: generic_file_write, poll: hostfs_poll, mmap: generic_file_mmap, open: hostfs_file_open, - release: hostfs_file_release, + release: NULL, fsync: hostfs_fsync, fasync: hostfs_fasync }; @@ -283,8 +292,37 @@ int hostfs_writepage(struct page *page) { - not_implemented(); - return(-EINVAL); + 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(inode->u.hostfs_i.fd, &base, buffer, count, 0); + if(err != count){ + ClearPageUptodate(page); + goto out; + } + + if (base > inode->i_size) + inode->i_size = base; + + if (PageError(page)) + ClearPageError(page); + + out: + kunmap(page); + + UnlockPage(page); + return err; } int hostfs_readpage(struct file *file, struct page *page) @@ -295,31 +333,65 @@ start = (long long) page->index << PAGE_CACHE_SHIFT; buffer = kmap(page); - err = read_file((int) file->private_data, &start, buffer, + err = read_file(file_hostfs_i(file)->fd, &start, buffer, PAGE_CACHE_SIZE); - if(err > 0){ - flush_dcache_page(page); - SetPageUptodate(page); - if (PageError(page)) ClearPageError(page); - err = 0; - } + if(err < 0) goto out; + + flush_dcache_page(page); + SetPageUptodate(page); + if (PageError(page)) ClearPageError(page); + err = 0; + out: kunmap(page); UnlockPage(page); return(err); } int hostfs_prepare_write(struct file *file, struct page *page, unsigned from, - unsigned to) + unsigned to) { - not_implemented(); - return(-EINVAL); + char *buffer; + long long start; + int err; + + start = (long long) page->index << PAGE_CACHE_SHIFT; + buffer = kmap(page); + if(from != 0){ + err = read_file(file_hostfs_i(file)->fd, &start, buffer, + from); + if(err < 0) goto out; + } + if(to != PAGE_CACHE_SIZE){ + start += to; + err = read_file(file_hostfs_i(file)->fd, &start, buffer + to, + PAGE_CACHE_SIZE - to); + if(err < 0) goto out; + } + err = 0; + out: + kunmap(page); + return(err); } int hostfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to) { - not_implemented(); - return(-EINVAL); + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + char *buffer; + long long start; + int err = 0; + + start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; + buffer = kmap(page); + err = write_file(file_hostfs_i(file)->fd, &start, buffer + from, + to - from, 0); + if(err > 0) err = 0; + if(!err && (start > inode->i_size)) + inode->i_size = start; + + kunmap(page); + return(err); } static struct address_space_operations hostfs_aops = { @@ -338,7 +410,9 @@ inode = get_empty_inode(); if(inode == NULL) return(NULL); - inode->u.generic_ip = NULL; + inode->u.hostfs_i.host_filename = NULL; + inode->u.hostfs_i.fd = -1; + inode->u.hostfs_i.mode = 0; if(error) *error = 0; insert_inode_hash(inode); if(dentry){ @@ -675,7 +749,7 @@ kfree(name); return(NULL); } - root_inode->u.generic_ip = name; + root_inode->u.hostfs_i.host_filename = name; sb->s_root = d_alloc_root(root_inode); if(read_inode(root_inode)){ iput(root_inode); diff -Naur -X exclude-files ac_cur/arch/um/fs/hostfs/hostfs_user.c ac/arch/um/fs/hostfs/hostfs_user.c --- ac_cur/arch/um/fs/hostfs/hostfs_user.c Sat Aug 4 22:01:03 2001 +++ ac/arch/um/fs/hostfs/hostfs_user.c Sun Aug 5 12:53:31 2001 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,11 @@ if(lstat64(path, &buf) < 0) return(-errno); if(dev_out != NULL) *dev_out = buf.st_dev; - if(inode_out != NULL) *inode_out = buf.st_ino; + + /* See the Makefile for why STAT64_INO_FIELD is passed in + * by the build + */ + if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD; if(mode_out != NULL) *mode_out = buf.st_mode; if(nlink_out != NULL) *nlink_out = buf.st_nlink; if(uid_out != NULL) *uid_out = buf.st_uid; @@ -51,8 +56,9 @@ else if(S_ISLNK(buf.st_mode)) return(HOSTFS_SYMLINK); else if(S_ISCHR(buf.st_mode)) return(HOSTFS_CHARDEV); else if(S_ISBLK(buf.st_mode)) return(HOSTFS_BLOCDEV); - else if(S_ISFIFO(buf.st_mode)) return(HOSTFS_FIFO); - else if(S_ISSOCK(buf.st_mode)) return(HOSTFS_SOCK); + else if(S_ISFIFO(buf.st_mode))return(HOSTFS_FIFO); + else if(S_ISSOCK(buf.st_mode))return(HOSTFS_SOCK); + else return(HOSTFS_FILE); } @@ -90,7 +96,8 @@ return(dir); } -char *read_dir(void *stream, unsigned long long *pos, int *len_out) +char *read_dir(void *stream, unsigned long long *pos, + unsigned long long *ino_out, int *len_out) { DIR *dir = stream; struct dirent *ent; @@ -99,6 +106,7 @@ ent = readdir(dir); if(ent == NULL) return(NULL); *len_out = strlen(ent->d_name); + *ino_out = ent->d_ino; *pos = telldir(dir); return(ent->d_name); } @@ -146,7 +154,7 @@ void close_file(void *stream) { - close((int) stream); + close(*((int *) stream)); } void close_dir(void *stream) @@ -299,8 +307,9 @@ return(0); } -int do_statfs(char *root, long *bsize_out, long long *blocks_out, long long *bfree_out, - long long *bavail_out, long long *files_out, long long *ffree_out, +int do_statfs(char *root, long *bsize_out, long long *blocks_out, + long long *bfree_out, long long *bavail_out, + long long *files_out, long long *ffree_out, void *fsid_out, int fsid_size, long *namelen_out, long *spare_out) { diff -Naur -X exclude-files ac_cur/include/linux/fs.h ac/include/linux/fs.h --- ac_cur/include/linux/fs.h Sat Aug 4 22:03:53 2001 +++ ac/include/linux/fs.h Sun Aug 5 12:57:32 2001 @@ -324,6 +324,7 @@ #include #include #include +#include /* * Attribute flags. These should be or-ed together to figure out what @@ -506,6 +507,7 @@ struct socket socket_i; struct usbdev_inode_info usbdev_i; struct jffs2_inode_info jffs2_i; + struct hostfs_inode_info hostfs_i; void *generic_ip; } u; }; diff -Naur -X exclude-files ac_cur/include/linux/hostfs_fs_i.h ac/include/linux/hostfs_fs_i.h --- ac_cur/include/linux/hostfs_fs_i.h Wed Dec 31 19:00:00 1969 +++ ac/include/linux/hostfs_fs_i.h Sun Aug 5 12:53:56 2001 @@ -0,0 +1,21 @@ +#ifndef _HOSTFS_FS_I +#define _HOSTFS_FS_I + +struct hostfs_inode_info { + char *host_filename; + int fd; + int mode; +}; + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */