don't put symlink bodies in pagecache into highmem

kmap() in page_follow_link_light() needed to go - allowing to hold
an arbitrary number of kmaps for long is a great way to deadlocking
the system.

new helper (inode_nohighmem(inode)) needs to be used for pagecache
symlinks inodes; done for all in-tree cases.  page_follow_link_light()
instrumented to yell about anything missed.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2015-11-17 01:07:57 -05:00
parent aa80deab33
commit 21fc61c73c
57 changed files with 81 additions and 46 deletions

View File

@ -504,3 +504,8 @@ in your dentry operations instead.
[mandatory] [mandatory]
__fd_install() & fd_install() can now sleep. Callers should not __fd_install() & fd_install() can now sleep. Callers should not
hold a spinlock or other resources that do not allow a schedule. hold a spinlock or other resources that do not allow a schedule.
--
[mandatory]
any symlink that might use page_follow_link_light/page_put_link() must
have inode_nohighmem(inode) called before anything might start playing with
its pagecache.

View File

@ -140,6 +140,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
break; break;
case ST_SOFTLINK: case ST_SOFTLINK:
inode->i_mode |= S_IFLNK; inode->i_mode |= S_IFLNK;
inode_nohighmem(inode);
inode->i_op = &affs_symlink_inode_operations; inode->i_op = &affs_symlink_inode_operations;
inode->i_data.a_ops = &affs_symlink_aops; inode->i_data.a_ops = &affs_symlink_aops;
break; break;

View File

@ -344,6 +344,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
return -ENOSPC; return -ENOSPC;
inode->i_op = &affs_symlink_inode_operations; inode->i_op = &affs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &affs_symlink_aops; inode->i_data.a_ops = &affs_symlink_aops;
inode->i_mode = S_IFLNK | 0777; inode->i_mode = S_IFLNK | 0777;
mode_to_prot(inode); mode_to_prot(inode);

View File

@ -14,7 +14,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
char *link = kmap(page); char *link = page_address(page);
struct slink_front *lf; struct slink_front *lf;
int i, j; int i, j;
char c; char c;
@ -57,12 +57,10 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
link[i] = '\0'; link[i] = '\0';
affs_brelse(bh); affs_brelse(bh);
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
fail: fail:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return -EIO; return -EIO;
} }

View File

@ -56,6 +56,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
case AFS_FTYPE_SYMLINK: case AFS_FTYPE_SYMLINK:
inode->i_mode = S_IFLNK | vnode->status.mode; inode->i_mode = S_IFLNK | vnode->status.mode;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
break; break;
default: default:
printk("kAFS: AFS vnode with undefined type\n"); printk("kAFS: AFS vnode with undefined type\n");

View File

@ -397,6 +397,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &befs_symlink_aops; inode->i_mapping->a_ops = &befs_symlink_aops;
} else { } else {
inode->i_link = befs_ino->i_data.symlink; inode->i_link = befs_ino->i_data.symlink;
@ -469,7 +470,7 @@ static int befs_symlink_readpage(struct file *unused, struct page *page)
struct befs_inode_info *befs_ino = BEFS_I(inode); struct befs_inode_info *befs_ino = BEFS_I(inode);
befs_data_stream *data = &befs_ino->i_data.ds; befs_data_stream *data = &befs_ino->i_data.ds;
befs_off_t len = data->size; befs_off_t len = data->size;
char *link = kmap(page); char *link = page_address(page);
if (len == 0 || len > PAGE_SIZE) { if (len == 0 || len > PAGE_SIZE) {
befs_error(sb, "Long symlink with illegal length"); befs_error(sb, "Long symlink with illegal length");
@ -483,12 +484,10 @@ static int befs_symlink_readpage(struct file *unused, struct page *page)
} }
link[len - 1] = '\0'; link[len - 1] = '\0';
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
fail: fail:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return -EIO; return -EIO;
} }

View File

@ -3774,6 +3774,7 @@ cache_acl:
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &btrfs_symlink_inode_operations; inode->i_op = &btrfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &btrfs_symlink_aops; inode->i_mapping->a_ops = &btrfs_symlink_aops;
break; break;
default: default:
@ -9705,6 +9706,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
btrfs_free_path(path); btrfs_free_path(path);
inode->i_op = &btrfs_symlink_inode_operations; inode->i_op = &btrfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &btrfs_symlink_aops; inode->i_mapping->a_ops = &btrfs_symlink_aops;
inode_set_bytes(inode, name_len); inode_set_bytes(inode, name_len);
btrfs_i_size_write(inode, name_len); btrfs_i_size_write(inode, name_len);

View File

@ -8,6 +8,7 @@
#include <linux/coda.h> #include <linux/coda.h>
#include <linux/coda_psdev.h> #include <linux/coda_psdev.h>
#include <linux/pagemap.h>
#include "coda_linux.h" #include "coda_linux.h"
static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
@ -35,6 +36,7 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
inode->i_fop = &coda_dir_operations; inode->i_fop = &coda_dir_operations;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &coda_symlink_inode_operations; inode->i_op = &coda_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &coda_symlink_aops; inode->i_data.a_ops = &coda_symlink_aops;
inode->i_mapping = &inode->i_data; inode->i_mapping = &inode->i_data;
} else } else

View File

@ -26,7 +26,7 @@ static int coda_symlink_filler(struct file *file, struct page *page)
int error; int error;
struct coda_inode_info *cii; struct coda_inode_info *cii;
unsigned int len = PAGE_SIZE; unsigned int len = PAGE_SIZE;
char *p = kmap(page); char *p = page_address(page);
cii = ITOC(inode); cii = ITOC(inode);
@ -34,13 +34,11 @@ static int coda_symlink_filler(struct file *file, struct page *page)
if (error) if (error)
goto fail; goto fail;
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
fail: fail:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return error; return error;
} }

View File

@ -100,6 +100,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &cramfs_aops; inode->i_data.a_ops = &cramfs_aops;
break; break;
default: default:

View File

@ -151,6 +151,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &efs_symlink_aops; inode->i_data.a_ops = &efs_symlink_aops;
break; break;
case S_IFCHR: case S_IFCHR:

View File

@ -13,7 +13,7 @@
static int efs_symlink_readpage(struct file *file, struct page *page) static int efs_symlink_readpage(struct file *file, struct page *page)
{ {
char *link = kmap(page); char *link = page_address(page);
struct buffer_head * bh; struct buffer_head * bh;
struct inode * inode = page->mapping->host; struct inode * inode = page->mapping->host;
efs_block_t size = inode->i_size; efs_block_t size = inode->i_size;
@ -39,12 +39,10 @@ static int efs_symlink_readpage(struct file *file, struct page *page)
} }
link[size] = '\0'; link[size] = '\0';
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
fail: fail:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return err; return err;
} }

View File

