aboutsummaryrefslogtreecommitdiff
path: root/fs/coda
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda')
-rw-r--r--fs/coda/Makefile2
-rw-r--r--fs/coda/cache.c14
-rw-r--r--fs/coda/cnode.c44
-rw-r--r--fs/coda/coda_fs_i.h6
-rw-r--r--fs/coda/coda_int.h4
-rw-r--r--fs/coda/coda_linux.c10
-rw-r--r--fs/coda/coda_linux.h17
-rw-r--r--fs/coda/dir.c158
-rw-r--r--fs/coda/file.c28
-rw-r--r--fs/coda/inode.c94
-rw-r--r--fs/coda/pioctl.c8
-rw-r--r--fs/coda/psdev.c47
-rw-r--r--fs/coda/sysctl.c21
-rw-r--r--fs/coda/upcall.c25
14 files changed, 226 insertions, 252 deletions
diff --git a/fs/coda/Makefile b/fs/coda/Makefile
index 6c22e61da39..1bab69a0d34 100644
--- a/fs/coda/Makefile
+++ b/fs/coda/Makefile
@@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \
# If you want debugging output, please uncomment the following line.
-# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1
+# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 69015787618..1da168c61d3 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -33,7 +33,7 @@ void coda_cache_enter(struct inode *inode, int mask)
spin_lock(&cii->c_lock);
cii->c_cached_epoch = atomic_read(&permission_epoch);
- if (cii->c_uid != current_fsuid()) {
+ if (!uid_eq(cii->c_uid, current_fsuid())) {
cii->c_uid = current_fsuid();
cii->c_cached_perm = mask;
} else
@@ -65,7 +65,7 @@ int coda_cache_check(struct inode *inode, int mask)
spin_lock(&cii->c_lock);
hit = (mask & cii->c_cached_perm) == mask &&
- cii->c_uid == current_fsuid() &&
+ uid_eq(cii->c_uid, current_fsuid()) &&
cii->c_cached_epoch == atomic_read(&permission_epoch);
spin_unlock(&cii->c_lock);
@@ -89,17 +89,13 @@ int coda_cache_check(struct inode *inode, int mask)
/* this won't do any harm: just flag all children */
static void coda_flag_children(struct dentry *parent, int flag)
{
- struct list_head *child;
struct dentry *de;
spin_lock(&parent->d_lock);
- list_for_each(child, &parent->d_subdirs)
- {
- de = list_entry(child, struct dentry, d_u.d_child);
+ list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
/* don't know what to do with negative dentries */
- if ( ! de->d_inode )
- continue;
- coda_flag_inode(de->d_inode, flag);
+ if (de->d_inode )
+ coda_flag_inode(de->d_inode, flag);
}
spin_unlock(&parent->d_lock);
return;
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 6475877b076..7740b1c871c 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -88,24 +88,21 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
- link the two up if this is needed
- fill in the attributes
*/
-int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_block *sb)
+struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
{
struct coda_vattr attr;
+ struct inode *inode;
int error;
/* We get inode numbers from Venus -- see venus source */
error = venus_getattr(sb, fid, &attr);
- if ( error ) {
- *inode = NULL;
- return error;
- }
-
- *inode = coda_iget(sb, fid, &attr);
- if ( IS_ERR(*inode) ) {
- printk("coda_cnode_make: coda_iget failed\n");
- return PTR_ERR(*inode);
- }
- return 0;
+ if (error)
+ return ERR_PTR(error);
+
+ inode = coda_iget(sb, fid, &attr);
+ if (IS_ERR(inode))
+ pr_warn("%s: coda_iget failed\n", __func__);
+ return inode;
}
@@ -140,7 +137,7 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)
unsigned long hash = coda_f2i(fid);
if ( !sb ) {
- printk("coda_fid_to_inode: no sb!\n");
+ pr_warn("%s: no sb!\n", __func__);
return NULL;
}
@@ -156,19 +153,16 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)
}
/* the CONTROL inode is made without asking attributes from Venus */
-int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
+struct inode *coda_cnode_makectl(struct super_block *sb)
{
- int error = -ENOMEM;
-
- *inode = new_inode(sb);
- if (*inode) {
- (*inode)->i_ino = CTL_INO;
- (*inode)->i_op = &coda_ioctl_inode_operations;
- (*inode)->i_fop = &coda_ioctl_operations;
- (*inode)->i_mode = 0444;
- error = 0;
+ struct inode *inode = new_inode(sb);
+ if (inode) {
+ inode->i_ino = CTL_INO;
+ inode->i_op = &coda_ioctl_inode_operations;
+ inode->i_fop = &coda_ioctl_operations;
+ inode->i_mode = 0444;
+ return inode;
}
-
- return error;
+ return ERR_PTR(-ENOMEM);
}
diff --git a/fs/coda/coda_fs_i.h b/fs/coda/coda_fs_i.h
index e35071b1de0..c6407521321 100644
--- a/fs/coda/coda_fs_i.h
+++ b/fs/coda/coda_fs_i.h
@@ -25,7 +25,7 @@ struct coda_inode_info {
u_short c_flags; /* flags (see below) */
unsigned int c_mapcount; /* nr of times this inode is mapped */
unsigned int c_cached_epoch; /* epoch for cached permissions */
- vuid_t c_uid; /* fsuid for cached permissions */
+ kuid_t c_uid; /* fsuid for cached permissions */
unsigned int c_cached_perm; /* cached access permissions */
spinlock_t c_lock;
struct inode vfs_inode;
@@ -49,9 +49,9 @@ struct coda_file_info {
#define C_DYING 0x4 /* from venus (which died) */
#define C_PURGE 0x8
-int coda_cnode_make(struct inode **, struct CodaFid *, struct super_block *);
+struct inode *coda_cnode_make(struct CodaFid *, struct super_block *);
struct inode *coda_iget(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *attr);
-int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
+struct inode *coda_cnode_makectl(struct super_block *sb);
struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);
void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
diff --git a/fs/coda/coda_int.h b/fs/coda/coda_int.h
index 6b443ff43a1..381c993b142 100644
--- a/fs/coda/coda_int.h
+++ b/fs/coda/coda_int.h
@@ -10,8 +10,8 @@ extern int coda_hard;
extern int coda_fake_statfs;
void coda_destroy_inodecache(void);
-int coda_init_inodecache(void);
-int coda_fsync(struct file *coda_file, int datasync);
+int __init coda_init_inodecache(void);
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync);
void coda_sysctl_init(void);
void coda_sysctl_clean(void);
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 2bdbcc11b37..2849f41e72a 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -100,11 +100,11 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_mode != (u_short) -1)
inode->i_mode = attr->va_mode | inode_type;
if (attr->va_uid != -1)
- inode->i_uid = (uid_t) attr->va_uid;
+ inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid);
if (attr->va_gid != -1)
- inode->i_gid = (gid_t) attr->va_gid;
+ inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid);
if (attr->va_nlink != -1)
- inode->i_nlink = attr->va_nlink;
+ set_nlink(inode, attr->va_nlink);
if (attr->va_size != -1)
inode->i_size = attr->va_size;
if (attr->va_size != -1)
@@ -171,10 +171,10 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
vattr->va_mode = iattr->ia_mode;
}
if ( valid & ATTR_UID ) {
- vattr->va_uid = (vuid_t) iattr->ia_uid;
+ vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
}
if ( valid & ATTR_GID ) {
- vattr->va_gid = (vgid_t) iattr->ia_gid;
+ vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
}
if ( valid & ATTR_SIZE ) {
vattr->va_size = iattr->ia_size;
diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
index 9b0c5323890..d42b725b1d2 100644
--- a/fs/coda/coda_linux.h
+++ b/fs/coda/coda_linux.h
@@ -12,6 +12,12 @@
#ifndef _LINUX_CODA_FS
#define _LINUX_CODA_FS
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/mm.h>
@@ -39,8 +45,8 @@ extern const struct file_operations coda_ioctl_operations;
/* operations shared over more than one file */
int coda_open(struct inode *i, struct file *f);
int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask, unsigned int flags);
-int coda_revalidate_inode(struct dentry *);
+int coda_permission(struct inode *inode, int mask);
+int coda_revalidate_inode(struct inode *);
int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *);
@@ -59,12 +65,11 @@ void coda_sysctl_clean(void);
#define CODA_ALLOC(ptr, cast, size) do { \
if (size < PAGE_SIZE) \
- ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
+ ptr = kzalloc((unsigned long) size, GFP_KERNEL); \
else \
- ptr = (cast)vmalloc((unsigned long) size); \
+ ptr = (cast)vzalloc((unsigned long) size); \
if (!ptr) \
- printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
- else memset( ptr, 0, size ); \
+ pr_warn("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
} while (0)
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 2b8dae4d121..cd8a63238b1 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -30,28 +30,27 @@
#include "coda_int.h"
/* dir inode-ops */
-static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
+static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl);
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags);
static int coda_link(struct dentry *old_dentry, struct inode *dir_inode,
struct dentry *entry);
static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
static int coda_symlink(struct inode *dir_inode, struct dentry *entry,
const char *symname);
-static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
+static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, umode_t mode);
static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry);
/* dir file-ops */
-static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
+static int coda_readdir(struct file *file, struct dir_context *ctx);
/* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
static int coda_dentry_delete(const struct dentry *);
/* support routines */
-static int coda_venus_readdir(struct file *coda_file, void *buf,
- filldir_t filldir);
+static int coda_venus_readdir(struct file *, struct dir_context *);
/* same as fs/bad_inode.c */
static int coda_return_EIO(void)
@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
const struct file_operations coda_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
- .readdir = coda_readdir,
+ .iterate = coda_readdir,
.open = coda_open,
.release = coda_release,
.fsync = coda_fsync,
@@ -94,49 +93,46 @@ const struct file_operations coda_dir_operations = {
/* inode operations for directories */
/* access routines: lookup, readlink, permission */
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags)
{
- struct inode *inode = NULL;
- struct CodaFid resfid = { { 0, } };
- int type = 0;
- int error = 0;
+ struct super_block *sb = dir->i_sb;
const char *name = entry->d_name.name;
size_t length = entry->d_name.len;
+ struct inode *inode;
+ int type = 0;
if (length > CODA_MAXNAMLEN) {
- printk(KERN_ERR "name too long: lookup, %s (%*s)\n",
+ pr_err("name too long: lookup, %s (%*s)\n",
coda_i2s(dir), (int)length, name);
return ERR_PTR(-ENAMETOOLONG);
}
/* control object, create inode on the fly */
if (coda_isroot(dir) && coda_iscontrol(name, length)) {
- error = coda_cnode_makectl(&inode, dir->i_sb);
+ inode = coda_cnode_makectl(sb);
type = CODA_NOCACHE;
- goto exit;
+ } else {
+ struct CodaFid fid = { { 0, } };
+ int error = venus_lookup(sb, coda_i2f(dir), name, length,
+ &type, &fid);
+ inode = !error ? coda_cnode_make(&fid, sb) : ERR_PTR(error);
}
- error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
- &type, &resfid);
- if (!error)
- error = coda_cnode_make(&inode, &resfid, dir->i_sb);
-
- if (error && error != -ENOENT)
- return ERR_PTR(error);
-
-exit:
- if (inode && (type & CODA_NOCACHE))
+ if (!IS_ERR(inode) && (type & CODA_NOCACHE))
coda_flag_inode(inode, C_VATTR | C_PURGE);
+ if (inode == ERR_PTR(-ENOENT))
+ inode = NULL;
+
return d_splice_alias(inode, entry);
}
-int coda_permission(struct inode *inode, int mask, unsigned int flags)
+int coda_permission(struct inode *inode, int mask)
{
int error;
- if (flags & IPERM_FLAG_RCU)
+ if (mask & MAY_NOT_BLOCK)
return -ECHILD;
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
@@ -191,7 +187,7 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
}
/* creation routines: create, mknod, mkdir, link, symlink */
-static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
+static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, bool excl)
{
int error;
const char *name=de->d_name.name;
@@ -223,7 +219,7 @@ err_out:
return error;
}
-static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+static int coda_mkdir(struct inode *dir, struct dentry *de, umode_t mode)
{
struct inode *inode;
struct coda_vattr attrs;
@@ -340,7 +336,7 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
if (!error) {
/* VFS may delete the child */
if (de->d_inode)
- de->d_inode->i_nlink = 0;
+ clear_nlink(de->d_inode);
/* fix the link count of the parent */
coda_dir_drop_nlink(dir);
@@ -381,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
/* file operations for directories */
-static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
{
struct coda_file_info *cfi;
struct file *host_file;
@@ -391,33 +387,19 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op)
- return -ENOTDIR;
-
- if (host_file->f_op->readdir)
- {
- /* potemkin case: we were handed a directory inode.
- * We can't use vfs_readdir because we have to keep the file
- * position in sync between the coda_file and the host_file.
- * and as such we need grab the inode mutex. */
- struct inode *host_inode = host_file->f_path.dentry->d_inode;
-
+ if (host_file->f_op->iterate) {
+ struct inode *host_inode = file_inode(host_file);
mutex_lock(&host_inode->i_mutex);
- host_file->f_pos = coda_file->f_pos;
-
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
- ret = host_file->f_op->readdir(host_file, buf, filldir);
+ ret = host_file->f_op->iterate(host_file, ctx);
file_accessed(host_file);
}
-
- coda_file->f_pos = host_file->f_pos;
mutex_unlock(&host_inode->i_mutex);
+ return ret;
}
- else /* Venus: we must read Venus dirents from a file */
- ret = coda_venus_readdir(coda_file, buf, filldir);
-
- return ret;
+ /* Venus: we must read Venus dirents from a file */
+ return coda_venus_readdir(coda_file, ctx);
}
static inline unsigned int CDT2DT(unsigned char cdt)
@@ -440,17 +422,14 @@ static inline unsigned int CDT2DT(unsigned char cdt)
}
/* support routines */
-static int coda_venus_readdir(struct file *coda_file, void *buf,
- filldir_t filldir)
+static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
{
- int result = 0; /* # of entries returned */
struct coda_file_info *cfi;
struct coda_inode_info *cii;
struct file *host_file;
struct dentry *de;
struct venus_dirent *vdir;
- unsigned long vdir_size =
- (unsigned long)(&((struct venus_dirent *)0)->d_name);
+ unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
unsigned int type;
struct qstr name;
ino_t ino;
@@ -466,42 +445,31 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
if (!vdir) return -ENOMEM;
- if (coda_file->f_pos == 0) {
- ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
- if (ret < 0)
- goto out;
- result++;
- coda_file->f_pos++;
- }
- if (coda_file->f_pos == 1) {
- ret = filldir(buf, "..", 2, 1, de->d_parent->d_inode->i_ino, DT_DIR);
- if (ret < 0)
- goto out;
- result++;
- coda_file->f_pos++;
- }
+ if (!dir_emit_dots(coda_file, ctx))
+ goto out;
+
while (1) {
/* read entries from the directory file */
- ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,
+ ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
sizeof(*vdir));
if (ret < 0) {
- printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
- coda_f2s(&cii->c_fid), ret);
+ pr_err("%s: read dir %s failed %d\n",
+ __func__, coda_f2s(&cii->c_fid), ret);
break;
}
if (ret == 0) break; /* end of directory file reached */
/* catch truncated reads */
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
- printk(KERN_ERR "coda readdir: short read on %s\n",
- coda_f2s(&cii->c_fid));
+ pr_err("%s: short read on %s\n",
+ __func__, coda_f2s(&cii->c_fid));
ret = -EBADF;
break;
}
/* validate whether the directory file actually makes sense */
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
- printk(KERN_ERR "coda readdir: invalid dir %s\n",
- coda_f2s(&cii->c_fid));
+ pr_err("%s: invalid dir %s\n",
+ __func__, coda_f2s(&cii->c_fid));
ret = -EBADF;
break;
}
@@ -511,41 +479,32 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
/* Make sure we skip '.' and '..', we already got those */
if (name.name[0] == '.' && (name.len == 1 ||
- (vdir->d_name[1] == '.' && name.len == 2)))
+ (name.name[1] == '.' && name.len == 2)))
vdir->d_fileno = name.len = 0;
/* skip null entries */
if (vdir->d_fileno && name.len) {
- /* try to look up this entry in the dcache, that way
- * userspace doesn't have to worry about breaking
- * getcwd by having mismatched inode numbers for
- * internal volume mountpoints. */
- ino = find_inode_number(de, &name);
- if (!ino) ino = vdir->d_fileno;
-
+ ino = vdir->d_fileno;
type = CDT2DT(vdir->d_type);
- ret = filldir(buf, name.name, name.len,
- coda_file->f_pos, ino, type);
- /* failure means no space for filling in this round */
- if (ret < 0) break;
- result++;
+ if (!dir_emit(ctx, name.name, name.len, ino, type))
+ break;
}
/* we'll always have progress because d_reclen is unsigned and
* we've already established it is non-zero. */
- coda_file->f_pos += vdir->d_reclen;
+ ctx->pos += vdir->d_reclen;
}
out:
kfree(vdir);
- return result ? result : ret;
+ return 0;
}
/* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
{
struct inode *inode;
struct coda_inode_info *cii;
- if (nd->flags & LOOKUP_RCU)
+ if (flags & LOOKUP_RCU)
return -ECHILD;
inode = de->d_inode;
@@ -564,7 +523,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
if (cii->c_flags & C_FLUSH)
coda_flag_inode_children(inode, C_FLUSH);
- if (de->d_count > 1)
+ if (d_count(de) > 1)
/* pretend it's valid, but don't change the flags */
goto out;
@@ -604,13 +563,12 @@ static int coda_dentry_delete(const struct dentry * dentry)
* cache manager Venus issues a downcall to the kernel when this
* happens
*/
-int coda_revalidate_inode(struct dentry *dentry)
+int coda_revalidate_inode(struct inode *inode)
{
struct coda_vattr attr;
int error;
int old_mode;
ino_t old_ino;
- struct inode *inode = dentry->d_inode;
struct coda_inode_info *cii = ITOC(inode);
if (!cii->c_flags)
@@ -631,8 +589,8 @@ int coda_revalidate_inode(struct dentry *dentry)
coda_vattr_to_iattr(inode, &attr);
if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
- printk("Coda: inode %ld, fid %s changed type!\n",
- inode->i_ino, coda_f2s(&(cii->c_fid)));
+ pr_warn("inode %ld, fid %s changed type!\n",
+ inode->i_ino, coda_f2s(&(cii->c_fid)));
}
/* the following can happen when a local fid is replaced
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 0433057be33..9e83b779021 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -36,7 +36,7 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op || !host_file->f_op->read)
+ if (!host_file->f_op->read)
return -EINVAL;
return host_file->f_op->read(host_file, buf, count, ppos);
@@ -66,7 +66,7 @@ coda_file_splice_read(struct file *coda_file, loff_t *ppos,
static ssize_t
coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *host_inode, *coda_inode = coda_file->f_path.dentry->d_inode;
+ struct inode *host_inode, *coda_inode = file_inode(coda_file);
struct coda_file_info *cfi;
struct file *host_file;
ssize_t ret;
@@ -75,10 +75,11 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op || !host_file->f_op->write)
+ if (!host_file->f_op->write)
return -EINVAL;
- host_inode = host_file->f_path.dentry->d_inode;
+ host_inode = file_inode(host_file);
+ file_start_write(host_file);
mutex_lock(&coda_inode->i_mutex);
ret = host_file->f_op->write(host_file, buf, count, ppos);
@@ -87,6 +88,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC;
mutex_unlock(&coda_inode->i_mutex);
+ file_end_write(host_file);
return ret;
}
@@ -103,11 +105,11 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op || !host_file->f_op->mmap)
+ if (!host_file->f_op->mmap)
return -ENODEV;
- coda_inode = coda_file->f_path.dentry->d_inode;
- host_inode = host_file->f_path.dentry->d_inode;
+ coda_inode = file_inode(coda_file);
+ host_inode = file_inode(host_file);
cii = ITOC(coda_inode);
spin_lock(&cii->c_lock);
@@ -178,7 +180,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
coda_flags, coda_file->f_cred->fsuid);
- host_inode = cfi->cfi_container->f_path.dentry->d_inode;
+ host_inode = file_inode(cfi->cfi_container);
cii = ITOC(coda_inode);
/* did we mmap this file? */
@@ -199,10 +201,10 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
return 0;
}
-int coda_fsync(struct file *coda_file, int datasync)
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync)
{
struct file *host_file;
- struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
+ struct inode *coda_inode = file_inode(coda_file);
struct coda_file_info *cfi;
int err;
@@ -210,6 +212,11 @@ int coda_fsync(struct file *coda_file, int datasync)
S_ISLNK(coda_inode->i_mode)))
return -EINVAL;
+ err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end);
+ if (err)
+ return err;
+ mutex_lock(&coda_inode->i_mutex);
+
cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
@@ -217,6 +224,7 @@ int coda_fsync(struct file *coda_file, int datasync)
err = vfs_fsync(host_file, datasync);
if (!err && !datasync)
err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
+ mutex_unlock(&coda_inode->i_mutex);
return err;
}
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 871b2771546..fe3afb2de88 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -20,8 +20,8 @@
#include <linux/file.h>
#include <linux/vfs.h>
#include <linux/slab.h>
+#include <linux/pid_namespace.h>
-#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
@@ -49,7 +49,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
return NULL;
memset(&ei->c_fid, 0, sizeof(struct CodaFid));
ei->c_flags = 0;
- ei->c_uid = 0;
+ ei->c_uid = GLOBAL_ROOT_UID;
ei->c_cached_perm = 0;
spin_lock_init(&ei->c_lock);
return &ei->vfs_inode;
@@ -58,7 +58,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
static void coda_i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
- INIT_LIST_HEAD(&inode->i_dentry);
kmem_cache_free(coda_inode_cachep, ITOC(inode));
}
@@ -74,7 +73,7 @@ static void init_once(void *foo)
inode_init_once(&ei->vfs_inode);
}
-int coda_init_inodecache(void)
+int __init coda_init_inodecache(void)
{
coda_inode_cachep = kmem_cache_create("coda_inode_cache",
sizeof(struct coda_inode_info),
@@ -87,11 +86,17 @@ int coda_init_inodecache(void)
void coda_destroy_inodecache(void)
{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
kmem_cache_destroy(coda_inode_cachep);
}
static int coda_remount(struct super_block *sb, int *flags, char *data)
{
+ sync_filesystem(sb);
*flags |= MS_NOATIME;
return 0;
}
@@ -109,43 +114,41 @@ static const struct super_operations coda_super_operations =
static int get_device_index(struct coda_mount_data *data)
{
- struct file *file;
+ struct fd f;
struct inode *inode;
int idx;
- if(data == NULL) {
- printk("coda_read_super: Bad mount data\n");
+ if (data == NULL) {
+ pr_warn("%s: Bad mount data\n", __func__);
return -1;
}
- if(data->version != CODA_MOUNT_VERSION) {
- printk("coda_read_super: Bad mount version\n");
+ if (data->version != CODA_MOUNT_VERSION) {
+ pr_warn("%s: Bad mount version\n", __func__);
return -1;
}
- file = fget(data->fd);
- inode = NULL;
- if(file)
- inode = file->f_path.dentry->d_inode;
-
- if(!inode || !S_ISCHR(inode->i_mode) ||
- imajor(inode) != CODA_PSDEV_MAJOR) {
- if(file)
- fput(file);
-
- printk("coda_read_super: Bad file\n");
- return -1;
+ f = fdget(data->fd);
+ if (!f.file)
+ goto Ebadf;
+ inode = file_inode(f.file);
+ if (!S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) {
+ fdput(f);
+ goto Ebadf;
}
idx = iminor(inode);
- fput(file);
+ fdput(f);
- if(idx < 0 || idx >= MAX_CODADEVS) {
- printk("coda_read_super: Bad minor number\n");
+ if (idx < 0 || idx >= MAX_CODADEVS) {
+ pr_warn("%s: Bad minor number\n", __func__);
return -1;
}
return idx;
+Ebadf:
+ pr_warn("%s: Bad file\n", __func__);
+ return -1;
}
static int coda_fill_super(struct super_block *sb, void *data, int silent)
@@ -156,25 +159,28 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
int error;
int idx;
+ if (task_active_pid_ns(current) != &init_pid_ns)
+ return -EINVAL;
+
idx = get_device_index((struct coda_mount_data *) data);
/* Ignore errors in data, for backward compatibility */
if(idx == -1)
idx = 0;
- printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
+ pr_info("%s: device index: %i\n", __func__, idx);
vc = &coda_comms[idx];
mutex_lock(&vc->vc_mutex);
if (!vc->vc_inuse) {
- printk("coda_read_super: No pseudo device\n");
+ pr_warn("%s: No pseudo device\n", __func__);
error = -EINVAL;
goto unlock_out;
}
if (vc->vc_sb) {
- printk("coda_read_super: Device already mounted\n");
+ pr_warn("%s: Device already mounted\n", __func__);
error = -EBUSY;
goto unlock_out;
}
@@ -198,22 +204,24 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
/* get root fid from Venus: this needs the root inode */
error = venus_rootfid(sb, &fid);
if ( error ) {
- printk("coda_read_super: coda_get_rootfid failed with %d\n",
- error);
+ pr_warn("%s: coda_get_rootfid failed with %d\n",
+ __func__, error);
goto error;
}
- printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
+ pr_info("%s: rootfid is %s\n", __func__, coda_f2s(&fid));
/* make root inode */
- error = coda_cnode_make(&root, &fid, sb);
- if ( error || !root ) {
- printk("Failure of coda_cnode_make for root: error %d\n", error);
- goto error;
+ root = coda_cnode_make(&fid, sb);
+ if (IS_ERR(root)) {
+ error = PTR_ERR(root);
+ pr_warn("Failure of coda_cnode_make for root: error %d\n",
+ error);
+ goto error;
}
- printk("coda_read_super: rootinode is %ld dev %s\n",
- root->i_ino, root->i_sb->s_id);
- sb->s_root = d_alloc_root(root);
+ pr_info("%s: rootinode is %ld dev %s\n",
+ __func__, root->i_ino, root->i_sb->s_id);
+ sb->s_root = d_make_root(root);
if (!sb->s_root) {
error = -EINVAL;
goto error;
@@ -221,9 +229,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
return 0;
error:
- if (root)
- iput(root);
-
mutex_lock(&vc->vc_mutex);
bdi_destroy(&vc->bdi);
vc->vc_sb = NULL;
@@ -242,19 +247,19 @@ static void coda_put_super(struct super_block *sb)
sb->s_fs_info = NULL;
mutex_unlock(&vcp->vc_mutex);
- printk("Coda: Bye bye.\n");
+ pr_info("Bye bye.\n");
}
static void coda_evict_inode(struct inode *inode)
{
- truncate_inode_pages(&inode->i_data, 0);
- end_writeback(inode);
+ truncate_inode_pages_final(&inode->i_data);
+ clear_inode(inode);
coda_cache_clear_inode(inode);
}
int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
- int err = coda_revalidate_inode(dentry);
+ int err = coda_revalidate_inode(dentry->d_inode);
if (!err)
generic_fillattr(dentry->d_inode, stat);
return err;
@@ -326,4 +331,5 @@ struct file_system_type coda_fs_type = {
.kill_sb = kill_anon_super,
.fs_flags = FS_BINARY_MOUNTDATA,
};
+MODULE_ALIAS_FS("coda");
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 6cbb3afb36d..3f5de96bbb5 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -24,7 +24,7 @@
#include "coda_linux.h"
/* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags);
+static int coda_ioctl_permission(struct inode *inode, int mask);
static long coda_pioctl(struct file *filp, unsigned int cmd,
unsigned long user_data);
@@ -41,10 +41,8 @@ const struct file_operations coda_ioctl_operations = {
};
/* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags)
+static int coda_ioctl_permission(struct inode *inode, int mask)
{
- if (flags & IPERM_FLAG_RCU)
- return -ECHILD;
return (mask & MAY_EXEC) ? -EACCES : 0;
}
@@ -54,7 +52,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
struct path path;
int error;
struct PioctlData data;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = file_inode(filp);
struct inode *target_inode = NULL;
struct coda_inode_info *cnp;
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 8f616e0e252..5c1e4242368 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -37,8 +37,8 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/device.h>
+#include <linux/pid_namespace.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/poll.h>
#include <asm/uaccess.h>
@@ -114,14 +114,14 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
int size = sizeof(*dcbuf);
if ( nbytes < sizeof(struct coda_out_hdr) ) {
- printk("coda_downcall opc %d uniq %d, not enough!\n",
- hdr.opcode, hdr.unique);
+ pr_warn("coda_downcall opc %d uniq %d, not enough!\n",
+ hdr.opcode, hdr.unique);
count = nbytes;
goto out;
}
if ( nbytes > size ) {
- printk("Coda: downcall opc %d, uniq %d, too much!",
- hdr.opcode, hdr.unique);
+ pr_warn("downcall opc %d, uniq %d, too much!",
+ hdr.opcode, hdr.unique);
nbytes = size;
}
CODA_ALLOC(dcbuf, union outputArgs *, nbytes);
@@ -136,7 +136,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
CODA_FREE(dcbuf, nbytes);
if (error) {
- printk("psdev_write: coda_downcall error: %d\n", error);
+ pr_warn("%s: coda_downcall error: %d\n",
+ __func__, error);
retval = error;
goto out;
}
@@ -157,16 +158,17 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
mutex_unlock(&vcp->vc_mutex);
if (!req) {
- printk("psdev_write: msg (%d, %d) not found\n",
- hdr.opcode, hdr.unique);
+ pr_warn("%s: msg (%d, %d) not found\n",
+ __func__, hdr.opcode, hdr.unique);
retval = -ESRCH;
goto out;
}
/* move data into response buffer. */
if (req->uc_outSize < nbytes) {
- printk("psdev_write: too much cnt: %d, cnt: %ld, opc: %d, uniq: %d.\n",
- req->uc_outSize, (long)nbytes, hdr.opcode, hdr.unique);
+ pr_warn("%s: too much cnt: %d, cnt: %ld, opc: %d, uniq: %d.\n",
+ __func__, req->uc_outSize, (long)nbytes,
+ hdr.opcode, hdr.unique);
nbytes = req->uc_outSize; /* don't have more space! */
}
if (copy_from_user(req->uc_data, buf, nbytes)) {
@@ -240,8 +242,8 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
/* Move the input args into userspace */
count = req->uc_inSize;
if (nbytes < req->uc_inSize) {
- printk ("psdev_read: Venus read %ld bytes of %d in message\n",
- (long)nbytes, req->uc_inSize);
+ pr_warn("%s: Venus read %ld bytes of %d in message\n",
+ __func__, (long)nbytes, req->uc_inSize);
count = nbytes;
}
@@ -267,6 +269,12 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
struct venus_comm *vcp;
int idx, err;
+ if (task_active_pid_ns(current) != &init_pid_ns)
+ return -EINVAL;
+
+ if (current_user_ns() != &init_user_ns)
+ return -EINVAL;
+
idx = iminor(inode);
if (idx < 0 || idx >= MAX_CODADEVS)
return -ENODEV;
@@ -299,7 +307,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
struct upc_req *req, *tmp;
if (!vcp || !vcp->vc_inuse ) {
- printk("psdev_release: Not open.\n");
+ pr_warn("%s: Not open.\n", __func__);
return -1;
}
@@ -348,8 +356,8 @@ static int init_coda_psdev(void)
{
int i, err = 0;
if (register_chrdev(CODA_PSDEV_MAJOR, "coda", &coda_psdev_fops)) {
- printk(KERN_ERR "coda_psdev: unable to get major %d\n",
- CODA_PSDEV_MAJOR);
+ pr_err("%s: unable to get major %d\n",
+ __func__, CODA_PSDEV_MAJOR);
return -EIO;
}
coda_psdev_class = class_create(THIS_MODULE, "coda");
@@ -387,13 +395,13 @@ static int __init init_coda(void)
goto out2;
status = init_coda_psdev();
if ( status ) {
- printk("Problem (%d) in init_coda_psdev\n", status);
+ pr_warn("Problem (%d) in init_coda_psdev\n", status);
goto out1;
}
status = register_filesystem(&coda_fs_type);
if (status) {
- printk("coda: failed to register filesystem!\n");
+ pr_warn("failed to register filesystem!\n");
goto out;
}
return 0;
@@ -414,9 +422,8 @@ static void __exit exit_coda(void)
int err, i;
err = unregister_filesystem(&coda_fs_type);
- if ( err != 0 ) {
- printk("coda: failed to unregister filesystem\n");
- }
+ if (err != 0)
+ pr_warn("failed to unregister filesystem\n");
for (i = 0; i < MAX_CODADEVS; i++)
device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
class_destroy(coda_psdev_class);
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index c6405ce3c50..34218a8a28c 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -13,9 +13,8 @@
#ifdef CONFIG_SYSCTL
static struct ctl_table_header *fs_table_header;
-#endif
-static ctl_table coda_table[] = {
+static struct ctl_table coda_table[] = {
{
.procname = "timeout",
.data = &coda_timeout,
@@ -40,8 +39,7 @@ static ctl_table coda_table[] = {
{}
};
-#ifdef CONFIG_SYSCTL
-static ctl_table fs_table[] = {
+static struct ctl_table fs_table[] = {
{
.procname = "coda",
.mode = 0555,
@@ -49,22 +47,27 @@ static ctl_table fs_table[] = {
},
{}
};
-#endif
void coda_sysctl_init(void)
{
-#ifdef CONFIG_SYSCTL
if ( !fs_table_header )
fs_table_header = register_sysctl_table(fs_table);
-#endif
}
void coda_sysctl_clean(void)
{
-#ifdef CONFIG_SYSCTL
if ( fs_table_header ) {
unregister_sysctl_table(fs_table_header);
fs_table_header = NULL;
}
-#endif
}
+
+#else
+void coda_sysctl_init(void)
+{
+}
+
+void coda_sysctl_clean(void)
+{
+}
+#endif
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 9727e0c5257..21fcf8dcb9c 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -14,7 +14,6 @@
* improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
*/
-#include <asm/system.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -51,9 +50,9 @@ static void *alloc_upcall(int opcode, int size)
return ERR_PTR(-ENOMEM);
inp->ih.opcode = opcode;
- inp->ih.pid = current->pid;
- inp->ih.pgid = task_pgrp_nr(current);
- inp->ih.uid = current_fsuid();
+ inp->ih.pid = task_pid_nr_ns(current, &init_pid_ns);
+ inp->ih.pgid = task_pgrp_nr_ns(current, &init_pid_ns);
+ inp->ih.uid = from_kuid(&init_user_ns, current_fsuid());
return (void*)inp;
}
@@ -158,7 +157,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
}
int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
- vuid_t uid)
+ kuid_t uid)
{
union inputArgs *inp;
union outputArgs *outp;
@@ -167,7 +166,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
insize = SIZE(release);
UPARG(CODA_CLOSE);
- inp->ih.uid = uid;
+ inp->ih.uid = from_kuid(&init_user_ns, uid);
inp->coda_close.VFid = *fid;
inp->coda_close.flags = flags;
@@ -509,8 +508,8 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
/* get the data out of user space */
- if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
- data->vi.in, data->vi.in_size) ) {
+ if (copy_from_user((char *)inp + (long)inp->coda_ioctl.data,
+ data->vi.in, data->vi.in_size)) {
error = -EINVAL;
goto exit;
}
@@ -519,8 +518,8 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
&outsize, inp);
if (error) {
- printk("coda_pioctl: Venus returns: %d for %s\n",
- error, coda_f2s(fid));
+ pr_warn("%s: Venus returns: %d for %s\n",
+ __func__, error, coda_f2s(fid));
goto exit;
}
@@ -676,7 +675,7 @@ static int coda_upcall(struct venus_comm *vcp,
mutex_lock(&vcp->vc_mutex);
if (!vcp->vc_inuse) {
- printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
+ pr_notice("Venus dead, not sending upcall\n");
error = -ENXIO;
goto exit;
}
@@ -726,7 +725,7 @@ static int coda_upcall(struct venus_comm *vcp,
error = -EINTR;
if ((req->uc_flags & CODA_REQ_ABORT) || !signal_pending(current)) {
- printk(KERN_WARNING "coda: Unexpected interruption.\n");
+ pr_warn("Unexpected interruption.\n");
goto exit;
}
@@ -736,7 +735,7 @@ static int coda_upcall(struct venus_comm *vcp,
/* Venus saw the upcall, make sure we can send interrupt signal */
if (!vcp->vc_inuse) {
- printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
+ pr_info("Venus dead, not sending signal.\n");
goto exit;
}