+2005-03-31 Miklos Szeredi <miklos@szeredi.hu>
+
+ * kernel API: add padding to structures, so 64bit and 32bit
+ compiler will return the same size
+
+ * kernel API: add offset field to fuse_dirent. This will allow
+ more sophisticated readdir interface for userspace
+
+ * kernel API: change major number to 6
+
+ * kernel: fix warnings on 64bit archs
+
+ * kernel: in case of API version mismatch, return ECONNREFUSED
+
2005-03-24 Miklos Szeredi <miklos@szeredi.hu>
* kernel: trivial cleanups
wake_up(&req->waitq);
if (req->in.h.opcode == FUSE_INIT) {
int i;
+
+ if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
+ fc->conn_error = 1;
+
/* After INIT reply is received other requests can go
out. So do (FUSE_MAX_OUTSTANDING - 1) number of
up()s on outstanding_sem. The last up() is done in
{
req->isreply = 1;
spin_lock(&fuse_lock);
- req->out.h.error = -ENOTCONN;
- if (fc->file) {
+ if (!fc->file)
+ req->out.h.error = -ENOTCONN;
+ else if (fc->conn_error)
+ req->out.h.error = -ECONNREFUSED;
+ else {
queue_request(fc, req);
/* acquire extra reference, since request is still needed
after request_end() */
remove_wait_queue(&fc->waitq, &wait);
}
+#ifndef KERNEL_2_6
+static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
+{
+ unsigned long seg;
+ size_t ret = 0;
+
+ for (seg = 0; seg < nr_segs; seg++)
+ ret += iov[seg].iov_len;
+ return ret;
+}
+#endif
/*
* Read a single request into the userspace filesystem's buffer. This
* function waits until a request is available, then removes it from
break;
over = filldir(dstbuf, dirent->name, dirent->namelen,
- file->f_pos, dirent->ino, dirent->type);
+ dirent->off, dirent->ino, dirent->type);
if (over)
break;
{
struct inode *inode = file->f_dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- unsigned nmax = write ? fc->max_write : fc->max_read;
+ size_t nmax = write ? fc->max_write : fc->max_read;
loff_t pos = *ppos;
ssize_t res = 0;
struct fuse_req *req = fuse_get_request(fc);
return -ERESTARTSYS;
while (count) {
- unsigned tmp;
- unsigned nres;
+ size_t tmp;
+ size_t nres;
size_t nbytes = min(count, nmax);
int err = fuse_get_user_pages(req, buf, nbytes, !write);
if (err) {
/** Is removexattr not implemented by fs? */
unsigned no_removexattr : 1;
+ /** Connection failed (version mismatch) */
+ unsigned conn_error : 1;
+
#ifdef KERNEL_2_6
/** Backing dev info */
struct backing_dev_info bdi;
*/
int fuse_release_common(struct inode *inode, struct file *file, int isdir);
-/**
+/**
* Send FSYNC or FSYNCDIR request
*/
int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
#include <asm/types.h>
/** Version number of this interface */
-#define FUSE_KERNEL_VERSION 5
+#define FUSE_KERNEL_VERSION 6
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 1
/** The minor number of the fuse character device */
#define FUSE_MINOR 229
+/* Make sure all structures are padded to 64bit boundary, so 32bit
+ userspace works under 64bit kernels */
+
struct fuse_attr {
__u64 ino;
__u64 size;
struct fuse_mkdir_in {
__u32 mode;
+ __u32 padding;
};
struct fuse_rename_in {
struct fuse_setattr_in {
__u32 valid;
+ __u32 padding;
struct fuse_attr attr;
};
struct fuse_open_in {
__u32 flags;
+ __u32 padding;
};
struct fuse_open_out {
__u64 fh;
__u32 open_flags;
+ __u32 padding;
};
struct fuse_release_in {
__u64 fh;
__u32 flags;
+ __u32 padding;
};
struct fuse_flush_in {
__u64 fh;
__u32 flush_flags;
+ __u32 padding;
};
struct fuse_read_in {
__u64 fh;
__u64 offset;
__u32 size;
+ __u32 padding;
};
struct fuse_write_in {
struct fuse_write_out {
__u32 size;
+ __u32 padding;
};
struct fuse_statfs_out {
struct fuse_fsync_in {
__u64 fh;
__u32 fsync_flags;
+ __u32 padding;
};
struct fuse_setxattr_in {
struct fuse_getxattr_in {
__u32 size;
+ __u32 padding;
};
struct fuse_getxattr_out {
__u32 size;
+ __u32 padding;
};
struct fuse_init_in_out {
__u32 uid;
__u32 gid;
__u32 pid;
+ __u32 padding;
};
struct fuse_out_header {
struct fuse_dirent {
__u64 ino;
+ __u64 off;
__u32 namelen;
__u32 type;
char name[0];
dirent->namelen = namelen;
strncpy(dirent->name, name, namelen);
dirent->type = type;
+ dirent->off = dh->len;
dh->len += FUSE_DIRENT_SIZE(dirent);
return 0;
}