@ -1227,6 +1227,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
inode->i_link = (char *)oi->i_data; inode->i_link = (char *)oi->i_data;
} else { } else {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &exofs_aops; inode->i_mapping->a_ops = &exofs_aops;
} }
} else { } else {

View File

@ -111,6 +111,7 @@ static int exofs_symlink(struct inode *dir, struct dentry *dentry,
if (l > sizeof(oi->i_data)) { if (l > sizeof(oi->i_data)) {
/* slow symlink */ /* slow symlink */
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &exofs_aops; inode->i_mapping->a_ops = &exofs_aops;
memset(oi->i_data, 0, sizeof(oi->i_data)); memset(oi->i_data, 0, sizeof(oi->i_data));

View File

@ -1420,6 +1420,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
sizeof(ei->i_data) - 1); sizeof(ei->i_data) - 1);
} else { } else {
inode->i_op = &ext2_symlink_inode_operations; inode->i_op = &ext2_symlink_inode_operations;
inode_nohighmem(inode);
if (test_opt(inode->i_sb, NOBH)) if (test_opt(inode->i_sb, NOBH))
inode->i_mapping->a_ops = &ext2_nobh_aops; inode->i_mapping->a_ops = &ext2_nobh_aops;
else else

View File

@ -183,6 +183,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
if (l > sizeof (EXT2_I(inode)->i_data)) { if (l > sizeof (EXT2_I(inode)->i_data)) {
/* slow symlink */ /* slow symlink */
inode->i_op = &ext2_symlink_inode_operations; inode->i_op = &ext2_symlink_inode_operations;
inode_nohighmem(inode);
if (test_opt(inode->i_sb, NOBH)) if (test_opt(inode->i_sb, NOBH))
inode->i_mapping->a_ops = &ext2_nobh_aops; inode->i_mapping->a_ops = &ext2_nobh_aops;
else else

View File

@ -4283,6 +4283,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &ext4_symlink_inode_operations; inode->i_op = &ext4_symlink_inode_operations;
ext4_set_aops(inode); ext4_set_aops(inode);
} }
inode_nohighmem(inode);
} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
inode->i_op = &ext4_special_inode_operations; inode->i_op = &ext4_special_inode_operations;

View File

@ -3132,6 +3132,7 @@ static int ext4_symlink(struct inode *dir,
if ((disk_link.len > EXT4_N_BLOCKS * 4)) { if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
if (!encryption_required) if (!encryption_required)
inode->i_op = &ext4_symlink_inode_operations; inode->i_op = &ext4_symlink_inode_operations;
inode_nohighmem(inode);
ext4_set_aops(inode); ext4_set_aops(inode);
/* /*
* We cannot call page_symlink() with transaction started * We cannot call page_symlink() with transaction started

View File

@ -45,7 +45,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
cpage = read_mapping_page(inode->i_mapping, 0, NULL); cpage = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(cpage)) if (IS_ERR(cpage))
return ERR_CAST(cpage); return ERR_CAST(cpage);
caddr = kmap(cpage); caddr = page_address(cpage);
caddr[size] = 0; caddr[size] = 0;
} }
@ -75,16 +75,12 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
/* Null-terminate the name */ /* Null-terminate the name */
if (res <= plen) if (res <= plen)
paddr[res] = '\0'; paddr[res] = '\0';
if (cpage) { if (cpage)
kunmap(cpage);
page_cache_release(cpage); page_cache_release(cpage);
}
return *cookie = paddr; return *cookie = paddr;
errout: errout:
if (cpage) { if (cpage)
kunmap(cpage);
page_cache_release(cpage); page_cache_release(cpage);
}
kfree(paddr); kfree(paddr);
return ERR_PTR(res); return ERR_PTR(res);
} }

View File

@ -202,6 +202,7 @@ make_now:
inode->i_op = &f2fs_encrypted_symlink_inode_operations; inode->i_op = &f2fs_encrypted_symlink_inode_operations;
else else
inode->i_op = &f2fs_symlink_inode_operations; inode->i_op = &f2fs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &f2fs_dblock_aops; inode->i_mapping->a_ops = &f2fs_dblock_aops;
} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {

View File

@ -351,6 +351,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
inode->i_op = &f2fs_encrypted_symlink_inode_operations; inode->i_op = &f2fs_encrypted_symlink_inode_operations;
else else
inode->i_op = &f2fs_symlink_inode_operations; inode->i_op = &f2fs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &f2fs_dblock_aops; inode->i_mapping->a_ops = &f2fs_dblock_aops;
f2fs_lock_op(sbi); f2fs_lock_op(sbi);
@ -942,7 +943,7 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
cpage = read_mapping_page(inode->i_mapping, 0, NULL); cpage = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(cpage)) if (IS_ERR(cpage))
return ERR_CAST(cpage); return ERR_CAST(cpage);
caddr = kmap(cpage); caddr = page_address(cpage);
caddr[size] = 0; caddr[size] = 0;
/* Symlink is encrypted */ /* Symlink is encrypted */
@ -982,13 +983,11 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
/* Null-terminate the name */ /* Null-terminate the name */
paddr[res] = '\0'; paddr[res] = '\0';
kunmap(cpage);
page_cache_release(cpage); page_cache_release(cpage);
return *cookie = paddr; return *cookie = paddr;
errout: errout:
kfree(cstr.name); kfree(cstr.name);
f2fs_fname_crypto_free_buffer(&pstr); f2fs_fname_crypto_free_buffer(&pstr);
kunmap(cpage);
page_cache_release(cpage); page_cache_release(cpage);
return ERR_PTR(res); return ERR_PTR(res);
} }

