⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
                return error;        }	presto_unlock(dir);         if ( presto_get_permit(dir) < 0 ) {                EXIT;                presto_fulllock(dir);                return -EROFS;        }        memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;	presto_relock_sem(dir); 	parent = dentry->d_parent;        error = presto_do_mkdir(fset, parent, dentry, mode, &info);	presto_relock_other(dir);         presto_put_permit(dir);        return error;}static int presto_symlink(struct inode *dir, struct dentry *dentry,                   const char *name){        int error;        struct presto_cache *cache;        struct presto_file_set *fset;        struct dentry *parent = dentry->d_parent;        struct lento_vfs_context info;        ENTRY;        error = presto_prep(dentry->d_parent, &cache, &fset);        if ( error ) {                EXIT;                return error;        }        presto_unlock(dir);        if ( presto_get_permit(dir) < 0 ) {                EXIT;		presto_fulllock(dir);                return -EROFS;        }	presto_relock_sem(dir);        parent = dentry->d_parent;        memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;        error = presto_do_symlink(fset, parent, dentry, name, &info);        presto_relock_other(dir);        presto_put_permit(dir);        return error;}int presto_unlink(struct inode *dir, struct dentry *dentry){        int error;        struct presto_cache *cache;        struct presto_file_set *fset;        struct dentry *parent = dentry->d_parent;        struct lento_vfs_context info;        ENTRY;        error = presto_prep(dentry->d_parent, &cache, &fset);        if ( error  ) {                EXIT;                return error;        }        presto_unlock(dir);        if ( presto_get_permit(dir) < 0 ) {                EXIT;		presto_fulllock(dir);                return -EROFS;        }	presto_relock_sem(dir);        parent = dentry->d_parent;        memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;        error = presto_do_unlink(fset, parent, dentry, &info);        presto_relock_other(dir);        presto_put_permit(dir);        return error;}static int presto_rmdir(struct inode *dir, struct dentry *dentry){        int error;        struct presto_cache *cache;        struct presto_file_set *fset;        struct dentry *parent = dentry->d_parent;        struct lento_vfs_context info;        ENTRY;        CDEBUG(D_FILE, "prepping presto\n");        error = presto_prep(dentry->d_parent, &cache, &fset);        if ( error ) {                EXIT;                return error;        }        CDEBUG(D_FILE, "unlocking\n");        /* We need to dget() before the dput in double_unlock, to ensure we         * still have dentry references.  double_lock doesn't do dget for us.         */	unlock_kernel();	if (d_unhashed(dentry))		d_rehash(dentry);        double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);        double_up(&dir->i_sem, &dentry->d_inode->i_sem);        CDEBUG(D_FILE, "getting permit\n");        if ( presto_get_permit(parent->d_inode) < 0 ) {                EXIT;		double_down(&dir->i_sem, &dentry->d_inode->i_sem);		double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);				lock_kernel();                return -EROFS;        }        CDEBUG(D_FILE, "locking\n");	double_down(&dir->i_sem, &dentry->d_inode->i_sem);	parent = dentry->d_parent;        memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;        error = presto_do_rmdir(fset, parent, dentry, &info);        presto_put_permit(parent->d_inode);	lock_kernel();        EXIT;        return error;}static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev){        int error;        struct presto_cache *cache;        struct presto_file_set *fset;        struct dentry *parent = dentry->d_parent;        struct lento_vfs_context info;        ENTRY;        error = presto_prep(dentry->d_parent, &cache, &fset);        if ( error  ) {                EXIT;                return error;        }        presto_unlock(dir);        if ( presto_get_permit(dir) < 0 ) {                EXIT;                presto_fulllock(dir);                return -EROFS;        }		presto_relock_sem(dir);        parent = dentry->d_parent;        memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;        error = presto_do_mknod(fset, parent, dentry, mode, rdev, &info);        presto_relock_other(dir);        presto_put_permit(dir);        EXIT;        return error;}inline void presto_triple_unlock(struct inode *old_dir, struct inode *new_dir, 				 struct dentry *old_dentry, 				 struct dentry *new_dentry, int triple){	/* rename_dir case */ 	if (S_ISDIR(old_dentry->d_inode->i_mode)) { 		if (triple) {						triple_up(&old_dir->i_zombie,				  &new_dir->i_zombie,				  &new_dentry->d_inode->i_zombie);		} else { 			double_up(&old_dir->i_zombie,				  &new_dir->i_zombie);		}		up(&old_dir->i_sb->s_vfs_rename_sem);	} else /* this case is rename_other */		double_up(&old_dir->i_zombie, &new_dir->i_zombie);	/* done by do_rename */	unlock_kernel();	double_up(&old_dir->i_sem, &new_dir->i_sem);}inline void presto_triple_fulllock(struct inode *old_dir, 				   struct inode *new_dir, 				   struct dentry *old_dentry, 				   struct dentry *new_dentry, int triple){	/* done by do_rename */	double_down(&old_dir->i_sem, &new_dir->i_sem);	lock_kernel();	/* rename_dir case */ 	if (S_ISDIR(old_dentry->d_inode->i_mode)) { 		down(&old_dir->i_sb->s_vfs_rename_sem);		if (triple) {						triple_down(&old_dir->i_zombie,				  &new_dir->i_zombie,				  &new_dentry->d_inode->i_zombie);		} else { 			double_down(&old_dir->i_zombie,				  &new_dir->i_zombie);		}	} else /* this case is rename_other */		double_down(&old_dir->i_zombie, &new_dir->i_zombie);}inline void presto_triple_relock_sem(struct inode *old_dir, 				   struct inode *new_dir, 				   struct dentry *old_dentry, 				   struct dentry *new_dentry, int triple){	/* done by do_rename */	double_down(&old_dir->i_sem, &new_dir->i_sem);	lock_kernel();}inline void presto_triple_relock_other(struct inode *old_dir, 				   struct inode *new_dir, 				   struct dentry *old_dentry, 				   struct dentry *new_dentry, int triple){	/* rename_dir case */ 	if (S_ISDIR(old_dentry->d_inode->i_mode)) { 		down(&old_dir->i_sb->s_vfs_rename_sem);		if (triple) {						triple_down(&old_dir->i_zombie,				  &new_dir->i_zombie,				  &new_dentry->d_inode->i_zombie);		} else { 			double_down(&old_dir->i_zombie,				  &new_dir->i_zombie);		}	} else /* this case is rename_other */		double_down(&old_dir->i_zombie, &new_dir->i_zombie);}// XXX this can be optimized: renamtes across filesets only require //     multiple KML records, but can locally be executed normally. int presto_rename(struct inode *old_dir, struct dentry *old_dentry,                  struct inode *new_dir, struct dentry *new_dentry){        int error;        struct presto_cache *cache, *new_cache;        struct presto_file_set *fset, *new_fset;        struct lento_vfs_context info;        struct dentry *old_parent = old_dentry->d_parent;        struct dentry *new_parent = new_dentry->d_parent;        int triple;        ENTRY;        error = presto_prep(old_dentry, &cache, &fset);        if ( error ) {                EXIT;                return error;        }        error = presto_prep(new_parent, &new_cache, &new_fset);        if ( error ) {                EXIT;                return error;        }        if ( fset != new_fset ) {                EXIT;                return -EXDEV;        }        /* We need to do dget before the dput in double_unlock, to ensure we         * still have dentry references.  double_lock doesn't do dget for us.         */        triple = (S_ISDIR(old_dentry->d_inode->i_mode) && new_dentry->d_inode)?                1:0;	presto_triple_unlock(old_dir, new_dir, old_dentry, new_dentry, triple);         if ( presto_get_permit(old_dir) < 0 ) {                EXIT;		presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple);                 return -EROFS;        }        if ( presto_get_permit(new_dir) < 0 ) {                EXIT;		presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple);                 return -EROFS;        }	presto_triple_relock_sem(old_dir, new_dir, old_dentry, new_dentry, triple);         memset(&info, 0, sizeof(info));        if (!ISLENTO(presto_c2m(cache)))                info.flags = LENTO_FL_KML;	info.flags |= LENTO_FL_IGNORE_TIME;        error = presto_do_rename(fset, old_parent, old_dentry, new_parent,                                 new_dentry, &info);	presto_triple_relock_other(old_dir, new_dir, old_dentry, new_dentry, triple);         presto_put_permit(new_dir);        presto_put_permit(old_dir);        return error;}/* basically this allows the ilookup processes access to all files for * reading, while not making ilookup totally insecure.  This could all * go away if we could set the CAP_DAC_READ_SEARCH capability for the client. *//* If posix acls are available, the underlying cache fs will export the * appropriate permission function. Thus we do not worry here about ACLs * or EAs. -SHP */int presto_permission(struct inode *inode, int mask){        unsigned short mode = inode->i_mode;        struct presto_cache *cache;        int rc;        ENTRY;        if ( presto_can_ilookup() && !(mask & S_IWOTH)) {                CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino);                EXIT;                return 0;        }        cache = presto_get_cache(inode);        if ( cache ) {                /* we only override the file/dir permission operations */                struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);                struct inode_operations *diops = filter_c2cdiops(cache->cache_filter);                if ( S_ISREG(mode) && fiops && fiops->permission ) {                        EXIT;                        return fiops->permission(inode, mask);                }                if ( S_ISDIR(mode) && diops && diops->permission ) {                        EXIT;                        return diops->permission(inode, mask);                }        }        /* The cache filesystem doesn't have its own permission function,         * but we don't want to duplicate the VFS code here.  In order         * to avoid looping from permission calling this function again,         * we temporarily override the permission operation while we call         * the VFS permission function.         */        inode->i_op->permission = NULL;        rc = permission(inode, mask);        inode->i_op->permission = &presto_permission;        EXIT;        return rc;}static int presto_dir_open(struct inode *inode, struct file *file){        int rc = 0;        struct dentry *de = file->f_dentry;        struct file_operations *fops;        struct presto_cache *cache;        struct presto_file_set *fset;        int minor;        int error;         ENTRY;        error = presto_prep(file->f_dentry, &cache, &fset);        if ( error  ) {                EXIT;                make_bad_inode(inode);                return error;        }        minor = presto_c2m(cache);        CDEBUG(D_CACHE, "minor %d, DATA_OK: %d, ino: %ld\n",               minor, presto_chk(de, PRESTO_DATA), inode->i_ino);        if ( ISLENTO(minor) )                goto cache;        if ( !presto_chk(de, PRESTO_DATA) ) {                CDEBUG(D_CACHE, "doing lento_opendir\n");                rc = presto_opendir_upcall(minor, file->f_dentry, fset->fset_mtpt, SYNCHRONOUS);        }        if ( rc ) {                printk("presto_dir_open: DATA_OK: %d, ino: %ld, error %d\n",                       presto_chk(de, PRESTO_DATA), inode->i_ino, rc);                return rc ;        } cache:        fops = filter_c2cdfops(cache->cache_filter);        if ( fops->open ) {                rc = fops->open(inode, file);        }        presto_set(de, PRESTO_DATA | PRESTO_ATTR);        CDEBUG(D_CACHE, "returns %d, data %d, attr %d\n", rc,               presto_chk(de, PRESTO_DATA), presto_chk(de, PRESTO_ATTR));        return 0;}struct file_operations presto_dir_fops = {        open: presto_dir_open};struct inode_operations presto_dir_iops = {        create: presto_create,        lookup: presto_lookup,        link:   presto_link,        unlink: presto_unlink,        symlink:        presto_symlink,        mkdir:  presto_mkdir,        rmdir:  presto_rmdir,        mknod:  presto_mknod,        rename: presto_rename,        permission:     presto_permission,        setattr:        presto_setattr,#ifdef CONFIG_FS_EXT_ATTR	set_ext_attr:	presto_set_ext_attr,#endif};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -