Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * Directory operations for Coda filesystem
0005  * Original version: (C) 1996 P. Braam and M. Callahan
0006  * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
0007  * 
0008  * Carnegie Mellon encourages users to contribute improvements to
0009  * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
0010  */
0011 
0012 #include <linux/types.h>
0013 #include <linux/kernel.h>
0014 #include <linux/time.h>
0015 #include <linux/fs.h>
0016 #include <linux/slab.h>
0017 #include <linux/file.h>
0018 #include <linux/stat.h>
0019 #include <linux/errno.h>
0020 #include <linux/string.h>
0021 #include <linux/spinlock.h>
0022 #include <linux/namei.h>
0023 #include <linux/uaccess.h>
0024 
0025 #include <linux/coda.h>
0026 #include "coda_psdev.h"
0027 #include "coda_linux.h"
0028 #include "coda_cache.h"
0029 
0030 #include "coda_int.h"
0031 
0032 /* same as fs/bad_inode.c */
0033 static int coda_return_EIO(void)
0034 {
0035     return -EIO;
0036 }
0037 #define CODA_EIO_ERROR ((void *) (coda_return_EIO))
0038 
0039 /* inode operations for directories */
0040 /* access routines: lookup, readlink, permission */
0041 static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags)
0042 {
0043     struct super_block *sb = dir->i_sb;
0044     const char *name = entry->d_name.name;
0045     size_t length = entry->d_name.len;
0046     struct inode *inode;
0047     int type = 0;
0048 
0049     if (length > CODA_MAXNAMLEN) {
0050         pr_err("name too long: lookup, %s %zu\n",
0051                coda_i2s(dir), length);
0052         return ERR_PTR(-ENAMETOOLONG);
0053     }
0054 
0055     /* control object, create inode on the fly */
0056     if (is_root_inode(dir) && coda_iscontrol(name, length)) {
0057         inode = coda_cnode_makectl(sb);
0058         type = CODA_NOCACHE;
0059     } else {
0060         struct CodaFid fid = { { 0, } };
0061         int error = venus_lookup(sb, coda_i2f(dir), name, length,
0062                      &type, &fid);
0063         inode = !error ? coda_cnode_make(&fid, sb) : ERR_PTR(error);
0064     }
0065 
0066     if (!IS_ERR(inode) && (type & CODA_NOCACHE))
0067         coda_flag_inode(inode, C_VATTR | C_PURGE);
0068 
0069     if (inode == ERR_PTR(-ENOENT))
0070         inode = NULL;
0071 
0072     return d_splice_alias(inode, entry);
0073 }
0074 
0075 
0076 int coda_permission(struct user_namespace *mnt_userns, struct inode *inode,
0077             int mask)
0078 {
0079     int error;
0080 
0081     if (mask & MAY_NOT_BLOCK)
0082         return -ECHILD;
0083 
0084     mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
0085  
0086     if (!mask)
0087         return 0;
0088 
0089     if ((mask & MAY_EXEC) && !execute_ok(inode))
0090         return -EACCES;
0091 
0092     if (coda_cache_check(inode, mask))
0093         return 0;
0094 
0095     error = venus_access(inode->i_sb, coda_i2f(inode), mask);
0096     
0097     if (!error)
0098         coda_cache_enter(inode, mask);
0099 
0100     return error;
0101 }
0102 
0103 
0104 static inline void coda_dir_update_mtime(struct inode *dir)
0105 {
0106 #ifdef REQUERY_VENUS_FOR_MTIME
0107     /* invalidate the directory cnode's attributes so we refetch the
0108      * attributes from venus next time the inode is referenced */
0109     coda_flag_inode(dir, C_VATTR);
0110 #else
0111     /* optimistically we can also act as if our nose bleeds. The
0112      * granularity of the mtime is coarse anyways so we might actually be
0113      * right most of the time. Note: we only do this for directories. */
0114     dir->i_mtime = dir->i_ctime = current_time(dir);
0115 #endif
0116 }
0117 
0118 /* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a
0119  * trick to fool GNU find's optimizations. If we can't be sure of the link
0120  * (because of volume mount points) we set i_nlink to 1 which forces find
0121  * to consider every child as a possible directory. We should also never
0122  * see an increment or decrement for deleted directories where i_nlink == 0 */
0123 static inline void coda_dir_inc_nlink(struct inode *dir)
0124 {
0125     if (dir->i_nlink >= 2)
0126         inc_nlink(dir);
0127 }
0128 
0129 static inline void coda_dir_drop_nlink(struct inode *dir)
0130 {
0131     if (dir->i_nlink > 2)
0132         drop_nlink(dir);
0133 }
0134 
0135 /* creation routines: create, mknod, mkdir, link, symlink */
0136 static int coda_create(struct user_namespace *mnt_userns, struct inode *dir,
0137                struct dentry *de, umode_t mode, bool excl)
0138 {
0139     int error;
0140     const char *name=de->d_name.name;
0141     int length=de->d_name.len;
0142     struct inode *inode;
0143     struct CodaFid newfid;
0144     struct coda_vattr attrs;
0145 
0146     if (is_root_inode(dir) && coda_iscontrol(name, length))
0147         return -EPERM;
0148 
0149     error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
0150                 0, mode, &newfid, &attrs);
0151     if (error)
0152         goto err_out;
0153 
0154     inode = coda_iget(dir->i_sb, &newfid, &attrs);
0155     if (IS_ERR(inode)) {
0156         error = PTR_ERR(inode);
0157         goto err_out;
0158     }
0159 
0160     /* invalidate the directory cnode's attributes */
0161     coda_dir_update_mtime(dir);
0162     d_instantiate(de, inode);
0163     return 0;
0164 err_out:
0165     d_drop(de);
0166     return error;
0167 }
0168 
0169 static int coda_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
0170               struct dentry *de, umode_t mode)
0171 {
0172     struct inode *inode;
0173     struct coda_vattr attrs;
0174     const char *name = de->d_name.name;
0175     int len = de->d_name.len;
0176     int error;
0177     struct CodaFid newfid;
0178 
0179     if (is_root_inode(dir) && coda_iscontrol(name, len))
0180         return -EPERM;
0181 
0182     attrs.va_mode = mode;
0183     error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
0184                    name, len, &newfid, &attrs);
0185     if (error)
0186         goto err_out;
0187          
0188     inode = coda_iget(dir->i_sb, &newfid, &attrs);
0189     if (IS_ERR(inode)) {
0190         error = PTR_ERR(inode);
0191         goto err_out;
0192     }
0193 
0194     /* invalidate the directory cnode's attributes */
0195     coda_dir_inc_nlink(dir);
0196     coda_dir_update_mtime(dir);
0197     d_instantiate(de, inode);
0198     return 0;
0199 err_out:
0200     d_drop(de);
0201     return error;
0202 }
0203 
0204 /* try to make de an entry in dir_inodde linked to source_de */ 
0205 static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
0206       struct dentry *de)
0207 {
0208     struct inode *inode = d_inode(source_de);
0209         const char * name = de->d_name.name;
0210     int len = de->d_name.len;
0211     int error;
0212 
0213     if (is_root_inode(dir_inode) && coda_iscontrol(name, len))
0214         return -EPERM;
0215 
0216     error = venus_link(dir_inode->i_sb, coda_i2f(inode),
0217                coda_i2f(dir_inode), (const char *)name, len);
0218     if (error) {
0219         d_drop(de);
0220         return error;
0221     }
0222 
0223     coda_dir_update_mtime(dir_inode);
0224     ihold(inode);
0225     d_instantiate(de, inode);
0226     inc_nlink(inode);
0227     return 0;
0228 }
0229 
0230 
0231 static int coda_symlink(struct user_namespace *mnt_userns,
0232             struct inode *dir_inode, struct dentry *de,
0233             const char *symname)
0234 {
0235     const char *name = de->d_name.name;
0236     int len = de->d_name.len;
0237     int symlen;
0238     int error;
0239 
0240     if (is_root_inode(dir_inode) && coda_iscontrol(name, len))
0241         return -EPERM;
0242 
0243     symlen = strlen(symname);
0244     if (symlen > CODA_MAXPATHLEN)
0245         return -ENAMETOOLONG;
0246 
0247     /*
0248      * This entry is now negative. Since we do not create
0249      * an inode for the entry we have to drop it.
0250      */
0251     d_drop(de);
0252     error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
0253                   symname, symlen);
0254 
0255     /* mtime is no good anymore */
0256     if (!error)
0257         coda_dir_update_mtime(dir_inode);
0258 
0259     return error;
0260 }
0261 
0262 /* destruction routines: unlink, rmdir */
0263 static int coda_unlink(struct inode *dir, struct dentry *de)
0264 {
0265         int error;
0266     const char *name = de->d_name.name;
0267     int len = de->d_name.len;
0268 
0269     error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
0270     if (error)
0271         return error;
0272 
0273     coda_dir_update_mtime(dir);
0274     drop_nlink(d_inode(de));
0275     return 0;
0276 }
0277 
0278 static int coda_rmdir(struct inode *dir, struct dentry *de)
0279 {
0280     const char *name = de->d_name.name;
0281     int len = de->d_name.len;
0282     int error;
0283 
0284     error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
0285     if (!error) {
0286         /* VFS may delete the child */
0287         if (d_really_is_positive(de))
0288             clear_nlink(d_inode(de));
0289 
0290         /* fix the link count of the parent */
0291         coda_dir_drop_nlink(dir);
0292         coda_dir_update_mtime(dir);
0293     }
0294     return error;
0295 }
0296 
0297 /* rename */
0298 static int coda_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
0299                struct dentry *old_dentry, struct inode *new_dir,
0300                struct dentry *new_dentry, unsigned int flags)
0301 {
0302     const char *old_name = old_dentry->d_name.name;
0303     const char *new_name = new_dentry->d_name.name;
0304     int old_length = old_dentry->d_name.len;
0305     int new_length = new_dentry->d_name.len;
0306     int error;
0307 
0308     if (flags)
0309         return -EINVAL;
0310 
0311     error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
0312                  coda_i2f(new_dir), old_length, new_length,
0313                  (const char *) old_name, (const char *)new_name);
0314     if (!error) {
0315         if (d_really_is_positive(new_dentry)) {
0316             if (d_is_dir(new_dentry)) {
0317                 coda_dir_drop_nlink(old_dir);
0318                 coda_dir_inc_nlink(new_dir);
0319             }
0320             coda_flag_inode(d_inode(new_dentry), C_VATTR);
0321         }
0322         coda_dir_update_mtime(old_dir);
0323         coda_dir_update_mtime(new_dir);
0324     }
0325     return error;
0326 }
0327 
0328 static inline unsigned int CDT2DT(unsigned char cdt)
0329 {
0330     unsigned int dt;
0331 
0332     switch(cdt) {
0333     case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
0334     case CDT_FIFO:    dt = DT_FIFO;    break;
0335     case CDT_CHR:     dt = DT_CHR;     break;
0336     case CDT_DIR:     dt = DT_DIR;     break;
0337     case CDT_BLK:     dt = DT_BLK;     break;
0338     case CDT_REG:     dt = DT_REG;     break;
0339     case CDT_LNK:     dt = DT_LNK;     break;
0340     case CDT_SOCK:    dt = DT_SOCK;    break;
0341     case CDT_WHT:     dt = DT_WHT;     break;
0342     default:      dt = DT_UNKNOWN; break;
0343     }
0344     return dt;
0345 }
0346 
0347 /* support routines */
0348 static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
0349 {
0350     struct coda_file_info *cfi;
0351     struct coda_inode_info *cii;
0352     struct file *host_file;
0353     struct venus_dirent *vdir;
0354     unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
0355     unsigned int type;
0356     struct qstr name;
0357     ino_t ino;
0358     int ret;
0359 
0360     cfi = coda_ftoc(coda_file);
0361     host_file = cfi->cfi_container;
0362 
0363     cii = ITOC(file_inode(coda_file));
0364 
0365     vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
0366     if (!vdir) return -ENOMEM;
0367 
0368     if (!dir_emit_dots(coda_file, ctx))
0369         goto out;
0370 
0371     while (1) {
0372         loff_t pos = ctx->pos - 2;
0373 
0374         /* read entries from the directory file */
0375         ret = kernel_read(host_file, vdir, sizeof(*vdir), &pos);
0376         if (ret < 0) {
0377             pr_err("%s: read dir %s failed %d\n",
0378                    __func__, coda_f2s(&cii->c_fid), ret);
0379             break;
0380         }
0381         if (ret == 0) break; /* end of directory file reached */
0382 
0383         /* catch truncated reads */
0384         if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
0385             pr_err("%s: short read on %s\n",
0386                    __func__, coda_f2s(&cii->c_fid));
0387             ret = -EBADF;
0388             break;
0389         }
0390         /* validate whether the directory file actually makes sense */
0391         if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
0392             pr_err("%s: invalid dir %s\n",
0393                    __func__, coda_f2s(&cii->c_fid));
0394             ret = -EBADF;
0395             break;
0396         }
0397 
0398         name.len = vdir->d_namlen;
0399         name.name = vdir->d_name;
0400 
0401         /* Make sure we skip '.' and '..', we already got those */
0402         if (name.name[0] == '.' && (name.len == 1 ||
0403             (name.name[1] == '.' && name.len == 2)))
0404             vdir->d_fileno = name.len = 0;
0405 
0406         /* skip null entries */
0407         if (vdir->d_fileno && name.len) {
0408             ino = vdir->d_fileno;
0409             type = CDT2DT(vdir->d_type);
0410             if (!dir_emit(ctx, name.name, name.len, ino, type))
0411                 break;
0412         }
0413         /* we'll always have progress because d_reclen is unsigned and
0414          * we've already established it is non-zero. */
0415         ctx->pos += vdir->d_reclen;
0416     }
0417 out:
0418     kfree(vdir);
0419     return 0;
0420 }
0421 
0422 /* file operations for directories */
0423 static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
0424 {
0425     struct coda_file_info *cfi;
0426     struct file *host_file;
0427     int ret;
0428 
0429     cfi = coda_ftoc(coda_file);
0430     host_file = cfi->cfi_container;
0431 
0432     if (host_file->f_op->iterate || host_file->f_op->iterate_shared) {
0433         struct inode *host_inode = file_inode(host_file);
0434         ret = -ENOENT;
0435         if (!IS_DEADDIR(host_inode)) {
0436             if (host_file->f_op->iterate_shared) {
0437                 inode_lock_shared(host_inode);
0438                 ret = host_file->f_op->iterate_shared(host_file, ctx);
0439                 file_accessed(host_file);
0440                 inode_unlock_shared(host_inode);
0441             } else {
0442                 inode_lock(host_inode);
0443                 ret = host_file->f_op->iterate(host_file, ctx);
0444                 file_accessed(host_file);
0445                 inode_unlock(host_inode);
0446             }
0447         }
0448         return ret;
0449     }
0450     /* Venus: we must read Venus dirents from a file */
0451     return coda_venus_readdir(coda_file, ctx);
0452 }
0453 
0454 /* called when a cache lookup succeeds */
0455 static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
0456 {
0457     struct inode *inode;
0458     struct coda_inode_info *cii;
0459 
0460     if (flags & LOOKUP_RCU)
0461         return -ECHILD;
0462 
0463     inode = d_inode(de);
0464     if (!inode || is_root_inode(inode))
0465         goto out;
0466     if (is_bad_inode(inode))
0467         goto bad;
0468 
0469     cii = ITOC(d_inode(de));
0470     if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
0471         goto out;
0472 
0473     shrink_dcache_parent(de);
0474 
0475     /* propagate for a flush */
0476     if (cii->c_flags & C_FLUSH) 
0477         coda_flag_inode_children(inode, C_FLUSH);
0478 
0479     if (d_count(de) > 1)
0480         /* pretend it's valid, but don't change the flags */
0481         goto out;
0482 
0483     /* clear the flags. */
0484     spin_lock(&cii->c_lock);
0485     cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
0486     spin_unlock(&cii->c_lock);
0487 bad:
0488     return 0;
0489 out:
0490     return 1;
0491 }
0492 
0493 /*
0494  * This is the callback from dput() when d_count is going to 0.
0495  * We use this to unhash dentries with bad inodes.
0496  */
0497 static int coda_dentry_delete(const struct dentry * dentry)
0498 {
0499     struct inode *inode;
0500     struct coda_inode_info *cii;
0501 
0502     if (d_really_is_negative(dentry)) 
0503         return 0;
0504 
0505     inode = d_inode(dentry);
0506     if (!inode || is_bad_inode(inode))
0507         return 1;
0508 
0509     cii = ITOC(inode);
0510     if (cii->c_flags & C_PURGE)
0511         return 1;
0512 
0513     return 0;
0514 }
0515 
0516 
0517 
0518 /*
0519  * This is called when we want to check if the inode has
0520  * changed on the server.  Coda makes this easy since the
0521  * cache manager Venus issues a downcall to the kernel when this 
0522  * happens 
0523  */
0524 int coda_revalidate_inode(struct inode *inode)
0525 {
0526     struct coda_vattr attr;
0527     int error;
0528     int old_mode;
0529     ino_t old_ino;
0530     struct coda_inode_info *cii = ITOC(inode);
0531 
0532     if (!cii->c_flags)
0533         return 0;
0534 
0535     if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
0536         error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
0537         if (error)
0538             return -EIO;
0539 
0540         /* this inode may be lost if:
0541            - it's ino changed 
0542            - type changes must be permitted for repair and
0543            missing mount points.
0544         */
0545         old_mode = inode->i_mode;
0546         old_ino = inode->i_ino;
0547         coda_vattr_to_iattr(inode, &attr);
0548 
0549         if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
0550             pr_warn("inode %ld, fid %s changed type!\n",
0551                 inode->i_ino, coda_f2s(&(cii->c_fid)));
0552         }
0553 
0554         /* the following can happen when a local fid is replaced 
0555            with a global one, here we lose and declare the inode bad */
0556         if (inode->i_ino != old_ino)
0557             return -EIO;
0558         
0559         coda_flag_inode_children(inode, C_FLUSH);
0560 
0561         spin_lock(&cii->c_lock);
0562         cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
0563         spin_unlock(&cii->c_lock);
0564     }
0565     return 0;
0566 }
0567 
0568 const struct dentry_operations coda_dentry_operations = {
0569     .d_revalidate   = coda_dentry_revalidate,
0570     .d_delete   = coda_dentry_delete,
0571 };
0572 
0573 const struct inode_operations coda_dir_inode_operations = {
0574     .create     = coda_create,
0575     .lookup     = coda_lookup,
0576     .link       = coda_link,
0577     .unlink     = coda_unlink,
0578     .symlink    = coda_symlink,
0579     .mkdir      = coda_mkdir,
0580     .rmdir      = coda_rmdir,
0581     .mknod      = CODA_EIO_ERROR,
0582     .rename     = coda_rename,
0583     .permission = coda_permission,
0584     .getattr    = coda_getattr,
0585     .setattr    = coda_setattr,
0586 };
0587 
0588 const struct file_operations coda_dir_operations = {
0589     .llseek     = generic_file_llseek,
0590     .read       = generic_read_dir,
0591     .iterate    = coda_readdir,
0592     .open       = coda_open,
0593     .release    = coda_release,
0594     .fsync      = coda_fsync,
0595 };