aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2006-08-18 18:43:50 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2006-08-18 18:43:50 +0000
commit3ded1a3176bb803e016e79d0e6db5e1f3ea30473 (patch)
treed67302d0f48290b6f865fff4a8f4d162e808439a
parent63d3c40e1fa56176a61df9ea6d430de4362aa77b (diff)
statfs improvement
-rw-r--r--ChangeLog4
-rw-r--r--include/fuse.h27
-rw-r--r--include/fuse_lowlevel.h7
-rw-r--r--kernel/.cvsignore1
-rw-r--r--kernel/configure.ac4
-rw-r--r--kernel/control.c7
-rw-r--r--lib/fuse.c25
-rw-r--r--lib/fuse_lowlevel.c2
8 files changed, 63 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 2244e89..8ddf026 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,10 @@
initialization. Bug found and original patch from Alexander
Zarochentsev
+ * For linux kernels >=2.6.18 (2.6.19 if using the fuse module from
+ the kernel tree) the statfs method will receive the path within
+ the filesystem on which the stat(v)fs syscall was called.
+
2006-07-30 Miklos Szeredi <miklos@szeredi.hu>
* fusermount: if selinux is active, restore the original file's
diff --git a/include/fuse.h b/include/fuse.h
index ad2ef00..d9041b2 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -68,9 +68,9 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type,
*
* All methods are optional, but some are essential for a useful
* filesystem (e.g. getattr). Open, flush, release, fsync, opendir,
- * releasedir, fsyncdir, access, create, ftruncate, fgetattr, init and
- * destroy are special purpose methods, without which a full featured
- * filesystem can still be implemented.
+ * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock,
+ * init and destroy are special purpose methods, without which a full
+ * featured filesystem can still be implemented.
*/
struct fuse_operations {
/** Get file attributes.
@@ -363,6 +363,27 @@ struct fuse_operations {
*/
int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
+ /**
+ * Perform POSIX file locking operation
+ *
+ * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
+ *
+ * For the meaning of fields in 'struct flock' see the man page
+ * for fcntl(2). The l_whence field will always be set to
+ * SEEK_SET.
+ *
+ * Unlike fcntl, the l_pid will be set in F_SETLK and F_SETLKW,
+ * and should be used by the filesystem to initialize this field
+ * in F_GETLK.
+ *
+ * For checking lock ownership, the 'owner' argument must be used.
+ *
+ * Note: if this method is not implemented, the kernel will still
+ * allow file locking to work locally. Hence it is only
+ * interesting for network filesystems and similar.
+ *
+ * Introduced in version 2.6
+ */
int (*lock) (const char *, struct fuse_file_info *, int cmd,
struct flock *, uint64_t owner);
};
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index ede1307..a676830 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -600,8 +600,9 @@ struct fuse_lowlevel_ops {
* fuse_reply_err
*
* @param req request handle
+ * @param ino the inode number, zero means "undefined"
*/
- void (*statfs) (fuse_req_t req);
+ void (*statfs) (fuse_req_t req, fuse_ino_t ino);
/**
* Set an extended attribute
@@ -754,6 +755,10 @@ struct fuse_lowlevel_ops {
* 'struct flock' should only be used to fill in this field in
* getlk().
*
+ * Note: if the locking methods are not implemented, the kernel
+ * will still allow file locking to work locally. Hence these are
+ * only interesting for network filesystems and similar.
+ *
* Valid replies:
* fuse_reply_err
*
diff --git a/kernel/.cvsignore b/kernel/.cvsignore
index 907cdec..ed24c33 100644
--- a/kernel/.cvsignore
+++ b/kernel/.cvsignore
@@ -9,3 +9,4 @@ config.*
*.s
.tmp_versions
.*.d
+*.symvers
diff --git a/kernel/configure.ac b/kernel/configure.ac
index 21dc036..c3c1f3f 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -76,8 +76,10 @@ if test "$ENABLE_FUSE_MODULE" = y; then
AC_MSG_RESULT([$kernelbuild])
AC_MSG_CHECKING([kernel source version])
- if test -r $kernelbuild/include/linux/version.h; then
+ if test -r $kernelbuild/include/linux/version.h && fgrep -q UTS_RELEASE $kernelbuild/include/linux/version.h; then
kernsrcver=`(echo "#include <linux/version.h>"; echo "kernsrcver=UTS_RELEASE") | cpp -I $kernelbuild/include | grep "^kernsrcver=" | cut -d \" -f 2`
+ elif test -r $kernelbuild/include/linux/utsrelease.h && fgrep -q UTS_RELEASE $kernelbuild/include/linux/utsrelease.h; then
+ kernsrcver=`(echo "#include <linux/utsrelease.h>"; echo "kernsrcver=UTS_RELEASE") | cpp -I $kernelbuild/include | grep "^kernsrcver=" | cut -d \" -f 2`
fi
if test -z "$kernsrcver"; then
AC_MSG_RESULT([Not found])
diff --git a/kernel/control.c b/kernel/control.c
index b17adb3..28956ef 100644
--- a/kernel/control.c
+++ b/kernel/control.c
@@ -74,7 +74,12 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
const char *name,
int mode, int nlink,
struct inode_operations *iop,
- struct file_operations *fop)
+#ifdef KERNEL_2_6_17_PLUS
+ const struct file_operations *fop
+#else
+ struct file_operations *fop
+#endif
+)
{
struct dentry *dentry;
struct inode *inode;
diff --git a/lib/fuse.c b/lib/fuse.c
index 00f34fb..4895192 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -108,7 +108,7 @@ static struct fuse_context *(*fuse_getcontext)(void) = NULL;
static int fuse_do_open(struct fuse *, char *, struct fuse_file_info *);
static void fuse_do_release(struct fuse *, char *, struct fuse_file_info *);
static int fuse_do_opendir(struct fuse *, char *, struct fuse_file_info *);
-static int fuse_do_statfs(struct fuse *, char *, struct statvfs *);
+static int fuse_do_statfs(struct fuse *, struct statvfs *);
#ifndef USE_UCLIBC
#define mutex_init(mut) pthread_mutex_init(mut, NULL)
@@ -1669,7 +1669,7 @@ static int default_statfs(struct statvfs *buf)
return 0;
}
-static void fuse_statfs(fuse_req_t req)
+static void fuse_statfs(fuse_req_t req, fuse_ino_t ino)
{
struct fuse *f = req_fuse_prepare(req);
struct statvfs buf;
@@ -1677,7 +1677,18 @@ static void fuse_statfs(fuse_req_t req)
memset(&buf, 0, sizeof(buf));
if (f->op.statfs) {
- err = fuse_do_statfs(f, "/", &buf);
+ if (ino && (!f->compat || f->compat >= 26)) {
+ char *path;
+ pthread_rwlock_rdlock(&f->tree_lock);
+ err = -ENOENT;
+ path = get_path(f, ino);
+ if (path) {
+ err = f->op.statfs(path, &buf);
+ free(path);
+ }
+ pthread_rwlock_unlock(&f->tree_lock);
+ } else
+ err = fuse_do_statfs(f, &buf);
} else
err = default_statfs(&buf);
@@ -2294,12 +2305,12 @@ static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
stbuf->f_namemax = oldbuf->f_namelen;
}
-static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf)
+static int fuse_do_statfs(struct fuse *f, struct statvfs *buf)
{
int err;
if (!f->compat || f->compat >= 25) {
- err = f->op.statfs(path, buf);
+ err = f->op.statfs("/", buf);
} else if (f->compat > 11) {
struct statfs oldbuf;
err = ((struct fuse_operations_compat22 *) &f->op)->statfs("/", &oldbuf);
@@ -2386,9 +2397,9 @@ static int fuse_do_opendir(struct fuse *f, char *path,
return f->op.opendir(path, fi);
}
-static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf)
+static int fuse_do_statfs(struct fuse *f, struct statvfs *buf)
{
- return f->op.statfs(path, buf);
+ return f->op.statfs("/", buf);
}
#endif /* __FreeBSD__ */
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 5076a5b..04a34f3 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -719,7 +719,7 @@ static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
(void) inarg;
if (req->f->op.statfs)
- req->f->op.statfs(req);
+ req->f->op.statfs(req, nodeid);
else {
struct statvfs buf = {
.f_namemax = 255,