aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/binfmt_elf.c4
-rw-r--r--fs/binfmt_flat.c6
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/buffer.c28
-rw-r--r--fs/char_dev.c2
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/README10
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c56
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c48
-rw-r--r--fs/cifs/misc.c1
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/eventpoll.c2
-rw-r--r--fs/exec.c7
-rw-r--r--fs/ext3/inode.c46
-rw-r--r--fs/ext3/super.c10
-rw-r--r--fs/hostfs/hostfs_kern.c11
-rw-r--r--fs/inode.c23
-rw-r--r--fs/jbd/checkpoint.c5
-rw-r--r--fs/jffs2/compr_rubin.c18
-rw-r--r--fs/jffs2/compr_zlib.c12
-rw-r--r--fs/jfs/jfs_xtree.c6
-rw-r--r--fs/locks.c6
-rw-r--r--fs/mbcache.c2
-rw-r--r--fs/mpage.c19
-rw-r--r--fs/namei.c182
-rw-r--r--fs/nfs/dir.c49
-rw-r--r--fs/nfs/file.c42
-rw-r--r--fs/nfs/idmap.c4
-rw-r--r--fs/nfs/inode.c4
-rw-r--r--fs/nls/nls_base.c2
-rw-r--r--fs/partitions/msdos.c5
-rw-r--r--fs/proc/base.c2
-rw-r--r--fs/proc/mmu.c14
-rw-r--r--fs/proc/proc_devtree.c105
-rw-r--r--fs/reiserfs/namei.c2
-rw-r--r--fs/reiserfs/stree.c1
-rw-r--r--fs/reiserfs/super.c4
-rw-r--r--fs/select.c6
-rw-r--r--fs/udf/udftime.c4
-rw-r--r--fs/xfs/Makefile2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c80
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c50
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c29
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h10
-rw-r--r--fs/xfs/xfs_dfrag.c2
-rw-r--r--fs/xfs/xfs_iget.c51
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_inode.h6
-rw-r--r--fs/xfs/xfs_iomap.c30
-rw-r--r--fs/xfs/xfs_iomap.h25
-rw-r--r--fs/xfs/xfs_mount.c9
-rw-r--r--fs/xfs/xfs_mount.h19
-rw-r--r--fs/xfs/xfs_types.h1
-rw-r--r--fs/xfs/xfs_utils.c2
-rw-r--r--fs/xfs/xfs_utils.h2
-rw-r--r--fs/xfs/xfs_vfsops.c67
-rw-r--r--fs/xfs/xfs_vnodeops.c11
67 files changed, 694 insertions, 498 deletions
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 672a31924f3c..e172180a1d8c 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -47,7 +47,7 @@ static struct file_operations bad_file_ops =
.get_unmapped_area = EIO_ERROR,
};
-struct inode_operations bad_inode_ops =
+static struct inode_operations bad_inode_ops =
{
.create = EIO_ERROR,
.lookup = EIO_ERROR,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ce9423bb2de3..c374be51b041 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -251,7 +251,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
}
/* Populate argv and envp */
- p = current->mm->arg_start;
+ p = current->mm->arg_end = current->mm->arg_start;
while (argc-- > 0) {
size_t len;
__put_user((elf_addr_t)p, argv++);
@@ -1301,7 +1301,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm)
{
- int i, len;
+ unsigned int i, len;
/* first copy the parameters from user space */
memset(psinfo, 0, sizeof(struct elf_prpsinfo));
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index f0cd67d9d31b..c8998dc66882 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
down_write(&current->mm->mmap_sem);
- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0);
+ textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm,
down_write(&current->mm->mmap_sem);
realdatastart = do_mmap(0, 0, data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
+ PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
up_write(&current->mm->mmap_sem);
if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm,
down_write(&current->mm->mmap_sem);
textpos = do_mmap(0, 0, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0);
+ PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index d19d07c49ad3..c0cbd1bc1a02 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -530,7 +530,7 @@ int check_disk_change(struct block_device *bdev)
if (!bdops->media_changed(bdev->bd_disk))
return 0;
- if (__invalidate_device(bdev, 0))
+ if (__invalidate_device(bdev))
printk("VFS: busy inodes on changed media.\n");
if (bdops->revalidate_disk)
diff --git a/fs/buffer.c b/fs/buffer.c
index 5f525b3c6d9f..7e9e409feaa7 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1210,7 +1210,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
return 1;
}
-struct buffer_head *
+static struct buffer_head *
__getblk_slow(struct block_device *bdev, sector_t block, int size)
{
/* Size must be multiple of hard sectorsize */
@@ -1809,7 +1809,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
} while (bh != head);
do {
- get_bh(bh);
if (!buffer_mapped(bh))
continue;
/*
@@ -1838,7 +1837,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
*/
BUG_ON(PageWriteback(page));
set_page_writeback(page);
- unlock_page(page);
do {
struct buffer_head *next = bh->b_this_page;
@@ -1846,9 +1844,9 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
submit_bh(WRITE, bh);
nr_underway++;
}
- put_bh(bh);
bh = next;
} while (bh != head);
+ unlock_page(page);
err = 0;
done:
@@ -1887,7 +1885,6 @@ recover:
bh = head;
/* Recovery: lock and submit the mapped buffers */
do {
- get_bh(bh);
if (buffer_mapped(bh) && buffer_dirty(bh)) {
lock_buffer(bh);
mark_buffer_async_write(bh);
@@ -1910,7 +1907,6 @@ recover:
submit_bh(WRITE, bh);
nr_underway++;
}
- put_bh(bh);
bh = next;
} while (bh != head);
goto done;
@@ -1953,7 +1949,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (!buffer_mapped(bh)) {
err = get_block(inode, block, bh, 1);
if (err)
- goto out;
+ break;
if (buffer_new(bh)) {
clear_buffer_new(bh);
unmap_underlying_metadata(bh->b_bdev,
@@ -1995,10 +1991,12 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
while(wait_bh > wait) {
wait_on_buffer(*--wait_bh);
if (!buffer_uptodate(*wait_bh))
- return -EIO;
+ err = -EIO;
}
- return 0;
-out:
+ if (!err)
+ return err;
+
+ /* Error case: */
/*
* Zero out any newly allocated blocks to avoid exposing stale
* data. If BH_New is set, we know that the block was newly
@@ -2096,9 +2094,12 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
continue;
if (!buffer_mapped(bh)) {
+ int err = 0;
+
fully_mapped = 0;
if (iblock < lblock) {
- if (get_block(inode, iblock, bh, 0))
+ err = get_block(inode, iblock, bh, 0);
+ if (err)
SetPageError(page);
}
if (!buffer_mapped(bh)) {
@@ -2106,7 +2107,8 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
memset(kaddr + i * blocksize, 0, blocksize);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
- set_buffer_uptodate(bh);
+ if (!err)
+ set_buffer_uptodate(bh);
continue;
}
/*
@@ -3115,7 +3117,7 @@ void __init buffer_init(void)
bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0,
- SLAB_PANIC, init_buffer_head, NULL);
+ SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_buffer_head, NULL);
/*
* Limit the bh occupancy to 10% of ZONE_NORMAL
diff --git a/fs/char_dev.c b/fs/char_dev.c
index a745b1d9e545..c1e3537909fc 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -328,7 +328,7 @@ void cd_forget(struct inode *inode)
spin_unlock(&cdev_lock);
}
-void cdev_purge(struct cdev *cdev)
+static void cdev_purge(struct cdev *cdev)
{
spin_lock(&cdev_lock);
while (!list_empty(&cdev->list)) {
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 95483baab706..dab4774ee7bb 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -6,7 +6,8 @@ kills the cifsd thread (NB: killing the cifs kernel threads is not
recommended, unmount and rmmod cifs will kill them when they are
no longer needed). Fix readdir to ASCII servers (ie older servers
which do not support Unicode) and also require asterik.
-
+Fix out of memory case in which data could be written one page
+off in the page cache.
Version 1.33
------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 7b4ac096cd11..34b0cf7111f3 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -32,9 +32,9 @@ the cifs download to your kernel build directory e.g.
6) make modules (or "make" if CIFS VFS not to be built as a module)
For Linux 2.6:
-1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
-at bk://linux.bkbits.net/linux-2.5) and change directory into the top
-of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+1) Download the kernel (e.g. from http://www.kernel.org)
+and change directory into the top of the kernel directory tree
+(e.g. /usr/src/linux-2.5.73)
2) make menuconfig (or make xconfig)
3) select cifs from within the network filesystem choices
4) save and exit
@@ -371,7 +371,7 @@ A partial list of the supported mount options follows:
on newly created files, directories, and devices (create,
mkdir, mknod) which will result in the server setting the
uid and gid to the default (usually the server uid of the
- usern who mounted the share). Letting the server (rather than
+ user who mounted the share). Letting the server (rather than
the client) set the uid and gid is the default. This
parameter has no effect if the CIFS Unix Extensions are not
negotiated.
@@ -384,7 +384,7 @@ A partial list of the supported mount options follows:
client (e.g. when the application is doing large sequential
reads bigger than page size without rereading the same data)
this can provide better performance than the default
- behavior which caches reads (reaadahead) and writes
+ behavior which caches reads (readahead) and writes
(writebehind) through the local Linux client pagecache
if oplock (caching token) is granted and held. Note that
direct allows write operations larger than page size
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d00b3bfe1a52..78af5850c558 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.34"
+#define CIFS_VERSION "1.35"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0010511083fc..ea239dea571e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage,
int remap_special_chars);
#endif /* CONFIG_CIFS_EXPERIMENTAL */
-extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
+extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
const struct nls_table * codepage);
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
const struct nls_table * cp, int mapChars);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 741ff0c69f37..3c628bf667a5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -567,7 +567,7 @@ DelFileRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -665,7 +665,7 @@ MkDirRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -719,7 +719,7 @@ openRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */
name_len =
- cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
+ cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1141,7 +1141,7 @@ renameRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
+ cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1149,7 +1149,7 @@ renameRetry:
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
- cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
+ cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
/* unicode only call */
if(target_name == NULL) {
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
- len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+ len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
dummy_string, 24, nls_codepage, remap);
} else {
- len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+ len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
target_name, PATH_MAX, nls_codepage, remap);
}
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
@@ -1296,7 +1296,7 @@ copyRetry:
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
fromName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */
@@ -1304,7 +1304,7 @@ copyRetry:
pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
- name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
+ name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1453,7 +1453,7 @@ createHardLinkRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1476,7 +1476,7 @@ createHardLinkRetry:
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
+ cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
nls_codepage, remap);
name_len_target++; /* trailing null */
name_len_target *= 2;
@@ -1546,14 +1546,14 @@ winCreateHardLinkRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
+ cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0; /* pad */
pSMB->OldFileName[name_len + 1] = 0x04;
name_len2 =
- cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
+ cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1939,7 +1939,7 @@ queryAclRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2024,7 +2024,7 @@ setAclRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2188,7 +2188,7 @@ QPathInfoRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2269,7 +2269,7 @@ UnixQPathInfoRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2350,7 +2350,7 @@ findUniqueRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
@@ -2435,7 +2435,7 @@ findFirstRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
PATH_MAX, nls_codepage, remap);
/* We can not add the asterik earlier in case
it got remapped to 0xF03A as if it were part of the
@@ -2726,7 +2726,7 @@ GetInodeNumberRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX,nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2837,7 +2837,7 @@ getDFSRetry:
if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
name_len =
- cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
+ cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
searchName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3369,7 +3369,7 @@ SetEOFRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3627,7 +3627,7 @@ SetTimesRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3708,7 +3708,7 @@ SetAttrLgcyRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
+ ConvertToUCS((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
@@ -3759,7 +3759,7 @@ setPermsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3904,7 +3904,7 @@ QAllEAsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -4047,7 +4047,7 @@ QEARetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -4194,7 +4194,7 @@ SetEARetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e3137aa48cdd..3f3538d4a1fa 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
rc = 0;
d_add(direntry, NULL);
} else {
- cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
+ cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
+ rc,full_path));
/* BB special case check for Access Denied - watch security
exposure of returning dir info implicitly via different rc
if file exists or not but no access BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dde2d251fc3d..30ab70ce5547 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1352,6 +1352,8 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
GFP_KERNEL)) {
page_cache_release(page);
cFYI(1, ("Add page cache failed"));
+ data += PAGE_CACHE_SIZE;
+ bytes_read -= PAGE_CACHE_SIZE;
continue;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 670947288262..8d336a900255 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,12 +82,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
- if(*pinode == NULL)
+ if (*pinode == NULL)
return -ENOMEM;
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
the server is really filling in that field? */
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
(*pinode)->i_ino =
(unsigned long)findData.UniqueId;
} /* note ino incremented to unique num in new_inode */
@@ -134,7 +134,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_gid = le64_to_cpu(findData.Gid);
inode->i_nlink = le64_to_cpu(findData.Nlinks);
- if(is_size_safe_to_change(cifsInfo)) {
+ if (is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
@@ -162,7 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
inode->i_fop = &cifs_file_direct_ops;
else
inode->i_fop = &cifs_file_ops;
@@ -198,17 +198,17 @@ int cifs_get_inode_info(struct inode **pinode,
pTcon = cifs_sb->tcon;
cFYI(1,("Getting info on %s ", search_path));
- if((pfindData == NULL) && (*pinode != NULL)) {
- if(CIFS_I(*pinode)->clientCanCacheRead) {
+ if ((pfindData == NULL) && (*pinode != NULL)) {
+ if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1,("No need to revalidate cached inode sizes"));
return rc;
}
}
/* if file info not passed in then get it from server */
- if(pfindData == NULL) {
+ if (pfindData == NULL) {
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
- if(buf == NULL)
+ if (buf == NULL)
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
/* could do find first instead but this returns more info */
@@ -268,7 +268,7 @@ int cifs_get_inode_info(struct inode **pinode,
IndexNumber field is not guaranteed unique? */
#ifdef CONFIG_CIFS_EXPERIMENTAL
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
int rc1 = 0;
__u64 inode_num;
@@ -277,7 +277,7 @@ int cifs_get_inode_info(struct inode **pinode,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(rc1) {
+ if (rc1) {
cFYI(1,("GetSrvInodeNum rc %d", rc1));
/* BB EOPNOSUPP disable SERVER_INUM? */
} else /* do we need cast or hash to ino? */
@@ -355,7 +355,7 @@ int cifs_get_inode_info(struct inode **pinode,
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
inode->i_fop = &cifs_file_direct_ops;
else
inode->i_fop = &cifs_file_ops;
@@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
} else if (rc == -ENOENT) {
d_drop(direntry);
} else if (rc == -ETXTBSY) {
@@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
@@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
@@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
}
/* BB if rc = -ETXTBUSY goto the rename logic BB */
}
}
}
- cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* will force revalidate to get info when
- needed */
- direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ if (direntry->d_inode) {
+ cifsInode = CIFS_I(direntry->d_inode);
+ cifsInode->time = 0; /* will force revalidate to get info
+ when needed */
+ direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
+ }
+ inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */
@@ -576,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
if (direntry->d_inode)
direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
(__u64)current->euid,
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index db14b503d89e..072b4ee8c53e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
break;
case UNI_LESSTHAN:
target[j] = '<';
+ break;
default:
len = cp->uni2char(src_char, &target[j],
NLS_MAX_CHARSET_SIZE);
diff --git a/fs/dcache.c b/fs/dcache.c
index 496a4e08369c..3aa8a7e980d8 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -39,7 +39,7 @@ int sysctl_vfs_cache_pressure = 100;
EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
-seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
+static seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
EXPORT_SYMBOL(dcache_lock);
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 05b966cd6f76..9900e333655a 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -320,7 +320,7 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
/*
* This semaphore is used to serialize ep_free() and eventpoll_release_file().
*/
-struct semaphore epsem;
+static struct semaphore epsem;
/* Safe wake up implementation */
static struct poll_safewake psw;
diff --git a/fs/exec.c b/fs/exec.c
index a8394499926c..e56ee2437025 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -197,7 +197,8 @@ static int count(char __user * __user * argv, int max)
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*/
-int copy_strings(int argc,char __user * __user * argv, struct linux_binprm *bprm)
+static int copy_strings(int argc, char __user * __user * argv,
+ struct linux_binprm *bprm)
{
struct page *kmapped_page = NULL;
char *kaddr = NULL;
@@ -868,9 +869,11 @@ int flush_old_exec(struct linux_binprm * bprm)
if (current->euid == current->uid && current->egid == current->gid)
current->mm->dumpable = 1;
name = bprm->filename;
+
+ /* Copies the binary name from after last slash */
for (i=0; (ch = *(name++)) != '\0';) {
if (ch == '/')
- i = 0;
+ i = 0; /* overwrite what we wrote */
else
if (i < (sizeof(tcomm) - 1))
tcomm[i++] = ch;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index ea5888688f94..0d5fa73b18dc 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -844,12 +844,6 @@ get_block:
return ret;
}
-static int ext3_writepages_get_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh, int create)
-{
- return ext3_direct_io_get_blocks(inode, iblock, 1, bh, create);
-}
-
/*
* `handle' can be NULL if create is zero
*/
@@ -1323,45 +1317,6 @@ out_fail:
return ret;
}
-static int
-ext3_writeback_writepage_helper(struct page *page,
- struct writeback_control *wbc)
-{
- return block_write_full_page(page, ext3_get_block, wbc);
-}
-
-static int
-ext3_writeback_writepages(struct address_space *mapping,
- struct writeback_control *wbc)
-{
- struct inode *inode = mapping->host;
- handle_t *handle = NULL;
- int err, ret = 0;
-
- if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
- return ret;
-
- handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
- return ret;
- }
-
- ret = __mpage_writepages(mapping, wbc, ext3_writepages_get_block,
- ext3_writeback_writepage_helper);
-
- /*
- * Need to reaquire the handle since ext3_writepages_get_block()
- * can restart the handle
- */
- handle = journal_current_handle();
-
- err = ext3_journal_stop(handle);
- if (!ret)
- ret = err;
- return ret;
-}
-
static int ext3_writeback_writepage(struct page *page,
struct writeback_control *wbc)
{
@@ -1599,7 +1554,6 @@ static struct address_space_operations ext3_writeback_aops = {
.readpage = ext3_readpage,
.readpages = ext3_readpages,
.writepage = ext3_writeback_writepage,
- .writepages = ext3_writeback_writepages,
.sync_page = block_sync_page,
.prepare_write = ext3_prepare_write,
.commit_write = ext3_writeback_commit_write,
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 545b440a2d2f..981ccb233ef5 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -225,8 +225,16 @@ void __ext3_std_error (struct super_block * sb, const char * function,
int errno)
{
char nbuf[16];
- const char *errstr = ext3_decode_error(sb, errno, nbuf);
+ const char *errstr;
+
+ /* Special case: if the error is EROFS, and we're not already
+ * inside a transaction, then there's really no point in logging
+ * an error. */
+ if (errno == -EROFS && journal_current_handle() == NULL &&
+ (sb->s_flags & MS_RDONLY))
+ return;
+ errstr = ext3_decode_error(sb, errno, nbuf);
printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n",
sb->s_id, function, errstr);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index e6c63d9cac7b..4bf43ea87c46 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -23,7 +23,6 @@
#include "kern_util.h"
#include "kern.h"
#include "user_util.h"
-#include "2_5compat.h"
#include "init.h"
struct hostfs_inode_info {
@@ -991,13 +990,17 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
goto out_put;
err = read_inode(root_inode);
- if(err)
- goto out_put;
+ if(err){
+ /* No iput in this case because the dput does that for us */
+ dput(sb->s_root);
+ sb->s_root = NULL;
+ goto out_free;
+ }
return(0);
out_put:
- iput(root_inode);
+ iput(root_inode);
out_free:
kfree(name);
out:
diff --git a/fs/inode.c b/fs/inode.c
index af8fd78d2099..801fe7f36280 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -26,7 +26,6 @@
* This is needed for the following functions:
* - inode_has_buffers
* - invalidate_inode_buffers
- * - fsync_bdev
* - invalidate_bdev
*
* FIXME: remove all knowledge of the buffer layer from this file
@@ -332,14 +331,6 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
return busy;
}
-/*
- * This is a two-stage process. First we collect all
- * offending inodes onto the throw-away list, and in
- * the second stage we actually dispose of them. This
- * is because we don't want to sleep while messing
- * with the global lists..
- */
-
/**
* invalidate_inodes - discard the inodes on a device
* @sb: superblock
@@ -366,16 +357,11 @@ int invalidate_inodes(struct super_block * sb)
EXPORT_SYMBOL(invalidate_inodes);
-int __invalidate_device(struct block_device *bdev, int do_sync)
+int __invalidate_device(struct block_device *bdev)
{
- struct super_block *sb;
- int res;
+ struct super_block *sb = get_super(bdev);
+ int res = 0;
- if (do_sync)
- fsync_bdev(bdev);
-
- res = 0;
- sb = get_super(bdev);
if (sb) {
/*
* no need to lock the super, get_super holds the
@@ -390,7 +376,6 @@ int __invalidate_device(struct block_device *bdev, int do_sync)
invalidate_bdev(bdev, 0);
return res;
}
-
EXPORT_SYMBOL(__invalidate_device);
static int can_unuse(struct inode *inode)
@@ -1336,7 +1321,7 @@ void __init inode_init(unsigned long mempages)
/* inode slab cache */
inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode),
- 0, SLAB_PANIC, init_once, NULL);
+ 0, SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_once, NULL);
set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
/* Hash may have been set up in inode_init_early */
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 98d830401c56..5a97e346bd95 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
} else {
jbd_unlock_bh_state(bh);
}
- jh = next_jh;
} while (jh != last_jh);
return ret;
@@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal)
}
} while (jh != last_jh && !retry);
- if (batch_count)
+ if (batch_count) {
__flush_batch(journal, bhs, &batch_count);
+ retry = 1;
+ }
/*
* If someone cleaned up this transaction while we slept, we're
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index 450d6624181f..09422388fb96 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -228,8 +228,10 @@ int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out,
return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
}
#endif
-int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t *sourcelen, uint32_t *dstlen, void *model)
+static int jffs2_dynrubin_compress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t *sourcelen, uint32_t *dstlen,
+ void *model)
{
int bits[8];
unsigned char histo[256];
@@ -306,15 +308,19 @@ static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata
}
-int jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t sourcelen, uint32_t dstlen, void *model)
+static int jffs2_rubinmips_decompress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t sourcelen, uint32_t dstlen,
+ void *model)
{
rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
return 0;
}
-int jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t sourcelen, uint32_t dstlen, void *model)
+static int jffs2_dynrubin_decompress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t sourcelen, uint32_t dstlen,
+ void *model)
{
int bits[8];
int c;
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 9f9932c22adb..078a30e406b5 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -69,8 +69,10 @@ static void free_workspaces(void)
#define free_workspaces() do { } while(0)
#endif /* __KERNEL__ */
-int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t *sourcelen, uint32_t *dstlen, void *model)
+static int jffs2_zlib_compress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t *sourcelen, uint32_t *dstlen,
+ void *model)
{
int ret;
@@ -135,8 +137,10 @@ int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
return ret;
}
-int jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t srclen, uint32_t destlen, void *model)
+static int jffs2_zlib_decompress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t srclen, uint32_t destlen,
+ void *model)
{
int ret;
int wbits = MAX_WBITS;
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 2c1f311914a1..31b34db4519e 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) International Business Machines Corp., 2000-2004
+ * Copyright (C) International Business Machines Corp., 2000-2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -688,7 +688,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
/* search hit - internal page:
* descend/search its child page
*/
- if (index < p->header.nextindex - 1)
+ if (index < le16_to_cpu(p->header.nextindex)-1)
next = offsetXAD(&p->xad[index + 1]);
goto next;
}
@@ -705,7 +705,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or maxentry index.
*/
- if (base < p->header.nextindex)
+ if (base < le16_to_cpu(p->header.nextindex))
next = offsetXAD(&p->xad[base]);
/*
* search miss - leaf page:
diff --git a/fs/locks.c b/fs/locks.c
index 1792ce547af7..3fa6a7ce57a7 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -406,12 +406,12 @@ static void lease_release_private_callback(struct file_lock *fl)
fl->fl_file->f_owner.signum = 0;
}
-int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
+static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
{
return fl->fl_file == try->fl_file;
}
-struct lock_manager_operations lease_manager_ops = {
+static struct lock_manager_operations lease_manager_ops = {
.fl_break = lease_break_callback,
.fl_release_private = lease_release_private_callback,
.fl_mylease = lease_mylease_callback,
@@ -1274,7 +1274,7 @@ int fcntl_getlease(struct file *filp)
*
* Called with kernel lock held.
*/
-int __setlease(struct file *filp, long arg, struct file_lock **flp)
+static int __setlease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease = *flp;
struct dentry *dentry = filp->f_dentry;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index f9e4d2700cd8..c7170b9221a3 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -57,7 +57,7 @@
#define MB_CACHE_WRITER ((unsigned short)~0U >> 1)
-DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
+static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
diff --git a/fs/mpage.c b/fs/mpage.c
index 32c7c8fcfce7..bb9aebe93862 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -79,15 +79,18 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
if (--bvec >= bio->bi_io_vec)
prefetchw(&bvec->bv_page->flags);
- if (!uptodate)
+ if (!uptodate){
SetPageError(page);
+ if (page->mapping)
+ set_bit(AS_EIO, &page->mapping->flags);
+ }
end_page_writeback(page);
} while (bvec >= bio->bi_io_vec);
bio_put(bio);
return 0;
}
-struct bio *mpage_bio_submit(int rw, struct bio *bio)
+static struct bio *mpage_bio_submit(int rw, struct bio *bio)
{
bio->bi_end_io = mpage_end_io_read;
if (rw == WRITE)
@@ -627,15 +630,6 @@ int
mpage_writepages(struct address_space *mapping,
struct writeback_control *wbc, get_block_t get_block)
{
- return __mpage_writepages(mapping, wbc, get_block,
- mapping->a_ops->writepage);
-}
-
-int
-__mpage_writepages(struct address_space *mapping,
- struct writeback_control *wbc, get_block_t get_block,
- writepage_t writepage_fn)
-{
struct backing_dev_info *bdi = mapping->backing_dev_info;
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
@@ -725,7 +719,7 @@ retry:
} else {
bio = __mpage_writepage(bio, page, get_block,
&last_block_in_bio, &ret, wbc,
- writepage_fn);
+ page->mapping->a_ops->writepage);
}
if (unlikely(ret == WRITEPAGE_ACTIVATE))
unlock_page(page);
@@ -755,7 +749,6 @@ retry:
return ret;
}
EXPORT_SYMBOL(mpage_writepages);
-EXPORT_SYMBOL(__mpage_writepages);
int mpage_writepage(struct page *page, get_block_t get_block,
struct writeback_control *wbc)
diff --git a/fs/namei.c b/fs/namei.c
index 9e4aef2a1a21..a7f7f44119b3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -493,12 +493,21 @@ fail:
return PTR_ERR(link);
}
-static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
+struct path {
+ struct vfsmount *mnt;
+ struct dentry *dentry;
+};
+
+static inline int __do_follow_link(struct path *path, struct nameidata *nd)
{
int error;
+ struct dentry *dentry = path->dentry;
- touch_atime(nd->mnt, dentry);
+ touch_atime(path->mnt, dentry);
nd_set_link(nd, NULL);
+
+ if (path->mnt == nd->mnt)
+ mntget(path->mnt);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
if (!error) {
char *s = nd_get_link(nd);
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
if (dentry->d_inode->i_op->put_link)
dentry->d_inode->i_op->put_link(dentry, nd);
}
+ dput(dentry);
+ mntput(path->mnt);
return error;
}
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
* Without that kind of total limit, nasty chains of consecutive
* symlinks can cause almost arbitrarily long lookups.
*/
-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
+static inline int do_follow_link(struct path *path, struct nameidata *nd)
{
int err = -ELOOP;
if (current->link_count >= MAX_NESTED_LINKS)
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
goto loop;
BUG_ON(nd->depth >= MAX_NESTED_LINKS);
cond_resched();
- err = security_inode_follow_link(dentry, nd);
+ err = security_inode_follow_link(path->dentry, nd);
if (err)
goto loop;
current->link_count++;
current->total_link_count++;
nd->depth++;
- err = __do_follow_link(dentry, nd);
+ err = __do_follow_link(path, nd);
current->link_count--;
nd->depth--;
return err;
loop:
+ dput(path->dentry);
+ if (path->mnt != nd->mnt)
+ mntput(path->mnt);
path_release(nd);
return err;
}
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry)
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+static int __follow_mount(struct path *path)
{
int res = 0;
+ while (d_mountpoint(path->dentry)) {
+ struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
+ if (!mounted)
+ break;
+ dput(path->dentry);
+ if (res)
+ mntput(path->mnt);
+ path->mnt = mounted;
+ path->dentry = dget(mounted->mnt_root);
+ res = 1;
+ }
+ return res;
+}
+
+static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
while (d_mountpoint(*dentry)) {
struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
if (!mounted)
break;
+ dput(*dentry);
mntput(*mnt);
*mnt = mounted;
- dput(*dentry);
*dentry = dget(mounted->mnt_root);
- res = 1;
}
- return res;
}
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
+int follow_down(struct vfsmount **mnt, struct dentry **dentry)
{
struct vfsmount *mounted;
mounted = lookup_mnt(*mnt, *dentry);
if (mounted) {
+ dput(*dentry);
mntput(*mnt);
*mnt = mounted;
- dput(*dentry);
*dentry = dget(mounted->mnt_root);
return 1;
}
return 0;
}
-int follow_down(struct vfsmount **mnt, struct dentry **dentry)
-{
- return __follow_down(mnt,dentry);
-}
-
-static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
+static inline void follow_dotdot(struct nameidata *nd)
{
while(1) {
struct vfsmount *parent;
- struct dentry *old = *dentry;
+ struct dentry *old = nd->dentry;
read_lock(&current->fs->lock);
- if (*dentry == current->fs->root &&
- *mnt == current->fs->rootmnt) {
+ if (nd->dentry == current->fs->root &&
+ nd->mnt == current->fs->rootmnt) {
read_unlock(&current->fs->lock);
break;
}
read_unlock(&current->fs->lock);
spin_lock(&dcache_lock);
- if (*dentry != (*mnt)->mnt_root) {
- *dentry = dget((*dentry)->d_parent);
+ if (nd->dentry != nd->mnt->mnt_root) {
+ nd->dentry = dget(nd->dentry->d_parent);
spin_unlock(&dcache_lock);
dput(old);
break;
}
spin_unlock(&dcache_lock);
spin_lock(&vfsmount_lock);
- parent = (*mnt)->mnt_parent;
- if (parent == *mnt) {
+ parent = nd->mnt->mnt_parent;
+ if (parent == nd->mnt) {
spin_unlock(&vfsmount_lock);
break;
}
mntget(parent);
- *dentry = dget((*mnt)->mnt_mountpoint);
+ nd->dentry = dget(nd->mnt->mnt_mountpoint);
spin_unlock(&vfsmount_lock);
dput(old);
- mntput(*mnt);
- *mnt = parent;
+ mntput(nd->mnt);
+ nd->mnt = parent;
}
- follow_mount(mnt, dentry);
+ follow_mount(&nd->mnt, &nd->dentry);
}
-struct path {
- struct vfsmount *mnt;
- struct dentry *dentry;
-};
-
/*
* It's more convoluted than I'd like it to be, but... it's still fairly
* small and for now I'd prefer to have fast path as straight as possible.
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
done:
path->mnt = mnt;
path->dentry = dentry;
+ __follow_mount(path);
return 0;
need_lookup:
@@ -686,11 +705,11 @@ fail:
/*
* Name resolution.
+ * This is the basic name resolution function, turning a pathname into
+ * the final dentry. We expect 'base' to be positive and a directory.
*
- * This is the basic name resolution function, turning a pathname
- * into the final dentry.
- *
- * We expect 'base' to be positive and a directory.
+ * Returns 0 and nd will have valid dentry and mnt on success.
+ * Returns error and drops reference to input namei data on failure.
*/
static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
{
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
case 2:
if (this.name[1] != '.')
break;
- follow_dotdot(&nd->mnt, &nd->dentry);
+ follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
err = do_lookup(nd, &this, &next);
if (err)
break;
- /* Check mountpoints.. */
- follow_mount(&next.mnt, &next.dentry);
err = -ENOENT;
inode = next.dentry->d_inode;
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
goto out_dput;
if (inode->i_op->follow_link) {
- mntget(next.mnt);
- err = do_follow_link(next.dentry, nd);
- dput(next.dentry);
- mntput(next.mnt);
+ err = do_follow_link(&next, nd);
if (err)
goto return_err;
err = -ENOENT;
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
break;
} else {
dput(nd->dentry);
+ if (nd->mnt != next.mnt)
+ mntput(nd->mnt);
nd->mnt = next.mnt;
nd->dentry = next.dentry;
}
@@ -819,7 +835,7 @@ last_component:
case 2:
if (this.name[1] != '.')
break;
- follow_dotdot(&nd->mnt, &nd->dentry);
+ follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
@@ -833,19 +849,17 @@ last_component:
err = do_lookup(nd, &this, &next);
if (err)
break;
- follow_mount(&next.mnt, &next.dentry);
inode = next.dentry->d_inode;
if ((lookup_flags & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
- mntget(next.mnt);
- err = do_follow_link(next.dentry, nd);
- dput(next.dentry);
- mntput(next.mnt);
+ err = do_follow_link(&next, nd);
if (err)
goto return_err;
inode = nd->dentry->d_inode;
} else {
dput(nd->dentry);
+ if (nd->mnt != next.mnt)
+ mntput(nd->mnt);
nd->mnt = next.mnt;
nd->dentry = next.dentry;
}
@@ -885,6 +899,8 @@ return_base:
return 0;
out_dput:
dput(next.dentry);
+ if (nd->mnt != next.mnt)
+ mntput(next.mnt);
break;
}
path_release(nd);
@@ -929,8 +945,10 @@ int fastcall path_walk(const char * name, struct nameidata *nd)
return link_path_walk(name, nd);
}
-/* SMP-safe */
-/* returns 1 if everything is done */
+/*
+ * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if
+ * everything is done. Returns 0 and drops input nd, if lookup failed;
+ */
static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
{
if (path_walk(name, nd))
@@ -994,9 +1012,10 @@ set_it:
}
}
+/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
{
- int retval;
+ int retval = 0;
nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags;
@@ -1009,7 +1028,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
nd->dentry = dget(current->fs->altroot);
read_unlock(&current->fs->lock);
if (__emul_lookup_dentry(name,nd))
- return 0;
+ goto out; /* found in altroot */
read_lock(&current->fs->lock);
}
nd->mnt = mntget(current->fs->rootmnt);
@@ -1021,6 +1040,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
read_unlock(&current->fs->lock);
current->total_link_count = 0;
retval = link_path_walk(name, nd);
+out:
if (unlikely(current->audit_context
&& nd && nd->dentry && nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode);
@@ -1394,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
{
int acc_mode, error = 0;
- struct dentry *dentry;
+ struct path path;
struct dentry *dir;
int count = 0;
@@ -1438,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
dir = nd->dentry;
nd->flags &= ~LOOKUP_PARENT;
down(&dir->d_inode->i_sem);
- dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.mnt = nd->mnt;
do_last:
- error = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
+ error = PTR_ERR(path.dentry);
+ if (IS_ERR(path.dentry)) {
up(&dir->d_inode->i_sem);
goto exit;
}
/* Negative dentry, just create the file */
- if (!dentry->d_inode) {
+ if (!path.dentry->d_inode) {
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, dentry, mode, nd);
+ error = vfs_create(dir->d_inode, path.dentry, mode, nd);
up(&dir->d_inode->i_sem);
dput(nd->dentry);
- nd->dentry = dentry;
+ nd->dentry = path.dentry;
if (error)
goto exit;
/* Don't check for write permission, don't truncate */
@@ -1472,22 +1493,24 @@ do_last:
if (flag & O_EXCL)
goto exit_dput;
- if (d_mountpoint(dentry)) {
+ if (__follow_mount(&path)) {
error = -ELOOP;
if (flag & O_NOFOLLOW)
goto exit_dput;
- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
}
error = -ENOENT;
- if (!dentry->d_inode)
+ if (!path.dentry->d_inode)
goto exit_dput;
- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
+ if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
goto do_link;
dput(nd->dentry);
- nd->dentry = dentry;
+ nd->dentry = path.dentry;
+ if (nd->mnt != path.mnt)
+ mntput(nd->mnt);
+ nd->mnt = path.mnt;
error = -EISDIR;
- if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
+ if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
goto exit;
ok:
error = may_open(nd, acc_mode, flag);
@@ -1496,7 +1519,9 @@ ok:
return 0;
exit_dput:
- dput(dentry);
+ dput(path.dentry);
+ if (nd->mnt != path.mnt)
+ mntput(path.mnt);
exit:
path_release(nd);
return error;
@@ -1516,18 +1541,15 @@ do_link:
* are done. Procfs-like symlinks just set LAST_BIND.
*/
nd->flags |= LOOKUP_PARENT;
- error = security_inode_follow_link(dentry, nd);
+ error = security_inode_follow_link(path.dentry, nd);
if (error)
goto exit_dput;
- error = __do_follow_link(dentry, nd);
- dput(dentry);
+ error = __do_follow_link(&path, nd);
if (error)
return error;
nd->flags &= ~LOOKUP_PARENT;
- if (nd->last_type == LAST_BIND) {
- dentry = nd->dentry;
+ if (nd->last_type == LAST_BIND)
goto ok;
- }
error = -EISDIR;
if (nd->last_type != LAST_NORM)
goto exit;
@@ -1542,7 +1564,8 @@ do_link:
}
dir = nd->dentry;
down(&dir->d_inode->i_sem);
- dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.mnt = nd->mnt;
putname(nd->last.name);
goto do_last;
}
@@ -1576,6 +1599,7 @@ enoent:
fail:
return dentry;
}
+EXPORT_SYMBOL_GPL(lookup_create);
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
@@ -2067,8 +2091,8 @@ exit:
* ->i_sem on parents, which works but leads to some truely excessive
* locking].
*/
-int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
int error = 0;
struct inode *target;
@@ -2112,8 +2136,8 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
return error;
}
-int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
struct inode *target;
int error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96acd5d37..ff6155f5e8d9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -528,19 +528,39 @@ static inline void nfs_renew_times(struct dentry * dentry)
dentry->d_time = jiffies;
}
+/*
+ * Return the intent data that applies to this particular path component
+ *
+ * Note that the current set of intents only apply to the very last
+ * component of the path.
+ * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
+ */
+static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
+{
+ if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
+ return 0;
+ return nd->flags & mask;
+}
+
+/*
+ * Inode and filehandle revalidation for lookups.
+ *
+ * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
+ * or if the intent information indicates that we're about to open this
+ * particular file and the "nocto" mount flag is not set.
+ *
+ */
static inline
int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
{
struct nfs_server *server = NFS_SERVER(inode);
if (nd != NULL) {
- int ndflags = nd->flags;
/* VFS wants an on-the-wire revalidation */
- if (ndflags & LOOKUP_REVAL)
+ if (nd->flags & LOOKUP_REVAL)
goto out_force;
/* This is an open(2) */
- if ((ndflags & LOOKUP_OPEN) &&
- !(ndflags & LOOKUP_CONTINUE) &&
+ if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
!(server->flags & NFS_MOUNT_NOCTO))
goto out_force;
}
@@ -560,12 +580,8 @@ static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
- int ndflags = 0;
-
- if (nd)
- ndflags = nd->flags;
/* Don't revalidate a negative dentry if we're creating a new file */
- if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
+ if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
return 0;
return !nfs_check_verifier(dir, dentry);
}
@@ -700,12 +716,16 @@ struct dentry_operations nfs_dentry_operations = {
.d_iput = nfs_dentry_iput,
};
+/*
+ * Use intent information to check whether or not we're going to do
+ * an O_EXCL create using this path component.
+ */
static inline
int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
{
if (NFS_PROTO(dir)->version == 2)
return 0;
- if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+ if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
return 0;
return (nd->intent.open.flags & O_EXCL) != 0;
}
@@ -772,12 +792,13 @@ struct dentry_operations nfs4_dentry_operations = {
.d_iput = nfs_dentry_iput,
};
+/*
+ * Use intent information to determine whether we need to substitute
+ * the NFSv4-style stateful OPEN for the LOOKUP call
+ */
static int is_atomic_open(struct inode *dir, struct nameidata *nd)
{
- if (!nd)
- return 0;
- /* Check that we are indeed trying to open this file */
- if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
+ if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
return 0;
/* NFS does not (yet) have a stateful open for directories */
if (nd->flags & LOOKUP_DIRECTORY)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6dcff5..55c907592490 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,6 +37,7 @@
static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
+static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
struct file_operations nfs_file_operations = {
- .llseek = remote_llseek,
+ .llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = nfs_file_read,
@@ -114,6 +115,45 @@ nfs_file_release(struct inode *inode, struct file *filp)
return NFS_PROTO(inode)->file_release(inode, filp);
}
+/**
+ * nfs_revalidate_size - Revalidate the file size
+ * @inode - pointer to inode struct
+ * @file - pointer to struct file
+ *
+ * Revalidates the file length. This is basically a wrapper around
+ * nfs_revalidate_inode() that takes into account the fact that we may
+ * have cached writes (in which case we don't care about the server's
+ * idea of what the file length is), or O_DIRECT (in which case we
+ * shouldn't trust the cache).
+ */
+static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (server->flags & NFS_MOUNT_NOAC)
+ goto force_reval;
+ if (filp->f_flags & O_DIRECT)
+ goto force_reval;
+ if (nfsi->npages != 0)
+ return 0;
+ return nfs_revalidate_inode(server, inode);
+force_reval:
+ return __nfs_revalidate_inode(server, inode);
+}
+
+static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+{
+ /* origin == SEEK_END => we must revalidate the cached file length */
+ if (origin == 2) {
+ struct inode *inode = filp->f_mapping->host;
+ int retval = nfs_revalidate_file_size(inode, filp);
+ if (retval < 0)
+ return (loff_t)retval;
+ }
+ return remote_llseek(filp, offset, origin);
+}
+
/*
* Flush all dirty pages, and check for write errors.
*
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index b74c4e3a64e2..87f4f9aeac86 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -79,7 +79,7 @@ static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *,
char __user *, size_t);
static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
size_t);
-void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
+static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
static unsigned int fnvhash32(const void *, size_t);
@@ -434,7 +434,7 @@ out:
return ret;
}
-void
+static void
idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
{
struct idmap_msg *im = msg->data;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6345f26e87ee..f2317f3e29f9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1904,7 +1904,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
}
}
-int nfs_init_inodecache(void)
+static int nfs_init_inodecache(void)
{
nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
sizeof(struct nfs_inode),
@@ -1916,7 +1916,7 @@ int nfs_init_inodecache(void)
return 0;
}
-void nfs_destroy_inodecache(void)
+static void nfs_destroy_inodecache(void)
{
if (kmem_cache_destroy(nfs_inode_cachep))
printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 897512796edb..a912debcd20b 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -243,7 +243,7 @@ void unload_nls(struct nls_table *nls)
module_put(nls->owner);
}
-wchar_t charset2uni[256] = {
+static wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 17ee1b4ff087..584a27b2bbd5 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -114,9 +114,6 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
*/
for (i=0; i<4; i++, p++) {
u32 offs, size, next;
-
- if (SYS_IND(p) == 0)
- continue;
if (!NR_SECTS(p) || is_extended_partition(p))
continue;
@@ -433,8 +430,6 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
for (slot = 1 ; slot <= 4 ; slot++, p++) {
u32 start = START_SECT(p)*sector_size;
u32 size = NR_SECTS(p)*sector_size;
- if (SYS_IND(p) == 0)
- continue;
if (!size)
continue;
if (is_extended_partition(p)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 07cafdf74ef2..e31903aadd96 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -820,7 +820,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
goto out_free_page;
}
- length = audit_set_loginuid(task->audit_context, loginuid);
+ length = audit_set_loginuid(task, loginuid);
if (likely(length == 0))
length = count;
diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c
index a7041038ad56..25d2d9c6e329 100644
--- a/fs/proc/mmu.c
+++ b/fs/proc/mmu.c
@@ -50,13 +50,23 @@ void get_vmalloc_info(struct vmalloc_info *vmi)
read_lock(&vmlist_lock);
for (vma = vmlist; vma; vma = vma->next) {
+ unsigned long addr = (unsigned long) vma->addr;
+
+ /*
+ * Some archs keep another range for modules in vmlist
+ */
+ if (addr < VMALLOC_START)
+ continue;
+ if (addr >= VMALLOC_END)
+ break;
+
vmi->used += vma->size;
- free_area_size = (unsigned long) vma->addr - prev_end;
+ free_area_size = addr - prev_end;
if (vmi->largest_chunk < free_area_size)
vmi->largest_chunk = free_area_size;
- prev_end = vma->size + (unsigned long) vma->addr;
+ prev_end = vma->size + addr;
}
if (VMALLOC_END - prev_end > vmi->largest_chunk)
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 67423c696c0a..6fd57f154197 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -12,15 +12,8 @@
#include <asm/uaccess.h>
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
-static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de)
-{
-}
-
-static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de)
-{
-}
-
-static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de)
+static inline void set_node_proc_entry(struct device_node *np,
+ struct proc_dir_entry *de)
{
}
#endif
@@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off,
/*
* Process a node, adding entries for its children and its properties.
*/
-void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de)
+void proc_device_tree_add_node(struct device_node *np,
+ struct proc_dir_entry *de)
{
struct property *pp;
struct proc_dir_entry *ent;
- struct device_node *child, *sib;
- const char *p, *at;
- int l;
- struct proc_dir_entry *list, **lastp, *al;
+ struct device_node *child;
+ struct proc_dir_entry *list = NULL, **lastp;
+ const char *p;
set_node_proc_entry(np, de);
lastp = &list;
- for (pp = np->properties; pp != 0; pp = pp->next) {
- /*
- * Unfortunately proc_register puts each new entry
- * at the beginning of the list. So we rearrange them.
- */
- ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ?
- S_IRUGO : S_IRUSR, de, property_read_proc, pp);
- if (ent == 0)
- break;
- if (!strncmp(pp->name, "security-", 9))
- ent->size = 0; /* don't leak number of password chars */
- else
- ent->size = pp->length;
- *lastp = ent;
- lastp = &ent->next;
- }
- child = NULL;
- while ((child = of_get_next_child(np, child))) {
+ for (child = NULL; (child = of_get_next_child(np, child));) {
p = strrchr(child->full_name, '/');
if (!p)
p = child->full_name;
else
++p;
- /* chop off '@0' if the name ends with that */
- l = strlen(p);
- if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
- l -= 2;
ent = proc_mkdir(p, de);
if (ent == 0)
break;
*lastp = ent;
+ ent->next = NULL;
lastp = &ent->next;
proc_device_tree_add_node(child, ent);
-
- /*
- * If we left the address part on the name, consider
- * adding symlinks from the name and address parts.
- */
- if (p[l] != 0 || (at = strchr(p, '@')) == 0)
- continue;
-
+ }
+ of_node_put(child);
+ for (pp = np->properties; pp != 0; pp = pp->next) {
/*
- * If this is the first node with a given name property,
- * add a symlink with the name property as its name.
+ * Yet another Apple device-tree bogosity: on some machines,
+ * they have properties & nodes with the same name. Those
+ * properties are quite unimportant for us though, thus we
+ * simply "skip" them here, but we do have to check.
*/
- sib = NULL;
- while ((sib = of_get_next_child(np, sib)) && sib != child)
- if (sib->name && strcmp(sib->name, child->name) == 0)
- break;
- if (sib == child && strncmp(p, child->name, l) != 0) {
- al = proc_symlink(child->name, de, ent->name);
- if (al == 0) {
- of_node_put(sib);
+ for (ent = list; ent != NULL; ent = ent->next)
+ if (!strcmp(ent->name, pp->name))
break;
- }
- set_node_name_link(child, al);
- *lastp = al;
- lastp = &al->next;
+ if (ent != NULL) {
+ printk(KERN_WARNING "device-tree: property \"%s\" name"
+ " conflicts with node in %s\n", pp->name,
+ np->full_name);
+ continue;
}
- of_node_put(sib);
+
/*
- * Add another directory with the @address part as its name.
+ * Unfortunately proc_register puts each new entry
+ * at the beginning of the list. So we rearrange them.
*/
- al = proc_symlink(at, de, ent->name);
- if (al == 0)
+ ent = create_proc_read_entry(pp->name,
+ strncmp(pp->name, "security-", 9)
+ ? S_IRUGO : S_IRUSR, de,
+ property_read_proc, pp);
+ if (ent == 0)
break;
- set_node_addr_link(child, al);
- *lastp = al;
- lastp = &al->next;
+ if (!strncmp(pp->name, "security-", 9))
+ ent->size = 0; /* don't leak number of password chars */
+ else
+ ent->size = pp->length;
+ ent->next = NULL;
+ *lastp = ent;
+ lastp = &ent->next;
}
- of_node_put(child);
- *lastp = NULL;
de->subdir = list;
}
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 80e92d9b81cb..7d4dc5f5aa8b 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -608,7 +608,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
goto out_failed;
}
- retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
+ retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode);
if (retval)
goto out_failed;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index da23ba75f3d5..c47f8fd31a2d 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -230,7 +230,6 @@ const struct reiserfs_key MAX_KEY = {
__constant_cpu_to_le32(0xffffffff)},}
};
-const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15};
/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
of the path, and going upwards. We must check the path's validity at each step. If the key is not in
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 31e75125f48b..b35b87744983 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -164,7 +164,9 @@ static int finish_unfinished (struct super_block * s)
/* compose key to look for "save" links */
max_cpu_key.version = KEY_FORMAT_3_5;
- max_cpu_key.on_disk_key = MAX_IN_CORE_KEY;
+ max_cpu_key.on_disk_key.k_dir_id = ~0U;
+ max_cpu_key.on_disk_key.k_objectid = ~0U;
+ set_cpu_key_k_offset (&max_cpu_key, ~0U);
max_cpu_key.key_length = 3;
#ifdef CONFIG_QUOTA
diff --git a/fs/select.c b/fs/select.c
index 25b1ccac2f2c..b80e7eb0ac0d 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -55,7 +55,8 @@ struct poll_table_page {
* as all select/poll functions have to call it to add an entry to the
* poll table.
*/
-void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p);
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+ poll_table *p);
void poll_initwait(struct poll_wqueues *pwq)
{
@@ -87,7 +88,8 @@ void poll_freewait(struct poll_wqueues *pwq)
EXPORT_SYMBOL(poll_freewait);
-void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p)
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+ poll_table *_p)
{
struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
struct poll_table_page *table = p->table;
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index c2634bda6b50..85d8dbe843f1 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -46,7 +46,7 @@
#endif
/* How many days come before each month (0-12). */
-const unsigned short int __mon_yday[2][13] =
+static const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
@@ -103,7 +103,7 @@ udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
offset = 0;
if ((src.year < EPOCH_YEAR) ||
- (src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
+ (src.year >= EPOCH_YEAR+MAX_YEAR_SECONDS))
{
*dest = -1;
*dest_usec = -1;
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 554e4a18c152..d3ff78354638 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -49,7 +49,7 @@ ifeq ($(CONFIG_XFS_TRACE),y)
EXTRA_CFLAGS += -DXFS_LOG_TRACE
EXTRA_CFLAGS += -DXFS_RW_TRACE
EXTRA_CFLAGS += -DPAGEBUF_TRACE
- # EXTRA_CFLAGS += -DXFS_VNODE_TRACE
+ EXTRA_CFLAGS += -DXFS_VNODE_TRACE
endif
obj-$(CONFIG_XFS_FS) += xfs.o
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 76a84758073a..93ce257cd149 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -558,7 +558,8 @@ xfs_submit_page(
int i;
BUG_ON(PageWriteback(page));
- set_page_writeback(page);
+ if (bh_count)
+ set_page_writeback(page);
if (clear_dirty)
clear_page_dirty(page);
unlock_page(page);
@@ -578,9 +579,6 @@ xfs_submit_page(
if (probed_page && clear_dirty)
wbc->nr_to_write--; /* Wrote an "extra" page */
- } else {
- end_page_writeback(page);
- wbc->pages_skipped++; /* We didn't write this page */
}
}
@@ -602,21 +600,26 @@ xfs_convert_page(
{
struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
xfs_iomap_t *mp = iomapp, *tmp;
- unsigned long end, offset;
- pgoff_t end_index;
- int i = 0, index = 0;
+ unsigned long offset, end_offset;
+ int index = 0;
int bbits = inode->i_blkbits;
+ int len, page_dirty;
- end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
- if (page->index < end_index) {
- end = PAGE_CACHE_SIZE;
- } else {
- end = i_size_read(inode) & (PAGE_CACHE_SIZE-1);
- }
+ end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1));
+
+ /*
+ * page_dirty is initially a count of buffers on the page before
+ * EOF and is decrememted as we move each into a cleanable state.
+ */
+ len = 1 << inode->i_blkbits;
+ end_offset = max(end_offset, PAGE_CACHE_SIZE);
+ end_offset = roundup(end_offset, len);
+ page_dirty = end_offset / len;
+
+ offset = 0;
bh = head = page_buffers(page);
do {
- offset = i << bbits;
- if (offset >= end)
+ if (offset >= end_offset)
break;
if (!(PageUptodate(page) || buffer_uptodate(bh)))
continue;
@@ -625,6 +628,7 @@ xfs_convert_page(
if (startio) {
lock_buffer(bh);
bh_arr[index++] = bh;
+ page_dirty--;
}
continue;
}
@@ -657,10 +661,11 @@ xfs_convert_page(
unlock_buffer(bh);
mark_buffer_dirty(bh);
}
- } while (i++, (bh = bh->b_this_page) != head);
+ page_dirty--;
+ } while (offset += len, (bh = bh->b_this_page) != head);
- if (startio) {
- xfs_submit_page(page, wbc, bh_arr, index, 1, index == i);
+ if (startio && index) {
+ xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty);
} else {
unlock_page(page);
}
@@ -725,8 +730,11 @@ xfs_page_state_convert(
__uint64_t end_offset;
pgoff_t end_index, last_index, tlast;
int len, err, i, cnt = 0, uptodate = 1;
- int flags = startio ? 0 : BMAPI_TRYLOCK;
- int page_dirty, delalloc = 0;
+ int flags;
+ int page_dirty;
+
+ /* wait for other IO threads? */
+ flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK;
/* Is this page beyond the end of the file? */
offset = i_size_read(inode);
@@ -740,19 +748,22 @@ xfs_page_state_convert(
}
}
- offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
end_offset = min_t(unsigned long long,
- offset + PAGE_CACHE_SIZE, i_size_read(inode));
-
- bh = head = page_buffers(page);
- iomp = NULL;
+ (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset);
+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
/*
- * page_dirty is initially a count of buffers on the page and
- * is decrememted as we move each into a cleanable state.
+ * page_dirty is initially a count of buffers on the page before
+ * EOF and is decrememted as we move each into a cleanable state.
*/
- len = bh->b_size;
- page_dirty = PAGE_CACHE_SIZE / len;
+ len = 1 << inode->i_blkbits;
+ p_offset = max(p_offset, PAGE_CACHE_SIZE);
+ p_offset = roundup(p_offset, len);
+ page_dirty = p_offset / len;
+
+ iomp = NULL;
+ p_offset = 0;
+ bh = head = page_buffers(page);
do {
if (offset >= end_offset)
@@ -804,7 +815,6 @@ xfs_page_state_convert(
*/
} else if (buffer_delay(bh)) {
if (!iomp) {
- delalloc = 1;
err = xfs_map_blocks(inode, offset, len, &iomap,
BMAPI_ALLOCATE | flags);
if (err) {
@@ -875,14 +885,14 @@ xfs_page_state_convert(
if (uptodate && bh == head)
SetPageUptodate(page);
- if (startio)
- xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1);
+ if (startio) {
+ xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
+ }
if (iomp) {
- tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
+ offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
PAGE_CACHE_SHIFT;
- if (delalloc && (tlast > last_index))
- tlast = last_index;
+ tlast = min_t(pgoff_t, offset, last_index);
xfs_cluster_write(inode, page->index + 1, iomp, wbc,
startio, unmapped, tlast);
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 23e0eb67fc25..997963e53622 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1746,13 +1746,15 @@ STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
STATIC struct task_struct *pagebuf_daemon_task;
STATIC int pagebuf_daemon_active;
STATIC int force_flush;
-
+STATIC int force_sleep;
STATIC int
pagebuf_daemon_wakeup(
int priority,
unsigned int mask)
{
+ if (force_sleep)
+ return 0;
force_flush = 1;
barrier();
wake_up_process(pagebuf_daemon_task);
@@ -1778,7 +1780,12 @@ pagebuf_daemon(
INIT_LIST_HEAD(&tmp);
do {
- try_to_freeze(PF_FREEZE);
+ if (unlikely(current->flags & PF_FREEZE)) {
+ force_sleep = 1;
+ refrigerator(PF_FREEZE);
+ } else {
+ force_sleep = 0;
+ }
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 9f057a4a5b06..24fa3b101b93 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -515,10 +515,49 @@ open_exec_out:
}
#endif /* HAVE_FOP_OPEN_EXEC */
+/*
+ * Temporary workaround to the AIO direct IO write problem.
+ * This code can go and we can revert to do_sync_write once
+ * the writepage(s) rework is merged.
+ */
+STATIC ssize_t
+linvfs_write(
+ struct file *filp,
+ const char __user *buf,
+ size_t len,
+ loff_t *ppos)
+{
+ struct kiocb kiocb;
+ ssize_t ret;
+
+ init_sync_kiocb(&kiocb, filp);
+ kiocb.ki_pos = *ppos;
+ ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
+ *ppos = kiocb.ki_pos;
+ return ret;
+}
+STATIC ssize_t
+linvfs_write_invis(
+ struct file *filp,
+ const char __user *buf,
+ size_t len,
+ loff_t *ppos)
+{
+ struct kiocb kiocb;
+ ssize_t ret;
+
+ init_sync_kiocb(&kiocb, filp);
+ kiocb.ki_pos = *ppos;
+ ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
+ *ppos = kiocb.ki_pos;
+ return ret;
+}
+
+
struct file_operations linvfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .write = do_sync_write,
+ .write = linvfs_write,
.readv = linvfs_readv,
.writev = linvfs_writev,
.aio_read = linvfs_aio_read,
@@ -526,7 +565,7 @@ struct file_operations linvfs_file_operations = {
.sendfile = linvfs_sendfile,
.unlocked_ioctl = linvfs_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = xfs_compat_ioctl,
+ .compat_ioctl = linvfs_compat_ioctl,
#endif
.mmap = linvfs_file_mmap,
.open = linvfs_open,
@@ -540,7 +579,7 @@ struct file_operations linvfs_file_operations = {
struct file_operations linvfs_invis_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .write = do_sync_write,
+ .write = linvfs_write_invis,
.readv = linvfs_readv_invis,
.writev = linvfs_writev_invis,
.aio_read = linvfs_aio_read_invis,
@@ -548,7 +587,7 @@ struct file_operations linvfs_invis_file_operations = {
.sendfile = linvfs_sendfile,
.unlocked_ioctl = linvfs_ioctl_invis,
#ifdef CONFIG_COMPAT
- .compat_ioctl = xfs_compat_invis_ioctl,
+ .compat_ioctl = linvfs_compat_invis_ioctl,
#endif
.mmap = linvfs_file_mmap,
.open = linvfs_open,
@@ -561,6 +600,9 @@ struct file_operations linvfs_dir_operations = {
.read = generic_read_dir,
.readdir = linvfs_readdir,
.unlocked_ioctl = linvfs_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = linvfs_compat_ioctl,
+#endif
.fsync = linvfs_fsync,
};
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 7a12c83184f5..0f8f1384eb36 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 {
__s32 ocount; /* output count pointer */
} xfs_fsop_bulkreq32_t;
-static unsigned long
-xfs_ioctl32_bulkstat(unsigned long arg)
+STATIC unsigned long
+xfs_ioctl32_bulkstat(
+ unsigned long arg)
{
xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
@@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg)
}
#endif
-static long
-__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
+STATIC long
+__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
{
int error;
- struct inode *inode = f->f_dentry->d_inode;
+ struct inode *inode = f->f_dentry->d_inode;
vnode_t *vp = LINVFS_GET_VP(inode);
switch (cmd) {
@@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
return error;
}
-long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+long
+linvfs_compat_ioctl(
+ struct file *f,
+ unsigned cmd,
+ unsigned long arg)
{
- return __xfs_compat_ioctl(0, f, cmd, arg);
+ return __linvfs_compat_ioctl(0, f, cmd, arg);
}
-long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+long
+linvfs_compat_invis_ioctl(
+ struct file *f,
+ unsigned cmd,
+ unsigned long arg)
{
- return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg);
+ return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg);
}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 779f69a48116..c874793a1dc9 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -30,5 +30,5 @@
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
-long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
-long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ff145fd0d1a4..aa9daaea6c34 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -683,6 +683,9 @@ xfs_write(
(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
+ if (ioflags & IO_ISAIO)
+ return XFS_ERROR(-ENOSYS);
+
if ((pos & target->pbr_smask) || (count & target->pbr_smask))
return XFS_ERROR(-EINVAL);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 53dc658cafa6..455e2b2fb964 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -66,7 +66,6 @@
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_version.h"
-#include "xfs_ioctl32.h"
#include <linux/namei.h>
#include <linux/init.h>
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 849c61c74f3c..a832d165f24f 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -156,7 +156,6 @@ vn_initialize(
#ifdef XFS_VNODE_TRACE
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
- printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace);
#endif /* XFS_VNODE_TRACE */
vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
@@ -424,13 +423,13 @@ vn_remove(
* Vnode tracing code.
*/
void
-vn_trace_entry(vnode_t *vp, char *func, inst_t *ra)
+vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
}
void
-vn_trace_exit(vnode_t *vp, char *func, inst_t *ra)
+vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
}
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index da76c1f1e11c..00466c3194ac 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -86,10 +86,11 @@ typedef struct vnode {
vnumber_t v_number; /* in-core vnode number */
vn_bhv_head_t v_bh; /* behavior head */
spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
- struct inode v_inode; /* Linux inode */
#ifdef XFS_VNODE_TRACE
struct ktrace *v_trace; /* trace header structure */
#endif
+ struct inode v_inode; /* Linux inode */
+ /* inode MUST be last */
} vnode_t;
#define v_fbhv v_bh.bh_first /* first behavior */
@@ -409,7 +410,7 @@ typedef struct vattr {
int va_mask; /* bit-mask of attributes present */
enum vtype va_type; /* vnode type (for create) */
mode_t va_mode; /* file access mode and type */
- nlink_t va_nlink; /* number of references to file */
+ xfs_nlink_t va_nlink; /* number of references to file */
uid_t va_uid; /* owner user id */
gid_t va_gid; /* owner group id */
xfs_ino_t va_nodeid; /* file id */
@@ -625,6 +626,7 @@ static inline int VN_BAD(struct vnode *vp)
#define ATTR_DMI 0x08 /* invocation from a DMI function */
#define ATTR_LAZY 0x80 /* set/get attributes lazily */
#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
+#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */
/*
* Flags to VOP_FSYNC and VOP_RECLAIM.
@@ -646,8 +648,8 @@ static inline int VN_BAD(struct vnode *vp)
#define VNODE_KTRACE_REF 4
#define VNODE_KTRACE_RELE 5
-extern void vn_trace_entry(struct vnode *, char *, inst_t *);
-extern void vn_trace_exit(struct vnode *, char *, inst_t *);
+extern void vn_trace_entry(struct vnode *, const char *, inst_t *);
+extern void vn_trace_exit(struct vnode *, const char *, inst_t *);
extern void vn_trace_hold(struct vnode *, char *, int, inst_t *);
extern void vn_trace_ref(struct vnode *, char *, int, inst_t *);
extern void vn_trace_rele(struct vnode *, char *, int, inst_t *);
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 08d551a17347..63abdc2ac7f4 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -182,7 +182,7 @@ xfs_swapext(
if (VN_CACHED(tvp) != 0)
xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
- (loff_t)0, 0, 0);
+ (xfs_off_t)0, 0, 0);
/* Verify O_DIRECT for ftmp */
if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3a0ba1dfd0e8..d3da00045f26 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -136,6 +136,40 @@ xfs_chash_free(xfs_mount_t *mp)
}
/*
+ * Try to move an inode to the front of its hash list if possible
+ * (and if its not there already). Called right after obtaining
+ * the list version number and then dropping the read_lock on the
+ * hash list in question (which is done right after looking up the
+ * inode in question...).
+ */
+STATIC void
+xfs_ihash_promote(
+ xfs_ihash_t *ih,
+ xfs_inode_t *ip,
+ ulong version)
+{
+ xfs_inode_t *iq;
+
+ if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
+ if (likely(version == ih->ih_version)) {
+ /* remove from list */
+ if ((iq = ip->i_next)) {
+ iq->i_prevp = ip->i_prevp;
+ }
+ *ip->i_prevp = iq;
+
+ /* insert at list head */
+ iq = ih->ih_next;
+ iq->i_prevp = &ip->i_next;
+ ip->i_next = iq;
+ ip->i_prevp = &ih->ih_next;
+ ih->ih_next = ip;
+ }
+ write_unlock(&ih->ih_lock);
+ }
+}
+
+/*
* Look up an inode by number in the given file system.
* The inode is looked up in the hash table for the file system
* represented by the mount point parameter mp. Each bucket of
@@ -229,7 +263,9 @@ again:
XFS_STATS_INC(xs_ig_found);
ip->i_flags &= ~XFS_IRECLAIMABLE;
+ version = ih->ih_version;
read_unlock(&ih->ih_lock);
+ xfs_ihash_promote(ih, ip, version);
XFS_MOUNT_ILOCK(mp);
list_del_init(&ip->i_reclaim);
@@ -259,8 +295,15 @@ again:
inode_vp, vp);
}
+ /*
+ * Inode cache hit: if ip is not at the front of
+ * its hash chain, move it there now.
+ * Do this with the lock held for update, but
+ * do statistics after releasing the lock.
+ */
+ version = ih->ih_version;
read_unlock(&ih->ih_lock);
-
+ xfs_ihash_promote(ih, ip, version);
XFS_STATS_INC(xs_ig_found);
finish_inode:
@@ -547,6 +590,7 @@ xfs_inode_incore(xfs_mount_t *mp,
{
xfs_ihash_t *ih;
xfs_inode_t *ip;
+ ulong version;
ih = XFS_IHASH(mp, ino);
read_lock(&ih->ih_lock);
@@ -554,11 +598,15 @@ xfs_inode_incore(xfs_mount_t *mp,
if (ip->i_ino == ino) {
/*
* If we find it and tp matches, return it.
+ * Also move it to the front of the hash list
+ * if we find it and it is not already there.
* Otherwise break from the loop and return
* NULL.
*/
if (ip->i_transp == tp) {
+ version = ih->ih_version;
read_unlock(&ih->ih_lock);
+ xfs_ihash_promote(ih, ip, version);
return (ip);
}
break;
@@ -685,6 +733,7 @@ xfs_iextract(
iq->i_prevp = ip->i_prevp;
}
*ip->i_prevp = iq;
+ ih->ih_version++;
write_unlock(&ih->ih_lock);
/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 43c632ab86ad..bc8c8c7f9039 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1130,7 +1130,7 @@ xfs_ialloc(
xfs_trans_t *tp,
xfs_inode_t *pip,
mode_t mode,
- nlink_t nlink,
+ xfs_nlink_t nlink,
xfs_dev_t rdev,
cred_t *cr,
xfs_prid_t prid,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a53b1ccf6070..37e1c316f3b6 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -495,9 +495,9 @@ int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
xfs_inode_t **, xfs_daddr_t);
int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
-int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t,
- xfs_dev_t, struct cred *, xfs_prid_t, int,
- struct xfs_buf **, boolean_t *, xfs_inode_t **);
+int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
+ xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
+ int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
int);
uint xfs_ip2xflags(struct xfs_inode *);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3826e8f0e28a..469e1a7939d4 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -278,7 +278,9 @@ phase2:
switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
case BMAPI_WRITE:
/* If we found an extent, return it */
- if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) {
+ if (nimaps &&
+ (imap.br_startblock != HOLESTARTBLOCK) &&
+ (imap.br_startblock != DELAYSTARTBLOCK)) {
xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
offset, count, iomapp, &imap, flags);
break;
@@ -308,7 +310,8 @@ phase2:
break;
}
- error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
+ error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,
+ &imap, &nimaps);
break;
case BMAPI_UNWRITTEN:
lockmode = 0;
@@ -365,7 +368,7 @@ xfs_flush_space(
int
xfs_iomap_write_direct(
xfs_inode_t *ip,
- loff_t offset,
+ xfs_off_t offset,
size_t count,
int flags,
xfs_bmbt_irec_t *ret_imap,
@@ -541,7 +544,7 @@ error_out:
int
xfs_iomap_write_delay(
xfs_inode_t *ip,
- loff_t offset,
+ xfs_off_t offset,
size_t count,
int ioflag,
xfs_bmbt_irec_t *ret_imap,
@@ -746,6 +749,8 @@ write_map:
int
xfs_iomap_write_allocate(
xfs_inode_t *ip,
+ xfs_off_t offset,
+ size_t count,
xfs_bmbt_irec_t *map,
int *retmap)
{
@@ -770,9 +775,9 @@ xfs_iomap_write_allocate(
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return XFS_ERROR(error);
- offset_fsb = map->br_startoff;
+ offset_fsb = XFS_B_TO_FSBT(mp, offset);
count_fsb = map->br_blockcount;
- map_start_fsb = offset_fsb;
+ map_start_fsb = map->br_startoff;
XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
@@ -868,9 +873,9 @@ xfs_iomap_write_allocate(
imap[i].br_startoff,
imap[i].br_blockcount,imap[i].br_state);
}
- if ((map->br_startoff >= imap[i].br_startoff) &&
- (map->br_startoff < (imap[i].br_startoff +
- imap[i].br_blockcount))) {
+ if ((offset_fsb >= imap[i].br_startoff) &&
+ (offset_fsb < (imap[i].br_startoff +
+ imap[i].br_blockcount))) {
*map = imap[i];
*retmap = 1;
XFS_STATS_INC(xs_xstrat_quick);
@@ -883,9 +888,8 @@ xfs_iomap_write_allocate(
* file, just surrounding data, try again.
*/
nimaps--;
- offset_fsb = imap[nimaps].br_startoff +
- imap[nimaps].br_blockcount;
- map_start_fsb = offset_fsb;
+ map_start_fsb = imap[nimaps].br_startoff +
+ imap[nimaps].br_blockcount;
}
trans_cancel:
@@ -899,7 +903,7 @@ error0:
int
xfs_iomap_write_unwritten(
xfs_inode_t *ip,
- loff_t offset,
+ xfs_off_t offset,
size_t count)
{
xfs_mount_t *mp = ip->i_mount;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 31c91087cb33..4daaa5212102 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003,2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -29,9 +29,6 @@
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
-
-
-
#ifndef __XFS_IOMAP_H__
#define __XFS_IOMAP_H__
@@ -56,7 +53,7 @@ typedef enum {
BMAPI_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */
/* modifiers */
BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */
- BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */
+ BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */
BMAPI_MMAP = (1 << 6), /* allocate for mmap write */
BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */
BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */
@@ -67,13 +64,13 @@ typedef enum {
/*
* xfs_iomap_t: File system I/O map
*
- * The iomap_bn field is expressed in 512-byte blocks, and is where the
+ * The iomap_bn field is expressed in 512-byte blocks, and is where the
* mapping starts on disk.
*
* The iomap_offset, iomap_bsize and iomap_delta fields are in bytes.
* iomap_offset is the offset of the mapping in the file itself.
- * iomap_bsize is the size of the mapping, iomap_delta is the
- * desired data's offset into the mapping, given the offset supplied
+ * iomap_bsize is the size of the mapping, iomap_delta is the
+ * desired data's offset into the mapping, given the offset supplied
* to the file I/O map routine.
*
* When a request is made to read beyond the logical end of the object,
@@ -84,8 +81,8 @@ typedef enum {
typedef struct xfs_iomap {
xfs_daddr_t iomap_bn; /* first 512b blk of mapping */
xfs_buftarg_t *iomap_target;
- loff_t iomap_offset; /* offset of mapping, bytes */
- loff_t iomap_bsize; /* size of mapping, bytes */
+ xfs_off_t iomap_offset; /* offset of mapping, bytes */
+ xfs_off_t iomap_bsize; /* size of mapping, bytes */
size_t iomap_delta; /* offset into mapping, bytes */
iomap_flags_t iomap_flags;
} xfs_iomap_t;
@@ -96,12 +93,12 @@ struct xfs_bmbt_irec;
extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
-extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t,
+extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
int, struct xfs_bmbt_irec *, int *, int);
-extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int,
+extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int,
struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_allocate(struct xfs_inode *,
+extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t,
struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t);
+extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t);
#endif /* __XFS_IOMAP_H__*/
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b57423caef9b..2ec967d93e5a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -301,6 +301,15 @@ xfs_mount_validate_sb(
}
/*
+ * Version 1 directory format has never worked on Linux.
+ */
+ if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
+ cmn_err(CE_WARN,
+ "XFS: Attempted to mount file system using version 1 directory format");
+ return XFS_ERROR(ENOSYS);
+ }
+
+ /*
* Until this is fixed only page-sized or smaller data blocks work.
*/
if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 5fc6201dd8e2..30dd08fb9f57 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -210,15 +210,16 @@ typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
struct xfs_bmap_free *);
typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
typedef int (*xfs_iomap_write_direct_t)(
- void *, loff_t, size_t, int,
+ void *, xfs_off_t, size_t, int,
struct xfs_bmbt_irec *, int *, int);
typedef int (*xfs_iomap_write_delay_t)(
- void *, loff_t, size_t, int,
+ void *, xfs_off_t, size_t, int,
struct xfs_bmbt_irec *, int *);
typedef int (*xfs_iomap_write_allocate_t)(
- void *, struct xfs_bmbt_irec *, int *);
+ void *, xfs_off_t, size_t,
+ struct xfs_bmbt_irec *, int *);
typedef int (*xfs_iomap_write_unwritten_t)(
- void *, loff_t, size_t);
+ void *, xfs_off_t, size_t);
typedef uint (*xfs_lck_map_shared_t)(void *);
typedef void (*xfs_lock_t)(void *, uint);
typedef void (*xfs_lock_demote_t)(void *, uint);
@@ -258,9 +259,9 @@ typedef struct xfs_ioops {
#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
(*(mp)->m_io_ops.xfs_iomap_write_delay) \
((io)->io_obj, offset, count, flags, mval, nmap)
-#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \
+#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \
(*(mp)->m_io_ops.xfs_iomap_write_allocate) \
- ((io)->io_obj, mval, nmap)
+ ((io)->io_obj, offset, count, mval, nmap)
#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
(*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
((io)->io_obj, offset, count)
@@ -428,10 +429,10 @@ typedef struct xfs_mount {
#define XFS_WRITEIO_LOG_LARGE 16
/*
- * Max and min values for UIO and mount-option defined I/O sizes;
- * min value can't be less than a page. Currently unused.
+ * Max and min values for mount-option defined I/O
+ * preallocation sizes.
*/
-#define XFS_MAX_IO_LOG 16 /* 64K */
+#define XFS_MAX_IO_LOG 30 /* 1G */
#define XFS_MIN_IO_LOG PAGE_SHIFT
/*
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 04609d27ea51..e4bf711e48ff 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -63,6 +63,7 @@ typedef __u64 xfs_ino_t; /* <inode> type */
typedef __s64 xfs_daddr_t; /* <disk address> type */
typedef char * xfs_caddr_t; /* <core address> type */
typedef __u32 xfs_dev_t;
+typedef __u32 xfs_nlink_t;
/* __psint_t is the same size as a pointer */
#if (BITS_PER_LONG == 32)
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 816b945fa0ea..d1f8146a06ea 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -147,7 +147,7 @@ xfs_dir_ialloc(
xfs_inode_t *dp, /* directory within whose allocate
the inode. */
mode_t mode,
- nlink_t nlink,
+ xfs_nlink_t nlink,
xfs_dev_t rdev,
cred_t *credp,
prid_t prid, /* project id */
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index e1ed6a588000..01d98b4b7af7 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -42,7 +42,7 @@ extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **);
extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *,
xfs_inode_t **);
extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
-extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, nlink_t,
+extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
xfs_dev_t, cred_t *, prid_t, int,
xfs_inode_t **, int *);
extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 00aae9c6a904..b53736650100 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1649,6 +1649,7 @@ xfs_vget(
#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
+#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */
@@ -1657,6 +1658,28 @@ xfs_vget(
#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */
+STATIC unsigned long
+suffix_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ int last, shift_left_factor = 0;
+ char *value = (char *)cp;
+
+ last = strlen(value) - 1;
+ if (value[last] == 'K' || value[last] == 'k') {
+ shift_left_factor = 10;
+ value[last] = '\0';
+ }
+ if (value[last] == 'M' || value[last] == 'm') {
+ shift_left_factor = 20;
+ value[last] = '\0';
+ }
+ if (value[last] == 'G' || value[last] == 'g') {
+ shift_left_factor = 30;
+ value[last] = '\0';
+ }
+
+ return simple_strtoul(cp, endp, base) << shift_left_factor;
+}
int
xfs_parseargs(
@@ -1688,60 +1711,60 @@ xfs_parseargs(
if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_LOGBUFS);
+ this_char);
return EINVAL;
}
args->logbufs = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
- int last, in_kilobytes = 0;
-
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_LOGBSIZE);
+ this_char);
return EINVAL;
}
- last = strlen(value) - 1;
- if (value[last] == 'K' || value[last] == 'k') {
- in_kilobytes = 1;
- value[last] = '\0';
- }
- args->logbufsize = simple_strtoul(value, &eov, 10);
- if (in_kilobytes)
- args->logbufsize <<= 10;
+ args->logbufsize = suffix_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_LOGDEV);
+ this_char);
return EINVAL;
}
strncpy(args->logname, value, MAXNAMELEN);
} else if (!strcmp(this_char, MNTOPT_MTPT)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_MTPT);
+ this_char);
return EINVAL;
}
strncpy(args->mtpt, value, MAXNAMELEN);
} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_RTDEV);
+ this_char);
return EINVAL;
}
strncpy(args->rtname, value, MAXNAMELEN);
} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_BIOSIZE);
+ this_char);
return EINVAL;
}
iosize = simple_strtoul(value, &eov, 10);
args->flags |= XFSMNT_IOSIZE;
args->iosizelog = (uint8_t) iosize;
+ } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
+ if (!value || !*value) {
+ printk("XFS: %s option requires an argument\n",
+ this_char);
+ return EINVAL;
+ }
+ iosize = suffix_strtoul(value, &eov, 10);
+ args->flags |= XFSMNT_IOSIZE;
+ args->iosizelog = ffs(iosize) - 1;
} else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- this_char);
+ this_char);
return EINVAL;
}
args->flags |= XFSMNT_IHASHSIZE;
@@ -1756,7 +1779,7 @@ xfs_parseargs(
args->flags |= XFSMNT_INO64;
#if !XFS_BIG_INUMS
printk("XFS: %s option not allowed on this system\n",
- MNTOPT_INO64);
+ this_char);
return EINVAL;
#endif
} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
@@ -1766,14 +1789,14 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_SUNIT);
+ this_char);
return EINVAL;
}
dsunit = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
- MNTOPT_SWIDTH);
+ this_char);
return EINVAL;
}
dswidth = simple_strtoul(value, &eov, 10);
@@ -1781,7 +1804,7 @@ xfs_parseargs(
args->flags &= ~XFSMNT_32BITINODES;
#if !XFS_BIG_INUMS
printk("XFS: %s option not allowed on this system\n",
- MNTOPT_64BITINODE);
+ this_char);
return EINVAL;
#endif
} else if (!strcmp(this_char, MNTOPT_NOUUID)) {
@@ -1877,7 +1900,7 @@ xfs_showargs(
seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
- seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log);
+ seq_printf(m, "," MNTOPT_ALLOCSIZE "=%d", 1<<mp->m_writeio_log);
if (mp->m_logbufs > 0)
seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 70092963ca9e..25a526629b12 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -305,7 +305,7 @@ xfs_setattr(
int mandlock_before, mandlock_after;
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
int file_owner;
- int need_iolock = (flags & ATTR_DMI) == 0;
+ int need_iolock = 1;
vp = BHV_TO_VNODE(bdp);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -384,6 +384,9 @@ xfs_setattr(
*/
tp = NULL;
lock_flags = XFS_ILOCK_EXCL;
+ ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
+ if (flags & ATTR_NOLOCK)
+ need_iolock = 0;
if (!(mask & XFS_AT_SIZE)) {
if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
(mp->m_flags & XFS_MOUNT_WSYNC)) {
@@ -4320,7 +4323,7 @@ xfs_free_file_space(
int rt;
xfs_fileoff_t startoffset_fsb;
xfs_trans_t *tp;
- int need_iolock = (attr_flags & ATTR_DMI) == 0;
+ int need_iolock = 1;
vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
mp = ip->i_mount;
@@ -4348,8 +4351,12 @@ xfs_free_file_space(
return(error);
}
+ ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
+ if (attr_flags & ATTR_NOLOCK)
+ need_iolock = 0;
if (need_iolock)
xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
(__uint8_t)NBPP);
ilen = len + (offset & (rounding - 1));