Commit 467a0077 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds

[PATCH] tmpfs 2/5 long symlinks

shmem_symlink was letting a long symlink overwrite its vfs_inode, now
included within struct shmem_inode_info - oops! and failed long symlink
inodes were freed but still left on the shmem_inodes list, causing oops
in swapoff at shutdown (if not earlier).
parent 004b361e
...@@ -1176,14 +1176,11 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * ...@@ -1176,14 +1176,11 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
info = SHMEM_I(inode); info = SHMEM_I(inode);
inode->i_size = len-1; inode->i_size = len-1;
if (len <= sizeof(struct shmem_inode_info)) { if (len <= (char *)inode - (char *)info) {
/* do it inline */ /* do it inline */
memcpy(info, symname, len); memcpy(info, symname, len);
inode->i_op = &shmem_symlink_inline_operations; inode->i_op = &shmem_symlink_inline_operations;
} else { } else {
spin_lock (&shmem_ilock);
list_add (&info->list, &shmem_inodes);
spin_unlock (&shmem_ilock);
down(&info->sem); down(&info->sem);
page = shmem_getpage_locked(info, inode, 0); page = shmem_getpage_locked(info, inode, 0);
if (IS_ERR(page)) { if (IS_ERR(page)) {
...@@ -1191,6 +1188,10 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * ...@@ -1191,6 +1188,10 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
iput(inode); iput(inode);
return PTR_ERR(page); return PTR_ERR(page);
} }
inode->i_op = &shmem_symlink_inode_operations;
spin_lock (&shmem_ilock);
list_add (&info->list, &shmem_inodes);
spin_unlock (&shmem_ilock);
kaddr = kmap(page); kaddr = kmap(page);
memcpy(kaddr, symname, len); memcpy(kaddr, symname, len);
kunmap(page); kunmap(page);
...@@ -1198,7 +1199,6 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * ...@@ -1198,7 +1199,6 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
up(&info->sem); up(&info->sem);
inode->i_op = &shmem_symlink_inode_operations;
} }
dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_ctime = dir->i_mtime = CURRENT_TIME;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment