Re: fgetattr/fsetattr file operation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 3 Jun 2009, Brian Molnar wrote:
> There was some talk on this list a year or two ago about adding
> f_op->fgetattr and f_op->fsetattr methods to the VFS file_operations
> struct. For some reason or another, that was dropped on the floor, but
> I'd like to pick that back up and discus it once again.
> 
> In the file-system I'm working on, there is a distinction between
> stat(2)s done against a pathname and fstat(2)s done against an open
> file descriptor. The results of the two are expected to differ in some
> circumstances. Moreover, I'm building this file-system in FUSE, and
> while I've managed to hack the underlying fuse code to achieve this
> behavior, it does so at a substantial performance cost. The more
> 'correct' solution here would be to export an fgetattr/fsetattr
> interface at VFS layer, then percolate that change up to the FUSE
> interface.

Can you tell us a bit more about your use case, and how you worked
around the limitation?

Attaching an untested patch that adds f_op->fgetattr().  Testing and
comments are welcome.

Thanks,
Miklos


Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h	2009-06-02 15:55:18.000000000 +0200
+++ linux-2.6/include/linux/fs.h	2009-06-04 11:56:04.000000000 +0200
@@ -1508,6 +1508,7 @@ struct file_operations {
 	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
 	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
 	int (*setlease)(struct file *, long, struct file_lock **);
+	int (*fgetattr)(struct file *, struct kstat *);
 };
 
 struct inode_operations {
Index: linux-2.6/fs/fuse/file.c
===================================================================
--- linux-2.6.orig/fs/fuse/file.c	2009-06-04 11:42:10.000000000 +0200
+++ linux-2.6/fs/fuse/file.c	2009-06-04 12:02:48.000000000 +0200
@@ -1449,6 +1449,17 @@ static int fuse_file_flock(struct file *
 	return err;
 }
 
+static int fuse_file_fgetattr(struct file *file, struct kstat *stat)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+
+	if (!fuse_allow_task(fc, current))
+		return -EACCES;
+
+	return fuse_update_attributes(inode, stat, file, NULL);
+}
+
 static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
 {
 	struct inode *inode = mapping->host;
@@ -1927,6 +1938,7 @@ static const struct file_operations fuse
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
 	.flock		= fuse_file_flock,
+	.fgetattr	= fuse_file_fgetattr,
 	.splice_read	= generic_file_splice_read,
 	.unlocked_ioctl	= fuse_file_ioctl,
 	.compat_ioctl	= fuse_file_compat_ioctl,
@@ -1944,6 +1956,7 @@ static const struct file_operations fuse
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
 	.flock		= fuse_file_flock,
+	.fgetattr	= fuse_file_fgetattr,
 	.unlocked_ioctl	= fuse_file_ioctl,
 	.compat_ioctl	= fuse_file_compat_ioctl,
 	.poll		= fuse_file_poll,
Index: linux-2.6/fs/stat.c
===================================================================
--- linux-2.6.orig/fs/stat.c	2009-05-20 14:11:59.000000000 +0200
+++ linux-2.6/fs/stat.c	2009-06-04 12:08:07.000000000 +0200
@@ -57,13 +57,33 @@ EXPORT_SYMBOL(vfs_getattr);
 
 int vfs_fstat(unsigned int fd, struct kstat *stat)
 {
-	struct file *f = fget(fd);
-	int error = -EBADF;
+	struct inode *inode;
+	struct vfsmount *mnt;
+	struct dentry *dentry;
+	struct file *f;
+	int error;
 
-	if (f) {
-		error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
-		fput(f);
+	f = fget(fd);
+	if (!f)
+		return -EBADF;
+
+	mnt = f->f_path.mnt;
+	dentry = f->f_path.dentry;
+	inode = dentry->d_inode;
+
+	error = security_inode_getattr(mnt, dentry);
+	if (!error) {
+		if (f->f_op && f->f_op->fgetattr) {
+			error = f->f_op->fgetattr(f, stat);
+		} else {
+			if (inode->i_op->getattr)
+				error = inode->i_op->getattr(mnt, dentry, stat);
+			else
+				generic_fillattr(inode, stat);
+		}
 	}
+	fput(f);
+
 	return error;
 }
 EXPORT_SYMBOL(vfs_fstat);
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux