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

📄 journal.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Intermezzo. (C) 1998 Peter J. Braam * * Support for journalling extended attributes * (C) 2001 Shirish H. Phatak, Tacit Networks, Inc. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/time.h>#include <linux/errno.h>#include <linux/locks.h>#include <asm/segment.h>#include <asm/uaccess.h>#include <linux/string.h>#include <linux/smp_lock.h>#include <linux/intermezzo_fs.h>#include <linux/intermezzo_upcall.h>#include <linux/intermezzo_psdev.h>#include <linux/intermezzo_kml.h>static int presto_log(struct presto_file_set *fset, struct rec_info *rec,                      const char *buf, size_t size,                      const char *string1, int len1,                       const char *string2, int len2,                      const char *string3, int len3);/* *  reserve record space and/or atomically request state of the log *  rec will hold the location reserved record upon return *  this reservation will be placed in the queue */ static void presto_reserve_record(struct presto_file_set *fset,                            struct presto_log_fd *fd,                            struct rec_info *rec,                           struct presto_reservation_data *rd){        int chunked_record = 0;         ENTRY;                write_lock(&fd->fd_lock);        if ( rec->is_kml ) {                 int chunk = 1 << fset->fset_chunkbits;                int chunk_mask = ~(chunk -1);                 loff_t boundary;                 boundary =  (fd->fd_offset + chunk - 1) & chunk_mask;                if ( fd->fd_offset + rec->size >= boundary ) {                        chunked_record = 1;                        fd->fd_offset = boundary;                 }        }        fd->fd_recno++;                /* this move the fd_offset back after truncation */         if ( list_empty(&fd->fd_reservations) &&              !chunked_record) {                 fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;        }        rec->offset = fd->fd_offset;        rec->recno = fd->fd_recno;        fd->fd_offset += rec->size;        /* add the reservation data to the end of the list */        list_add(&rd->ri_list, fd->fd_reservations.prev);        rd->ri_offset = rec->offset;        rd->ri_size = rec->size;        rd->ri_recno = rec->recno;         write_unlock(&fd->fd_lock);         EXIT;}static inline void presto_release_record(struct presto_log_fd *fd,                                         struct presto_reservation_data *rd){        write_lock(&fd->fd_lock);        list_del(&rd->ri_list);        write_unlock(&fd->fd_lock);}static int presto_do_truncate(struct presto_file_set *fset,                               struct dentry *dentry, loff_t length,                               loff_t size_check){        struct inode *inode = dentry->d_inode;        struct inode_operations *op;         int error;        struct iattr newattrs;        ENTRY;        /* Not pretty: "inode->i_size" shouldn't really be "loff_t". */        if ((off_t) length < 0)                return -EINVAL;        fs_down(&inode->i_sem);        lock_kernel();                if (size_check != inode->i_size) {                 unlock_kernel();                fs_up(&inode->i_sem);                EXIT;                return -EALREADY;         }        newattrs.ia_size = length;        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;        op = filter_c2cfiops(fset->fset_cache->cache_filter);        if (op != NULL && op->setattr != NULL)                error = op->setattr(dentry, &newattrs);        else {                inode_setattr(dentry->d_inode, &newattrs);                /* Some filesystems, e.g. ext2 and older versions of ext3                   legitimately do not have a <fs>_setattr method. -SHP                */                /*                printk ("Warning:: int presto_do_truncate(xxx), op->setattr == NULL");		error = -EOPNOTSUPP; 		*/		error = 0;        }        unlock_kernel();        fs_up(&inode->i_sem);        EXIT;        return error;}void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,                         int op){        ENTRY;        if ( !fset->fset_cache->cache_filter->o_trops )                return NULL;        EXIT;        return fset->fset_cache->cache_filter->o_trops->tr_start                (fset, inode, op);}void presto_trans_commit(struct presto_file_set *fset, void *handle){        ENTRY;        if (!fset->fset_cache->cache_filter->o_trops )                return;        EXIT;        return fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);}inline int presto_no_journal(struct presto_file_set *fset){        int minor = fset->fset_cache->cache_psdev->uc_minor;        return upc_comms[minor].uc_no_journal;}#define size_round(x)  (((x)+3) & ~0x3)#define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)#define BUFF_ALLOC(newbuf, oldbuf)                      \        PRESTO_ALLOC(newbuf, char *, PAGE_SIZE);        \        if ( !newbuf ) {                                \                if (oldbuf)                             \                        BUFF_FREE(oldbuf);              \                return -ENOMEM;                         \        }/* * "buflen" should be PAGE_SIZE or more. * Give relative path wrt to a fsetroot */char * presto_path(struct dentry *dentry, struct dentry *root,                   char *buffer, int buflen){        char * end = buffer+buflen;        char * retval;        *--end = '\0';        buflen--;        if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {                buflen -= 10;                end -= 10;                memcpy(end, " (deleted)", 10);        }        /* Get '/' right */        retval = end-1;        *retval = '/';        for (;;) {                struct dentry * parent;                int namelen;                if (dentry == root)                        break;                parent = dentry->d_parent;                if (dentry == parent)                        break;                namelen = dentry->d_name.len;                buflen -= namelen + 1;                if (buflen < 0)                        break;                end -= namelen;                memcpy(end, dentry->d_name.name, namelen);                *--end = '/';                retval = end;                dentry = parent;        }        return retval;}static inline char *logit(char *buf, const void *value, int size){        char *ptr = (char *)value;        memcpy(buf, ptr, size);        buf += size;        return buf;}static inline char *journal_log_prefix_with_groups_and_ids(char *buf, int opcode,                                        struct rec_info *rec,                                       __u32 ngroups, gid_t *groups,                                       __u32 fsuid, __u32 fsgid){        struct big_journal_prefix p;        int i;         p.len = cpu_to_le32(rec->size);        p.version = PRESTO_KML_MAJOR_VERSION | PRESTO_KML_MINOR_VERSION;        p.pid = cpu_to_le32(current->pid);        p.uid = cpu_to_le32(current->uid);        p.fsuid = cpu_to_le32(fsuid);        p.fsgid = cpu_to_le32(fsgid);        p.ngroups = cpu_to_le32(ngroups);        p.opcode = cpu_to_le32(opcode);        for (i=0 ; i < ngroups ; i++)                p.groups[i] = cpu_to_le32((__u32) groups[i]);        buf = logit(buf, &p, sizeof(struct journal_prefix) +                     sizeof(__u32) * ngroups);        return buf;}static inline char *journal_log_prefix(char *buf, int opcode, struct rec_info *rec){	__u32 groups[NGROUPS_MAX]; 	int i; 	/* convert 16 bit gid's to 32 bit gid's */	for (i=0; i<current->ngroups; i++) 		groups[i] = (__u32) current->groups[i];	        return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,                                                      (__u32)current->ngroups,						      groups,                                                      (__u32)current->fsuid,                                                      (__u32)current->fsgid);}static inline char *journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec,                                __u32 ngroups, gid_t *groups){        return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,                                                      ngroups, groups,                                                      (__u32)current->fsuid,                                                      (__u32)current->fsgid);}static inline char *log_version(char *buf, struct dentry *dentry){        struct presto_version version;        presto_getversion(&version, dentry->d_inode);        return logit(buf, &version, sizeof(version));}static inline char *journal_log_suffix(char *buf, char *log,                                       struct presto_file_set *fset,                                       struct dentry *dentry,                                       struct rec_info *rec){        struct journal_suffix s;        struct journal_prefix *p = (struct journal_prefix *)log;#if 0	/* XXX needs to be done after reservation, 	   disable ths until version 1.2 */        if ( dentry ) {                 s.prevrec = cpu_to_le32(rec->offset - dentry->d_time);                dentry->d_time = (unsigned long) rec->offset;        } else {                 s.prevrec = -1;        }#endif	s.prevrec = 0;         /* record number needs to be filled in after reservation            s.recno = cpu_to_le32(rec->recno); */         s.time = cpu_to_le32(CURRENT_TIME);        s.len = cpu_to_le32(p->len);        return logit(buf, &s, sizeof(s));}int presto_close_journal_file(struct presto_file_set *fset){        int rc = 0;        int rc2 = 0;        int rc3 = 0;        ENTRY;        if ( fset->fset_kml.fd_file) {                rc =filp_close(fset->fset_kml.fd_file, 0);                fset->fset_kml.fd_file = NULL;        } else {                printk("hehehehe no filp\n");        }        if ( rc ) {                printk("presto: close files: kml filp won't close %d\n", rc);        }        if ( fset->fset_last_rcvd) {                rc2 = filp_close(fset->fset_last_rcvd, 0);                fset->fset_last_rcvd = NULL;        } else {                printk("hehehehe no filp\n");        }        if ( rc2 ) {                if ( !rc )                        rc = rc2;                printk("presto: close files: last_rcvd filp won't close %d\n", rc2);        }        if ( fset->fset_lml.fd_file) {                rc3 = filp_close(fset->fset_lml.fd_file, 0);                fset->fset_lml.fd_file = NULL;        } else {                printk("hehehehe no filp\n");        }        if ( rc3 ) {                if ( (!rc) && (!rc2) )                        rc = rc3;                printk("presto: close files: lml filp won't close %d\n", rc3);        }        return rc;}int presto_fwrite(struct file *file, const char *str, int len, loff_t *off){        int rc;        mm_segment_t old_fs;        ENTRY;        rc = -EINVAL;        if ( !off ) {                EXIT;                return rc;        }        if ( ! file ) {                EXIT;                return rc;        }        if ( ! file->f_op ) {                EXIT;                return rc;        }        if ( ! file->f_op->write ) {                EXIT;                return rc;        }        old_fs = get_fs();        set_fs(get_ds());        rc = file->f_op->write(file, str, len, off);        if (rc != len) {                printk("presto_fwrite: wrote %d bytes instead of "                       "%d at %ld\n", rc, len, (long)*off);                rc = -EIO;         }        set_fs(old_fs);        EXIT;        return rc;}

⌨️ 快捷键说明

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