+2005-01-11 Miklos Szeredi <miklos@szeredi.hu>
+
+ * KERNEL: fix possible inode allocation problem, where
+ sizeof(struct inode) is not aligned (found by Mike Waychison)
+
+ * KERNEL: use new follow_link/put_link methods
+
+ * KERNEL: cosmetic fixes
+
2005-01-10 Miklos Szeredi <miklos@szeredi.hu>
* Released 2.2-pre3
#include <linux/mm.h>
#endif
#include <linux/sched.h>
+#ifdef KERNEL_2_6_7_PLUS
+#include <linux/namei.h>
+#endif
static inline unsigned long time_to_jiffies(unsigned long sec,
unsigned long nsec)
{
- /* prevent wrapping of jiffies */
- if (sec + 1 >= LONG_MAX / HZ)
- return 0;
-
- return jiffies + sec * HZ + nsec / (1000000000 / HZ);
+ struct timespec ts = {sec, nsec};
+ return jiffies + timespec_to_jiffies(&ts);
}
static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
{
if (!entry->d_inode || is_bad_inode(entry->d_inode))
return 0;
- else if (entry->d_time && time_after(jiffies, entry->d_time)) {
+ else if (time_after(jiffies, entry->d_time)) {
int err;
int version;
struct fuse_entry_out outarg;
(!(fc->flags & FUSE_ALLOW_ROOT) ||
current->fsuid != 0))
return -EACCES;
- } else if (!fi->i_time || time_before_eq(jiffies, fi->i_time))
+ } else if (time_before_eq(jiffies, fi->i_time))
return 0;
return fuse_do_getattr(inode);
free_page((unsigned long) link);
}
+#ifdef KERNEL_2_6_7_PLUS
+static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ nd_set_link(nd, read_link(dentry));
+ return 0;
+}
+
+static void fuse_put_link(struct dentry *dentry, struct nameidata *nd)
+{
+ free_link(nd_get_link(nd));
+}
+#else
static int fuse_readlink(struct dentry *dentry, char __user *buffer,
int buflen)
{
free_link(link);
return ret;
}
+#endif
static int fuse_dir_open(struct inode *inode, struct file *file)
{
static struct inode_operations fuse_symlink_inode_operations = {
.setattr = fuse_setattr,
- .readlink = fuse_readlink,
.follow_link = fuse_follow_link,
+#ifdef KERNEL_2_6_7_PLUS
+ .put_link = fuse_put_link,
+ .readlink = generic_readlink,
+#else
+ .readlink = fuse_readlink,
+#endif
#ifdef KERNEL_2_6
.getattr = fuse_getattr,
#else
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
# define KERNEL_2_6_6_PLUS
# endif
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
+# define KERNEL_2_6_7_PLUS
+# endif
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
# define KERNEL_2_6_10_PLUS
# endif
filesystems */
#define FUSE_ALLOW_ROOT (1 << 4)
-/** FUSE specific inode data */
+/** FUSE inode */
struct fuse_inode {
+ /** Inode data */
+ struct inode inode;
+
/** Unique ID, which identifies the inode between userspace
* and kernel */
u64 nodeid;
static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
{
- return (struct fuse_inode *) (&inode[1]);
+ return container_of(inode, struct fuse_inode, inode);
}
static inline u64 get_node_id(struct inode *inode)
inode->u.generic_ip = NULL;
#endif
fi = get_fuse_inode(inode);
- memset(fi, 0, sizeof(*fi));
+ fi->i_time = jiffies - 1;
+ fi->nodeid = 0;
fi->forget_req = fuse_request_alloc();
if (!fi->forget_req) {
kmem_cache_free(fuse_inode_cachep, inode);
return success;
}
-static int fuse_read_super(struct super_block *sb, void *data, int silent)
+static int fuse_fill_super(struct super_block *sb, void *data, int silent)
{
struct fuse_conn *fc;
struct inode *root;
int flags, const char *dev_name,
void *raw_data)
{
- return get_sb_nodev(fs_type, flags, raw_data, fuse_read_super);
+ return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super);
}
static struct file_system_type fuse_fs_type = {
static struct super_block *fuse_read_super_compat(struct super_block *sb,
void *data, int silent)
{
- int err = fuse_read_super(sb, data, silent);
+ int err = fuse_fill_super(sb, data, silent);
if (err)
return NULL;
else
static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super_compat, 0);
#endif
-static void fuse_inode_init_once(void * foo, kmem_cache_t * cachep,
+static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
unsigned long flags)
{
struct inode * inode = foo;
printk("fuse: failed to register filesystem\n");
else {
fuse_inode_cachep = kmem_cache_create("fuse_inode",
- sizeof(struct inode) + sizeof(struct fuse_inode) ,
+ sizeof(struct fuse_inode),
0, SLAB_HWCACHE_ALIGN,
fuse_inode_init_once, NULL);
if (!fuse_inode_cachep) {
kmem_cache_destroy(fuse_inode_cachep);
}
-int __init fuse_init(void)
+static int __init fuse_init(void)
{
int res;
return res;
}
-void __exit fuse_exit(void)
+static void __exit fuse_exit(void)
{
printk(KERN_DEBUG "fuse exit\n");