Merge tag 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:
 - hostfs saw a face lifting
 - old/broken stuff was removed (SMP, HIGHMEM, SKAS3/4)
 - random cleanups and bug fixes

* tag 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (26 commits)
  um: Print minimum physical memory requirement
  um: Move uml_postsetup in the init_thread stack
  um: add a kmsg_dumper
  x86, UML: fix integer overflow in ELF_ET_DYN_BASE
  um: hostfs: Reduce number of syscalls in readdir
  um: Remove broken highmem support
  um: Remove broken SMP support
  um: Remove SKAS3/4 support
  um: Remove ppc cruft
  um: Remove ia64 cruft
  um: Remove dead code from stacktrace
  hostfs: No need to box and later unbox the file mode
  hostfs: Use page_offset()
  hostfs: Set page flags in hostfs_readpage() correctly
  hostfs: Remove superfluous initializations in hostfs_open()
  hostfs: hostfs_open: Reset open flags upon each retry
  hostfs: Remove superfluous test in hostfs_open()
  hostfs: Report append flag in ->show_options()
  hostfs: Use __getname() in follow_link
  hostfs: Remove open coded strcpy()
  ...
This commit is contained in:
Linus Torvalds 2015-04-15 13:49:27 -07:00
commit e44740c1a9
59 changed files with 323 additions and 2067 deletions

View file

