Back to index

avfs  1.0.1
glassfs.c
Go to the documentation of this file.
00001 #include <linux/module.h>
00002 #include <linux/fs.h>
00003 #include <linux/file.h>
00004 #include <linux/namei.h>
00005 #include <linux/init.h>
00006 #include <linux/mount.h>
00007 #include <linux/security.h>
00008 
00009 #include <asm/uaccess.h>
00010 
00011 /* some random number */
00012 #define GLASSFS_MAGIC       0x28476c61
00013 #define FUSE_MAGIC 0x65735546
00014 
00015 #define AVFS_MAGIC_CHAR '#'
00016 #define OVERLAY_DIR "/overlay"
00017 #define OVERLAY_DIR_LEN 8
00018 
00019 struct base_entry {
00020        struct dentry *dentry;
00021        struct vfsmount *mnt;
00022        int is_avfs;
00023 };
00024 
00025 /* Rules for storing underlying filesystem data:
00026  *
00027  *  inode->u.generic_ip:  contains a kmalloced base_entry struct 
00028  *  sb->s_fs_info:        contains the underlying superblock
00029  */
00030 
00031 static struct super_operations glassfs_ops;
00032 static struct inode_operations glassfs_file_inode_operations;
00033 static struct file_operations glassfs_file_operations;
00034 static struct file_operations glassfs_dir_operations;
00035 static struct inode_operations glassfs_dir_inode_operations;
00036 static struct inode_operations glassfs_symlink_inode_operations;
00037 static struct dentry_operations glassfs_dentry_operations;
00038 
00039 static struct inode *glassfs_alloc_inode(struct super_block *sb)
00040 {
00041        struct base_entry *be;
00042        struct inode * inode = new_inode(sb);
00043        if (!inode)
00044               return NULL;
00045        
00046        be = kmalloc(sizeof(struct base_entry), GFP_KERNEL);
00047        if (!be) {
00048               iput(inode);
00049               return NULL;
00050        }
00051        inode->u.generic_ip = be;
00052        be->mnt = NULL;
00053        be->dentry = NULL;
00054        
00055        return inode;
00056 }
00057 
00058 static void glassfs_fill_inode(struct inode *inode, int mode, dev_t dev,
00059                             struct dentry *ndentry, struct vfsmount *nmnt,
00060                             int is_avfs)
00061 {
00062        struct base_entry *be = inode->u.generic_ip;
00063 
00064        be->dentry = dget(ndentry);
00065        be->mnt =  mntget(nmnt);
00066        be->is_avfs = is_avfs;
00067 
00068        inode->i_mode = mode;
00069        inode->i_rdev = dev;
00070        
00071        switch (mode & S_IFMT) {
00072        default:
00073               inode->i_op = &glassfs_file_inode_operations;
00074               inode->i_fop = &glassfs_file_operations;
00075               break;
00076        case S_IFDIR:
00077               inode->i_op = &glassfs_dir_inode_operations;
00078               inode->i_fop = &glassfs_dir_operations;
00079               break;
00080        case S_IFLNK:
00081               inode->i_op = &glassfs_symlink_inode_operations;
00082               inode->i_fop = &glassfs_file_operations;
00083               break;
00084        }
00085 }
00086 
00087 static void change_list(struct list_head *oldlist, struct list_head *newlist)
00088 {
00089        struct list_head *prev = oldlist->prev;
00090        struct list_head *next = oldlist->next;
00091        prev->next = newlist;
00092        next->prev = newlist;
00093 }
00094 
00095 static void exchange_lists(struct list_head *list1, struct list_head *list2)
00096 {
00097        change_list(list1, list2);
00098        change_list(list2, list1);
00099 }
00100 
00101 static void exchange_files(struct file *file1, struct file *file2)
00102 {
00103        struct file tmp;
00104        
00105        exchange_lists(&file1->f_list, &file2->f_list);
00106        exchange_lists(&file1->f_ep_links, &file2->f_ep_links);
00107 
00108        tmp = *file1;
00109        *file1 = *file2;
00110        *file2 = tmp;
00111 }
00112 
00113 static int glassfs_open(struct inode *inode, struct file *file)
00114 {
00115        struct base_entry *be = inode->u.generic_ip;
00116        struct vfsmount *nmnt = mntget(be->mnt);
00117        struct dentry *ndentry = dget(be->dentry);
00118        struct file *nfile;
00119        //printk("glassfs_open %.*s\n", ndentry->d_name.len, ndentry->d_name.name);
00120        nfile = dentry_open(ndentry, nmnt, file->f_flags);
00121        if (IS_ERR(nfile))
00122               return PTR_ERR(nfile);
00123 
00124        exchange_files(file, nfile);
00125        fput(nfile);
00126 
00127        return 0;
00128 }
00129 
00130 static int glassfs_open_dir(struct inode *inode, struct file *file)
00131 {
00132        struct base_entry *be = inode->u.generic_ip;
00133        struct file *nfile;
00134        //printk("glassfs_open_dir\n")
00135        nfile = dentry_open(dget(be->dentry), mntget(be->mnt), file->f_flags);
00136        if (IS_ERR(nfile))
00137               return PTR_ERR(nfile);
00138        
00139        file->private_data = nfile;
00140        return 0;
00141 }
00142 
00143 static int glassfs_release(struct inode *inode, struct file *file)
00144 {
00145        struct file *nfile = file->private_data;
00146        return filp_close(nfile, current->files);
00147 }
00148 
00149 static int glassfs_readdir(struct file *file, void *buf, filldir_t filler)
00150 {
00151        struct file *nfile = file->private_data;
00152        return vfs_readdir(nfile, filler, buf);
00153 }
00154 
00155 static loff_t glassfs_llseek(struct file *file, loff_t offset, int origin)
00156 {
00157        struct file *nfile = file->private_data;
00158        loff_t (*fn)(struct file *, loff_t, int);
00159 
00160        fn = default_llseek;
00161        if (nfile->f_op && nfile->f_op->llseek)
00162               fn = nfile->f_op->llseek;
00163        return fn(nfile, offset, origin);
00164 }
00165 
00166 static int glassfs_ioctl(struct inode *inode, struct file *file,
00167                       unsigned int cmd, unsigned long arg)
00168 {
00169        int err;
00170        struct file *nfile = file->private_data;
00171 
00172        err = security_file_ioctl(nfile, cmd, arg);
00173        if (err)
00174               return err;
00175 
00176        err = -ENOTTY;
00177        if (nfile->f_op && nfile->f_op->ioctl)
00178               err = nfile->f_op->ioctl(nfile->f_dentry->d_inode, nfile,
00179                                     cmd, arg);
00180        return err;
00181 }
00182 
00183 static int glassfs_fsync(struct file *file, struct dentry *dentry,
00184                       int datasync)
00185 {
00186        int err;
00187        struct file *nfile = file->private_data;
00188        struct address_space *mapping = nfile->f_mapping;
00189 
00190        if (!nfile->f_op || !nfile->f_op->fsync)
00191               return -EINVAL;
00192        down(&mapping->host->i_sem);
00193        err = nfile->f_op->fsync(nfile, nfile->f_dentry, datasync);
00194        up(&mapping->host->i_sem);
00195        return err;
00196 }
00197 
00198 static int glassfs_flush(struct file *file)
00199 {
00200         //printk("glassfs_flush\n");
00201         struct file *nfile = file->private_data;
00202         if (nfile->f_op && nfile->f_op->flush)
00203                 return nfile->f_op->flush(nfile);
00204         else
00205                 return 0;
00206 }
00207 
00208 
00209 static int is_avfs(const unsigned char *name, unsigned int len)
00210 {
00211        for (; len--; name++)
00212               if (*name == (unsigned char) AVFS_MAGIC_CHAR)
00213                      return 1;
00214        return 0;
00215 }
00216 
00217 
00218 static char * my_d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
00219                      struct dentry *root, struct vfsmount *rootmnt,
00220                      char *buffer, int buflen)
00221 {
00222        char * end = buffer+buflen;
00223        char * retval;
00224        int namelen;
00225 
00226        *--end = '\0';
00227        buflen--;
00228        if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
00229               buflen -= 10;
00230               end -= 10;
00231               if (buflen < 0)
00232                      goto Elong;
00233               memcpy(end, " (deleted)", 10);
00234        }
00235 
00236        if (buflen < 1)
00237               goto Elong;
00238        /* Get '/' right */
00239        retval = end-1;
00240        *retval = '/';
00241 
00242        for (;;) {
00243               struct dentry * parent;
00244 
00245               if (dentry == root && vfsmnt == rootmnt)
00246                      break;
00247               if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
00248                      /* Global root? */
00249                      spin_lock(&vfsmount_lock);
00250                      if (vfsmnt->mnt_parent == vfsmnt) {
00251                             spin_unlock(&vfsmount_lock);
00252                             goto global_root;
00253                      }
00254                      dentry = vfsmnt->mnt_mountpoint;
00255                      vfsmnt = vfsmnt->mnt_parent;
00256                      spin_unlock(&vfsmount_lock);
00257                      continue;
00258               }
00259               parent = dentry->d_parent;
00260               prefetch(parent);
00261               namelen = dentry->d_name.len;
00262               buflen -= namelen + 1;
00263               if (buflen < 0)
00264                      goto Elong;
00265               end -= namelen;
00266               memcpy(end, dentry->d_name.name, namelen);
00267               *--end = '/';
00268               retval = end;
00269               dentry = parent;
00270        }
00271 
00272        return retval;
00273 
00274 global_root:
00275        namelen = dentry->d_name.len;
00276        buflen -= namelen;
00277        if (buflen < 0)
00278               goto Elong;
00279        retval -= namelen-1; /* hit the slash */
00280        memcpy(retval, dentry->d_name.name, namelen);
00281        return retval;
00282 Elong:
00283        return ERR_PTR(-ENAMETOOLONG);
00284 }
00285 
00286 
00287 static int lookup_avfs(struct dentry *dentry, struct nameidata *nd,
00288                      struct vfsmount *nmnt, struct base_entry *be)
00289 {
00290        int err;
00291        char *page;
00292        char *path;
00293        
00294        err = -ENOMEM;
00295        page = (char *) __get_free_page(GFP_KERNEL);
00296        if (page) {
00297               struct nameidata avfsnd;
00298               unsigned int offset = PAGE_SIZE - dentry->d_name.len - 2;
00299               spin_lock(&dcache_lock);
00300               path = my_d_path(nd->dentry,nd->mnt, nd->mnt->mnt_sb->s_root, nd->mnt, page, offset);
00301               spin_unlock(&dcache_lock);
00302               err = -ENAMETOOLONG;
00303               if (!IS_ERR(path) && page + OVERLAY_DIR_LEN < path) {
00304                      unsigned int pathlen = strlen(path);
00305                      path[pathlen] = '/';
00306                      memcpy(path + pathlen + 1, dentry->d_name.name,
00307                             dentry->d_name.len);
00308                      path[1 + pathlen + dentry->d_name.len] = '\0';
00309                      path -= OVERLAY_DIR_LEN;
00310                      memcpy(path, OVERLAY_DIR, OVERLAY_DIR_LEN);
00311 
00312                      //printk("lookup_avfs: '%s'\n", path);
00313                      avfsnd.last_type = LAST_ROOT;
00314                      avfsnd.flags = 0;
00315                      avfsnd.mnt = mntget(nmnt);
00316                      avfsnd.dentry = dget(nmnt->mnt_sb->s_root);
00317 
00318                      err = path_walk(path, &avfsnd);
00319                      if (!err) {
00320                             if (avfsnd.dentry->d_sb->s_magic != FUSE_MAGIC) {
00321                                    printk("glassfs: not an AVFS inode\n");
00322                                    path_release(&avfsnd);
00323                                    err = -ENOENT;
00324                             } else {
00325                                    be->mnt = avfsnd.mnt;
00326                                    be->dentry = avfsnd.dentry;
00327                             }
00328                      }
00329               }
00330               free_page((unsigned long) page);
00331        }
00332        return err;
00333 }
00334 
00335 static inline int is_create(struct nameidata *nd)
00336 {
00337        if (!nd)
00338               return 1;
00339        if ((nd->flags & LOOKUP_CREATE) && !(nd->flags & LOOKUP_CONTINUE))
00340               return 1;
00341        return 0;
00342 }
00343 
00344 static struct dentry *glassfs_lookup(struct inode *dir, struct dentry *dentry,
00345                                 struct nameidata *nd)
00346 {
00347        struct base_entry *be = dir->u.generic_ip;
00348        struct dentry *ndentry;
00349        struct vfsmount *nmnt;
00350        struct inode *inode = NULL;
00351        int curravfs = be->is_avfs;
00352 
00353 //     printk("glassfs_lookup\n");
00354        down(&be->dentry->d_inode->i_sem);
00355        ndentry = lookup_hash(&dentry->d_name, be->dentry);
00356        up(&be->dentry->d_inode->i_sem);
00357        if (IS_ERR(ndentry))
00358               return ndentry;
00359 
00360        nmnt = mntget(be->mnt);
00361        if (!is_create(nd) && !ndentry->d_inode && !curravfs && 
00362           is_avfs(dentry->d_name.name, dentry->d_name.len)) {
00363               struct base_entry avfsbe;
00364               int err;
00365               int total_link_count_save = current->total_link_count;
00366               err = lookup_avfs(dentry, nd, nmnt, &avfsbe);
00367               current->total_link_count = total_link_count_save;
00368               if (!err) {
00369                      if (avfsbe.dentry->d_inode) {
00370                             dput(ndentry);
00371                             mntput(nmnt);
00372                             ndentry = avfsbe.dentry;
00373                             nmnt = avfsbe.mnt;
00374                             curravfs = 1;
00375                      } else {
00376                             dput(avfsbe.dentry);
00377                             mntput(avfsbe.mnt);
00378                      }
00379               }
00380        }
00381 
00382        if (ndentry->d_inode) {
00383               struct inode *ninode = ndentry->d_inode;
00384               inode = glassfs_alloc_inode(dir->i_sb);
00385               if (!inode) {
00386                      dput(ndentry);
00387                      mntput(nmnt);
00388                      return ERR_PTR(-ENOMEM);
00389               }
00390               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00391                                ndentry, nmnt, curravfs);
00392        }
00393 
00394        dentry->d_op = &glassfs_dentry_operations;
00395        dput(ndentry);
00396        mntput(nmnt);
00397        
00398        return d_splice_alias(inode, dentry);
00399 }
00400 
00401 static int glassfs_permission(struct inode *inode, int mask,
00402                         struct nameidata *nd)
00403 {
00404        struct base_entry *be = inode->u.generic_ip;
00405        struct inode *ninode = be->dentry->d_inode;
00406 //     printk("glassfs_permission\n");
00407        /* Exec needs i_mode to contain the correct permission bits */
00408        inode->i_mode = ninode->i_mode;
00409        return permission(ninode, mask, NULL);
00410 }
00411 
00412 static int glassfs_create(struct inode *dir, struct dentry *dentry,
00413                        int mode, struct nameidata *nd)
00414 {
00415        int err;
00416        struct base_entry *be = dir->u.generic_ip;
00417        struct inode *ndir = be->dentry->d_inode;
00418        struct dentry *ndentry;
00419        struct inode *inode = glassfs_alloc_inode(dir->i_sb);
00420        if (!inode)
00421               return -ENOMEM;
00422 
00423 //     printk("glassfs_create\n");
00424        down(&ndir->i_sem);
00425        ndentry = lookup_hash(&dentry->d_name, be->dentry);
00426        if (IS_ERR(ndentry)) {
00427               err = PTR_ERR(ndentry);
00428               ndentry = NULL;
00429        }
00430        else
00431               err = vfs_create(ndir, ndentry, mode, NULL);
00432        up(&ndir->i_sem);
00433        if (!err && ndentry->d_inode) {
00434               struct inode *ninode = ndentry->d_inode;
00435               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00436                                ndentry, be->mnt, be->is_avfs);
00437               d_instantiate(dentry, inode);
00438        } else
00439               iput(inode);
00440 
00441        dput(ndentry);
00442 
00443        return err;
00444 }
00445 
00446 static int glassfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
00447 {
00448        int err;
00449        struct base_entry *be = dir->u.generic_ip;
00450        struct inode *ndir = be->dentry->d_inode;
00451        struct dentry *ndentry;
00452        struct inode *inode = glassfs_alloc_inode(dir->i_sb);
00453        if (!inode)
00454               return -ENOMEM;
00455 
00456 //     printk("glassfs_mkdir\n");
00457        down(&ndir->i_sem);
00458        ndentry = lookup_hash(&dentry->d_name, be->dentry);
00459        if (IS_ERR(ndentry)) {
00460               err = PTR_ERR(ndentry);
00461               ndentry = NULL;
00462        } else 
00463               err = vfs_mkdir(ndir, ndentry, mode);
00464        up(&ndir->i_sem);
00465        if (!err && ndentry->d_inode) {
00466               struct inode *ninode = ndentry->d_inode;
00467               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00468                                ndentry, be->mnt, be->is_avfs);
00469               d_instantiate(dentry, inode);
00470        } else
00471               iput(inode);
00472 
00473        dput(ndentry);
00474 
00475        return err;
00476 }
00477 
00478 static int glassfs_link(struct dentry *old_dentry, struct inode *dir,
00479                      struct dentry *new_dentry)
00480 {
00481        int err;
00482        struct base_entry *be = dir->u.generic_ip;
00483        struct base_entry *old_be = old_dentry->d_inode->u.generic_ip;
00484        struct inode *ndir = be->dentry->d_inode;
00485        struct dentry *new_ndentry;
00486        struct inode *inode;
00487 
00488        if (be->mnt != old_be->mnt)
00489               return -EXDEV;
00490 
00491        inode = glassfs_alloc_inode(dir->i_sb);
00492        if (!inode)
00493               return -ENOMEM;
00494 
00495 //     printk("glassfs_link\n");
00496        down(&ndir->i_sem);
00497        new_ndentry = lookup_hash(&new_dentry->d_name, be->dentry);
00498        if (IS_ERR(new_ndentry)) {
00499               err = PTR_ERR(new_ndentry);
00500               new_ndentry = NULL;
00501        } else 
00502               err = vfs_link(old_be->dentry, ndir, new_ndentry);
00503        up(&ndir->i_sem);
00504        if (!err && new_ndentry->d_inode) {
00505               struct inode *ninode = new_ndentry->d_inode;
00506               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00507                                new_ndentry, be->mnt, be->is_avfs);
00508               d_instantiate(new_dentry, inode);
00509        } else
00510               iput(inode);
00511 
00512        dput(new_ndentry);
00513 
00514        return err;
00515 }
00516 
00517 static int glassfs_symlink(struct inode *dir, struct dentry *dentry,
00518                         const char *oldname)
00519 {
00520        int err;
00521        struct base_entry *be = dir->u.generic_ip;
00522        struct inode *ndir = be->dentry->d_inode;
00523        struct dentry *ndentry;
00524        struct inode *inode = glassfs_alloc_inode(dir->i_sb);
00525        if (!inode)
00526               return -ENOMEM;
00527 
00528 //     printk("glassfs_symlink\n");
00529        down(&ndir->i_sem);
00530        ndentry = lookup_hash(&dentry->d_name, be->dentry);
00531        if (IS_ERR(ndentry)) {
00532               err = PTR_ERR(ndentry);
00533               ndentry = NULL;
00534        } else 
00535               err = vfs_symlink(ndir, ndentry, oldname);
00536        up(&ndir->i_sem);
00537        if (!err && ndentry->d_inode) {
00538               struct inode *ninode = ndentry->d_inode;
00539               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00540                                ndentry, be->mnt, be->is_avfs);
00541               d_instantiate(dentry, inode);
00542        } else
00543               iput(inode);
00544 
00545        dput(ndentry);
00546 
00547        return err;
00548 }
00549 
00550 static int glassfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
00551                       dev_t dev)
00552 {
00553        int err;
00554        struct base_entry *be = dir->u.generic_ip;
00555        struct inode *ndir = be->dentry->d_inode;
00556        struct dentry *ndentry;
00557        struct inode *inode = glassfs_alloc_inode(dir->i_sb);
00558        if (!inode)
00559               return -ENOMEM;
00560 
00561 //     printk("glassfs_mknod\n");
00562        down(&ndir->i_sem);
00563        ndentry = lookup_hash(&dentry->d_name, be->dentry);
00564        if (IS_ERR(ndentry)) {
00565               err = PTR_ERR(ndentry);
00566               ndentry = NULL;
00567        } else 
00568               err = vfs_mknod(ndir, ndentry, mode, dev);
00569        up(&ndir->i_sem);
00570        if (!err && ndentry->d_inode) {
00571               struct inode *ninode = ndentry->d_inode;
00572               glassfs_fill_inode(inode, ninode->i_mode, ninode->i_rdev,
00573                                ndentry, be->mnt, be->is_avfs);
00574               d_instantiate(dentry, inode);
00575        } else
00576               iput(inode);
00577        
00578        dput(ndentry);
00579 
00580        return err;
00581 }
00582 
00583 static int glassfs_rename(struct inode *old_dir, struct dentry *old_dentry,
00584                        struct inode *new_dir, struct dentry *new_dentry)
00585 {
00586        int err;
00587        struct base_entry *old_be = old_dir->u.generic_ip;
00588        struct base_entry *new_be = new_dir->u.generic_ip;
00589        struct inode *old_ndir = old_be->dentry->d_inode;
00590        struct inode *new_ndir = new_be->dentry->d_inode;
00591        struct dentry *old_ndentry = NULL;
00592        struct dentry *new_ndentry = NULL;
00593        struct dentry *trap;
00594 
00595        if (old_be->mnt != new_be->mnt)
00596               return -EXDEV;
00597 
00598        trap = lock_rename(new_be->dentry, old_be->dentry);
00599        old_ndentry = lookup_hash(&old_dentry->d_name, old_be->dentry);
00600        if (IS_ERR(old_ndentry)) {
00601               err = PTR_ERR(old_ndentry);
00602               old_ndentry = NULL;
00603               goto out;
00604        }
00605        if (old_ndentry == trap) {
00606               err = -EINVAL;
00607               goto out;
00608        }
00609        if (!old_ndentry->d_inode) {
00610               err = -ENOENT;
00611               goto out;
00612        }
00613               
00614        new_ndentry = lookup_hash(&new_dentry->d_name, new_be->dentry);
00615        if (IS_ERR(new_ndentry)) {
00616               err = PTR_ERR(new_ndentry);
00617               new_ndentry = NULL;
00618               goto out;
00619        }
00620        if (new_ndentry == trap) {
00621               err = -ENOTEMPTY;
00622               goto out;
00623        }
00624        err = vfs_rename(old_ndir, old_ndentry, new_ndir, new_ndentry);
00625 
00626   out:
00627        unlock_rename(new_be->dentry, old_be->dentry);
00628        dput(new_ndentry);
00629        dput(old_ndentry);
00630        
00631        return err;
00632 }
00633 
00634 static int glassfs_unlink(struct inode *dir, struct dentry *dentry)
00635 {
00636        int err;
00637        struct base_entry *dir_be = dir->u.generic_ip;
00638        struct inode *ndir = dir_be->dentry->d_inode;
00639        struct base_entry *be = dentry->d_inode->u.generic_ip;
00640 
00641 //     printk("glassfs_unlink\n");
00642        down(&ndir->i_sem);
00643        err = vfs_unlink(ndir, be->dentry);
00644        up(&ndir->i_sem);
00645        if (!err)
00646               dentry->d_inode->i_nlink = 0;
00647        
00648        return err;
00649 }
00650 
00651 static int glassfs_rmdir(struct inode *dir, struct dentry *dentry)
00652 {
00653        int err;
00654        struct base_entry *dir_be = dir->u.generic_ip;
00655        struct inode *ndir = dir_be->dentry->d_inode;
00656        struct base_entry *be = dentry->d_inode->u.generic_ip;
00657 
00658 //     printk("glassfs_rmdir\n");
00659        down(&ndir->i_sem);
00660        err = vfs_rmdir(ndir, be->dentry);
00661        up(&ndir->i_sem);
00662        if (!err)
00663               dentry->d_inode->i_nlink = 0;
00664        return err;
00665 }
00666 
00667 static int glassfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
00668                         struct kstat *stat)
00669 {
00670        struct base_entry *be = dentry->d_inode->u.generic_ip;
00671        //printk("glassfs_getattr (is avfs: %i)\n", be->is_avfs);
00672        return vfs_getattr(be->mnt, be->dentry, stat);
00673 }
00674 
00675 static int glassfs_setattr(struct dentry *dentry, struct iattr *attr)
00676 {
00677        int err;
00678        struct base_entry *be = dentry->d_inode->u.generic_ip;
00679        struct inode *ninode = be->dentry->d_inode;
00680        
00681        if (IS_RDONLY(ninode))
00682               return -EROFS;
00683 
00684        if (IS_IMMUTABLE(ninode) || IS_APPEND(ninode))
00685               return -EPERM;
00686 
00687        down(&ninode->i_sem);
00688        err = notify_change(be->dentry, attr);
00689        up(&ninode->i_sem);
00690        return err;
00691 }
00692 
00693 static int glassfs_setxattr(struct dentry *dentry, const char *name,
00694                          const void *value, size_t size, int flags)
00695 {
00696        int err;
00697        struct base_entry *be = dentry->d_inode->u.generic_ip;
00698        struct dentry *ndentry = be->dentry;
00699        struct inode *ninode = ndentry->d_inode;
00700        
00701        err = -EOPNOTSUPP;
00702        if (ninode->i_op && ninode->i_op->setxattr) {
00703               down(&ninode->i_sem);
00704               err = security_inode_setxattr(ndentry, (char *) name, (void *) value, size, flags);
00705               if (!err) {
00706                      err = ninode->i_op->setxattr(ndentry, name, value, size, flags);
00707                      if (!err)
00708                             security_inode_post_setxattr(ndentry, (char *) name, (void *) value, size, flags);
00709               }
00710               up(&ninode->i_sem);
00711        }
00712        return err;
00713 }
00714 
00715 static ssize_t glassfs_getxattr(struct dentry *dentry, const char *name, 
00716                             void *value, size_t size)
00717 {
00718        ssize_t err;
00719        struct base_entry *be = dentry->d_inode->u.generic_ip;
00720        struct dentry *ndentry = be->dentry;
00721        struct inode *ninode = ndentry->d_inode;
00722 
00723        err = -EOPNOTSUPP;
00724        if (ninode->i_op && ninode->i_op->getxattr) {
00725               err = security_inode_getxattr(ndentry, (char *) name);
00726               if (!err)
00727                      err = ninode->i_op->getxattr(ndentry, name, value, size);
00728        }
00729        return err;
00730 }
00731 static ssize_t glassfs_listxattr(struct dentry *dentry, char *list, size_t size)
00732 {
00733        ssize_t err;
00734        struct base_entry *be = dentry->d_inode->u.generic_ip;
00735        struct dentry *ndentry = be->dentry;
00736        struct inode *ninode = ndentry->d_inode;
00737 
00738        err = -EOPNOTSUPP;
00739        if (ninode->i_op && ninode->i_op->listxattr) {
00740               err = security_inode_listxattr(ndentry);
00741               if (!err)
00742                      err = ninode->i_op->listxattr(ndentry, list, size);
00743        }
00744        return err;
00745 }
00746 
00747 static int glassfs_removexattr(struct dentry *dentry, const char *name)
00748 {
00749        int err;
00750        struct base_entry *be = dentry->d_inode->u.generic_ip;
00751        struct dentry *ndentry = be->dentry;
00752        struct inode *ninode = ndentry->d_inode;
00753 
00754        err = -EOPNOTSUPP;
00755        if (ninode->i_op && ninode->i_op->removexattr) {
00756               err = security_inode_removexattr(ndentry, (char *) name);
00757               if (!err) {
00758                      /* strange: the security... usually is within
00759                            the locked region */
00760                      down(&ninode->i_sem);
00761                      err = ninode->i_op->removexattr(ndentry, name);
00762                      up(&ninode->i_sem);
00763               }
00764        }
00765        return err;
00766 }
00767 
00768 static int glassfs_statfs(struct super_block *sb, struct kstatfs *buf)
00769 {
00770        struct super_block *nsb = sb->s_fs_info;
00771 //     printk("glassfs_statfs\n");
00772        return vfs_statfs(nsb, buf);
00773 }
00774 
00775 static int glassfs_dentry_revalidate(struct dentry *dentry,
00776                                  struct nameidata *nd)
00777 {
00778        struct base_entry *be;
00779        //printk("glassfs_dentry_revalidate %.*s\n", dentry->d_name.len, dentry->d_name.name);
00780 
00781        if (!dentry->d_inode)
00782               return 0;
00783 
00784        be = dentry->d_inode->u.generic_ip;
00785        if (d_unhashed(be->dentry))
00786               return 0;
00787 
00788        if (be->dentry->d_op && be->dentry->d_op->d_revalidate)
00789               return be->dentry->d_op->d_revalidate(be->dentry, NULL);
00790        return 1;
00791 }
00792 
00793 static int glassfs_readlink (struct dentry *dentry, char __user *buf,
00794                            int buflen)
00795 {
00796 
00797        int err;
00798        struct base_entry *be = dentry->d_inode->u.generic_ip;
00799        struct dentry *ndentry = be->dentry;
00800        struct inode *ninode = ndentry->d_inode;
00801        
00802        err = -EINVAL;
00803        if (ninode->i_op && ninode->i_op->readlink) {
00804               err = security_inode_readlink(ndentry);
00805               if (!err) {
00806                      update_atime(ninode);
00807                      err = ninode->i_op->readlink(ndentry, buf, buflen);
00808               }
00809        }
00810        return err;
00811 }
00812 
00813 static int glassfs_follow_link(struct dentry *dentry, struct nameidata *nd)
00814 {
00815        int err = 0;
00816        struct base_entry *be = dentry->d_inode->u.generic_ip;
00817        struct dentry *ndentry = be->dentry;
00818        struct inode *ninode = ndentry->d_inode;
00819        
00820        if (ninode->i_op && ninode->i_op->follow_link) {
00821               err = security_inode_follow_link(ndentry, nd);
00822               if (!err) {
00823                      update_atime(ninode);
00824                      err = ninode->i_op->follow_link(ndentry, nd);
00825               }
00826        }
00827        return err;
00828 }
00829 
00830 static void glassfs_clear_inode(struct inode *inode)
00831 {
00832        struct base_entry *be = inode->u.generic_ip;
00833        //printk("glassfs_clear_inode\n");
00834        dput(be->dentry);
00835        mntput(be->mnt);
00836        kfree(be);
00837 }
00838 
00839 static struct dentry_operations glassfs_dentry_operations = {
00840        .d_revalidate = glassfs_dentry_revalidate,
00841 };
00842 
00843 static struct file_operations glassfs_dir_operations = {
00844        .llseek              = glassfs_llseek,
00845        .read         = generic_read_dir, /* Every FS does this */
00846        .readdir      = glassfs_readdir,
00847        .ioctl        = glassfs_ioctl,
00848        .open         = glassfs_open_dir,
00849        .flush        = glassfs_flush,
00850        .release      = glassfs_release,
00851        .fsync        = glassfs_fsync,
00852 };
00853 
00854 static struct file_operations glassfs_file_operations = {
00855        .open         = glassfs_open,
00856 };
00857 
00858 static struct inode_operations glassfs_dir_inode_operations = {
00859        .create              = glassfs_create,
00860        .lookup              = glassfs_lookup,
00861        .link         = glassfs_link,
00862        .unlink              = glassfs_unlink,
00863        .symlink      = glassfs_symlink,
00864        .mkdir        = glassfs_mkdir,
00865        .rmdir        = glassfs_rmdir,
00866        .mknod        = glassfs_mknod,
00867        .rename              = glassfs_rename,
00868        .permission   = glassfs_permission,
00869        .getattr      = glassfs_getattr,
00870        .setattr      = glassfs_setattr,
00871        .setxattr     = glassfs_setxattr,
00872        .getxattr     = glassfs_getxattr,
00873        .listxattr    = glassfs_listxattr,
00874        .removexattr  = glassfs_removexattr,
00875 };
00876 
00877 static struct inode_operations glassfs_file_inode_operations = {
00878        .permission   = glassfs_permission,
00879        .getattr      = glassfs_getattr,
00880        .setattr      = glassfs_setattr,
00881        .setxattr     = glassfs_setxattr,
00882        .getxattr     = glassfs_getxattr,
00883        .listxattr    = glassfs_listxattr,
00884        .removexattr  = glassfs_removexattr,
00885 };
00886 
00887 static struct inode_operations glassfs_symlink_inode_operations = {
00888        .readlink     = glassfs_readlink,
00889        .follow_link  = glassfs_follow_link,
00890        .permission   = glassfs_permission,
00891        .getattr      = glassfs_getattr,
00892        .setattr      = glassfs_setattr,
00893        .setxattr     = glassfs_setxattr,
00894        .getxattr     = glassfs_getxattr,
00895        .listxattr    = glassfs_listxattr,
00896        .removexattr  = glassfs_removexattr,
00897 };
00898 
00899 
00900 static struct super_operations glassfs_ops = {
00901        .statfs              = glassfs_statfs,
00902        .clear_inode  = glassfs_clear_inode,
00903 };
00904 
00905 
00906 static int glassfs_fill_super(struct super_block * sb, void * data, int silent)
00907 {
00908        struct inode * inode;
00909        struct dentry * root;
00910        struct super_block *nsb;
00911        struct dentry * nroot;
00912        struct vfsmount *nmnt;
00913 
00914        inode = glassfs_alloc_inode(sb);
00915        if (!inode)
00916               return -ENOMEM;
00917        read_lock(&current->fs->lock);
00918        nroot = current->fs->root;
00919        nmnt = current->fs->rootmnt;
00920        glassfs_fill_inode(inode, S_IFDIR | 0755, 0, nroot, nmnt, 0);
00921        read_unlock(&current->fs->lock);
00922        
00923        nsb = nmnt->mnt_sb;
00924        sb->s_blocksize = nsb->s_blocksize;
00925        sb->s_blocksize_bits = nsb->s_blocksize_bits;
00926        sb->s_magic = GLASSFS_MAGIC;
00927        sb->s_op = &glassfs_ops;
00928 
00929        root = d_alloc_root(inode);
00930        if (!root) {
00931               iput(inode);
00932               return -ENOMEM;
00933        }
00934        sb->s_fs_info = nsb;
00935        root->d_op = &glassfs_dentry_operations;
00936 
00937        sb->s_root = root;
00938        return 0;
00939 }
00940 
00941 static struct super_block *glassfs_get_sb(struct file_system_type *fs_type,
00942        int flags, const char *dev_name, void *data)
00943 {
00944 //     printk("glassfs_get_sb\n");
00945        return get_sb_nodev(fs_type, flags, data, glassfs_fill_super);
00946 }
00947 
00948 static struct file_system_type glassfs_fs_type = {
00949        .owner        = THIS_MODULE,
00950        .name         = "glassfs",
00951        .get_sb              = glassfs_get_sb,
00952        .kill_sb      = kill_anon_super,
00953 };
00954 
00955 static int __init init_glassfs_fs(void)
00956 {
00957        return register_filesystem(&glassfs_fs_type);
00958 }
00959 
00960 static void __exit exit_glassfs_fs(void)
00961 {
00962        unregister_filesystem(&glassfs_fs_type);
00963 }
00964 
00965 
00966 module_init(init_glassfs_fs)
00967 module_exit(exit_glassfs_fs)
00968 
00969 
00970 MODULE_LICENSE("GPL");
00971 
00972 /* 
00973  * Local Variables:
00974  * indent-tabs-mode: t
00975  * c-basic-offset: 8
00976  * End:
00977  */