File mode stored in i_mode
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 24 Aug 2010 04:55:42 +0000 (21:55 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:52 +0000 (17:35 -0700)
This is what stat and glibc expect, so we do it in the kernel now,
instead of mucking with i_type.  The use of the macros makes this much
nicer anyways.

kern/include/ros/fs.h
kern/include/vfs.h
kern/src/devfs.c
kern/src/kfs.c
kern/src/syscall.c
kern/src/vfs.c

index 9865553..a837e2d 100644 (file)
@@ -37,9 +37,86 @@ struct kstat {
        struct timespec                         st_ctime;       /* Time of last status change.  */
 };
 
+/* There are a bunch of things that glibc expects, which are part of the kernel
+ * interface, but that we don't want to clobber or otherwise conflict with
+ * glibc. */
 #ifdef ROS_KERNEL
 #define stat kstat
 #define dirent kdirent 
-#endif
+
+/* File access modes for open and fcntl. */
+#define O_RDONLY               0                       /* Open read-only */
+#define O_WRONLY               1                       /* Open write-only */
+#define O_RDWR                 2                       /* Open read/write */
+#define O_ACCMODE              3
+
+/* Bits OR'd into the second argument to open */
+#define O_CREAT                        00000100        /* not fcntl */
+#define O_EXCL                 00000200        /* not fcntl */
+#define O_NOCTTY               00000400        /* not fcntl */
+#define O_TRUNC                        00001000        /* not fcntl */
+#define O_APPEND               00002000
+#define O_NONBLOCK             00004000
+#define O_SYNC                 00010000
+#define O_FSYNC                        O_SYNC
+#define O_ASYNC                        00020000
+#define O_DIRECT               00040000        /* Direct disk access. */
+#define O_DIRECTORY            00200000        /* Must be a directory. */
+#define O_NOFOLLOW             00400000        /* Do not follow links. */
+#define O_NOATIME              01000000        /* Do not set atime. */
+#define O_CLOEXEC              02000000        /* Set close_on_exec. */
+#define O_CREAT_FLAGS (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC)
+
+/* File creation modes (access controls) */
+#define S_IRWXU 00700  /* user (file owner) has read, write and execute perms */
+#define S_IRUSR 00400  /* user has read permission */
+#define S_IWUSR 00200  /* user has write permission */
+#define S_IXUSR 00100  /* user has execute permission */
+#define S_IRWXG 00070  /* group has read, write and execute permission */
+#define S_IRGRP 00040  /* group has read permission */
+#define S_IWGRP 00020  /* group has write permission */
+#define S_IXGRP 00010  /* group has execute permission */
+#define S_IRWXO 00007  /* others have read, write and execute permission */
+#define S_IROTH 00004  /* others have read permission */
+#define S_IWOTH 00002  /* others have write permission */
+#define S_IXOTH 00001  /* others have execute permission */
+#define S_PMASK 00777  /* mask for all perms */
+
+/* fcntl flags that we support, keep in sync with glibc */
+#define F_DUPFD                0       /* Duplicate file descriptor */
+#define F_GETFD                1       /* Get file descriptor flags */
+#define F_SETFD                2       /* Set file descriptor flags */
+#define F_GETFL                3       /* Get file status flags */
+#define F_SETFL                4       /* Set file status flags */
+/* For F_[GET|SET]FD */
+#define FD_CLOEXEC     1
+
+/* File type is encoded in the file mode */
+#define __S_IFMT       0170000 /* These bits determine file type */
+/* File types */
+#define __S_IFDIR      0040000 /* Directory */
+#define __S_IFCHR      0020000 /* Character device */
+#define __S_IFBLK      0060000 /* Block device */
+#define __S_IFREG      0100000 /* Regular file */
+#define __S_IFIFO      0010000 /* FIFO */
+#define __S_IFLNK      0120000 /* Symbolic link */
+#define __S_IFSOCK     0140000 /* Socket */
+/* Protection bits */
+#define __S_ISUID      04000   /* Set user ID on execution */
+#define __S_ISGID      02000   /* Set group ID on execution */
+#define __S_ISVTX      01000   /* Save swapped text after use (sticky) */
+#define __S_IREAD      0400    /* Read by owner */
+#define __S_IWRITE     0200    /* Write by owner */
+#define __S_IEXEC      0100    /* Execute by owner */
+/* Test macros for file types. */
+#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
+#define S_ISDIR(mode)  __S_ISTYPE((mode), __S_IFDIR)
+#define S_ISCHR(mode)  __S_ISTYPE((mode), __S_IFCHR)
+#define S_ISBLK(mode)  __S_ISTYPE((mode), __S_IFBLK)
+#define S_ISREG(mode)  __S_ISTYPE((mode), __S_IFREG)
+#define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO)
+#define S_ISLNK(mode)  __S_ISTYPE((mode), __S_IFLNK)
+
+#endif /* ROS_KERNEL */
 
 #endif /* _ROS_INC_STAT_H */
index 1e2b8d0..1a83fe8 100644 (file)
@@ -107,53 +107,6 @@ struct nameidata {
 #define LOOKUP_CREATE          0x11    /* create a file if it doesn't exist */
 #define LOOKUP_ACCESS          0x12    /* access / check user permissions */
 
-/* TODO: make our own versions (fucking octal) and put it in fcntl.h */
-/* File access modes for open and fcntl. */
-#define O_RDONLY               0                       /* Open read-only. */
-#define O_WRONLY               1                       /* Open write-only. */
-#define O_RDWR                 2                       /* Open read/write. */
-#define O_ACCMODE              3
-
-/* Bits OR'd into the second argument to open. */
-#define O_CREAT                        00000100        /* not fcntl */
-#define O_EXCL                 00000200        /* not fcntl */
-#define O_NOCTTY               00000400        /* not fcntl */
-#define O_TRUNC                        00001000        /* not fcntl */
-#define O_APPEND               00002000
-#define O_NONBLOCK             00004000
-#define O_SYNC                 00010000
-#define O_FSYNC                        O_SYNC
-#define O_ASYNC                        00020000
-#define O_DIRECT               00040000        /* Direct disk access. */
-#define O_DIRECTORY            00200000        /* Must be a directory. */
-#define O_NOFOLLOW             00400000        /* Do not follow links. */
-#define O_NOATIME              01000000        /* Do not set atime. */
-#define O_CLOEXEC              02000000        /* Set close_on_exec. */
-#define O_CREAT_FLAGS (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC)
-
-/* File creation modes (access controls) */
-#define S_IRWXU 00700  /* user (file owner) has read, write and execute perms */
-#define S_IRUSR 00400  /* user has read permission */
-#define S_IWUSR 00200  /* user has write permission */
-#define S_IXUSR 00100  /* user has execute permission */
-#define S_IRWXG 00070  /* group has read, write and execute permission */
-#define S_IRGRP 00040  /* group has read permission */
-#define S_IWGRP 00020  /* group has write permission */
-#define S_IXGRP 00010  /* group has execute permission */
-#define S_IRWXO 00007  /* others have read, write and execute permission */
-#define S_IROTH 00004  /* others have read permission */
-#define S_IWOTH 00002  /* others have write permission */
-#define S_IXOTH 00001  /* others have execute permission */
-
-/* fcntl flags that we support, keep in sync with glibc */
-#define F_DUPFD                0       /* Duplicate file descriptor */
-#define F_GETFD                1       /* Get file descriptor flags */
-#define F_SETFD                2       /* Set file descriptor flags */
-#define F_GETFL                3       /* Get file status flags */
-#define F_SETFL                4       /* Set file status flags */
-/* For F_[GET|SET]FD */
-#define FD_CLOEXEC     1
-
 /* Every object that has pages, like an inode or the swap (or even direct block
  * devices) has a page_map, tracking which of its pages are currently in memory.
  * It is a map, per object, from index to physical page frame. */
@@ -229,9 +182,8 @@ struct super_operations {
        void (*umount_begin) (struct super_block *);/* called by NFS */
 };
 
-#define FS_I_FILE                              0x01
-#define FS_I_DIR                               0x02
-#define FS_I_SYMLINK                   0x03
+/* Sets the type of file, IAW the bits in ros/fs.h */
+#define SET_FTYPE(mode, type) ((mode) = ((mode) & ~__S_IFMT) | (type))
 
 /* Inode: represents a specific file */
 struct inode {
@@ -241,8 +193,7 @@ struct inode {
        struct dentry_tailq                     i_dentry;               /* all dentries pointing here*/
        unsigned long                           i_ino;
        struct kref                                     i_kref;
-       int                                                     i_mode;                 /* access mode */
-       unsigned short                          i_type;                 /* file type */
+       int                                                     i_mode;                 /* access mode and file type */
        unsigned int                            i_nlink;                /* hard links */
        uid_t                                           i_uid;
        gid_t                                           i_gid;
index ad3ff14..ebd59a5 100644 (file)
@@ -29,6 +29,7 @@ static struct file *get_stdinout(char *name, int mode,
        /* Overwrite the f_op with our own f_ops */
        f_char_dev->f_dentry->d_inode->i_fop = fop;
        f_char_dev->f_op = fop;
+       SET_FTYPE(f_char_dev->f_dentry->d_inode->i_mode, __S_IFCHR);
        return f_char_dev;
 }
 
index fd54e97..3fac0d1 100644 (file)
@@ -167,7 +167,7 @@ struct inode *kfs_alloc_inode(struct super_block *sb)
 void kfs_dealloc_inode(struct inode *inode)
 {
        /* If we're a symlink, give up our storage for the symname */
-       if (inode->i_type == FS_I_SYMLINK)
+       if (S_ISLNK(inode->i_mode))
                kfree(((struct kfs_i_info*)inode->i_fs_info)->filestart);
        kmem_cache_free(kfs_i_kcache, inode->i_fs_info);
 }
@@ -183,7 +183,7 @@ void kfs_read_inode(struct inode *inode)
         *      possibly a bug, since these inos come from directories */
        if (inode->i_ino == 1) {
                inode->i_mode = S_IRWXU | S_IRWXG | S_IRWXO;
-               inode->i_type = FS_I_DIR;
+               SET_FTYPE(inode->i_mode, __S_IFDIR);
                inode->i_fop = &kfs_f_op_dir;
                inode->i_nlink = 1;                             /* assuming only one hardlink */
                inode->i_uid = 0;
@@ -294,7 +294,7 @@ int kfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
        struct inode *inode = dentry->d_inode;
        kfs_init_inode(dir, dentry);
-       inode->i_type = FS_I_FILE;
+       SET_FTYPE(inode->i_mode, __S_IFREG);
        inode->i_fop = &kfs_f_op_file;
        /* fs_info->filestart is set by the caller, or else when first written (for
         * new files.  it was set to 0 in alloc_inode(). */
@@ -322,7 +322,7 @@ struct dentry *kfs_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *d_i;
 
        assert(dir_dent && dir_dent == TAILQ_LAST(&dir->i_dentry, dentry_tailq));
-       assert(dir->i_type & FS_I_DIR);
+       assert(S_ISDIR(dir->i_mode));
        assert(kref_refcnt(&dentry->d_kref) == 1);
        TAILQ_FOREACH(d_i, &dir_dent->d_subdirs, d_subdirs_link) {
                if (!strcmp(d_i->d_name.name, dentry->d_name.name)) {
@@ -381,7 +381,7 @@ int kfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        char *string = kmalloc(len + 1, 0);
 
        kfs_init_inode(dir, dentry);
-       inode->i_type = FS_I_SYMLINK;
+       SET_FTYPE(inode->i_mode, __S_IFLNK);
        inode->i_fop = &kfs_f_op_sym;
        strncpy(string, symname, len);
        string[len] = '\0';             /* symname should be \0d anyway, but just in case */
@@ -398,7 +398,7 @@ int kfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        struct inode *inode = dentry->d_inode;
        kref_get(&dentry->d_kref, 1);   /* to pin the dentry in RAM, KFS-style... */
        inode->i_ino = kfs_get_free_ino();
-       inode->i_type = FS_I_DIR;
+       SET_FTYPE(inode->i_mode, __S_IFDIR);
        inode->i_fop = &kfs_f_op_dir;
        /* get ready to have our own kids */
        TAILQ_INIT(&((struct kfs_i_info*)inode->i_fs_info)->children);
@@ -441,7 +441,7 @@ char *kfs_readlink(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        struct kfs_i_info *k_i_info = (struct kfs_i_info*)inode->i_fs_info;
-       if (inode->i_type != FS_I_SYMLINK)
+       if (!S_ISLNK(inode->i_mode))
                return 0;
        return k_i_info->filestart;
 }
@@ -553,7 +553,7 @@ int kfs_readdir(struct file *dir, struct dirent *dirent)
        }
        /* some of this error handling can be done by the VFS.  The syscall should
         * handle EBADF, EFAULT, and EINVAL (TODO, memory related). */
-       if (!(dir_d->d_inode->i_type & FS_I_DIR)) {
+       if (!S_ISDIR(dir_d->d_inode->i_mode)) {
                set_errno(ENOTDIR);
                return -1;
        }
@@ -580,7 +580,7 @@ int kfs_readdir(struct file *dir, struct dirent *dirent)
  * the file was opened or the file type. */
 int kfs_mmap(struct file *file, struct vm_region *vmr)
 {
-       if (file->f_dentry->d_inode->i_type & FS_I_FILE)
+       if (S_ISREG(file->f_dentry->d_inode->i_mode))
                return 0;
        return -1;
 }
index d36b8af..ba740ed 100644 (file)
@@ -826,6 +826,7 @@ static intreg_t sys_open(struct proc *p, const char *path, size_t path_l,
        int fd = 0;
        struct file *file;
 
+       printd("File %s Open attempt\n", path);
        char *t_path = user_strdup_errno(p, path, path_l);
        if (!t_path)
                return -1;
@@ -988,7 +989,7 @@ static intreg_t sys_access(struct proc *p, const char *path, size_t path_l,
 intreg_t sys_umask(struct proc *p, int mask)
 {
        int old_mask = p->fs_env.umask;
-       p->fs_env.umask = mask & 0777;
+       p->fs_env.umask = mask & S_PMASK;
        return old_mask;
 }
 
index 7d792f3..10648a5 100644 (file)
@@ -207,7 +207,7 @@ static int follow_symlink(struct nameidata *nd)
 {
        int retval;
        char *symname;
-       if (nd->dentry->d_inode->i_type != FS_I_SYMLINK)
+       if (!S_ISLNK(nd->dentry->d_inode->i_mode))
                return 0;
        if (nd->depth > MAX_SYMLINK_DEPTH)
                return -ELOOP;
@@ -328,7 +328,7 @@ static int link_path_walk(char *path, struct nameidata *nd)
                 * during the follow_symlink (a symlink could have had a directory at
                 * the end), though it was in the middle of the real path. */
                nd->flags &= ~LOOKUP_DIRECTORY;
-               if (!(nd->dentry->d_inode->i_type & FS_I_DIR))
+               if (!S_ISDIR(nd->dentry->d_inode->i_mode))
                        return -ENOTDIR;
 next_loop:
                /* move through the path string to the next entry */
@@ -392,8 +392,7 @@ next_loop:
         * mountpoint still.  FYI: this hasn't been thought through completely. */
        follow_mount(nd);
        /* If we wanted a directory, but didn't get one, error out */
-       if ((nd->flags & LOOKUP_DIRECTORY) &&
-          !(nd->dentry->d_inode->i_type & FS_I_DIR))
+       if ((nd->flags & LOOKUP_DIRECTORY) && !S_ISDIR(nd->dentry->d_inode->i_mode))
                return -ENOTDIR;
        return 0;
 }
@@ -685,7 +684,7 @@ static struct inode *create_inode(struct dentry *dentry, int mode)
        struct inode *inode = get_inode(dentry);
        if (!inode)
                return 0;
-       inode->i_mode = mode;
+       inode->i_mode = mode & S_PMASK; /* note that after this, we have no type */
        inode->i_nlink = 1;
        inode->i_size = 0;
        inode->i_blocks = 0;
@@ -1082,7 +1081,7 @@ int do_link(char *old_path, char *new_path)
        if (!old_d)                                     /* errno set by lookup_dentry */
                goto out_link_d;
        /* For now, can only link to files */
-       if (old_d->d_inode->i_type != FS_I_FILE) {
+       if (!S_ISREG(old_d->d_inode->i_mode)) {
                set_errno(EPERM);
                goto out_both_ds;
        }
@@ -1140,7 +1139,7 @@ int do_unlink(char *path)
                goto out_path_only;
        }
        /* Make sure the target is not a directory */
-       if (dentry->d_inode->i_type == FS_I_DIR) {
+       if (S_ISDIR(dentry->d_inode->i_mode)) {
                set_errno(EISDIR);
                goto out_dentry;
        }
@@ -1191,7 +1190,7 @@ int do_chmod(char *path, int mode)
                        retval = -EPERM;
                else
                #endif
-                       nd->dentry->d_inode->i_mode = mode & 0777;
+                       nd->dentry->d_inode->i_mode |= mode & S_PMASK;
        }
        path_release(nd);       
        return retval;
@@ -1261,7 +1260,7 @@ int do_rmdir(char *path)
                set_errno(ENOENT);
                goto out_path_only;
        }
-       if (dentry->d_inode->i_type != FS_I_DIR) {
+       if (!S_ISDIR(dentry->d_inode->i_mode)) {
                set_errno(ENOTDIR);
                goto out_dentry;
        }
@@ -1676,7 +1675,7 @@ static void print_dir(struct dentry *dentry, char *buf, int depth)
        int retval;
        int child_num = 0;
 
-       if (!dentry->d_inode->i_type & FS_I_DIR) {
+       if (!S_ISDIR(dentry->d_inode->i_mode)) {
                warn("Thought this was only directories!!");
                return;
        }
@@ -1700,18 +1699,22 @@ static void print_dir(struct dentry *dentry, char *buf, int depth)
                        if (!child_d)
                                panic("Inconsistent FS, dirent doesn't have a dentry!");
                        /* Recurse for directories, or just print the name for others */
-                       switch (child_d->d_inode->i_type) {
-                               case (FS_I_DIR):
+                       switch (child_d->d_inode->i_mode & __S_IFMT) {
+                               case (__S_IFDIR):
                                        print_dir(child_d, buf, depth + 1);
                                        break;
-                               case (FS_I_FILE):
+                               case (__S_IFREG):
                                        printk("%s%s size(B): %d nlink: %d\n", buf, next.d_name,
                                               child_d->d_inode->i_size, child_d->d_inode->i_nlink);
                                        break;
-                               case (FS_I_SYMLINK):
+                               case (__S_IFLNK):
                                        printk("%s%s -> %s\n", buf, next.d_name,
                                               child_d->d_inode->i_op->readlink(child_d));
                                        break;
+                               case (__S_IFCHR):
+                                       printk("%s%s (char device) nlink: %d\n", buf, next.d_name,
+                                              child_d->d_inode->i_nlink);
+                                       break;
                                default:
                                        warn("Look around you!  Unknown filetype!");
                        }