X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fhostfs%2Fhostfs_kern.c;h=4e8bb2fba0489767e940303698b4f0891d3575f9;hb=5822b7faca709c03a59c2929005bfe9caffe6592;hp=e6c63d9cac7bd473f8b7dd00734eea0682cf9658;hpb=ffa0aea681a5f3c8aecbb86f1cfd3486043805de;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index e6c63d9..4e8bb2f 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -8,22 +8,18 @@ #include #include -#include #include #include #include #include #include #include -#include #include #include #include #include "hostfs.h" #include "kern_util.h" #include "kern.h" -#include "user_util.h" -#include "2_5compat.h" #include "init.h" struct hostfs_inode_info { @@ -38,7 +34,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) return(list_entry(inode, struct hostfs_inode_info, vfs_inode)); } -#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode) +#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) int hostfs_d_delete(struct dentry *dentry) { @@ -50,14 +46,14 @@ struct dentry_operations hostfs_dentry_ops = { }; /* Changed in hostfs_args before the kernel starts running */ -static char *root_ino = "/"; +static char *root_ino = ""; static int append = 0; #define HOSTFS_SUPER_MAGIC 0x00c0ffee -static struct inode_operations hostfs_iops; -static struct inode_operations hostfs_dir_iops; -static struct address_space_operations hostfs_link_aops; +static const struct inode_operations hostfs_iops; +static const struct inode_operations hostfs_dir_iops; +static const struct address_space_operations hostfs_link_aops; #ifndef MODULE static int __init hostfs_args(char *options, int *add) @@ -151,7 +147,7 @@ static int read_name(struct inode *ino, char *name) err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, - &ino->i_ctime, &i_blksize, &i_blocks); + &ino->i_ctime, &i_blksize, &i_blocks, -1); if(err) return(err); @@ -159,10 +155,7 @@ static int read_name(struct inode *ino, char *name) ino->i_mode = i_mode; ino->i_nlink = i_nlink; ino->i_size = i_size; - ino->i_blksize = i_blksize; ino->i_blocks = i_blocks; - if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid())) - ino->i_uid = 0; return(0); } @@ -244,7 +237,7 @@ static int read_inode(struct inode *ino) return(err); } -int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) +int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) { /* do_statfs uses struct statfs64 internally, but the linux kernel * struct statfs still has 32-bit versions for most of these fields, @@ -257,7 +250,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) long long f_files; long long f_ffree; - err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, + err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->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); @@ -288,6 +281,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb) static void hostfs_delete_inode(struct inode *inode) { + truncate_inode_pages(&inode->i_data, 0); if(HOSTFS_I(inode)->fd != -1) { close_file(&HOSTFS_I(inode)->fd); HOSTFS_I(inode)->fd = -1; @@ -297,8 +291,7 @@ static void hostfs_delete_inode(struct inode *inode) static void hostfs_destroy_inode(struct inode *inode) { - if(HOSTFS_I(inode)->host_filename) - kfree(HOSTFS_I(inode)->host_filename); + kfree(HOSTFS_I(inode)->host_filename); /*XXX: This should not happen, probably. The check is here for * additional safety.*/ @@ -315,7 +308,7 @@ static void hostfs_read_inode(struct inode *inode) read_inode(inode); } -static struct super_operations hostfs_sbops = { +static const struct super_operations hostfs_sbops = { .alloc_inode = hostfs_alloc_inode, .drop_inode = generic_delete_inode, .delete_inode = hostfs_delete_inode, @@ -331,7 +324,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) unsigned long long next, ino; int error, len; - name = dentry_name(file->f_dentry, 0); + name = dentry_name(file->f_path.dentry, 0); if(name == NULL) return(-ENOMEM); dir = open_dir(name, &error); kfree(name); @@ -372,7 +365,7 @@ int hostfs_file_open(struct inode *ino, struct file *file) if(w) r = 1; - name = dentry_name(file->f_dentry, 0); + name = dentry_name(file->f_path.dentry, 0); if(name == NULL) return(-ENOMEM); @@ -386,25 +379,23 @@ int hostfs_file_open(struct inode *ino, struct file *file) int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) { - return(0); + return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); } -static struct file_operations hostfs_file_fops = { +static const struct file_operations hostfs_file_fops = { .llseek = generic_file_llseek, - .read = generic_file_read, + .read = do_sync_read, .sendfile = generic_file_sendfile, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, - .readv = generic_file_readv, - .writev = generic_file_writev, - .write = generic_file_write, + .write = do_sync_write, .mmap = generic_file_mmap, .open = hostfs_file_open, .release = NULL, .fsync = hostfs_fsync, }; -static struct file_operations hostfs_dir_fops = { +static const struct file_operations hostfs_dir_fops = { .llseek = generic_file_llseek, .readdir = hostfs_readdir, .read = generic_read_dir, @@ -506,11 +497,16 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from, long long start; int err = 0; - start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; + 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); if(err > 0) err = 0; + + /* Actually, if !err, write_file has added to-from to start, so, despite + * the appearance, we are comparing i_size against the _last_ written + * location, as we should. */ + if(!err && (start > inode->i_size)) inode->i_size = start; @@ -518,7 +514,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from, return(err); } -static struct address_space_operations hostfs_aops = { +static const struct address_space_operations hostfs_aops = { .writepage = hostfs_writepage, .readpage = hostfs_readpage, .set_page_dirty = __set_page_dirty_nobuffers, @@ -758,7 +754,7 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) goto out_put; init_special_inode(inode, mode, dev); - err = do_mknod(name, mode, dev); + err = do_mknod(name, mode, MAJOR(dev), MINOR(dev)); if(err) goto out_free; @@ -796,11 +792,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, return(err); } -void hostfs_truncate(struct inode *ino) -{ - not_implemented(); -} - int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) { char *name; @@ -829,6 +820,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) char *name; int err; + int fd = HOSTFS_I(dentry->d_inode)->fd; + err = inode_change_ok(dentry->d_inode, attr); if (err) return err; @@ -842,16 +835,10 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) attrs.ia_mode = attr->ia_mode; } if(attr->ia_valid & ATTR_UID){ - if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && - (attr->ia_uid == 0)) - attr->ia_uid = getuid(); attrs.ia_valid |= HOSTFS_ATTR_UID; attrs.ia_uid = attr->ia_uid; } if(attr->ia_valid & ATTR_GID){ - if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && - (attr->ia_gid == 0)) - attr->ia_gid = getgid(); attrs.ia_valid |= HOSTFS_ATTR_GID; attrs.ia_gid = attr->ia_gid; } @@ -879,7 +866,7 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) } name = dentry_name(dentry, 0); if(name == NULL) return(-ENOMEM); - err = set_attr(name, &attrs); + err = set_attr(name, &attrs, fd); kfree(name); if(err) return(err); @@ -894,7 +881,7 @@ int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, return(0); } -static struct inode_operations hostfs_iops = { +static const struct inode_operations hostfs_iops = { .create = hostfs_create, .link = hostfs_link, .unlink = hostfs_unlink, @@ -903,13 +890,12 @@ static struct inode_operations hostfs_iops = { .rmdir = hostfs_rmdir, .mknod = hostfs_mknod, .rename = hostfs_rename, - .truncate = hostfs_truncate, .permission = hostfs_permission, .setattr = hostfs_setattr, .getattr = hostfs_getattr, }; -static struct inode_operations hostfs_dir_iops = { +static const struct inode_operations hostfs_dir_iops = { .create = hostfs_create, .lookup = hostfs_lookup, .link = hostfs_link, @@ -919,7 +905,6 @@ static struct inode_operations hostfs_dir_iops = { .rmdir = hostfs_rmdir, .mknod = hostfs_mknod, .rename = hostfs_rename, - .truncate = hostfs_truncate, .permission = hostfs_permission, .setattr = hostfs_setattr, .getattr = hostfs_getattr, @@ -928,10 +913,8 @@ static struct inode_operations hostfs_dir_iops = { int hostfs_link_readpage(struct file *file, struct page *page) { char *buffer, *name; - long long start; int err; - start = page->index << PAGE_CACHE_SHIFT; buffer = kmap(page); name = inode_name(page->mapping->host, 0); if(name == NULL) return(-ENOMEM); @@ -950,14 +933,14 @@ int hostfs_link_readpage(struct file *file, struct page *page) return(err); } -static struct address_space_operations hostfs_link_aops = { +static const struct address_space_operations hostfs_link_aops = { .readpage = hostfs_link_readpage, }; static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) { struct inode *root_inode; - char *name, *data = d; + char *host_root_path, *req_root = d; int err; sb->s_blocksize = 1024; @@ -965,15 +948,17 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) sb->s_magic = HOSTFS_SUPER_MAGIC; sb->s_op = &hostfs_sbops; - if((data == NULL) || (*data == '\0')) - data = root_ino; + /* NULL is printed as by sprintf: avoid that. */ + if (req_root == NULL) + req_root = ""; err = -ENOMEM; - name = kmalloc(strlen(data) + 1, GFP_KERNEL); - if(name == NULL) + host_root_path = kmalloc(strlen(root_ino) + 1 + + strlen(req_root) + 1, GFP_KERNEL); + if(host_root_path == NULL) goto out; - strcpy(name, data); + sprintf(host_root_path, "%s/%s", root_ino, req_root); root_inode = iget(sb, 0); if(root_inode == NULL) @@ -983,7 +968,10 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) if(err) goto out_put; - HOSTFS_I(root_inode)->host_filename = name; + HOSTFS_I(root_inode)->host_filename = host_root_path; + /* Avoid that in the error path, iput(root_inode) frees again + * host_root_path through hostfs_destroy_inode! */ + host_root_path = NULL; err = -ENOMEM; sb->s_root = d_alloc_root(root_inode); @@ -991,24 +979,28 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) goto out_put; err = read_inode(root_inode); - if(err) - goto out_put; + if(err){ + /* No iput in this case because the dput does that for us */ + dput(sb->s_root); + sb->s_root = NULL; + goto out; + } return(0); out_put: - iput(root_inode); + iput(root_inode); out_free: - kfree(name); + kfree(host_root_path); out: return(err); } -static struct super_block *hostfs_read_sb(struct file_system_type *type, - int flags, const char *dev_name, - void *data) +static int hostfs_read_sb(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); + return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt); } static struct file_system_type hostfs_type = {