aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNathan Scott <nathans@bruce>2006-03-22 15:31:14 +1100
committerNathan Scott <nathans@bruce>2006-03-22 15:31:14 +1100
commit4d74f423c722b8cadfabe087369200013b217b67 (patch)
treed62facddfdb0dfd89f3e61f4fc699cf2feb4b082 /fs
parentbb19fba1937cb6ab2bb98ac893365f6ebf88ef1b (diff)
parente952f31bce6e9f64db01f607abc46529ba57ac9e (diff)
downloadlinux-4d74f423c722b8cadfabe087369200013b217b67.tar.gz
Merge HEAD from ../linux-2.6
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_dir.c1
-rw-r--r--fs/buffer.c6
-rw-r--r--fs/char_dev.c17
-rw-r--r--fs/debugfs/file.c46
-rw-r--r--fs/direct-io.c21
-rw-r--r--fs/ext2/dir.c28
-rw-r--r--fs/jfs/Makefile3
-rw-r--r--fs/jfs/acl.c7
-rw-r--r--fs/jfs/file.c1
-rw-r--r--fs/jfs/inode.c15
-rw-r--r--fs/jfs/ioctl.c107
-rw-r--r--fs/jfs/jfs_dinode.h31
-rw-r--r--fs/jfs/jfs_dmap.c15
-rw-r--r--fs/jfs/jfs_dmap.h2
-rw-r--r--fs/jfs/jfs_dtree.c13
-rw-r--r--fs/jfs/jfs_extent.c20
-rw-r--r--fs/jfs/jfs_imap.c78
-rw-r--r--fs/jfs/jfs_imap.h4
-rw-r--r--fs/jfs/jfs_incore.h10
-rw-r--r--fs/jfs/jfs_inode.c46
-rw-r--r--fs/jfs/jfs_inode.h3
-rw-r--r--fs/jfs/jfs_lock.h1
-rw-r--r--fs/jfs/jfs_logmgr.c35
-rw-r--r--fs/jfs/jfs_logmgr.h2
-rw-r--r--fs/jfs/jfs_metapage.c3
-rw-r--r--fs/jfs/jfs_superblock.h9
-rw-r--r--fs/jfs/jfs_txnmgr.c36
-rw-r--r--fs/jfs/namei.c99
-rw-r--r--fs/jfs/super.c98
-rw-r--r--fs/jfs/xattr.c8
-rw-r--r--fs/lockd/clntproc.c9
-rw-r--r--fs/namespace.c5
-rw-r--r--fs/nfs/direct.c10
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfsctl.c4
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/sysfs/file.c9
-rw-r--r--fs/sysfs/inode.c9
-rw-r--r--fs/sysfs/symlink.c6
-rw-r--r--fs/sysfs/sysfs.h1
40 files changed, 585 insertions, 272 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index ae6d032b9b59f..cd5eeb032d643 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -202,7 +202,6 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
filp->private_data = NULL;
}
- d_drop(filp->f_dentry);
return 0;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 62cfd17dc5fee..a9b3994020074 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -3060,6 +3060,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
{
struct address_space *mapping = page->mapping;
struct buffer_head *bh, *head;
+ int rc;
if (!mapping)
return -EAGAIN;
@@ -3069,8 +3070,9 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
head = page_buffers(page);
- if (migrate_page_remove_references(newpage, page, 3))
- return -EAGAIN;
+ rc = migrate_page_remove_references(newpage, page, 3);
+ if (rc)
+ return rc;
bh = head;
do {
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 21195c4816376..5c36345c9bf78 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -19,6 +19,7 @@
#include <linux/kobject.h>
#include <linux/kobj_map.h>
#include <linux/cdev.h>
+#include <linux/mutex.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
@@ -28,7 +29,7 @@ static struct kobj_map *cdev_map;
#define MAX_PROBE_HASH 255 /* random */
-static DECLARE_MUTEX(chrdevs_lock);
+static DEFINE_MUTEX(chrdevs_lock);
static struct char_device_struct {
struct char_device_struct *next;
@@ -88,13 +89,13 @@ out:
void *acquire_chrdev_list(void)
{
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
return get_next_chrdev(NULL);
}
void release_chrdev_list(void *dev)
{
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
kfree(dev);
}
@@ -151,7 +152,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
memset(cd, 0, sizeof(struct char_device_struct));
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
/* temporary */
if (major == 0) {
@@ -186,10 +187,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
}
cd->next = *cp;
*cp = cd;
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
return cd;
out:
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
kfree(cd);
return ERR_PTR(ret);
}
@@ -200,7 +201,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
struct char_device_struct *cd = NULL, **cp;
int i = major_to_index(major);
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major == major &&
(*cp)->baseminor == baseminor &&
@@ -210,7 +211,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
cd = *cp;
*cp = cd->next;
}
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
return cd;
}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index d575452cd9f75..40c4fc973fad3 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -251,3 +251,49 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_bool);
+static ssize_t read_file_blob(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct debugfs_blob_wrapper *blob = file->private_data;
+ return simple_read_from_buffer(user_buf, count, ppos, blob->data,
+ blob->size);
+}
+
+static struct file_operations fops_blob = {
+ .read = read_file_blob,
+ .open = default_open,
+};
+
+/**
+ * debugfs_create_blob - create a file in the debugfs filesystem that is
+ * used to read and write a binary blob.
+ *
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this paramater is NULL, then the
+ * file will be created in the root of the debugfs filesystem.
+ * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer
+ * to the blob data and the size of the data.
+ *
+ * This function creates a file in debugfs with the given name that exports
+ * @blob->data as a binary blob. If the @mode variable is so set it can be
+ * read from. Writing is not supported.
+ *
+ * This function will return a pointer to a dentry if it succeeds. This
+ * pointer must be passed to the debugfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.) If an error occurs, NULL will be returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -ENODEV will be
+ * returned. It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *debugfs_create_blob(const char *name, mode_t mode,
+ struct dentry *parent,
+ struct debugfs_blob_wrapper *blob)
+{
+ return debugfs_create_file(name, mode, parent, blob, &fops_blob);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_blob);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 848044af7e167..27f3e787facaf 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
* For writes, i_mutex is not held on entry; it is never taken.
*
* DIO_LOCKING (simple locking for regular files)
- * For writes we are called under i_mutex and return with i_mutex held, even though
- * it is internally dropped.
+ * For writes we are called under i_mutex and return with i_mutex held, even
+ * though it is internally dropped.
* For reads, i_mutex is not held on entry, but it is taken and dropped before
* returning.
*
* DIO_OWN_LOCKING (filesystem provides synchronisation and handling of
* uninitialised data, allowing parallel direct readers and writers)
* For writes we are called without i_mutex, return without it, never touch it.
- * For reads, i_mutex is held on entry and will be released before returning.
+ * For reads we are called under i_mutex and return with i_mutex held, even
+ * though it may be internally dropped.
*
* Additional i_alloc_sem locking requirements described inline below.
*/
@@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
ssize_t retval = -EINVAL;
loff_t end = offset;
struct dio *dio;
- int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING);
+ int release_i_mutex = 0;
+ int acquire_i_mutex = 0;
if (rw & WRITE)
current->flags |= PF_SYNCWRITE;
@@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
* writers need to grab i_alloc_sem only (i_mutex is already held)
* For regular files using DIO_OWN_LOCKING,
* neither readers nor writers take any locks here
- * (i_mutex is already held and release for writers here)
*/
dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
mapping = iocb->ki_filp->f_mapping;
if (dio_lock_type != DIO_OWN_LOCKING) {
mutex_lock(&inode->i_mutex);
- reader_with_isem = 1;
+ release_i_mutex = 1;
}
retval = filemap_write_and_wait_range(mapping, offset,
@@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
if (dio_lock_type == DIO_OWN_LOCKING) {
mutex_unlock(&inode->i_mutex);
- reader_with_isem = 0;
+ acquire_i_mutex = 1;
}
}
@@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
nr_segs, blkbits, get_blocks, end_io, dio);
if (rw == READ && dio_lock_type == DIO_LOCKING)
- reader_with_isem = 0;
+ release_i_mutex = 0;
out:
- if (reader_with_isem)
+ if (release_i_mutex)
mutex_unlock(&inode->i_mutex);
+ else if (acquire_i_mutex)
+ mutex_lock(&inode->i_mutex);
if (rw & WRITE)
current->flags &= ~PF_SYNCWRITE;
return retval;
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 7442bdd1267a4..b3dbd716cd3a1 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -256,11 +256,10 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
unsigned long npages = dir_pages(inode);
unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
unsigned char *types = NULL;
- int need_revalidate = (filp->f_version != inode->i_version);
- int ret;
+ int need_revalidate = filp->f_version != inode->i_version;
if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
- goto success;
+ return 0;
if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
types = ext2_filetype_table;
@@ -275,12 +274,15 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
"bad page in #%lu",
inode->i_ino);
filp->f_pos += PAGE_CACHE_SIZE - offset;
- ret = -EIO;
- goto done;
+ return -EIO;
}
kaddr = page_address(page);
- if (need_revalidate) {
- offset = ext2_validate_entry(kaddr, offset, chunk_mask);
+ if (unlikely(need_revalidate)) {
+ if (offset) {
+ offset = ext2_validate_entry(kaddr, offset, chunk_mask);
+ filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
+ }
+ filp->f_version = inode->i_version;
need_revalidate = 0;
}
de = (ext2_dirent *)(kaddr+offset);
@@ -289,9 +291,8 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
if (de->rec_len == 0) {
ext2_error(sb, __FUNCTION__,
"zero-length directory entry");
- ret = -EIO;
ext2_put_page(page);
- goto done;
+ return -EIO;
}
if (de->inode) {
int over;
@@ -306,19 +307,14 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
le32_to_cpu(de->inode), d_type);
if (over) {
ext2_put_page(page);
- goto success;
+ return 0;
}
}
filp->f_pos += le16_to_cpu(de->rec_len);
}
ext2_put_page(page);
}
-
-success:
- ret = 0;
-done:
- filp->f_version = inode->i_version;
- return ret;
+ return 0;
}
/*
diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile
index 6f1e0e95587a1..3adb6395e42de 100644
--- a/fs/jfs/Makefile
+++ b/fs/jfs/Makefile
@@ -8,7 +8,8 @@ jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \
jfs_xtree.o jfs_imap.o jfs_debug.o jfs_dmap.o \
jfs_unicode.o jfs_dtree.o jfs_inode.o \
jfs_extent.o symlink.o jfs_metapage.o \
- jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o resize.o xattr.o
+ jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o \
+ resize.o xattr.o ioctl.o
jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 461e4934ca7c2..e2281300979c7 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -183,6 +183,9 @@ cleanup:
posix_acl_release(acl);
} else
inode->i_mode &= ~current->fs->umask;
+
+ JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
+ inode->i_mode;
return rc;
}
@@ -207,12 +210,12 @@ static int jfs_acl_chmod(struct inode *inode)
rc = posix_acl_chmod_masq(clone, inode->i_mode);
if (!rc) {
tid_t tid = txBegin(inode->i_sb, 0);
- down(&JFS_IP(inode)->commit_sem);
+ mutex_lock(&JFS_IP(inode)->commit_mutex);
rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
if (!rc)
rc = txCommit(tid, 1, &inode, 0);
txEnd(tid);
- up(&JFS_IP(inode)->commit_sem);
+ mutex_unlock(&JFS_IP(inode)->commit_mutex);
}
posix_acl_release(clone);
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index c2c19c9ed9a40..e1ac6e497e2be 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -113,4 +113,5 @@ struct file_operations jfs_file_operations = {
.sendfile = generic_file_sendfile,
.fsync = jfs_fsync,
.release = jfs_release,
+ .ioctl = jfs_ioctl,
};
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 9f942ca8e4e33..51a5fed90cca4 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -55,6 +55,7 @@ void jfs_read_inode(struct inode *inode)
inode->i_op = &jfs_file_inode_operations;
init_special_inode(inode, inode->i_mode, inode->i_rdev);
}
+ jfs_set_inode_flags(inode);
}
/*
@@ -89,16 +90,16 @@ int jfs_commit_inode(struct inode *inode, int wait)
}
tid = txBegin(inode->i_sb, COMMIT_INODE);
- down(&JFS_IP(inode)->commit_sem);
+ mutex_lock(&JFS_IP(inode)->commit_mutex);
/*
- * Retest inode state after taking commit_sem
+ * Retest inode state after taking commit_mutex
*/
if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode))
rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0);
txEnd(tid);
- up(&JFS_IP(inode)->commit_sem);
+ mutex_unlock(&JFS_IP(inode)->commit_mutex);
return rc;
}
@@ -335,18 +336,18 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length)
tid = txBegin(ip->i_sb, 0);
/*
- * The commit_sem cannot be taken before txBegin.
+ * The commit_mutex cannot be taken before txBegin.
* txBegin may block and there is a chance the inode
* could be marked dirty and need to be committed
* before txBegin unblocks
*/
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
newsize = xtTruncate(tid, ip, length,
COMMIT_TRUNCATE | COMMIT_PWMAP);
if (newsize < 0) {
txEnd(tid);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
break;
}
@@ -355,7 +356,7 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length)
txCommit(tid, 1, &ip, 0);
txEnd(tid);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
} while (newsize > length); /* Truncate isn't always atomic */
}
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
new file mode 100644
index 0000000000000..67b3774820eb6
--- /dev/null
+++ b/fs/jfs/ioctl.c
@@ -0,0 +1,107 @@
+/*
+ * linux/fs/jfs/ioctl.c
+ *
+ * Copyright (C) 2006 Herbert Poetzl
+ * adapted from Remy Card's ext2/ioctl.c
+ */
+
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/ctype.h>
+#include <linux/capability.h>
+#include <linux/time.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+
+#include "jfs_incore.h"
+#include "jfs_dinode.h"
+#include "jfs_inode.h"
+
+
+static struct {
+ long jfs_flag;
+ long ext2_flag;
+} jfs_map[] = {
+ {JFS_NOATIME_FL, EXT2_NOATIME_FL},
+ {JFS_DIRSYNC_FL, EXT2_DIRSYNC_FL},
+ {JFS_SYNC_FL, EXT2_SYNC_FL},
+ {JFS_SECRM_FL, EXT2_SECRM_FL},
+ {JFS_UNRM_FL, EXT2_UNRM_FL},
+ {JFS_APPEND_FL, EXT2_APPEND_FL},
+ {JFS_IMMUTABLE_FL, EXT2_IMMUTABLE_FL},
+ {0, 0},
+};
+
+static long jfs_map_ext2(unsigned long flags, int from)
+{
+ int index=0;
+ long mapped=0;
+
+ while (jfs_map[index].jfs_flag) {
+ if (from) {
+ if (jfs_map[index].ext2_flag & flags)
+ mapped |= jfs_map[index].jfs_flag;
+ } else {
+ if (jfs_map[index].jfs_flag & flags)
+ mapped |= jfs_map[index].ext2_flag;
+ }
+ index++;
+ }
+ return mapped;
+}
+
+
+int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct jfs_inode_info *jfs_inode = JFS_IP(inode);
+ unsigned int flags;
+
+ switch (cmd) {
+ case JFS_IOC_GETFLAGS:
+ flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
+ flags = jfs_map_ext2(flags, 0);
+ return put_user(flags, (int __user *) arg);
+ case JFS_IOC_SETFLAGS: {
+ unsigned int oldflags;
+
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EACCES;
+
+ if (get_user(flags, (int __user *) arg))
+ return -EFAULT;
+
+ flags = jfs_map_ext2(flags, 1);
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~JFS_DIRSYNC_FL;
+
+ oldflags = jfs_inode->mode2;
+
+ /*
+ * The IMMUTABLE and APPEND_ONLY flags can only be changed by
+ * the relevant capability.
+ */
+ if ((oldflags & JFS_IMMUTABLE_FL) ||
+ ((flags ^ oldflags) &
+ (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
+ if (!capable(CAP_LINUX_IMMUTABLE))
+ return -EPERM;
+ }
+
+ flags = flags & JFS_FL_USER_MODIFIABLE;
+ flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
+ jfs_inode->mode2 = flags;
+
+ jfs_set_inode_flags(inode);
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+ return 0;
+ }
+ default:
+ return -ENOTTY;
+ }
+}
+
diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
index 580a3258449b5..9f2572aea5611 100644
--- a/fs/jfs/jfs_dinode.h
+++ b/fs/jfs/jfs_dinode.h
@@ -139,13 +139,36 @@ struct dinode {
/* more extended mode bits: attributes for OS/2 */
#define IREADONLY 0x02000000 /* no write access to file */
-#define IARCHIVE 0x40000000 /* file archive bit */
-#define ISYSTEM 0x08000000 /* system file */
#define IHIDDEN 0x04000000 /* hidden file */
-#define IRASH 0x4E000000 /* mask for changeable attributes */
-#define INEWNAME 0x80000000 /* non-8.3 filename format */
+#define ISYSTEM 0x08000000 /* system file */
+
#define IDIRECTORY 0x20000000 /* directory (shadow of real bit) */
+#define IARCHIVE 0x40000000 /* file archive bit */
+#define INEWNAME 0x80000000 /* non-8.3 filename format */
+
+#define IRASH 0x4E000000 /* mask for changeable attributes */
#define ATTRSHIFT 25 /* bits to shift to move attribute
specification to mode position */
+/* extended attributes for Linux */
+
+#define JFS_NOATIME_FL 0x00080000 /* do not update atime */
+
+#define JFS_DIRSYNC_FL 0x00100000 /* dirsync behaviour */
+#define JFS_SYNC_FL 0x00200000 /* Synchronous updates */
+#define JFS_SECRM_FL 0x00400000 /* Secure deletion */
+#define JFS_UNRM_FL 0x00800000 /* allow for undelete */
+
+#define JFS_APPEND_FL 0x01000000 /* writes to file may only append */
+#define JFS_IMMUTABLE_FL 0x02000000 /* Immutable file */
+
+#define JFS_FL_USER_VISIBLE 0x03F80000
+#define JFS_FL_USER_MODIFIABLE 0x03F80000
+#define JFS_FL_INHERIT 0x03C80000
+
+/* These are identical to EXT[23]_IOC_GETFLAGS/SETFLAGS */
+#define JFS_IOC_GETFLAGS _IOR('f', 1, long)
+#define JFS_IOC_SETFLAGS _IOW('f', 2, long)
+
+
#endif /*_H_JFS_DINODE */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 2967b73934151..c161c98954e08 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -64,9 +64,9 @@
* to the persistent bitmaps in dmaps) is guarded by (busy) buffers.
*/
-#define BMAP_LOCK_INIT(bmp) init_MUTEX(&bmp->db_bmaplock)
-#define BMAP_LOCK(bmp) down(&bmp->db_bmaplock)
-#define BMAP_UNLOCK(bmp) up(&bmp->db_bmaplock)
+#define BMAP_LOCK_INIT(bmp) mutex_init(&bmp->db_bmaplock)
+#define BMAP_LOCK(bmp) mutex_lock(&bmp->db_bmaplock)
+#define BMAP_UNLOCK(bmp) mutex_unlock(&bmp->db_bmaplock)
/*
* forward references
@@ -125,7 +125,7 @@ static int dbGetL2AGSize(s64 nblocks);
* into the table, with the table elements yielding the maximum
* binary buddy of free bits within the character.
*/
-static s8 budtab[256] = {
+static const s8 budtab[256] = {
3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -532,10 +532,10 @@ dbUpdatePMap(struct inode *ipbmap,
lastlblkno = lblkno;
+ LOGSYNC_LOCK(log, flags);
if (mp->lsn != 0) {
/* inherit older/smaller lsn */
logdiff(diffp, mp->lsn, log);
- LOGSYNC_LOCK(log, flags);
if (difft < diffp) {
mp->lsn = lsn;
@@ -548,20 +548,17 @@ dbUpdatePMap(struct inode *ipbmap,
logdiff(diffp, mp->clsn, log);
if (difft > diffp)
mp->clsn = tblk->clsn;
- LOGSYNC_UNLOCK(log, flags);
} else {
mp->log = log;
mp->lsn = lsn;
/* insert bp after tblock in logsync list */
- LOGSYNC_LOCK(log, flags);
-
log->count++;
list_add(&mp->synclist, &tblk->synclist);
mp->clsn = tblk->clsn;
- LOGSYNC_UNLOCK(log, flags);
}
+ LOGSYNC_UNLOCK(log, flags);
}
/* write the last buffer. */
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
index 32e25884e7e84..8b14cc8e02283 100644
--- a/fs/jfs/jfs_dmap.h
+++ b/fs/jfs/jfs_dmap.h
@@ -243,7 +243,7 @@ struct dbmap {
struct bmap {
struct dbmap db_bmap; /* on-disk aggregate map descriptor */
struct inode *db_ipbmap; /* ptr to aggregate map incore inode */
- struct semaphore db_bmaplock; /* aggregate map lock */
+ struct mutex db_bmaplock; /* aggregate map lock */
atomic_t db_active[MAXAG]; /* count of active, open files in AG */
u32 *db_DBmap;
};
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 404f33eae5079..6c3f083198468 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -1005,6 +1005,9 @@ static int dtSplitUp(tid_t tid,
DT_PUTPAGE(smp);
+ if (!DO_INDEX(ip))
+ ip->i_size = xlen << sbi->l2bsize;
+
goto freeKeyName;
}
@@ -1055,7 +1058,9 @@ static int dtSplitUp(tid_t tid,
xaddr = addressPXD(pxd) + xlen;
dbFree(ip, xaddr, (s64) n);
}
- }
+ } else if (!DO_INDEX(ip))
+ ip->i_size = lengthPXD(pxd) << sbi->l2bsize;
+
extendOut:
DT_PUTPAGE(smp);
@@ -1098,6 +1103,9 @@ static int dtSplitUp(tid_t tid,
goto splitOut;
}
+ if (!DO_INDEX(ip))
+ ip->i_size += PSIZE;
+
/*
* propagate up the router entry for the leaf page just split
*
@@ -2424,6 +2432,9 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
break;
}
+ if (!DO_INDEX(ip))
+ ip->i_size -= PSIZE;
+
return 0;
}
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 4879603daa1c7..5549378358bfd 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -94,7 +94,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
txBeginAnon(ip->i_sb);
/* Avoid race with jfs_commit_inode() */
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
/* validate extent length */
if (xlen > MAXXLEN)
@@ -136,14 +136,14 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
*/
nxlen = xlen;
if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) {
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return (rc);
}
/* Allocate blocks to quota. */
if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
dbFree(ip, nxaddr, (s64) nxlen);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return -EDQUOT;
}
@@ -165,7 +165,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
if (rc) {
dbFree(ip, nxaddr, nxlen);
DQUOT_FREE_BLOCK(ip, nxlen);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return (rc);
}
@@ -177,7 +177,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
mark_inode_dirty(ip);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
/*
* COMMIT_SyncList flags an anonymous tlock on page that is on
* sync list.
@@ -222,7 +222,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
/* This blocks if we are low on resources */
txBeginAnon(ip->i_sb);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
/* validate extent length */
if (nxlen > MAXXLEN)
nxlen = MAXXLEN;
@@ -258,7 +258,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
/* Allocat blocks to quota. */
if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
dbFree(ip, nxaddr, (s64) nxlen);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return -EDQUOT;
}
@@ -338,7 +338,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
mark_inode_dirty(ip);
exit:
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return (rc);
}
#endif /* _NOTYET */
@@ -439,12 +439,12 @@ int extRecord(struct inode *ip, xad_t * xp)
txBeginAnon(ip->i_sb);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
/* update the extent */
rc = xtUpdate(0, ip, xp);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
return rc;
}
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 31b4aa13dd4b9..ccbe60aff83de 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -66,14 +66,14 @@ static HLIST_HEAD(aggregate_hash);
* imap locks
*/
/* iag free list lock */
-#define IAGFREE_LOCK_INIT(imap) init_MUTEX(&imap->im_freelock)
-#define IAGFREE_LOCK(imap) down(&imap->im_freelock)
-#define IAGFREE_UNLOCK(imap) up(&imap->im_freelock)
+#define IAGFREE_LOCK_INIT(imap) mutex_init(&imap->im_freelock)
+#define IAGFREE_LOCK(imap) mutex_lock(&imap->im_freelock)
+#define IAGFREE_UNLOCK(imap) mutex_unlock(&imap->im_freelock)
/* per ag iag list locks */
-#define AG_LOCK_INIT(imap,index) init_MUTEX(&(imap->im_aglock[index]))
-#define AG_LOCK(imap,agno) down(&imap->im_aglock[agno])
-#define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno])
+#define AG_LOCK_INIT(imap,index) mutex_init(&(imap->im_aglock[index]))
+#define AG_LOCK(imap,agno) mutex_lock(&imap->im_aglock[agno])
+#define AG_UNLOCK(imap,agno) mutex_unlock(&imap->im_aglock[agno])
/*
* forward references
@@ -1261,7 +1261,7 @@ int diFree(struct inode *ip)
* to be freed by the transaction;
*/
tid = txBegin(ipimap->i_sb, COMMIT_FORCE);
- down(&JFS_IP(ipimap)->commit_sem);
+ mutex_lock(&JFS_IP(ipimap)->commit_mutex);
/* acquire tlock of the iag page of the freed ixad
* to force the page NOHOMEOK (even though no data is
@@ -1294,7 +1294,7 @@ int diFree(struct inode *ip)
rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
txEnd(tid);
- up(&JFS_IP(ipimap)->commit_sem);
+ mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
/* unlock the AG inode map information */
AG_UNLOCK(imap, agno);
@@ -2554,13 +2554,13 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
* addressing structure pointing to the new iag page;
*/
tid = txBegin(sb, COMMIT_FORCE);
- down(&JFS_IP(ipimap)->commit_sem);
+ mutex_lock(&JFS_IP(ipimap)->commit_mutex);
/* update the inode map addressing structure to point to it */
if ((rc =
xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
txEnd(tid);
- up(&JFS_IP(ipimap)->commit_sem);
+ mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
/* Free the blocks allocated for the iag since it was
* not successfully added to the inode map
*/
@@ -2626,7 +2626,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
txEnd(tid);
- up(&JFS_IP(ipimap)->commit_sem);
+ mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
duplicateIXtree(sb, blkno, xlen, &xaddr);
@@ -2844,11 +2844,11 @@ diUpdatePMap(struct inode *ipimap,
*/
lsn = tblk->lsn;
log = JFS_SBI(tblk->sb)->log;
+ LOGSYNC_LOCK(log, flags);
if (mp->lsn != 0) {
/* inherit older/smaller lsn */
logdiff(difft, lsn, log);
logdiff(diffp, mp->lsn, log);
- LOGSYNC_LOCK(log, flags);
if (difft < diffp) {
mp->lsn = lsn;
/* move mp after tblock in logsync list */
@@ -2860,17 +2860,15 @@ diUpdatePMap(struct inode *ipimap,
logdiff(diffp, mp->clsn, log);
if (difft > diffp)
mp->clsn = tblk->clsn;
- LOGSYNC_UNLOCK(log, flags);
} else {
mp->log = log;
mp->lsn = lsn;
/* insert mp after tblock in logsync list */
- LOGSYNC_LOCK(log, flags);
log->count++;
list_add(&mp->synclist, &tblk->synclist);
mp->clsn = tblk->clsn;
- LOGSYNC_UNLOCK(log, flags);
}
+ LOGSYNC_UNLOCK(log, flags);
write_metapage(mp);
return (0);
}
@@ -3076,14 +3074,40 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
static int copy_from_dinode(struct dinode * dip, struct inode *ip)
{
struct jfs_inode_info *jfs_ip = JFS_IP(ip);
+ struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
+ if (sbi->umask != -1) {
+ ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask);
+ /* For directories, add x permission if r is allowed by umask */
+ if (S_ISDIR(ip->i_mode)) {
+ if (ip->i_mode & 0400)
+ ip->i_mode |= 0100;
+ if (ip->i_mode & 0040)
+ ip->i_mode |= 0010;
+ if (ip->i_mode & 0004)
+ ip->i_mode |= 0001;
+ }
+ }
ip->i_nlink = le32_to_cpu(dip->di_nlink);
- ip->i_uid = le32_to_cpu(dip->di_uid);
- ip->i_gid = le32_to_cpu(dip->di_gid);
+
+ jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
+ if (sbi->uid == -1)
+ ip->i_uid = jfs_ip->saved_uid;
+ else {
+ ip->i_uid = sbi->uid;
+ }
+
+ jfs_ip->saved_gid = le32_to_cpu(dip->di_gid);
+ if (sbi->gid == -1)
+ ip->i_gid = jfs_ip->saved_gid;
+ else {
+ ip->i_gid = sbi->gid;
+ }
+
ip->i_size = le64_to_cpu(dip->di_size);
ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
@@ -3134,21 +3158,33 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
static void copy_to_dinode(struct dinode * dip, struct inode *ip)
{
struct jfs_inode_info *jfs_ip = JFS_IP(ip);
+ struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
- dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp);
+ dip->di_inostamp = cpu_to_le32(sbi->inostamp);
dip->di_number = cpu_to_le32(ip->i_ino);
dip->di_gen = cpu_to_le32(ip->i_generation);
dip->di_size = cpu_to_le64(ip->i_size);
dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
dip->di_nlink = cpu_to_le32(ip->i_nlink);
- dip->di_uid = cpu_to_le32(ip->i_uid);
- dip->di_gid = cpu_to_le32(ip->i_gid);
+ if (sbi->uid == -1)
+ dip->di_uid = cpu_to_le32(ip->i_uid);
+ else
+ dip->di_uid = cpu_to_le32(jfs_ip->saved_uid);
+ if (sbi->gid == -1)
+ dip->di_gid = cpu_to_le32(ip->i_gid);
+ else
+ dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
/*
* mode2 is only needed for storing the higher order bits.
* Trust i_mode for the lower order ones
*/
- dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode);
+ if (sbi->umask == -1)
+ dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) |
+ ip->i_mode);
+ else /* Leave the original permissions alone */
+ dip->di_mode = cpu_to_le32(jfs_ip->mode2);
+
dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
diff --git a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
index 6b59adec036a8..6e24465f0f98d 100644
--- a/fs/jfs/jfs_imap.h
+++ b/fs/jfs/jfs_imap.h
@@ -140,8 +140,8 @@ struct dinomap {
struct inomap {
struct dinomap im_imap; /* 4096: inode allocation control */
struct inode *im_ipimap; /* 4: ptr to inode for imap */
- struct semaphore im_freelock; /* 4: iag free list lock */
- struct semaphore im_aglock[MAXAG]; /* 512: per AG locks */
+ struct mutex im_freelock; /* 4: iag free list lock */
+ struct mutex im_aglock[MAXAG]; /* 512: per AG locks */
u32 *im_DBGdimap;
atomic_t im_numinos; /* num of backed inodes */
atomic_t im_numfree; /* num of free backed inodes */
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index dc21a5bd54d43..54d73716ca8c4 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -19,6 +19,7 @@
#ifndef _H_JFS_INCORE
#define _H_JFS_INCORE
+#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/bitops.h>
@@ -37,6 +38,8 @@
struct jfs_inode_info {
int fileset; /* fileset number (always 16)*/
uint mode2; /* jfs-specific mode */
+ uint saved_uid; /* saved for uid mount option */
+ uint saved_gid; /* saved for gid mount option */
pxd_t ixpxd; /* inode extent descriptor */
dxd_t acl; /* dxd describing acl */
dxd_t ea; /* dxd describing ea */
@@ -62,12 +65,12 @@ struct jfs_inode_info {
*/
struct rw_semaphore rdwrlock;
/*
- * commit_sem serializes transaction processing on an inode.
+ * commit_mutex serializes transaction processing on an inode.
* It must be taken after beginning a transaction (txBegin), since
* dirty inodes may be committed while a new transaction on the
* inode is blocked in txBegin or TxBeginAnon
*/
- struct semaphore commit_sem;
+ struct mutex commit_mutex;
/* xattr_sem allows us to access the xattrs without taking i_mutex */
struct rw_semaphore xattr_sem;
lid_t xtlid; /* lid of xtree lock on directory */
@@ -169,6 +172,9 @@ struct jfs_sb_info {
uint state; /* mount/recovery state */
unsigned long flag; /* mount time flags */
uint p_state; /* state prior to going no integrity */
+ uint uid; /* uid to override on-disk uid */
+ uint gid; /* gid to override on-disk gid */
+ uint umask; /* umask to override on-disk umask */
};
/* jfs_sb_info commit_state */
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 2af5efbfd06fa..495df402916db 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -25,6 +25,26 @@
#include "jfs_dinode.h"
#include "jfs_debug.h"
+
+void jfs_set_inode_flags(struct inode *inode)
+{
+ unsigned int flags = JFS_IP(inode)->mode2;
+
+ inode->i_flags &= ~(S_IMMUTABLE | S_APPEND |
+ S_NOATIME | S_DIRSYNC | S_SYNC);
+
+ if (flags & JFS_IMMUTABLE_FL)
+ inode->i_flags |= S_IMMUTABLE;
+ if (flags & JFS_APPEND_FL)
+ inode->i_flags |= S_APPEND;
+ if (flags & JFS_NOATIME_FL)
+ inode->i_flags |= S_NOATIME;
+ if (flags & JFS_DIRSYNC_FL)
+ inode->i_flags |= S_DIRSYNC;
+ if (flags & JFS_SYNC_FL)
+ inode->i_flags |= S_SYNC;
+}
+
/*
* NAME: ialloc()
*
@@ -63,6 +83,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
inode->i_gid = current->fsgid;
/*
+ * New inodes need to save sane values on disk when
+ * uid & gid mount options are used
+ */
+ jfs_inode->saved_uid = inode->i_uid;
+ jfs_inode->saved_gid = inode->i_gid;
+
+ /*
* Allocate inode to quota.
*/
if (DQUOT_ALLOC_INODE(inode)) {
@@ -74,10 +101,20 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
}
inode->i_mode = mode;
- if (S_ISDIR(mode))
- jfs_inode->mode2 = IDIRECTORY | mode;
- else
- jfs_inode->mode2 = INLINEEA | ISPARSE | mode;
+ /* inherit flags from parent */
+ jfs_inode->mode2 = JFS_IP(parent)->mode2 & JFS_FL_INHERIT;
+
+ if (S_ISDIR(mode)) {
+ jfs_inode->mode2 |= IDIRECTORY;
+ jfs_inode->mode2 &= ~JFS_DIRSYNC_FL;
+ }
+ else {
+ jfs_inode->mode2 |= INLINEEA | ISPARSE;
+ if (S_ISLNK(mode))
+ jfs_inode->mode2 &= ~(JFS_IMMUTABLE_FL|JFS_APPEND_FL);
+ }
+ jfs_inode->mode2 |= mode;
+
inode->i_blksize = sb->s_blocksize;
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -98,6 +135,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
jfs_inode->atlhead = 0;
jfs_inode->atltail = 0;
jfs_inode->xtlid = 0;
+ jfs_set_inode_flags(inode);
jfs_info("ialloc returns inode = 0x%p\n", inode);
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index b54bac576cb3b..095d471b9f9a1 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -20,6 +20,8 @@
extern struct inode *ialloc(struct inode *, umode_t);
extern int jfs_fsync(struct file *, struct dentry *, int);
+extern int jfs_ioctl(struct inode *, struct file *,
+ unsigned int, unsigned long);
extern void jfs_read_inode(struct inode *);
extern int jfs_commit_inode(struct inode *, int);
extern int jfs_write_inode(struct inode*, int);
@@ -29,6 +31,7 @@ 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 void jfs_set_inode_flags(struct inode *);
extern struct address_space_operations jfs_aops;
extern struct inode_operations jfs_dir_inode_operations;
diff --git a/fs/jfs/jfs_lock.h b/fs/jfs/jfs_lock.h
index 10ad1d0866856..70ac9f7d1e00c 100644
--- a/fs/jfs/jfs_lock.h
+++ b/fs/jfs/jfs_lock.h
@@ -20,6 +20,7 @@
#define _H_JFS_LOCK
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/sched.h>
/*
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index d27bac6acaa34..0b348b13b5515 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -64,6 +64,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
+#include <linux/kthread.h>
#include <linux/buffer_head.h> /* for sync_blockdev() */
#include <linux/bio.h>
#include <linux/suspend.h>
@@ -81,15 +82,14 @@
*/
static struct lbuf *log_redrive_list;
static DEFINE_SPINLOCK(log_redrive_lock);
-DECLARE_WAIT_QUEUE_HEAD(jfs_IO_thread_wait);
/*
* log read/write serialization (per log)
*/
-#define LOG_LOCK_INIT(log) init_MUTEX(&(log)->loglock)
-#define LOG_LOCK(log) down(&((log)->loglock))
-#define LOG_UNLOCK(log) up(&((log)->loglock))
+#define LOG_LOCK_INIT(log) mutex_init(&(log)->loglock)
+#define LOG_LOCK(log) mutex_lock(&((log)->loglock))
+#define LOG_UNLOCK(log) mutex_unlock(&((log)->loglock))
/*
@@ -1105,11 +1105,10 @@ int lmLogOpen(struct super_block *sb)
}
}
- if (!(log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL))) {
+ if (!(log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL))) {
up(&jfs_log_sem);
return -ENOMEM;
}
- memset(log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&log->sb_list);
init_waitqueue_head(&log->syncwait);
@@ -1181,9 +1180,8 @@ static int open_inline_log(struct super_block *sb)
struct jfs_log *log;
int rc;
- if (!(log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL)))
+ if (!(log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL)))
return -ENOMEM;
- memset(log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&log->sb_list);
init_waitqueue_head(&log->syncwait);
@@ -1216,12 +1214,11 @@ static int open_dummy_log(struct super_block *sb)
down(&jfs_log_sem);
if (!dummy_log) {
- dummy_log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL);
+ dummy_log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL);
if (!dummy_log) {
up(&jfs_log_sem);
return -ENOMEM;
}
- memset(dummy_log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&dummy_log->sb_list);
init_waitqueue_head(&dummy_log->syncwait);
dummy_log->no_integrity = 1;
@@ -1980,7 +1977,7 @@ static inline void lbmRedrive(struct lbuf *bp)
log_redrive_list = bp;
spin_unlock_irqrestore(&log_redrive_lock, flags);
- wake_up(&jfs_IO_thread_wait);
+ wake_up_process(jfsIOthread);
}
@@ -2347,13 +2344,7 @@ int jfsIOWait(void *arg)
{
struct lbuf *bp;
- daemonize("jfsIO");
-
- complete(&jfsIOwait);
-
do {
- DECLARE_WAITQUEUE(wq, current);
-
spin_lock_irq(&log_redrive_lock);
while ((bp = log_redrive_list) != 0) {
log_redrive_list = bp->l_redrive_next;
@@ -2362,21 +2353,19 @@ int jfsIOWait(void *arg)
lbmStartIO(bp);
spin_lock_irq(&log_redrive_lock);
}
+ spin_unlock_irq(&log_redrive_lock);
+
if (freezing(current)) {
- spin_unlock_irq(&log_redrive_lock);
refrigerator();
} else {
- add_wait_queue(&jfs_IO_thread_wait, &wq);
set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&log_redrive_lock);
schedule();
current->state = TASK_RUNNING;
- remove_wait_queue(&jfs_IO_thread_wait, &wq);
}
- } while (!jfs_stop_threads);
+ } while (!kthread_should_stop());
jfs_info("jfsIOWait being killed!");
- complete_and_exit(&jfsIOwait, 0);
+ return 0;
}
/*
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index e4978b5b65ee0..8c6909b80014b 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -389,7 +389,7 @@ struct jfs_log {
int eor; /* 4: eor of last record in eol page */
struct lbuf *bp; /* 4: current log page buffer */
- struct semaphore loglock; /* 4: log write serialization lock */
+ struct mutex loglock; /* 4: log write serialization lock */
/* syncpt */
int nextsync; /* 4: bytes to write before next syncpt */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 8a53981f9f279..5fbaeaadccd39 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -104,10 +104,9 @@ static inline int insert_metapage(struct page *page, struct metapage *mp)
if (PagePrivate(page))
a = mp_anchor(page);
else {
- a = kmalloc(sizeof(struct meta_anchor), GFP_NOFS);
+ a = kzalloc(sizeof(struct meta_anchor), GFP_NOFS);
if (!a)
return -ENOMEM;
- memset(a, 0, sizeof(struct meta_anchor));
set_page_private(page, (unsigned long)a);
SetPagePrivate(page);
kmap(page);
diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
index fcf781bf31cbf..682cf1a68a185 100644
--- a/fs/jfs/jfs_superblock.h
+++ b/fs/jfs/jfs_superblock.h
@@ -113,12 +113,9 @@ 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);
+extern struct task_struct *jfsIOthread;
+extern struct task_struct *jfsSyncThread;
+
#endif /*_H_JFS_SUPERBLOCK */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 2ddb6b892bcf1..ac3d66948e8ce 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -49,6 +49,7 @@
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/kthread.h>
#include "jfs_incore.h"
#include "jfs_inode.h"
#include "jfs_filsys.h"
@@ -121,8 +122,7 @@ static DEFINE_SPINLOCK(jfsTxnLock);
#define LAZY_LOCK(flags) spin_lock_irqsave(&TxAnchor.LazyLock, flags)
#define LAZY_UNLOCK(flags) spin_unlock_irqrestore(&TxAnchor.LazyLock, flags)
-DECLARE_WAIT_QUEUE_HEAD(jfs_sync_thread_wait);
-DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
+static DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
static int jfs_commit_thread_waking;
/*
@@ -207,7 +207,7 @@ static lid_t txLockAlloc(void)
if ((++TxAnchor.tlocksInUse > TxLockHWM) && (jfs_tlocks_low == 0)) {
jfs_info("txLockAlloc tlocks low");
jfs_tlocks_low = 1;
- wake_up(&jfs_sync_thread_wait);
+ wake_up_process(jfsSyncThread);
}
return lid;
@@ -2743,10 +2743,6 @@ int jfs_lazycommit(void *arg)
unsigned long flags;
struct jfs_sb_info *sbi;
- daemonize("jfsCommit");
-
- complete(&jfsIOwait);
-
do {
LAZY_LOCK(flags);
jfs_commit_thread_waking = 0; /* OK to wake another thread */
@@ -2806,13 +2802,13 @@ int jfs_lazycommit(void *arg)
current->state = TASK_RUNNING;
remove_wait_queue(&jfs_commit_thread_wait, &wq);
}
- } while (!jfs_stop_threads);
+ } while (!kthread_should_stop());
if (!list_empty(&TxAnchor.unlock_queue))
jfs_err("jfs_lazycommit being killed w/pending transactions!");
else
jfs_info("jfs_lazycommit being killed\n");
- complete_and_exit(&jfsIOwait, 0);
+ return 0;
}
void txLazyUnlock(struct tblock * tblk)
@@ -2876,10 +2872,10 @@ restart:
*/
TXN_UNLOCK();
tid = txBegin(ip->i_sb, COMMIT_INODE | COMMIT_FORCE);
- down(&jfs_ip->commit_sem);
+ mutex_lock(&jfs_ip->commit_mutex);
txCommit(tid, 1, &ip, 0);
txEnd(tid);
- up(&jfs_ip->commit_sem);
+ mutex_unlock(&jfs_ip->commit_mutex);
/*
* Just to be safe. I don't know how
* long we can run without blocking
@@ -2932,10 +2928,6 @@ int jfs_sync(void *arg)
int rc;
tid_t tid;
- daemonize("jfsSync");
-
- complete(&jfsIOwait);
-
do {
/*
* write each inode on the anonymous inode list
@@ -2952,7 +2944,7 @@ int jfs_sync(void *arg)
* Inode is being freed
*/
list_del_init(&jfs_ip->anon_inode_list);
- } else if (! down_trylock(&jfs_ip->commit_sem)) {
+ } else if (! !mutex_trylock(&jfs_ip->commit_mutex)) {
/*
* inode will be removed from anonymous list
* when it is committed
@@ -2961,7 +2953,7 @@ int jfs_sync(void *arg)
tid = txBegin(ip->i_sb, COMMIT_INODE);
rc = txCommit(tid, 1, &ip, 0);
txEnd(tid);
- up(&jfs_ip->commit_sem);
+ mutex_unlock(&jfs_ip->commit_mutex);
iput(ip);
/*
@@ -2971,7 +2963,7 @@ int jfs_sync(void *arg)
cond_resched();
TXN_LOCK();
} else {
- /* We can't get the commit semaphore. It may
+ /* We can't get the commit mutex. It may
* be held by a thread waiting for tlock's
* so let's not block here. Save it to
* put back on the anon_list.
@@ -2996,19 +2988,15 @@ int jfs_sync(void *arg)
TXN_UNLOCK();
refrigerator();
} else {
- DECLARE_WAITQUEUE(wq, current);
-
- add_wait_queue(&jfs_sync_thread_wait, &wq);
set_current_state(TASK_INTERRUPTIBLE);
TXN_UNLOCK();
schedule();
current->state = TASK_RUNNING;
- remove_wait_queue(&jfs_sync_thread_wait, &wq);
}
- } while (!jfs_stop_threads);
+ } while (!kthread_should_stop());
jfs_info("jfs_sync being killed");
- complete_and_exit(&jfsIOwait, 0);
+ return 0;
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_JFS_DEBUG)
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 4abbe86043021..309cee575f7db 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -104,8 +104,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(dip)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dip)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
rc = jfs_init_acl(tid, ip, dip);
if (rc)
@@ -165,8 +165,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
out3:
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
ip->i_nlink = 0;
@@ -238,8 +238,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(dip)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dip)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
rc = jfs_init_acl(tid, ip, dip);
if (rc)
@@ -300,8 +300,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
out3:
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
ip->i_nlink = 0;
@@ -365,8 +365,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(dip)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dip)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
iplist[0] = dip;
iplist[1] = ip;
@@ -384,8 +384,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
if (rc == -EIO)
txAbort(tid, 1);
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
goto out2;
}
@@ -422,8 +422,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
/*
* Truncating the directory index table is not guaranteed. It
@@ -488,8 +488,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(dip)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dip)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
iplist[0] = dip;
iplist[1] = ip;
@@ -503,8 +503,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
if (rc == -EIO)
txAbort(tid, 1); /* Marks FS Dirty */
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
IWRITE_UNLOCK(ip);
goto out1;
}
@@ -527,8 +527,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
if ((new_size = commitZeroLink(tid, ip)) < 0) {
txAbort(tid, 1); /* Marks FS Dirty */
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
IWRITE_UNLOCK(ip);
rc = new_size;
goto out1;
@@ -556,13 +556,13 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
while (new_size && (rc == 0)) {
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
new_size = xtTruncate_pmap(tid, ip, new_size);
if (new_size < 0) {
txAbort(tid, 1); /* Marks FS Dirty */
@@ -570,7 +570,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
} else
rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
txEnd(tid);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
}
if (ip->i_nlink == 0)
@@ -805,8 +805,8 @@ static int jfs_link(struct dentry *old_dentry,
tid = txBegin(ip->i_sb, 0);
- down(&JFS_IP(dir)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dir)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
/*
* scan parent directory for entry/freespace
@@ -847,8 +847,8 @@ static int jfs_link(struct dentry *old_dentry,
out:
txEnd(tid);
- up(&JFS_IP(dir)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dir)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
jfs_info("jfs_link: rc:%d", rc);
return rc;
@@ -916,8 +916,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
tid = txBegin(dip->i_sb, 0);
- down(&JFS_IP(dip)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dip)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
rc = jfs_init_security(tid, ip, dip);
if (rc)
@@ -1037,8 +1037,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
out3:
txEnd(tid);
- up(&JFS_IP(dip)->commit_sem);
- up(&JFS_IP(ip)->commit_sem);
+ mutex_unlock(&JFS_IP(dip)->commit_mutex);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
ip->i_nlink = 0;
@@ -1141,13 +1141,13 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
*/
tid = txBegin(new_dir->i_sb, 0);
- down(&JFS_IP(new_dir)->commit_sem);
- down(&JFS_IP(old_ip)->commit_sem);
+ mutex_lock(&JFS_IP(new_dir)->commit_mutex);
+ mutex_lock(&JFS_IP(old_ip)->commit_mutex);
if (old_dir != new_dir)
- down(&JFS_IP(old_dir)->commit_sem);
+ mutex_lock(&JFS_IP(old_dir)->commit_mutex);
if (new_ip) {
- down(&JFS_IP(new_ip)->commit_sem);
+ mutex_lock(&JFS_IP(new_ip)->commit_mutex);
/*
* Change existing directory entry to new inode number
*/
@@ -1160,10 +1160,10 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (S_ISDIR(new_ip->i_mode)) {
new_ip->i_nlink--;
if (new_ip->i_nlink) {
- up(&JFS_IP(new_dir)->commit_sem);
- up(&JFS_IP(old_ip)->commit_sem);
+ mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
+ mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
if (old_dir != new_dir)
- up(&JFS_IP(old_dir)->commit_sem);
+ mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
if (!S_ISDIR(old_ip->i_mode) && new_ip)
IWRITE_UNLOCK(new_ip);
jfs_error(new_ip->i_sb,
@@ -1282,16 +1282,16 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
out4:
txEnd(tid);
- up(&JFS_IP(new_dir)->commit_sem);
- up(&JFS_IP(old_ip)->commit_sem);
+ mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
+ mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
if (old_dir != new_dir)
- up(&JFS_IP(old_dir)->commit_sem);
+ mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
if (new_ip)
- up(&JFS_IP(new_ip)->commit_sem);
+ mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
while (new_size && (rc == 0)) {
tid = txBegin(new_ip->i_sb, 0);
- down(&JFS_IP(new_ip)->commit_sem);
+ mutex_lock(&JFS_IP(new_ip)->commit_mutex);
new_size = xtTruncate_pmap(tid, new_ip, new_size);
if (new_size < 0) {
txAbort(tid, 1);
@@ -1299,7 +1299,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
} else
rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
txEnd(tid);
- up(&JFS_IP(new_ip)->commit_sem);
+ mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
}
if (new_ip && (new_ip->i_nlink == 0))
set_cflag(COMMIT_Nolink, new_ip);
@@ -1361,8 +1361,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
tid = txBegin(dir->i_sb, 0);
- down(&JFS_IP(dir)->commit_sem);
- down(&JFS_IP(ip)->commit_sem);
+ mutex_lock(&JFS_IP(dir)->commit_mutex);
+ mutex_lock(&JFS_IP(ip)->commit_mutex);
rc = jfs_init_acl(tid, ip, dir);
if (rc)
@@ -1407,8 +1407,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
out3:
txEnd(tid);
- up(&JFS_IP(ip)->commit_sem);
- up(&JFS_IP(dir)->commit_sem);
+ mutex_unlock(&JFS_IP(ip)->commit_mutex);
+ mutex_unlock(&JFS_IP(dir)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
ip->i_nlink = 0;
@@ -1523,6 +1523,7 @@ struct file_operations jfs_dir_operations = {
.read = generic_read_dir,
.readdir = jfs_readdir,
.fsync = jfs_fsync,
+ .ioctl = jfs_ioctl,
};
static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 8d31f1336431a..18f69e6aa7193 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -25,6 +25,7 @@
#include <linux/vfs.h>
#include <linux/mount.h>
#include <linux/moduleparam.h>
+#include <linux/kthread.h>
#include <linux/posix_acl.h>
#include <asm/uaccess.h>
#include <linux/seq_file.h>
@@ -54,11 +55,9 @@ static int commit_threads = 0;
module_param(commit_threads, int, 0);
MODULE_PARM_DESC(commit_threads, "Number of commit threads");
-int jfs_stop_threads;
-static pid_t jfsIOthread;
-static pid_t jfsCommitThread[MAX_COMMIT_THREADS];
-static pid_t jfsSyncThread;
-DECLARE_COMPLETION(jfsIOwait);
+static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS];
+struct task_struct *jfsIOthread;
+struct task_struct *jfsSyncThread;
#ifdef CONFIG_JFS_DEBUG
int jfsloglevel = JFS_LOGLEVEL_WARN;
@@ -195,7 +194,7 @@ static void jfs_put_super(struct super_block *sb)
enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
- Opt_usrquota, Opt_grpquota
+ Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
};
static match_table_t tokens = {
@@ -209,6 +208,9 @@ static match_table_t tokens = {
{Opt_ignore, "quota"},
{Opt_usrquota, "usrquota"},
{Opt_grpquota, "grpquota"},
+ {Opt_uid, "uid=%u"},
+ {Opt_gid, "gid=%u"},
+ {Opt_umask, "umask=%u"},
{Opt_err, NULL}
};
@@ -313,7 +315,29 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
"JFS: quota operations not supported\n");
break;
#endif
-
+ case Opt_uid:
+ {
+ char *uid = args[0].from;
+ sbi->uid = simple_strtoul(uid, &uid, 0);
+ break;
+ }
+ case Opt_gid:
+ {
+ char *gid = args[0].from;
+ sbi->gid = simple_strtoul(gid, &gid, 0);
+ break;
+ }
+ case Opt_umask:
+ {
+ char *umask = args[0].from;
+ sbi->umask = simple_strtoul(umask, &umask, 8);
+ if (sbi->umask & ~0777) {
+ printk(KERN_ERR
+ "JFS: Invalid value of umask\n");
+ goto cleanup;
+ }
+ break;
+ }
default:
printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p);
@@ -396,12 +420,12 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
if (!new_valid_dev(sb->s_bdev->bd_dev))
return -EOVERFLOW;
- sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
+ sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
if (!sbi)
return -ENOSPC;
- memset(sbi, 0, sizeof (struct jfs_sb_info));
sb->s_fs_info = sbi;
sbi->sb = sb;
+ sbi->uid = sbi->gid = sbi->umask = -1;
/* initialize the mount flag and determine the default error handler */
flag = JFS_ERR_REMOUNT_RO;
@@ -564,10 +588,14 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
+ if (sbi->uid != -1)
+ seq_printf(seq, ",uid=%d", sbi->uid);
+ if (sbi->gid != -1)
+ seq_printf(seq, ",gid=%d", sbi->gid);
+ if (sbi->umask != -1)
+ seq_printf(seq, ",umask=%03o", sbi->umask);
if (sbi->flag & JFS_NOINTEGRITY)
seq_puts(seq, ",nointegrity");
- else
- seq_puts(seq, ",integrity");
#if defined(CONFIG_QUOTA)
if (sbi->flag & JFS_USRQUOTA)
@@ -617,7 +645,7 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
init_rwsem(&jfs_ip->rdwrlock);
- init_MUTEX(&jfs_ip->commit_sem);
+ mutex_init(&jfs_ip->commit_mutex);
init_rwsem(&jfs_ip->xattr_sem);
spin_lock_init(&jfs_ip->ag_lock);
jfs_ip->active_ag = -1;
@@ -661,12 +689,12 @@ static int __init init_jfs_fs(void)
/*
* I/O completion thread (endio)
*/
- jfsIOthread = kernel_thread(jfsIOWait, NULL, CLONE_KERNEL);
- if (jfsIOthread < 0) {
- jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsIOthread);
+ jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO");
+ if (IS_ERR(jfsIOthread)) {
+ rc = PTR_ERR(jfsIOthread);
+ jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
goto end_txmngr;
}
- wait_for_completion(&jfsIOwait); /* Wait until thread starts */
if (commit_threads < 1)
commit_threads = num_online_cpus();
@@ -674,24 +702,21 @@ static int __init init_jfs_fs(void)
commit_threads = MAX_COMMIT_THREADS;
for (i = 0; i < commit_threads; i++) {
- jfsCommitThread[i] = kernel_thread(jfs_lazycommit, NULL,
- CLONE_KERNEL);
- if (jfsCommitThread[i] < 0) {
- jfs_err("init_jfs_fs: fork failed w/rc = %d",
- jfsCommitThread[i]);
+ jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, "jfsCommit");
+ if (IS_ERR(jfsCommitThread[i])) {
+ rc = PTR_ERR(jfsCommitThread[i]);
+ jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
commit_threads = i;
goto kill_committask;
}
- /* Wait until thread starts */
- wait_for_completion(&jfsIOwait);
}
- jfsSyncThread = kernel_thread(jfs_sync, NULL, CLONE_KERNEL);
- if (jfsSyncThread < 0) {
- jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsSyncThread);
+ jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync");
+ if (IS_ERR(jfsSyncThread)) {
+ rc = PTR_ERR(jfsSyncThread);
+ jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
goto kill_committask;
}
- wait_for_completion(&jfsIOwait); /* Wait until thread starts */
#ifdef PROC_FS_JFS
jfs_proc_init();
@@ -700,13 +725,9 @@ static int __init init_jfs_fs(void)
return register_filesystem(&jfs_fs_type);
kill_committask:
- jfs_stop_threads = 1;
- wake_up_all(&jfs_commit_thread_wait);
for (i = 0; i < commit_threads; i++)
- wait_for_completion(&jfsIOwait);
-
- wake_up(&jfs_IO_thread_wait);
- wait_for_completion(&jfsIOwait); /* Wait for thread exit */
+ kthread_stop(jfsCommitThread[i]);
+ kthread_stop(jfsIOthread);
end_txmngr:
txExit();
free_metapage:
@@ -722,16 +743,13 @@ static void __exit exit_jfs_fs(void)
jfs_info("exit_jfs_fs called");
- jfs_stop_threads = 1;
txExit();
metapage_exit();
- wake_up(&jfs_IO_thread_wait);
- wait_for_completion(&jfsIOwait); /* Wait until IO thread exits */
- wake_up_all(&jfs_commit_thread_wait);
+
+ kthread_stop(jfsIOthread);
for (i = 0; i < commit_threads; i++)
- wait_for_completion(&jfsIOwait);
- wake_up(&jfs_sync_thread_wait);
- wait_for_completion(&jfsIOwait); /* Wait until Sync thread exits */
+ kthread_stop(jfsCommitThread[i]);
+ kthread_stop(jfsSyncThread);
#ifdef PROC_FS_JFS
jfs_proc_clean();
#endif
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index f23048f9471f0..9bc5b7c055ce1 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -934,13 +934,13 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
}
tid = txBegin(inode->i_sb, 0);
- down(&ji->commit_sem);
+ mutex_lock(&ji->commit_mutex);
rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len,
flags);
if (!rc)
rc = txCommit(tid, 1, &inode, 0);
txEnd(tid);
- up(&ji->commit_sem);
+ mutex_unlock(&ji->commit_mutex);
return rc;
}
@@ -1093,12 +1093,12 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
return rc;
tid = txBegin(inode->i_sb, 0);
- down(&ji->commit_sem);
+ mutex_lock(&ji->commit_mutex);
rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
if (!rc)
rc = txCommit(tid, 1, &inode, 0);
txEnd(tid);
- up(&ji->commit_sem);
+ mutex_unlock(&ji->commit_mutex);
return rc;
}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 220058d8616d1..970b6a6aa3378 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -662,12 +662,18 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
* reclaimed while we're stuck in the unlock call. */
fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
+ /*
+ * Note: the server is supposed to either grant us the unlock
+ * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either
+ * case, we want to unlock.
+ */
+ do_vfs_lock(fl);
+
if (req->a_flags & RPC_TASK_ASYNC) {
status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
&nlmclnt_unlock_ops);
/* Hrmf... Do the unlock early since locks_remove_posix()
* really expects us to free the lock synchronously */
- do_vfs_lock(fl);
if (status < 0) {
nlmclnt_release_lockargs(req);
kfree(req);
@@ -680,7 +686,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (status < 0)
return status;
- do_vfs_lock(fl);
if (resp->status == NLM_LCK_GRANTED)
return 0;
diff --git a/fs/namespace.c b/fs/namespace.c
index 058a44865bebd..39c81a8d6316a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1338,7 +1338,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
if (!new_ns)
- goto out;
+ return NULL;
atomic_set(&new_ns->count, 1);
INIT_LIST_HEAD(&new_ns->list);
@@ -1352,7 +1352,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
if (!new_ns->root) {
up_write(&namespace_sem);
kfree(new_ns);
- goto out;
+ return NULL;
}
spin_lock(&vfsmount_lock);
list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1393,7 +1393,6 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
if (altrootmnt)
mntput(altrootmnt);
-out:
return new_ns;
}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 04ab2fc360e79..4e9b3a1b36c5c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -57,6 +57,7 @@
#define NFSDBG_FACILITY NFSDBG_VFS
#define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT)
+static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty);
static kmem_cache_t *nfs_direct_cachep;
/*
@@ -107,6 +108,15 @@ nfs_get_user_pages(int rw, unsigned long user_addr, size_t size,
page_count, (rw == READ), 0,
*pages, NULL);
up_read(&current->mm->mmap_sem);
+ /*
+ * If we got fewer pages than expected from get_user_pages(),
+ * the user buffer runs off the end of a mapping; return EFAULT.
+ */
+ if (result >= 0 && result < page_count) {
+ nfs_free_user_pages(*pages, result, 0);
+ *pages = NULL;
+ result = -EFAULT;
+ }
}
return result;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 984ca3454d044..f8c0066e02e14 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1430,7 +1430,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
if (status == 0)
status = nfs4_do_fsinfo(server, fhandle, info);
out:
- return status;
+ return nfs4_map_errors(status);
}
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 0d4cf94860686..1c72c7f85ddc1 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -98,10 +98,8 @@ asmlinkage sys_nfsservctl(int cmd, struct nfsctl_arg __user *arg, void __user *r
if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
return -EFAULT;
- if (version != NFSCTL_VERSION) {
- printk(KERN_WARNING "nfsd: incompatible version in syscall.\n");
+ if (version != NFSCTL_VERSION)
return -EINVAL;
- }
if (cmd < 0 || cmd >= sizeof(map)/sizeof(map[0]) || !map[cmd].name)
return -EINVAL;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 49bd219275db3..9ee956864445e 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -50,6 +50,32 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
return sd;
}
+/**
+ *
+ * Return -EEXIST if there is already a sysfs element with the same name for
+ * the same parent.
+ *
+ * called with parent inode's i_mutex held
+ */
+int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
+ const unsigned char *new)
+{
+ struct sysfs_dirent * sd;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_element) {
+ const unsigned char *existing = sysfs_get_name(sd);
+ if (strcmp(existing, new))
+ continue;
+ else
+ return -EEXIST;
+ }
+ }
+
+ return 0;
+}
+
+
int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
void * element, umode_t mode, int type)
{
@@ -102,7 +128,11 @@ static int create_dir(struct kobject * k, struct dentry * p,
mutex_lock(&p->d_inode->i_mutex);
*d = lookup_one_len(n, p, strlen(n));
if (!IS_ERR(*d)) {
- error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
+ if (sysfs_dirent_exist(p->d_fsdata, n))
+ error = -EEXIST;
+ else
+ error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
+ SYSFS_DIR);
if (!error) {
error = sysfs_create(*d, mode, init_dir);
if (!error) {
@@ -302,6 +332,7 @@ void sysfs_remove_dir(struct kobject * kobj)
* Drop reference from dget() on entrance.
*/
dput(dentry);
+ kobj->dentry = NULL;
}
int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
@@ -479,7 +510,3 @@ struct file_operations sysfs_dir_operations = {
.read = generic_read_dir,
.readdir = sysfs_readdir,
};
-
-EXPORT_SYMBOL_GPL(sysfs_create_dir);
-EXPORT_SYMBOL_GPL(sysfs_remove_dir);
-EXPORT_SYMBOL_GPL(sysfs_rename_dir);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d0e3d84951652..5e83e72467885 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -301,9 +301,8 @@ static int check_perm(struct inode * inode, struct file * file)
/* No error? Great, allocate a buffer for the file, and store it
* it in file->private_data for easy access.
*/
- buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
+ buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
if (buffer) {
- memset(buffer,0,sizeof(struct sysfs_buffer));
init_MUTEX(&buffer->sem);
buffer->needs_read_fill = 1;
buffer->ops = ops;
@@ -362,10 +361,12 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
{
struct sysfs_dirent * parent_sd = dir->d_fsdata;
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
- int error = 0;
+ int error = -EEXIST;
mutex_lock(&dir->d_inode->i_mutex);
- error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
+ if (!sysfs_dirent_exist(parent_sd, attr->name))
+ error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
+ mode, type);
mutex_unlock(&dir->d_inode->i_mutex);
return error;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 689f7bcfaf304..4c29ac41ac3ec 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -54,11 +54,10 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
if (!sd_iattr) {
/* setting attributes for the first time, allocate now */
- sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+ sd_iattr = kzalloc(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;
@@ -227,12 +226,16 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
void sysfs_hash_and_remove(struct dentry * dir, const char * name)
{
struct sysfs_dirent * sd;
- struct sysfs_dirent * parent_sd = dir->d_fsdata;
+ struct sysfs_dirent * parent_sd;
+
+ if (!dir)
+ return;
if (dir->d_inode == NULL)
/* no inode means this hasn't been made visible yet */
return;
+ parent_sd = dir->d_fsdata;
mutex_lock(&dir->d_inode->i_mutex);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index e38d6338a20dd..d2eac3ceed5f3 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -66,6 +66,7 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
if (!error)
return 0;
+ kobject_put(target);
kfree(sl->link_name);
exit2:
kfree(sl);
@@ -82,12 +83,13 @@ exit1:
int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
struct dentry * dentry = kobj->dentry;
- int error = 0;
+ int error = -EEXIST;
BUG_ON(!kobj || !kobj->dentry || !name);
mutex_lock(&dentry->d_inode->i_mutex);
- error = sysfs_add_link(dentry, name, target);
+ if (!sysfs_dirent_exist(dentry->d_fsdata, name))
+ error = sysfs_add_link(dentry, name, target);
mutex_unlock(&dentry->d_inode->i_mutex);
return error;
}
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3f8953e0e5d00..cf11d5b789d9a 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -5,6 +5,7 @@ extern kmem_cache_t *sysfs_dir_cachep;
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_dirent_exist(struct sysfs_dirent *, const unsigned char *);
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
umode_t, int);