1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 3*1da177e4SLinus Torvalds * Licensed under the GPL 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds * Ported the filesystem routines to 2.5. 6*1da177e4SLinus Torvalds * 2003-02-10 Petr Baudis <pasky@ucw.cz> 7*1da177e4SLinus Torvalds */ 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds #include <linux/stddef.h> 10*1da177e4SLinus Torvalds #include <linux/fs.h> 11*1da177e4SLinus Torvalds #include <linux/version.h> 12*1da177e4SLinus Torvalds #include <linux/module.h> 13*1da177e4SLinus Torvalds #include <linux/init.h> 14*1da177e4SLinus Torvalds #include <linux/slab.h> 15*1da177e4SLinus Torvalds #include <linux/pagemap.h> 16*1da177e4SLinus Torvalds #include <linux/blkdev.h> 17*1da177e4SLinus Torvalds #include <linux/list.h> 18*1da177e4SLinus Torvalds #include <linux/root_dev.h> 19*1da177e4SLinus Torvalds #include <linux/statfs.h> 20*1da177e4SLinus Torvalds #include <linux/kdev_t.h> 21*1da177e4SLinus Torvalds #include <asm/uaccess.h> 22*1da177e4SLinus Torvalds #include "hostfs.h" 23*1da177e4SLinus Torvalds #include "kern_util.h" 24*1da177e4SLinus Torvalds #include "kern.h" 25*1da177e4SLinus Torvalds #include "user_util.h" 26*1da177e4SLinus Torvalds #include "2_5compat.h" 27*1da177e4SLinus Torvalds #include "init.h" 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds struct hostfs_inode_info { 30*1da177e4SLinus Torvalds char *host_filename; 31*1da177e4SLinus Torvalds int fd; 32*1da177e4SLinus Torvalds int mode; 33*1da177e4SLinus Torvalds struct inode vfs_inode; 34*1da177e4SLinus Torvalds }; 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) 37*1da177e4SLinus Torvalds { 38*1da177e4SLinus Torvalds return(list_entry(inode, struct hostfs_inode_info, vfs_inode)); 39*1da177e4SLinus Torvalds } 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode) 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds int hostfs_d_delete(struct dentry *dentry) 44*1da177e4SLinus Torvalds { 45*1da177e4SLinus Torvalds return(1); 46*1da177e4SLinus Torvalds } 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds struct dentry_operations hostfs_dentry_ops = { 49*1da177e4SLinus Torvalds .d_delete = hostfs_d_delete, 50*1da177e4SLinus Torvalds }; 51*1da177e4SLinus Torvalds 52*1da177e4SLinus Torvalds /* Changed in hostfs_args before the kernel starts running */ 53*1da177e4SLinus Torvalds static char *root_ino = "/"; 54*1da177e4SLinus Torvalds static int append = 0; 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds #define HOSTFS_SUPER_MAGIC 0x00c0ffee 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds static struct inode_operations hostfs_iops; 59*1da177e4SLinus Torvalds static struct inode_operations hostfs_dir_iops; 60*1da177e4SLinus Torvalds static struct address_space_operations hostfs_link_aops; 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds #ifndef MODULE 63*1da177e4SLinus Torvalds static int __init hostfs_args(char *options, int *add) 64*1da177e4SLinus Torvalds { 65*1da177e4SLinus Torvalds char *ptr; 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds ptr = strchr(options, ','); 68*1da177e4SLinus Torvalds if(ptr != NULL) 69*1da177e4SLinus Torvalds *ptr++ = '\0'; 70*1da177e4SLinus Torvalds if(*options != '\0') 71*1da177e4SLinus Torvalds root_ino = options; 72*1da177e4SLinus Torvalds 73*1da177e4SLinus Torvalds options = ptr; 74*1da177e4SLinus Torvalds while(options){ 75*1da177e4SLinus Torvalds ptr = strchr(options, ','); 76*1da177e4SLinus Torvalds if(ptr != NULL) 77*1da177e4SLinus Torvalds *ptr++ = '\0'; 78*1da177e4SLinus Torvalds if(*options != '\0'){ 79*1da177e4SLinus Torvalds if(!strcmp(options, "append")) 80*1da177e4SLinus Torvalds append = 1; 81*1da177e4SLinus Torvalds else printf("hostfs_args - unsupported option - %s\n", 82*1da177e4SLinus Torvalds options); 83*1da177e4SLinus Torvalds } 84*1da177e4SLinus Torvalds options = ptr; 85*1da177e4SLinus Torvalds } 86*1da177e4SLinus Torvalds return(0); 87*1da177e4SLinus Torvalds } 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds __uml_setup("hostfs=", hostfs_args, 90*1da177e4SLinus Torvalds "hostfs=<root dir>,<flags>,...\n" 91*1da177e4SLinus Torvalds " This is used to set hostfs parameters. The root directory argument\n" 92*1da177e4SLinus Torvalds " is used to confine all hostfs mounts to within the specified directory\n" 93*1da177e4SLinus Torvalds " tree on the host. If this isn't specified, then a user inside UML can\n" 94*1da177e4SLinus Torvalds " mount anything on the host that's accessible to the user that's running\n" 95*1da177e4SLinus Torvalds " it.\n" 96*1da177e4SLinus Torvalds " The only flag currently supported is 'append', which specifies that all\n" 97*1da177e4SLinus Torvalds " files opened by hostfs will be opened in append mode.\n\n" 98*1da177e4SLinus Torvalds ); 99*1da177e4SLinus Torvalds #endif 100*1da177e4SLinus Torvalds 101*1da177e4SLinus Torvalds static char *dentry_name(struct dentry *dentry, int extra) 102*1da177e4SLinus Torvalds { 103*1da177e4SLinus Torvalds struct dentry *parent; 104*1da177e4SLinus Torvalds char *root, *name; 105*1da177e4SLinus Torvalds int len; 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds len = 0; 108*1da177e4SLinus Torvalds parent = dentry; 109*1da177e4SLinus Torvalds while(parent->d_parent != parent){ 110*1da177e4SLinus Torvalds len += parent->d_name.len + 1; 111*1da177e4SLinus Torvalds parent = parent->d_parent; 112*1da177e4SLinus Torvalds } 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds root = HOSTFS_I(parent->d_inode)->host_filename; 115*1da177e4SLinus Torvalds len += strlen(root); 116*1da177e4SLinus Torvalds name = kmalloc(len + extra + 1, GFP_KERNEL); 117*1da177e4SLinus Torvalds if(name == NULL) return(NULL); 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds name[len] = '\0'; 120*1da177e4SLinus Torvalds parent = dentry; 121*1da177e4SLinus Torvalds while(parent->d_parent != parent){ 122*1da177e4SLinus Torvalds len -= parent->d_name.len + 1; 123*1da177e4SLinus Torvalds name[len] = '/'; 124*1da177e4SLinus Torvalds strncpy(&name[len + 1], parent->d_name.name, 125*1da177e4SLinus Torvalds parent->d_name.len); 126*1da177e4SLinus Torvalds parent = parent->d_parent; 127*1da177e4SLinus Torvalds } 128*1da177e4SLinus Torvalds strncpy(name, root, strlen(root)); 129*1da177e4SLinus Torvalds return(name); 130*1da177e4SLinus Torvalds } 131*1da177e4SLinus Torvalds 132*1da177e4SLinus Torvalds static char *inode_name(struct inode *ino, int extra) 133*1da177e4SLinus Torvalds { 134*1da177e4SLinus Torvalds struct dentry *dentry; 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias); 137*1da177e4SLinus Torvalds return(dentry_name(dentry, extra)); 138*1da177e4SLinus Torvalds } 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds static int read_name(struct inode *ino, char *name) 141*1da177e4SLinus Torvalds { 142*1da177e4SLinus Torvalds /* The non-int inode fields are copied into ints by stat_file and 143*1da177e4SLinus Torvalds * then copied into the inode because passing the actual pointers 144*1da177e4SLinus Torvalds * in and having them treated as int * breaks on big-endian machines 145*1da177e4SLinus Torvalds */ 146*1da177e4SLinus Torvalds int err; 147*1da177e4SLinus Torvalds int i_mode, i_nlink, i_blksize; 148*1da177e4SLinus Torvalds unsigned long long i_size; 149*1da177e4SLinus Torvalds unsigned long long i_ino; 150*1da177e4SLinus Torvalds unsigned long long i_blocks; 151*1da177e4SLinus Torvalds 152*1da177e4SLinus Torvalds err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, 153*1da177e4SLinus Torvalds &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, 154*1da177e4SLinus Torvalds &ino->i_ctime, &i_blksize, &i_blocks); 155*1da177e4SLinus Torvalds if(err) 156*1da177e4SLinus Torvalds return(err); 157*1da177e4SLinus Torvalds 158*1da177e4SLinus Torvalds ino->i_ino = i_ino; 159*1da177e4SLinus Torvalds ino->i_mode = i_mode; 160*1da177e4SLinus Torvalds ino->i_nlink = i_nlink; 161*1da177e4SLinus Torvalds ino->i_size = i_size; 162*1da177e4SLinus Torvalds ino->i_blksize = i_blksize; 163*1da177e4SLinus Torvalds ino->i_blocks = i_blocks; 164*1da177e4SLinus Torvalds if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid())) 165*1da177e4SLinus Torvalds ino->i_uid = 0; 166*1da177e4SLinus Torvalds return(0); 167*1da177e4SLinus Torvalds } 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds static char *follow_link(char *link) 170*1da177e4SLinus Torvalds { 171*1da177e4SLinus Torvalds int len, n; 172*1da177e4SLinus Torvalds char *name, *resolved, *end; 173*1da177e4SLinus Torvalds 174*1da177e4SLinus Torvalds len = 64; 175*1da177e4SLinus Torvalds while(1){ 176*1da177e4SLinus Torvalds n = -ENOMEM; 177*1da177e4SLinus Torvalds name = kmalloc(len, GFP_KERNEL); 178*1da177e4SLinus Torvalds if(name == NULL) 179*1da177e4SLinus Torvalds goto out; 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds n = do_readlink(link, name, len); 182*1da177e4SLinus Torvalds if(n < len) 183*1da177e4SLinus Torvalds break; 184*1da177e4SLinus Torvalds len *= 2; 185*1da177e4SLinus Torvalds kfree(name); 186*1da177e4SLinus Torvalds } 187*1da177e4SLinus Torvalds if(n < 0) 188*1da177e4SLinus Torvalds goto out_free; 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds if(*name == '/') 191*1da177e4SLinus Torvalds return(name); 192*1da177e4SLinus Torvalds 193*1da177e4SLinus Torvalds end = strrchr(link, '/'); 194*1da177e4SLinus Torvalds if(end == NULL) 195*1da177e4SLinus Torvalds return(name); 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds *(end + 1) = '\0'; 198*1da177e4SLinus Torvalds len = strlen(link) + strlen(name) + 1; 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds resolved = kmalloc(len, GFP_KERNEL); 201*1da177e4SLinus Torvalds if(resolved == NULL){ 202*1da177e4SLinus Torvalds n = -ENOMEM; 203*1da177e4SLinus Torvalds goto out_free; 204*1da177e4SLinus Torvalds } 205*1da177e4SLinus Torvalds 206*1da177e4SLinus Torvalds sprintf(resolved, "%s%s", link, name); 207*1da177e4SLinus Torvalds kfree(name); 208*1da177e4SLinus Torvalds kfree(link); 209*1da177e4SLinus Torvalds return(resolved); 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds out_free: 212*1da177e4SLinus Torvalds kfree(name); 213*1da177e4SLinus Torvalds out: 214*1da177e4SLinus Torvalds return(ERR_PTR(n)); 215*1da177e4SLinus Torvalds } 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds static int read_inode(struct inode *ino) 218*1da177e4SLinus Torvalds { 219*1da177e4SLinus Torvalds char *name; 220*1da177e4SLinus Torvalds int err = 0; 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds /* Unfortunately, we are called from iget() when we don't have a dentry 223*1da177e4SLinus Torvalds * allocated yet. 224*1da177e4SLinus Torvalds */ 225*1da177e4SLinus Torvalds if(list_empty(&ino->i_dentry)) 226*1da177e4SLinus Torvalds goto out; 227*1da177e4SLinus Torvalds 228*1da177e4SLinus Torvalds err = -ENOMEM; 229*1da177e4SLinus Torvalds name = inode_name(ino, 0); 230*1da177e4SLinus Torvalds if(name == NULL) 231*1da177e4SLinus Torvalds goto out; 232*1da177e4SLinus Torvalds 233*1da177e4SLinus Torvalds if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){ 234*1da177e4SLinus Torvalds name = follow_link(name); 235*1da177e4SLinus Torvalds if(IS_ERR(name)){ 236*1da177e4SLinus Torvalds err = PTR_ERR(name); 237*1da177e4SLinus Torvalds goto out; 238*1da177e4SLinus Torvalds } 239*1da177e4SLinus Torvalds } 240*1da177e4SLinus Torvalds 241*1da177e4SLinus Torvalds err = read_name(ino, name); 242*1da177e4SLinus Torvalds kfree(name); 243*1da177e4SLinus Torvalds out: 244*1da177e4SLinus Torvalds return(err); 245*1da177e4SLinus Torvalds } 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) 248*1da177e4SLinus Torvalds { 249*1da177e4SLinus Torvalds /* do_statfs uses struct statfs64 internally, but the linux kernel 250*1da177e4SLinus Torvalds * struct statfs still has 32-bit versions for most of these fields, 251*1da177e4SLinus Torvalds * so we convert them here 252*1da177e4SLinus Torvalds */ 253*1da177e4SLinus Torvalds int err; 254*1da177e4SLinus Torvalds long long f_blocks; 255*1da177e4SLinus Torvalds long long f_bfree; 256*1da177e4SLinus Torvalds long long f_bavail; 257*1da177e4SLinus Torvalds long long f_files; 258*1da177e4SLinus Torvalds long long f_ffree; 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, 261*1da177e4SLinus Torvalds &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, 262*1da177e4SLinus Torvalds &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), 263*1da177e4SLinus Torvalds &sf->f_namelen, sf->f_spare); 264*1da177e4SLinus Torvalds if(err) return(err); 265*1da177e4SLinus Torvalds sf->f_blocks = f_blocks; 266*1da177e4SLinus Torvalds sf->f_bfree = f_bfree; 267*1da177e4SLinus Torvalds sf->f_bavail = f_bavail; 268*1da177e4SLinus Torvalds sf->f_files = f_files; 269*1da177e4SLinus Torvalds sf->f_ffree = f_ffree; 270*1da177e4SLinus Torvalds sf->f_type = HOSTFS_SUPER_MAGIC; 271*1da177e4SLinus Torvalds return(0); 272*1da177e4SLinus Torvalds } 273*1da177e4SLinus Torvalds 274*1da177e4SLinus Torvalds static struct inode *hostfs_alloc_inode(struct super_block *sb) 275*1da177e4SLinus Torvalds { 276*1da177e4SLinus Torvalds struct hostfs_inode_info *hi; 277*1da177e4SLinus Torvalds 278*1da177e4SLinus Torvalds hi = kmalloc(sizeof(*hi), GFP_KERNEL); 279*1da177e4SLinus Torvalds if(hi == NULL) 280*1da177e4SLinus Torvalds return(NULL); 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds *hi = ((struct hostfs_inode_info) { .host_filename = NULL, 283*1da177e4SLinus Torvalds .fd = -1, 284*1da177e4SLinus Torvalds .mode = 0 }); 285*1da177e4SLinus Torvalds inode_init_once(&hi->vfs_inode); 286*1da177e4SLinus Torvalds return(&hi->vfs_inode); 287*1da177e4SLinus Torvalds } 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds static void hostfs_delete_inode(struct inode *inode) 290*1da177e4SLinus Torvalds { 291*1da177e4SLinus Torvalds if(HOSTFS_I(inode)->fd != -1) { 292*1da177e4SLinus Torvalds close_file(&HOSTFS_I(inode)->fd); 293*1da177e4SLinus Torvalds HOSTFS_I(inode)->fd = -1; 294*1da177e4SLinus Torvalds } 295*1da177e4SLinus Torvalds clear_inode(inode); 296*1da177e4SLinus Torvalds } 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds static void hostfs_destroy_inode(struct inode *inode) 299*1da177e4SLinus Torvalds { 300*1da177e4SLinus Torvalds if(HOSTFS_I(inode)->host_filename) 301*1da177e4SLinus Torvalds kfree(HOSTFS_I(inode)->host_filename); 302*1da177e4SLinus Torvalds 303*1da177e4SLinus Torvalds /*XXX: This should not happen, probably. The check is here for 304*1da177e4SLinus Torvalds * additional safety.*/ 305*1da177e4SLinus Torvalds if(HOSTFS_I(inode)->fd != -1) { 306*1da177e4SLinus Torvalds close_file(&HOSTFS_I(inode)->fd); 307*1da177e4SLinus Torvalds printk(KERN_DEBUG "Closing host fd in .destroy_inode\n"); 308*1da177e4SLinus Torvalds } 309*1da177e4SLinus Torvalds 310*1da177e4SLinus Torvalds kfree(HOSTFS_I(inode)); 311*1da177e4SLinus Torvalds } 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds static void hostfs_read_inode(struct inode *inode) 314*1da177e4SLinus Torvalds { 315*1da177e4SLinus Torvalds read_inode(inode); 316*1da177e4SLinus Torvalds } 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds static struct super_operations hostfs_sbops = { 319*1da177e4SLinus Torvalds .alloc_inode = hostfs_alloc_inode, 320*1da177e4SLinus Torvalds .drop_inode = generic_delete_inode, 321*1da177e4SLinus Torvalds .delete_inode = hostfs_delete_inode, 322*1da177e4SLinus Torvalds .destroy_inode = hostfs_destroy_inode, 323*1da177e4SLinus Torvalds .read_inode = hostfs_read_inode, 324*1da177e4SLinus Torvalds .statfs = hostfs_statfs, 325*1da177e4SLinus Torvalds }; 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) 328*1da177e4SLinus Torvalds { 329*1da177e4SLinus Torvalds void *dir; 330*1da177e4SLinus Torvalds char *name; 331*1da177e4SLinus Torvalds unsigned long long next, ino; 332*1da177e4SLinus Torvalds int error, len; 333*1da177e4SLinus Torvalds 334*1da177e4SLinus Torvalds name = dentry_name(file->f_dentry, 0); 335*1da177e4SLinus Torvalds if(name == NULL) return(-ENOMEM); 336*1da177e4SLinus Torvalds dir = open_dir(name, &error); 337*1da177e4SLinus Torvalds kfree(name); 338*1da177e4SLinus Torvalds if(dir == NULL) return(-error); 339*1da177e4SLinus Torvalds next = file->f_pos; 340*1da177e4SLinus Torvalds while((name = read_dir(dir, &next, &ino, &len)) != NULL){ 341*1da177e4SLinus Torvalds error = (*filldir)(ent, name, len, file->f_pos, 342*1da177e4SLinus Torvalds ino, DT_UNKNOWN); 343*1da177e4SLinus Torvalds if(error) break; 344*1da177e4SLinus Torvalds file->f_pos = next; 345*1da177e4SLinus Torvalds } 346*1da177e4SLinus Torvalds close_dir(dir); 347*1da177e4SLinus Torvalds return(0); 348*1da177e4SLinus Torvalds } 349*1da177e4SLinus Torvalds 350*1da177e4SLinus Torvalds int hostfs_file_open(struct inode *ino, struct file *file) 351*1da177e4SLinus Torvalds { 352*1da177e4SLinus Torvalds char *name; 353*1da177e4SLinus Torvalds int mode = 0, r = 0, w = 0, fd; 354*1da177e4SLinus Torvalds 355*1da177e4SLinus Torvalds mode = file->f_mode & (FMODE_READ | FMODE_WRITE); 356*1da177e4SLinus Torvalds if((mode & HOSTFS_I(ino)->mode) == mode) 357*1da177e4SLinus Torvalds return(0); 358*1da177e4SLinus Torvalds 359*1da177e4SLinus Torvalds /* The file may already have been opened, but with the wrong access, 360*1da177e4SLinus Torvalds * so this resets things and reopens the file with the new access. 361*1da177e4SLinus Torvalds */ 362*1da177e4SLinus Torvalds if(HOSTFS_I(ino)->fd != -1){ 363*1da177e4SLinus Torvalds close_file(&HOSTFS_I(ino)->fd); 364*1da177e4SLinus Torvalds HOSTFS_I(ino)->fd = -1; 365*1da177e4SLinus Torvalds } 366*1da177e4SLinus Torvalds 367*1da177e4SLinus Torvalds HOSTFS_I(ino)->mode |= mode; 368*1da177e4SLinus Torvalds if(HOSTFS_I(ino)->mode & FMODE_READ) 369*1da177e4SLinus Torvalds r = 1; 370*1da177e4SLinus Torvalds if(HOSTFS_I(ino)->mode & FMODE_WRITE) 371*1da177e4SLinus Torvalds w = 1; 372*1da177e4SLinus Torvalds if(w) 373*1da177e4SLinus Torvalds r = 1; 374*1da177e4SLinus Torvalds 375*1da177e4SLinus Torvalds name = dentry_name(file->f_dentry, 0); 376*1da177e4SLinus Torvalds if(name == NULL) 377*1da177e4SLinus Torvalds return(-ENOMEM); 378*1da177e4SLinus Torvalds 379*1da177e4SLinus Torvalds fd = open_file(name, r, w, append); 380*1da177e4SLinus Torvalds kfree(name); 381*1da177e4SLinus Torvalds if(fd < 0) return(fd); 382*1da177e4SLinus Torvalds FILE_HOSTFS_I(file)->fd = fd; 383*1da177e4SLinus Torvalds 384*1da177e4SLinus Torvalds return(0); 385*1da177e4SLinus Torvalds } 386*1da177e4SLinus Torvalds 387*1da177e4SLinus Torvalds int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) 388*1da177e4SLinus Torvalds { 389*1da177e4SLinus Torvalds return(0); 390*1da177e4SLinus Torvalds } 391*1da177e4SLinus Torvalds 392*1da177e4SLinus Torvalds static struct file_operations hostfs_file_fops = { 393*1da177e4SLinus Torvalds .llseek = generic_file_llseek, 394*1da177e4SLinus Torvalds .read = generic_file_read, 395*1da177e4SLinus Torvalds .sendfile = generic_file_sendfile, 396*1da177e4SLinus Torvalds .aio_read = generic_file_aio_read, 397*1da177e4SLinus Torvalds .aio_write = generic_file_aio_write, 398*1da177e4SLinus Torvalds .readv = generic_file_readv, 399*1da177e4SLinus Torvalds .writev = generic_file_writev, 400*1da177e4SLinus Torvalds .write = generic_file_write, 401*1da177e4SLinus Torvalds .mmap = generic_file_mmap, 402*1da177e4SLinus Torvalds .open = hostfs_file_open, 403*1da177e4SLinus Torvalds .release = NULL, 404*1da177e4SLinus Torvalds .fsync = hostfs_fsync, 405*1da177e4SLinus Torvalds }; 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvalds static struct file_operations hostfs_dir_fops = { 408*1da177e4SLinus Torvalds .llseek = generic_file_llseek, 409*1da177e4SLinus Torvalds .readdir = hostfs_readdir, 410*1da177e4SLinus Torvalds .read = generic_read_dir, 411*1da177e4SLinus Torvalds }; 412*1da177e4SLinus Torvalds 413*1da177e4SLinus Torvalds int hostfs_writepage(struct page *page, struct writeback_control *wbc) 414*1da177e4SLinus Torvalds { 415*1da177e4SLinus Torvalds struct address_space *mapping = page->mapping; 416*1da177e4SLinus Torvalds struct inode *inode = mapping->host; 417*1da177e4SLinus Torvalds char *buffer; 418*1da177e4SLinus Torvalds unsigned long long base; 419*1da177e4SLinus Torvalds int count = PAGE_CACHE_SIZE; 420*1da177e4SLinus Torvalds int end_index = inode->i_size >> PAGE_CACHE_SHIFT; 421*1da177e4SLinus Torvalds int err; 422*1da177e4SLinus Torvalds 423*1da177e4SLinus Torvalds if (page->index >= end_index) 424*1da177e4SLinus Torvalds count = inode->i_size & (PAGE_CACHE_SIZE-1); 425*1da177e4SLinus Torvalds 426*1da177e4SLinus Torvalds buffer = kmap(page); 427*1da177e4SLinus Torvalds base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count); 430*1da177e4SLinus Torvalds if(err != count){ 431*1da177e4SLinus Torvalds ClearPageUptodate(page); 432*1da177e4SLinus Torvalds goto out; 433*1da177e4SLinus Torvalds } 434*1da177e4SLinus Torvalds 435*1da177e4SLinus Torvalds if (base > inode->i_size) 436*1da177e4SLinus Torvalds inode->i_size = base; 437*1da177e4SLinus Torvalds 438*1da177e4SLinus Torvalds if (PageError(page)) 439*1da177e4SLinus Torvalds ClearPageError(page); 440*1da177e4SLinus Torvalds err = 0; 441*1da177e4SLinus Torvalds 442*1da177e4SLinus Torvalds out: 443*1da177e4SLinus Torvalds kunmap(page); 444*1da177e4SLinus Torvalds 445*1da177e4SLinus Torvalds unlock_page(page); 446*1da177e4SLinus Torvalds return err; 447*1da177e4SLinus Torvalds } 448*1da177e4SLinus Torvalds 449*1da177e4SLinus Torvalds int hostfs_readpage(struct file *file, struct page *page) 450*1da177e4SLinus Torvalds { 451*1da177e4SLinus Torvalds char *buffer; 452*1da177e4SLinus Torvalds long long start; 453*1da177e4SLinus Torvalds int err = 0; 454*1da177e4SLinus Torvalds 455*1da177e4SLinus Torvalds start = (long long) page->index << PAGE_CACHE_SHIFT; 456*1da177e4SLinus Torvalds buffer = kmap(page); 457*1da177e4SLinus Torvalds err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, 458*1da177e4SLinus Torvalds PAGE_CACHE_SIZE); 459*1da177e4SLinus Torvalds if(err < 0) goto out; 460*1da177e4SLinus Torvalds 461*1da177e4SLinus Torvalds memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); 462*1da177e4SLinus Torvalds 463*1da177e4SLinus Torvalds flush_dcache_page(page); 464*1da177e4SLinus Torvalds SetPageUptodate(page); 465*1da177e4SLinus Torvalds if (PageError(page)) ClearPageError(page); 466*1da177e4SLinus Torvalds err = 0; 467*1da177e4SLinus Torvalds out: 468*1da177e4SLinus Torvalds kunmap(page); 469*1da177e4SLinus Torvalds unlock_page(page); 470*1da177e4SLinus Torvalds return(err); 471*1da177e4SLinus Torvalds } 472*1da177e4SLinus Torvalds 473*1da177e4SLinus Torvalds int hostfs_prepare_write(struct file *file, struct page *page, 474*1da177e4SLinus Torvalds unsigned int from, unsigned int to) 475*1da177e4SLinus Torvalds { 476*1da177e4SLinus Torvalds char *buffer; 477*1da177e4SLinus Torvalds long long start, tmp; 478*1da177e4SLinus Torvalds int err; 479*1da177e4SLinus Torvalds 480*1da177e4SLinus Torvalds start = (long long) page->index << PAGE_CACHE_SHIFT; 481*1da177e4SLinus Torvalds buffer = kmap(page); 482*1da177e4SLinus Torvalds if(from != 0){ 483*1da177e4SLinus Torvalds tmp = start; 484*1da177e4SLinus Torvalds err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer, 485*1da177e4SLinus Torvalds from); 486*1da177e4SLinus Torvalds if(err < 0) goto out; 487*1da177e4SLinus Torvalds } 488*1da177e4SLinus Torvalds if(to != PAGE_CACHE_SIZE){ 489*1da177e4SLinus Torvalds start += to; 490*1da177e4SLinus Torvalds err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to, 491*1da177e4SLinus Torvalds PAGE_CACHE_SIZE - to); 492*1da177e4SLinus Torvalds if(err < 0) goto out; 493*1da177e4SLinus Torvalds } 494*1da177e4SLinus Torvalds err = 0; 495*1da177e4SLinus Torvalds out: 496*1da177e4SLinus Torvalds kunmap(page); 497*1da177e4SLinus Torvalds return(err); 498*1da177e4SLinus Torvalds } 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds int hostfs_commit_write(struct file *file, struct page *page, unsigned from, 501*1da177e4SLinus Torvalds unsigned to) 502*1da177e4SLinus Torvalds { 503*1da177e4SLinus Torvalds struct address_space *mapping = page->mapping; 504*1da177e4SLinus Torvalds struct inode *inode = mapping->host; 505*1da177e4SLinus Torvalds char *buffer; 506*1da177e4SLinus Torvalds long long start; 507*1da177e4SLinus Torvalds int err = 0; 508*1da177e4SLinus Torvalds 509*1da177e4SLinus Torvalds start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; 510*1da177e4SLinus Torvalds buffer = kmap(page); 511*1da177e4SLinus Torvalds err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from, 512*1da177e4SLinus Torvalds to - from); 513*1da177e4SLinus Torvalds if(err > 0) err = 0; 514*1da177e4SLinus Torvalds if(!err && (start > inode->i_size)) 515*1da177e4SLinus Torvalds inode->i_size = start; 516*1da177e4SLinus Torvalds 517*1da177e4SLinus Torvalds kunmap(page); 518*1da177e4SLinus Torvalds return(err); 519*1da177e4SLinus Torvalds } 520*1da177e4SLinus Torvalds 521*1da177e4SLinus Torvalds static struct address_space_operations hostfs_aops = { 522*1da177e4SLinus Torvalds .writepage = hostfs_writepage, 523*1da177e4SLinus Torvalds .readpage = hostfs_readpage, 524*1da177e4SLinus Torvalds /* .set_page_dirty = __set_page_dirty_nobuffers, */ 525*1da177e4SLinus Torvalds .prepare_write = hostfs_prepare_write, 526*1da177e4SLinus Torvalds .commit_write = hostfs_commit_write 527*1da177e4SLinus Torvalds }; 528*1da177e4SLinus Torvalds 529*1da177e4SLinus Torvalds static int init_inode(struct inode *inode, struct dentry *dentry) 530*1da177e4SLinus Torvalds { 531*1da177e4SLinus Torvalds char *name; 532*1da177e4SLinus Torvalds int type, err = -ENOMEM; 533*1da177e4SLinus Torvalds int maj, min; 534*1da177e4SLinus Torvalds dev_t rdev = 0; 535*1da177e4SLinus Torvalds 536*1da177e4SLinus Torvalds if(dentry){ 537*1da177e4SLinus Torvalds name = dentry_name(dentry, 0); 538*1da177e4SLinus Torvalds if(name == NULL) 539*1da177e4SLinus Torvalds goto out; 540*1da177e4SLinus Torvalds type = file_type(name, &maj, &min); 541*1da177e4SLinus Torvalds /*Reencode maj and min with the kernel encoding.*/ 542*1da177e4SLinus Torvalds rdev = MKDEV(maj, min); 543*1da177e4SLinus Torvalds kfree(name); 544*1da177e4SLinus Torvalds } 545*1da177e4SLinus Torvalds else type = OS_TYPE_DIR; 546*1da177e4SLinus Torvalds 547*1da177e4SLinus Torvalds err = 0; 548*1da177e4SLinus Torvalds if(type == OS_TYPE_SYMLINK) 549*1da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 550*1da177e4SLinus Torvalds else if(type == OS_TYPE_DIR) 551*1da177e4SLinus Torvalds inode->i_op = &hostfs_dir_iops; 552*1da177e4SLinus Torvalds else inode->i_op = &hostfs_iops; 553*1da177e4SLinus Torvalds 554*1da177e4SLinus Torvalds if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops; 555*1da177e4SLinus Torvalds else inode->i_fop = &hostfs_file_fops; 556*1da177e4SLinus Torvalds 557*1da177e4SLinus Torvalds if(type == OS_TYPE_SYMLINK) 558*1da177e4SLinus Torvalds inode->i_mapping->a_ops = &hostfs_link_aops; 559*1da177e4SLinus Torvalds else inode->i_mapping->a_ops = &hostfs_aops; 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds switch (type) { 562*1da177e4SLinus Torvalds case OS_TYPE_CHARDEV: 563*1da177e4SLinus Torvalds init_special_inode(inode, S_IFCHR, rdev); 564*1da177e4SLinus Torvalds break; 565*1da177e4SLinus Torvalds case OS_TYPE_BLOCKDEV: 566*1da177e4SLinus Torvalds init_special_inode(inode, S_IFBLK, rdev); 567*1da177e4SLinus Torvalds break; 568*1da177e4SLinus Torvalds case OS_TYPE_FIFO: 569*1da177e4SLinus Torvalds init_special_inode(inode, S_IFIFO, 0); 570*1da177e4SLinus Torvalds break; 571*1da177e4SLinus Torvalds case OS_TYPE_SOCK: 572*1da177e4SLinus Torvalds init_special_inode(inode, S_IFSOCK, 0); 573*1da177e4SLinus Torvalds break; 574*1da177e4SLinus Torvalds } 575*1da177e4SLinus Torvalds out: 576*1da177e4SLinus Torvalds return(err); 577*1da177e4SLinus Torvalds } 578*1da177e4SLinus Torvalds 579*1da177e4SLinus Torvalds int hostfs_create(struct inode *dir, struct dentry *dentry, int mode, 580*1da177e4SLinus Torvalds struct nameidata *nd) 581*1da177e4SLinus Torvalds { 582*1da177e4SLinus Torvalds struct inode *inode; 583*1da177e4SLinus Torvalds char *name; 584*1da177e4SLinus Torvalds int error, fd; 585*1da177e4SLinus Torvalds 586*1da177e4SLinus Torvalds error = -ENOMEM; 587*1da177e4SLinus Torvalds inode = iget(dir->i_sb, 0); 588*1da177e4SLinus Torvalds if(inode == NULL) goto out; 589*1da177e4SLinus Torvalds 590*1da177e4SLinus Torvalds error = init_inode(inode, dentry); 591*1da177e4SLinus Torvalds if(error) 592*1da177e4SLinus Torvalds goto out_put; 593*1da177e4SLinus Torvalds 594*1da177e4SLinus Torvalds error = -ENOMEM; 595*1da177e4SLinus Torvalds name = dentry_name(dentry, 0); 596*1da177e4SLinus Torvalds if(name == NULL) 597*1da177e4SLinus Torvalds goto out_put; 598*1da177e4SLinus Torvalds 599*1da177e4SLinus Torvalds fd = file_create(name, 600*1da177e4SLinus Torvalds mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, 601*1da177e4SLinus Torvalds mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, 602*1da177e4SLinus Torvalds mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH); 603*1da177e4SLinus Torvalds if(fd < 0) 604*1da177e4SLinus Torvalds error = fd; 605*1da177e4SLinus Torvalds else error = read_name(inode, name); 606*1da177e4SLinus Torvalds 607*1da177e4SLinus Torvalds kfree(name); 608*1da177e4SLinus Torvalds if(error) 609*1da177e4SLinus Torvalds goto out_put; 610*1da177e4SLinus Torvalds 611*1da177e4SLinus Torvalds HOSTFS_I(inode)->fd = fd; 612*1da177e4SLinus Torvalds HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE; 613*1da177e4SLinus Torvalds d_instantiate(dentry, inode); 614*1da177e4SLinus Torvalds return(0); 615*1da177e4SLinus Torvalds 616*1da177e4SLinus Torvalds out_put: 617*1da177e4SLinus Torvalds iput(inode); 618*1da177e4SLinus Torvalds out: 619*1da177e4SLinus Torvalds return(error); 620*1da177e4SLinus Torvalds } 621*1da177e4SLinus Torvalds 622*1da177e4SLinus Torvalds struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, 623*1da177e4SLinus Torvalds struct nameidata *nd) 624*1da177e4SLinus Torvalds { 625*1da177e4SLinus Torvalds struct inode *inode; 626*1da177e4SLinus Torvalds char *name; 627*1da177e4SLinus Torvalds int err; 628*1da177e4SLinus Torvalds 629*1da177e4SLinus Torvalds err = -ENOMEM; 630*1da177e4SLinus Torvalds inode = iget(ino->i_sb, 0); 631*1da177e4SLinus Torvalds if(inode == NULL) 632*1da177e4SLinus Torvalds goto out; 633*1da177e4SLinus Torvalds 634*1da177e4SLinus Torvalds err = init_inode(inode, dentry); 635*1da177e4SLinus Torvalds if(err) 636*1da177e4SLinus Torvalds goto out_put; 637*1da177e4SLinus Torvalds 638*1da177e4SLinus Torvalds err = -ENOMEM; 639*1da177e4SLinus Torvalds name = dentry_name(dentry, 0); 640*1da177e4SLinus Torvalds if(name == NULL) 641*1da177e4SLinus Torvalds goto out_put; 642*1da177e4SLinus Torvalds 643*1da177e4SLinus Torvalds err = read_name(inode, name); 644*1da177e4SLinus Torvalds kfree(name); 645*1da177e4SLinus Torvalds if(err == -ENOENT){ 646*1da177e4SLinus Torvalds iput(inode); 647*1da177e4SLinus Torvalds inode = NULL; 648*1da177e4SLinus Torvalds } 649*1da177e4SLinus Torvalds else if(err) 650*1da177e4SLinus Torvalds goto out_put; 651*1da177e4SLinus Torvalds 652*1da177e4SLinus Torvalds d_add(dentry, inode); 653*1da177e4SLinus Torvalds dentry->d_op = &hostfs_dentry_ops; 654*1da177e4SLinus Torvalds return(NULL); 655*1da177e4SLinus Torvalds 656*1da177e4SLinus Torvalds out_put: 657*1da177e4SLinus Torvalds iput(inode); 658*1da177e4SLinus Torvalds out: 659*1da177e4SLinus Torvalds return(ERR_PTR(err)); 660*1da177e4SLinus Torvalds } 661*1da177e4SLinus Torvalds 662*1da177e4SLinus Torvalds static char *inode_dentry_name(struct inode *ino, struct dentry *dentry) 663*1da177e4SLinus Torvalds { 664*1da177e4SLinus Torvalds char *file; 665*1da177e4SLinus Torvalds int len; 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvalds file = inode_name(ino, dentry->d_name.len + 1); 668*1da177e4SLinus Torvalds if(file == NULL) return(NULL); 669*1da177e4SLinus Torvalds strcat(file, "/"); 670*1da177e4SLinus Torvalds len = strlen(file); 671*1da177e4SLinus Torvalds strncat(file, dentry->d_name.name, dentry->d_name.len); 672*1da177e4SLinus Torvalds file[len + dentry->d_name.len] = '\0'; 673*1da177e4SLinus Torvalds return(file); 674*1da177e4SLinus Torvalds } 675*1da177e4SLinus Torvalds 676*1da177e4SLinus Torvalds int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) 677*1da177e4SLinus Torvalds { 678*1da177e4SLinus Torvalds char *from_name, *to_name; 679*1da177e4SLinus Torvalds int err; 680*1da177e4SLinus Torvalds 681*1da177e4SLinus Torvalds if((from_name = inode_dentry_name(ino, from)) == NULL) 682*1da177e4SLinus Torvalds return(-ENOMEM); 683*1da177e4SLinus Torvalds to_name = dentry_name(to, 0); 684*1da177e4SLinus Torvalds if(to_name == NULL){ 685*1da177e4SLinus Torvalds kfree(from_name); 686*1da177e4SLinus Torvalds return(-ENOMEM); 687*1da177e4SLinus Torvalds } 688*1da177e4SLinus Torvalds err = link_file(to_name, from_name); 689*1da177e4SLinus Torvalds kfree(from_name); 690*1da177e4SLinus Torvalds kfree(to_name); 691*1da177e4SLinus Torvalds return(err); 692*1da177e4SLinus Torvalds } 693*1da177e4SLinus Torvalds 694*1da177e4SLinus Torvalds int hostfs_unlink(struct inode *ino, struct dentry *dentry) 695*1da177e4SLinus Torvalds { 696*1da177e4SLinus Torvalds char *file; 697*1da177e4SLinus Torvalds int err; 698*1da177e4SLinus Torvalds 699*1da177e4SLinus Torvalds if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); 700*1da177e4SLinus Torvalds if(append) 701*1da177e4SLinus Torvalds return(-EPERM); 702*1da177e4SLinus Torvalds 703*1da177e4SLinus Torvalds err = unlink_file(file); 704*1da177e4SLinus Torvalds kfree(file); 705*1da177e4SLinus Torvalds return(err); 706*1da177e4SLinus Torvalds } 707*1da177e4SLinus Torvalds 708*1da177e4SLinus Torvalds int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) 709*1da177e4SLinus Torvalds { 710*1da177e4SLinus Torvalds char *file; 711*1da177e4SLinus Torvalds int err; 712*1da177e4SLinus Torvalds 713*1da177e4SLinus Torvalds if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); 714*1da177e4SLinus Torvalds err = make_symlink(file, to); 715*1da177e4SLinus Torvalds kfree(file); 716*1da177e4SLinus Torvalds return(err); 717*1da177e4SLinus Torvalds } 718*1da177e4SLinus Torvalds 719*1da177e4SLinus Torvalds int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode) 720*1da177e4SLinus Torvalds { 721*1da177e4SLinus Torvalds char *file; 722*1da177e4SLinus Torvalds int err; 723*1da177e4SLinus Torvalds 724*1da177e4SLinus Torvalds if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); 725*1da177e4SLinus Torvalds err = do_mkdir(file, mode); 726*1da177e4SLinus Torvalds kfree(file); 727*1da177e4SLinus Torvalds return(err); 728*1da177e4SLinus Torvalds } 729*1da177e4SLinus Torvalds 730*1da177e4SLinus Torvalds int hostfs_rmdir(struct inode *ino, struct dentry *dentry) 731*1da177e4SLinus Torvalds { 732*1da177e4SLinus Torvalds char *file; 733*1da177e4SLinus Torvalds int err; 734*1da177e4SLinus Torvalds 735*1da177e4SLinus Torvalds if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); 736*1da177e4SLinus Torvalds err = do_rmdir(file); 737*1da177e4SLinus Torvalds kfree(file); 738*1da177e4SLinus Torvalds return(err); 739*1da177e4SLinus Torvalds } 740*1da177e4SLinus Torvalds 741*1da177e4SLinus Torvalds int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) 742*1da177e4SLinus Torvalds { 743*1da177e4SLinus Torvalds struct inode *inode; 744*1da177e4SLinus Torvalds char *name; 745*1da177e4SLinus Torvalds int err = -ENOMEM; 746*1da177e4SLinus Torvalds 747*1da177e4SLinus Torvalds inode = iget(dir->i_sb, 0); 748*1da177e4SLinus Torvalds if(inode == NULL) 749*1da177e4SLinus Torvalds goto out; 750*1da177e4SLinus Torvalds 751*1da177e4SLinus Torvalds err = init_inode(inode, dentry); 752*1da177e4SLinus Torvalds if(err) 753*1da177e4SLinus Torvalds goto out_put; 754*1da177e4SLinus Torvalds 755*1da177e4SLinus Torvalds err = -ENOMEM; 756*1da177e4SLinus Torvalds name = dentry_name(dentry, 0); 757*1da177e4SLinus Torvalds if(name == NULL) 758*1da177e4SLinus Torvalds goto out_put; 759*1da177e4SLinus Torvalds 760*1da177e4SLinus Torvalds init_special_inode(inode, mode, dev); 761*1da177e4SLinus Torvalds err = do_mknod(name, mode, dev); 762*1da177e4SLinus Torvalds if(err) 763*1da177e4SLinus Torvalds goto out_free; 764*1da177e4SLinus Torvalds 765*1da177e4SLinus Torvalds err = read_name(inode, name); 766*1da177e4SLinus Torvalds kfree(name); 767*1da177e4SLinus Torvalds if(err) 768*1da177e4SLinus Torvalds goto out_put; 769*1da177e4SLinus Torvalds 770*1da177e4SLinus Torvalds d_instantiate(dentry, inode); 771*1da177e4SLinus Torvalds return(0); 772*1da177e4SLinus Torvalds 773*1da177e4SLinus Torvalds out_free: 774*1da177e4SLinus Torvalds kfree(name); 775*1da177e4SLinus Torvalds out_put: 776*1da177e4SLinus Torvalds iput(inode); 777*1da177e4SLinus Torvalds out: 778*1da177e4SLinus Torvalds return(err); 779*1da177e4SLinus Torvalds } 780*1da177e4SLinus Torvalds 781*1da177e4SLinus Torvalds int hostfs_rename(struct inode *from_ino, struct dentry *from, 782*1da177e4SLinus Torvalds struct inode *to_ino, struct dentry *to) 783*1da177e4SLinus Torvalds { 784*1da177e4SLinus Torvalds char *from_name, *to_name; 785*1da177e4SLinus Torvalds int err; 786*1da177e4SLinus Torvalds 787*1da177e4SLinus Torvalds if((from_name = inode_dentry_name(from_ino, from)) == NULL) 788*1da177e4SLinus Torvalds return(-ENOMEM); 789*1da177e4SLinus Torvalds if((to_name = inode_dentry_name(to_ino, to)) == NULL){ 790*1da177e4SLinus Torvalds kfree(from_name); 791*1da177e4SLinus Torvalds return(-ENOMEM); 792*1da177e4SLinus Torvalds } 793*1da177e4SLinus Torvalds err = rename_file(from_name, to_name); 794*1da177e4SLinus Torvalds kfree(from_name); 795*1da177e4SLinus Torvalds kfree(to_name); 796*1da177e4SLinus Torvalds return(err); 797*1da177e4SLinus Torvalds } 798*1da177e4SLinus Torvalds 799*1da177e4SLinus Torvalds void hostfs_truncate(struct inode *ino) 800*1da177e4SLinus Torvalds { 801*1da177e4SLinus Torvalds not_implemented(); 802*1da177e4SLinus Torvalds } 803*1da177e4SLinus Torvalds 804*1da177e4SLinus Torvalds int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) 805*1da177e4SLinus Torvalds { 806*1da177e4SLinus Torvalds char *name; 807*1da177e4SLinus Torvalds int r = 0, w = 0, x = 0, err; 808*1da177e4SLinus Torvalds 809*1da177e4SLinus Torvalds if (desired & MAY_READ) r = 1; 810*1da177e4SLinus Torvalds if (desired & MAY_WRITE) w = 1; 811*1da177e4SLinus Torvalds if (desired & MAY_EXEC) x = 1; 812*1da177e4SLinus Torvalds name = inode_name(ino, 0); 813*1da177e4SLinus Torvalds if (name == NULL) return(-ENOMEM); 814*1da177e4SLinus Torvalds 815*1da177e4SLinus Torvalds if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) || 816*1da177e4SLinus Torvalds S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode)) 817*1da177e4SLinus Torvalds err = 0; 818*1da177e4SLinus Torvalds else 819*1da177e4SLinus Torvalds err = access_file(name, r, w, x); 820*1da177e4SLinus Torvalds kfree(name); 821*1da177e4SLinus Torvalds if(!err) 822*1da177e4SLinus Torvalds err = generic_permission(ino, desired, NULL); 823*1da177e4SLinus Torvalds return err; 824*1da177e4SLinus Torvalds } 825*1da177e4SLinus Torvalds 826*1da177e4SLinus Torvalds int hostfs_setattr(struct dentry *dentry, struct iattr *attr) 827*1da177e4SLinus Torvalds { 828*1da177e4SLinus Torvalds struct hostfs_iattr attrs; 829*1da177e4SLinus Torvalds char *name; 830*1da177e4SLinus Torvalds int err; 831*1da177e4SLinus Torvalds 832*1da177e4SLinus Torvalds err = inode_change_ok(dentry->d_inode, attr); 833*1da177e4SLinus Torvalds if (err) 834*1da177e4SLinus Torvalds return err; 835*1da177e4SLinus Torvalds 836*1da177e4SLinus Torvalds if(append) 837*1da177e4SLinus Torvalds attr->ia_valid &= ~ATTR_SIZE; 838*1da177e4SLinus Torvalds 839*1da177e4SLinus Torvalds attrs.ia_valid = 0; 840*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_MODE){ 841*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_MODE; 842*1da177e4SLinus Torvalds attrs.ia_mode = attr->ia_mode; 843*1da177e4SLinus Torvalds } 844*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_UID){ 845*1da177e4SLinus Torvalds if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && 846*1da177e4SLinus Torvalds (attr->ia_uid == 0)) 847*1da177e4SLinus Torvalds attr->ia_uid = getuid(); 848*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_UID; 849*1da177e4SLinus Torvalds attrs.ia_uid = attr->ia_uid; 850*1da177e4SLinus Torvalds } 851*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_GID){ 852*1da177e4SLinus Torvalds if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && 853*1da177e4SLinus Torvalds (attr->ia_gid == 0)) 854*1da177e4SLinus Torvalds attr->ia_gid = getgid(); 855*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_GID; 856*1da177e4SLinus Torvalds attrs.ia_gid = attr->ia_gid; 857*1da177e4SLinus Torvalds } 858*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_SIZE){ 859*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_SIZE; 860*1da177e4SLinus Torvalds attrs.ia_size = attr->ia_size; 861*1da177e4SLinus Torvalds } 862*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_ATIME){ 863*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_ATIME; 864*1da177e4SLinus Torvalds attrs.ia_atime = attr->ia_atime; 865*1da177e4SLinus Torvalds } 866*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_MTIME){ 867*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_MTIME; 868*1da177e4SLinus Torvalds attrs.ia_mtime = attr->ia_mtime; 869*1da177e4SLinus Torvalds } 870*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_CTIME){ 871*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_CTIME; 872*1da177e4SLinus Torvalds attrs.ia_ctime = attr->ia_ctime; 873*1da177e4SLinus Torvalds } 874*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_ATIME_SET){ 875*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET; 876*1da177e4SLinus Torvalds } 877*1da177e4SLinus Torvalds if(attr->ia_valid & ATTR_MTIME_SET){ 878*1da177e4SLinus Torvalds attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET; 879*1da177e4SLinus Torvalds } 880*1da177e4SLinus Torvalds name = dentry_name(dentry, 0); 881*1da177e4SLinus Torvalds if(name == NULL) return(-ENOMEM); 882*1da177e4SLinus Torvalds err = set_attr(name, &attrs); 883*1da177e4SLinus Torvalds kfree(name); 884*1da177e4SLinus Torvalds if(err) 885*1da177e4SLinus Torvalds return(err); 886*1da177e4SLinus Torvalds 887*1da177e4SLinus Torvalds return(inode_setattr(dentry->d_inode, attr)); 888*1da177e4SLinus Torvalds } 889*1da177e4SLinus Torvalds 890*1da177e4SLinus Torvalds int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 891*1da177e4SLinus Torvalds struct kstat *stat) 892*1da177e4SLinus Torvalds { 893*1da177e4SLinus Torvalds generic_fillattr(dentry->d_inode, stat); 894*1da177e4SLinus Torvalds return(0); 895*1da177e4SLinus Torvalds } 896*1da177e4SLinus Torvalds 897*1da177e4SLinus Torvalds static struct inode_operations hostfs_iops = { 898*1da177e4SLinus Torvalds .create = hostfs_create, 899*1da177e4SLinus Torvalds .link = hostfs_link, 900*1da177e4SLinus Torvalds .unlink = hostfs_unlink, 901*1da177e4SLinus Torvalds .symlink = hostfs_symlink, 902*1da177e4SLinus Torvalds .mkdir = hostfs_mkdir, 903*1da177e4SLinus Torvalds .rmdir = hostfs_rmdir, 904*1da177e4SLinus Torvalds .mknod = hostfs_mknod, 905*1da177e4SLinus Torvalds .rename = hostfs_rename, 906*1da177e4SLinus Torvalds .truncate = hostfs_truncate, 907*1da177e4SLinus Torvalds .permission = hostfs_permission, 908*1da177e4SLinus Torvalds .setattr = hostfs_setattr, 909*1da177e4SLinus Torvalds .getattr = hostfs_getattr, 910*1da177e4SLinus Torvalds }; 911*1da177e4SLinus Torvalds 912*1da177e4SLinus Torvalds static struct inode_operations hostfs_dir_iops = { 913*1da177e4SLinus Torvalds .create = hostfs_create, 914*1da177e4SLinus Torvalds .lookup = hostfs_lookup, 915*1da177e4SLinus Torvalds .link = hostfs_link, 916*1da177e4SLinus Torvalds .unlink = hostfs_unlink, 917*1da177e4SLinus Torvalds .symlink = hostfs_symlink, 918*1da177e4SLinus Torvalds .mkdir = hostfs_mkdir, 919*1da177e4SLinus Torvalds .rmdir = hostfs_rmdir, 920*1da177e4SLinus Torvalds .mknod = hostfs_mknod, 921*1da177e4SLinus Torvalds .rename = hostfs_rename, 922*1da177e4SLinus Torvalds .truncate = hostfs_truncate, 923*1da177e4SLinus Torvalds .permission = hostfs_permission, 924*1da177e4SLinus Torvalds .setattr = hostfs_setattr, 925*1da177e4SLinus Torvalds .getattr = hostfs_getattr, 926*1da177e4SLinus Torvalds }; 927*1da177e4SLinus Torvalds 928*1da177e4SLinus Torvalds int hostfs_link_readpage(struct file *file, struct page *page) 929*1da177e4SLinus Torvalds { 930*1da177e4SLinus Torvalds char *buffer, *name; 931*1da177e4SLinus Torvalds long long start; 932*1da177e4SLinus Torvalds int err; 933*1da177e4SLinus Torvalds 934*1da177e4SLinus Torvalds start = page->index << PAGE_CACHE_SHIFT; 935*1da177e4SLinus Torvalds buffer = kmap(page); 936*1da177e4SLinus Torvalds name = inode_name(page->mapping->host, 0); 937*1da177e4SLinus Torvalds if(name == NULL) return(-ENOMEM); 938*1da177e4SLinus Torvalds err = do_readlink(name, buffer, PAGE_CACHE_SIZE); 939*1da177e4SLinus Torvalds kfree(name); 940*1da177e4SLinus Torvalds if(err == PAGE_CACHE_SIZE) 941*1da177e4SLinus Torvalds err = -E2BIG; 942*1da177e4SLinus Torvalds else if(err > 0){ 943*1da177e4SLinus Torvalds flush_dcache_page(page); 944*1da177e4SLinus Torvalds SetPageUptodate(page); 945*1da177e4SLinus Torvalds if (PageError(page)) ClearPageError(page); 946*1da177e4SLinus Torvalds err = 0; 947*1da177e4SLinus Torvalds } 948*1da177e4SLinus Torvalds kunmap(page); 949*1da177e4SLinus Torvalds unlock_page(page); 950*1da177e4SLinus Torvalds return(err); 951*1da177e4SLinus Torvalds } 952*1da177e4SLinus Torvalds 953*1da177e4SLinus Torvalds static struct address_space_operations hostfs_link_aops = { 954*1da177e4SLinus Torvalds .readpage = hostfs_link_readpage, 955*1da177e4SLinus Torvalds }; 956*1da177e4SLinus Torvalds 957*1da177e4SLinus Torvalds static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) 958*1da177e4SLinus Torvalds { 959*1da177e4SLinus Torvalds struct inode *root_inode; 960*1da177e4SLinus Torvalds char *name, *data = d; 961*1da177e4SLinus Torvalds int err; 962*1da177e4SLinus Torvalds 963*1da177e4SLinus Torvalds sb->s_blocksize = 1024; 964*1da177e4SLinus Torvalds sb->s_blocksize_bits = 10; 965*1da177e4SLinus Torvalds sb->s_magic = HOSTFS_SUPER_MAGIC; 966*1da177e4SLinus Torvalds sb->s_op = &hostfs_sbops; 967*1da177e4SLinus Torvalds 968*1da177e4SLinus Torvalds if((data == NULL) || (*data == '\0')) 969*1da177e4SLinus Torvalds data = root_ino; 970*1da177e4SLinus Torvalds 971*1da177e4SLinus Torvalds err = -ENOMEM; 972*1da177e4SLinus Torvalds name = kmalloc(strlen(data) + 1, GFP_KERNEL); 973*1da177e4SLinus Torvalds if(name == NULL) 974*1da177e4SLinus Torvalds goto out; 975*1da177e4SLinus Torvalds 976*1da177e4SLinus Torvalds strcpy(name, data); 977*1da177e4SLinus Torvalds 978*1da177e4SLinus Torvalds root_inode = iget(sb, 0); 979*1da177e4SLinus Torvalds if(root_inode == NULL) 980*1da177e4SLinus Torvalds goto out_free; 981*1da177e4SLinus Torvalds 982*1da177e4SLinus Torvalds err = init_inode(root_inode, NULL); 983*1da177e4SLinus Torvalds if(err) 984*1da177e4SLinus Torvalds goto out_put; 985*1da177e4SLinus Torvalds 986*1da177e4SLinus Torvalds HOSTFS_I(root_inode)->host_filename = name; 987*1da177e4SLinus Torvalds 988*1da177e4SLinus Torvalds err = -ENOMEM; 989*1da177e4SLinus Torvalds sb->s_root = d_alloc_root(root_inode); 990*1da177e4SLinus Torvalds if(sb->s_root == NULL) 991*1da177e4SLinus Torvalds goto out_put; 992*1da177e4SLinus Torvalds 993*1da177e4SLinus Torvalds err = read_inode(root_inode); 994*1da177e4SLinus Torvalds if(err) 995*1da177e4SLinus Torvalds goto out_put; 996*1da177e4SLinus Torvalds 997*1da177e4SLinus Torvalds return(0); 998*1da177e4SLinus Torvalds 999*1da177e4SLinus Torvalds out_put: 1000*1da177e4SLinus Torvalds iput(root_inode); 1001*1da177e4SLinus Torvalds out_free: 1002*1da177e4SLinus Torvalds kfree(name); 1003*1da177e4SLinus Torvalds out: 1004*1da177e4SLinus Torvalds return(err); 1005*1da177e4SLinus Torvalds } 1006*1da177e4SLinus Torvalds 1007*1da177e4SLinus Torvalds static struct super_block *hostfs_read_sb(struct file_system_type *type, 1008*1da177e4SLinus Torvalds int flags, const char *dev_name, 1009*1da177e4SLinus Torvalds void *data) 1010*1da177e4SLinus Torvalds { 1011*1da177e4SLinus Torvalds return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); 1012*1da177e4SLinus Torvalds } 1013*1da177e4SLinus Torvalds 1014*1da177e4SLinus Torvalds static struct file_system_type hostfs_type = { 1015*1da177e4SLinus Torvalds .owner = THIS_MODULE, 1016*1da177e4SLinus Torvalds .name = "hostfs", 1017*1da177e4SLinus Torvalds .get_sb = hostfs_read_sb, 1018*1da177e4SLinus Torvalds .kill_sb = kill_anon_super, 1019*1da177e4SLinus Torvalds .fs_flags = 0, 1020*1da177e4SLinus Torvalds }; 1021*1da177e4SLinus Torvalds 1022*1da177e4SLinus Torvalds static int __init init_hostfs(void) 1023*1da177e4SLinus Torvalds { 1024*1da177e4SLinus Torvalds return(register_filesystem(&hostfs_type)); 1025*1da177e4SLinus Torvalds } 1026*1da177e4SLinus Torvalds 1027*1da177e4SLinus Torvalds static void __exit exit_hostfs(void) 1028*1da177e4SLinus Torvalds { 1029*1da177e4SLinus Torvalds unregister_filesystem(&hostfs_type); 1030*1da177e4SLinus Torvalds } 1031*1da177e4SLinus Torvalds 1032*1da177e4SLinus Torvalds module_init(init_hostfs) 1033*1da177e4SLinus Torvalds module_exit(exit_hostfs) 1034*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1035*1da177e4SLinus Torvalds 1036*1da177e4SLinus Torvalds /* 1037*1da177e4SLinus Torvalds * Overrides for Emacs so that we follow Linus's tabbing style. 1038*1da177e4SLinus Torvalds * Emacs will notice this stuff at the end of the file and automatically 1039*1da177e4SLinus Torvalds * adjust the settings for this buffer only. This must remain at the end 1040*1da177e4SLinus Torvalds * of the file. 1041*1da177e4SLinus Torvalds * --------------------------------------------------------------------------- 1042*1da177e4SLinus Torvalds * Local variables: 1043*1da177e4SLinus Torvalds * c-file-style: "linux" 1044*1da177e4SLinus Torvalds * End: 1045*1da177e4SLinus Torvalds */ 1046