Patch to implement getattr [patch]

Magnus Ahltorp (map@stacken.kth.se)
11 Aug 1999 15:12:21 +0200


This patch implements an inode operation (getattr) that lets the file
system decide what the stat system call should return. This is (for
example) necessary if the file system wishes to avoid inode number
clashes internally, but still wants to present a consistent picture to
the user level programs.

It also introduces a new function, vfs_getattr(), that can be used by
other parts of the kernel wishing to get a struct stat from a struct
inode.

Source compatibility with file systems is maintained, since a NULL in
the getattr field will make vfs_getattr use the generic getattr
function.

Magnus Ahltorp <map@stacken.kth.se>
Assar Westerlund <assar@sics.se>

--- fs/stat.c.orig Tue Jul 13 20:17:22 1999
+++ fs/stat.c Thu Jul 15 18:14:00 1999
@@ -24,56 +24,22 @@
}


-#if !defined(__alpha__) && !defined(__sparc__)
-
-/*
- * For backward compatibility? Maybe this should be moved
- * into arch/i386 instead?
- */
-static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
-{
- static int warncount = 5;
- struct __old_kernel_stat tmp;
-
- if (warncount) {
- warncount--;
- printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
- current->comm);
- }
-
- tmp.st_dev = kdev_t_to_nr(inode->i_dev);
- tmp.st_ino = inode->i_ino;
- tmp.st_mode = inode->i_mode;
- tmp.st_nlink = inode->i_nlink;
- tmp.st_uid = inode->i_uid;
- tmp.st_gid = inode->i_gid;
- tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
- tmp.st_ctime = inode->i_ctime;
- return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
-}
-
-#endif
-
-static int cp_new_stat(struct inode * inode, struct stat * statbuf)
+int generic_getattr(struct inode * inode, struct stat * statbuf)
{
- struct stat tmp;
unsigned int blocks, indirect;

- memset(&tmp, 0, sizeof(tmp));
- tmp.st_dev = kdev_t_to_nr(inode->i_dev);
- tmp.st_ino = inode->i_ino;
- tmp.st_mode = inode->i_mode;
- tmp.st_nlink = inode->i_nlink;
- tmp.st_uid = inode->i_uid;
- tmp.st_gid = inode->i_gid;
- tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
- tmp.st_ctime = inode->i_ctime;
+ memset(statbuf, 0, sizeof(*statbuf));
+ statbuf->st_dev = kdev_t_to_nr(inode->i_dev);
+ statbuf->st_ino = inode->i_ino;
+ statbuf->st_mode = inode->i_mode;
+ statbuf->st_nlink = inode->i_nlink;
+ statbuf->st_uid = inode->i_uid;
+ statbuf->st_gid = inode->i_gid;
+ statbuf->st_rdev = kdev_t_to_nr(inode->i_rdev);
+ statbuf->st_size = inode->i_size;
+ statbuf->st_atime = inode->i_atime;
+ statbuf->st_mtime = inode->i_mtime;
+ statbuf->st_ctime = inode->i_ctime;
/*
* st_blocks and st_blksize are approximated with a simple algorithm if
* they aren't supported directly by the filesystem. The minix and msdos
@@ -87,13 +53,13 @@
* Use minix fs values for the number of direct and indirect blocks. The
* count is now exact for the minix fs except that it counts zero blocks.
* Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
+ * statbuf->st_blksize.
*/
#define D_B 7
#define I_B (BLOCK_SIZE / sizeof(unsigned short))

if (!inode->i_blksize) {
- blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ blocks = (statbuf->st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (blocks > D_B) {
indirect = (blocks - D_B + I_B - 1) / I_B;
blocks += indirect;
@@ -104,15 +70,72 @@
blocks++;
}
}
- tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
- tmp.st_blksize = BLOCK_SIZE;
+ statbuf->st_blocks = (BLOCK_SIZE / 512) * blocks;
+ statbuf->st_blksize = BLOCK_SIZE;
} else {
- tmp.st_blocks = inode->i_blocks;
- tmp.st_blksize = inode->i_blksize;
+ statbuf->st_blocks = inode->i_blocks;
+ statbuf->st_blksize = inode->i_blksize;
+ }
+ return 0;
+}
+
+int vfs_getattr(struct inode * inode, struct stat * statbuf)
+{
+ if (inode->i_op && inode->i_op->getattr)
+ return inode->i_op->getattr (inode, statbuf);
+ else
+ return generic_getattr (inode, statbuf);
}
+
+#if !defined(__alpha__) && !defined(__sparc__)
+
+/*
+ * For backward compatibility? Maybe this should be moved
+ * into arch/i386 instead?
+ */
+static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
+{
+ static int warncount = 5;
+ struct __old_kernel_stat tmp;
+ struct stat new_tmp;
+ int ret;
+
+ if (warncount) {
+ warncount--;
+ printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+ current->comm);
+ }
+
+ ret = vfs_getattr (inode, &new_tmp);
+ if (ret)
+ return ret;
+ tmp.st_dev = new_tmp.st_dev;
+ tmp.st_ino = new_tmp.st_ino;
+ tmp.st_mode = new_tmp.st_mode;
+ tmp.st_nlink = new_tmp.st_nlink;
+ tmp.st_uid = new_tmp.st_uid;
+ tmp.st_gid = new_tmp.st_gid;
+ tmp.st_rdev = new_tmp.st_rdev;
+ tmp.st_size = new_tmp.st_size;
+ tmp.st_atime = new_tmp.st_atime;
+ tmp.st_mtime = new_tmp.st_mtime;
+ tmp.st_ctime = new_tmp.st_ctime;
+
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

+#endif
+
+static int cp_new_stat(struct inode * inode, struct stat * statbuf)
+{
+ struct stat tmp;
+ int ret;
+
+ ret = vfs_getattr (inode, &tmp);
+ if (ret)
+ return ret;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}

#if !defined(__alpha__) && !defined(__sparc__)
/*
--- include/linux/fs.h.orig Tue Jan 26 05:00:51 1999
+++ include/linux/fs.h Thu Jul 15 18:10:10 1999
@@ -613,6 +613,7 @@
int (*smap) (struct inode *,int);
int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int);
int (*revalidate) (struct dentry *);
+ int (*getattr) (struct inode *, struct stat *);
};

struct super_operations {
@@ -876,6 +877,9 @@

extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
+
+extern int generic_getattr(struct inode *, struct stat *);
+extern int vfs_getattr(struct inode * inode, struct stat * statbuf);

/* kludge to get SCSI modules working */
#include <linux/minix_fs.h>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/