summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-06-21 16:21:20 -0700
committerTony Luck <tony.luck@intel.com>2005-06-21 16:21:20 -0700
commit29516d75a0b09e0a0328dd55c98a342515c9615a (patch)
tree4b03326311958ad6de82653a1caf289ad8c38538 /fs
parent4ea78729b8dbfc400fe165a57b90a394a7275a54 (diff)
parent4a4f8fdba6f5a34ca90f426021e17491a30202da (diff)
Auto merge with /home/aegl/GIT/linus
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig50
-rw-r--r--fs/coda/psdev.c18
-rw-r--r--fs/debugfs/file.c67
-rw-r--r--fs/jfs/acl.c6
-rw-r--r--fs/jfs/file.c9
-rw-r--r--fs/jfs/inode.c11
-rw-r--r--fs/jfs/jfs_debug.c10
-rw-r--r--fs/jfs/jfs_debug.h15
-rw-r--r--fs/jfs/jfs_dmap.c9
-rw-r--r--fs/jfs/jfs_dtree.c3
-rw-r--r--fs/jfs/jfs_extent.c7
-rw-r--r--fs/jfs/jfs_imap.c6
-rw-r--r--fs/jfs/jfs_inode.c1
-rw-r--r--fs/jfs/jfs_inode.h19
-rw-r--r--fs/jfs/jfs_logmgr.c14
-rw-r--r--fs/jfs/jfs_logmgr.h2
-rw-r--r--fs/jfs/jfs_metapage.c6
-rw-r--r--fs/jfs/jfs_metapage.h6
-rw-r--r--fs/jfs/jfs_superblock.h11
-rw-r--r--fs/jfs/jfs_txnmgr.c40
-rw-r--r--fs/jfs/jfs_txnmgr.h52
-rw-r--r--fs/jfs/namei.c28
-rw-r--r--fs/jfs/super.c37
-rw-r--r--fs/jfs/symlink.c3
-rw-r--r--fs/jfs/xattr.c6
-rw-r--r--fs/libfs.c100
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/dir.c26
-rw-r--r--fs/sysfs/file.c6
-rw-r--r--fs/sysfs/inode.c102
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h4
33 files changed, 365 insertions, 325 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a4ad4bb7a5..178e27494b7 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -741,56 +741,6 @@ config SYSFS
Designers of embedded systems may wish to say N here to conserve space.
-config DEVFS_FS
- bool "/dev file system support (OBSOLETE)"
- depends on EXPERIMENTAL
- help
- This is support for devfs, a virtual file system (like /proc) which
- provides the file system interface to device drivers, normally found
- in /dev. Devfs does not depend on major and minor number
- allocations. Device drivers register entries in /dev which then
- appear automatically, which means that the system administrator does
- not have to create character and block special device files in the
- /dev directory using the mknod command (or MAKEDEV script) anymore.
-
- This is work in progress. If you want to use this, you *must* read
- the material in <file:Documentation/filesystems/devfs/>, especially
- the file README there.
-
- Note that devfs no longer manages /dev/pts! If you are using UNIX98
- ptys, you will also need to mount the /dev/pts filesystem (devpts).
-
- Note that devfs has been obsoleted by udev,
- <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
- It has been stripped down to a bare minimum and is only provided for
- legacy installations that use its naming scheme which is
- unfortunately different from the names normal Linux installations
- use.
-
- If unsure, say N.
-
-config DEVFS_MOUNT
- bool "Automatically mount at boot"
- depends on DEVFS_FS
- help
- This option appears if you have CONFIG_DEVFS_FS enabled. Setting
- this to 'Y' will make the kernel automatically mount devfs onto /dev
- when the system is booted, before the init thread is started.
- You can override this with the "devfs=nomount" boot option.
-
- If unsure, say N.
-
-config DEVFS_DEBUG
- bool "Debug devfs"
- depends on DEVFS_FS
- help
- If you say Y here, then the /dev file system code will generate
- debugging messages. See the file
- <file:Documentation/filesystems/devfs/boot-options> for more
- details.
-
- If unsure, say N.
-
config DEVPTS_FS_XATTR
bool "/dev/pts Extended Attributes"
depends on UNIX98_PTYS
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ef001a9313e..3d1cce3653b 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -61,7 +61,7 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
struct venus_comm coda_comms[MAX_CODADEVS];
-static struct class_simple *coda_psdev_class;
+static struct class *coda_psdev_class;
/*
* Device operations
@@ -363,14 +363,14 @@ static int init_coda_psdev(void)
CODA_PSDEV_MAJOR);
return -EIO;
}
- coda_psdev_class = class_simple_create(THIS_MODULE, "coda");
+ coda_psdev_class = class_create(THIS_MODULE, "coda");
if (IS_ERR(coda_psdev_class)) {
err = PTR_ERR(coda_psdev_class);
goto out_chrdev;
}
devfs_mk_dir ("coda");
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
+ class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
NULL, "cfs%d", i);
err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
@@ -382,8 +382,8 @@ static int init_coda_psdev(void)
out_class:
for (i = 0; i < MAX_CODADEVS; i++)
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
- class_simple_destroy(coda_psdev_class);
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
+ class_destroy(coda_psdev_class);
out_chrdev:
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
out:
@@ -425,10 +425,10 @@ static int __init init_coda(void)
return 0;
out:
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
devfs_remove("coda/%d", i);
}
- class_simple_destroy(coda_psdev_class);
+ class_destroy(coda_psdev_class);
devfs_remove("coda");
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
@@ -447,10 +447,10 @@ static void __exit exit_coda(void)
printk("coda: failed to unregister filesystem\n");
}
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
devfs_remove("coda/%d", i);
}
- class_simple_destroy(coda_psdev_class);
+ class_destroy(coda_psdev_class);
devfs_remove("coda");
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 548556ff250..efc97d9b786 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -45,44 +45,15 @@ struct file_operations debugfs_file_operations = {
.open = default_open,
};
-#define simple_type(type, format, temptype, strtolfn) \
-static ssize_t read_file_##type(struct file *file, char __user *user_buf, \
- size_t count, loff_t *ppos) \
-{ \
- char buf[32]; \
- type *val = file->private_data; \
- \
- snprintf(buf, sizeof(buf), format "\n", *val); \
- return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\
-} \
-static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
- size_t count, loff_t *ppos) \
-{ \
- char *endp; \
- char buf[32]; \
- int buf_size; \
- type *val = file->private_data; \
- temptype tmp; \
- \
- memset(buf, 0x00, sizeof(buf)); \
- buf_size = min(count, (sizeof(buf)-1)); \
- if (copy_from_user(buf, user_buf, buf_size)) \
- return -EFAULT; \
- \
- tmp = strtolfn(buf, &endp, 0); \
- if ((endp == buf) || ((type)tmp != tmp)) \
- return -EINVAL; \
- *val = tmp; \
- return count; \
-} \
-static struct file_operations fops_##type = { \
- .read = read_file_##type, \
- .write = write_file_##type, \
- .open = default_open, \
-};
-simple_type(u8, "%c", unsigned long, simple_strtoul);
-simple_type(u16, "%hi", unsigned long, simple_strtoul);
-simple_type(u32, "%i", unsigned long, simple_strtoul);
+static void debugfs_u8_set(void *data, u64 val)
+{
+ *(u8 *)data = val;
+}
+static u64 debugfs_u8_get(void *data)
+{
+ return *(u8 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
/**
* debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
@@ -116,6 +87,16 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_u8);
+static void debugfs_u16_set(void *data, u64 val)
+{
+ *(u16 *)data = val;
+}
+static u64 debugfs_u16_get(void *data)
+{
+ return *(u16 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
+
/**
* debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
*
@@ -148,6 +129,16 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_u16);
+static void debugfs_u32_set(void *data, u64 val)
+{
+ *(u32 *)data = val;
+}
+static u64 debugfs_u32_get(void *data)
+{
+ return *(u32 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
+
/**
* debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
*
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8d2a9ab981d..30a2bf9eeda 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -70,8 +70,7 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
if (!IS_ERR(acl))
*p_acl = posix_acl_dup(acl);
}
- if (value)
- kfree(value);
+ kfree(value);
return acl;
}
@@ -112,8 +111,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
}
rc = __jfs_setxattr(inode, ea_name, value, size, 0);
out:
- if (value)
- kfree(value);
+ kfree(value);
if (!rc) {
if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index a87b06fa8ff..c2c19c9ed9a 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,16 +19,13 @@
#include <linux/fs.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_dmap.h"
#include "jfs_txnmgr.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
#include "jfs_debug.h"
-
-extern int jfs_commit_inode(struct inode *, int);
-extern void jfs_truncate(struct inode *);
-
int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct inode *inode = dentry->d_inode;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 24a689179af..2137138c59b 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -23,6 +23,7 @@
#include <linux/pagemap.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
#include "jfs_extent.h"
@@ -30,14 +31,6 @@
#include "jfs_debug.h"
-extern struct inode_operations jfs_dir_inode_operations;
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_dir_operations;
-extern struct file_operations jfs_file_operations;
-struct address_space_operations jfs_aops;
-extern int freeZeroLink(struct inode *);
-
void jfs_read_inode(struct inode *inode)
{
if (diRead(inode)) {
@@ -136,7 +129,7 @@ void jfs_delete_inode(struct inode *inode)
jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
if (test_cflag(COMMIT_Freewmap, inode))
- freeZeroLink(inode);
+ jfs_free_zero_link(inode);
diFree(inode);
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 91a0a889ebc..4caea6b43b9 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -58,8 +58,6 @@ void dump_mem(char *label, void *data, int length)
static struct proc_dir_entry *base;
#ifdef CONFIG_JFS_DEBUG
-extern read_proc_t jfs_txanchor_read;
-
static int loglevel_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -97,14 +95,6 @@ static int loglevel_write(struct file *file, const char __user *buffer,
}
#endif
-
-#ifdef CONFIG_JFS_STATISTICS
-extern read_proc_t jfs_lmstats_read;
-extern read_proc_t jfs_txstats_read;
-extern read_proc_t jfs_xtstat_read;
-extern read_proc_t jfs_mpstat_read;
-#endif
-
static struct {
const char *name;
read_proc_t *read_fn;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index a38079ae1e0..ddffbbd4d95 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,7 +31,9 @@
* CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined
*/
#if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS))
- #define PROC_FS_JFS
+#define PROC_FS_JFS
+extern void jfs_proc_init(void);
+extern void jfs_proc_clean(void);
#endif
/*
@@ -65,8 +67,8 @@
extern int jfsloglevel;
-/* dump memory contents */
extern void dump_mem(char *label, void *data, int length);
+extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
/* information message: e.g., configuration, major event */
#define jfs_info(fmt, arg...) do { \
@@ -110,6 +112,11 @@ extern void dump_mem(char *label, void *data, int length);
* ----------
*/
#ifdef CONFIG_JFS_STATISTICS
+extern int jfs_lmstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_txstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_mpstat_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_xtstat_read(char *, char **, off_t, int, int *, void *);
+
#define INCREMENT(x) ((x)++)
#define DECREMENT(x) ((x)--)
#define HIGHWATERMARK(x,y) ((x) = max((x), (y)))
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 69007fd546e..cced2fed9d0 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -272,7 +272,6 @@ int dbMount(struct inode *ipbmap)
int dbUnmount(struct inode *ipbmap, int mounterror)
{
struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- int i;
if (!(mounterror || isReadOnly(ipbmap)))
dbSync(ipbmap);
@@ -282,14 +281,6 @@ int dbUnmount(struct inode *ipbmap, int mounterror)
*/
truncate_inode_pages(ipbmap->i_mapping, 0);
- /*
- * Sanity Check
- */
- for (i = 0; i < bmp->db_numag; i++)
- if (atomic_read(&bmp->db_active[i]))
- printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n",
- i, atomic_read(&bmp->db_active[i]));
-
/* free the memory for the in-memory bmap. */
kfree(bmp);
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac41f72d6d5..8676aee3ae4 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -2931,6 +2931,9 @@ static void add_missing_indices(struct inode *inode, s64 bn)
ASSERT(p->header.flag & BT_LEAF);
tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
+ if (BT_IS_ROOT(mp))
+ tlck->type |= tlckBTROOT;
+
dtlck = (struct dt_lock *) &tlck->lock;
stbl = DT_GETSTBL(p);
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 1953acb7926..4879603daa1 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
#include "jfs_extent.h"
@@ -33,12 +34,6 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
#endif
static s64 extRoundDown(s64 nb);
-/*
- * external references
- */
-extern int jfs_commit_inode(struct inode *, int);
-
-
#define DPD(a) (printk("(a): %d\n",(a)))
#define DPC(a) (printk("(a): %c\n",(a)))
#define DPL1(a) \
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 7acff2ce3c8..971af2977ef 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -47,6 +47,7 @@
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_dinode.h"
#include "jfs_dmap.h"
@@ -69,11 +70,6 @@
#define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno])
/*
- * external references
- */
-extern struct address_space_operations jfs_aops;
-
-/*
* forward references
*/
static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 84f2459b219..2af5efbfd06 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
#include "jfs_dinode.h"
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 3df91fbfe78..b54bac576cb 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2001
+ * Copyright (C) International Business Machines Corp., 2000-2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,5 +19,22 @@
#define _H_JFS_INODE
extern struct inode *ialloc(struct inode *, umode_t);
+extern int jfs_fsync(struct file *, struct dentry *, int);
+extern void jfs_read_inode(struct inode *);
+extern int jfs_commit_inode(struct inode *, int);
+extern int jfs_write_inode(struct inode*, int);
+extern void jfs_delete_inode(struct inode *);
+extern void jfs_dirty_inode(struct inode *);
+extern void jfs_truncate(struct inode *);
+extern void jfs_truncate_nolock(struct inode *, loff_t);
+extern void jfs_free_zero_link(struct inode *);
+extern struct dentry *jfs_get_parent(struct dentry *dentry);
+extern struct address_space_operations jfs_aops;
+extern struct inode_operations jfs_dir_inode_operations;
+extern struct file_operations jfs_dir_operations;
+extern struct inode_operations jfs_file_inode_operations;
+extern struct file_operations jfs_file_operations;
+extern struct inode_operations jfs_symlink_inode_operations;
+extern struct dentry_operations jfs_ci_dentry_operations;
#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index dfa1200daa6..7c8387ed419 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -71,6 +71,7 @@
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
+#include "jfs_superblock.h"
#include "jfs_txnmgr.h"
#include "jfs_debug.h"
@@ -167,14 +168,6 @@ static struct jfs_log *dummy_log = NULL;
static DECLARE_MUTEX(jfs_log_sem);
/*
- * external references
- */
-extern void txLazyUnlock(struct tblock * tblk);
-extern int jfs_stop_threads;
-extern struct completion jfsIOwait;
-extern int jfs_tlocks_low;
-
-/*
* forward references
*/
static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk,
@@ -1624,6 +1617,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
}
}
assert(list_empty(&log->cqueue));
+
+#ifdef CONFIG_JFS_DEBUG
if (!list_empty(&log->synclist)) {
struct logsyncblk *lp;
@@ -1638,9 +1633,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
dump_mem("orphan tblock", lp,
sizeof(struct tblock));
}
-// current->state = TASK_INTERRUPTIBLE;
-// schedule();
}
+#endif
//assert(list_empty(&log->synclist));
clear_bit(log_FLUSH, &log->flag);
}
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 51291fbc420..747114cd38b 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -507,6 +507,8 @@ extern int lmLogClose(struct super_block *sb);
extern int lmLogShutdown(struct jfs_log * log);
extern int lmLogInit(struct jfs_log * log);
extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
+extern int lmGroupCommit(struct jfs_log *, struct tblock *);
+extern int jfsIOWait(void *);
extern void jfs_flush_journal(struct jfs_log * log, int wait);
extern void jfs_syncpt(struct jfs_log *log);
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 41bf078dce0..6c5485d16c3 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
}
}
-static inline struct metapage *alloc_metapage(int gfp_mask)
+static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
{
return mempool_alloc(metapage_mempool, gfp_mask);
}
@@ -726,12 +726,12 @@ void force_metapage(struct metapage *mp)
page_cache_release(page);
}
-extern void hold_metapage(struct metapage *mp)
+void hold_metapage(struct metapage *mp)
{
lock_page(mp->page);
}
-extern void put_metapage(struct metapage *mp)
+void put_metapage(struct metapage *mp)
{
if (mp->count || mp->nohomeok) {
/* Someone else will release this */
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 991e9fb84c7..f0b7d3282b0 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -58,6 +58,8 @@ struct metapage {
#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
/* function prototypes */
+extern int metapage_init(void);
+extern void metapage_exit(void);
extern struct metapage *__get_metapage(struct inode *inode,
unsigned long lblock, unsigned int size,
int absolute, unsigned long new);
diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
index ab0566f70cf..fcf781bf31c 100644
--- a/fs/jfs/jfs_superblock.h
+++ b/fs/jfs/jfs_superblock.h
@@ -109,5 +109,16 @@ struct jfs_superblock {
extern int readSuper(struct super_block *, struct buffer_head **);
extern int updateSuper(struct super_block *, uint);
extern void jfs_error(struct super_block *, const char *, ...);
+extern int jfs_mount(struct super_block *);
+extern int jfs_mount_rw(struct super_block *, int);
+extern int jfs_umount(struct super_block *);
+extern int jfs_umount_rw(struct super_block *);
+
+extern int jfs_stop_threads;
+extern struct completion jfsIOwait;
+extern wait_queue_head_t jfs_IO_thread_wait;
+extern wait_queue_head_t jfs_commit_thread_wait;
+extern wait_queue_head_t jfs_sync_thread_wait;
+extern int jfs_extendfs(struct super_block *, s64, int);
#endif /*_H_JFS_SUPERBLOCK */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e93d01aa12c..8cbaaff1d5f 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -42,7 +42,6 @@
* hold on to mp+lock thru update of maps
*/
-
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
@@ -51,6 +50,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
#include "jfs_dinode.h"
@@ -109,7 +109,6 @@ static int TxLockHWM; /* High water mark for number of txLocks used */
static int TxLockVHWM; /* Very High water mark */
struct tlock *TxLock; /* transaction lock table */
-
/*
* transaction management lock
*/
@@ -149,7 +148,6 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
#define TXN_WAKEUP(event) wake_up_all(event)
-
/*
* statistics
*/
@@ -161,16 +159,6 @@ static struct {
int waitlock; /* 4: # of tlock wait */
} stattx;
-
-/*
- * external references
- */
-extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern int jfs_commit_inode(struct inode *, int);
-extern int jfs_stop_threads;
-
-extern struct completion jfsIOwait;
-
/*
* forward references
*/
@@ -358,7 +346,6 @@ void txExit(void)
TxBlock = NULL;
}
-
/*
* NAME: txBegin()
*
@@ -460,7 +447,6 @@ tid_t txBegin(struct super_block *sb, int flag)
return t;
}
-
/*
* NAME: txBeginAnon()
*
@@ -503,7 +489,6 @@ void txBeginAnon(struct super_block *sb)
TXN_UNLOCK();
}
-
/*
* txEnd()
*
@@ -592,7 +577,6 @@ wakeup:
TXN_WAKEUP(&TxAnchor.freewait);
}
-
/*
* txLock()
*
@@ -868,7 +852,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
return NULL;
}
-
/*
* NAME: txRelease()
*
@@ -908,7 +891,6 @@ static void txRelease(struct tblock * tblk)
TXN_UNLOCK();
}
-
/*
* NAME: txUnlock()
*
@@ -996,7 +978,6 @@ static void txUnlock(struct tblock * tblk)
}
}
-
/*
* txMaplock()
*
@@ -1069,7 +1050,6 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
return tlck;
}
-
/*
* txLinelock()
*
@@ -1103,8 +1083,6 @@ struct linelock *txLinelock(struct linelock * tlock)
return linelock;
}
-
-
/*
* transaction commit management
* -----------------------------
@@ -1373,7 +1351,6 @@ int txCommit(tid_t tid, /* transaction identifier */
return rc;
}
-
/*
* NAME: txLog()
*
@@ -1437,7 +1414,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
return rc;
}
-
/*
* diLog()
*
@@ -1465,7 +1441,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
if (tlck->type & tlckENTRY) {
/* log after-image for logredo(): */
lrd->type = cpu_to_le16(LOG_REDOPAGE);
-// *pxd = mp->cm_pxd;
PXDaddress(pxd, mp->index);
PXDlength(pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1552,7 +1527,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return rc;
}
-
/*
* dataLog()
*
@@ -1599,7 +1573,6 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return 0;
}
-
/*
* dtLog()
*
@@ -1639,7 +1612,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);
else
lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);
-// *pxd = mp->cm_pxd;
PXDaddress(pxd, mp->index);
PXDlength(pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1704,7 +1676,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return;
}
-
/*
* xtLog()
*
@@ -1760,7 +1731,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* applying the after-image to the meta-data page.
*/
lrd->type = cpu_to_le16(LOG_REDOPAGE);
-// *page_pxd = mp->cm_pxd;
PXDaddress(page_pxd, mp->index);
PXDlength(page_pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -2093,7 +2063,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return;
}
-
/*
* mapLog()
*
@@ -2180,7 +2149,6 @@ void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
}
-
/*
* txEA()
*
@@ -2233,7 +2201,6 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
}
}
-
/*
* txForce()
*
@@ -2300,7 +2267,6 @@ void txForce(struct tblock * tblk)
}
}
-
/*
* txUpdateMap()
*
@@ -2437,7 +2403,6 @@ static void txUpdateMap(struct tblock * tblk)
}
}
-
/*
* txAllocPMap()
*
@@ -2509,7 +2474,6 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
}
}
-
/*
* txFreeMap()
*
@@ -2611,7 +2575,6 @@ void txFreeMap(struct inode *ip,
}
}
-
/*
* txFreelock()
*
@@ -2652,7 +2615,6 @@ void txFreelock(struct inode *ip)
TXN_UNLOCK();
}
-
/*
* txAbort()
*
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index b71b82c2df0..59ad0f6b723 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -285,34 +285,26 @@ struct commit {
/*
* external declarations
*/
-extern struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage *mp,
- int flag);
-
-extern struct tlock *txMaplock(tid_t tid, struct inode *ip, int flag);
-
-extern int txCommit(tid_t tid, int nip, struct inode **iplist, int flag);
-
-extern tid_t txBegin(struct super_block *sb, int flag);
-
-extern void txBeginAnon(struct super_block *sb);
-
-extern void txEnd(tid_t tid);
-
-extern void txAbort(tid_t tid, int dirty);
-
-extern struct linelock *txLinelock(struct linelock * tlock);
-
-extern void txFreeMap(struct inode *ip, struct maplock * maplock,
- struct tblock * tblk, int maptype);
-
-extern void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea);
-
-extern void txFreelock(struct inode *ip);
-
-extern int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
- struct tlock * tlck);
-
-extern void txQuiesce(struct super_block *sb);
-
-extern void txResume(struct super_block *sb);
+extern int jfs_tlocks_low;
+
+extern int txInit(void);
+extern void txExit(void);
+extern struct tlock *txLock(tid_t, struct inode *, struct metapage *, int);
+extern struct tlock *txMaplock(tid_t, struct inode *, int);
+extern int txCommit(tid_t, int, struct inode **, int);
+extern tid_t txBegin(struct super_block *, int);
+extern void txBeginAnon(struct super_block *);
+extern void txEnd(tid_t);
+extern void txAbort(tid_t, int);
+extern struct linelock *txLinelock(struct linelock *);
+extern void txFreeMap(struct inode *, struct maplock *, struct tblock *, int);
+extern void txEA(tid_t, struct inode *, dxd_t *, dxd_t *);
+extern void txFreelock(struct inode *);
+extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
+ struct tlock *);
+extern void txQuiesce(struct super_block *);
+extern void txResume(struct super_block *);
+extern void txLazyUnlock(struct tblock *);
+extern int jfs_lazycommit(void *);
+extern int jfs_sync(void *);
#endif /* _H_JFS_TXNMGR */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8413a368f44..1cae14e741e 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -31,20 +31,9 @@
#include "jfs_acl.h"
#include "jfs_debug.h"
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_file_operations;
-extern struct address_space_operations jfs_aops;
-
-extern int jfs_fsync(struct file *, struct dentry *, int);
-extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern int jfs_init_acl(struct inode *, struct inode *);
-
/*
* forward references
*/
-struct inode_operations jfs_dir_inode_operations;
-struct file_operations jfs_dir_operations;
struct dentry_operations jfs_ci_dentry_operations;
static s64 commitZeroLink(tid_t, struct inode *);
@@ -655,7 +644,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
/*
- * NAME: freeZeroLink()
+ * NAME: jfs_free_zero_link()
*
* FUNCTION: for non-directory, called by iClose(),
* free resources of a file from cache and WORKING map
@@ -663,15 +652,12 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
* while associated with a pager object,
*
* PARAMETER: ip - pointer to inode of file.
- *
- * RETURN: 0 -ok
*/
-int freeZeroLink(struct inode *ip)
+void jfs_free_zero_link(struct inode *ip)
{
- int rc = 0;
int type;
- jfs_info("freeZeroLink: ip = 0x%p", ip);
+ jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
/* return if not reg or symbolic link or if size is
* already ok.
@@ -684,10 +670,10 @@ int freeZeroLink(struct inode *ip)
case S_IFLNK:
/* if its contained in inode nothing to do */
if (ip->i_size < IDATASIZE)
- return 0;
+ return;
break;
default:
- return 0;
+ return;
}
/*
@@ -737,9 +723,7 @@ int freeZeroLink(struct inode *ip)
* free xtree/data blocks from working block map;
*/
if (ip->i_size)
- rc = xtTruncate(0, ip, 0, COMMIT_WMAP);
-
- return rc;
+ xtTruncate(0, ip, 0, COMMIT_WMAP);
}
/*
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5e774ed7fb6..810a3653d8b 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -28,6 +28,7 @@
#include "jfs_incore.h"
#include "jfs_filsys.h"
+#include "jfs_inode.h"
#include "jfs_metapage.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
@@ -62,37 +63,6 @@ module_param(jfsloglevel, int, 0644);
MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
#endif
-/*
- * External declarations
- */
-extern int jfs_mount(struct super_block *);
-extern int jfs_mount_rw(struct super_block *, int);
-extern int jfs_umount(struct super_block *);
-extern int jfs_umount_rw(struct super_block *);
-
-extern int jfsIOWait(void *);
-extern int jfs_lazycommit(void *);
-extern int jfs_sync(void *);
-
-extern void jfs_read_inode(struct inode *inode);
-extern void jfs_dirty_inode(struct inode *inode);
-extern void jfs_delete_inode(struct inode *inode);
-extern int jfs_write_inode(struct inode *inode, int wait);
-
-extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern int jfs_extendfs(struct super_block *, s64, int);
-
-extern struct dentry_operations jfs_ci_dentry_operations;
-
-#ifdef PROC_FS_JFS /* see jfs_debug.h */
-extern void jfs_proc_init(void);
-extern void jfs_proc_clean(void);
-#endif
-
-extern wait_queue_head_t jfs_IO_thread_wait;
-extern wait_queue_head_t jfs_commit_thread_wait;
-extern wait_queue_head_t jfs_sync_thread_wait;
-
static void jfs_handle_error(struct super_block *sb)
{
struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -593,11 +563,6 @@ static struct file_system_type jfs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-extern int metapage_init(void);
-extern int txInit(void);
-extern void txExit(void);
-extern void metapage_exit(void);
-
static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
{
struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index ef4c07ee92b..287d8d6c3cf 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/namei.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_xattr.h"
static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 7a9ffd5d03d..6016373701a 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -946,8 +946,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
out:
up_write(&JFS_IP(inode)->xattr_sem);
- if (os2name)
- kfree(os2name);
+ kfree(os2name);
return rc;
}
@@ -1042,8 +1041,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
out:
up_read(&JFS_IP(inode)->xattr_sem);
- if (os2name)
- kfree(os2name);
+ kfree(os2name);
return size;
}
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b2959592..5025563e737 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -519,6 +519,102 @@ int simple_transaction_release(struct inode *inode, struct file *file)
return 0;
}
+/* Simple attribute files */
+
+struct simple_attr {
+ u64 (*get)(void *);
+ void (*set)(void *, u64);
+ char get_buf[24]; /* enough to store a u64 and "\n\0" */
+ char set_buf[24];
+ void *data;
+ const char *fmt; /* format for read operation */
+ struct semaphore sem; /* protects access to these buffers */
+};
+
+/* simple_attr_open is called by an actual attribute open file operation
+ * to set the attribute specific access operations. */
+int simple_attr_open(struct inode *inode, struct file *file,
+ u64 (*get)(void *), void (*set)(void *, u64),
+ const char *fmt)
+{
+ struct simple_attr *attr;
+
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr)
+ return -ENOMEM;
+
+ attr->get = get;
+ attr->set = set;
+ attr->data = inode->u.generic_ip;
+ attr->fmt = fmt;
+ init_MUTEX(&attr->sem);
+
+ file->private_data = attr;
+
+ return nonseekable_open(inode, file);
+}
+
+int simple_attr_close(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+/* read from the buffer that is filled with the get function */
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct simple_attr *attr;
+ size_t size;
+ ssize_t ret;
+
+ attr = file->private_data;
+
+ if (!attr->get)
+ return -EACCES;
+
+ down(&attr->sem);
+ if (*ppos) /* continued read */
+ size = strlen(attr->get_buf);
+ else /* first read */
+ size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+ attr->fmt,
+ (unsigned long long)attr->get(attr->data));
+
+ ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+ up(&attr->sem);
+ return ret;
+}
+
+/* interpret the buffer as a number to call the set function with */
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct simple_attr *attr;
+ u64 val;
+ size_t size;
+ ssize_t ret;
+
+ attr = file->private_data;
+
+ if (!attr->set)
+ return -EACCES;
+
+ down(&attr->sem);
+ ret = -EFAULT;
+ size = min(sizeof(attr->set_buf) - 1, len);
+ if (copy_from_user(attr->set_buf, buf, size))
+ goto out;
+
+ ret = len; /* claim we got the whole input */
+ attr->set_buf[size] = '\0';
+ val = simple_strtol(attr->set_buf, NULL, 0);
+ attr->set(attr->data, val);
+out:
+ up(&attr->sem);
+ return ret;
+}
+
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +643,7 @@ EXPORT_SYMBOL(simple_read_from_buffer);
EXPORT_SYMBOL(simple_transaction_get);
EXPORT_SYMBOL(simple_transaction_read);
EXPORT_SYMBOL(simple_transaction_release);
+EXPORT_SYMBOL_GPL(simple_attr_open);
+EXPORT_SYMBOL_GPL(simple_attr_close);
+EXPORT_SYMBOL_GPL(simple_attr_read);
+EXPORT_SYMBOL_GPL(simple_attr_write);
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d4aaa88d021..78899eeab97 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -25,7 +25,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
struct kobject * kobj = to_kobj(dentry->d_parent);
if (!attr->read)
- return -EINVAL;
+ return -EIO;
return attr->read(kobj, buffer, off, count);
}
@@ -71,7 +71,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
struct kobject *kobj = to_kobj(dentry->d_parent);
if (!attr->write)
- return -EINVAL;
+ return -EIO;
return attr->write(kobj, buffer, offset, count);
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index fe198210bc2..37d7a6875d8 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -101,18 +101,19 @@ static int create_dir(struct kobject * k, struct dentry * p,
down(&p->d_inode->i_sem);
*d = sysfs_get_dentry(p,n);
if (!IS_ERR(*d)) {
- error = sysfs_create(*d, mode, init_dir);
+ error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
if (!error) {
- error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
- SYSFS_DIR);
+ error = sysfs_create(*d, mode, init_dir);
if (!error) {
p->d_inode->i_nlink++;
(*d)->d_op = &sysfs_dentry_ops;
d_rehash(*d);
}
}
- if (error && (error != -EEXIST))
+ if (error && (error != -EEXIST)) {
+ sysfs_put((*d)->d_fsdata);
d_drop(*d);
+ }
dput(*d);
} else
error = PTR_ERR(*d);
@@ -171,17 +172,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
init = init_file;
}
+ dentry->d_fsdata = sysfs_get(sd);
+ sd->s_dentry = dentry;
error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
- if (error)
+ if (error) {
+ sysfs_put(sd);
return error;
+ }
if (bin_attr) {
dentry->d_inode->i_size = bin_attr->size;
dentry->d_inode->i_fop = &bin_fops;
}
dentry->d_op = &sysfs_dentry_ops;
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
d_rehash(dentry);
return 0;
@@ -191,13 +194,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
{
int err = 0;
+ dentry->d_fsdata = sysfs_get(sd);
+ sd->s_dentry = dentry;
err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
if (!err) {
dentry->d_op = &sysfs_dentry_ops;
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
d_rehash(dentry);
- }
+ } else
+ sysfs_put(sd);
+
return err;
}
@@ -228,6 +233,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
struct inode_operations sysfs_dir_inode_operations = {
.lookup = sysfs_lookup,
+ .setattr = sysfs_setattr,
};
static void remove_dir(struct dentry * d)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 364208071e1..849aac11546 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -23,7 +23,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
{
struct subsystem * s = to_subsys(kobj);
struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (sattr->show)
ret = sattr->show(s,page);
@@ -36,7 +36,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct subsystem * s = to_subsys(kobj);
struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (sattr->store)
ret = sattr->store(s,page,count);
@@ -182,7 +182,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
return -ENOMEM;
if (count >= PAGE_SIZE)
- count = PAGE_SIZE - 1;
+ count = PAGE_SIZE;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
return error ? -EFAULT : count;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8e..565cac1d420 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
-struct inode * sysfs_new_inode(mode_t mode)
+static struct inode_operations sysfs_inode_operations ={
+ .setattr = sysfs_setattr,
+};
+
+int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+{
+ struct inode * inode = dentry->d_inode;
+ struct sysfs_dirent * sd = dentry->d_fsdata;
+ struct iattr * sd_iattr;
+ unsigned int ia_valid = iattr->ia_valid;
+ int error;
+
+ if (!sd)
+ return -EINVAL;
+
+ sd_iattr = sd->s_iattr;
+
+ error = inode_change_ok(inode, iattr);
+ if (error)
+ return error;
+
+ error = inode_setattr(inode, iattr);
+ if (error)
+ return error;
+
+ if (!sd_iattr) {
+ /* setting attributes for the first time, allocate now */
+ sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+ if (!sd_iattr)
+ return -ENOMEM;
+ /* assign default attributes */
+ memset(sd_iattr, 0, sizeof(struct iattr));
+ sd_iattr->ia_mode = sd->s_mode;
+ sd_iattr->ia_uid = 0;
+ sd_iattr->ia_gid = 0;
+ sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
+ sd->s_iattr = sd_iattr;
+ }
+
+ /* attributes were changed atleast once in past */
+
+ if (ia_valid & ATTR_UID)
+ sd_iattr->ia_uid = iattr->ia_uid;
+ if (ia_valid & ATTR_GID)
+ sd_iattr->ia_gid = iattr->ia_gid;
+ if (ia_valid & ATTR_ATIME)
+ sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_MTIME)
+ sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_CTIME)
+ sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_MODE) {
+ umode_t mode = iattr->ia_mode;
+
+ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+ mode &= ~S_ISGID;
+ sd_iattr->ia_mode = mode;
+ }
+
+ return error;
+}
+
+static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
+{
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
+{
+ inode->i_mode = iattr->ia_mode;
+ inode->i_uid = iattr->ia_uid;
+ inode->i_gid = iattr->ia_gid;
+ inode->i_atime = iattr->ia_atime;
+ inode->i_mtime = iattr->ia_mtime;
+ inode->i_ctime = iattr->ia_ctime;
+}
+
+struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
{
struct inode * inode = new_inode(sysfs_sb);
if (inode) {
- inode->i_mode = mode;
- inode->i_uid = 0;
- inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+ inode->i_op = &sysfs_inode_operations;
+
+ if (sd->s_iattr) {
+ /* sysfs_dirent has non-default attributes
+ * get them for the new inode from persistent copy
+ * in sysfs_dirent
+ */
+ set_inode_attr(inode, sd->s_iattr);
+ } else
+ set_default_inode_attr(inode, mode);
}
return inode;
}
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
struct inode * inode = NULL;
if (dentry) {
if (!dentry->d_inode) {
- if ((inode = sysfs_new_inode(mode))) {
+ struct sysfs_dirent * sd = dentry->d_fsdata;
+ if ((inode = sysfs_new_inode(mode, sd))) {
if (dentry->d_parent && dentry->d_parent->d_inode) {
struct inode *p_inode = dentry->d_parent->d_inode;
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 5c805bb1a4b..f1117e885bd 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -28,6 +28,7 @@ static struct sysfs_dirent sysfs_root = {
.s_children = LIST_HEAD_INIT(sysfs_root.s_children),
.s_element = NULL,
.s_type = SYSFS_ROOT,
+ .s_iattr = NULL,
};
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -42,7 +43,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1;
sysfs_sb = sb;
- inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+ inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+ &sysfs_root);
if (inode) {
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index dfdf7017435..fae57c83a72 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -43,7 +43,7 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
}
}
-static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target)
+static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
{
struct sysfs_dirent * parent_sd = parent->d_fsdata;
struct sysfs_symlink * sl;
@@ -79,7 +79,7 @@ exit1:
* @target: object we're pointing to.
* @name: name of the symlink.
*/
-int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
+int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
struct dentry * dentry = kobj->dentry;
int error = 0;
@@ -99,13 +99,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
* @name: name of the symlink to remove.
*/
-void sysfs_remove_link(struct kobject * kobj, char * name)
+void sysfs_remove_link(struct kobject * kobj, const char * name)
{
sysfs_hash_and_remove(kobj->dentry,name);
}
static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
- char *path)
+ char *path)
{
char * s;
int depth, size;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a8a24a0c0b3..29da6f5f07c 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,7 +2,7 @@
extern struct vfsmount * sysfs_mount;
extern kmem_cache_t *sysfs_dir_cachep;
-extern struct inode * sysfs_new_inode(mode_t mode);
+extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
@@ -17,6 +17,7 @@ extern void sysfs_remove_subdir(struct dentry *);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
+extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
@@ -75,6 +76,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
kobject_put(sl->target_kobj);
kfree(sl);
}
+ kfree(sd->s_iattr);
kmem_cache_free(sysfs_dir_cachep, sd);
}