View File

@ -326,6 +326,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
} else if (S_ISLNK(ip->i_mode)) { } else if (S_ISLNK(ip->i_mode)) {
if (!VXFS_ISIMMED(vip)) { if (!VXFS_ISIMMED(vip)) {
ip->i_op = &page_symlink_inode_operations; ip->i_op = &page_symlink_inode_operations;
inode_nohighmem(ip);
ip->i_mapping->a_ops = &vxfs_aops; ip->i_mapping->a_ops = &vxfs_aops;
} else { } else {
ip->i_op = &simple_symlink_inode_operations; ip->i_op = &simple_symlink_inode_operations;

View File

@ -403,6 +403,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
sbi->file_count++; sbi->file_count++;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &hfsplus_aops; inode->i_mapping->a_ops = &hfsplus_aops;
hip->clump_blocks = 1; hip->clump_blocks = 1;
} else } else
@ -526,6 +527,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
inode->i_mapping->a_ops = &hfsplus_aops; inode->i_mapping->a_ops = &hfsplus_aops;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &hfsplus_aops; inode->i_mapping->a_ops = &hfsplus_aops;
} else { } else {
init_special_inode(inode, inode->i_mode, init_special_inode(inode, inode->i_mode,

View File

@ -77,6 +77,7 @@ void hpfs_read_inode(struct inode *i)
kfree(ea); kfree(ea);
i->i_mode = S_IFLNK | 0777; i->i_mode = S_IFLNK | 0777;
i->i_op = &page_symlink_inode_operations; i->i_op = &page_symlink_inode_operations;
inode_nohighmem(i);
i->i_data.a_ops = &hpfs_symlink_aops; i->i_data.a_ops = &hpfs_symlink_aops;
set_nlink(i, 1); set_nlink(i, 1);
i->i_size = ea_size; i->i_size = ea_size;

View File

@ -332,6 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
result->i_blocks = 1; result->i_blocks = 1;
set_nlink(result, 1); set_nlink(result, 1);
result->i_size = strlen(symlink); result->i_size = strlen(symlink);
inode_nohighmem(result);
result->i_op = &page_symlink_inode_operations; result->i_op = &page_symlink_inode_operations;
result->i_data.a_ops = &hpfs_symlink_aops; result->i_data.a_ops = &hpfs_symlink_aops;
@ -500,7 +501,7 @@ out:
static int hpfs_symlink_readpage(struct file *file, struct page *page) static int hpfs_symlink_readpage(struct file *file, struct page *page)
{ {
char *link = kmap(page); char *link = page_address(page);
struct inode *i = page->mapping->host; struct inode *i = page->mapping->host;
struct fnode *fnode; struct fnode *fnode;
struct buffer_head *bh; struct buffer_head *bh;
@ -516,14 +517,12 @@ static int hpfs_symlink_readpage(struct file *file, struct page *page)
goto fail; goto fail;
hpfs_unlock(i->i_sb); hpfs_unlock(i->i_sb);
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
fail: fail:
hpfs_unlock(i->i_sb); hpfs_unlock(i->i_sb);
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return err; return err;
} }

View File

@ -760,6 +760,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
break; break;
} }
lockdep_annotate_inode_mutex_key(inode); lockdep_annotate_inode_mutex_key(inode);

View File

@ -2028,3 +2028,9 @@ void inode_set_flags(struct inode *inode, unsigned int flags,
new_flags) != old_flags)); new_flags) != old_flags));
} }
EXPORT_SYMBOL(inode_set_flags); EXPORT_SYMBOL(inode_set_flags);
void inode_nohighmem(struct inode *inode)
{
mapping_set_gfp_mask(inode->i_mapping, GFP_USER);
}
EXPORT_SYMBOL(inode_nohighmem);

