passthrough_ll: fix refcount for "." and ".." entries
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 14 Aug 2018 19:37:02 +0000 (21:37 +0200)
committerNikolaus Rath <Nikolaus@rath.org>
Wed, 10 Oct 2018 09:49:48 +0000 (10:49 +0100)
Kernel is not expecting an elevated lookup count for the "." and ".."
entries when doing READDIRPLUS.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
example/passthrough_ll.c

index f358e55fc5ff0a78a64d1c8b759f22374c55abb2..0b92d9cdc8ed7a911b92a9de9b6ba795cfbe9689 100644 (file)
@@ -342,6 +342,12 @@ out_err:
        fuse_reply_err(req, error);
 }
 
+static int is_dot_or_dotdot(const char *name)
+{
+       return name[0] == '.' && (name[1] == '\0' ||
+                                 (name[1] == '.' && name[2] == '\0'));
+}
+
 static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
                          off_t offset, struct fuse_file_info *fi, int plus)
 {
@@ -367,6 +373,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
        while (1) {
                size_t entsize;
                off_t nextoff;
+               const char *name;
 
                if (!d->entry) {
                        errno = 0;
@@ -380,23 +387,28 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
                        }
                }
                nextoff = telldir(d->dp);
+               name = d->entry->d_name;
                if (plus) {
                        struct fuse_entry_param e;
 
-                       err = lo_do_lookup(req, ino, d->entry->d_name, &e);
-                       if (err)
-                               goto error;
+                       if (is_dot_or_dotdot(name)) {
+                               e.ino = 0;
+                               e.attr.st_ino = d->entry->d_ino;
+                               e.attr.st_mode = d->entry->d_type << 12;
+                       } else {
+                               err = lo_do_lookup(req, ino, name, &e);
+                               if (err)
+                                       goto error;
+                       }
 
-                       entsize = fuse_add_direntry_plus(req, p, rem,
-                                                        d->entry->d_name,
+                       entsize = fuse_add_direntry_plus(req, p, rem, name,
                                                         &e, nextoff);
                } else {
                        struct stat st = {
                                .st_ino = d->entry->d_ino,
                                .st_mode = d->entry->d_type << 12,
                        };
-                       entsize = fuse_add_direntry(req, p, rem,
-                                                   d->entry->d_name,
+                       entsize = fuse_add_direntry(req, p, rem, name,
                                                    &st, nextoff);
                }
                if (entsize > rem)