summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-12-01 09:56:43 +0000
committerDavid Woodhouse <dwmw2@infradead.org>2006-12-01 09:56:43 +0000
commitbd3c97a7c718bfb9f1e4f31c16c383a5c6f815eb (patch)
tree3f56594e813c6f35cbacbdb3e137ba5bfd0b3069 /fs
parent6c33cafc794d07c9254c160789120a0e98c088c9 (diff)
parent0215ffb08ce99e2bb59eca114a99499a4d06e704 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig5
-rw-r--r--fs/autofs/inode.c14
-rw-r--r--fs/autofs/waitq.c1
-rw-r--r--fs/autofs4/inode.c17
-rw-r--r--fs/autofs4/waitq.c6
-rw-r--r--fs/block_dev.c58
-rw-r--r--fs/cifs/CHANGES5
-rw-r--r--fs/cifs/connect.c7
-rw-r--r--fs/cifs/file.c31
-rw-r--r--fs/cifs/inode.c18
-rw-r--r--fs/cifs/readdir.c9
-rw-r--r--fs/cifs/sess.c23
-rw-r--r--fs/compat.c20
-rw-r--r--fs/dcache.c156
-rw-r--r--fs/debugfs/inode.c5
-rw-r--r--fs/dlm/lockspace.c14
-rw-r--r--fs/ecryptfs/crypto.c209
-rw-r--r--fs/ecryptfs/dentry.c14
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h22
-rw-r--r--fs/ecryptfs/file.c44
-rw-r--r--fs/ecryptfs/inode.c100
-rw-r--r--fs/ecryptfs/keystore.c114
-rw-r--r--fs/ecryptfs/main.c15
-rw-r--r--fs/ecryptfs/super.c18
-rw-r--r--fs/ext4/resize.c23
-rw-r--r--fs/fat/file.c10
-rw-r--r--fs/fuse/dir.c52
-rw-r--r--fs/fuse/file.c9
-rw-r--r--fs/gfs2/inode.c3
-rw-r--r--fs/gfs2/main.c4
-rw-r--r--fs/gfs2/ops_address.c7
-rw-r--r--fs/gfs2/ops_super.c44
-rw-r--r--fs/hfs/super.c2
-rw-r--r--fs/hugetlbfs/inode.c46
-rw-r--r--fs/inode.c36
-rw-r--r--fs/jbd/transaction.c15
-rw-r--r--fs/jbd2/transaction.c15
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/jfs_imap.c4
-rw-r--r--fs/jfs/xattr.c9
-rw-r--r--fs/lockd/svc.c3
-rw-r--r--fs/msdos/namei.c1
-rw-r--r--fs/nfs/dir.c13
-rw-r--r--fs/nfs/sysctl.c5
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4proc.c26
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/vfs.c6
-rw-r--r--fs/proc/base.c3
-rw-r--r--fs/reiserfs/file.c3
-rw-r--r--fs/reiserfs/super.c1
-rw-r--r--fs/splice.c140
-rw-r--r--fs/vfat/namei.c1
-rw-r--r--fs/xattr.c13
-rw-r--r--fs/xfs/Makefile-linux-2.617
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_dmapi_priv.h28
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c4
-rw-r--r--fs/xfs/support/debug.c4
-rw-r--r--fs/xfs/support/move.c2
-rw-r--r--fs/xfs/support/move.h2
-rw-r--r--fs/xfs/xfs.h23
-rw-r--r--fs/xfs/xfs_bmap.c2
-rw-r--r--fs/xfs/xfs_dir2.c2
-rw-r--r--fs/xfs/xfs_dmapi.h22
-rw-r--r--fs/xfs/xfs_iget.c51
-rw-r--r--fs/xfs/xfs_inode.c64
-rw-r--r--fs/xfs/xfs_inode.h41
-rw-r--r--fs/xfs/xfs_vnodeops.c33
70 files changed, 1098 insertions, 631 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index fee318e6f4bb..7b1511d50b05 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1777,6 +1777,7 @@ config RPCSEC_GSS_KRB5
select CRYPTO
select CRYPTO_MD5
select CRYPTO_DES
+ select CRYPTO_CBC
help
Provides for secure RPC calls by means of a gss-api
mechanism based on Kerberos V5. This is required for
@@ -1795,6 +1796,7 @@ config RPCSEC_GSS_SPKM3
select CRYPTO_MD5
select CRYPTO_DES
select CRYPTO_CAST5
+ select CRYPTO_CBC
help
Provides for secure RPC calls by means of a gss-api
mechanism based on the SPKM3 public-key mechanism.
@@ -2058,8 +2060,7 @@ config CODA_FS_OLD_API
For most cases you probably want to say N.
config AFS_FS
-# for fs/nls/Config.in
- tristate "Andrew File System support (AFS) (Experimental)"
+ tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
select RXRPC
help
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 54c518c89e4c..38ede5c9d6fd 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -25,6 +25,14 @@ void autofs_kill_sb(struct super_block *sb)
struct autofs_sb_info *sbi = autofs_sbi(sb);
unsigned int n;
+ /*
+ * In the event of a failure in get_sb_nodev the superblock
+ * info is not present so nothing else has been setup, so
+ * just exit when we are called from deactivate_super.
+ */
+ if (!sbi)
+ return;
+
if ( !sbi->catatonic )
autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
@@ -136,7 +144,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
- sbi->catatonic = 0;
+ sbi->pipe = NULL;
+ sbi->catatonic = 1;
sbi->exp_timeout = 0;
sbi->oz_pgrp = process_group(current);
autofs_initialize_hash(&sbi->dirhash);
@@ -180,6 +189,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
if ( !pipe->f_op || !pipe->f_op->write )
goto fail_fput;
sbi->pipe = pipe;
+ sbi->catatonic = 0;
/*
* Success! Install the root dentry now to indicate completion.
@@ -198,6 +208,8 @@ fail_iput:
iput(root_inode);
fail_free:
kfree(sbi);
+ s->s_fs_info = NULL;
+ kill_anon_super(s);
fail_unlock:
return -EINVAL;
}
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index 633f628005b4..19a9cafb5ddf 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -41,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
wq = nwq;
}
fput(sbi->pipe); /* Close the pipe */
+ sbi->pipe = NULL;
autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 51fd8595bf85..ce7c0f1dd529 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -99,6 +99,9 @@ static void autofs4_force_release(struct autofs_sb_info *sbi)
struct dentry *this_parent = sbi->sb->s_root;
struct list_head *next;
+ if (!sbi->sb->s_root)
+ return;
+
spin_lock(&dcache_lock);
repeat:
next = this_parent->d_subdirs.next;
@@ -146,6 +149,14 @@ void autofs4_kill_sb(struct super_block *sb)
{
struct autofs_sb_info *sbi = autofs4_sbi(sb);
+ /*
+ * In the event of a failure in get_sb_nodev the superblock
+ * info is not present so nothing else has been setup, so
+ * just exit when we are called from deactivate_super.
+ */
+ if (!sbi)
+ return;
+
sb->s_fs_info = NULL;
if ( !sbi->catatonic )
@@ -310,7 +321,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
sbi->pipefd = -1;
- sbi->catatonic = 0;
+ sbi->pipe = NULL;
+ sbi->catatonic = 1;
sbi->exp_timeout = 0;
sbi->oz_pgrp = process_group(current);
sbi->sb = s;
@@ -388,6 +400,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
goto fail_fput;
sbi->pipe = pipe;
sbi->pipefd = pipefd;
+ sbi->catatonic = 0;
/*
* Success! Install the root dentry now to indicate completion.
@@ -412,6 +425,8 @@ fail_ino:
kfree(ino);
fail_free:
kfree(sbi);
+ s->s_fs_info = NULL;
+ kill_anon_super(s);
fail_unlock:
return -EINVAL;
}
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index c0a6c8d445c7..1e4a539f4417 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -41,10 +41,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
wake_up_interruptible(&wq->queue);
wq = nwq;
}
- if (sbi->pipe) {
- fput(sbi->pipe); /* Close the pipe */
- sbi->pipe = NULL;
- }
+ fput(sbi->pipe); /* Close the pipe */
+ sbi->pipe = NULL;
}
static int autofs4_write(struct file *file, const void *addr, int bytes)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index bc8f27cc4483..36c0e7af9d0f 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -642,34 +642,47 @@ static void free_bd_holder(struct bd_holder *bo)
}
/**
+ * find_bd_holder - find matching struct bd_holder from the block device
+ *
+ * @bdev: struct block device to be searched
+ * @bo: target struct bd_holder
+ *
+ * Returns matching entry with @bo in @bdev->bd_holder_list.
+ * If found, increment the reference count and return the pointer.
+ * If not found, returns NULL.
+ */
+static struct bd_holder *find_bd_holder(struct block_device *bdev,
+ struct bd_holder *bo)
+{
+ struct bd_holder *tmp;
+
+ list_for_each_entry(tmp, &bdev->bd_holder_list, list)
+ if (tmp->sdir == bo->sdir) {
+ tmp->count++;
+ return tmp;
+ }
+
+ return NULL;
+}
+
+/**
* add_bd_holder - create sysfs symlinks for bd_claim() relationship
*
* @bdev: block device to be bd_claimed
* @bo: preallocated and initialized by alloc_bd_holder()
*
- * If there is no matching entry with @bo in @bdev->bd_holder_list,
- * add @bo to the list, create symlinks.
+ * Add @bo to @bdev->bd_holder_list, create symlinks.
*
- * Returns 0 if symlinks are created or already there.
- * Returns -ve if something fails and @bo can be freed.
+ * Returns 0 if symlinks are created.
+ * Returns -ve if something fails.
*/
static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
{
- struct bd_holder *tmp;
int ret;
if (!bo)
return -EINVAL;
- list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
- if (tmp->sdir == bo->sdir) {
- tmp->count++;
- /* We've already done what we need to do here. */
- free_bd_holder(bo);
- return 0;
- }
- }
-
if (!bd_holder_grab_dirs(bdev, bo))
return -EBUSY;
@@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
struct kobject *kobj)
{
int res;
- struct bd_holder *bo;
+ struct bd_holder *bo, *found;
if (!kobj)
return -EINVAL;
@@ -751,9 +764,16 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
res = bd_claim(bdev, holder);
- if (res == 0)
- res = add_bd_holder(bdev, bo);
- if (res)
+ if (res == 0) {
+ found = find_bd_holder(bdev, bo);
+ if (found == NULL) {
+ res = add_bd_holder(bdev, bo);
+ if (res)
+ bd_release(bdev);
+ }
+ }
+
+ if (res || found)
free_bd_holder(bo);
mutex_unlock(&bdev->bd_mutex);
@@ -1131,6 +1151,8 @@ static int blkdev_open(struct inode * inode, struct file * filp)
filp->f_flags |= O_LARGEFILE;
bdev = bd_acquire(inode);
+ if (bdev == NULL)
+ return -ENOMEM;
res = do_open(bdev, filp, BD_MUTEX_NORMAL);
if (res)
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 1eb9a2ec0a3b..0b3c37ef52e0 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,6 +1,11 @@
Version 1.46
------------
Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps.
+Allow null user to be specified on mount ("username="). Do not return
+EINVAL on readdir when filldir fails due to overwritten blocksize
+(fixes FC problem). Return error in rename 2nd attempt retry (ie report
+if rename by handle also fails, after rename by path fails, we were
+not reporting whether the retry worked or not).
Version 1.45
------------
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4093d5332930..71f77914ce93 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -822,10 +822,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
} else if (strnicmp(data, "nouser_xattr",12) == 0) {
vol->no_xattr = 1;
} else if (strnicmp(data, "user", 4) == 0) {
- if (!value || !*value) {
+ if (!value) {
printk(KERN_WARNING
"CIFS: invalid or missing username\n");
return 1; /* needs_arg; */
+ } else if(!*value) {
+ /* null user, ie anonymous, authentication */
+ vol->nullauth = 1;
}
if (strnlen(value, 200) < 200) {
vol->username = value;
@@ -1642,6 +1645,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* BB fixme parse for domain name here */
cFYI(1, ("Username: %s ", volume_info.username));
+ } else if (volume_info.nullauth) {
+ cFYI(1,("null user"));
} else {
cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 976a691c5a68..2436ed8fc840 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -492,10 +492,14 @@ int cifs_close(struct inode *inode, struct file *file)
the struct would be in each open file,
but this should give enough time to
clear the socket */
- cERROR(1,("close with pending writes"));
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1,("close delay, write pending"));
+#endif /* DEBUG2 */
msleep(timeout);
timeout *= 4;
- }
+ }
+ if(atomic_read(&pSMBFile->wrtPending))
+ cERROR(1,("close with pending writes"));
rc = CIFSSMBClose(xid, pTcon,
pSMBFile->netfid);
}
@@ -1806,13 +1810,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
if ((rc < 0) || (smb_read_data == NULL)) {
cFYI(1, ("Read error in readpages: %d", rc));
- /* clean up remaing pages off list */
- while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page,
- lru);
- list_del(&page->lru);
- page_cache_release(page);
- }
break;
} else if (bytes_read > 0) {
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
@@ -1831,13 +1828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
this case is ok - if we are at server EOF
we will hit it on next read */
- /* while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev,
- struct page, list);
- list_del(&page->list);
- page_cache_release(page);
- }
- break; */
+ /* break; */
}
} else {
cFYI(1, ("No bytes read (%d) at offset %lld . "
@@ -1845,14 +1836,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
bytes_read, offset));
/* BB turn off caching and do new lookup on
file size at server? */
- while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page,
- lru);
- list_del(&page->lru);
-
- /* BB removeme - replace with zero of page? */
- page_cache_release(page);
- }
break;
}
if (smb_read_data) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 35d54bb0869a..1ad8c9fcc742 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -885,10 +885,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (info_buf_source != NULL) {
info_buf_target = info_buf_source + 1;
- rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
- info_buf_source, cifs_sb_source->local_nls,
- cifs_sb_source->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
+ info_buf_source,
+ cifs_sb_source->local_nls,
+ cifs_sb_source->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ /* else rc is still EEXIST so will fall through to
+ unlink the target and retry rename */
if (rc == 0) {
rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
info_buf_target,
@@ -937,7 +941,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) {
- CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
+ rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1085,8 +1089,10 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
int err = cifs_revalidate(dentry);
- if (!err)
+ if (!err) {
generic_fillattr(dentry->d_inode, stat);
+ stat->blksize = CIFS_MAX_MSGSIZE;
+ }
return err;
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b5b0a2a41bef..ed18c3965f7b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -896,6 +896,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
tmp_inode->i_ino,obj_type);
if(rc) {
cFYI(1,("filldir rc = %d",rc));
+ /* we can not return filldir errors to the caller
+ since they are "normal" when the stat blocksize
+ is too small - we return remapped error instead */
+ rc = -EOVERFLOW;
}
dput(tmp_dentry);
@@ -1074,6 +1078,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
we want to check for that here? */
rc = cifs_filldir(current_entry, file,
filldir, direntry, tmp_buf, max_len);
+ if(rc == -EOVERFLOW) {
+ rc = 0;
+ break;
+ }
+
file->f_pos++;
if(file->f_pos ==
cifsFile->srch_inf.index_of_last_entry) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index a8a083543ba0..bbdda99dce61 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -90,7 +90,9 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
} */
/* copy user */
if(ses->userName == NULL) {
- /* BB what about null user mounts - check that we do this BB */
+ /* null user mount */
+ *bcc_ptr = 0;
+ *(bcc_ptr+1) = 0;
} else { /* 300 should be long enough for any conceivable user name */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
300, nls_cp);
@@ -98,10 +100,13 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */
/* copy domain */
- if(ses->domainName == NULL)
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
- "CIFS_LINUX_DOM", 32, nls_cp);
- else
+ if(ses->domainName == NULL) {
+ /* Sending null domain better than using a bogus domain name (as
+ we did briefly in 2.6.18) since server will use its default */
+ *bcc_ptr = 0;
+ *(bcc_ptr+1) = 0;
+ bytes_ret = 0;
+ } else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
@@ -144,13 +149,11 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
/* copy domain */
- if(ses->domainName == NULL) {
- strcpy(bcc_ptr, "CIFS_LINUX_DOM");
- bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
- } else {
+ if(ses->domainName != NULL) {
strncpy(bcc_ptr, ses->domainName, 256);
bcc_ptr += strnlen(ses->domainName, 256);
- }
+ } /* else we will send a null domain name
+ so the server will default to its own domain */
*bcc_ptr = 0;
bcc_ptr++;
diff --git a/fs/compat.c b/fs/compat.c
index 50624d4a70c6..8d0a0018a7d2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1835,9 +1835,12 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
} while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
- if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) {
+ if (tsp) {
struct compat_timespec rts;
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+
rts.tv_sec = timeout / HZ;
rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
if (rts.tv_nsec >= NSEC_PER_SEC) {
@@ -1846,8 +1849,19 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
}
if (compat_timespec_compare(&rts, &ts) >= 0)
rts = ts;
- if (copy_to_user(tsp, &rts, sizeof(rts)))
- ret = -EFAULT;
+ if (copy_to_user(tsp, &rts, sizeof(rts))) {
+sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
}
if (ret == -ERESTARTNOHAND) {
diff --git a/fs/dcache.c b/fs/dcache.c
index 2bac4ba1d1d3..fd4a428998ef 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -478,11 +478,12 @@ static void prune_dcache(int count, struct super_block *sb)
up_read(s_umount);
}
spin_unlock(&dentry->d_lock);
- /* Cannot remove the first dentry, and it isn't appropriate
- * to move it to the head of the list, so give up, and try
- * later
+ /*
+ * Insert dentry at the head of the list as inserting at the
+ * tail leads to a cycle.
*/
- break;
+ list_add(&dentry->d_lru, &dentry_unused);
+ dentry_stat.nr_unused++;
}
spin_unlock(&dcache_lock);
}
@@ -556,6 +557,7 @@ repeat:
static void shrink_dcache_for_umount_subtree(struct dentry *dentry)