View File

@ -1417,6 +1417,7 @@ static int isofs_read_inode(struct inode *inode, int relocated)
inode->i_fop = &isofs_dir_operations; inode->i_fop = &isofs_dir_operations;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &isofs_symlink_aops; inode->i_data.a_ops = &isofs_symlink_aops;
} else } else
/* XXX - parse_rock_ridge_inode() had already set i_rdev. */ /* XXX - parse_rock_ridge_inode() had already set i_rdev. */

View File

@ -687,7 +687,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct iso_inode_info *ei = ISOFS_I(inode); struct iso_inode_info *ei = ISOFS_I(inode);
struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb); struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
char *link = kmap(page); char *link = page_address(page);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
struct buffer_head *bh; struct buffer_head *bh;
char *rpnt = link; char *rpnt = link;
@ -774,7 +774,6 @@ repeat:
brelse(bh); brelse(bh);
*rpnt = '\0'; *rpnt = '\0';
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
@ -791,7 +790,6 @@ fail:
brelse(bh); brelse(bh);
error: error:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return -EIO; return -EIO;
} }

View File

@ -60,6 +60,7 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino)
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
if (inode->i_size >= IDATASIZE) { if (inode->i_size >= IDATASIZE) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &jfs_aops; inode->i_mapping->a_ops = &jfs_aops;
} else { } else {
inode->i_op = &jfs_fast_symlink_inode_operations; inode->i_op = &jfs_fast_symlink_inode_operations;

View File

@ -983,6 +983,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);
ip->i_op = &jfs_symlink_inode_operations; ip->i_op = &jfs_symlink_inode_operations;
inode_nohighmem(ip);
ip->i_mapping->a_ops = &jfs_aops; ip->i_mapping->a_ops = &jfs_aops;
/* /*

View File

@ -529,6 +529,7 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry,
return PTR_ERR(inode); return PTR_ERR(inode);
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &logfs_reg_aops; inode->i_mapping->a_ops = &logfs_reg_aops;
return __logfs_create(dir, dentry, inode, target, destlen); return __logfs_create(dir, dentry, inode, target, destlen);

View File

@ -65,6 +65,7 @@ static void logfs_inode_setops(struct inode *inode)
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &logfs_reg_aops; inode->i_mapping->a_ops = &logfs_reg_aops;
break; break;
case S_IFSOCK: /* fall through */ case S_IFSOCK: /* fall through */

View File

@ -452,6 +452,7 @@ void minix_set_inode(struct inode *inode, dev_t rdev)
inode->i_mapping->a_ops = &minix_aops; inode->i_mapping->a_ops = &minix_aops;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &minix_symlink_inode_operations; inode->i_op = &minix_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &minix_aops; inode->i_mapping->a_ops = &minix_aops;
} else } else
init_special_inode(inode, inode->i_mode, rdev); init_special_inode(inode, inode->i_mode, rdev);

View File

