On Sat, Mar 10, 2018 at 10:17:45AM -0800, Andiry Xu wrote:
> From: Andiry Xu <jix...@cs.ucsd.edu>
> 
> inode.h defines the non-volatile and volatile NOVA inode data structures.
> 
> The non-volatile NOVA inode (nova_inode) is aligned to 128 bytes and contains
> file/directory metadata information. The most important fields
> are log_head and log_tail. log_head points to the start of
> the log, and log_tail points to the end of the latest committed
> log entry. NOVA make updates to the inode by appending
> to the log tail and update the log_tail pointer atomically.
> 
> The volatile NOVA inode (nova_inode_info) contains necessary
> information to limit access to the non-volatile NOVA inode during runtime.
> It has a radix tree to map file offset or filenames to the corresponding
> log entries.
> 
> Signed-off-by: Andiry Xu <jix...@cs.ucsd.edu>
> ---
>  fs/nova/inode.h | 187 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 187 insertions(+)
>  create mode 100644 fs/nova/inode.h
> 
> diff --git a/fs/nova/inode.h b/fs/nova/inode.h
> new file mode 100644
> index 0000000..f9187e3
> --- /dev/null
> +++ b/fs/nova/inode.h
> @@ -0,0 +1,187 @@
> +#ifndef __INODE_H
> +#define __INODE_H
> +
> +struct nova_inode_info_header;
> +struct nova_inode;
> +
> +#include "super.h"
> +
> +enum nova_new_inode_type {
> +     TYPE_CREATE = 0,
> +     TYPE_MKNOD,
> +     TYPE_SYMLINK,
> +     TYPE_MKDIR
> +};
> +
> +
> +/*
> + * Structure of an inode in PMEM
> + * Keep the inode size to within 120 bytes: We use the last eight bytes
> + * as inode table tail pointer.

I would've expected a
BUILD_BUG_ON(NOVA_INODE_SIZE - sizeof(struct nova_inode) == 8);
or something to enforce this.

(Or just equate inode number with byte offset?  I looked ahead at the
directory entries and they seem to be 64-bit...)

I guess I'm being lazy and doing a on-disk-format-only review. :)

> + */
> +struct nova_inode {
> +
> +     /* first 40 bytes */
> +     u8      i_rsvd;          /* reserved. used to be checksum */

Magic number?

> +     u8      valid;           /* Is this inode valid? */
> +     u8      deleted;         /* Is this inode deleted? */

Would i_mode == 0 cover these?

> +     u8      i_blk_type;      /* data block size this inode uses */

I would've thought these would just be bits of i_flags?

Also, if I have a 1G blocksize file and free space fragments to the
point that there's > 1G of free space but none of it contiguous, I guess
I can expect ENOSPC?

> +     __le32  i_flags;         /* Inode flags */
> +     __le64  i_size;          /* Size of data in bytes */
> +     __le32  i_ctime;         /* Inode modification time */
> +     __le32  i_mtime;         /* Inode b-tree Modification time */
> +     __le32  i_atime;         /* Access time */

Same y2038 grumble from the previous patch.

> +     __le16  i_mode;          /* File mode */
> +     __le16  i_links_count;   /* Links count */
> +
> +     __le64  i_xattr;         /* Extended attribute block */
> +
> +     /* second 40 bytes */
> +     __le32  i_uid;           /* Owner Uid */
> +     __le32  i_gid;           /* Group Id */
> +     __le32  i_generation;    /* File version (for NFS) */
> +     __le32  i_create_time;   /* Create time */
> +     __le64  nova_ino;        /* nova inode number */
> +
> +     __le64  log_head;        /* Log head pointer */
> +     __le64  log_tail;        /* Log tail pointer */
> +
> +     /* last 40 bytes */
> +     __le64  create_epoch_id; /* Transaction ID when create */
> +     __le64  delete_epoch_id; /* Transaction ID when deleted */
> +
> +     struct {
> +             __le32 rdev;     /* major/minor # */
> +     } dev;                   /* device inode */
> +
> +     __le32  csum;            /* CRC32 checksum */
> +     /* Leave 8 bytes for inode table tail pointer */
> +} __attribute((__packed__));
> +
> +/*
> + * NOVA-specific inode state kept in DRAM
> + */
> +struct nova_inode_info_header {
> +     /* For files, tree holds a map from file offsets to
> +      * write log entries.
> +      *
> +      * For directories, tree holds a map from a hash of the file name to
> +      * dentry log entry.
> +      */
> +     struct radix_tree_root tree;
> +     struct rw_semaphore i_sem;      /* Protect log and tree */
> +     unsigned short i_mode;          /* Dir or file? */
> +     unsigned int i_flags;
> +     unsigned long log_pages;        /* Num of log pages */
> +     unsigned long i_size;
> +     unsigned long i_blocks;
> +     unsigned long ino;
> +     unsigned long pi_addr;
> +     unsigned long valid_entries;    /* For thorough GC */
> +     unsigned long num_entries;      /* For thorough GC */
> +     u64 last_setattr;               /* Last setattr entry */
> +     u64 last_link_change;           /* Last link change entry */
> +     u64 last_dentry;                /* Last updated dentry */
> +     u64 trans_id;                   /* Transaction ID */
> +     u64 log_head;                   /* Log head pointer */
> +     u64 log_tail;                   /* Log tail pointer */
> +     u8  i_blk_type;
> +};
> +
> +/*
> + * DRAM state for inodes
> + */
> +struct nova_inode_info {
> +     struct nova_inode_info_header header;
> +     struct inode vfs_inode;
> +};
> +
> +
> +static inline struct nova_inode_info *NOVA_I(struct inode *inode)
> +{
> +     return container_of(inode, struct nova_inode_info, vfs_inode);
> +}
> +
> +static inline void sih_lock(struct nova_inode_info_header *header)

