2014-09-05 19:20:16 +04:00
|
|
|
/* $NetBSD: ops.c,v 1.73 2014/09/05 15:20:16 manu Exp $ */
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*-
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
|
2010-08-25 11:16:00 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include <sysexits.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <puffs.h>
|
2012-07-21 09:49:42 +04:00
|
|
|
#include <sys/socket.h>
|
2010-08-25 11:16:00 +04:00
|
|
|
#include <sys/socket.h>
|
2011-06-28 20:19:16 +04:00
|
|
|
#include <sys/extattr.h>
|
2011-12-28 21:33:52 +04:00
|
|
|
#include <sys/time.h>
|
2010-08-25 11:16:00 +04:00
|
|
|
#include <machine/vmparam.h>
|
|
|
|
|
|
|
|
#include "perfuse_priv.h"
|
|
|
|
#include "fuse.h"
|
|
|
|
|
2010-09-07 06:11:04 +04:00
|
|
|
extern int perfuse_diagflags;
|
|
|
|
|
2011-11-28 09:33:33 +04:00
|
|
|
#if 0
|
|
|
|
static void print_node(const char *, puffs_cookie_t);
|
|
|
|
#endif
|
2012-04-18 04:57:21 +04:00
|
|
|
#ifdef PUFFS_KFLAG_CACHE_FS_TTL
|
|
|
|
static void perfuse_newinfo_setttl(struct puffs_newinfo *,
|
2012-07-21 09:49:42 +04:00
|
|
|
struct puffs_node *, struct fuse_entry_out *, struct fuse_attr_out *);
|
2012-04-08 19:13:06 +04:00
|
|
|
#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
|
2010-09-20 11:00:21 +04:00
|
|
|
static int xchg_msg(struct puffs_usermount *, puffs_cookie_t,
|
|
|
|
perfuse_msg_t *, size_t, enum perfuse_xchg_pb_reply);
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
static int mode_access(puffs_cookie_t, const struct puffs_cred *, mode_t);
|
2012-07-21 09:49:42 +04:00
|
|
|
static int sticky_access(puffs_cookie_t, struct puffs_node *,
|
|
|
|
const struct puffs_cred *);
|
2010-08-25 11:16:00 +04:00
|
|
|
static void fuse_attr_to_vap(struct perfuse_state *,
|
|
|
|
struct vattr *, struct fuse_attr *);
|
|
|
|
static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t,
|
2012-04-18 04:57:21 +04:00
|
|
|
struct puffs_newinfo *, const char *, const struct puffs_cred *,
|
|
|
|
struct puffs_node **);
|
2010-08-25 11:16:00 +04:00
|
|
|
static int node_mk_common(struct puffs_usermount *, puffs_cookie_t,
|
2010-09-02 12:58:06 +04:00
|
|
|
struct puffs_newinfo *, const struct puffs_cn *pcn, perfuse_msg_t *);
|
2011-07-14 19:37:32 +04:00
|
|
|
static uint64_t readdir_last_cookie(struct fuse_dirent *, size_t);
|
2010-08-25 11:16:00 +04:00
|
|
|
static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t,
|
|
|
|
struct fuse_dirent *, size_t);
|
2012-07-21 09:49:42 +04:00
|
|
|
static void readdir_buffered(puffs_cookie_t, struct dirent *, off_t *,
|
2011-07-14 19:37:32 +04:00
|
|
|
size_t *);
|
2012-07-21 09:49:42 +04:00
|
|
|
static void node_ref(puffs_cookie_t);
|
|
|
|
static void node_rele(puffs_cookie_t);
|
2010-08-25 11:16:00 +04:00
|
|
|
static void requeue_request(struct puffs_usermount *,
|
|
|
|
puffs_cookie_t opc, enum perfuse_qtype);
|
2012-07-21 09:49:42 +04:00
|
|
|
static int dequeue_requests(puffs_cookie_t opc, enum perfuse_qtype, int);
|
2010-08-25 11:16:00 +04:00
|
|
|
#define DEQUEUE_ALL 0
|
|
|
|
|
|
|
|
/*
|
|
|
|
* From <sys/vnode>, inside #ifdef _KERNEL section
|
|
|
|
*/
|
|
|
|
#define IO_SYNC (0x40|IO_DSYNC)
|
|
|
|
#define IO_DSYNC 0x00200
|
|
|
|
#define IO_DIRECT 0x02000
|
|
|
|
|
|
|
|
/*
|
|
|
|
* From <fcntl>, inside #ifdef _KERNEL section
|
|
|
|
*/
|
|
|
|
#define F_WAIT 0x010
|
|
|
|
#define F_FLOCK 0x020
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
#define OFLAGS(fflags) ((fflags) - 1)
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Borrowed from src/sys/kern/vfs_subr.c and src/sys/sys/vnode.h
|
|
|
|
*/
|
|
|
|
const enum vtype iftovt_tab[16] = {
|
|
|
|
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
|
|
|
|
VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
|
|
|
|
};
|
|
|
|
const int vttoif_tab[9] = {
|
|
|
|
0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
|
|
|
|
S_IFSOCK, S_IFIFO, S_IFMT,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
|
|
|
|
#define VTTOIF(indx) (vttoif_tab[(int)(indx)])
|
|
|
|
|
2011-11-28 09:33:33 +04:00
|
|
|
#if 0
|
|
|
|
static void
|
2012-03-21 14:10:36 +04:00
|
|
|
print_node(const char *func, puffs_cookie_t opc)
|
2011-11-28 09:33:33 +04:00
|
|
|
{
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
struct vattr *vap;
|
|
|
|
|
|
|
|
pn = (struct puffs_node *)opc;
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
vap = &pn->pn_va;
|
|
|
|
|
|
|
|
printf("%s: \"%s\", opc = %p, nodeid = 0x%"PRIx64" ino = %"PRIu64"\n",
|
|
|
|
func, pnd->pnd_name, opc, pnd->pnd_nodeid, vap->va_fileid);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_close_common(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
int mode)
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
int op;
|
|
|
|
uint64_t fh;
|
|
|
|
struct fuse_release_in *fri;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
pn = (struct puffs_node *)opc;
|
|
|
|
pnd = PERFUSE_NODE_DATA(pn);
|
|
|
|
|
|
|
|
if (puffs_pn_getvap(pn)->va_type == VDIR) {
|
|
|
|
op = FUSE_RELEASEDIR;
|
|
|
|
mode = FREAD;
|
|
|
|
} else {
|
|
|
|
op = FUSE_RELEASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Destroy the filehandle before sending the
|
|
|
|
* request to the FUSE filesystem, otherwise
|
|
|
|
* we may get a second close() while we wait
|
|
|
|
* for the reply, and we would end up closing
|
|
|
|
* the same fh twice instead of closng both.
|
|
|
|
*/
|
|
|
|
fh = perfuse_get_fh(opc, mode);
|
|
|
|
perfuse_destroy_fh(pn, fh);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* release_flags may be set to FUSE_RELEASE_FLUSH
|
|
|
|
* to flush locks. lock_owner must be set in that case
|
2011-08-02 18:53:38 +04:00
|
|
|
*
|
|
|
|
* ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser. We come here from the
|
|
|
|
* inactive method, which provides no creds, but obviously
|
|
|
|
* runs with kernel privilege.
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, op, sizeof(*fri), NULL);
|
|
|
|
fri = GET_INPAYLOAD(ps, pm, fuse_release_in);
|
|
|
|
fri->fh = fh;
|
|
|
|
fri->flags = 0;
|
|
|
|
fri->release_flags = 0;
|
|
|
|
fri->lock_owner = pnd->pnd_lock_owner;
|
|
|
|
fri->flags = (fri->lock_owner != 0) ? FUSE_RELEASE_FLUSH : 0;
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
|
|
|
|
__func__, (void *)opc, pnd->pnd_nodeid, fri->fh);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
#endif
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm,
|
|
|
|
NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
DERRX(EX_SOFTWARE, "%s: freed fh = 0x%"PRIx64" but filesystem "
|
|
|
|
"returned error = %d", __func__, fh, error);
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
|
|
|
return 0;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
static int
|
2012-03-21 14:10:36 +04:00
|
|
|
xchg_msg(struct puffs_usermount *pu, puffs_cookie_t opc, perfuse_msg_t *pm,
|
|
|
|
size_t len, enum perfuse_xchg_pb_reply wait)
|
2010-09-20 11:00:21 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
2010-09-29 12:01:10 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2011-12-28 21:33:52 +04:00
|
|
|
struct perfuse_trace *pt = NULL;
|
2010-09-20 11:00:21 +04:00
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-29 12:01:10 +04:00
|
|
|
pnd = NULL;
|
|
|
|
if ((struct puffs_node *)opc != NULL)
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0))
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("file = \"%s\", ino = %"PRIu64" flags = 0x%x\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_path(ps, opc),
|
2011-10-30 09:11:37 +04:00
|
|
|
((struct puffs_node *)opc)->pn_va.va_fileid,
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_flags);
|
2010-09-20 11:00:21 +04:00
|
|
|
#endif
|
2012-07-21 09:49:42 +04:00
|
|
|
ps->ps_xchgcount++;
|
2010-09-29 12:01:10 +04:00
|
|
|
if (pnd)
|
2012-07-21 09:49:42 +04:00
|
|
|
pnd->pnd_inxchg++;
|
2010-09-29 12:01:10 +04:00
|
|
|
|
2011-12-28 21:33:52 +04:00
|
|
|
/*
|
|
|
|
* Record FUSE call start if requested
|
|
|
|
*/
|
2012-01-29 10:22:01 +04:00
|
|
|
if (perfuse_diagflags & PDF_TRACE)
|
|
|
|
pt = perfuse_trace_begin(ps, opc, pm);
|
2011-12-28 21:33:52 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do actual FUSE exchange
|
|
|
|
*/
|
2011-12-16 09:34:54 +04:00
|
|
|
if ((error = ps->ps_xchg_msg(pu, pm, len, wait)) != 0)
|
|
|
|
ps->ps_destroy_msg(pm);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2011-12-28 21:33:52 +04:00
|
|
|
/*
|
|
|
|
* Record FUSE call end if requested
|
|
|
|
*/
|
2012-01-29 10:22:01 +04:00
|
|
|
if (pt != NULL)
|
|
|
|
perfuse_trace_end(ps, pt, error);
|
2011-12-28 21:33:52 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
ps->ps_xchgcount--;
|
2010-09-29 12:01:10 +04:00
|
|
|
if (pnd) {
|
2012-07-21 09:49:42 +04:00
|
|
|
pnd->pnd_inxchg--;
|
|
|
|
(void)dequeue_requests(opc, PCQ_AFTERXCHG, DEQUEUE_ALL);
|
2010-09-29 12:01:10 +04:00
|
|
|
}
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2010-08-28 07:46:21 +04:00
|
|
|
static int
|
2012-03-21 14:10:36 +04:00
|
|
|
mode_access(puffs_cookie_t opc, const struct puffs_cred *pcr, mode_t mode)
|
2010-08-28 07:46:21 +04:00
|
|
|
{
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct vattr *va;
|
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
/*
|
|
|
|
* pcr is NULL for self open through fsync or readdir.
|
|
|
|
* In both case, access control is useless, as it was
|
|
|
|
* done before, at open time.
|
|
|
|
*/
|
|
|
|
if (pcr == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2010-08-28 07:46:21 +04:00
|
|
|
pn = (struct puffs_node *)opc;
|
|
|
|
va = puffs_pn_getvap(pn);
|
|
|
|
return puffs_access(va->va_type, va->va_mode,
|
|
|
|
va->va_uid, va->va_gid,
|
|
|
|
mode, pcr);
|
|
|
|
}
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
static int
|
2012-07-21 09:49:42 +04:00
|
|
|
sticky_access(puffs_cookie_t opc, struct puffs_node *targ,
|
|
|
|
const struct puffs_cred *pcr)
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
{
|
|
|
|
uid_t uid;
|
2014-09-03 20:01:45 +04:00
|
|
|
int sticky, owner, parent_owner;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
/*
|
|
|
|
* This covers the case where the kernel requests a DELETE
|
|
|
|
* or RENAME on its own, and where puffs_cred_getuid would
|
|
|
|
* return -1. While such a situation should not happen,
|
|
|
|
* we allow it here.
|
|
|
|
*
|
|
|
|
* This also allows root to tamper with other users' files
|
|
|
|
* that have the sticky bit.
|
|
|
|
*/
|
|
|
|
if (puffs_cred_isjuggernaut(pcr))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (puffs_cred_getuid(pcr, &uid) != 0)
|
|
|
|
DERRX(EX_SOFTWARE, "puffs_cred_getuid fails in %s", __func__);
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
sticky = puffs_pn_getvap(opc)->va_mode & S_ISTXT;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
owner = puffs_pn_getvap(targ)->va_uid == uid;
|
2014-09-03 20:01:45 +04:00
|
|
|
parent_owner = puffs_pn_getvap(opc)->va_uid == uid;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2014-09-03 20:01:45 +04:00
|
|
|
if (sticky && !owner && !parent_owner)
|
|
|
|
return EPERM;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2011-08-09 13:06:52 +04:00
|
|
|
return 0;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
static void
|
2012-03-21 14:10:36 +04:00
|
|
|
fuse_attr_to_vap(struct perfuse_state *ps, struct vattr *vap,
|
|
|
|
struct fuse_attr *fa)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
vap->va_type = IFTOVT(fa->mode);
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
vap->va_mode = fa->mode & ALLPERMS;
|
2010-08-25 11:16:00 +04:00
|
|
|
vap->va_nlink = fa->nlink;
|
|
|
|
vap->va_uid = fa->uid;
|
|
|
|
vap->va_gid = fa->gid;
|
2011-05-18 19:28:12 +04:00
|
|
|
vap->va_fsid = (long)ps->ps_fsid;
|
2010-08-25 11:16:00 +04:00
|
|
|
vap->va_fileid = fa->ino;
|
|
|
|
vap->va_size = fa->size;
|
|
|
|
vap->va_blocksize = fa->blksize;
|
2010-09-01 18:57:24 +04:00
|
|
|
vap->va_atime.tv_sec = (time_t)fa->atime;
|
|
|
|
vap->va_atime.tv_nsec = (long) fa->atimensec;
|
|
|
|
vap->va_mtime.tv_sec = (time_t)fa->mtime;
|
|
|
|
vap->va_mtime.tv_nsec = (long)fa->mtimensec;
|
|
|
|
vap->va_ctime.tv_sec = (time_t)fa->ctime;
|
|
|
|
vap->va_ctime.tv_nsec = (long)fa->ctimensec;
|
2010-08-25 11:16:00 +04:00
|
|
|
vap->va_birthtime.tv_sec = 0;
|
|
|
|
vap->va_birthtime.tv_nsec = 0;
|
|
|
|
vap->va_gen = 0;
|
|
|
|
vap->va_flags = 0;
|
|
|
|
vap->va_rdev = fa->rdev;
|
|
|
|
vap->va_bytes = fa->size;
|
2010-10-11 05:08:26 +04:00
|
|
|
vap->va_filerev = (u_quad_t)PUFFS_VNOVAL;
|
2010-08-25 11:16:00 +04:00
|
|
|
vap->va_vaflags = 0;
|
|
|
|
|
|
|
|
if (vap->va_blocksize == 0)
|
|
|
|
vap->va_blocksize = DEV_BSIZE;
|
|
|
|
|
2010-10-11 05:08:26 +04:00
|
|
|
if (vap->va_size == (size_t)PUFFS_VNOVAL) /* XXX */
|
2010-08-25 11:16:00 +04:00
|
|
|
vap->va_size = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
#ifdef PUFFS_KFLAG_CACHE_FS_TTL
|
2012-07-21 09:49:42 +04:00
|
|
|
static void
|
|
|
|
perfuse_newinfo_setttl(struct puffs_newinfo *pni,
|
|
|
|
struct puffs_node *pn, struct fuse_entry_out *feo,
|
|
|
|
struct fuse_attr_out *fao)
|
2012-04-18 04:57:21 +04:00
|
|
|
{
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if ((feo == NULL) && (fao == NULL))
|
|
|
|
DERRX(EX_SOFTWARE, "%s: feo and fao NULL", __func__);
|
|
|
|
|
|
|
|
if ((feo != NULL) && (fao != NULL))
|
|
|
|
DERRX(EX_SOFTWARE, "%s: feo and fao != NULL", __func__);
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
|
|
|
|
|
|
|
if (fao != NULL) {
|
|
|
|
struct timespec va_ttl;
|
|
|
|
|
|
|
|
va_ttl.tv_sec = fao->attr_valid;
|
|
|
|
va_ttl.tv_nsec = fao->attr_valid_nsec;
|
|
|
|
|
|
|
|
puffs_newinfo_setvattl(pni, &va_ttl);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feo != NULL) {
|
|
|
|
struct timespec va_ttl;
|
|
|
|
struct timespec cn_ttl;
|
2012-07-21 09:49:42 +04:00
|
|
|
struct timespec now;
|
|
|
|
struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(pn);
|
2012-04-18 04:57:21 +04:00
|
|
|
|
|
|
|
va_ttl.tv_sec = feo->attr_valid;
|
|
|
|
va_ttl.tv_nsec = feo->attr_valid_nsec;
|
|
|
|
cn_ttl.tv_sec = feo->entry_valid;
|
|
|
|
cn_ttl.tv_nsec = feo->entry_valid_nsec;
|
|
|
|
|
|
|
|
puffs_newinfo_setvattl(pni, &va_ttl);
|
|
|
|
puffs_newinfo_setcnttl(pni, &cn_ttl);
|
2012-07-21 09:49:42 +04:00
|
|
|
|
|
|
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
|
|
|
DERR(EX_OSERR, "clock_gettime failed");
|
|
|
|
|
|
|
|
timespecadd(&now, &cn_ttl, &pnd->pnd_cn_expire);
|
2012-04-18 04:57:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2012-04-08 19:13:06 +04:00
|
|
|
#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
|
2011-10-30 09:11:37 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
static int
|
2012-03-21 14:10:36 +04:00
|
|
|
node_lookup_common(struct puffs_usermount *pu, puffs_cookie_t opc,
|
2012-04-18 04:57:21 +04:00
|
|
|
struct puffs_newinfo *pni, const char *path,
|
|
|
|
const struct puffs_cred *pcr, struct puffs_node **pnp)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
2011-10-30 09:11:37 +04:00
|
|
|
struct perfuse_node_data *oldpnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_entry_out *feo;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
size_t len;
|
|
|
|
int error;
|
|
|
|
|
2011-11-28 09:33:33 +04:00
|
|
|
/*
|
|
|
|
* Prevent further lookups if the parent was removed
|
|
|
|
*/
|
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ESTALE;
|
|
|
|
|
2011-10-30 09:11:37 +04:00
|
|
|
if (pnp == NULL)
|
|
|
|
DERRX(EX_SOFTWARE, "pnp must be != NULL");
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
|
|
|
DPRINTF("%s: opc = %p, file = \"%s\" looking up \"%s\"\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
__func__, (void *)opc,
|
|
|
|
perfuse_node_path(ps, opc), path);
|
|
|
|
|
|
|
|
if (strcmp(path, ".") == 0)
|
|
|
|
DERRX(EX_SOFTWARE, "unexpected dot-lookup");
|
|
|
|
|
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_RECLAIMED)
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"looking up reclaimed node opc = %p, name = \"%s\"",
|
|
|
|
opc, path);
|
|
|
|
|
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_INVALID)
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"looking up freed node opc = %p, name = \"%s\"",
|
|
|
|
opc, path);
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
2010-10-03 09:46:47 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
len = strlen(path) + 1;
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, pcr);
|
2010-08-25 11:16:00 +04:00
|
|
|
(void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len);
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
|
2011-12-16 09:34:54 +04:00
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
|
|
|
|
|
2012-11-03 19:43:20 +04:00
|
|
|
/*
|
|
|
|
* Starting with ABI 7.4, inode number 0 means ENOENT,
|
|
|
|
* with entry_valid / entry_valid_nsec giving negative
|
|
|
|
* cache timeout (which we do not implement yet).
|
|
|
|
*/
|
|
|
|
if (feo->attr.ino == 0) {
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Check for a known node, not reclaimed, with another name.
|
|
|
|
* It may have been moved, or we can lookup ../
|
|
|
|
*/
|
|
|
|
if (((oldpnd = perfuse_node_bynodeid(ps, feo->nodeid)) != NULL) &&
|
|
|
|
!(oldpnd->pnd_flags & PND_RECLAIMED)) {
|
|
|
|
/*
|
|
|
|
* Save the new node name if not ..
|
|
|
|
*/
|
|
|
|
if (strncmp(path, "..", len) != 0)
|
|
|
|
(void)strlcpy(oldpnd->pnd_name,
|
|
|
|
path, MAXPATHLEN);
|
|
|
|
pn = oldpnd->pnd_pn;
|
2011-10-30 09:11:37 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
} else {
|
2012-04-18 04:57:21 +04:00
|
|
|
pn = perfuse_new_pn(pu, path, opc);
|
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_cache(ps, pn);
|
2012-04-18 04:57:21 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_RECLAIMED)
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"reclaimed in lookup opc = %p, name = \"%s\", ck = %p",
|
|
|
|
opc, path, pn);
|
|
|
|
|
|
|
|
if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_INVALID)
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"freed in lookup opc = %p, name = \"%s\", ck = %p",
|
|
|
|
opc, path, pn);
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
|
2010-10-11 05:08:26 +04:00
|
|
|
pn->pn_va.va_gen = (u_long)(feo->generation);
|
2012-07-21 09:49:42 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_fuse_nlookup++;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-10-30 09:11:37 +04:00
|
|
|
*pnp = pn;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, looked up opc = %p, "
|
|
|
|
"nodeid = 0x%"PRIx64" file = \"%s\"\n", __func__,
|
|
|
|
(void *)opc, pn, feo->nodeid, path);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
2012-07-21 09:49:42 +04:00
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
if (pni != NULL) {
|
|
|
|
#ifdef PUFFS_KFLAG_CACHE_FS_TTL
|
|
|
|
puffs_newinfo_setva(pni, &pn->pn_va);
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_newinfo_setttl(pni, pn, feo, NULL);
|
2012-04-18 04:57:21 +04:00
|
|
|
#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
|
|
|
|
puffs_newinfo_setcookie(pni, pn);
|
|
|
|
puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
|
|
|
|
puffs_newinfo_setsize(pni, (voff_t)pn->pn_va.va_size);
|
|
|
|
puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_NODELEAK) {
|
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_NODELEAK;
|
|
|
|
ps->ps_nodeleakcount--;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* Common code for methods that create objects:
|
2010-08-25 11:16:00 +04:00
|
|
|
* perfuse_node_mkdir
|
|
|
|
* perfuse_node_mknod
|
|
|
|
* perfuse_node_symlink
|
|
|
|
*/
|
|
|
|
static int
|
2012-03-21 14:10:36 +04:00
|
|
|
node_mk_common(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
|
|
|
|
perfuse_msg_t *pm)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct fuse_entry_out *feo;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
|
2011-12-16 09:34:54 +04:00
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
|
2011-10-30 09:11:37 +04:00
|
|
|
if (feo->nodeid == PERFUSE_UNKNOWN_NODEID)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: no nodeid", __func__);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
pn = perfuse_new_pn(pu, pcn->pcn_name, opc);
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
|
2012-07-21 09:49:42 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
|
|
|
|
perfuse_node_cache(ps, pn);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
|
2010-10-11 05:08:26 +04:00
|
|
|
pn->pn_va.va_gen = (u_long)(feo->generation);
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
puffs_newinfo_setcookie(pni, pn);
|
2012-04-18 04:57:21 +04:00
|
|
|
#ifdef PUFFS_KFLAG_CACHE_FS_TTL
|
|
|
|
puffs_newinfo_setva(pni, &pn->pn_va);
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_newinfo_setttl(pni, pn, feo, NULL);
|
|
|
|
#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
|
2012-04-18 04:57:21 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
|
|
|
DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
|
2011-10-30 09:11:37 +04:00
|
|
|
"nodeid = 0x%"PRIx64"\n",
|
2010-10-03 09:46:47 +04:00
|
|
|
__func__, (void *)pn, pcn->pcn_name,
|
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid);
|
|
|
|
#endif
|
2010-08-28 07:46:21 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-04-18 04:57:21 +04:00
|
|
|
|
|
|
|
/* Parents is now dirty */
|
2010-09-09 13:12:35 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
|
2010-10-03 09:46:47 +04:00
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2011-07-14 19:37:32 +04:00
|
|
|
static uint64_t
|
2012-03-21 14:10:36 +04:00
|
|
|
readdir_last_cookie(struct fuse_dirent *fd, size_t fd_len)
|
2011-07-14 19:37:32 +04:00
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
size_t seen = 0;
|
|
|
|
char *ndp;
|
|
|
|
|
|
|
|
do {
|
|
|
|
len = FUSE_DIRENT_ALIGN(sizeof(*fd) + fd->namelen);
|
|
|
|
seen += len;
|
|
|
|
|
|
|
|
if (seen >= fd_len)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ndp = (char *)(void *)fd + (size_t)len;
|
|
|
|
fd = (struct fuse_dirent *)(void *)ndp;
|
|
|
|
} while (1 /* CONSTCOND */);
|
|
|
|
|
|
|
|
return fd->off;
|
|
|
|
}
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
static ssize_t
|
2012-03-21 14:10:36 +04:00
|
|
|
fuse_to_dirent(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct fuse_dirent *fd, size_t fd_len)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct dirent *dents;
|
|
|
|
size_t dents_len;
|
|
|
|
ssize_t written;
|
|
|
|
uint64_t fd_offset;
|
|
|
|
struct fuse_dirent *fd_base;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
fd_base = fd;
|
|
|
|
fd_offset = 0;
|
|
|
|
written = 0;
|
|
|
|
dents = PERFUSE_NODE_DATA(opc)->pnd_dirent;
|
2010-09-06 05:17:05 +04:00
|
|
|
dents_len = (size_t)PERFUSE_NODE_DATA(opc)->pnd_dirent_len;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
do {
|
|
|
|
char *ndp;
|
|
|
|
size_t reclen;
|
|
|
|
|
|
|
|
reclen = _DIRENT_RECLEN(dents, fd->namelen);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check we do not overflow the output buffer
|
|
|
|
* struct fuse_dirent is bigger than struct dirent,
|
|
|
|
* so we should always use fd_len and never reallocate
|
|
|
|
* later.
|
|
|
|
* If we have to reallocate,try to double the buffer
|
|
|
|
* each time so that we do not have to do it too often.
|
|
|
|
*/
|
|
|
|
if (written + reclen > dents_len) {
|
|
|
|
if (dents_len == 0)
|
|
|
|
dents_len = fd_len;
|
|
|
|
else
|
|
|
|
dents_len =
|
|
|
|
MAX(2 * dents_len, written + reclen);
|
|
|
|
|
|
|
|
dents = PERFUSE_NODE_DATA(opc)->pnd_dirent;
|
|
|
|
if ((dents = realloc(dents, dents_len)) == NULL)
|
2011-08-14 03:12:15 +04:00
|
|
|
DERR(EX_OSERR, "%s: malloc failed", __func__);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_dirent = dents;
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_dirent_len = dents_len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (void *) for delint
|
|
|
|
*/
|
|
|
|
ndp = (char *)(void *)dents + written;
|
|
|
|
dents = (struct dirent *)(void *)ndp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Filesystem was mounted without -o use_ino
|
|
|
|
* Perform a lookup to find it.
|
|
|
|
*/
|
|
|
|
if (fd->ino == PERFUSE_UNKNOWN_INO) {
|
|
|
|
struct puffs_node *pn;
|
2014-01-06 12:56:34 +04:00
|
|
|
struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2014-01-06 12:56:34 +04:00
|
|
|
/*
|
|
|
|
* Avoid breaking out of fs
|
|
|
|
* by lookup to .. on root
|
|
|
|
*/
|
|
|
|
if ((strcmp(fd->name, "..") == 0) &&
|
|
|
|
(pnd->pnd_nodeid == FUSE_ROOT_ID)) {
|
|
|
|
fd->ino = FUSE_ROOT_ID;
|
2011-10-30 09:11:37 +04:00
|
|
|
} else {
|
2014-01-06 12:56:34 +04:00
|
|
|
if (node_lookup_common(pu, opc, NULL, fd->name,
|
|
|
|
NULL, &pn) != 0) {
|
|
|
|
DWARNX("node_lookup_common failed");
|
|
|
|
} else {
|
|
|
|
fd->ino = pn->pn_va.va_fileid;
|
|
|
|
(void)perfuse_node_reclaim(pu, pn);
|
|
|
|
}
|
2011-10-30 09:11:37 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
dents->d_fileno = fd->ino;
|
2010-09-01 18:57:24 +04:00
|
|
|
dents->d_reclen = (unsigned short)reclen;
|
2010-08-25 11:16:00 +04:00
|
|
|
dents->d_namlen = fd->namelen;
|
|
|
|
dents->d_type = fd->type;
|
|
|
|
strlcpy(dents->d_name, fd->name, fd->namelen + 1);
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_READDIR)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: translated \"%s\" ino = %"PRIu64"\n",
|
2010-08-25 11:16:00 +04:00
|
|
|
__func__, dents->d_name, dents->d_fileno);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dents = _DIRENT_NEXT(dents);
|
|
|
|
written += reclen;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move to the next record.
|
2011-07-14 19:37:32 +04:00
|
|
|
* fd->off is not the offset, it is an opaque cookie
|
|
|
|
* given by the filesystem to keep state across multiple
|
|
|
|
* readdir() operation.
|
|
|
|
* Use record alignement instead.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
len = FUSE_DIRENT_ALIGN(sizeof(*fd) + fd->namelen);
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_READDIR)
|
2010-09-01 18:57:24 +04:00
|
|
|
DPRINTF("%s: record at %"PRId64"/0x%"PRIx64" "
|
|
|
|
"length = %zd/0x%zx. "
|
|
|
|
"next record at %"PRId64"/0x%"PRIx64" "
|
|
|
|
"max %zd/0x%zx\n",
|
2010-08-25 11:16:00 +04:00
|
|
|
__func__, fd_offset, fd_offset, len, len,
|
|
|
|
fd_offset + len, fd_offset + len,
|
|
|
|
fd_len, fd_len);
|
|
|
|
#endif
|
|
|
|
fd_offset += len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if next record is still within the packet
|
|
|
|
* If it is not, we reached the end of the buffer.
|
|
|
|
*/
|
|
|
|
if (fd_offset >= fd_len)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (void *) for delint
|
|
|
|
*/
|
|
|
|
ndp = (char *)(void *)fd_base + (size_t)fd_offset;
|
|
|
|
fd = (struct fuse_dirent *)(void *)ndp;
|
|
|
|
|
|
|
|
} while (1 /* CONSTCOND */);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust the dirent output length
|
|
|
|
*/
|
|
|
|
if (written != -1)
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_dirent_len = written;
|
|
|
|
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
static void
|
2012-03-21 14:10:36 +04:00
|
|
|
readdir_buffered(puffs_cookie_t opc, struct dirent *dent, off_t *readoff,
|
|
|
|
size_t *reslen)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct dirent *fromdent;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
char *ndp;
|
|
|
|
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
|
|
|
while (*readoff < pnd->pnd_dirent_len) {
|
|
|
|
/*
|
|
|
|
* (void *) for delint
|
|
|
|
*/
|
|
|
|
ndp = (char *)(void *)pnd->pnd_dirent + (size_t)*readoff;
|
|
|
|
fromdent = (struct dirent *)(void *)ndp;
|
|
|
|
|
|
|
|
if (*reslen < _DIRENT_SIZE(fromdent))
|
|
|
|
break;
|
|
|
|
|
|
|
|
memcpy(dent, fromdent, _DIRENT_SIZE(fromdent));
|
|
|
|
*readoff += _DIRENT_SIZE(fromdent);
|
|
|
|
*reslen -= _DIRENT_SIZE(fromdent);
|
|
|
|
|
|
|
|
dent = _DIRENT_NEXT(dent);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_READDIR)
|
2010-09-06 05:17:05 +04:00
|
|
|
DPRINTF("%s: readoff = %"PRId64", "
|
|
|
|
"pnd->pnd_dirent_len = %"PRId64"\n",
|
2010-08-25 11:16:00 +04:00
|
|
|
__func__, *readoff, pnd->pnd_dirent_len);
|
|
|
|
#endif
|
|
|
|
if (*readoff >= pnd->pnd_dirent_len) {
|
|
|
|
free(pnd->pnd_dirent);
|
|
|
|
pnd->pnd_dirent = NULL;
|
|
|
|
pnd->pnd_dirent_len = 0;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_ref(puffs_cookie_t opc)
|
|
|
|
{
|
|
|
|
struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (pnd->pnd_flags & PND_INVALID)
|
|
|
|
DERRX(EX_SOFTWARE, "Use of freed node opc = %p", opc);
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
|
|
|
|
|
|
|
pnd->pnd_ref++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_rele(puffs_cookie_t opc)
|
|
|
|
{
|
|
|
|
struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (pnd->pnd_flags & PND_INVALID)
|
|
|
|
DERRX(EX_SOFTWARE, "Use of freed node opc = %p", opc);
|
|
|
|
#endif /* PERFUSE_DEBUG */
|
|
|
|
|
|
|
|
pnd->pnd_ref--;
|
|
|
|
|
|
|
|
if (pnd->pnd_ref == 0)
|
|
|
|
(void)dequeue_requests(opc, PCQ_REF, DEQUEUE_ALL);
|
|
|
|
|
|
|
|
return;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 14:10:36 +04:00
|
|
|
requeue_request(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
enum perfuse_qtype type)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_cc_queue pcq;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
|
|
|
|
ps = perfuse_getspecific(pu);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
pcq.pcq_type = type;
|
|
|
|
pcq.pcq_cc = puffs_cc_getcc(pu);
|
|
|
|
TAILQ_INSERT_TAIL(&pnd->pnd_pcq, &pcq, pcq_next);
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_REQUEUE)
|
2010-09-15 05:51:43 +04:00
|
|
|
DPRINTF("%s: REQUEUE opc = %p, pcc = %p (%s)\n",
|
|
|
|
__func__, (void *)opc, pcq.pcq_cc,
|
|
|
|
perfuse_qtypestr[type]);
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
puffs_cc_yield(pcq.pcq_cc);
|
2010-09-02 12:58:06 +04:00
|
|
|
TAILQ_REMOVE(&pnd->pnd_pcq, &pcq, pcq_next);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_REQUEUE)
|
2010-09-15 05:51:43 +04:00
|
|
|
DPRINTF("%s: RESUME opc = %p, pcc = %p (%s)\n",
|
|
|
|
__func__, (void *)opc, pcq.pcq_cc,
|
|
|
|
perfuse_qtypestr[type]);
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
static int
|
2012-07-21 09:49:42 +04:00
|
|
|
dequeue_requests(puffs_cookie_t opc, enum perfuse_qtype type, int max)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_cc_queue *pcq;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
int dequeued;
|
|
|
|
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
dequeued = 0;
|
|
|
|
TAILQ_FOREACH(pcq, &pnd->pnd_pcq, pcq_next) {
|
|
|
|
if (pcq->pcq_type != type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_REQUEUE)
|
2010-09-15 05:51:43 +04:00
|
|
|
DPRINTF("%s: SCHEDULE opc = %p, pcc = %p (%s)\n",
|
|
|
|
__func__, (void *)opc, pcq->pcq_cc,
|
|
|
|
perfuse_qtypestr[type]);
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
2010-09-02 12:58:06 +04:00
|
|
|
puffs_cc_schedule(pcq->pcq_cc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
if (++dequeued == max)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_REQUEUE)
|
|
|
|
DPRINTF("%s: DONE opc = %p\n", __func__, (void *)opc);
|
|
|
|
#endif
|
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
return dequeued;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_init(struct puffs_usermount *pu)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_init_in *fii;
|
|
|
|
struct fuse_init_out *fio;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
if (puffs_mount(pu, ps->ps_target, ps->ps_mountflags, ps->ps_root) != 0)
|
2011-08-14 03:12:15 +04:00
|
|
|
DERR(EX_OSERR, "%s: puffs_mount failed", __func__);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux 2.6.34.1 sends theses flags:
|
|
|
|
* FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC
|
|
|
|
* FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK
|
|
|
|
*
|
|
|
|
* Linux also sets max_readahead at 32 pages (128 kB)
|
2011-08-02 18:53:38 +04:00
|
|
|
*
|
|
|
|
* ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, 0, FUSE_INIT, sizeof(*fii), NULL);
|
|
|
|
fii = GET_INPAYLOAD(ps, pm, fuse_init_in);
|
|
|
|
fii->major = FUSE_KERNEL_VERSION;
|
|
|
|
fii->minor = FUSE_KERNEL_MINOR_VERSION;
|
2011-09-10 02:51:44 +04:00
|
|
|
fii->max_readahead = (unsigned int)(32 * sysconf(_SC_PAGESIZE));
|
2010-08-25 11:16:00 +04:00
|
|
|
fii->flags = (FUSE_ASYNC_READ|FUSE_POSIX_LOCKS|FUSE_ATOMIC_O_TRUNC);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, 0, pm, sizeof(*fio), wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
DERRX(EX_SOFTWARE, "init message exchange failed (%d)", error);
|
|
|
|
|
|
|
|
fio = GET_OUTPAYLOAD(ps, pm, fuse_init_out);
|
|
|
|
ps->ps_max_readahead = fio->max_readahead;
|
|
|
|
ps->ps_max_write = fio->max_write;
|
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_unmount(struct puffs_usermount *pu, int flags)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
puffs_cookie_t opc;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
opc = (puffs_cookie_t)puffs_getroot(pu);
|
2011-08-02 18:53:38 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser.
|
|
|
|
*/
|
2010-08-25 11:16:00 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_DESTROY, 0, NULL);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0){
|
2010-08-25 11:16:00 +04:00
|
|
|
DWARN("unmount %s", ps->ps_target);
|
|
|
|
if (!(flags & MNT_FORCE))
|
2011-12-16 09:34:54 +04:00
|
|
|
return error;
|
|
|
|
else
|
|
|
|
error = 0;
|
|
|
|
} else {
|
|
|
|
ps->ps_destroy_msg(pm);
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2011-05-30 18:50:08 +04:00
|
|
|
ps->ps_umount(pu);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-05-30 18:50:08 +04:00
|
|
|
if (perfuse_diagflags & PDF_MISC)
|
|
|
|
DPRINTF("%s unmounted, exit\n", ps->ps_target);
|
|
|
|
|
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_statvfs(struct puffs_usermount *pu, struct statvfs *svfsb)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
puffs_cookie_t opc;
|
|
|
|
struct fuse_statfs_out *fso;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
opc = (puffs_cookie_t)puffs_getroot(pu);
|
2011-08-02 18:53:38 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser.
|
|
|
|
*/
|
2010-08-25 11:16:00 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply)) != 0)
|
2011-12-16 09:34:54 +04:00
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out);
|
|
|
|
svfsb->f_flag = ps->ps_mountflags;
|
|
|
|
svfsb->f_bsize = fso->st.bsize;
|
|
|
|
svfsb->f_frsize = fso->st.frsize;
|
|
|
|
svfsb->f_iosize = ((struct puffs_node *)opc)->pn_va.va_blocksize;
|
|
|
|
svfsb->f_blocks = fso->st.blocks;
|
|
|
|
svfsb->f_bfree = fso->st.bfree;
|
|
|
|
svfsb->f_bavail = fso->st.bavail;
|
|
|
|
svfsb->f_bresvd = fso->st.bfree - fso->st.bavail;
|
|
|
|
svfsb->f_files = fso->st.files;
|
|
|
|
svfsb->f_ffree = fso->st.ffree;
|
|
|
|
svfsb->f_favail = fso->st.ffree;/* files not reserved for root */
|
|
|
|
svfsb->f_fresvd = 0; /* files reserved for root */
|
|
|
|
|
|
|
|
svfsb->f_syncreads = ps->ps_syncreads;
|
|
|
|
svfsb->f_syncwrites = ps->ps_syncwrites;
|
|
|
|
|
|
|
|
svfsb->f_asyncreads = ps->ps_asyncreads;
|
|
|
|
svfsb->f_asyncwrites = ps->ps_asyncwrites;
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
(void)memcpy(&svfsb->f_fsidx, &ps->ps_fsid, sizeof(ps->ps_fsid));
|
|
|
|
svfsb->f_fsid = (unsigned long)ps->ps_fsid;
|
2010-08-25 11:16:00 +04:00
|
|
|
svfsb->f_namemax = MAXPATHLEN; /* XXX */
|
2010-08-27 13:58:17 +04:00
|
|
|
svfsb->f_owner = ps->ps_owner_uid;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
(void)strlcpy(svfsb->f_mntonname, ps->ps_target, _VFS_NAMELEN);
|
|
|
|
|
|
|
|
if (ps->ps_filesystemtype != NULL)
|
|
|
|
(void)strlcpy(svfsb->f_fstypename,
|
|
|
|
ps->ps_filesystemtype, _VFS_NAMELEN);
|
|
|
|
else
|
|
|
|
(void)strlcpy(svfsb->f_fstypename, "fuse", _VFS_NAMELEN);
|
|
|
|
|
|
|
|
if (ps->ps_source != NULL)
|
|
|
|
strlcpy(svfsb->f_mntfromname, ps->ps_source, _VFS_NAMELEN);
|
|
|
|
else
|
|
|
|
strlcpy(svfsb->f_mntfromname, _PATH_FUSE, _VFS_NAMELEN);
|
2011-12-16 09:34:54 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2011-12-16 09:34:54 +04:00
|
|
|
|
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_sync(struct puffs_usermount *pu, int waitfor,
|
|
|
|
const struct puffs_cred *pcr)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* FUSE does not seem to have a FS sync callback.
|
|
|
|
* Maybe do not even register this callback
|
|
|
|
*/
|
|
|
|
return puffs_fsnop_sync(pu, waitfor, pcr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
|
|
|
|
struct puffs_newinfo *pni)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie,
|
|
|
|
void *fid, size_t *fidsize)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
void
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_extattrctl(struct puffs_usermount *pu, int cmd,
|
|
|
|
puffs_cookie_t *cookie, int flags, int namespace, const char *attrname)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* 0 */
|
|
|
|
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
void
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_fs_suspend(struct puffs_usermount *pu, int status)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
2012-07-21 09:49:42 +04:00
|
|
|
struct perfuse_state *ps;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct puffs_node *pn;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
mode_t mode;
|
2010-08-25 11:16:00 +04:00
|
|
|
int error;
|
2010-10-11 05:08:26 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
node_ref(opc);
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Check permissions
|
|
|
|
*/
|
|
|
|
switch(pcn->pcn_nameiop) {
|
|
|
|
case NAMEI_DELETE: /* FALLTHROUGH */
|
|
|
|
case NAMEI_RENAME: /* FALLTHROUGH */
|
|
|
|
case NAMEI_CREATE:
|
2011-05-18 19:28:12 +04:00
|
|
|
if (pcn->pcn_flags & NAMEI_ISLASTCN)
|
|
|
|
mode = PUFFS_VEXEC|PUFFS_VWRITE;
|
|
|
|
else
|
|
|
|
mode = PUFFS_VEXEC;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
break;
|
|
|
|
case NAMEI_LOOKUP: /* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
mode = PUFFS_VEXEC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((error = mode_access(opc, pcn->pcn_cred, mode)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
error = node_lookup_common(pu, (puffs_cookie_t)opc, pni,
|
|
|
|
pcn->pcn_name, pcn->pcn_cred, &pn);
|
2010-09-29 12:01:10 +04:00
|
|
|
|
|
|
|
if (error != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-11-28 09:33:33 +04:00
|
|
|
/*
|
|
|
|
* Kernel would kill us if the filesystem returned the parent
|
|
|
|
* itself. If we want to live, hide that!
|
|
|
|
*/
|
|
|
|
if ((opc == (puffs_cookie_t)pn) && (strcmp(pcn->pcn_name, ".") != 0)) {
|
2012-04-08 19:13:06 +04:00
|
|
|
DERRX(EX_SOFTWARE, "lookup \"%s\" in \"%s\" returned parent",
|
2012-07-21 09:49:42 +04:00
|
|
|
pcn->pcn_name, perfuse_node_path(ps, opc));
|
2012-04-08 19:13:06 +04:00
|
|
|
/* NOTREACHED */
|
2012-07-21 09:49:42 +04:00
|
|
|
error = ESTALE;
|
|
|
|
goto out;
|
2011-11-28 09:33:33 +04:00
|
|
|
}
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Removed node
|
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_REMOVED) {
|
|
|
|
error = ENOENT;
|
|
|
|
goto out;
|
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Check for sticky bit. Unfortunately there is no way to
|
|
|
|
* do this before creating the puffs_node, since we require
|
|
|
|
* this operation to get the node owner.
|
|
|
|
*/
|
|
|
|
switch (pcn->pcn_nameiop) {
|
|
|
|
case NAMEI_DELETE: /* FALLTHROUGH */
|
|
|
|
case NAMEI_RENAME:
|
2012-07-21 09:49:42 +04:00
|
|
|
error = sticky_access(opc, pn, pcn->pcn_cred);
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
if (error != 0) {
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)perfuse_node_reclaim(pu, pn);
|
|
|
|
goto out;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
|
|
|
|
|
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
2010-09-29 12:01:10 +04:00
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_create(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
|
|
|
|
const struct vattr *vap)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
struct fuse_create_in *fci;
|
|
|
|
struct fuse_entry_out *feo;
|
|
|
|
struct fuse_open_out *foo;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
const char *name;
|
|
|
|
size_t namelen;
|
|
|
|
size_t len;
|
|
|
|
int error;
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* If create is unimplemented: Check that it does not
|
|
|
|
* already exists, and if not, do mknod and open
|
|
|
|
*/
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
if (ps->ps_flags & PS_NO_CREAT) {
|
2012-04-18 04:57:21 +04:00
|
|
|
error = node_lookup_common(pu, opc, NULL, pcn->pcn_name,
|
2011-08-02 18:53:38 +04:00
|
|
|
pcn->pcn_cred, &pn);
|
2012-07-21 09:49:42 +04:00
|
|
|
if (error == 0) {
|
|
|
|
(void)perfuse_node_reclaim(pu, pn);
|
|
|
|
error = EEXIST;
|
|
|
|
goto out;
|
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
error = perfuse_node_mknod(pu, opc, pni, pcn, vap);
|
2012-07-21 09:49:42 +04:00
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
error = node_lookup_common(pu, opc, NULL, pcn->pcn_name,
|
2011-08-02 18:53:38 +04:00
|
|
|
pcn->pcn_cred, &pn);
|
2012-07-21 09:49:42 +04:00
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
|
2010-10-11 05:08:26 +04:00
|
|
|
/*
|
|
|
|
* FUSE does the open at create time, while
|
|
|
|
* NetBSD will open in a subsequent operation.
|
|
|
|
* We need to open now, in order to retain FUSE
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* semantics. The calling process will not get
|
|
|
|
* a file descriptor before the kernel sends
|
|
|
|
* the open operation.
|
2010-10-11 05:08:26 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
error = perfuse_node_open(pu, (puffs_cookie_t)pn,
|
|
|
|
FWRITE, pcn->pcn_cred);
|
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
name = pcn->pcn_name;
|
|
|
|
namelen = pcn->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
len = sizeof(*fci) + namelen;
|
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
/*
|
|
|
|
* flags should use O_WRONLY instead of O_RDWR, but it
|
|
|
|
* breaks when the caller tries to read from file.
|
2010-09-07 20:58:13 +04:00
|
|
|
*
|
|
|
|
* mode must contain file type (ie: S_IFREG), use VTTOIF(vap->va_type)
|
2010-09-05 10:49:13 +04:00
|
|
|
*/
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_CREATE, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
fci = GET_INPAYLOAD(ps, pm, fuse_create_in);
|
2010-09-05 10:49:13 +04:00
|
|
|
fci->flags = O_CREAT | O_TRUNC | O_RDWR;
|
2010-09-07 20:58:13 +04:00
|
|
|
fci->mode = vap->va_mode | VTTOIF(vap->va_type);
|
2010-09-05 10:49:13 +04:00
|
|
|
fci->umask = 0; /* Seems unused by libfuse */
|
2010-08-25 11:16:00 +04:00
|
|
|
(void)strlcpy((char*)(void *)(fci + 1), name, namelen);
|
|
|
|
|
|
|
|
len = sizeof(*feo) + sizeof(*foo);
|
2011-12-16 09:34:54 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0) {
|
|
|
|
/*
|
|
|
|
* create is unimplmented, remember it for later,
|
|
|
|
* and start over using mknod and open instead.
|
|
|
|
*/
|
|
|
|
if (error == ENOSYS) {
|
|
|
|
ps->ps_flags |= PS_NO_CREAT;
|
2012-07-21 09:49:42 +04:00
|
|
|
error = perfuse_node_create(pu, opc, pni, pcn, vap);
|
2011-12-16 09:34:54 +04:00
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2011-12-16 09:34:54 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
|
|
|
|
foo = (struct fuse_open_out *)(void *)(feo + 1);
|
2011-10-30 09:11:37 +04:00
|
|
|
if (feo->nodeid == PERFUSE_UNKNOWN_NODEID)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: no nodeid", __func__);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Save the file handle and inode in node private data
|
|
|
|
* so that we can reuse it later
|
|
|
|
*/
|
2010-10-03 09:46:47 +04:00
|
|
|
pn = perfuse_new_pn(pu, name, opc);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
|
2012-07-21 09:49:42 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
|
|
|
|
perfuse_node_cache(ps, pn);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
|
2010-10-11 05:08:26 +04:00
|
|
|
pn->pn_va.va_gen = (u_long)(feo->generation);
|
2012-04-18 04:57:21 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
puffs_newinfo_setcookie(pni, pn);
|
2012-04-18 04:57:21 +04:00
|
|
|
#ifdef PUFFS_KFLAG_CACHE_FS_TTL
|
|
|
|
puffs_newinfo_setva(pni, &pn->pn_va);
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_newinfo_setttl(pni, pn, feo, NULL);
|
2012-04-18 04:57:21 +04:00
|
|
|
#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
|
2010-08-25 11:16:00 +04:00
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
|
|
|
|
DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
|
2011-10-30 09:11:37 +04:00
|
|
|
"nodeid = 0x%"PRIx64", wfh = 0x%"PRIx64"\n",
|
2010-09-29 12:01:10 +04:00
|
|
|
__func__, (void *)pn, pcn->pcn_name,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid,
|
|
|
|
foo->fh);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
2010-09-20 11:00:21 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
|
|
|
|
const struct vattr *vap)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_mknod_in *fmi;
|
|
|
|
const char* path;
|
|
|
|
size_t len;
|
2012-07-21 09:49:42 +04:00
|
|
|
int error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2010-08-28 07:46:21 +04:00
|
|
|
/*
|
|
|
|
* Only superuser can mknod objects other than
|
|
|
|
* directories, files, socks, fifo and links.
|
|
|
|
*
|
|
|
|
* Create an object require -WX permission in the parent directory
|
|
|
|
*/
|
|
|
|
switch (vap->va_type) {
|
|
|
|
case VDIR: /* FALLTHROUGH */
|
|
|
|
case VREG: /* FALLTHROUGH */
|
|
|
|
case VFIFO: /* FALLTHROUGH */
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
case VSOCK:
|
2010-08-28 07:46:21 +04:00
|
|
|
break;
|
|
|
|
default: /* VNON, VBLK, VCHR, VBAD */
|
2012-07-21 09:49:42 +04:00
|
|
|
if (!puffs_cred_isjuggernaut(pcn->pcn_cred)) {
|
2014-09-03 20:01:45 +04:00
|
|
|
error = EPERM;
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
|
|
|
}
|
2010-08-28 07:46:21 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-29 12:01:10 +04:00
|
|
|
path = pcn->pcn_name;
|
|
|
|
len = sizeof(*fmi) + pcn->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
/*
|
2010-09-07 20:58:13 +04:00
|
|
|
* mode must contain file type (ie: S_IFREG), use VTTOIF(vap->va_type)
|
2010-09-05 10:49:13 +04:00
|
|
|
*/
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_MKNOD, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
fmi = GET_INPAYLOAD(ps, pm, fuse_mknod_in);
|
|
|
|
fmi->mode = vap->va_mode | VTTOIF(vap->va_type);
|
2010-09-06 05:17:05 +04:00
|
|
|
fmi->rdev = (uint32_t)vap->va_rdev;
|
2010-08-25 11:16:00 +04:00
|
|
|
fmi->umask = 0; /* Seems unused bu libfuse */
|
|
|
|
(void)strlcpy((char *)(void *)(fmi + 1), path, len - sizeof(*fmi));
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
error = node_mk_common(pu, opc, pni, pcn, pm);
|
|
|
|
|
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
|
|
|
|
const struct puffs_cred *pcr)
|
2014-08-16 20:28:43 +04:00
|
|
|
{
|
|
|
|
return perfuse_node_open2(pu, opc, mode, pcr, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
perfuse_node_open2(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
|
|
|
|
const struct puffs_cred *pcr, int *oflags)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
mode_t fmode;
|
2010-08-25 11:16:00 +04:00
|
|
|
int op;
|
|
|
|
struct fuse_open_in *foi;
|
|
|
|
struct fuse_open_out *foo;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
pn = (struct puffs_node *)opc;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
error = 0;
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (pnd->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
if (puffs_pn_getvap(pn)->va_type == VDIR)
|
2010-08-25 11:16:00 +04:00
|
|
|
op = FUSE_OPENDIR;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
else
|
2010-08-25 11:16:00 +04:00
|
|
|
op = FUSE_OPEN;
|
2010-08-28 07:46:21 +04:00
|
|
|
|
|
|
|
/*
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* libfuse docs says
|
2011-05-18 19:28:12 +04:00
|
|
|
* - O_CREAT and O_EXCL should never be set.
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* - O_TRUNC may be used if mount option atomic_o_trunc is used XXX
|
|
|
|
*
|
|
|
|
* O_APPEND makes no sense since FUSE always sends
|
|
|
|
* the file offset for write operations. If the
|
|
|
|
* filesystem uses pwrite(), O_APPEND would cause
|
|
|
|
* the offset to be ignored and cause file corruption.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
2011-05-18 19:28:12 +04:00
|
|
|
mode &= ~(O_CREAT|O_EXCL|O_APPEND);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not open twice, and do not reopen for reading
|
2010-10-04 07:56:24 +04:00
|
|
|
* if we already have write handle.
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
*/
|
2013-07-18 13:01:20 +04:00
|
|
|
switch (mode & (FREAD|FWRITE)) {
|
|
|
|
case FREAD:
|
|
|
|
if (pnd->pnd_flags & (PND_RFH|PND_WFH))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case FWRITE:
|
|
|
|
if (pnd->pnd_flags & PND_WFH)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case FREAD|FWRITE:
|
|
|
|
if (pnd->pnd_flags & PND_WFH)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Corner case: if already open for reading (PND_RFH)
|
|
|
|
* and re-opening FREAD|FWRITE, we need to reopen,
|
|
|
|
* but only for writing. Note the change on mode
|
|
|
|
* will only affect perfuse_new_fh()
|
|
|
|
*/
|
|
|
|
if (pnd->pnd_flags & PND_RFH)
|
|
|
|
mode &= ~FREAD;
|
|
|
|
break;
|
2013-07-19 11:32:35 +04:00
|
|
|
default:
|
|
|
|
DWARNX("open without either FREAD nor FWRITE");
|
|
|
|
error = EPERM;
|
|
|
|
goto out;
|
2013-07-18 13:01:20 +04:00
|
|
|
}
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
/*
|
|
|
|
* Queue open on a node so that we do not open
|
|
|
|
* twice. This would be better with read and
|
|
|
|
* write distinguished.
|
|
|
|
*/
|
|
|
|
while (pnd->pnd_flags & PND_INOPEN)
|
|
|
|
requeue_request(pu, opc, PCQ_OPEN);
|
|
|
|
pnd->pnd_flags |= PND_INOPEN;
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
/*
|
|
|
|
* Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
|
|
|
|
* to O_RDONLY/O_WRONLY while perserving the other options.
|
|
|
|
*/
|
|
|
|
fmode = mode & ~(FREAD|FWRITE);
|
|
|
|
fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr);
|
|
|
|
foi = GET_INPAYLOAD(ps, pm, fuse_open_in);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
foi->flags = fmode;
|
2010-08-25 11:16:00 +04:00
|
|
|
foi->unused = 0;
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*foo), wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* Save the file handle in node private data
|
|
|
|
* so that we can reuse it later
|
|
|
|
*/
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
perfuse_new_fh(opc, foo->fh, mode);
|
2012-04-08 19:13:06 +04:00
|
|
|
|
2014-08-16 20:28:43 +04:00
|
|
|
/*
|
|
|
|
* Set direct I/O if the filesystems forces it
|
|
|
|
*/
|
|
|
|
if ((foo->open_flags & FUSE_FOPEN_DIRECT_IO) && (oflags != NULL))
|
|
|
|
*oflags |= PUFFS_OPEN_IO_DIRECT;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
|
2010-08-26 17:29:01 +04:00
|
|
|
DPRINTF("%s: opc = %p, file = \"%s\", "
|
2011-10-30 09:11:37 +04:00
|
|
|
"nodeid = 0x%"PRIx64", %s%sfh = 0x%"PRIx64"\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
__func__, (void *)opc, perfuse_node_path(ps, opc),
|
2011-10-30 09:11:37 +04:00
|
|
|
pnd->pnd_nodeid, mode & FREAD ? "r" : "",
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
mode & FWRITE ? "w" : "", foo->fh);
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2010-08-25 11:16:00 +04:00
|
|
|
out:
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
pnd->pnd_flags &= ~PND_INOPEN;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_OPEN, DEQUEUE_ALL);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
/* ARGSUSED0 */
|
2010-08-25 11:16:00 +04:00
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags,
|
|
|
|
const struct puffs_cred *pcr)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
2010-08-26 17:29:01 +04:00
|
|
|
|
|
|
|
if (!(pnd->pnd_flags & PND_OPEN))
|
2010-08-25 11:16:00 +04:00
|
|
|
return EBADF;
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
/*
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
* Actual close is postponed at inactive time.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
|
|
|
|
const struct puffs_cred *pcr)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
struct fuse_access_in *fai;
|
|
|
|
int error;
|
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* If we previously detected the filesystem does not
|
|
|
|
* implement access(), short-circuit the call and skip
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* to libpuffs access() emulation.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
if (ps->ps_flags & PS_NO_ACCESS) {
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
const struct vattr *vap;
|
2010-10-04 07:56:24 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
vap = puffs_pn_getvap((struct puffs_node *)opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
error = puffs_access(IFTOVT(vap->va_mode),
|
|
|
|
vap->va_mode & ACCESSPERMS,
|
|
|
|
vap->va_uid, vap->va_gid,
|
|
|
|
(mode_t)mode, pcr);
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Plain access call
|
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_ACCESS, sizeof(*fai), pcr);
|
|
|
|
fai = GET_INPAYLOAD(ps, pm, fuse_access_in);
|
|
|
|
fai->mask = 0;
|
|
|
|
fai->mask |= (mode & PUFFS_VREAD) ? R_OK : 0;
|
|
|
|
fai->mask |= (mode & PUFFS_VWRITE) ? W_OK : 0;
|
|
|
|
fai->mask |= (mode & PUFFS_VEXEC) ? X_OK : 0;
|
2010-09-29 12:01:10 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2010-10-11 05:08:26 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* If unimplemented, start over with emulation
|
|
|
|
*/
|
|
|
|
if (error == ENOSYS) {
|
|
|
|
ps->ps_flags |= PS_NO_ACCESS;
|
2012-07-21 09:49:42 +04:00
|
|
|
error = perfuse_node_access(pu, opc, mode, pcr);
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct vattr *vap, const struct puffs_cred *pcr)
|
2012-04-18 04:57:21 +04:00
|
|
|
{
|
|
|
|
return perfuse_node_getattr_ttl(pu, opc, vap, pcr, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
perfuse_node_getattr_ttl(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct vattr *vap, const struct puffs_cred *pcr,
|
|
|
|
struct timespec *va_ttl)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
2011-10-30 09:11:37 +04:00
|
|
|
perfuse_msg_t *pm = NULL;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct perfuse_state *ps;
|
2011-09-09 19:45:28 +04:00
|
|
|
struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_getattr_in *fgi;
|
|
|
|
struct fuse_attr_out *fao;
|
2011-10-30 09:11:37 +04:00
|
|
|
int error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2014-08-09 07:17:11 +04:00
|
|
|
if ((pnd->pnd_flags & PND_REMOVED) && !(pnd->pnd_flags & PND_OPEN))
|
2010-09-05 10:49:13 +04:00
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
/*
|
|
|
|
* Serialize size access, see comment in perfuse_node_setattr().
|
|
|
|
*/
|
|
|
|
while (pnd->pnd_flags & PND_INRESIZE)
|
|
|
|
requeue_request(pu, opc, PCQ_RESIZE);
|
|
|
|
pnd->pnd_flags |= PND_INRESIZE;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2011-10-30 09:11:37 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* FUSE_GETATTR_FH must be set in fgi->flags
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
* if we use for fgi->fh
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_GETATTR, sizeof(*fgi), pcr);
|
|
|
|
fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in);
|
|
|
|
fgi->getattr_flags = 0;
|
|
|
|
fgi->dummy = 0;
|
2010-10-04 07:56:24 +04:00
|
|
|
fgi->fh = 0;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2010-10-04 07:56:24 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) {
|
|
|
|
fgi->fh = perfuse_get_fh(opc, FREAD);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
fgi->getattr_flags |= FUSE_GETATTR_FH;
|
2010-10-04 07:56:24 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RESIZE)
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF(">> %s %p %" PRIu64 "\n", __func__, (void *)opc,
|
|
|
|
vap->va_size);
|
2011-09-09 19:45:28 +04:00
|
|
|
#endif
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*fao), wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RESIZE)
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF("<< %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
|
|
|
|
(void *)opc, vap->va_size, fao->attr.size);
|
2011-09-09 19:45:28 +04:00
|
|
|
#endif
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
2011-10-30 09:11:37 +04:00
|
|
|
* We set birthtime, flags, filerev,vaflags to 0.
|
2010-08-25 11:16:00 +04:00
|
|
|
* This seems the best bet, since the information is
|
|
|
|
* not available from filesystem.
|
|
|
|
*/
|
|
|
|
fuse_attr_to_vap(ps, vap, &fao->attr);
|
2012-04-18 04:57:21 +04:00
|
|
|
|
|
|
|
if (va_ttl != NULL) {
|
|
|
|
va_ttl->tv_sec = fao->attr_valid;
|
|
|
|
va_ttl->tv_nsec = fao->attr_valid_nsec;
|
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
out:
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
pnd->pnd_flags &= ~PND_INRESIZE;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_RESIZE, DEQUEUE_ALL);
|
2011-09-09 19:45:28 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
const struct vattr *vap, const struct puffs_cred *pcr)
|
2012-04-18 04:57:21 +04:00
|
|
|
{
|
|
|
|
return perfuse_node_setattr_ttl(pu, opc,
|
2012-06-28 17:53:13 +04:00
|
|
|
__UNCONST(vap), pcr, NULL, 0);
|
2012-04-18 04:57:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
perfuse_node_setattr_ttl(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct vattr *vap, const struct puffs_cred *pcr,
|
2012-07-21 09:49:42 +04:00
|
|
|
struct timespec *va_ttl, int xflag)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
uint64_t fh;
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_setattr_in *fsi;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
struct fuse_attr_out *fao;
|
2010-08-28 07:46:21 +04:00
|
|
|
struct vattr *old_va;
|
2012-07-21 09:49:42 +04:00
|
|
|
enum perfuse_xchg_pb_reply reply;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
int error;
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
struct vattr *old_vap;
|
|
|
|
int resize_debug = 0;
|
|
|
|
#endif
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
2010-09-05 10:49:13 +04:00
|
|
|
/*
|
|
|
|
* The only operation we can do once the file is removed
|
|
|
|
* is to resize it, and we can do it only if it is open.
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
* Do not even send the operation to the filesystem: the
|
|
|
|
* file is not there anymore.
|
2010-09-05 10:49:13 +04:00
|
|
|
*/
|
|
|
|
if (pnd->pnd_flags & PND_REMOVED) {
|
|
|
|
if (!(pnd->pnd_flags & PND_OPEN))
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
return 0;
|
2010-09-05 10:49:13 +04:00
|
|
|
}
|
|
|
|
|
2010-08-28 07:46:21 +04:00
|
|
|
old_va = puffs_pn_getvap((struct puffs_node *)opc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for permission to change size
|
2012-07-21 09:49:42 +04:00
|
|
|
* It is always allowed if we already have a write file handle
|
2010-08-28 07:46:21 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
|
|
|
|
!(pnd->pnd_flags & PND_WFH) &&
|
|
|
|
(error = mode_access(opc, pcr, PUFFS_VWRITE)) != 0)
|
|
|
|
return error;
|
2010-08-28 07:46:21 +04:00
|
|
|
|
|
|
|
/*
|
2012-07-21 09:49:42 +04:00
|
|
|
* Check for permission to change dates
|
2010-08-28 07:46:21 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if (((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) ||
|
|
|
|
(vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) &&
|
|
|
|
(puffs_access_times(old_va->va_uid, old_va->va_gid,
|
|
|
|
old_va->va_mode, 0, pcr) != 0))
|
2014-09-03 20:01:45 +04:00
|
|
|
return EPERM;
|
2012-06-14 09:58:22 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Check for permission to change owner and group
|
|
|
|
*/
|
|
|
|
if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) ||
|
|
|
|
(vap->va_gid != (gid_t)PUFFS_VNOVAL)) &&
|
|
|
|
(puffs_access_chown(old_va->va_uid, old_va->va_gid,
|
|
|
|
vap->va_uid, vap->va_gid, pcr)) != 0)
|
2014-09-03 20:01:45 +04:00
|
|
|
return EPERM;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for sticky bit on non-directory by non root user
|
|
|
|
*/
|
|
|
|
if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
|
|
|
|
(vap->va_mode & S_ISTXT) && (old_va->va_type != VDIR) &&
|
|
|
|
!puffs_cred_isjuggernaut(pcr))
|
|
|
|
return EFTYPE;
|
2010-08-28 07:46:21 +04:00
|
|
|
|
|
|
|
/*
|
2012-06-14 09:58:22 +04:00
|
|
|
* Check for permission to change permissions
|
2010-08-28 07:46:21 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
|
|
|
|
(puffs_access_chmod(old_va->va_uid, old_va->va_gid,
|
|
|
|
old_va->va_type, vap->va_mode, pcr)) != 0)
|
2014-09-03 20:01:45 +04:00
|
|
|
return EPERM;
|
2012-07-21 09:49:42 +04:00
|
|
|
|
|
|
|
node_ref(opc);
|
|
|
|
|
|
|
|
if (pnd->pnd_flags & PND_WFH)
|
|
|
|
fh = perfuse_get_fh(opc, FWRITE);
|
|
|
|
else
|
|
|
|
fh = FUSE_UNKNOWN_FH;
|
2010-08-28 07:46:21 +04:00
|
|
|
|
|
|
|
/*
|
2012-07-21 09:49:42 +04:00
|
|
|
* fchmod() sets mode and fh, and it may carry
|
|
|
|
* a resize as well. That may break if the
|
|
|
|
* filesystem does chmod then resize, and fails
|
|
|
|
* because it does not have permission anymore.
|
|
|
|
* We work this around by splitting into two setattr.
|
2010-08-28 07:46:21 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
|
|
|
|
(vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
|
|
|
|
(fh != FUSE_UNKNOWN_FH)) {
|
|
|
|
struct vattr resize_va;
|
2012-06-14 09:58:22 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)memcpy(&resize_va, vap, sizeof(resize_va));
|
|
|
|
resize_va.va_mode = (mode_t)PUFFS_VNOVAL;
|
|
|
|
if ((error = perfuse_node_setattr_ttl(pu, opc, &resize_va,
|
|
|
|
pcr, va_ttl, xflag)) != 0)
|
|
|
|
goto out2;
|
2012-06-14 09:58:22 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
vap->va_size = (u_quad_t)PUFFS_VNOVAL;
|
2012-06-14 09:58:22 +04:00
|
|
|
}
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr);
|
|
|
|
fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
|
|
|
|
fsi->valid = 0;
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
/*
|
|
|
|
* Get a fh if the node is open for writing
|
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if (fh != FUSE_UNKNOWN_FH) {
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->fh = fh;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fsi->valid |= FUSE_FATTR_FH;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
|
|
|
|
if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) {
|
2011-09-09 19:45:28 +04:00
|
|
|
fsi->size = vap->va_size;
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->valid |= FUSE_FATTR_SIZE;
|
2011-09-09 19:45:28 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Serialize anything that can touch file size
|
|
|
|
* to avoid reordered GETATTR and SETATTR.
|
|
|
|
* Out of order SETATTR can report stale size,
|
|
|
|
* which will cause the kernel to truncate the file.
|
2012-04-08 19:13:06 +04:00
|
|
|
* XXX Probably useless now we have a lock on GETATTR
|
2011-09-09 19:45:28 +04:00
|
|
|
*/
|
|
|
|
while (pnd->pnd_flags & PND_INRESIZE)
|
|
|
|
requeue_request(pu, opc, PCQ_RESIZE);
|
|
|
|
pnd->pnd_flags |= PND_INRESIZE;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2010-10-11 05:08:26 +04:00
|
|
|
/*
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* Setting mtime without atime or vice versa leads to
|
2010-10-11 05:08:26 +04:00
|
|
|
* dates being reset to Epoch on glusterfs. If one
|
|
|
|
* is missing, use the old value.
|
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) ||
|
|
|
|
(vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)) {
|
|
|
|
|
|
|
|
if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) {
|
2010-10-11 05:08:26 +04:00
|
|
|
fsi->atime = vap->va_atime.tv_sec;
|
|
|
|
fsi->atimensec = (uint32_t)vap->va_atime.tv_nsec;
|
|
|
|
} else {
|
|
|
|
fsi->atime = old_va->va_atime.tv_sec;
|
|
|
|
fsi->atimensec = (uint32_t)old_va->va_atime.tv_nsec;
|
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) {
|
2010-10-11 05:08:26 +04:00
|
|
|
fsi->mtime = vap->va_mtime.tv_sec;
|
|
|
|
fsi->mtimensec = (uint32_t)vap->va_mtime.tv_nsec;
|
|
|
|
} else {
|
|
|
|
fsi->mtime = old_va->va_mtime.tv_sec;
|
|
|
|
fsi->mtimensec = (uint32_t)old_va->va_mtime.tv_nsec;
|
|
|
|
}
|
|
|
|
|
|
|
|
fsi->valid |= (FUSE_FATTR_MTIME|FUSE_FATTR_ATIME);
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (vap->va_mode != (mode_t)PUFFS_VNOVAL) {
|
2010-09-05 10:49:13 +04:00
|
|
|
fsi->mode = vap->va_mode;
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->valid |= FUSE_FATTR_MODE;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (vap->va_uid != (uid_t)PUFFS_VNOVAL) {
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->uid = vap->va_uid;
|
|
|
|
fsi->valid |= FUSE_FATTR_UID;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (vap->va_gid != (gid_t)PUFFS_VNOVAL) {
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->gid = vap->va_gid;
|
|
|
|
fsi->valid |= FUSE_FATTR_GID;
|
|
|
|
}
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
if (pnd->pnd_lock_owner != 0) {
|
|
|
|
fsi->lock_owner = pnd->pnd_lock_owner;
|
2010-08-25 11:16:00 +04:00
|
|
|
fsi->valid |= FUSE_FATTR_LOCKOWNER;
|
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* ftruncate() sends only va_size, and metadata cache
|
|
|
|
* flush adds va_atime and va_mtime. Some FUSE
|
|
|
|
* filesystems will attempt to detect ftruncate by
|
|
|
|
* checking for FATTR_SIZE being set without
|
|
|
|
* FATTR_UID|FATTR_GID|FATTR_ATIME|FATTR_MTIME|FATTR_MODE
|
|
|
|
*
|
|
|
|
* Try to adapt and remove FATTR_ATIME|FATTR_MTIME
|
|
|
|
* if we suspect a ftruncate().
|
|
|
|
*/
|
|
|
|
if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
|
|
|
|
((vap->va_mode == (mode_t)PUFFS_VNOVAL) &&
|
|
|
|
(vap->va_uid == (uid_t)PUFFS_VNOVAL) &&
|
|
|
|
(vap->va_gid == (gid_t)PUFFS_VNOVAL))) {
|
|
|
|
fsi->atime = 0;
|
|
|
|
fsi->atimensec = 0;
|
|
|
|
fsi->mtime = 0;
|
|
|
|
fsi->mtimensec = 0;
|
|
|
|
fsi->valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If nothing remain, discard the operation.
|
|
|
|
*/
|
|
|
|
if (!(fsi->valid & (FUSE_FATTR_SIZE|FUSE_FATTR_ATIME|FUSE_FATTR_MTIME|
|
|
|
|
FUSE_FATTR_MODE|FUSE_FATTR_UID|FUSE_FATTR_GID))) {
|
|
|
|
error = 0;
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-09-05 10:49:13 +04:00
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
old_vap = puffs_pn_getvap((struct puffs_node *)opc);
|
|
|
|
|
|
|
|
if ((perfuse_diagflags & PDF_RESIZE) &&
|
|
|
|
(old_vap->va_size != (u_quad_t)PUFFS_VNOVAL)) {
|
|
|
|
resize_debug = 1;
|
|
|
|
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF(">> %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
|
|
|
|
(void *)opc,
|
|
|
|
puffs_pn_getvap((struct puffs_node *)opc)->va_size,
|
|
|
|
fsi->size);
|
2011-09-09 19:45:28 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Do not honour FAF when changing size. How do
|
|
|
|
* you want such a thing to work?
|
|
|
|
*/
|
|
|
|
reply = wait_reply;
|
|
|
|
#ifdef PUFFS_SETATTR_FAF
|
|
|
|
if ((xflag & PUFFS_SETATTR_FAF) && !(fsi->valid & FUSE_FATTR_SIZE))
|
|
|
|
reply = no_reply;
|
|
|
|
#endif
|
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*fao), reply)) != 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (reply == no_reply)
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
goto out;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* Copy back the new values
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
|
2011-09-09 19:45:28 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (resize_debug)
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF("<< %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
|
|
|
|
(void *)opc, old_vap->va_size, fao->attr.size);
|
2011-09-09 19:45:28 +04:00
|
|
|
#endif
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
fuse_attr_to_vap(ps, old_va, &fao->attr);
|
2012-04-18 04:57:21 +04:00
|
|
|
|
|
|
|
if (va_ttl != NULL) {
|
|
|
|
va_ttl->tv_sec = fao->attr_valid;
|
|
|
|
va_ttl->tv_nsec = fao->attr_valid_nsec;
|
|
|
|
(void)memcpy(vap, old_va, sizeof(*vap));
|
|
|
|
}
|
2011-10-30 09:11:37 +04:00
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
out:
|
2011-09-09 19:45:28 +04:00
|
|
|
if (pnd->pnd_flags & PND_INRESIZE) {
|
|
|
|
pnd->pnd_flags &= ~PND_INRESIZE;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_RESIZE, DEQUEUE_ALL);
|
2011-09-09 19:45:28 +04:00
|
|
|
}
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out2:
|
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_poll(struct puffs_usermount *pu, puffs_cookie_t opc, int *events)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_poll_in *fpi;
|
|
|
|
struct fuse_poll_out *fpo;
|
|
|
|
int error;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
/*
|
|
|
|
* kh is set if FUSE_POLL_SCHEDULE_NOTIFY is set.
|
2011-08-02 18:53:38 +04:00
|
|
|
*
|
|
|
|
* XXX ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser. We have no way to
|
|
|
|
* know the requesting process' credential, but since poll
|
|
|
|
* is supposed to operate on a file that has been open,
|
|
|
|
* permission should have already been checked at open time.
|
|
|
|
* That still may breaks on filesystems that provides odd
|
|
|
|
* semantics.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_POLL, sizeof(*fpi), NULL);
|
|
|
|
fpi = GET_INPAYLOAD(ps, pm, fuse_poll_in);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fpi->fh = perfuse_get_fh(opc, FREAD);
|
2010-08-25 11:16:00 +04:00
|
|
|
fpi->kh = 0;
|
|
|
|
fpi->flags = 0;
|
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-12-16 09:34:54 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", "
|
|
|
|
"fh = 0x%"PRIx64"\n", __func__, (void *)opc,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_nodeid, fpi->fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, sizeof(*fpo), wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
fpo = GET_OUTPAYLOAD(ps, pm, fuse_poll_out);
|
|
|
|
*events = fpo->revents;
|
2011-12-16 09:34:54 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED2 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
2010-09-09 13:12:35 +04:00
|
|
|
int op;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct perfuse_state *ps;
|
2010-08-26 17:29:01 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_fsync_in *ffi;
|
2010-08-26 17:29:01 +04:00
|
|
|
uint64_t fh;
|
2012-07-21 09:49:42 +04:00
|
|
|
int error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
pm = NULL;
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No need to sync a removed node
|
|
|
|
*/
|
|
|
|
if (pnd->pnd_flags & PND_REMOVED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do not sync closed files. They have been
|
|
|
|
* sync at inactive time already.
|
|
|
|
*/
|
|
|
|
if (!(pnd->pnd_flags & PND_OPEN))
|
|
|
|
return 0;
|
2010-09-09 13:12:35 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2010-09-09 13:12:35 +04:00
|
|
|
if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR)
|
|
|
|
op = FUSE_FSYNCDIR;
|
|
|
|
else /* VREG but also other types such as VLNK */
|
|
|
|
op = FUSE_FSYNC;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
/*
|
|
|
|
* Do not sync if there are no change to sync
|
2010-09-09 13:12:35 +04:00
|
|
|
* XXX remove that test on files if we implement mmap
|
2010-08-26 17:29:01 +04:00
|
|
|
*/
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_SYNC)
|
|
|
|
DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
__func__, (void*)opc, perfuse_node_path(ps, opc),
|
2010-08-26 17:29:01 +04:00
|
|
|
pnd->pnd_flags & PND_DIRTY ? "" : "not ");
|
|
|
|
#endif
|
|
|
|
if (!(pnd->pnd_flags & PND_DIRTY))
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-26 17:29:01 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
/*
|
|
|
|
* It seems NetBSD can call fsync without open first
|
|
|
|
* glusterfs complain in such a situation:
|
|
|
|
* "FSYNC() ERR => -1 (Invalid argument)"
|
|
|
|
* The file will be closed at inactive time.
|
|
|
|
*
|
|
|
|
* We open the directory for reading in order to sync.
|
|
|
|
* This sounds rather counterintuitive, but it works.
|
|
|
|
*/
|
|
|
|
if (!(pnd->pnd_flags & PND_WFH)) {
|
|
|
|
if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
if (op == FUSE_FSYNCDIR)
|
|
|
|
fh = perfuse_get_fh(opc, FREAD);
|
|
|
|
else
|
|
|
|
fh = perfuse_get_fh(opc, FWRITE);
|
2010-08-26 17:29:01 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* If fsync_flags is set, meta data should not be flushed.
|
|
|
|
*/
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, op, sizeof(*ffi), pcr);
|
2010-08-25 11:16:00 +04:00
|
|
|
ffi = GET_INPAYLOAD(ps, pm, fuse_fsync_in);
|
2010-08-26 17:29:01 +04:00
|
|
|
ffi->fh = fh;
|
2010-08-25 11:16:00 +04:00
|
|
|
ffi->fsync_flags = (flags & FFILESYNC) ? 0 : 1;
|
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
|
2010-08-26 17:29:01 +04:00
|
|
|
__func__, (void *)opc,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_nodeid, ffi->fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm,
|
|
|
|
NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
/*
|
2010-08-26 17:29:01 +04:00
|
|
|
* No reply beyond fuse_out_header: nothing to do on success
|
|
|
|
* just clear the dirty flag
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
2010-08-26 17:29:01 +04:00
|
|
|
pnd->pnd_flags &= ~PND_DIRTY;
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_SYNC)
|
|
|
|
DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
__func__, (void*)opc, perfuse_node_path(ps, opc));
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2011-12-16 09:34:54 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
out:
|
2010-09-09 13:12:35 +04:00
|
|
|
/*
|
|
|
|
* ENOSYS is not returned to kernel,
|
|
|
|
*/
|
2010-08-25 11:16:00 +04:00
|
|
|
if (error == ENOSYS)
|
2010-09-09 13:12:35 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
puffs_cookie_t targ, const struct puffs_cn *pcn)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
perfuse_msg_t *pm;
|
2010-08-25 11:16:00 +04:00
|
|
|
char *path;
|
|
|
|
const char *name;
|
|
|
|
size_t len;
|
|
|
|
int error;
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if ((pnd->pnd_flags & PND_REMOVED) ||
|
|
|
|
(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_REMOVED))
|
|
|
|
return ENOENT;
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
2010-08-25 11:16:00 +04:00
|
|
|
if (targ == NULL)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__);
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
|
|
|
|
DPRINTF("%s: opc = %p, remove opc = %p, file = \"%s\"\n",
|
2010-09-29 12:01:10 +04:00
|
|
|
__func__, (void *)opc, (void *)targ, pcn->pcn_name);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
node_ref(targ);
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
/*
|
2010-09-29 12:01:10 +04:00
|
|
|
* Await for all operations on the deleted node to drain,
|
|
|
|
* as the filesystem may be confused to have it deleted
|
|
|
|
* during a getattr
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
while (PERFUSE_NODE_DATA(targ)->pnd_inxchg)
|
2010-09-29 12:01:10 +04:00
|
|
|
requeue_request(pu, targ, PCQ_AFTERXCHG);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
name = pcn->pcn_name;
|
|
|
|
len = pcn->pcn_namelen + 1;
|
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
path = _GET_INPAYLOAD(ps, pm, char *);
|
|
|
|
(void)strlcpy(path, name, len);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_cache_flush(targ);
|
2010-09-29 12:01:10 +04:00
|
|
|
PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
|
2012-07-21 09:49:42 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN))
|
|
|
|
puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
|
2010-09-09 13:12:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The parent directory needs a sync
|
|
|
|
*/
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: remove nodeid = 0x%"PRIx64" file = \"%s\"\n",
|
|
|
|
__func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid,
|
2010-09-29 12:01:10 +04:00
|
|
|
pcn->pcn_name);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
node_rele(targ);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_link(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
puffs_cookie_t targ, const struct puffs_cn *pcn)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
const char *name;
|
|
|
|
size_t len;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct fuse_link_in *fli;
|
|
|
|
int error;
|
2010-09-29 12:01:10 +04:00
|
|
|
|
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
node_ref(targ);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
pn = (struct puffs_node *)targ;
|
2010-09-29 12:01:10 +04:00
|
|
|
name = pcn->pcn_name;
|
|
|
|
len = sizeof(*fli) + pcn->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_LINK, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
fli = GET_INPAYLOAD(ps, pm, fuse_link_in);
|
2011-10-30 09:11:37 +04:00
|
|
|
fli->oldnodeid = PERFUSE_NODE_DATA(pn)->pnd_nodeid;
|
2010-08-25 11:16:00 +04:00
|
|
|
(void)strlcpy((char *)(void *)(fli + 1), name, len - sizeof(*fli));
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
node_rele(targ);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
puffs_cookie_t src, const struct puffs_cn *pcn_src,
|
|
|
|
puffs_cookie_t targ_dir, puffs_cookie_t targ,
|
|
|
|
const struct puffs_cn *pcn_targ)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
2012-07-21 09:49:42 +04:00
|
|
|
struct perfuse_node_data *dstdir_pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_rename_in *fri;
|
|
|
|
const char *newname;
|
|
|
|
const char *oldname;
|
|
|
|
char *np;
|
|
|
|
int error;
|
|
|
|
size_t len;
|
|
|
|
size_t newname_len;
|
|
|
|
size_t oldname_len;
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if ((PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED) ||
|
|
|
|
(PERFUSE_NODE_DATA(src)->pnd_flags & PND_REMOVED) ||
|
|
|
|
(PERFUSE_NODE_DATA(targ_dir)->pnd_flags & PND_REMOVED))
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
node_ref(src);
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
/*
|
|
|
|
* Await for all operations on the deleted node to drain,
|
|
|
|
* as the filesystem may be confused to have it deleted
|
|
|
|
* during a getattr
|
|
|
|
*/
|
|
|
|
if ((struct puffs_node *)targ != NULL) {
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(targ);
|
|
|
|
while (PERFUSE_NODE_DATA(targ)->pnd_inxchg)
|
2010-09-29 12:01:10 +04:00
|
|
|
requeue_request(pu, targ, PCQ_AFTERXCHG);
|
|
|
|
} else {
|
2012-07-21 09:49:42 +04:00
|
|
|
while (PERFUSE_NODE_DATA(src)->pnd_inxchg)
|
2010-09-29 12:01:10 +04:00
|
|
|
requeue_request(pu, src, PCQ_AFTERXCHG);
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-29 12:01:10 +04:00
|
|
|
newname = pcn_targ->pcn_name;
|
|
|
|
newname_len = pcn_targ->pcn_namelen + 1;
|
|
|
|
oldname = pcn_src->pcn_name;
|
|
|
|
oldname_len = pcn_src->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
len = sizeof(*fri) + oldname_len + newname_len;
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_RENAME, len, pcn_targ->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
fri = GET_INPAYLOAD(ps, pm, fuse_rename_in);
|
2011-10-30 09:11:37 +04:00
|
|
|
fri->newdir = PERFUSE_NODE_DATA(targ_dir)->pnd_nodeid;
|
2010-08-25 11:16:00 +04:00
|
|
|
np = (char *)(void *)(fri + 1);
|
|
|
|
(void)strlcpy(np, oldname, oldname_len);
|
|
|
|
np += oldname_len;
|
|
|
|
(void)strlcpy(np, newname, newname_len);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Record new parent nodeid
|
|
|
|
*/
|
|
|
|
dstdir_pnd = PERFUSE_NODE_DATA(targ_dir);
|
|
|
|
PERFUSE_NODE_DATA(src)->pnd_parent_nodeid = dstdir_pnd->pnd_nodeid;
|
2010-09-29 12:01:10 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (opc != targ_dir)
|
|
|
|
dstdir_pnd->pnd_flags |= PND_DIRTY;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if (strcmp(newname, "..") != 0)
|
|
|
|
(void)strlcpy(PERFUSE_NODE_DATA(src)->pnd_name,
|
|
|
|
newname, MAXPATHLEN);
|
|
|
|
else
|
|
|
|
PERFUSE_NODE_DATA(src)->pnd_name[0] = 0; /* forget name */
|
2010-10-03 09:46:47 +04:00
|
|
|
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((struct puffs_node *)targ != NULL) {
|
|
|
|
perfuse_cache_flush(targ);
|
2010-10-03 09:46:47 +04:00
|
|
|
PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
|
2012-07-21 09:49:42 +04:00
|
|
|
}
|
2010-10-03 09:46:47 +04:00
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: nodeid = 0x%"PRIx64" file = \"%s\" renamed \"%s\" "
|
|
|
|
"nodeid = 0x%"PRIx64" -> nodeid = 0x%"PRIx64" \"%s\"\n",
|
|
|
|
__func__, PERFUSE_NODE_DATA(src)->pnd_nodeid,
|
2010-10-03 09:46:47 +04:00
|
|
|
pcn_src->pcn_name, pcn_targ->pcn_name,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_nodeid,
|
|
|
|
PERFUSE_NODE_DATA(targ_dir)->pnd_nodeid,
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_path(ps, targ_dir));
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
node_rele(src);
|
|
|
|
if ((struct puffs_node *)targ != NULL)
|
|
|
|
node_rele(targ);
|
|
|
|
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
|
|
|
|
const struct vattr *vap)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_mkdir_in *fmi;
|
|
|
|
const char *path;
|
|
|
|
size_t len;
|
2012-07-21 09:49:42 +04:00
|
|
|
int error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-29 12:01:10 +04:00
|
|
|
path = pcn->pcn_name;
|
|
|
|
len = sizeof(*fmi) + pcn->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_MKDIR, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
fmi = GET_INPAYLOAD(ps, pm, fuse_mkdir_in);
|
2010-09-05 10:49:13 +04:00
|
|
|
fmi->mode = vap->va_mode;
|
|
|
|
fmi->umask = 0; /* Seems unused by libfuse? */
|
2010-08-25 11:16:00 +04:00
|
|
|
(void)strlcpy((char *)(void *)(fmi + 1), path, len - sizeof(*fmi));
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
error = node_mk_common(pu, opc, pni, pcn, pm);
|
|
|
|
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
puffs_cookie_t targ, const struct puffs_cn *pcn)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
char *path;
|
|
|
|
const char *name;
|
|
|
|
size_t len;
|
|
|
|
int error;
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
2011-11-28 09:33:33 +04:00
|
|
|
|
|
|
|
if ((pnd->pnd_flags & PND_REMOVED) ||
|
|
|
|
(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_REMOVED))
|
2010-09-29 12:01:10 +04:00
|
|
|
return ENOENT;
|
|
|
|
|
2014-09-05 19:20:16 +04:00
|
|
|
/*
|
|
|
|
* Attempt to rmdir dir/.. shoud raise ENOTEMPTY
|
|
|
|
*/
|
|
|
|
if (PERFUSE_NODE_DATA(targ)->pnd_nodeid == pnd->pnd_parent_nodeid)
|
|
|
|
return ENOTEMPTY;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
node_ref(targ);
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
/*
|
2010-09-29 12:01:10 +04:00
|
|
|
* Await for all operations on the deleted node to drain,
|
|
|
|
* as the filesystem may be confused to have it deleted
|
|
|
|
* during a getattr
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
while (PERFUSE_NODE_DATA(targ)->pnd_inxchg)
|
2010-09-29 12:01:10 +04:00
|
|
|
requeue_request(pu, targ, PCQ_AFTERXCHG);
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
name = pcn->pcn_name;
|
|
|
|
len = pcn->pcn_namelen + 1;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
path = _GET_INPAYLOAD(ps, pm, char *);
|
|
|
|
(void)strlcpy(path, name, len);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_cache_flush(targ);
|
2010-09-29 12:01:10 +04:00
|
|
|
PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
|
2012-07-21 09:49:42 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN))
|
|
|
|
puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
|
2010-08-26 17:29:01 +04:00
|
|
|
|
2010-09-09 13:12:35 +04:00
|
|
|
/*
|
|
|
|
* The parent directory needs a sync
|
|
|
|
*/
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FILENAME)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: remove nodeid = 0x%"PRIx64" file = \"%s\"\n",
|
|
|
|
__func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid,
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_path(ps, targ));
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
#endif
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
node_rele(targ);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vap is unused */
|
|
|
|
/* ARGSUSED4 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct puffs_newinfo *pni, const struct puffs_cn *pcn_src,
|
|
|
|
const struct vattr *vap, const char *link_target)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
char *np;
|
|
|
|
const char *path;
|
|
|
|
size_t path_len;
|
|
|
|
size_t linkname_len;
|
|
|
|
size_t len;
|
2012-07-21 09:49:42 +04:00
|
|
|
int error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2010-09-29 12:01:10 +04:00
|
|
|
path = pcn_src->pcn_name;
|
|
|
|
path_len = pcn_src->pcn_namelen + 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
linkname_len = strlen(link_target) + 1;
|
|
|
|
len = path_len + linkname_len;
|
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_SYMLINK, len, pcn_src->pcn_cred);
|
2010-08-25 11:16:00 +04:00
|
|
|
np = _GET_INPAYLOAD(ps, pm, char *);
|
|
|
|
(void)strlcpy(np, path, path_len);
|
|
|
|
np += path_len;
|
|
|
|
(void)strlcpy(np, link_target, linkname_len);
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
error = node_mk_common(pu, opc, pni, pcn_src, pm);
|
|
|
|
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
2011-07-14 19:37:32 +04:00
|
|
|
/* ARGSUSED4 */
|
2010-08-25 11:16:00 +04:00
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
struct dirent *dent, off_t *readoff, size_t *reslen,
|
|
|
|
const struct puffs_cred *pcr, int *eofflag, off_t *cookies,
|
|
|
|
size_t *ncookies)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
uint64_t fh;
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
struct perfuse_node_data *pnd;
|
|
|
|
struct fuse_read_in *fri;
|
|
|
|
struct fuse_out_header *foh;
|
|
|
|
struct fuse_dirent *fd;
|
|
|
|
size_t foh_len;
|
|
|
|
int error;
|
2010-09-20 11:00:21 +04:00
|
|
|
size_t fd_maxlen;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
error = 0;
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* readdir state is kept at node level, and several readdir
|
|
|
|
* requests can be issued at the same time on the same node.
|
|
|
|
* We need to queue requests so that only one is in readdir
|
|
|
|
* code at the same time.
|
|
|
|
*/
|
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
while (pnd->pnd_flags & PND_INREADDIR)
|
|
|
|
requeue_request(pu, opc, PCQ_READDIR);
|
|
|
|
pnd->pnd_flags |= PND_INREADDIR;
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_READDIR)
|
|
|
|
DPRINTF("%s: READDIR opc = %p enter critical section\n",
|
|
|
|
__func__, (void *)opc);
|
|
|
|
#endif
|
2011-07-14 19:37:32 +04:00
|
|
|
/*
|
|
|
|
* Re-initialize pnd->pnd_fd_cookie on the first readdir for a node
|
|
|
|
*/
|
|
|
|
if (*readoff == 0)
|
|
|
|
pnd->pnd_fd_cookie = 0;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* Do we already have the data bufered?
|
|
|
|
*/
|
|
|
|
if (pnd->pnd_dirent != NULL)
|
|
|
|
goto out;
|
|
|
|
pnd->pnd_dirent_len = 0;
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
/*
|
|
|
|
* It seems NetBSD can call readdir without open first
|
|
|
|
* libfuse will crash if it is done that way, hence open first.
|
|
|
|
*/
|
|
|
|
if (!(pnd->pnd_flags & PND_OPEN)) {
|
|
|
|
if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fh = perfuse_get_fh(opc, FREAD);
|
2010-08-26 17:29:01 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-12-16 09:34:54 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", "
|
|
|
|
"rfh = 0x%"PRIx64"\n", __func__, (void *)opc,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_nodeid, fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
pnd->pnd_all_fd = NULL;
|
|
|
|
pnd->pnd_all_fd_len = 0;
|
2010-09-20 11:00:21 +04:00
|
|
|
fd_maxlen = ps->ps_max_readahead - sizeof(*foh);
|
2011-07-14 19:37:32 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
do {
|
|
|
|
size_t fd_len;
|
|
|
|
char *afdp;
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_READDIR, sizeof(*fri), pcr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* read_flags, lock_owner and flags are unused in libfuse
|
|
|
|
*/
|
|
|
|
fri = GET_INPAYLOAD(ps, pm, fuse_read_in);
|
|
|
|
fri->fh = fh;
|
2011-07-14 19:37:32 +04:00
|
|
|
fri->offset = pnd->pnd_fd_cookie;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
fri->size = (uint32_t)fd_maxlen;
|
2010-08-25 11:16:00 +04:00
|
|
|
fri->read_flags = 0;
|
|
|
|
fri->lock_owner = 0;
|
|
|
|
fri->flags = 0;
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm,
|
|
|
|
UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There are many puffs_framebufs calls later,
|
|
|
|
* therefore foh will not be valid for a long time.
|
|
|
|
* Just get the length and forget it.
|
|
|
|
*/
|
|
|
|
foh = GET_OUTHDR(ps, pm);
|
|
|
|
foh_len = foh->len;
|
|
|
|
|
|
|
|
/*
|
2010-09-20 11:00:21 +04:00
|
|
|
* Empty read: we reached the end of the buffer.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
2011-07-14 19:37:32 +04:00
|
|
|
if (foh_len == sizeof(*foh)) {
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2011-07-14 19:37:32 +04:00
|
|
|
*eofflag = 1;
|
2010-08-25 11:16:00 +04:00
|
|
|
break;
|
2011-07-14 19:37:32 +04:00
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
2011-07-14 19:37:32 +04:00
|
|
|
* Check for corrupted message.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
|
|
|
if (foh_len < sizeof(*foh) + sizeof(*fd)) {
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2010-08-25 11:16:00 +04:00
|
|
|
DWARNX("readdir reply too short");
|
|
|
|
error = EIO;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fd = GET_OUTPAYLOAD(ps, pm, fuse_dirent);
|
|
|
|
fd_len = foh_len - sizeof(*foh);
|
|
|
|
|
|
|
|
pnd->pnd_all_fd = realloc(pnd->pnd_all_fd,
|
|
|
|
pnd->pnd_all_fd_len + fd_len);
|
|
|
|
if (pnd->pnd_all_fd == NULL)
|
2011-08-14 03:12:15 +04:00
|
|
|
DERR(EX_OSERR, "%s: malloc failed", __func__);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
afdp = (char *)(void *)pnd->pnd_all_fd + pnd->pnd_all_fd_len;
|
|
|
|
(void)memcpy(afdp, fd, fd_len);
|
|
|
|
|
|
|
|
pnd->pnd_all_fd_len += fd_len;
|
2011-07-14 19:37:32 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The fd->off field is used as a cookie for
|
|
|
|
* resuming the next readdir() where this one was left.
|
|
|
|
*/
|
|
|
|
pnd->pnd_fd_cookie = readdir_last_cookie(fd, fd_len);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
2011-07-14 19:37:32 +04:00
|
|
|
} while (1 /* CONSTCOND */);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2011-07-14 19:37:32 +04:00
|
|
|
if (pnd->pnd_all_fd != NULL) {
|
|
|
|
if (fuse_to_dirent(pu, opc, pnd->pnd_all_fd,
|
|
|
|
pnd->pnd_all_fd_len) == -1)
|
|
|
|
error = EIO;
|
|
|
|
}
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
out:
|
|
|
|
if (pnd->pnd_all_fd != NULL) {
|
|
|
|
free(pnd->pnd_all_fd);
|
|
|
|
pnd->pnd_all_fd = NULL;
|
|
|
|
pnd->pnd_all_fd_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error == 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
readdir_buffered(opc, dent, readoff, reslen);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Schedule queued readdir requests
|
|
|
|
*/
|
|
|
|
pnd->pnd_flags &= ~PND_INREADDIR;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_READDIR, DEQUEUE_ALL);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_READDIR)
|
|
|
|
DPRINTF("%s: READDIR opc = %p exit critical section\n",
|
|
|
|
__func__, (void *)opc);
|
|
|
|
#endif
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
const struct puffs_cred *pcr, char *linkname, size_t *linklen)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
int error;
|
|
|
|
size_t len;
|
|
|
|
struct fuse_out_header *foh;
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
|
|
|
|
return ENOENT;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_READLINK, 0, pcr);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
foh = GET_OUTHDR(ps, pm);
|
2010-10-11 05:52:05 +04:00
|
|
|
len = foh->len - sizeof(*foh);
|
2010-08-25 11:16:00 +04:00
|
|
|
if (len > *linklen)
|
2010-09-01 18:57:24 +04:00
|
|
|
DERRX(EX_PROTOCOL, "path len = %zd too long", len);
|
2010-10-11 05:52:05 +04:00
|
|
|
if (len == 0)
|
|
|
|
DERRX(EX_PROTOCOL, "path len = %zd too short", len);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2014-08-29 08:58:40 +04:00
|
|
|
(void)memcpy(linkname, _GET_OUTPAYLOAD(ps, pm, char *), len);
|
|
|
|
|
2010-10-11 05:52:05 +04:00
|
|
|
/*
|
|
|
|
* FUSE filesystems return a NUL terminated string, we
|
2014-08-29 08:58:40 +04:00
|
|
|
* do not want the trailing \0
|
2010-10-11 05:52:05 +04:00
|
|
|
*/
|
2014-08-29 08:58:40 +04:00
|
|
|
while (len > 0 && linkname[len - 1] == '\0')
|
|
|
|
len--;
|
|
|
|
|
|
|
|
*linklen = len;
|
2011-12-16 09:34:54 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
2010-08-26 17:29:01 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_forget_in *ffi;
|
2012-07-21 09:49:42 +04:00
|
|
|
int nlookup;
|
|
|
|
struct timespec now;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
if (opc == 0)
|
|
|
|
return 0;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
2010-08-26 17:29:01 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Never forget the root.
|
|
|
|
*/
|
2011-10-30 09:11:37 +04:00
|
|
|
if (pnd->pnd_nodeid == FUSE_ROOT_ID)
|
2010-08-25 11:16:00 +04:00
|
|
|
return 0;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* There is a race condition between reclaim and lookup.
|
|
|
|
* When looking up an already known node, the kernel cannot
|
|
|
|
* hold a reference on the result until it gets the PUFFS
|
|
|
|
* reply. It mayy therefore reclaim the node after the
|
|
|
|
* userland looked it up, and before it gets the reply.
|
|
|
|
* On rely, the kernel re-creates the node, but at that
|
|
|
|
* time the node has been reclaimed in userland.
|
|
|
|
*
|
|
|
|
* In order to avoid this, we refuse reclaiming nodes that
|
|
|
|
* are too young since the last lookup - and that we do
|
|
|
|
* not have removed on our own, of course.
|
|
|
|
*/
|
|
|
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
|
|
|
DERR(EX_OSERR, "clock_gettime failed");
|
|
|
|
|
|
|
|
if (timespeccmp(&pnd->pnd_cn_expire, &now, >) &&
|
|
|
|
!(pnd->pnd_flags & PND_REMOVED)) {
|
|
|
|
if (!(pnd->pnd_flags & PND_NODELEAK)) {
|
|
|
|
ps->ps_nodeleakcount++;
|
|
|
|
pnd->pnd_flags |= PND_NODELEAK;
|
|
|
|
}
|
|
|
|
DWARNX("possible leaked node:: opc = %p \"%s\"",
|
|
|
|
opc, pnd->pnd_name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
node_ref(opc);
|
2010-08-26 17:29:01 +04:00
|
|
|
pnd->pnd_flags |= PND_RECLAIMED;
|
2012-03-08 18:58:57 +04:00
|
|
|
pnd->pnd_puffs_nlookup--;
|
2012-07-21 09:49:42 +04:00
|
|
|
nlookup = pnd->pnd_puffs_nlookup;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RECLAIM)
|
2010-09-01 18:57:24 +04:00
|
|
|
DPRINTF("%s (nodeid %"PRId64") reclaimed\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_path(ps, opc), pnd->pnd_nodeid);
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RECLAIM)
|
2012-03-08 18:58:57 +04:00
|
|
|
DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, nlookup = %d "
|
2012-07-21 09:49:42 +04:00
|
|
|
"%s%s%s%s, pending ops:%s%s%s\n",
|
|
|
|
perfuse_node_path(ps, opc), pnd->pnd_nodeid,
|
2010-08-26 17:29:01 +04:00
|
|
|
pnd->pnd_flags & PND_RECLAIMED ? "" : "not ",
|
2012-07-21 09:49:42 +04:00
|
|
|
pnd->pnd_puffs_nlookup,
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd->pnd_flags & PND_OPEN ? "open " : "not open",
|
|
|
|
pnd->pnd_flags & PND_RFH ? "r" : "",
|
|
|
|
pnd->pnd_flags & PND_WFH ? "w" : "",
|
2010-09-15 05:51:43 +04:00
|
|
|
pnd->pnd_flags & PND_BUSY ? "" : " none",
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd->pnd_flags & PND_INREADDIR ? " readdir" : "",
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
pnd->pnd_flags & PND_INWRITE ? " write" : "",
|
|
|
|
pnd->pnd_flags & PND_INOPEN ? " open" : "");
|
2010-08-25 11:16:00 +04:00
|
|
|
#endif
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Make sure it is not looked up again
|
|
|
|
*/
|
|
|
|
if (!(pnd->pnd_flags & PND_REMOVED))
|
|
|
|
perfuse_cache_flush(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Purge any activity on the node, while checking
|
|
|
|
* that it remains eligible for a reclaim.
|
|
|
|
*/
|
|
|
|
while (pnd->pnd_ref > 1)
|
|
|
|
requeue_request(pu, opc, PCQ_REF);
|
2012-04-08 19:13:06 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* reclaim cancel?
|
|
|
|
*/
|
|
|
|
if (pnd->pnd_puffs_nlookup > nlookup) {
|
|
|
|
pnd->pnd_flags &= ~PND_RECLAIMED;
|
|
|
|
perfuse_node_cache(ps, opc);
|
|
|
|
node_rele(opc);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-08-26 17:29:01 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if ((pnd->pnd_flags & PND_OPEN) ||
|
|
|
|
!TAILQ_EMPTY(&pnd->pnd_pcq))
|
2013-07-18 13:01:20 +04:00
|
|
|
DERRX(EX_SOFTWARE, "%s: opc = %p \"%s\": still open",
|
|
|
|
__func__, opc, pnd->pnd_name);
|
2012-07-21 09:49:42 +04:00
|
|
|
|
|
|
|
if ((pnd->pnd_flags & PND_BUSY) ||
|
|
|
|
!TAILQ_EMPTY(&pnd->pnd_pcq))
|
|
|
|
DERRX(EX_SOFTWARE, "%s: opc = %p: queued operations",
|
|
|
|
__func__, opc);
|
|
|
|
|
|
|
|
if (pnd->pnd_inxchg != 0)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: opc = %p: ongoing operations",
|
|
|
|
__func__, opc);
|
|
|
|
#endif
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* Send the FORGET message
|
|
|
|
*
|
|
|
|
* ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser. This is obviously
|
|
|
|
* fine since we operate with kernel creds here.
|
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_FORGET,
|
|
|
|
sizeof(*ffi), NULL);
|
|
|
|
ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in);
|
|
|
|
ffi->nlookup = pnd->pnd_fuse_nlookup;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* No reply is expected, pm is freed in xchg_msg
|
|
|
|
*/
|
|
|
|
(void)xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, no_reply);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_destroy_pn(pu, opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2012-04-08 19:13:06 +04:00
|
|
|
int error;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2012-04-18 04:57:21 +04:00
|
|
|
if (opc == 0)
|
|
|
|
return 0;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
if (!(pnd->pnd_flags & (PND_OPEN|PND_REMOVED)))
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure all operation are finished
|
|
|
|
* There can be an ongoing write. Other
|
2010-09-29 12:01:10 +04:00
|
|
|
* operation wait for all data before
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
* the close/inactive.
|
|
|
|
*/
|
|
|
|
while (pnd->pnd_flags & PND_INWRITE)
|
|
|
|
requeue_request(pu, opc, PCQ_AFTERWRITE);
|
|
|
|
|
|
|
|
/*
|
2012-04-08 19:13:06 +04:00
|
|
|
* The inactive operation may be cancelled,
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
* If no open is in progress, set PND_INOPEN
|
|
|
|
* so that a new open will be queued.
|
|
|
|
*/
|
2012-04-08 19:13:06 +04:00
|
|
|
if (pnd->pnd_flags & PND_INOPEN)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
pnd->pnd_flags |= PND_INOPEN;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sync data
|
|
|
|
*/
|
2012-04-08 19:13:06 +04:00
|
|
|
if (pnd->pnd_flags & PND_DIRTY) {
|
|
|
|
if ((error = perfuse_node_fsync(pu, opc, NULL, 0, 0, 0)) != 0)
|
|
|
|
DWARN("%s: perfuse_node_fsync failed error = %d",
|
|
|
|
__func__, error);
|
|
|
|
}
|
|
|
|
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Close handles
|
|
|
|
*/
|
2012-04-08 19:13:06 +04:00
|
|
|
if (pnd->pnd_flags & PND_WFH) {
|
|
|
|
if ((error = perfuse_node_close_common(pu, opc, FWRITE)) != 0)
|
|
|
|
DWARN("%s: close write FH failed error = %d",
|
|
|
|
__func__, error);
|
|
|
|
}
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2012-04-08 19:13:06 +04:00
|
|
|
if (pnd->pnd_flags & PND_RFH) {
|
|
|
|
if ((error = perfuse_node_close_common(pu, opc, FREAD)) != 0)
|
|
|
|
DWARN("%s: close read FH failed error = %d",
|
|
|
|
__func__, error);
|
|
|
|
}
|
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.
- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,
- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls
== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync
- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename
== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file
- set FH in getattr, if the file is open
- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)
== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time
- short circuit nilpotent operations in setattr
- add a filename diagnostic flag to dump file names
2010-09-23 20:02:34 +04:00
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
/*
|
|
|
|
* This will cause a reclaim to be sent
|
|
|
|
*/
|
2010-09-29 12:01:10 +04:00
|
|
|
if (pnd->pnd_flags & PND_REMOVED)
|
|
|
|
puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1);
|
|
|
|
|
2010-10-03 09:46:47 +04:00
|
|
|
/*
|
|
|
|
* Schedule awaiting operations
|
|
|
|
*/
|
|
|
|
pnd->pnd_flags &= ~PND_INOPEN;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_OPEN, DEQUEUE_ALL);
|
2010-10-03 09:46:47 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* errors are ignored, since the kernel ignores the return code.
|
|
|
|
*/
|
|
|
|
out:
|
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_print(struct puffs_usermount *pu, puffs_cookie_t opc)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc,
|
2014-09-04 03:59:58 +04:00
|
|
|
int name, register_t *retval)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
2014-09-03 20:01:45 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
struct fuse_statfs_out *fso;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Static values copied from UFS
|
|
|
|
* in src/sys/ufs/ufs/ufs_vnops.c
|
|
|
|
*/
|
|
|
|
switch (name) {
|
|
|
|
case _PC_LINK_MAX:
|
|
|
|
*retval = LINK_MAX;
|
|
|
|
break;
|
|
|
|
case _PC_PATH_MAX:
|
|
|
|
*retval = PATH_MAX;
|
|
|
|
break;
|
|
|
|
case _PC_PIPE_BUF:
|
|
|
|
*retval = PIPE_BUF;
|
|
|
|
break;
|
|
|
|
case _PC_CHOWN_RESTRICTED:
|
|
|
|
*retval = 1;
|
|
|
|
break;
|
|
|
|
case _PC_NO_TRUNC:
|
|
|
|
*retval = 1;
|
|
|
|
break;
|
|
|
|
case _PC_SYNC_IO:
|
|
|
|
*retval = 1;
|
|
|
|
break;
|
|
|
|
case _PC_FILESIZEBITS:
|
|
|
|
*retval = 42;
|
|
|
|
break;
|
|
|
|
case _PC_SYMLINK_MAX:
|
|
|
|
*retval = MAXPATHLEN;
|
|
|
|
break;
|
|
|
|
case _PC_2_SYMLINKS:
|
|
|
|
*retval = 1;
|
|
|
|
break;
|
|
|
|
case _PC_NAME_MAX:
|
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL);
|
|
|
|
|
|
|
|
error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply);
|
|
|
|
if (error != 0)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out);
|
|
|
|
*retval = fso->st.namelen;
|
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DWARN("Unimplemented pathconf for name = %d", name);
|
|
|
|
error = ENOSYS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_advlock(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
void *id, int op, struct flock *fl, int flags)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
int fop;
|
|
|
|
perfuse_msg_t *pm;
|
2011-11-16 08:52:40 +04:00
|
|
|
uint64_t fh;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_lk_in *fli;
|
2011-05-03 17:19:50 +04:00
|
|
|
struct fuse_out_header *foh;
|
2010-08-25 11:16:00 +04:00
|
|
|
struct fuse_lk_out *flo;
|
2011-05-03 17:19:50 +04:00
|
|
|
uint32_t owner;
|
|
|
|
size_t len;
|
2010-08-25 11:16:00 +04:00
|
|
|
int error;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2011-11-16 08:52:40 +04:00
|
|
|
/*
|
|
|
|
* Make sure we do have a filehandle, as the FUSE filesystem
|
|
|
|
* expect one. E.g.: if we provide none, GlusterFS logs an error
|
|
|
|
* "0-glusterfs-fuse: xl is NULL"
|
|
|
|
*
|
|
|
|
* We need the read file handle if the file is open read only,
|
|
|
|
* in order to support shared locks on read-only files.
|
|
|
|
* NB: The kernel always sends advlock for read-only
|
|
|
|
* files at exit time when the process used lock, see
|
|
|
|
* sys_exit -> exit1 -> fd_free -> fd_close -> VOP_ADVLOCK
|
|
|
|
*/
|
2012-07-21 09:49:42 +04:00
|
|
|
if ((fh = perfuse_get_fh(opc, FREAD)) == FUSE_UNKNOWN_FH) {
|
|
|
|
error = EBADF;
|
|
|
|
goto out;
|
|
|
|
}
|
2011-11-16 08:52:40 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
|
|
|
|
if (op == F_GETLK)
|
|
|
|
fop = FUSE_GETLK;
|
|
|
|
else
|
|
|
|
fop = (flags & F_WAIT) ? FUSE_SETLKW : FUSE_SETLK;
|
|
|
|
|
2011-08-02 18:53:38 +04:00
|
|
|
/*
|
|
|
|
* XXX ps_new_msg() is called with NULL creds, which will
|
|
|
|
* be interpreted as FUSE superuser. We have no way to
|
|
|
|
* know the requesting process' credential, but since advlock()
|
|
|
|
* is supposed to operate on a file that has been open(),
|
|
|
|
* permission should have already been checked at open() time.
|
|
|
|
*/
|
2010-08-25 11:16:00 +04:00
|
|
|
pm = ps->ps_new_msg(pu, opc, fop, sizeof(*fli), NULL);
|
|
|
|
fli = GET_INPAYLOAD(ps, pm, fuse_lk_in);
|
2011-11-16 08:52:40 +04:00
|
|
|
fli->fh = fh;
|
|
|
|
fli->owner = (uint64_t)(vaddr_t)id;
|
2010-08-25 11:16:00 +04:00
|
|
|
fli->lk.start = fl->l_start;
|
|
|
|
fli->lk.end = fl->l_start + fl->l_len;
|
|
|
|
fli->lk.type = fl->l_type;
|
|
|
|
fli->lk.pid = fl->l_pid;
|
|
|
|
fli->lk_flags = (flags & F_FLOCK) ? FUSE_LK_FLOCK : 0;
|
|
|
|
|
2011-11-28 09:33:33 +04:00
|
|
|
owner = (uint32_t)(vaddr_t)id;
|
2011-05-03 17:19:50 +04:00
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
|
2010-08-26 17:29:01 +04:00
|
|
|
__func__, (void *)opc,
|
2011-10-30 09:11:37 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_nodeid, fli->fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
|
|
|
|
2011-05-03 17:19:50 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-05-03 17:19:50 +04:00
|
|
|
foh = GET_OUTHDR(ps, pm);
|
|
|
|
len = foh->len - sizeof(*foh);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Save or clear the lock
|
|
|
|
*/
|
|
|
|
switch (op) {
|
2011-05-03 17:19:50 +04:00
|
|
|
case F_GETLK:
|
|
|
|
if (len != sizeof(*flo))
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"%s: Unexpected lock reply len %zd",
|
|
|
|
__func__, len);
|
|
|
|
|
|
|
|
flo = GET_OUTPAYLOAD(ps, pm, fuse_lk_out);
|
|
|
|
fl->l_start = flo->lk.start;
|
|
|
|
fl->l_len = flo->lk.end - flo->lk.start;
|
|
|
|
fl->l_pid = flo->lk.pid;
|
|
|
|
fl->l_type = flo->lk.type;
|
|
|
|
fl->l_whence = SEEK_SET; /* libfuse hardcodes it */
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_lock_owner = flo->lk.pid;
|
|
|
|
break;
|
|
|
|
case F_UNLCK:
|
2011-05-03 17:19:50 +04:00
|
|
|
owner = 0;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case F_SETLK:
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case F_SETLKW:
|
|
|
|
if (error != 0)
|
|
|
|
PERFUSE_NODE_DATA(opc)->pnd_lock_owner = owner;
|
|
|
|
|
|
|
|
if (len != 0)
|
|
|
|
DERRX(EX_SOFTWARE,
|
|
|
|
"%s: Unexpected unlock reply len %zd",
|
|
|
|
__func__, len);
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
break;
|
|
|
|
default:
|
2011-05-03 17:19:50 +04:00
|
|
|
DERRX(EX_SOFTWARE, "%s: Unexpected op %d", __func__, op);
|
2010-08-25 11:16:00 +04:00
|
|
|
break;
|
|
|
|
}
|
2011-12-16 09:34:54 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, uint8_t *buf,
|
|
|
|
off_t offset, size_t *resid, const struct puffs_cred *pcr, int ioflag)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
2011-09-09 19:45:28 +04:00
|
|
|
const struct vattr *vap;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_read_in *fri;
|
|
|
|
struct fuse_out_header *foh;
|
|
|
|
size_t readen;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
2011-09-09 19:45:28 +04:00
|
|
|
vap = puffs_pn_getvap((struct puffs_node *)opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-11-10 20:21:09 +04:00
|
|
|
/*
|
|
|
|
* NetBSD turns that into a getdents(2) output
|
|
|
|
* We just do a EISDIR as this feature is of little use.
|
|
|
|
*/
|
|
|
|
if (vap->va_type == VDIR)
|
|
|
|
return EISDIR;
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
do {
|
2010-09-20 11:00:21 +04:00
|
|
|
size_t max_read;
|
|
|
|
|
|
|
|
max_read = ps->ps_max_readahead - sizeof(*foh);
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
|
|
|
* flags may be set to FUSE_READ_LOCKOWNER
|
|
|
|
* if lock_owner is provided.
|
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_READ, sizeof(*fri), pcr);
|
|
|
|
fri = GET_INPAYLOAD(ps, pm, fuse_read_in);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fri->fh = perfuse_get_fh(opc, FREAD);
|
2010-08-25 11:16:00 +04:00
|
|
|
fri->offset = offset;
|
2010-09-20 11:00:21 +04:00
|
|
|
fri->size = (uint32_t)MIN(*resid, max_read);
|
2010-08-25 11:16:00 +04:00
|
|
|
fri->read_flags = 0; /* XXX Unused by libfuse? */
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fri->lock_owner = pnd->pnd_lock_owner;
|
2010-08-25 11:16:00 +04:00
|
|
|
fri->flags = 0;
|
|
|
|
fri->flags |= (fri->lock_owner != 0) ? FUSE_READ_LOCKOWNER : 0;
|
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
|
|
|
|
__func__, (void *)opc, pnd->pnd_nodeid, fri->fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
2010-09-20 11:00:21 +04:00
|
|
|
error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply);
|
2010-08-25 11:16:00 +04:00
|
|
|
if (error != 0)
|
2011-12-16 09:34:54 +04:00
|
|
|
return error;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
|
|
|
foh = GET_OUTHDR(ps, pm);
|
|
|
|
readen = foh->len - sizeof(*foh);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (readen > *resid)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: Unexpected big read %zd",
|
|
|
|
__func__, readen);
|
|
|
|
#endif
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
(void)memcpy(buf, _GET_OUTPAYLOAD(ps, pm, char *), readen);
|
|
|
|
|
|
|
|
buf += readen;
|
|
|
|
offset += readen;
|
|
|
|
*resid -= readen;
|
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
} while ((*resid != 0) && (readen != 0));
|
|
|
|
|
|
|
|
if (ioflag & (IO_SYNC|IO_DSYNC))
|
|
|
|
ps->ps_syncreads++;
|
|
|
|
else
|
|
|
|
ps->ps_asyncreads++;
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
return 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-07-21 09:49:42 +04:00
|
|
|
perfuse_node_write(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
uint8_t *buf, off_t offset, size_t *resid,
|
|
|
|
const struct puffs_cred *pcr, int ioflag)
|
|
|
|
{
|
|
|
|
return perfuse_node_write2(pu, opc, buf, offset, resid, pcr, ioflag, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED7 */
|
|
|
|
int
|
|
|
|
perfuse_node_write2(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
uint8_t *buf, off_t offset, size_t *resid,
|
|
|
|
const struct puffs_cred *pcr, int ioflag, int xflag)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
struct perfuse_node_data *pnd;
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
struct vattr *vap;
|
2010-08-25 11:16:00 +04:00
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_write_in *fwi;
|
|
|
|
struct fuse_write_out *fwo;
|
|
|
|
size_t data_len;
|
|
|
|
size_t payload_len;
|
|
|
|
size_t written;
|
2011-09-09 19:45:28 +04:00
|
|
|
int inresize;
|
2010-08-25 11:16:00 +04:00
|
|
|
int error;
|
|
|
|
|
|
|
|
ps = puffs_getspecific(pu);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd = PERFUSE_NODE_DATA(opc);
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
vap = puffs_pn_getvap((struct puffs_node *)opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
written = 0;
|
2011-09-09 19:45:28 +04:00
|
|
|
inresize = 0;
|
2011-12-16 09:34:54 +04:00
|
|
|
error = 0;
|
2010-08-25 11:16:00 +04:00
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
if (vap->va_type == VDIR)
|
2011-11-10 20:21:09 +04:00
|
|
|
return EISDIR;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
/*
|
|
|
|
* We need to queue write requests in order to avoid
|
|
|
|
* dequeueing PCQ_AFTERWRITE when there are pending writes.
|
|
|
|
*/
|
2010-09-05 10:49:13 +04:00
|
|
|
while (pnd->pnd_flags & PND_INWRITE)
|
|
|
|
requeue_request(pu, opc, PCQ_WRITE);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd->pnd_flags |= PND_INWRITE;
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
/*
|
|
|
|
* Serialize size access, see comment in perfuse_node_setattr().
|
|
|
|
*/
|
2011-09-10 14:06:10 +04:00
|
|
|
if ((u_quad_t)offset + *resid > vap->va_size) {
|
2011-09-09 19:45:28 +04:00
|
|
|
while (pnd->pnd_flags & PND_INRESIZE)
|
|
|
|
requeue_request(pu, opc, PCQ_RESIZE);
|
|
|
|
pnd->pnd_flags |= PND_INRESIZE;
|
|
|
|
inresize = 1;
|
|
|
|
}
|
|
|
|
|
2010-09-29 12:01:10 +04:00
|
|
|
/*
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
* append flag: re-read the file size so that
|
|
|
|
* we get the latest value.
|
2010-09-29 12:01:10 +04:00
|
|
|
*/
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
if (ioflag & PUFFS_IO_APPEND) {
|
|
|
|
if ((error = perfuse_node_getattr(pu, opc, vap, pcr)) != 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
offset = vap->va_size;
|
|
|
|
}
|
2010-09-29 12:01:10 +04:00
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RESIZE)
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF(">> %s %p %" PRIu64 "\n", __func__,
|
2011-09-09 19:45:28 +04:00
|
|
|
(void *)opc, vap->va_size);
|
|
|
|
#endif
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
do {
|
2010-09-20 11:00:21 +04:00
|
|
|
size_t max_write;
|
2010-08-25 11:16:00 +04:00
|
|
|
/*
|
2010-09-20 11:00:21 +04:00
|
|
|
* There is a writepage flag when data
|
2011-05-11 18:52:48 +04:00
|
|
|
* is aligned to page size. Use it for
|
2010-09-20 11:00:21 +04:00
|
|
|
* everything but the data after the last
|
|
|
|
* page boundary.
|
2010-08-25 11:16:00 +04:00
|
|
|
*/
|
2010-09-20 11:00:21 +04:00
|
|
|
max_write = ps->ps_max_write - sizeof(*fwi);
|
|
|
|
|
|
|
|
data_len = MIN(*resid, max_write);
|
2011-05-11 18:52:48 +04:00
|
|
|
if (data_len > (size_t)sysconf(_SC_PAGESIZE))
|
|
|
|
data_len = data_len & ~(sysconf(_SC_PAGESIZE) - 1);
|
2010-09-20 11:00:21 +04:00
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
payload_len = data_len + sizeof(*fwi);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* flags may be set to FUSE_WRITE_CACHE (XXX usage?)
|
|
|
|
* or FUSE_WRITE_LOCKOWNER, if lock_owner is provided.
|
|
|
|
* write_flags is set to 1 for writepage.
|
|
|
|
*/
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_WRITE, payload_len, pcr);
|
|
|
|
fwi = GET_INPAYLOAD(ps, pm, fuse_write_in);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fwi->fh = perfuse_get_fh(opc, FWRITE);
|
2010-08-25 11:16:00 +04:00
|
|
|
fwi->offset = offset;
|
2010-09-01 18:57:24 +04:00
|
|
|
fwi->size = (uint32_t)data_len;
|
2011-05-11 18:52:48 +04:00
|
|
|
fwi->write_flags = (fwi->size % sysconf(_SC_PAGESIZE)) ? 0 : 1;
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
fwi->lock_owner = pnd->pnd_lock_owner;
|
2010-08-25 11:16:00 +04:00
|
|
|
fwi->flags = 0;
|
|
|
|
fwi->flags |= (fwi->lock_owner != 0) ? FUSE_WRITE_LOCKOWNER : 0;
|
|
|
|
fwi->flags |= (ioflag & IO_DIRECT) ? 0 : FUSE_WRITE_CACHE;
|
2010-09-29 12:01:10 +04:00
|
|
|
(void)memcpy((fwi + 1), buf, data_len);
|
|
|
|
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
if (perfuse_diagflags & PDF_FH)
|
2011-10-30 09:11:37 +04:00
|
|
|
DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", "
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
"fh = 0x%"PRIx64"\n", __func__,
|
2011-10-30 09:11:37 +04:00
|
|
|
(void *)opc, pnd->pnd_nodeid, fwi->fh);
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
2010-09-20 11:00:21 +04:00
|
|
|
if ((error = xchg_msg(pu, opc, pm,
|
|
|
|
sizeof(*fwo), wait_reply)) != 0)
|
2010-08-25 11:16:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
fwo = GET_OUTPAYLOAD(ps, pm, fuse_write_out);
|
|
|
|
written = fwo->size;
|
2012-07-21 09:49:42 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
2010-09-20 11:00:21 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (written > *resid)
|
|
|
|
DERRX(EX_SOFTWARE, "%s: Unexpected big write %zd",
|
|
|
|
__func__, written);
|
|
|
|
#endif
|
2010-08-25 11:16:00 +04:00
|
|
|
*resid -= written;
|
|
|
|
offset += written;
|
|
|
|
buf += written;
|
|
|
|
|
|
|
|
} while (*resid != 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* puffs_ops(3) says
|
|
|
|
* "everything must be written or an error will be generated"
|
|
|
|
*/
|
|
|
|
if (*resid != 0)
|
|
|
|
error = EFBIG;
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_RESIZE) {
|
|
|
|
if (offset > (off_t)vap->va_size)
|
2011-09-10 02:51:44 +04:00
|
|
|
DPRINTF("<< %s %p %" PRIu64 " -> %lld\n", __func__,
|
|
|
|
(void *)opc, vap->va_size, (long long)offset);
|
2011-09-09 19:45:28 +04:00
|
|
|
else
|
|
|
|
DPRINTF("<< %s %p \n", __func__, (void *)opc);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Update file size if we wrote beyond the end
|
|
|
|
*/
|
|
|
|
if (offset > (off_t)vap->va_size)
|
|
|
|
vap->va_size = offset;
|
|
|
|
|
2011-09-09 19:45:28 +04:00
|
|
|
if (inresize) {
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (!(pnd->pnd_flags & PND_INRESIZE))
|
|
|
|
DERRX(EX_SOFTWARE, "file write grow without resize");
|
|
|
|
#endif
|
|
|
|
pnd->pnd_flags &= ~PND_INRESIZE;
|
2012-07-21 09:49:42 +04:00
|
|
|
(void)dequeue_requests(opc, PCQ_RESIZE, DEQUEUE_ALL);
|
2011-09-09 19:45:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
- Implement proper unprivilegied user permission verifications
Verification is now done in the lookup method, as it is the way to
go. Of course there are corner cases, such as the sticky bit which
need special handling in the remove method.
- Set full fsidx in vftstat method
- Do not pass O_APPEND to the filesystem. FUSE always sends the
write offset, so setting O_APPEND is useless. If the filesystem
uses it in an open(2) system call, it will even cause file
corruptions, since offsets given to pwrite(2) will be ignored.
This fix allows glusterfs to host a NetBSD ./build.sh -o build
- Do not use the FUSE access method, use getattr and check for
permission on our own. The problem is that a FUSE filesystem will
typically use the Linux-specific setfsuid() to perform access
control. If that is missing, any chack is likely to occur on
behalf of the user running the filesystem (typically root), causing
access method to return wrong information.
- When possible, avoid performing a getattr method call and use
cached value in puffs_node instead. We still retreive the latest
value by calling getattr when performing append write operation,
to minimize the chances that another writer appended since the
last time we did.
- Update puffs_node cached file size in write method
- Remove unused argument to perfuse_destroy_pn()
2011-04-25 08:54:53 +04:00
|
|
|
/*
|
|
|
|
* Statistics
|
|
|
|
*/
|
2010-08-25 11:16:00 +04:00
|
|
|
if (ioflag & (IO_SYNC|IO_DSYNC))
|
|
|
|
ps->ps_syncwrites++;
|
|
|
|
else
|
|
|
|
ps->ps_asyncwrites++;
|
|
|
|
|
2010-08-26 17:29:01 +04:00
|
|
|
/*
|
|
|
|
* Remember to sync the file
|
|
|
|
*/
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
pnd->pnd_flags |= PND_DIRTY;
|
2010-08-26 17:29:01 +04:00
|
|
|
|
|
|
|
#ifdef PERFUSE_DEBUG
|
|
|
|
if (perfuse_diagflags & PDF_SYNC)
|
|
|
|
DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n",
|
2012-07-21 09:49:42 +04:00
|
|
|
__func__, (void*)opc, perfuse_node_path(ps, opc));
|
2010-08-26 17:29:01 +04:00
|
|
|
#endif
|
2010-08-25 11:16:00 +04:00
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
out:
|
2012-07-21 09:49:42 +04:00
|
|
|
/*
|
|
|
|
* VOP_PUTPAGE causes FAF write where kernel does not
|
|
|
|
* check operation result. At least warn if it failed.
|
|
|
|
*/
|
|
|
|
#ifdef PUFFS_WRITE_FAF
|
|
|
|
if (error && (xflag & PUFFS_WRITE_FAF))
|
|
|
|
DWARN("Data loss caused by FAF write failed on \"%s\"",
|
|
|
|
pnd->pnd_name);
|
|
|
|
#endif /* PUFFS_WRITE_FAF */
|
|
|
|
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
/*
|
2010-09-05 10:49:13 +04:00
|
|
|
* If there are no more queued write, we can resume
|
|
|
|
* an operation awaiting write completion.
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
*/
|
2010-09-05 10:49:13 +04:00
|
|
|
pnd->pnd_flags &= ~PND_INWRITE;
|
2012-07-21 09:49:42 +04:00
|
|
|
if (dequeue_requests(opc, PCQ_WRITE, 1) == 0)
|
|
|
|
(void)dequeue_requests(opc, PCQ_AFTERWRITE, DEQUEUE_ALL);
|
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations
- remove unused argument to node_mk_common()
- remove requeued requests when they are executed, not when they
are tagged for schedule
- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).
- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.
- lookup file we just created: glusterfs does not really see them
otherwise.
- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.
- Do not flush pagecache for removed nodes
- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.
2010-09-03 11:15:18 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2010-08-25 11:16:00 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED0 */
|
|
|
|
void
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_cache_write(struct puffs_usermount *pu, puffs_cookie_t opc, size_t size,
|
|
|
|
struct puffs_cacherun *runs)
|
2010-08-25 11:16:00 +04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-28 20:19:16 +04:00
|
|
|
/* ARGSUSED4 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_getextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
int attrns, const char *attrname, size_t *attrsize, uint8_t *attr,
|
|
|
|
size_t *resid, const struct puffs_cred *pcr)
|
2011-06-28 20:19:16 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_getxattr_in *fgi;
|
|
|
|
struct fuse_getxattr_out *fgo;
|
|
|
|
struct fuse_out_header *foh;
|
|
|
|
size_t attrnamelen;
|
|
|
|
size_t len;
|
|
|
|
char *np;
|
|
|
|
int error;
|
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
/* system namespace attrs are not accessible to non root users */
|
|
|
|
if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr))
|
|
|
|
return EPERM;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2011-06-28 20:19:16 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
|
|
|
|
attrnamelen = strlen(attrname) + 1;
|
|
|
|
len = sizeof(*fgi) + attrnamelen;
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_GETXATTR, len, pcr);
|
|
|
|
fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
|
2011-09-10 02:51:44 +04:00
|
|
|
fgi->size = (unsigned int)((resid != NULL) ? *resid : 0);
|
2011-06-28 20:19:16 +04:00
|
|
|
np = (char *)(void *)(fgi + 1);
|
|
|
|
(void)strlcpy(np, attrname, attrnamelen);
|
|
|
|
|
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We just get fuse_getattr_out with list size if we requested
|
|
|
|
* a null size.
|
|
|
|
*/
|
|
|
|
if (resid == NULL) {
|
|
|
|
fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
|
|
|
|
|
|
|
|
if (attrsize != NULL)
|
|
|
|
*attrsize = fgo->size;
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
|
|
|
goto out;
|
2011-06-28 20:19:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And with a non null requested size, we get the list just
|
|
|
|
* after the header
|
|
|
|
*/
|
|
|
|
foh = GET_OUTHDR(ps, pm);
|
|
|
|
np = (char *)(void *)(foh + 1);
|
2014-08-09 23:06:50 +04:00
|
|
|
len = foh->len - sizeof(*foh);
|
|
|
|
|
|
|
|
if (attrsize != NULL)
|
|
|
|
*attrsize = len;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
|
|
|
if (resid != NULL) {
|
2014-08-09 23:06:50 +04:00
|
|
|
if (*resid < len) {
|
|
|
|
error = ERANGE;
|
2014-08-10 07:22:33 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
2014-08-09 23:06:50 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2011-06-28 20:19:16 +04:00
|
|
|
(void)memcpy(attr, np, len);
|
|
|
|
*resid -= len;
|
|
|
|
}
|
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2011-06-28 20:19:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_setextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
int attrns, const char *attrname, uint8_t *attr, size_t *resid,
|
|
|
|
const struct puffs_cred *pcr)
|
2011-06-28 20:19:16 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_setxattr_in *fsi;
|
|
|
|
size_t attrnamelen;
|
|
|
|
size_t len;
|
|
|
|
char *np;
|
|
|
|
int error;
|
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
/* system namespace attrs are not accessible to non root users */
|
|
|
|
if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr))
|
|
|
|
return EPERM;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
2011-06-28 20:19:16 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
|
|
|
|
attrnamelen = strlen(attrname) + 1;
|
|
|
|
len = sizeof(*fsi) + attrnamelen + *resid;
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_SETXATTR, len, pcr);
|
|
|
|
fsi = GET_INPAYLOAD(ps, pm, fuse_setxattr_in);
|
2011-09-10 02:51:44 +04:00
|
|
|
fsi->size = (unsigned int)*resid;
|
2011-06-28 20:19:16 +04:00
|
|
|
fsi->flags = 0;
|
|
|
|
np = (char *)(void *)(fsi + 1);
|
|
|
|
(void)strlcpy(np, attrname, attrnamelen);
|
|
|
|
np += attrnamelen;
|
|
|
|
(void)memcpy(np, (char *)attr, *resid);
|
|
|
|
|
|
|
|
if ((error = xchg_msg(pu, opc, pm,
|
|
|
|
NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
*resid = 0;
|
|
|
|
error = 0;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2011-06-28 20:19:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED2 */
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_listextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
int attrns, size_t *attrsize, uint8_t *attrs, size_t *resid, int flag,
|
|
|
|
const struct puffs_cred *pcr)
|
2011-06-28 20:19:16 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
struct fuse_getxattr_in *fgi;
|
|
|
|
struct fuse_getxattr_out *fgo;
|
|
|
|
struct fuse_out_header *foh;
|
|
|
|
char *np;
|
2014-08-10 07:22:33 +04:00
|
|
|
size_t len, puffs_len, i, attrlen, outlen;
|
2011-06-28 20:19:16 +04:00
|
|
|
int error;
|
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
/* system namespace attrs are not accessible to non root users */
|
|
|
|
if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr))
|
|
|
|
return EPERM;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2011-06-28 20:19:16 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
len = sizeof(*fgi);
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_LISTXATTR, len, pcr);
|
|
|
|
fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
|
|
|
|
if (resid != NULL)
|
2011-09-10 02:51:44 +04:00
|
|
|
fgi->size = (unsigned int)*resid;
|
2011-06-28 20:19:16 +04:00
|
|
|
else
|
|
|
|
fgi->size = 0;
|
|
|
|
|
|
|
|
if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
|
2012-07-21 09:49:42 +04:00
|
|
|
goto out;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We just get fuse_getattr_out with list size if we requested
|
|
|
|
* a null size.
|
|
|
|
*/
|
|
|
|
if (resid == NULL) {
|
|
|
|
fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
|
|
|
|
|
|
|
|
if (attrsize != NULL)
|
|
|
|
*attrsize = fgo->size;
|
|
|
|
|
2011-12-16 09:34:54 +04:00
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
|
|
|
goto out;
|
2011-06-28 20:19:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And with a non null requested size, we get the list just
|
|
|
|
* after the header
|
|
|
|
*/
|
|
|
|
foh = GET_OUTHDR(ps, pm);
|
|
|
|
np = (char *)(void *)(foh + 1);
|
|
|
|
puffs_len = foh->len - sizeof(*foh);
|
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
if (attrsize != NULL)
|
|
|
|
*attrsize = puffs_len;
|
|
|
|
|
2011-06-28 20:19:16 +04:00
|
|
|
if (attrs != NULL) {
|
2014-08-10 07:22:33 +04:00
|
|
|
if (*resid < puffs_len) {
|
|
|
|
error = ERANGE;
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
goto out;
|
2011-07-04 12:07:29 +04:00
|
|
|
}
|
2014-08-10 07:22:33 +04:00
|
|
|
|
|
|
|
outlen = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < puffs_len; i += attrlen + 1) {
|
|
|
|
attrlen = strlen(np + i);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Filter attributes per namespace
|
|
|
|
*/
|
|
|
|
if (!perfuse_ns_match(attrns, np + i))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
#ifdef PUFFS_EXTATTR_LIST_LENPREFIX
|
|
|
|
/*
|
|
|
|
* Convert the FUSE reply to length prefixed strings
|
|
|
|
* if this is what the kernel wants.
|
|
|
|
*/
|
|
|
|
if (flag & PUFFS_EXTATTR_LIST_LENPREFIX) {
|
|
|
|
(void)memcpy(attrs + outlen + 1,
|
|
|
|
np + i, attrlen);
|
|
|
|
*(attrs + outlen) = (uint8_t)attrlen;
|
|
|
|
} else
|
2011-07-19 11:29:39 +04:00
|
|
|
#endif /* PUFFS_EXTATTR_LIST_LENPREFIX */
|
2014-08-10 07:22:33 +04:00
|
|
|
(void)memcpy(attrs + outlen, np + i, attrlen + 1);
|
|
|
|
outlen += attrlen + 1;
|
|
|
|
}
|
2011-06-28 20:19:16 +04:00
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
*resid -= outlen;
|
|
|
|
}
|
2011-06-28 20:19:16 +04:00
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
2012-07-21 09:49:42 +04:00
|
|
|
error = 0;
|
2011-06-28 20:19:16 +04:00
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
out:
|
|
|
|
node_rele(opc);
|
|
|
|
return error;
|
2011-06-28 20:19:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-03-21 14:10:36 +04:00
|
|
|
perfuse_node_deleteextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
|
|
|
|
int attrns, const char *attrname, const struct puffs_cred *pcr)
|
2011-06-28 20:19:16 +04:00
|
|
|
{
|
|
|
|
struct perfuse_state *ps;
|
|
|
|
char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
|
|
|
|
perfuse_msg_t *pm;
|
|
|
|
size_t attrnamelen;
|
|
|
|
char *np;
|
|
|
|
int error;
|
|
|
|
|
2014-08-10 07:22:33 +04:00
|
|
|
/* system namespace attrs are not accessible to non root users */
|
|
|
|
if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr))
|
|
|
|
return EPERM;
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_ref(opc);
|
|
|
|
|
2011-06-28 20:19:16 +04:00
|
|
|
ps = puffs_getspecific(pu);
|
|
|
|
attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
|
|
|
|
attrnamelen = strlen(attrname) + 1;
|
|
|
|
|
|
|
|
pm = ps->ps_new_msg(pu, opc, FUSE_REMOVEXATTR, attrnamelen, pcr);
|
|
|
|
np = _GET_INPAYLOAD(ps, pm, char *);
|
|
|
|
(void)strlcpy(np, attrname, attrnamelen);
|
|
|
|
|
|
|
|
error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
|
|
|
|
|
|
|
|
ps->ps_destroy_msg(pm);
|
|
|
|
|
2012-07-21 09:49:42 +04:00
|
|
|
node_rele(opc);
|
2011-06-28 20:19:16 +04:00
|
|
|
return error;
|
|
|
|
}
|