aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig4
-rw-r--r--fs/binfmt_elf.c4
-rw-r--r--fs/compat_ioctl.c8
-rw-r--r--fs/dquot.c32
-rw-r--r--fs/ecryptfs/crypto.c9
-rw-r--r--fs/ecryptfs/inode.c20
-rw-r--r--fs/ecryptfs/main.c5
-rw-r--r--fs/ecryptfs/messaging.c1
-rw-r--r--fs/ecryptfs/super.c1
-rw-r--r--fs/fat/fatent.c28
-rw-r--r--fs/fs-writeback.c2
-rw-r--r--fs/hfs/bfind.c12
-rw-r--r--fs/hfs/brec.c15
-rw-r--r--fs/hfs/btree.c20
-rw-r--r--fs/hfs/hfs.h5
-rw-r--r--fs/jbd/transaction.c2
-rw-r--r--fs/namei.c4
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c34
-rw-r--r--fs/nfs/nfs4renewd.c2
-rw-r--r--fs/nfs/nfs4state.c5
-rw-r--r--fs/nfs/super.c12
-rw-r--r--fs/nfsd/nfs3xdr.c5
-rw-r--r--fs/nfsd/nfsxdr.c5
-rw-r--r--fs/proc/array.c4
-rw-r--r--fs/proc/base.c20
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/proc_misc.c4
-rw-r--r--fs/proc/task_mmu.c3
-rw-r--r--fs/proc/task_nommu.c4
-rw-r--r--fs/sysfs/dir.c8
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c16
32 files changed, 212 insertions, 85 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 487236c..781b47d 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1112,8 +1112,8 @@ config HFS_FS
help
If you say Y here, you will be able to mount Macintosh-formatted
floppy disks and hard drive partitions with full read-write access.
- Please read <file:fs/hfs/HFS.txt> to learn about the available mount
- options.
+ Please read <file:Documentation/filesystems/hfs.txt> to learn about
+ the available mount options.
To compile this file system support as a module, choose M here: the
module will be called hfs.
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ba8de7c..f0b3171 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1384,7 +1384,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
prstatus->pr_pid = task_pid_vnr(p);
- prstatus->pr_ppid = task_pid_vnr(p->parent);
+ prstatus->pr_ppid = task_pid_vnr(p->real_parent);
prstatus->pr_pgrp = task_pgrp_vnr(p);
prstatus->pr_sid = task_session_vnr(p);
if (thread_group_leader(p)) {
@@ -1430,7 +1430,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_psargs[len] = 0;
psinfo->pr_pid = task_pid_vnr(p);
- psinfo->pr_ppid = task_pid_vnr(p->parent);
+ psinfo->pr_ppid = task_pid_vnr(p->real_parent);
psinfo->pr_pgrp = task_pgrp_vnr(p);
psinfo->pr_sid = task_session_vnr(p);
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index e8b7c3a..da8cb3b 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -10,6 +10,8 @@
* ioctls.
*/
+#include <linux/joystick.h>
+
#include <linux/types.h>
#include <linux/compat.h>
#include <linux/kernel.h>
@@ -2642,6 +2644,12 @@ COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
+/* joystick */
+COMPATIBLE_IOCTL(JSIOCGVERSION)
+COMPATIBLE_IOCTL(JSIOCGAXES)
+COMPATIBLE_IOCTL(JSIOCGBUTTONS)
+COMPATIBLE_IOCTL(JSIOCGNAME(0))
+
/* now things that need handlers */
HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
diff --git a/fs/dquot.c b/fs/dquot.c
index 686ab63..cee7c6f 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -827,6 +827,18 @@ static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
clear_bit(DQ_BLKS_B, &dquot->dq_flags);
}
+static int warning_issued(struct dquot *dquot, const int warntype)
+{
+ int flag = (warntype == QUOTA_NL_BHARDWARN ||
+ warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
+ ((warntype == QUOTA_NL_IHARDWARN ||
+ warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
+
+ if (!flag)
+ return 0;
+ return test_and_set_bit(flag, &dquot->dq_flags);
+}
+
#ifdef CONFIG_PRINT_QUOTA_WARNING
static int flag_print_warnings = 1;
@@ -845,16 +857,12 @@ static inline int need_print_warning(struct dquot *dquot)
}
/* Print warning to user which exceeded quota */
-static void print_warning(struct dquot *dquot, const char warntype)
+static void print_warning(struct dquot *dquot, const int warntype)
{
char *msg = NULL;
struct tty_struct *tty;
- int flag = (warntype == QUOTA_NL_BHARDWARN ||
- warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
- ((warntype == QUOTA_NL_IHARDWARN ||
- warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
- if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
+ if (!need_print_warning(dquot))
return;
mutex_lock(&tty_mutex);
@@ -895,9 +903,6 @@ out_lock:
#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
-/* Size of quota netlink message - actually an upperbound for buffer size */
-#define QUOTA_NL_MSG_SIZE 32
-
/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
.id = GENL_ID_GENERATE,
@@ -914,11 +919,13 @@ static void send_warning(const struct dquot *dquot, const char warntype)
struct sk_buff *skb;
void *msg_head;
int ret;
+ int msg_size = 4 * nla_total_size(sizeof(u32)) +
+ 2 * nla_total_size(sizeof(u64));
/* We have to allocate using GFP_NOFS as we are called from a
* filesystem performing write and thus further recursion into
* the fs to free some data could cause deadlocks. */
- skb = genlmsg_new(QUOTA_NL_MSG_SIZE, GFP_NOFS);
+ skb = genlmsg_new(msg_size, GFP_NOFS);
if (!skb) {
printk(KERN_ERR
"VFS: Not enough memory to send quota warning.\n");
@@ -959,7 +966,7 @@ static void send_warning(const struct dquot *dquot, const char warntype)
"VFS: Failed to send notification message: %d\n", ret);
return;
attr_err_out:
- printk(KERN_ERR "VFS: Failed to compose quota message: %d\n", ret);
+ printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
err_out:
kfree_skb(skb);
}
@@ -970,7 +977,8 @@ static inline void flush_warnings(struct dquot * const *dquots, char *warntype)
int i;
for (i = 0; i < MAXQUOTAS; i++)
- if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN) {
+ if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN &&
+ !warning_issued(dquots[i], warntype[i])) {
#ifdef CONFIG_PRINT_QUOTA_WARNING
print_warning(dquots[i], warntype[i]);
#endif
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index bbed2fd..f8ef0af 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -799,7 +799,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
crypt_stat->cipher, "cbc");
if (rc)
- goto out;
+ goto out_unlock;
crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
CRYPTO_ALG_ASYNC);
kfree(full_alg_name);
@@ -808,12 +808,12 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "
"Error initializing cipher [%s]\n",
crypt_stat->cipher);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- goto out;
+ goto out_unlock;
}
crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
rc = 0;
+out_unlock:
+ mutex_unlock(&crypt_stat->cs_tfm_mutex);
out:
return rc;
}
@@ -1847,6 +1847,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
mutex_init(&tmp_tfm->key_tfm_mutex);
strncpy(tmp_tfm->cipher_name, cipher_name,
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+ tmp_tfm->cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
tmp_tfm->key_size = key_size;
rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm,
tmp_tfm->cipher_name,
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..5a71918 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
ecryptfs_dentry, mode, nd);
if (rc) {
- struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
- struct ecryptfs_inode_info *inode_info =
- ecryptfs_inode_to_private(ecryptfs_inode);
-
- printk(KERN_WARNING "%s: Error creating underlying file; "
- "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
- if (inode_info) {
- mutex_lock(&inode_info->lower_file_mutex);
- if (!inode_info->lower_file) {
- mutex_unlock(&inode_info->lower_file_mutex);
- printk(KERN_ERR "%s: Failure to set underlying "
- "file; rc = [%d]\n", __FUNCTION__, rc);
- goto out_lock;
- }
- mutex_unlock(&inode_info->lower_file_mutex);
- }
+ printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
+ "rc = [%d]\n", __FUNCTION__, rc);
+ goto out_lock;
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode->i_sb, 0);
@@ -451,6 +438,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
dentry->d_inode->i_ctime = dir->i_ctime;
+ d_drop(dentry);
out_unlock:
unlock_parent(lower_dentry);
return rc;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a277754..e5580bc 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -138,11 +138,14 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
inode_info->lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDWR | O_LARGEFILE));
- if (IS_ERR(inode_info->lower_file))
+ if (IS_ERR(inode_info->lower_file)) {
+ dget(lower_dentry);
+ mntget(lower_mnt);
inode_info->lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDONLY
| O_LARGEFILE));
+ }
if (IS_ERR(inode_info->lower_file)) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index a96d341..9cc2aec 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -427,6 +427,7 @@ int ecryptfs_init_messaging(unsigned int transport)
if (!ecryptfs_daemon_id_hash) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
goto out;
}
for (i = 0; i < ecryptfs_hash_buckets; i++)
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index f8cdab2..4859c4e 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode)
fput(inode_info->lower_file);
inode_info->lower_file = NULL;
d_drop(lower_dentry);
- d_delete(lower_dentry);
}
}
mutex_unlock(&inode_info->lower_file_mutex);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 2c1b73f..5fb3669 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -590,21 +590,49 @@ error:
EXPORT_SYMBOL_GPL(fat_free_clusters);
+/* 128kb is the whole sectors for FAT12 and FAT16 */
+#define FAT_READA_SIZE (128 * 1024)
+
+static void fat_ent_reada(struct super_block *sb, struct fat_entry *fatent,
+ unsigned long reada_blocks)
+{
+ struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+ sector_t blocknr;
+ int i, offset;
+
+ ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
+
+ for (i = 0; i < reada_blocks; i++)
+ sb_breadahead(sb, blocknr + i);
+}
+
int fat_count_free_clusters(struct super_block *sb)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct fatent_operations *ops = sbi->fatent_ops;
struct fat_entry fatent;
+ unsigned long reada_blocks, reada_mask, cur_block;
int err = 0, free;
lock_fat(sbi);
if (sbi->free_clusters != -1)
goto out;
+ reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
+ reada_mask = reada_blocks - 1;
+ cur_block = 0;
+
free = 0;
fatent_init(&fatent);
fatent_set_entry(&fatent, FAT_START_ENT);
while (fatent.entry < sbi->max_cluster) {
+ /* readahead of fat blocks */
+ if ((cur_block & reada_mask) == 0) {
+ unsigned long rest = sbi->fat_length - cur_block;
+ fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
+ }
+ cur_block++;
+
err = fat_ent_read_block(sb, &fatent);
if (err)
goto out;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 0fca820..300324b 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -482,8 +482,6 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
if (wbc->nr_to_write <= 0)
break;
}
- if (!list_empty(&sb->s_more_io))
- wbc->more_io = 1;
return; /* Leave any unwritten inodes on s_io */
}
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index f13f149..f8452a0 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -52,6 +52,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
rec = (e + b) / 2;
len = hfs_brec_lenoff(bnode, rec, &off);
keylen = hfs_brec_keylen(bnode, rec);
+ if (keylen == HFS_BAD_KEYLEN) {
+ res = -EINVAL;
+ goto done;
+ }
hfs_bnode_read(bnode, fd->key, off, keylen);
cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
if (!cmpval) {
@@ -67,6 +71,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
if (rec != e && e >= 0) {
len = hfs_brec_lenoff(bnode, e, &off);
keylen = hfs_brec_keylen(bnode, e);
+ if (keylen == HFS_BAD_KEYLEN) {
+ res = -EINVAL;
+ goto done;
+ }
hfs_bnode_read(bnode, fd->key, off, keylen);
}
done:
@@ -198,6 +206,10 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
len = hfs_brec_lenoff(bnode, fd->record, &off);
keylen = hfs_brec_keylen(bnode, fd->record);
+ if (keylen == HFS_BAD_KEYLEN) {
+ res = -EINVAL;
+ goto out;
+ }
fd->keyoffset = off;
fd->keylength = keylen;
fd->entryoffset = off + keylen;
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 5c87cf4..8626ee3 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -44,10 +44,21 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
if (!recoff)
return 0;
- if (node->tree->attributes & HFS_TREE_BIGKEYS)
+ if (node->tree->attributes & HFS_TREE_BIGKEYS) {
retval = hfs_bnode_read_u16(node, recoff) + 2;
- else
+ if (retval > node->tree->max_key_len + 2) {
+ printk(KERN_ERR "hfs: keylen %d too large\n",
+ retval);
+ retval = HFS_BAD_KEYLEN;
+ }
+ } else {
retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
+ if (retval > node->tree->max_key_len + 1) {
+ printk(KERN_ERR "hfs: keylen %d too large\n",
+ retval);
+ retval = HFS_BAD_KEYLEN;
+ }
+ }
}
return retval;
}
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 8a3a650..110dd35 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -61,7 +61,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
mapping = tree->inode->i_mapping;
page = read_mapping_page(mapping, 0, NULL);
if (IS_ERR(page))
- goto free_tree;
+ goto free_inode;
/* Load the header */
head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
@@ -81,6 +81,17 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
goto fail_page;
if (!tree->node_count)
goto fail_page;
+ if ((id == HFS_EXT_CNID) && (tree->max_key_len != HFS_MAX_EXT_KEYLEN)) {
+ printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
+ tree->max_key_len);
+ goto fail_page;
+ }
+ if ((id == HFS_CAT_CNID) && (tree->max_key_len != HFS_MAX_CAT_KEYLEN)) {
+ printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
+ tree->max_key_len);
+ goto fail_page;
+ }
+
tree->node_size_shift = ffs(size) - 1;
tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -88,11 +99,12 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
page_cache_release(page);
return tree;
- fail_page:
- tree->inode->i_mapping->a_ops = &hfs_aops;
+fail_page:
page_cache_release(page);
- free_tree:
+free_inode:
+ tree->inode->i_mapping->a_ops = &hfs_aops;
iput(tree->inode);
+free_tree:
kfree(tree);
return NULL;
}
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index 1445e3a..c6aae61 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -28,6 +28,8 @@
#define HFS_MAX_NAMELEN 128
#define HFS_MAX_VALENCE 32767U
+#define HFS_BAD_KEYLEN 0xFF
+
/* Meanings of the drAtrb field of the MDB,
* Reference: _Inside Macintosh: Files_ p. 2-61
*/
@@ -167,6 +169,9 @@ typedef union hfs_btree_key {
struct hfs_ext_key ext;
} hfs_btree_key;
+#define HFS_MAX_CAT_KEYLEN (sizeof(struct hfs_cat_key) - sizeof(u8))
+#define HFS_MAX_EXT_KEYLEN (sizeof(struct hfs_ext_key) - sizeof(u8))
+
typedef union hfs_btree_key btree_key;
struct hfs_extent {
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 08ff6c7..038ed74 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -288,10 +288,12 @@ handle_t *journal_start(journal_t *journal, int nblocks)
jbd_free_handle(handle);
current->journal_info = NULL;
handle = ERR_PTR(err);
+ goto out;
}
lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+out:
return handle;
}
diff --git a/fs/namei.c b/fs/namei.c
index 3b993db..73e2e66 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1605,7 +1605,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISLNK(inode->i_mode))
return -ELOOP;
- if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
+ if (S_ISDIR(inode->i_mode) && (acc_mode & MAY_WRITE))
return -EISDIR;
/*
@@ -1620,7 +1620,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
return -EACCES;
flag &= ~O_TRUNC;
- } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
+ } else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE))
return -EROFS;
error = vfs_permission(nd, acc_mode);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b35069a..bd1b9d6 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -115,6 +115,7 @@ struct nfs4_lock_state {
#define NFS_LOCK_INITIALIZED 1
int ls_flags;
struct nfs_seqid_counter ls_seqid;
+ struct rpc_sequence ls_sequence;
struct nfs_unique_id ls_id;
nfs4_stateid ls_stateid;
atomic_t ls_count;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f03d9d5..9e2e1c7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -741,10 +741,10 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
if (data->rpc_status == 0) {
memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
sizeof(data->o_res.stateid.data));
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
renew_lease(data->o_res.server, data->timestamp);
data->rpc_done = 1;
}
- nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
}
@@ -759,7 +759,6 @@ static void nfs4_open_confirm_release(void *calldata)
/* In case of error, no cleanup! */
if (!data->rpc_done)
goto out_free;
- nfs_confirm_seqid(&data->owner->so_seqid, 0);
state = nfs4_opendata_to_nfs4_state(data);
if (!IS_ERR(state))
nfs4_close_state(&data->path, state, data->o_arg.open_flags);
@@ -886,7 +885,6 @@ static void nfs4_open_release(void *calldata)
/* In case we need an open_confirm, no cleanup! */
if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
goto out_free;
- nfs_confirm_seqid(&data->owner->so_seqid, 0);
state = nfs4_opendata_to_nfs4_state(data);
if (!IS_ERR(state))
nfs4_close_state(&data->path, state, data->o_arg.open_flags);
@@ -3333,6 +3331,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
p->arg.fh = NFS_FH(inode);
p->arg.fl = &p->fl;
+ if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
+ p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid);
+ if (p->arg.open_seqid == NULL)
+ goto out_free;
+
+ }
p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
if (p->arg.lock_seqid == NULL)
goto out_free;
@@ -3345,6 +3349,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
memcpy(&p->fl, fl, sizeof(p->fl));
return p;
out_free:
+ if (p->arg.open_seqid != NULL)
+ nfs_free_seqid(p->arg.open_seqid);
kfree(p);
return NULL;
}
@@ -3361,23 +3367,23 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
.rpc_cred = sp->so_cred,
};
- if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
- return;
dprintk("%s: begin!\n", __FUNCTION__);
/* Do we need to do an open_to_lock_owner? */
if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
- data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid);
- if (data->arg.open_seqid == NULL) {
- data->rpc_status = -ENOMEM;
- task->tk_action = NULL;
- goto out;
- }
+ if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
+ return;
data->arg.open_stateid = &state->stateid;
data->arg.new_lock_owner = 1;
+ /* Retest in case we raced... */
+ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED))
+ goto do_rpc;
}
+ if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
+ return;
+ data->arg.new_lock_owner = 0;
+do_rpc:
data->timestamp = jiffies;
rpc_call_setup(task, &msg, 0);
-out:
dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
}
@@ -3413,8 +3419,6 @@ static void nfs4_lock_release(void *calldata)
struct nfs4_lockdata *data = calldata;
dprintk("%s: begin!\n", __FUNCTION__);
- if (data->arg.open_seqid != NULL)
- nfs_free_seqid(data->arg.open_seqid);
if (data->cancelled != 0) {
struct rpc_task *task;
task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
@@ -3424,6 +3428,8 @@ static void nfs4_lock_release(void *calldata)
dprintk("%s: cancelling lock!\n", __FUNCTION__);
} else
nfs_free_seqid(data->arg.lock_seqid);
+ if (data->arg.open_seqid != NULL)
+ nfs_free_seqid(data->arg.open_seqid);
nfs4_put_lock_state(data->lsp);
put_nfs_open_context(data->ctx);
kfree(data);
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 3ea352d..5e2e4af 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -133,9 +133,7 @@ nfs4_renewd_prepare_shutdown(struct nfs_server *server)
void
nfs4_kill_renewd(struct nfs_client *clp)
{
- down_read(&clp->cl_sem);
cancel_delayed_work_sync(&clp->cl_renewd);
- up_read(&clp->cl_sem);
}
/*
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 23a9a36..5a39c6f 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -509,7 +509,10 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
lsp = kzalloc(sizeof(*lsp), GFP_KERNEL);
if (lsp == NULL)
return NULL;
- lsp->ls_seqid.sequence = &state->owner->so_sequence;
+ rpc_init_wait_queue(&lsp->ls_sequence.wait, "lock_seqid_waitqueue");
+ spin_lock_init(&lsp->ls_sequence.lock);
+ INIT_LIST_HEAD(&lsp->ls_sequence.list);
+ lsp->ls_seqid.sequence = &lsp->ls_sequence;
atomic_set(&lsp->ls_count, 1);
lsp->ls_owner = fl_owner;
spin_lock(&clp->cl_lock);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ea92920..0b0c72a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1475,7 +1475,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
error = PTR_ERR(mntroot);
goto error_splat_super;
}
- if (mntroot->d_inode->i_op != server->nfs_client->rpc_ops->dir_inode_ops) {
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
dput(mntroot);
error = -ESTALE;
goto error_splat_super;
@@ -1826,6 +1826,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
error = PTR_ERR(mntroot);
goto error_splat_super;
}
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
+ dput(mntroot);
+ error = -ESTALE;
+ goto error_splat_super;
+ }
s->s_flags |= MS_ACTIVE;
mnt->mnt_sb = s;
@@ -1900,6 +1905,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
error = PTR_ERR(mntroot);
goto error_splat_super;
}
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
+ dput(mntroot);
+ error = -ESTALE;
+ goto error_splat_super;
+ }
s->s_flags |= MS_ACTIVE;
mnt->mnt_sb = s;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 2d116d2..f917fd2 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -388,8 +388,11 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
* Round the length of the data which was specified up to
* the next multiple of XDR units and then compare that
* against the length which was actually received.
+ * Note that when RPCSEC/GSS (for example) is used, the
+ * data buffer can be padded so dlen might be larger
+ * than required. It must never be smaller.
*/
- if (dlen != XDR_QUADLEN(len)*4)
+ if (dlen < XDR_QUADLEN(len)*4)
return 0;
if (args->count > max_blocksize) {
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 986f9b3..b86e365 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -313,8 +313,11 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
* Round the length of the data which was specified up to
* the next multiple of XDR units and then compare that
* against the length which was actually received.
+ * Note that when RPCSEC/GSS (for example) is used, the
+ * data buffer can be padded so dlen might be larger
+ * than required. It must never be smaller.
*/
- if (dlen != XDR_QUADLEN(len)*4)
+ if (dlen < XDR_QUADLEN(len)*4)
return 0;
rqstp->rq_vec[0].iov_base = (void*)p;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 65c62e1..eb97f28 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -169,7 +169,7 @@ static inline char *task_state(struct task_struct *p, char *buffer)
ppid = pid_alive(p) ?
task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
tpid = pid_alive(p) && p->ptrace ?
- task_ppid_nr_ns(rcu_dereference(p->parent), ns) : 0;
+ task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
buffer += sprintf(buffer,
"State:\t%s\n"
"Tgid:\t%d\n"
@@ -464,8 +464,8 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
}
sid = task_session_nr_ns(task, ns);
+ ppid = task_tgid_nr_ns(task->real_parent, ns);
pgid = task_pgrp_nr_ns(task, ns);
- ppid = task_ppid_nr_ns(task, ns);
unlock_task_sighand(task, &flags);
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 02a63ac..7411bfb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -202,6 +202,26 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
(task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
security_ptrace(current,task) == 0))
+struct mm_struct *mm_for_maps(struct task_struct *task)
+{
+ struct mm_struct *mm = get_task_mm(task);
+ if (!mm)
+ return NULL;
+ down_read(&mm->mmap_sem);
+ task_lock(task);
+ if (task->mm != mm)
+ goto out;
+ if (task->mm != current->mm && __ptrace_may_attach(task) < 0)
+ goto out;
+ task_unlock(task);
+ return mm;
+out:
+ task_unlock(task);
+ up_read(&mm->mmap_sem);
+ mmput(mm);
+ return NULL;
+}
+
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
int res = 0;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 1820eb2..05b3e90 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -27,6 +27,8 @@ struct vmalloc_info {
unsigned long largest_chunk;
};
+extern struct mm_struct *mm_for_maps(struct task_struct *);
+
#ifdef CONFIG_MMU
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
extern void get_vmalloc_info(struct vmalloc_info *vmi);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index e0d064e..3462bfd 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -410,7 +410,7 @@ static const struct file_operations proc_modules_operations = {
};
#endif
-#ifdef CONFIG_SLAB
+#ifdef CONFIG_SLABINFO
static int slabinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &slabinfo_op);
@@ -728,7 +728,7 @@ void __init proc_misc_init(void)
#endif
create_seq_entry("stat", 0, &proc_stat_operations);
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
-#ifdef CONFIG_SLAB
+#ifdef CONFIG_SLABINFO
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
#ifdef CONFIG_DEBUG_SLAB_LEAK
create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c24d81a..8043a3e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -397,12 +397,11 @@ static void *m_start(struct seq_file *m, loff_t *pos)
if (!priv->task)
return NULL;
- mm = get_task_mm(priv->task);
+ mm = mm_for_maps(priv->task);
if (!mm)
return NULL;
priv->tail_vma = tail_vma = get_gate_vma(priv->task);
- down_read(&mm->mmap_sem);
/* Start with last addr hint */
if (last_addr && (vma = find_vma(mm, last_addr))) {
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index d8b8c71..1932c2c 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -165,15 +165,13 @@ static void *m_start(struct seq_file *m, loff_t *pos)
if (!priv->task)
return NULL;
- mm = get_task_mm(priv->task);
+ mm = mm_for_maps(priv->task);
if (!mm) {
put_task_struct(priv->task);
priv->task = NULL;
return NULL;
}
- down_read(&mm->mmap_sem);
-
/* start from the Nth VMA */
for (vml = mm->context.vmlist; vml; vml = vml->next)
if (n-- == 0)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 3371629..f281cc6 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -678,8 +678,10 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
sd = sysfs_find_dirent(parent_sd, dentry->d_name.name);
/* no such entry */
- if (!sd)
+ if (!sd) {
+ ret = ERR_PTR(-ENOENT);
goto out_unlock;
+ }
/* attach dentry and inode */
inode = sysfs_get_inode(sd);
@@ -781,6 +783,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
old_dentry = sysfs_get_dentry(sd);
if (IS_ERR(old_dentry)) {
error = PTR_ERR(old_dentry);
+ old_dentry = NULL;
goto out;
}
@@ -848,6 +851,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
old_dentry = sysfs_get_dentry(sd);
if (IS_ERR(old_dentry)) {
error = PTR_ERR(old_dentry);
+ old_dentry = NULL;
goto out;
}
old_parent = old_dentry->d_parent;
@@ -855,6 +859,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
new_parent = sysfs_get_dentry(new_parent_sd);
if (IS_ERR(new_parent)) {
error = PTR_ERR(new_parent);
+ new_parent = NULL;
goto out;
}
@@ -878,7 +883,6 @@ again:
error = 0;
d_add(new_dentry, NULL);
d_move(old_dentry, new_dentry);
- dput(new_dentry);
/* Remove from old parent's list and insert into new parent's list. */
sysfs_unlink_sibling(sd);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 4847eb8..21a1c2b 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -261,9 +261,9 @@ xfs_file_readdir(
#else
struct hack_dirent {
- int namlen;
- loff_t offset;
u64 ino;
+ loff_t offset;
+ int namlen;
unsigned int d_type;
char name[];
};
@@ -285,8 +285,10 @@ xfs_hack_filldir(
{
struct hack_callback *buf = __buf;
struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);
+ unsigned int reclen;
- if (buf->used + sizeof(struct hack_dirent) + namlen > buf->len)
+ reclen = ALIGN(sizeof(struct hack_dirent) + namlen, sizeof(u64));
+ if (buf->used + reclen > buf->len)
return -EINVAL;
de->namlen = namlen;
@@ -294,7 +296,7 @@ xfs_hack_filldir(
de->ino = ino;
de->d_type = d_type;
memcpy(de->name, name, namlen);
- buf->used += sizeof(struct hack_dirent) + namlen;
+ buf->used += reclen;
return 0;
}
@@ -334,7 +336,8 @@ xfs_file_readdir(
offset = filp->f_pos;
while (!eof) {
- int reclen;
+ unsigned int reclen;
+
start_offset = offset;
buf.used = 0;
@@ -355,7 +358,8 @@ xfs_file_readdir(
goto done;
}
- reclen = sizeof(struct hack_dirent) + de->namlen;
+ reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen,
+ sizeof(u64));
size -= reclen;
de = (struct hack_dirent *)((char *)de + reclen);
curr_offset = de->offset /* & 0x7fffffff */;