@ -66,7 +66,8 @@ extern int stat_file(const char *path, struct hostfs_stat *p, int fd);
extern int access_file(char *path, int r, int w, int x);
extern int open_file(char *path, int r, int w, int append);
extern void *open_dir(char *path, int *err_out);
extern char *read_dir(void *stream, unsigned long long *pos,
extern void seek_dir(void *stream, unsigned long long pos);
extern char *read_dir(void *stream, unsigned long long *pos_out,
unsigned long long *ino_out, int *len_out,
unsigned int *type_out);
extern void close_file(void *stream);
@ -77,8 +78,7 @@ extern int write_file(int fd, unsigned long long *offset, const char *buf,
int len);
extern int lseek_file(int fd, long long offset, int whence);
extern int fsync_file(int fd, int datasync);
extern int file_create(char *name, int ur, int uw, int ux, int gr,
int gw, int gx, int or, int ow, int ox);
extern int file_create(char *name, int mode);
extern int set_attr(const char *file, struct hostfs_iattr *attrs, int fd);
extern int make_symlink(const char *from, const char *to);
extern int unlink_file(const char *file);

View file

@ -24,6 +24,7 @@ struct hostfs_inode_info {
int fd;
fmode_t mode;
struct inode vfs_inode;
struct mutex open_mutex;
};
static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
@ -92,16 +93,22 @@ static char *__dentry_name(struct dentry *dentry, char *name)
__putname(name);
return NULL;
}
/*
* This function relies on the fact that dentry_path_raw() will place
* the path name at the end of the provided buffer.
*/
BUG_ON(p + strlen(p) + 1 != name + PATH_MAX);
strlcpy(name, root, PATH_MAX);
if (len > p - name) {
__putname(name);
return NULL;
}
if (p > name + len) {
char *s = name + len;
while ((*s++ = *p++) != '\0')
;
}
if (p > name + len)
strcpy(name + len, p);
return name;
}
@ -135,21 +142,19 @@ static char *follow_link(char *link)
int len, n;
char *name, *resolved, *end;
len = 64;
while (1) {
name = __getname();
if (!name) {
n = -ENOMEM;
name = kmalloc(len, GFP_KERNEL);
if (name == NULL)
goto out;
n = hostfs_do_readlink(link, name, len);
if (n < len)
break;
len *= 2;
kfree(name);
goto out_free;
}
n = hostfs_do_readlink(link, name, PATH_MAX);
if (n < 0)
goto out_free;
else if (n == PATH_MAX) {
n = -E2BIG;
goto out_free;
}
if (*name == '/')
return name;
@ -168,13 +173,12 @@ static char *follow_link(char *link)
}
sprintf(resolved, "%s%s", link, name);
kfree(name);
__putname(name);
kfree(link);
return resolved;
out_free:
kfree(name);
out:
__putname(name);
return ERR_PTR(n);
}
@ -225,6 +229,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
hi->fd = -1;
hi->mode = 0;
inode_init_once(&hi->vfs_inode);
mutex_init(&hi->open_mutex);
return &hi->vfs_inode;
}
@ -257,6 +262,9 @@ static int hostfs_show_options(struct seq_file *seq, struct dentry *root)
if (strlen(root_path) > offset)
seq_printf(seq, ",%s", root_path + offset);
if (append)
seq_puts(seq, ",append");
return 0;
}
@ -284,6 +292,7 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx)
if (dir == NULL)
return -error;
next = ctx->pos;
seek_dir(dir, next);
while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
if (!dir_emit(ctx, name, len, ino, type))
break;
@ -293,13 +302,12 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx)
return 0;
}
static int hostfs_file_open(struct inode *ino, struct file *file)
static int hostfs_open(struct inode *ino, struct file *file)
{
static DEFINE_MUTEX(open_mutex);
char *name;
fmode_t mode = 0;
fmode_t mode;
int err;
int r = 0, w = 0, fd;
int r, w, fd;
mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
if ((mode & HOSTFS_I(ino)->mode) == mode)
@ -308,12 +316,12 @@ static int hostfs_file_open(struct inode *ino, struct file *file)
mode |= HOSTFS_I(ino)->mode;
retry:
r = w = 0;
if (mode & FMODE_READ)
r = 1;
if (mode & FMODE_WRITE)
w = 1;
if (w)
r = 1;
r = w = 1;
name = dentry_name(file->f_path.dentry);
if (name == NULL)
@ -324,15 +332,16 @@ retry:
if (fd < 0)
return fd;
mutex_lock(&open_mutex);
mutex_lock(&HOSTFS_I(ino)->open_mutex);
/* somebody else had handled it first? */
if ((mode & HOSTFS_I(ino)->mode) == mode) {
mutex_unlock(&open_mutex);
mutex_unlock(&HOSTFS_I(ino)->open_mutex);
close_file(&fd);
return 0;
}
if ((mode | HOSTFS_I(ino)->mode) != mode) {
mode |= HOSTFS_I(ino)->mode;
mutex_unlock(&open_mutex);
mutex_unlock(&HOSTFS_I(ino)->open_mutex);
close_file(&fd);
goto retry;
}
@ -342,12 +351,12 @@ retry:
err = replace_file(fd, HOSTFS_I(ino)->fd);
close_file(&fd);
if (err < 0) {
mutex_unlock(&open_mutex);
mutex_unlock(&HOSTFS_I(ino)->open_mutex);
return err;
}
}
HOSTFS_I(ino)->mode = mode;
mutex_unlock(&open_mutex);
mutex_unlock(&HOSTFS_I(ino)->open_mutex);
return 0;
}
@ -382,7 +391,7 @@ static const struct file_operations hostfs_file_fops = {
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.open = hostfs_file_open,
.open = hostfs_open,
.release = hostfs_file_release,
.fsync = hostfs_fsync,
};
@ -391,6 +400,8 @@ static const struct file_operations hostfs_dir_fops = {
.llseek = generic_file_llseek,
.iterate = hostfs_readdir,
.read = generic_read_dir,
.open = hostfs_open,
.fsync = hostfs_fsync,
};
static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
@ -398,7 +409,7 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
char *buffer;
unsigned long long base;
loff_t base = page_offset(page);
int count = PAGE_CACHE_SIZE;
int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
int err;
@ -407,7 +418,6 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
count = inode->i_size & (PAGE_CACHE_SIZE-1);
buffer = kmap(page);
base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
if (err != count) {
@ -432,26 +442,29 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
static int hostfs_readpage(struct file *file, struct page *page)
{
char *buffer;
long long start;
int err = 0;
loff_t start = page_offset(page);
int bytes_read, ret = 0;
start = (long long) page->index << PAGE_CACHE_SHIFT;
buffer = kmap(page);
err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
PAGE_CACHE_SIZE);
if (err < 0)
if (bytes_read < 0) {
ClearPageUptodate(page);
SetPageError(page);
ret = bytes_read;
goto out;
}
memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
memset(buffer + bytes_read, 0, PAGE_CACHE_SIZE - bytes_read);
flush_dcache_page(page);
ClearPageError(page);
SetPageUptodate(page);
if (PageError(page)) ClearPageError(page);
err = 0;
out:
flush_dcache_page(page);
kunmap(page);
unlock_page(page);
return err;
return ret;
}
static int hostfs_write_begin(struct file *file, struct address_space *mapping,
@ -528,11 +541,13 @@ static int read_name(struct inode *ino, char *name)
init_special_inode(ino, st.mode & S_IFMT, rdev);
ino->i_op = &hostfs_iops;
break;
default:
case S_IFREG:
ino->i_op = &hostfs_iops;
ino->i_fop = &hostfs_file_fops;
ino->i_mapping->a_ops = &hostfs_aops;
break;
default:
return -EIO;
}
ino->i_ino = st.ino;
@ -566,10 +581,7 @@ static int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
if (name == NULL)
goto out_put;
fd = file_create(name,
mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
fd = file_create(name, mode & S_IFMT);
if (fd < 0)
error = fd;
else

View file

@ -97,21 +97,27 @@ void *open_dir(char *path, int *err_out)
return dir;
}
char *read_dir(void *stream, unsigned long long *pos,
void seek_dir(void *stream, unsigned long long pos)
{
DIR *dir = stream;
seekdir(dir, pos);
}
char *read_dir(void *stream, unsigned long long *pos_out,
unsigned long long *ino_out, int *len_out,
unsigned int *type_out)
{
DIR *dir = stream;
struct dirent *ent;
seekdir(dir, *pos);
ent = readdir(dir);
if (ent == NULL)
return NULL;
*len_out = strlen(ent->d_name);
*ino_out = ent->d_ino;
*type_out = ent->d_type;
*pos = telldir(dir);
*pos_out = ent->d_off;
return ent->d_name;
}
@ -175,21 +181,10 @@ void close_dir(void *stream)
closedir(stream);
}
int file_create(char *name, int ur, int uw, int ux, int gr,
int gw, int gx, int or, int ow, int ox)
int file_create(char *name, int mode)
{
int mode, fd;
int fd;
mode = 0;
mode |= ur ? S_IRUSR : 0;
mode |= uw ? S_IWUSR : 0;
mode |= ux ? S_IXUSR : 0;
mode |= gr ? S_IRGRP : 0;
mode |= gw ? S_IWGRP : 0;
mode |= gx ? S_IXGRP : 0;
mode |= or ? S_IROTH : 0;
mode |= ow ? S_IWOTH : 0;
mode |= ox ? S_IXOTH : 0;
fd = open64(name, O_CREAT | O_RDWR, mode);
if (fd < 0)
return -errno;