@ -4527,7 +4527,8 @@ static const char *page_getlink(struct dentry * dentry, void **cookie)
if (IS_ERR(page)) if (IS_ERR(page))
return (char*)page; return (char*)page;
*cookie = page; *cookie = page;
kaddr = kmap(page); BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
kaddr = page_address(page);
nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1);
return kaddr; return kaddr;
} }
@ -4541,7 +4542,6 @@ EXPORT_SYMBOL(page_follow_link_light);
void page_put_link(struct inode *unused, void *cookie) void page_put_link(struct inode *unused, void *cookie)
{ {
struct page *page = cookie; struct page *page = cookie;
kunmap(page);
page_cache_release(page); page_cache_release(page);
} }
EXPORT_SYMBOL(page_put_link); EXPORT_SYMBOL(page_put_link);
@ -4565,7 +4565,6 @@ int __page_symlink(struct inode *inode, const char *symname, int len, int nofs)
struct page *page; struct page *page;
void *fsdata; void *fsdata;
int err; int err;
char *kaddr;
unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE; unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE;
if (nofs) if (nofs)
flags |= AOP_FLAG_NOFS; flags |= AOP_FLAG_NOFS;
@ -4576,9 +4575,7 @@ retry:
if (err) if (err)
goto fail; goto fail;
kaddr = kmap_atomic(page); memcpy(page_address(page), symname, len-1);
memcpy(kaddr, symname, len-1);
kunmap_atomic(kaddr);
err = pagecache_write_end(NULL, mapping, 0, len-1, len-1, err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
page, fsdata); page, fsdata);

View File

@ -283,6 +283,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &ncp_symlink_inode_operations; inode->i_op = &ncp_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_data.a_ops = &ncp_symlink_aops; inode->i_data.a_ops = &ncp_symlink_aops;
#endif #endif
} else { } else {

View File

@ -408,9 +408,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
inode->i_fop = NULL; inode->i_fop = NULL;
inode->i_flags |= S_AUTOMOUNT; inode->i_flags |= S_AUTOMOUNT;
} }
} else if (S_ISLNK(inode->i_mode)) } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &nfs_symlink_inode_operations; inode->i_op = &nfs_symlink_inode_operations;
else inode_nohighmem(inode);
} else
init_special_inode(inode, inode->i_mode, fattr->rdev); init_special_inode(inode, inode->i_mode, fattr->rdev);
memset(&inode->i_atime, 0, sizeof(inode->i_atime)); memset(&inode->i_atime, 0, sizeof(inode->i_atime));

View File

@ -56,7 +56,7 @@ static const char *nfs_follow_link(struct dentry *dentry, void **cookie)
if (IS_ERR(page)) if (IS_ERR(page))
return ERR_CAST(page); return ERR_CAST(page);
*cookie = page; *cookie = page;
return kmap(page); return page_address(page);
} }
/* /*

View File

@ -510,6 +510,7 @@ static int __nilfs_read_inode(struct super_block *sb,
inode->i_mapping->a_ops = &nilfs_aops; inode->i_mapping->a_ops = &nilfs_aops;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &nilfs_symlink_inode_operations; inode->i_op = &nilfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &nilfs_aops; inode->i_mapping->a_ops = &nilfs_aops;
} else { } else {
inode->i_op = &nilfs_special_inode_operations; inode->i_op = &nilfs_special_inode_operations;

View File

@ -161,6 +161,7 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
/* slow symlink */ /* slow symlink */
inode->i_op = &nilfs_symlink_inode_operations; inode->i_op = &nilfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &nilfs_aops; inode->i_mapping->a_ops = &nilfs_aops;
err = page_symlink(inode, symname, l); err = page_symlink(inode, symname, l);
if (err) if (err)

View File

@ -361,6 +361,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &ocfs2_symlink_inode_operations; inode->i_op = &ocfs2_symlink_inode_operations;
inode_nohighmem(inode);
i_size_write(inode, le64_to_cpu(fe->i_size)); i_size_write(inode, le64_to_cpu(fe->i_size));
break; break;
default: default:

View File

