add ftruncate() method

This commit is contained in:
Miklos Szeredi 2005-10-26 16:04:04 +00:00
parent d9079a75b1
commit 11509ce3fc
8 changed files with 103 additions and 36 deletions

View File

@ -1,15 +1,20 @@
2005-10-26 Miklos Szeredi <miklos@szeredi.hu>
* Change kernel ABI version to 7.3
* Add ACCESS operation. This is called from the access() system
call if 'default_permissions' mount option is not given, and is
not called on kernels 2.4.*
* Fix kernel module compile if kernel source and build directories
differ. Report and initial patch by John Eastman
* Add atomic CREATE+OPEN operation. This will only work with
2.6.15 (presumably) or later Linux kernels.
* Add ftruncate() method. This will only work with 2.6.15
(presumably) or later Linux kernels.
* Fix kernel module compile if kernel source and build directories
differ. Report and initial patch by John Eastman
2005-10-18 Miklos Szeredi <miklos@szeredi.hu>
* lib: optimize buffer reallocation in fill_dir.

View File

@ -204,6 +204,20 @@ static int xmp_truncate(const char *path, off_t size)
return 0;
}
static int xmp_ftruncate(const char *path, off_t size,
struct fuse_file_info *fi)
{
int res;
(void) path;
res = ftruncate(fi->fh, size);
if(res == -1)
return -errno;
return 0;
}
static int xmp_utime(const char *path, struct utimbuf *buf)
{
int res;
@ -354,6 +368,7 @@ static struct fuse_operations xmp_oper = {
.chmod = xmp_chmod,
.chown = xmp_chown,
.truncate = xmp_truncate,
.ftruncate = xmp_ftruncate,
.utime = xmp_utime,
.create = xmp_create,
.open = xmp_open,

View File

@ -63,9 +63,9 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type,
*
* All methods are optional, but some are essential for a useful
* filesystem (e.g. getattr). Open, flush, release, fsync, opendir,
* releasedir, fsyncdir, access, create, init and destroy are special
* purpose methods, without which a full featured filesystem can still
* be implemented.
* releasedir, fsyncdir, access, create, ftruncate, init and destroy
* are special purpose methods, without which a full featured
* filesystem can still be implemented.
*/
struct fuse_operations {
/** Get file attributes.
@ -324,6 +324,20 @@ struct fuse_operations {
* Introduced in version 2.5
*/
int (*create) (const char *, mode_t, struct fuse_file_info *);
/**
* Change the size of an open file
*
* This method is called instead of the truncate() method if the
* truncation was invoked from an ftruncate() system call.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the truncate() method will be
* called instead.
*
* Introduced in version 2.5
*/
int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
};
/** Extra context that may be needed by some filesystems

View File

@ -198,6 +198,13 @@ struct fuse_lowlevel_ops {
* bitmask contain valid values. Other members contain undefined
* values.
*
* If the setattr was invoked from the ftruncate() system call
* under Linux kernel versions 2.6.15 or later, the fi->fh will
* contain the value set by the open method or will be undefined
* if the open method didn't set any value. Otherwise (not
* ftruncate call, or kernel version earlier than 2.6.15) the fi
* parameter will be NULL.
*
* Valid replies:
* fuse_reply_attr()
* fuse_reply_err()
@ -206,7 +213,10 @@ struct fuse_lowlevel_ops {
* @param ino the inode number
* @param attr the attributes
* @param to_set bit mask of attributes which should be set
* @param fi for future use, currently always NULL
* @param fi file information, or NULL
*
* Changed in version 2.5:
* file information filled in for ftruncate
*/
void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi);

View File

@ -838,34 +838,36 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
{
unsigned ivalid = iattr->ia_valid;
unsigned fvalid = 0;
memset(fattr, 0, sizeof(*fattr));
if (ivalid & ATTR_MODE)
fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
if (ivalid & ATTR_GID)
fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
if (ivalid & ATTR_SIZE)
fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
/* You can only _set_ these together (they may change by themselves) */
if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
fvalid |= FATTR_ATIME | FATTR_MTIME;
arg->valid |= FATTR_ATIME | FATTR_MTIME;
#ifdef KERNEL_2_6
fattr->atime = iattr->ia_atime.tv_sec;
fattr->mtime = iattr->ia_mtime.tv_sec;
arg->atime = iattr->ia_atime.tv_sec;
arg->mtime = iattr->ia_mtime.tv_sec;
#else
fattr->atime = iattr->ia_atime;
fattr->mtime = iattr->ia_mtime;
arg->atime = iattr->ia_atime;
arg->mtime = iattr->ia_mtime;
#endif
}
return fvalid;
#ifdef ATTR_FILE
if (ivalid & ATTR_FILE) {
struct fuse_file *ff = iattr->ia_file->private_data;
arg->valid |= FATTR_FH;
arg->fh = ff->fh;
}
#endif
}
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
@ -904,7 +906,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
return -EINTR;
memset(&inarg, 0, sizeof(inarg));
inarg.valid = iattr_to_fattr(attr, &inarg.attr);
iattr_to_fattr(attr, &inarg);
req->in.h.opcode = FUSE_SETATTR;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;

