From 0bd2a0808b023763c80b181f923eea80286f3bd8 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Tue, 27 Nov 2012 17:13:54 -0800 Subject: [PATCH] Imported Upstream version 2.9.2 --- ChangeLog | 57 ++++++++ NEWS | 2 + configure | 42 +++--- configure.in | 14 +- example/cusexmp.c | 2 +- example/fioc.c | 2 +- example/fsel.c | 2 +- example/fusexmp.c | 28 +++- example/fusexmp_fh.c | 18 ++- example/hello.c | 2 +- example/hello_ll.c | 2 +- example/null.c | 2 +- fuse.pc.in | 2 +- include/config.h.in | 3 + include/fuse.h | 15 +++ include/fuse_kernel.h | 14 +- include/fuse_lowlevel.h | 20 +++ lib/Makefile.am | 2 +- lib/Makefile.in | 2 +- lib/buffer.c | 1 + lib/fuse.c | 352 ++++++++++++++++++++++++++++++------------------ lib/fuse_lowlevel.c | 18 ++- lib/fuse_versionscript | 7 +- lib/modules/iconv.c | 4 +- lib/modules/subdir.c | 4 +- lib/mount.c | 2 +- util/Makefile.am | 10 +- util/Makefile.in | 10 +- 28 files changed, 451 insertions(+), 188 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3457ffb..dbd10e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2012-10-01 Miklos Szeredi + + * Released 2.9.2 + +2012-10-01 Miklos Szeredi + + * Fix deadlock in libfuse. Running "svn update" on a fuse + filesystem could deadlock because of a bug in the way the paths + are locked. Reported by Kazuaki Anami + +2012-08-23 Miklos Szeredi + + * Fix missing config.h in buffer.c. Reported by Matthew Gabeler-Lee + +2012-08-14 Miklos Szeredi + + * Not unhashing the name in forget (commit on 2011-12-09) broke + the forget logic in a subtle way, resulting in "fuse internal + error: node NNN not found" and causing the filesystem daemon to + abort. Fix by incrementing the node refcount if nlookup goes from + zero to one. Reported by Kyle Lippincott + +2012-08-13 Miklos Szeredi + + * Fix linking against GNU libiconv. Patch by Natanael Copa + +2012-07-19 Miklos Szeredi + + * Released 2.9.1 + +2012-07-19 Miklos Szeredi + + * Fix crash caused by freeing a stack address. Reported by Itay + Perl + +2012-07-04 Miklos Szeredi + + * Fix install of mount.fuse from out-of-tree build. Patch by + Olivier Blin + + * Fix build with automake >= 1.12.1. Patch by Olivier Blin + +2012-04-24 Miklos Szeredi + + * Add fallocate operation. Only works on linux kernels 3.5 or + later. Patch by Anatol Pomozov + +2012-05-16 Miklos Szeredi + + * Linking to a library that uses threads requires the application + to be linked with -pthreads otherwise some pthread functions will + be linked to stubs in glibc. So move -pthread from Libs.private + to Libs in fuse.pc. Reported by Werner Fink + + * Fix the compile command in the examples. Reported by Luciano + Dalle Ore + 2012-04-20 Miklos Szeredi * Released 2.9.0 diff --git a/NEWS b/NEWS index 72c57e6..559ee86 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ What is new in 2.9 o Add delete notification + o Add fallocate operation (linux kernel 3.5 or newer) + - Bug fixes and small improvements ============================================================================ diff --git a/configure b/configure index 929dc0e..1a909f3 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for fuse 2.9.0. +# Generated by GNU Autoconf 2.68 for fuse 2.9.2. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -567,8 +567,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='fuse' PACKAGE_TARNAME='fuse' -PACKAGE_VERSION='2.9.0' -PACKAGE_STRING='fuse 2.9.0' +PACKAGE_VERSION='2.9.2' +PACKAGE_STRING='fuse 2.9.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1312,7 +1312,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures fuse 2.9.0 to adapt to many kinds of systems. +\`configure' configures fuse 2.9.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1383,7 +1383,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of fuse 2.9.0:";; + short | recursive ) echo "Configuration of fuse 2.9.2:";; esac cat <<\_ACEOF @@ -1496,7 +1496,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -fuse configure 2.9.0 +fuse configure 2.9.2 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1831,7 +1831,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by fuse $as_me 2.9.0, which was +It was created by fuse $as_me 2.9.2, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2180,6 +2180,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then @@ -2757,7 +2758,7 @@ fi # Define the identity of the package. PACKAGE='fuse' - VERSION='2.9.0' + VERSION='2.9.2' cat >>confdefs.h <<_ACEOF @@ -11915,6 +11916,7 @@ else fi + if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } @@ -12042,12 +12044,6 @@ fi -# compatibility for automake < 1.8 -if test -z "$mkdir_p"; then - mkdir_p="../mkinstalldirs" - -fi - case $target_os in *linux*) arch=linux;; *netbsd*) arch=netbsd;; @@ -12119,6 +12115,17 @@ _ACEOF fi done +for ac_func in posix_fallocate +do : + ac_fn_c_check_func "$LINENO" "posix_fallocate" "ac_cv_func_posix_fallocate" +if test "x$ac_cv_func_posix_fallocate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_POSIX_FALLOCATE 1 +_ACEOF + +fi +done + ac_fn_c_check_member "$LINENO" "struct stat" "st_atim" "ac_cv_member_struct_stat_st_atim" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_atim" = xyes; then : @@ -12140,7 +12147,6 @@ _ACEOF fi -libfuse_libs="-pthread" LIBS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } @@ -12254,7 +12260,7 @@ if test "$ac_res" != no; then : fi -libfuse_libs="$libfuse_libs $LIBS" +libfuse_libs=$LIBS LIBS= # Check whether --with-libiconv-prefix was given. @@ -13855,7 +13861,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by fuse $as_me 2.9.0, which was +This file was extended by fuse $as_me 2.9.2, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13921,7 +13927,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -fuse config.status 2.9.0 +fuse config.status 2.9.2 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index f2e6c87..b93f259 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,5 @@ -AC_INIT(fuse, 2.9.0) +AC_INIT(fuse, 2.9.2) +AC_PREREQ(2.59d) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE @@ -7,14 +8,9 @@ AM_CONFIG_HEADER(include/config.h) AC_PROG_LIBTOOL AC_PROG_CC +AC_PROG_MKDIR_P AM_PROG_CC_C_O -# compatibility for automake < 1.8 -if test -z "$mkdir_p"; then - mkdir_p="../mkinstalldirs" - AC_SUBST(mkdir_p) -fi - case $target_os in *linux*) arch=linux;; *netbsd*) arch=netbsd;; @@ -57,14 +53,14 @@ if test "$enable_mtab" = "no"; then fi AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice utimensat]) +AC_CHECK_FUNCS([posix_fallocate]) AC_CHECK_MEMBERS([struct stat.st_atim]) AC_CHECK_MEMBERS([struct stat.st_atimespec]) -libfuse_libs="-pthread" LIBS= AC_SEARCH_LIBS(dlopen, [dl]) AC_SEARCH_LIBS(clock_gettime, [rt]) -libfuse_libs="$libfuse_libs $LIBS" +libfuse_libs=$LIBS LIBS= AC_ARG_WITH([libiconv-prefix], [ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [ diff --git a/example/cusexmp.c b/example/cusexmp.c index 900c985..01fcdf7 100644 --- a/example/cusexmp.c +++ b/example/cusexmp.c @@ -6,7 +6,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` cusexmp.c -o cusexmp + gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp */ #define FUSE_USE_VERSION 29 diff --git a/example/fioc.c b/example/fioc.c index d0dce15..bee40b9 100644 --- a/example/fioc.c +++ b/example/fioc.c @@ -6,7 +6,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` fioc.c -o fioc + gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc */ #define FUSE_USE_VERSION 26 diff --git a/example/fsel.c b/example/fsel.c index f30ddd5..9cf0221 100644 --- a/example/fsel.c +++ b/example/fsel.c @@ -6,7 +6,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` fsel.c -o fsel + gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel */ #define FUSE_USE_VERSION 29 diff --git a/example/fusexmp.c b/example/fusexmp.c index fa3fb4d..dca8a46 100644 --- a/example/fusexmp.c +++ b/example/fusexmp.c @@ -6,7 +6,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` fusexmp.c -o fusexmp + gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp */ #define FUSE_USE_VERSION 26 @@ -310,6 +310,29 @@ static int xmp_fsync(const char *path, int isdatasync, return 0; } +#ifdef HAVE_POSIX_FALLOCATE +static int xmp_fallocate(const char *path, int mode, + off_t offset, off_t length, struct fuse_file_info *fi) +{ + int fd; + int res; + + (void) fi; + + if (mode) + return -EOPNOTSUPP; + + fd = open(path, O_WRONLY); + if (fd == -1) + return -errno; + + res = -posix_fallocate(fd, offset, length); + + close(fd); + return res; +} +#endif + #ifdef HAVE_SETXATTR /* xattr operations are optional and can safely be left unimplemented */ static int xmp_setxattr(const char *path, const char *name, const char *value, @@ -371,6 +394,9 @@ static struct fuse_operations xmp_oper = { .statfs = xmp_statfs, .release = xmp_release, .fsync = xmp_fsync, +#ifdef HAVE_POSIX_FALLOCATE + .fallocate = xmp_fallocate, +#endif #ifdef HAVE_SETXATTR .setxattr = xmp_setxattr, .getxattr = xmp_getxattr, diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index e9524c6..1ba9dbc 100644 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -6,7 +6,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh + gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh */ #define FUSE_USE_VERSION 26 @@ -439,6 +439,19 @@ static int xmp_fsync(const char *path, int isdatasync, return 0; } +#ifdef HAVE_POSIX_FALLOCATE +static int xmp_fallocate(const char *path, int mode, + off_t offset, off_t length, struct fuse_file_info *fi) +{ + (void) path; + + if (mode) + return -EOPNOTSUPP; + + return -posix_fallocate(fi->fh, offset, length); +} +#endif + #ifdef HAVE_SETXATTR /* xattr operations are optional and can safely be left unimplemented */ static int xmp_setxattr(const char *path, const char *name, const char *value, @@ -529,6 +542,9 @@ static struct fuse_operations xmp_oper = { .flush = xmp_flush, .release = xmp_release, .fsync = xmp_fsync, +#ifdef HAVE_POSIX_FALLOCATE + .fallocate = xmp_fallocate, +#endif #ifdef HAVE_SETXATTR .setxattr = xmp_setxattr, .getxattr = xmp_getxattr, diff --git a/example/hello.c b/example/hello.c index bcde80a..bcb6b4c 100644 --- a/example/hello.c +++ b/example/hello.c @@ -5,7 +5,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` hello.c -o hello + gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello */ #define FUSE_USE_VERSION 26 diff --git a/example/hello_ll.c b/example/hello_ll.c index 1d3a1a8..1405441 100644 --- a/example/hello_ll.c +++ b/example/hello_ll.c @@ -5,7 +5,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` hello_ll.c -o hello_ll + gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll */ #define FUSE_USE_VERSION 26 diff --git a/example/null.c b/example/null.c index 0845586..b72cf4d 100644 --- a/example/null.c +++ b/example/null.c @@ -5,7 +5,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall `pkg-config fuse --cflags --libs` null.c -o null + gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null */ #define FUSE_USE_VERSION 26 diff --git a/fuse.pc.in b/fuse.pc.in index d87f7af..8fdb841 100644 --- a/fuse.pc.in +++ b/fuse.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: fuse Description: Filesystem in Userspace Version: @VERSION@ -Libs: -L${libdir} -lfuse +Libs: -L${libdir} -lfuse -pthread Libs.private: @libfuse_libs@ Cflags: -I${includedir}/fuse -D_FILE_OFFSET_BITS=64 diff --git a/include/config.h.in b/include/config.h.in index 2860250..2afe007 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -18,6 +18,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + /* Define to 1 if you have the `setxattr' function. */ #undef HAVE_SETXATTR diff --git a/include/fuse.h b/include/fuse.h index 36b168c..c657e67 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -575,6 +575,19 @@ struct fuse_operations { * Introduced in version 2.9 */ int (*flock) (const char *, struct fuse_file_info *, int op); + + /** + * Allocates space for an open file + * + * This function ensures that required space is allocated for specified + * file. If this function returns success then any subsequent write + * request to specified range is guaranteed not to fail because of lack + * of space on the file system media. + * + * Introduced in version 2.9.1 + */ + int (*fallocate) (const char *, int, off_t, off_t, + struct fuse_file_info *); }; /** Extra context that may be needed by some filesystems @@ -870,6 +883,8 @@ int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, int fuse_fs_poll(struct fuse_fs *fs, const char *path, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp); +int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode, + off_t offset, off_t length, struct fuse_file_info *fi); void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); void fuse_fs_destroy(struct fuse_fs *fs); diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 1ce072c..c632b58 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -80,6 +80,9 @@ * 7.18 * - add FUSE_IOCTL_DIR flag * - add FUSE_NOTIFY_DELETE + * + * 7.19 + * - add FUSE_FALLOCATE */ #ifndef _LINUX_FUSE_H @@ -116,7 +119,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 18 +#define FUSE_KERNEL_MINOR_VERSION 19 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -309,6 +312,7 @@ enum fuse_opcode { FUSE_POLL = 40, FUSE_NOTIFY_REPLY = 41, FUSE_BATCH_FORGET = 42, + FUSE_FALLOCATE = 43, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -602,6 +606,14 @@ struct fuse_notify_poll_wakeup_out { __u64 kh; }; +struct fuse_fallocate_in { + __u64 fh; + __u64 offset; + __u64 length; + __u32 mode; + __u32 padding; +}; + struct fuse_in_header { __u32 len; __u32 opcode; diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 3ecc46e..2036717 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -996,6 +996,26 @@ struct fuse_lowlevel_ops { */ void (*flock) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, int op); + + /** + * Allocate requested space. If this function returns success then + * subsequent writes to the specified range shall not fail due to the lack + * of free space on the file system storage media. + * + * Introduced in version 2.9 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param offset starting point for allocated region + * @param length size of allocated region + * @param mode determines the operation to be performed on the given range, + * see fallocate(2) + */ + void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, + off_t offset, off_t length, struct fuse_file_info *fi); }; /** diff --git a/lib/Makefile.am b/lib/Makefile.am index 010b244..3ec2401 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -36,7 +36,7 @@ libfuse_la_SOURCES = \ $(iconv_source) \ $(mount_source) -libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:9:0 \ +libfuse_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 2:9:2 \ -Wl,--version-script,$(srcdir)/fuse_versionscript if NETBSD diff --git a/lib/Makefile.in b/lib/Makefile.in index 67b9e4a..db9846a 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -283,7 +283,7 @@ libfuse_la_SOURCES = \ $(iconv_source) \ $(mount_source) -libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:9:0 \ +libfuse_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 2:9:2 \ -Wl,--version-script,$(srcdir)/fuse_versionscript @NETBSD_TRUE@libfuse_la_LIBADD = -lperfuse -lpuffs diff --git a/lib/buffer.c b/lib/buffer.c index 65b0dea..17a595c 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -8,6 +8,7 @@ #define _GNU_SOURCE +#include "config.h" #include "fuse_i.h" #include "fuse_lowlevel.h" #include diff --git a/lib/fuse.c b/lib/fuse.c index 4922361..599a587 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -10,6 +10,7 @@ /* For pthread_rwlock_t */ #define _GNU_SOURCE +#include "config.h" #include "fuse_i.h" #include "fuse_lowlevel.h" #include "fuse_opt.h" @@ -22,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -90,8 +92,20 @@ struct fusemod_so { }; struct lock_queue_element { - struct lock_queue_element *next; - pthread_cond_t cond; + struct lock_queue_element *next; + pthread_cond_t cond; + fuse_ino_t nodeid1; + const char *name1; + char **path1; + struct node **wnode1; + fuse_ino_t nodeid2; + const char *name2; + char **path2; + struct node **wnode2; + int err; + bool first_locked : 1; + bool second_locked : 1; + bool done : 1; }; struct node_table { @@ -133,7 +147,6 @@ struct fuse { struct fuse_fs *fs; int nullpath_ok; int utime_omit_ok; - int curr_ticket; struct lock_queue_element *lockq; int pagesize; struct list_head partial_slabs; @@ -167,10 +180,12 @@ struct node { unsigned int is_hidden : 1; unsigned int cache_valid : 1; int treelock; - int ticket; char inline_name[32]; }; +#define TREELOCK_WRITE -1 +#define TREELOCK_WAIT_OFFSET INT_MIN + struct node_lru { struct node node; struct list_head lru; @@ -325,12 +340,12 @@ static void list_add(struct list_head *new, struct list_head *prev, prev->next = new; } -static void list_add_head(struct list_head *new, struct list_head *head) +static inline void list_add_head(struct list_head *new, struct list_head *head) { list_add(new, head, head->next); } -static void list_add_tail(struct list_head *new, struct list_head *head) +static inline void list_add_tail(struct list_head *new, struct list_head *head) { list_add(new, head->prev, head); } @@ -423,6 +438,7 @@ static struct node *alloc_node(struct fuse *f) list_del(&slab->list); list_add_tail(&slab->list, &f->full_slabs); } + memset(node, 0, sizeof(struct node)); return (struct node *) node; } @@ -816,6 +832,13 @@ static struct node *lookup_node(struct fuse *f, fuse_ino_t parent, return NULL; } +static void inc_nlookup(struct node *node) +{ + if (!node->nlookup) + node->refctr++; + node->nlookup++; +} + static struct node *find_node(struct fuse *f, fuse_ino_t parent, const char *name) { @@ -831,15 +854,11 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent, if (node == NULL) goto out_err; - if (f->conf.remember) - node->nlookup = 1; - node->refctr = 1; node->nodeid = next_id(f); node->generation = f->generation; - node->open_count = 0; - node->is_hidden = 0; - node->treelock = 0; - node->ticket = 0; + if (f->conf.remember) + inc_nlookup(node); + if (hash_name(f, node, parent, name) == -1) { free_node(f, node); node = NULL; @@ -853,7 +872,7 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent, } else if (lru_enabled(f) && node->nlookup == 1) { remove_node_lru(node); } - node->nlookup ++; + inc_nlookup(node); out_err: pthread_mutex_unlock(&f->lock); return node; @@ -893,48 +912,28 @@ static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name) } static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode, - struct node *end, int ticket) + struct node *end) { struct node *node; if (wnode) { - assert(wnode->treelock == -1); + assert(wnode->treelock == TREELOCK_WRITE); wnode->treelock = 0; - if (!wnode->ticket) - wnode->ticket = ticket; } for (node = get_node(f, nodeid); node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) { - assert(node->treelock > 0); + assert(node->treelock != 0); + assert(node->treelock != TREELOCK_WAIT_OFFSET); + assert(node->treelock != TREELOCK_WRITE); node->treelock--; - if (!node->ticket) - node->ticket = ticket; - } -} - -static void release_tickets(struct fuse *f, fuse_ino_t nodeid, - struct node *wnode, int ticket) -{ - struct node *node; - - if (wnode) { - if (wnode->ticket != ticket) - return; - - wnode->ticket = 0; - } - - for (node = get_node(f, nodeid); - node->nodeid != FUSE_ROOT_ID; node = node->parent) { - if (node->ticket != ticket) - return; - node->ticket = 0; + if (node->treelock == TREELOCK_WAIT_OFFSET) + node->treelock = 0; } } static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, - char **path, struct node **wnodep, int ticket) + char **path, struct node **wnodep, bool need_lock) { unsigned bufsize = 256; char *buf; @@ -961,18 +960,16 @@ static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, } if (wnodep) { - assert(ticket); + assert(need_lock); wnode = lookup_node(f, nodeid, name); if (wnode) { - if (wnode->treelock != 0 || - (wnode->ticket && wnode->ticket != ticket)) { - if (!wnode->ticket) - wnode->ticket = ticket; + if (wnode->treelock != 0) { + if (wnode->treelock > 0) + wnode->treelock += TREELOCK_WAIT_OFFSET; err = -EAGAIN; goto out_free; } - wnode->treelock = -1; - wnode->ticket = 0; + wnode->treelock = TREELOCK_WRITE; } } @@ -987,14 +984,12 @@ static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, if (s == NULL) goto out_unlock; - if (ticket) { + if (need_lock) { err = -EAGAIN; - if (node->treelock == -1 || - (node->ticket && node->ticket != ticket)) + if (node->treelock < 0) goto out_unlock; node->treelock++; - node->ticket = 0; } } @@ -1010,40 +1005,95 @@ static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, return 0; out_unlock: - if (ticket) - unlock_path(f, nodeid, wnode, node, ticket); + if (need_lock) + unlock_path(f, nodeid, wnode, node); out_free: free(buf); out_err: - if (ticket && err != -EAGAIN) - release_tickets(f, nodeid, wnode, ticket); - return err; } -static void wake_up_first(struct fuse *f) +static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe) { - if (f->lockq) - pthread_cond_signal(&f->lockq->cond); + struct node *wnode; + + if (qe->first_locked) { + wnode = qe->wnode1 ? *qe->wnode1 : NULL; + unlock_path(f, qe->nodeid1, wnode, NULL); + } + if (qe->second_locked) { + wnode = qe->wnode2 ? *qe->wnode2 : NULL; + unlock_path(f, qe->nodeid2, wnode, NULL); + } } -static void wake_up_next(struct lock_queue_element *qe) +static void queue_element_wakeup(struct fuse *f, struct lock_queue_element *qe) { - if (qe->next) - pthread_cond_signal(&qe->next->cond); + int err; + bool first = (qe == f->lockq); + + if (!qe->path1) { + /* Just waiting for it to be unlocked */ + if (get_node(f, qe->nodeid1)->treelock == 0) + pthread_cond_signal(&qe->cond); + + return; + } + + if (!qe->first_locked) { + err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1, + qe->wnode1, true); + if (!err) + qe->first_locked = true; + else if (err != -EAGAIN) + goto err_unlock; + } + if (!qe->second_locked && qe->path2) { + err = try_get_path(f, qe->nodeid2, qe->name2, qe->path2, + qe->wnode2, true); + if (!err) + qe->second_locked = true; + else if (err != -EAGAIN) + goto err_unlock; + } + + if (qe->first_locked && (qe->second_locked || !qe->path2)) { + err = 0; + goto done; + } + + /* + * Only let the first element be partially locked otherwise there could + * be a deadlock. + * + * But do allow the first element to be partially locked to prevent + * starvation. + */ + if (!first) + queue_element_unlock(f, qe); + + /* keep trying */ + return; + +err_unlock: + queue_element_unlock(f, qe); +done: + qe->err = err; + qe->done = true; + pthread_cond_signal(&qe->cond); } -static int get_ticket(struct fuse *f) +static void wake_up_queued(struct fuse *f) { - do f->curr_ticket++; - while (f->curr_ticket == 0); + struct lock_queue_element *qe; - return f->curr_ticket; + for (qe = f->lockq; qe != NULL; qe = qe->next) + queue_element_wakeup(f, qe); } static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid, - const char *name, int wr) + const char *name, bool wr) { if (f->conf.debug) { struct node *wnode = NULL; @@ -1058,56 +1108,58 @@ static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid, } } -static void queue_path(struct fuse *f, struct lock_queue_element *qe, - fuse_ino_t nodeid, const char *name, int wr) +static void queue_path(struct fuse *f, struct lock_queue_element *qe) { struct lock_queue_element **qp; - debug_path(f, "QUEUE PATH", nodeid, name, wr); + qe->done = false; + qe->first_locked = false; + qe->second_locked = false; pthread_cond_init(&qe->cond, NULL); qe->next = NULL; for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next); *qp = qe; } -static void dequeue_path(struct fuse *f, struct lock_queue_element *qe, - fuse_ino_t nodeid, const char *name, int wr) +static void dequeue_path(struct fuse *f, struct lock_queue_element *qe) { struct lock_queue_element **qp; - debug_path(f, "DEQUEUE PATH", nodeid, name, wr); pthread_cond_destroy(&qe->cond); for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next); *qp = qe->next; } -static void wait_on_path(struct fuse *f, struct lock_queue_element *qe, - fuse_ino_t nodeid, const char *name, int wr) +static int wait_path(struct fuse *f, struct lock_queue_element *qe) { - debug_path(f, "WAIT ON PATH", nodeid, name, wr); - pthread_cond_wait(&qe->cond, &f->lock); + queue_path(f, qe); + + do { + pthread_cond_wait(&qe->cond, &f->lock); + } while (!qe->done); + + dequeue_path(f, qe); + + return qe->err; } static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name, char **path, struct node **wnode) { int err; - int ticket; pthread_mutex_lock(&f->lock); - ticket = get_ticket(f); - err = try_get_path(f, nodeid, name, path, wnode, ticket); + err = try_get_path(f, nodeid, name, path, wnode, true); if (err == -EAGAIN) { - struct lock_queue_element qe; - - queue_path(f, &qe, nodeid, name, !!wnode); - do { - wait_on_path(f, &qe, nodeid, name, !!wnode); - err = try_get_path(f, nodeid, name, path, wnode, - ticket); - wake_up_next(&qe); - } while (err == -EAGAIN); - dequeue_path(f, &qe, nodeid, name, !!wnode); + struct lock_queue_element qe = { + .nodeid1 = nodeid, + .name1 = name, + .path1 = path, + .wnode1 = wnode, + }; + debug_path(f, "QUEUE PATH", nodeid, name, !!wnode); + err = wait_path(f, &qe); + debug_path(f, "DEQUEUE PATH", nodeid, name, !!wnode); } pthread_mutex_unlock(&f->lock); @@ -1149,22 +1201,19 @@ static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name, static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, fuse_ino_t nodeid2, const char *name2, char **path1, char **path2, - struct node **wnode1, struct node **wnode2, - int ticket) + struct node **wnode1, struct node **wnode2) { int err; /* FIXME: locking two paths needs deadlock checking */ - err = try_get_path(f, nodeid1, name1, path1, wnode1, ticket); + err = try_get_path(f, nodeid1, name1, path1, wnode1, true); if (!err) { - err = try_get_path(f, nodeid2, name2, path2, wnode2, ticket); + err = try_get_path(f, nodeid2, name2, path2, wnode2, true); if (err) { struct node *wn1 = wnode1 ? *wnode1 : NULL; - unlock_path(f, nodeid1, wn1, NULL, ticket); - free(path1); - if (ticket && err != -EAGAIN) - release_tickets(f, nodeid1, wn1, ticket); + unlock_path(f, nodeid1, wn1, NULL); + free(*path1); } } return err; @@ -1176,27 +1225,27 @@ static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, struct node **wnode1, struct node **wnode2) { int err; - int ticket; pthread_mutex_lock(&f->lock); - ticket = get_ticket(f); err = try_get_path2(f, nodeid1, name1, nodeid2, name2, - path1, path2, wnode1, wnode2, ticket); + path1, path2, wnode1, wnode2); if (err == -EAGAIN) { - struct lock_queue_element qe; + struct lock_queue_element qe = { + .nodeid1 = nodeid1, + .name1 = name1, + .path1 = path1, + .wnode1 = wnode1, + .nodeid2 = nodeid2, + .name2 = name2, + .path2 = path2, + .wnode2 = wnode2, + }; - queue_path(f, &qe, nodeid1, name1, !!wnode1); - debug_path(f, " path2", nodeid2, name2, !!wnode2); - do { - wait_on_path(f, &qe, nodeid1, name1, !!wnode1); - debug_path(f, " path2", nodeid2, name2, !!wnode2); - err = try_get_path2(f, nodeid1, name1, nodeid2, name2, - path1, path2, wnode1, wnode2, - ticket); - wake_up_next(&qe); - } while (err == -EAGAIN); - dequeue_path(f, &qe, nodeid1, name1, !!wnode1); - debug_path(f, " path2", nodeid2, name2, !!wnode2); + debug_path(f, "QUEUE PATH1", nodeid1, name1, !!wnode1); + debug_path(f, " PATH2", nodeid2, name2, !!wnode2); + err = wait_path(f, &qe); + debug_path(f, "DEQUEUE PATH1", nodeid1, name1, !!wnode1); + debug_path(f, " PATH2", nodeid2, name2, !!wnode2); } pthread_mutex_unlock(&f->lock); @@ -1207,8 +1256,9 @@ static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid, struct node *wnode, char *path) { pthread_mutex_lock(&f->lock); - unlock_path(f, nodeid, wnode, NULL, 0); - wake_up_first(f); + unlock_path(f, nodeid, wnode, NULL); + if (f->lockq) + wake_up_queued(f); pthread_mutex_unlock(&f->lock); free(path); } @@ -1224,9 +1274,9 @@ static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2, char *path1, char *path2) { pthread_mutex_lock(&f->lock); - unlock_path(f, nodeid1, wnode1, NULL, 0); - unlock_path(f, nodeid2, wnode2, NULL, 0); - wake_up_first(f); + unlock_path(f, nodeid1, wnode1, NULL); + unlock_path(f, nodeid2, wnode2, NULL); + wake_up_queued(f); pthread_mutex_unlock(&f->lock); free(path1); free(path2); @@ -1245,15 +1295,19 @@ static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) * create and opendir */ while (node->nlookup == nlookup && node->treelock) { - struct lock_queue_element qe; + struct lock_queue_element qe = { + .nodeid1 = nodeid, + }; - queue_path(f, &qe, node->nodeid, NULL, 0); - do { - wait_on_path(f, &qe, node->nodeid, NULL, 0); - wake_up_next(&qe); + debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false); + queue_path(f, &qe); + do { + pthread_cond_wait(&qe.cond, &f->lock); } while (node->nlookup == nlookup && node->treelock); - dequeue_path(f, &qe, node->nodeid, NULL, 0); + + dequeue_path(f, &qe); + debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false); } assert(node->nlookup >= nlookup); @@ -2281,6 +2335,23 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path, return -ENOSYS; } +int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode, + off_t offset, off_t length, struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.fallocate) { + if (fs->debug) + fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n", + path, + mode, + (unsigned long long) offset, + (unsigned long long) length); + + return fs->op.fallocate(path, mode, offset, length, fi); + } else + return -ENOSYS; +} + static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) { struct node *node; @@ -2317,7 +2388,7 @@ static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname, newnode = lookup_node(f, dir, newname); } while(newnode); - res = try_get_path(f, dir, newname, &newpath, NULL, 0); + res = try_get_path(f, dir, newname, &newpath, NULL, false); pthread_mutex_unlock(&f->lock); if (res) break; @@ -3990,6 +4061,24 @@ static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino, reply_err(req, err); } +static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, + off_t offset, off_t length, struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int err; + + err = get_path_nullok(f, ino, &path); + if (!err) { + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + static int clean_delay(struct fuse *f) { /* @@ -4084,6 +4173,7 @@ static struct fuse_lowlevel_ops fuse_path_ops = { .bmap = fuse_lib_bmap, .ioctl = fuse_lib_ioctl, .poll = fuse_lib_poll, + .fallocate = fuse_lib_fallocate, }; int fuse_notify_poll(struct fuse_pollhandle *ph) @@ -4617,9 +4707,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, root->parent = NULL; root->nodeid = FUSE_ROOT_ID; - root->generation = 0; - root->refctr = 1; - root->nlookup = 1; + inc_nlookup(root); hash_id(f, root); return f; @@ -4673,7 +4761,7 @@ void fuse_destroy(struct fuse *f) node = node->id_next) { if (node->is_hidden) { char *path; - if (try_get_path(f, node->nodeid, NULL, &path, NULL, 0) == 0) { + if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) { fuse_fs_unlink(f->fs, path); free(path); } diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 2282ccf..01efc6a 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -8,6 +8,7 @@ #define _GNU_SOURCE +#include "config.h" #include "fuse_i.h" #include "fuse_kernel.h" #include "fuse_opt.h" @@ -1717,6 +1718,20 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) } } +static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_fallocate_in *arg = (struct fuse_fallocate_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + + if (req->f->op.fallocate) + req->f->op.fallocate(req, nodeid, arg->mode, arg->offset, arg->length, &fi); + else + fuse_reply_err(req, ENOSYS); +} + static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_init_in *arg = (struct fuse_init_in *) inarg; @@ -2267,6 +2282,7 @@ static struct { [FUSE_BMAP] = { do_bmap, "BMAP" }, [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, [FUSE_POLL] = { do_poll, "POLL" }, + [FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" }, [FUSE_DESTROY] = { do_destroy, "DESTROY" }, [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" }, [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, @@ -2452,7 +2468,7 @@ enum { KEY_VERSION, }; -static struct fuse_opt fuse_ll_opts[] = { +static const struct fuse_opt fuse_ll_opts[] = { { "debug", offsetof(struct fuse_ll, debug), 1 }, { "-d", offsetof(struct fuse_ll, debug), 1 }, { "allow_root", offsetof(struct fuse_ll, allow_root), 1 }, diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 2d110fb..8d91887 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -196,7 +196,12 @@ FUSE_2.9 { fuse_clean_cache; fuse_lowlevel_notify_delete; fuse_fs_flock; +} FUSE_2.8; + +FUSE_2.9.1 { + global: + fuse_fs_fallocate; local: *; -} FUSE_2.8; +} FUSE_2.9; diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c index 1b78192..89b22e4 100644 --- a/lib/modules/iconv.c +++ b/lib/modules/iconv.c @@ -592,7 +592,7 @@ static void iconv_destroy(void *data) free(ic); } -static struct fuse_operations iconv_oper = { +static const struct fuse_operations iconv_oper = { .destroy = iconv_destroy, .init = iconv_init, .getattr = iconv_getattr, @@ -635,7 +635,7 @@ static struct fuse_operations iconv_oper = { .flag_nopath = 1, }; -static struct fuse_opt iconv_opts[] = { +static const struct fuse_opt iconv_opts[] = { FUSE_OPT_KEY("-h", 0), FUSE_OPT_KEY("--help", 0), { "from_code=%s", offsetof(struct iconv, from_code), 0 }, diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c index 24dede6..76a53fa 100644 --- a/lib/modules/subdir.c +++ b/lib/modules/subdir.c @@ -575,7 +575,7 @@ static void subdir_destroy(void *data) free(d); } -static struct fuse_operations subdir_oper = { +static const struct fuse_operations subdir_oper = { .destroy = subdir_destroy, .init = subdir_init, .getattr = subdir_getattr, @@ -618,7 +618,7 @@ static struct fuse_operations subdir_oper = { .flag_nopath = 1, }; -static struct fuse_opt subdir_opts[] = { +static const struct fuse_opt subdir_opts[] = { FUSE_OPT_KEY("-h", 0), FUSE_OPT_KEY("--help", 0), { "subdir=%s", offsetof(struct subdir, base), 0 }, diff --git a/lib/mount.c b/lib/mount.c index be7b4cb..6a9da9e 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -160,7 +160,7 @@ struct mount_flags { int on; }; -static struct mount_flags mount_flags[] = { +static const struct mount_flags mount_flags[] = { {"rw", MS_RDONLY, 0}, {"ro", MS_RDONLY, 1}, {"suid", MS_NOSUID, 0}, diff --git a/util/Makefile.am b/util/Makefile.am index 927b98c..059d5fc 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -23,7 +23,7 @@ ulockmgr_server_LDFLAGS = -pthread install-exec-hook: -chmod u+s $(DESTDIR)$(bindir)/fusermount @if test ! -e $(DESTDIR)/dev/fuse; then \ - $(mkdir_p) $(DESTDIR)/dev; \ + $(MKDIR_P) $(DESTDIR)/dev; \ echo "mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true"; \ mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true; \ fi @@ -35,9 +35,9 @@ UDEV_RULES_PATH = @UDEV_RULES_PATH@ INIT_D_PATH = @INIT_D_PATH@ install-exec-local: - $(mkdir_p) $(DESTDIR)$(MOUNT_FUSE_PATH) - $(INSTALL_PROGRAM) $(srcdir)/mount.fuse $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse - $(mkdir_p) $(DESTDIR)$(INIT_D_PATH) + $(MKDIR_P) $(DESTDIR)$(MOUNT_FUSE_PATH) + $(INSTALL_PROGRAM) $(builddir)/mount.fuse $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse + $(MKDIR_P) $(DESTDIR)$(INIT_D_PATH) $(INSTALL_SCRIPT) $(srcdir)/init_script $(DESTDIR)$(INIT_D_PATH)/fuse @if test -x /usr/sbin/update-rc.d; then \ echo "/usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true"; \ @@ -45,7 +45,7 @@ install-exec-local: fi install-data-local: - $(mkdir_p) $(DESTDIR)$(UDEV_RULES_PATH) + $(MKDIR_P) $(DESTDIR)$(UDEV_RULES_PATH) $(INSTALL_DATA) $(srcdir)/udev.rules $(DESTDIR)$(UDEV_RULES_PATH)/99-fuse.rules uninstall-local: diff --git a/util/Makefile.in b/util/Makefile.in index 9b8b1be..1db4fe6 100644 --- a/util/Makefile.in +++ b/util/Makefile.in @@ -642,15 +642,15 @@ mount_util.c: $(top_srcdir)/lib/mount_util.c install-exec-hook: -chmod u+s $(DESTDIR)$(bindir)/fusermount @if test ! -e $(DESTDIR)/dev/fuse; then \ - $(mkdir_p) $(DESTDIR)/dev; \ + $(MKDIR_P) $(DESTDIR)/dev; \ echo "mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true"; \ mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true; \ fi install-exec-local: - $(mkdir_p) $(DESTDIR)$(MOUNT_FUSE_PATH) - $(INSTALL_PROGRAM) $(srcdir)/mount.fuse $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse - $(mkdir_p) $(DESTDIR)$(INIT_D_PATH) + $(MKDIR_P) $(DESTDIR)$(MOUNT_FUSE_PATH) + $(INSTALL_PROGRAM) $(builddir)/mount.fuse $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse + $(MKDIR_P) $(DESTDIR)$(INIT_D_PATH) $(INSTALL_SCRIPT) $(srcdir)/init_script $(DESTDIR)$(INIT_D_PATH)/fuse @if test -x /usr/sbin/update-rc.d; then \ echo "/usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true"; \ @@ -658,7 +658,7 @@ install-exec-local: fi install-data-local: - $(mkdir_p) $(DESTDIR)$(UDEV_RULES_PATH) + $(MKDIR_P) $(DESTDIR)$(UDEV_RULES_PATH) $(INSTALL_DATA) $(srcdir)/udev.rules $(DESTDIR)$(UDEV_RULES_PATH)/99-fuse.rules uninstall-local: -- 2.7.4