"sih"?  What happened to the "nova" prefix?

--D

> +{
> +     down_write(&header->i_sem);
> +}
> +
> +static inline void sih_unlock(struct nova_inode_info_header *header)
> +{
> +     up_write(&header->i_sem);
> +}
> +
> +static inline void sih_lock_shared(struct nova_inode_info_header *header)
> +{
> +     down_read(&header->i_sem);
> +}
> +
> +static inline void sih_unlock_shared(struct nova_inode_info_header *header)
> +{
> +     up_read(&header->i_sem);
> +}
> +
> +static inline unsigned int
> +nova_inode_blk_shift(struct nova_inode_info_header *sih)
> +{
> +     return blk_type_to_shift[sih->i_blk_type];
> +}
> +
> +static inline uint32_t nova_inode_blk_size(struct nova_inode_info_header 
> *sih)
> +{
> +     return blk_type_to_size[sih->i_blk_type];
> +}
> +
> +static inline u64 nova_get_reserved_inode_addr(struct super_block *sb,
> +     u64 inode_number)
> +{
> +     return (NOVA_DEF_BLOCK_SIZE_4K * RESERVE_INODE_START) +
> +                     inode_number * NOVA_INODE_SIZE;
> +}
> +
> +static inline struct nova_inode *nova_get_reserved_inode(struct super_block 
> *sb,
> +     u64 inode_number)
> +{
> +     struct nova_sb_info *sbi = NOVA_SB(sb);
> +     u64 addr;
> +
> +     addr = nova_get_reserved_inode_addr(sb, inode_number);
> +
> +     return (struct nova_inode *)(sbi->virt_addr + addr);
> +}
> +
> +static inline struct nova_inode *nova_get_inode_by_ino(struct super_block 
> *sb,
> +                                               u64 ino)
> +{
> +     if (ino == 0 || ino >= NOVA_NORMAL_INODE_START)
> +             return NULL;
> +
> +     return nova_get_reserved_inode(sb, ino);
> +}
> +
> +static inline struct nova_inode *nova_get_inode(struct super_block *sb,
> +     struct inode *inode)
> +{
> +     struct nova_inode_info *si = NOVA_I(inode);
> +     struct nova_inode_info_header *sih = &si->header;
> +     struct nova_inode fake_pi;
> +     void *addr;
> +     int rc;
> +
> +     addr = nova_get_block(sb, sih->pi_addr);
> +     rc = memcpy_mcsafe(&fake_pi, addr, sizeof(struct nova_inode));
> +     if (rc)
> +             return NULL;
> +
> +     return (struct nova_inode *)addr;
> +}
> +
> +static inline int nova_persist_inode(struct nova_inode *pi)
> +{
> +     nova_flush_buffer(pi, sizeof(struct nova_inode), 1);
> +     return 0;
> +}
> +
> +#endif
> -- 
> 2.7.4
> 
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to