statfs improvement
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 18 Aug 2006 18:43:50 +0000 (18:43 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Fri, 18 Aug 2006 18:43:50 +0000 (18:43 +0000)
ChangeLog
include/fuse.h
include/fuse_lowlevel.h
kernel/.cvsignore
kernel/configure.ac
kernel/control.c
lib/fuse.c
lib/fuse_lowlevel.c

index 2244e8950aedac248c4fc04ebe8d8529cb51e98e..8ddf02642c0193d57f0f3c7614c65f994e91cd3d 100644 (file)
--- 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
index ad2ef0086b92913f3ad52d3be735ccf9e6817836..d9041b279baf348db7bba7f04c2b3d7c9d54f0a9 100644 (file)
@@ -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);
 };
index ede130704da0313bf6ef6eee0d6bcd1e0e5d93ab..a676830b3eb7bbdf447ef15056cf4c374234bf8a 100644 (file)
@@ -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
      *
index 907cdec3b6877166c3336f590cd46064f8b84464..ed24c33995086bffc688c9b85376dc115b46ad85 100644 (file)
@@ -9,3 +9,4 @@ config.*
 *.s
 .tmp_versions
 .*.d
+*.symvers
index 21dc03621a6bf752d67024edd93e6c1a55e0032c..c3c1f3fe48ea7b60f8f56000ae7300122e0c9af2 100644 (file)
@@ -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])
index b17adb359a276c03e3569829bf5ca976fb034531..28956eff68fd221f409243a165771dcf7288870e 100644 (file)
@@ -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;
index 00f34fb0d20632d1dc8bb39c48b602f57a1f6240..48951927513acf175e5ac7bf7647e3219e64f59e 100644 (file)
@@ -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__ */
index 5076a5b9d37835e2cb8546daecfb65994fae7745..04a34f3bb4b0e8d8fe3acdac5bc95c001c9c977c 100644 (file)
@@ -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,