@ -1960,6 +1960,7 @@ static int ocfs2_symlink(struct inode *dir,
inode->i_rdev = 0; inode->i_rdev = 0;
newsize = l - 1; newsize = l - 1;
inode->i_op = &ocfs2_symlink_inode_operations; inode->i_op = &ocfs2_symlink_inode_operations;
inode_nohighmem(inode);
if (l > ocfs2_fast_symlink_chars(sb)) { if (l > ocfs2_fast_symlink_chars(sb)) {
u32 offset = 0; u32 offset = 0;

View File

@ -316,6 +316,7 @@ struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)
inode->i_fop = &qnx4_dir_operations; inode->i_fop = &qnx4_dir_operations;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &qnx4_aops; inode->i_mapping->a_ops = &qnx4_aops;
qnx4_i(inode)->mmu_private = inode->i_size; qnx4_i(inode)->mmu_private = inode->i_size;
} else { } else {

View File

@ -582,6 +582,7 @@ struct inode *qnx6_iget(struct super_block *sb, unsigned ino)
inode->i_mapping->a_ops = &qnx6_aops; inode->i_mapping->a_ops = &qnx6_aops;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &qnx6_aops; inode->i_mapping->a_ops = &qnx6_aops;
} else } else
init_special_inode(inode, inode->i_mode, 0); init_special_inode(inode, inode->i_mode, 0);

View File

@ -79,6 +79,7 @@ struct inode *ramfs_get_inode(struct super_block *sb,
break; break;
case S_IFLNK: case S_IFLNK:
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
break; break;
} }
} }

View File

@ -1361,6 +1361,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
inode->i_fop = &reiserfs_dir_operations; inode->i_fop = &reiserfs_dir_operations;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &reiserfs_symlink_inode_operations; inode->i_op = &reiserfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &reiserfs_address_space_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations;
} else { } else {
inode->i_blocks = 0; inode->i_blocks = 0;

View File

@ -1170,6 +1170,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
reiserfs_update_inode_transaction(parent_dir); reiserfs_update_inode_transaction(parent_dir);
inode->i_op = &reiserfs_symlink_inode_operations; inode->i_op = &reiserfs_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &reiserfs_address_space_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations;
retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name, retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name,

View File

@ -360,6 +360,7 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
break; break;
case ROMFH_SYM: case ROMFH_SYM:
i->i_op = &page_symlink_inode_operations; i->i_op = &page_symlink_inode_operations;
inode_nohighmem(i);
i->i_data.a_ops = &romfs_aops; i->i_data.a_ops = &romfs_aops;
mode |= S_IRWXUGO; mode |= S_IRWXUGO;
break; break;

View File

@ -41,6 +41,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/pagemap.h>
#include "squashfs_fs.h" #include "squashfs_fs.h"
#include "squashfs_fs_sb.h" #include "squashfs_fs_sb.h"
@ -291,6 +292,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink)); set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
inode->i_size = le32_to_cpu(sqsh_ino->symlink_size); inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
inode->i_op = &squashfs_symlink_inode_ops; inode->i_op = &squashfs_symlink_inode_ops;
inode_nohighmem(inode);
inode->i_data.a_ops = &squashfs_symlink_aops; inode->i_data.a_ops = &squashfs_symlink_aops;
inode->i_mode |= S_IFLNK; inode->i_mode |= S_IFLNK;
squashfs_i(inode)->start = block; squashfs_i(inode)->start = block;

View File

@ -163,6 +163,7 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
inode->i_mapping->a_ops = &sysv_aops; inode->i_mapping->a_ops = &sysv_aops;
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &sysv_symlink_inode_operations; inode->i_op = &sysv_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &sysv_aops; inode->i_mapping->a_ops = &sysv_aops;
} else } else
init_special_inode(inode, inode->i_mode, rdev); init_special_inode(inode, inode->i_mode, rdev);

View File

@ -1541,6 +1541,7 @@ reread:
case ICBTAG_FILE_TYPE_SYMLINK: case ICBTAG_FILE_TYPE_SYMLINK:
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_mode = S_IFLNK | S_IRWXUGO;
break; break;
case ICBTAG_FILE_TYPE_MAIN: case ICBTAG_FILE_TYPE_MAIN:

View File

@ -922,6 +922,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
struct kernel_lb_addr eloc; struct kernel_lb_addr eloc;

View File

@ -107,7 +107,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
unsigned char *symlink; unsigned char *symlink;
int err; int err;
unsigned char *p = kmap(page); unsigned char *p = page_address(page);
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
uint32_t pos; uint32_t pos;
@ -141,7 +141,6 @@ static int udf_symlink_filler(struct file *file, struct page *page)
up_read(&iinfo->i_data_sem); up_read(&iinfo->i_data_sem);
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page);
unlock_page(page); unlock_page(page);
return 0; return 0;
@ -149,7 +148,6 @@ out_unlock_inode:
up_read(&iinfo->i_data_sem); up_read(&iinfo->i_data_sem);
SetPageError(page); SetPageError(page);
out_unmap: out_unmap:
kunmap(page);
unlock_page(page); unlock_page(page);
return err; return err;
} }

View File

@ -533,6 +533,7 @@ static void ufs_set_inode_ops(struct inode *inode)
} else { } else {
inode->i_mapping->a_ops = &ufs_aops; inode->i_mapping->a_ops = &ufs_aops;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
} }
} else } else
init_special_inode(inode, inode->i_mode, init_special_inode(inode, inode->i_mode,

View File

@ -124,6 +124,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) { if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
/* slow symlink */ /* slow symlink */
inode->i_op = &page_symlink_inode_operations; inode->i_op = &page_symlink_inode_operations;
inode_nohighmem(inode);
inode->i_mapping->a_ops = &ufs_aops; inode->i_mapping->a_ops = &ufs_aops;
err = page_symlink(inode, symname, l); err = page_symlink(inode, symname, l);
if (err) if (err)

View File

@ -3025,5 +3025,6 @@ static inline bool dir_relax(struct inode *inode)
} }
extern bool path_noexec(const struct path *path); extern bool path_noexec(const struct path *path);
extern void inode_nohighmem(struct inode *inode);
#endif /* _LINUX_FS_H */ #endif /* _LINUX_FS_H */

View File

@ -2444,7 +2444,6 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
int len; int len;
struct inode *inode; struct inode *inode;
struct page *page; struct page *page;
char *kaddr;
struct shmem_inode_info *info; struct shmem_inode_info *info;
len = strlen(symname) + 1; len = strlen(symname) + 1;
@ -2483,9 +2482,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
} }
inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->a_ops = &shmem_aops;
inode->i_op = &shmem_symlink_inode_operations; inode->i_op = &shmem_symlink_inode_operations;
kaddr = kmap_atomic(page); inode_nohighmem(inode);
memcpy(kaddr, symname, len); memcpy(page_address(page), symname, len);
kunmap_atomic(kaddr);
SetPageUptodate(page); SetPageUptodate(page);
set_page_dirty(page); set_page_dirty(page);
unlock_page(page); unlock_page(page);
@ -2506,13 +2504,12 @@ static const char *shmem_follow_link(struct dentry *dentry, void **cookie)
return ERR_PTR(error); return ERR_PTR(error);
unlock_page(page); unlock_page(page);
*cookie = page; *cookie = page;
return kmap(page); return page_address(page);
} }
static void shmem_put_link(struct inode *unused, void *cookie) static void shmem_put_link(struct inode *unused, void *cookie)
{ {
struct page *page = cookie; struct page *page = cookie;
kunmap(page);
mark_page_accessed(page); mark_page_accessed(page);
page_cache_release(page); page_cache_release(page);
} }