View File

@ -42,7 +42,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 2
#define FUSE_KERNEL_MINOR_VERSION 3
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@ -89,6 +89,7 @@ struct fuse_kstatfs {
#define FATTR_SIZE (1 << 3)
#define FATTR_ATIME (1 << 4)
#define FATTR_MTIME (1 << 5)
#define FATTR_FH (1 << 6)
/**
* Flags returned by the OPEN request
@ -182,7 +183,20 @@ struct fuse_link_in {
struct fuse_setattr_in {
__u32 valid;
__u32 padding;
struct fuse_attr attr;
__u64 fh;
__u64 size;
__u64 unused1;
__u64 atime;
__u64 mtime;
__u64 unused2;
__u32 atimensec;
__u32 mtimensec;
__u32 unused3;
__u32 mode;
__u32 unused4;
__u32 uid;
__u32 gid;
__u32 unused5;
};
struct fuse_open_in {

View File

@ -674,12 +674,15 @@ static int do_chown(struct fuse *f, const char *path, struct stat *attr,
return err;
}
static int do_truncate(struct fuse *f, const char *path, struct stat *attr)
static int do_truncate(struct fuse *f, const char *path, struct stat *attr,
struct fuse_file_info *fi)
{
int err;
err = -ENOSYS;
if (f->op.truncate)
if (fi && f->op.ftruncate)
err = f->op.ftruncate(path, attr->st_size, fi);
else if (f->op.truncate)
err = f->op.truncate(path, attr->st_size);
return err;
@ -706,8 +709,6 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
char *path;
int err;
(void) fi;
err = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
@ -720,7 +721,7 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)))
err = do_chown(f, path, attr, valid);
if (!err && (valid & FUSE_SET_ATTR_SIZE))
err = do_truncate(f, path, attr);
err = do_truncate(f, path, attr, fi);
if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))
err = do_utime(f, path, attr);
if (!err)

View File

@ -95,7 +95,7 @@ static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
#endif
}
static void convert_attr(const struct fuse_attr *attr, struct stat *stbuf)
static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
{
stbuf->st_mode = attr->mode;
stbuf->st_uid = attr->uid;
@ -103,11 +103,9 @@ static void convert_attr(const struct fuse_attr *attr, struct stat *stbuf)
stbuf->st_size = attr->size;
stbuf->st_atime = attr->atime;
stbuf->st_mtime = attr->mtime;
stbuf->st_ctime = attr->ctime;
#ifdef HAVE_STRUCT_STAT_ST_ATIM
stbuf->st_atim.tv_nsec = attr->atimensec;
stbuf->st_mtim.tv_nsec = attr->mtimensec;
stbuf->st_ctim.tv_nsec = attr->ctimensec;
#endif
}
@ -366,12 +364,20 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid)
}
static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
struct fuse_setattr_in *arg, struct fuse_file_info *fi)
struct fuse_setattr_in *arg)
{
if (req->f->op.setattr) {
struct fuse_file_info *fi = NULL;
struct fuse_file_info fi_store;
struct stat stbuf;
memset(&stbuf, 0, sizeof(stbuf));
convert_attr(&arg->attr, &stbuf);
convert_attr(arg, &stbuf);
if (arg->valid & FATTR_FH) {
arg->valid &= ~FATTR_FH;
memset(&fi_store, 0, sizeof(fi_store));
fi = &fi_store;
fi->fh = arg->fh;
}
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
} else
fuse_reply_err(req, ENOSYS);
@ -754,7 +760,7 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
break;
case FUSE_SETATTR:
do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg, NULL);
do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg);
break;
case FUSE_READLINK: