From: Miklos Szeredi Date: Fri, 20 Feb 2004 14:10:49 +0000 (+0000) Subject: more kernel interface changes X-Git-Tag: fuse_1_9~87 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=b59586199b5c53fa7002e9e1e6accc08a515f420;p=qemu-gpiodev%2Flibfuse.git more kernel interface changes --- diff --git a/ChangeLog b/ChangeLog index cdc2579..cd1da1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-02-20 Miklos Szeredi + + * more kernel interface changes: + + * added nanosecond precision to file times + 2004-02-19 Miklos Szeredi * statfs library API changed to match other methods. Since this diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 9bca31c..10ef186 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -66,11 +66,13 @@ struct fuse_attr { unsigned int gid; unsigned int rdev; unsigned long long size; - unsigned long _dummy; unsigned long blocks; unsigned long atime; + unsigned long atimensec; unsigned long mtime; + unsigned long mtimensec; unsigned long ctime; + unsigned long ctimensec; }; struct fuse_kstatfs { @@ -87,7 +89,9 @@ struct fuse_kstatfs { #define FATTR_UID (1 << 1) #define FATTR_GID (1 << 2) #define FATTR_SIZE (1 << 3) -#define FATTR_UTIME (1 << 4) +#define FATTR_ATIME (1 << 4) +#define FATTR_MTIME (1 << 5) +#define FATTR_CTIME (1 << 6) enum fuse_opcode { FUSE_LOOKUP = 1, diff --git a/kernel/dir.c b/kernel/dir.c index b9c26e6..c5810e9 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -47,11 +47,11 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr) inode->i_blocks = attr->blocks; #ifdef KERNEL_2_6 inode->i_atime.tv_sec = attr->atime; - inode->i_atime.tv_nsec = 0; + inode->i_atime.tv_nsec = attr->atimensec; inode->i_mtime.tv_sec = attr->mtime; - inode->i_mtime.tv_nsec = 0; + inode->i_mtime.tv_nsec = attr->mtimensec; inode->i_ctime.tv_sec = attr->ctime; - inode->i_ctime.tv_nsec = 0; + inode->i_ctime.tv_nsec = attr->ctimensec; #else inode->i_atime = attr->atime; inode->i_mtime = attr->mtime; @@ -261,43 +261,46 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK); } -static int fuse_remove(struct inode *dir, struct dentry *entry, - enum fuse_opcode op) +static int fuse_unlink(struct inode *dir, struct dentry *entry) { struct fuse_conn *fc = INO_FC(dir); struct fuse_in in = FUSE_IN_INIT; struct fuse_out out = FUSE_OUT_INIT; - in.h.opcode = op; + in.h.opcode = FUSE_UNLINK; in.h.ino = dir->i_ino; in.numargs = 1; in.args[0].size = entry->d_name.len + 1; in.args[0].value = entry->d_name.name; request_send(fc, &in, &out); - return out.h.error; -} - -static int fuse_unlink(struct inode *dir, struct dentry *entry) -{ - int err = fuse_remove(dir, entry, FUSE_UNLINK); - if(!err) { - /* FIXME: the new i_nlink could be returned by the - unlink operation */ - err = fuse_do_getattr(entry->d_inode); - if(err == -ENOENT) - entry->d_inode->i_nlink = 0; - return 0; + if(!out.h.error) { + /* Set nlink to zero so the inode can be cleared, if + the inode does have more links this will be + discovered at the next lookup/getattr */ + /* FIXME: mark inode "not uptodate" */ + entry->d_inode->i_nlink = 0; } - return err; + + return out.h.error; } static int fuse_rmdir(struct inode *dir, struct dentry *entry) { - int err = fuse_remove(dir, entry, FUSE_RMDIR); - if(!err) + struct fuse_conn *fc = INO_FC(dir); + struct fuse_in in = FUSE_IN_INIT; + struct fuse_out out = FUSE_OUT_INIT; + + in.h.opcode = FUSE_RMDIR; + in.h.ino = dir->i_ino; + in.numargs = 1; + in.args[0].size = entry->d_name.len + 1; + in.args[0].value = entry->d_name.name; + request_send(fc, &in, &out); + if(!out.h.error) entry->d_inode->i_nlink = 0; - return err; + + return out.h.error; } static int fuse_rename(struct inode *olddir, struct dentry *oldent, @@ -594,7 +597,7 @@ static unsigned int iattr_to_fattr(struct iattr *iattr, fvalid |= FATTR_SIZE, fattr->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_UTIME; + fvalid |= FATTR_ATIME | FATTR_MTIME; #ifdef KERNEL_2_6 fattr->atime = iattr->ia_atime.tv_sec; fattr->mtime = iattr->ia_mtime.tv_sec; diff --git a/lib/fuse.c b/lib/fuse.c index 079220a..2e6950d 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -315,17 +315,19 @@ static void rename_node(struct fuse *f, fino_t olddir, const char *oldname, static void convert_stat(struct stat *stbuf, struct fuse_attr *attr) { - attr->mode = stbuf->st_mode; - attr->nlink = stbuf->st_nlink; - attr->uid = stbuf->st_uid; - attr->gid = stbuf->st_gid; - attr->rdev = stbuf->st_rdev; - attr->size = stbuf->st_size; - attr->blocks = stbuf->st_blocks; - attr->atime = stbuf->st_atime; - attr->mtime = stbuf->st_mtime; - attr->ctime = stbuf->st_ctime; - attr->_dummy = 4096; + attr->mode = stbuf->st_mode; + attr->nlink = stbuf->st_nlink; + attr->uid = stbuf->st_uid; + attr->gid = stbuf->st_gid; + attr->rdev = stbuf->st_rdev; + attr->size = stbuf->st_size; + attr->blocks = stbuf->st_blocks; + attr->atime = stbuf->st_atime; + attr->atimensec = stbuf->st_atim.tv_nsec; + attr->mtime = stbuf->st_mtime; + attr->mtimensec = stbuf->st_mtim.tv_nsec; + attr->ctime = stbuf->st_ctime; + attr->ctimensec = stbuf->st_ctim.tv_nsec; } static int fill_dir(struct fuse_dirhandle *dh, char *name, int type) @@ -553,7 +555,8 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in, res = do_chown(f, path, attr, valid); if(!res && (valid & FATTR_SIZE)) res = do_truncate(f, path, attr); - if(!res && (valid & FATTR_UTIME)) + if(!res && (valid & (FATTR_ATIME | FATTR_MTIME)) == + (FATTR_ATIME | FATTR_MTIME)) res = do_utime(f, path, attr); if(!res) { struct stat buf; @@ -665,7 +668,7 @@ static void do_mkdir(struct fuse *f, struct fuse_in_header *in, send_reply(f, in, res, &outarg, sizeof(outarg)); } -static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name) +static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name) { int res; char *path; @@ -674,18 +677,32 @@ static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name) path = get_path_name(f, in->ino, name); if(path != NULL) { res = -ENOSYS; - if(in->opcode == FUSE_UNLINK) { - if(f->op.unlink) - res = f->op.unlink(path); + if(f->op.unlink) { + res = f->op.unlink(path); + if(res == 0) + remove_node(f, in->ino, name); } - else { - if(f->op.rmdir) - res = f->op.rmdir(path); + free(path); + } + send_reply(f, in, res, NULL, 0); +} + +static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name) +{ + int res; + char *path; + + res = -ENOENT; + path = get_path_name(f, in->ino, name); + if(path != NULL) { + res = -ENOSYS; + if(f->op.rmdir) { + res = f->op.rmdir(path); + if(res == 0) + remove_node(f, in->ino, name); } free(path); } - if(res == 0) - remove_node(f, in->ino, name); send_reply(f, in, res, NULL, 0); } @@ -990,8 +1007,11 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) break; case FUSE_UNLINK: + do_unlink(f, in, (char *) inarg); + break; + case FUSE_RMDIR: - do_remove(f, in, (char *) inarg); + do_rmdir(f, in, (char *) inarg); break; case FUSE_SYMLINK: