summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig19
-rw-r--r--fs/Makefile2
-rw-r--r--fs/bpkfs.c32
-rw-r--r--fs/cramfs/Makefile2
-rw-r--r--fs/cramfs/cramfs.c21
-rw-r--r--fs/cramfs/uncompress.c2
-rw-r--r--fs/devfs-core.c315
-rw-r--r--fs/devfs.c95
-rw-r--r--fs/efi.c109
-rw-r--r--fs/efivarfs.c112
-rw-r--r--fs/ext4/Kconfig2
-rw-r--r--fs/ext4/Makefile2
-rw-r--r--fs/ext4/ext4_common.c23
-rw-r--r--fs/ext4/ext4_common.h4
-rw-r--r--fs/ext4/ext4fs.c44
-rw-r--r--fs/ext4/ext4fs.h33
-rw-r--r--fs/ext4/ext_barebox.c42
-rw-r--r--fs/ext4/ext_common.h10
-rw-r--r--fs/fat/Kconfig4
-rw-r--r--fs/fat/Makefile2
-rw-r--r--fs/fat/diskio.h2
-rw-r--r--fs/fat/fat-pbl.c2
-rw-r--r--fs/fat/fat.c42
-rw-r--r--fs/fat/ffconf.h2
-rw-r--r--fs/fat/integer.h2
-rw-r--r--fs/fs.c1074
-rw-r--r--fs/jffs2/Kconfig2
-rw-r--r--fs/jffs2/Makefile2
-rw-r--r--fs/jffs2/acl.h4
-rw-r--r--fs/jffs2/build.c4
-rw-r--r--fs/jffs2/compr.c4
-rw-r--r--fs/jffs2/compr.h4
-rw-r--r--fs/jffs2/compr_lzo.c4
-rw-r--r--fs/jffs2/compr_rtime.c5
-rw-r--r--fs/jffs2/compr_rubin.c4
-rw-r--r--fs/jffs2/compr_zlib.c4
-rw-r--r--fs/jffs2/debug.c4
-rw-r--r--fs/jffs2/debug.h5
-rw-r--r--fs/jffs2/dir.c4
-rw-r--r--fs/jffs2/fs.c59
-rw-r--r--fs/jffs2/jffs2_fs_i.h5
-rw-r--r--fs/jffs2/jffs2_fs_sb.h5
-rw-r--r--fs/jffs2/malloc.c135
-rw-r--r--fs/jffs2/nodelist.c4
-rw-r--r--fs/jffs2/nodelist.h6
-rw-r--r--fs/jffs2/os-linux.h9
-rw-r--r--fs/jffs2/read.c4
-rw-r--r--fs/jffs2/readinode.c4
-rw-r--r--fs/jffs2/scan.c4
-rw-r--r--fs/jffs2/summary.h4
-rw-r--r--fs/jffs2/super.c7
-rw-r--r--fs/jffs2/xattr.h4
-rw-r--r--fs/legacy.c21
-rw-r--r--fs/nfs.c161
-rw-r--r--fs/omap4_usbbootfs.c32
-rw-r--r--fs/pstore/Kconfig2
-rw-r--r--fs/pstore/Makefile2
-rw-r--r--fs/pstore/fs.c24
-rw-r--r--fs/pstore/internal.h2
-rw-r--r--fs/pstore/platform.c2
-rw-r--r--fs/pstore/ram.c49
-rw-r--r--fs/pstore/ram_core.c1
-rw-r--r--fs/ramfs.c18
-rw-r--r--fs/ratpfs.c48
-rw-r--r--fs/smhfs.c28
-rw-r--r--fs/squashfs/Kconfig2
-rw-r--r--fs/squashfs/Makefile2
-rw-r--r--fs/squashfs/inode.c24
-rw-r--r--fs/squashfs/squashfs.c25
-rw-r--r--fs/squashfs/squashfs.h7
-rw-r--r--fs/squashfs/squashfs_fs_sb.h2
-rw-r--r--fs/squashfs/super.c5
-rw-r--r--fs/tftp-selftest.h56
-rw-r--r--fs/tftp.c550
-rw-r--r--fs/ubifs/Kconfig7
-rw-r--r--fs/ubifs/Makefile2
-rw-r--r--fs/ubifs/scan.c2
-rw-r--r--fs/ubifs/super.c10
-rw-r--r--fs/ubifs/tnc.c7
-rw-r--r--fs/ubifs/ubifs-media.h2
-rw-r--r--fs/ubifs/ubifs.c95
-rw-r--r--fs/ubifs/ubifs.h5
-rw-r--r--fs/ubootvarfs.c23
-rw-r--r--fs/uimagefs.c57
84 files changed, 2250 insertions, 1322 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index e0405de334..a3ba84b6ae 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
menu "Filesystem support"
@@ -42,6 +43,20 @@ config FS_TFTP
prompt "tftp support"
depends on NET
+config FS_TFTP_MAX_WINDOW_SIZE
+ int
+ prompt "maximum tftp window size (RFC 7440)"
+ depends on FS_TFTP
+ default 128
+ range 1 128
+ help
+ The maximum allowed tftp "windowsize" (RFC 7440). Higher
+ value increase speed of the tftp download with the cost of
+ memory (1432 bytes per slot).
+
+ Requires tftp "windowsize" (RFC 7440) support on server side
+ to have an effect.
+
config FS_OMAP4_USBBOOT
bool
prompt "Filesystem over usb boot"
@@ -54,7 +69,7 @@ config FS_NFS
prompt "nfs support"
config FS_EFI
- depends on EFI_BOOTUP
+ depends on EFI_PAYLOAD
select FS_LEGACY
bool
prompt "EFI filesystem support"
@@ -63,7 +78,7 @@ config FS_EFI
by the EFI Firmware via the EFI Simple File System Protocol.
config FS_EFIVARFS
- depends on EFI_BOOTUP
+ depends on EFI_PAYLOAD
select FS_LEGACY
bool
prompt "EFI variable filesystem support (efivarfs)"
diff --git a/fs/Makefile b/fs/Makefile
index fa950941de..6160ef4e1a 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-$(CONFIG_FS_CRAMFS) += cramfs/
obj-$(CONFIG_FS_EXT4) += ext4/
obj-$(CONFIG_FS_RAMFS) += ramfs.o
diff --git a/fs/bpkfs.c b/fs/bpkfs.c
index 8fc4df65de..ea2c279585 100644
--- a/fs/bpkfs.c
+++ b/fs/bpkfs.c
@@ -127,7 +127,7 @@ static struct bpkfs_handle_data *bpkfs_get_by_type(
return NULL;
}
-static int bpkfs_open(struct device_d *dev, FILE *f, const char *filename)
+static int bpkfs_open(struct device *dev, FILE *f, const char *filename)
{
struct bpkfs_handle *priv = dev->priv;
struct bpkfs_handle_data *d;
@@ -171,7 +171,7 @@ out:
return ret;
}
-static int bpkfs_close(struct device_d *dev, FILE *file)
+static int bpkfs_close(struct device *dev, FILE *file)
{
struct bpkfs_handle_data *d = file->priv;
@@ -180,7 +180,8 @@ static int bpkfs_close(struct device_d *dev, FILE *file)
return 0;
}
-static int bpkfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
+static int bpkfs_read(struct device *dev, FILE *file, void *buf,
+ size_t insize)
{
struct bpkfs_handle_data *d = file->priv;
@@ -192,7 +193,7 @@ static int bpkfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize
}
}
-static int bpkfs_lseek(struct device_d *dev, FILE *file, loff_t pos)
+static int bpkfs_lseek(struct device *dev, FILE *file, loff_t pos)
{
struct bpkfs_handle_data *d = file->priv;
@@ -211,7 +212,7 @@ struct somfy_readdir {
DIR dir;
};
-static DIR *bpkfs_opendir(struct device_d *dev, const char *pathname)
+static DIR *bpkfs_opendir(struct device *dev, const char *pathname)
{
struct bpkfs_handle *priv = dev->priv;
struct somfy_readdir *sdir;
@@ -242,7 +243,7 @@ static DIR *bpkfs_opendir(struct device_d *dev, const char *pathname)
return dir;
}
-static struct dirent *bpkfs_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *bpkfs_readdir(struct device *dev, DIR *dir)
{
struct bpkfs_handle *priv = dev->priv;
struct somfy_readdir *sdir = dir->priv;
@@ -269,7 +270,7 @@ static struct dirent *bpkfs_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int bpkfs_closedir(struct device_d *dev, DIR *dir)
+static int bpkfs_closedir(struct device *dev, DIR *dir)
{
struct somfy_readdir *sdir = dir->priv;
@@ -277,7 +278,8 @@ static int bpkfs_closedir(struct device_d *dev, DIR *dir)
return 0;
}
-static int bpkfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+static int bpkfs_stat(struct device *dev, const char *filename,
+ struct stat *s)
{
struct bpkfs_handle *priv = dev->priv;
struct bpkfs_handle_data *d;
@@ -335,7 +337,7 @@ static void bpkfs_remove_data(struct bpkfs_handle_hw *h)
}
}
-static void bpkfs_remove(struct device_d *dev)
+static void bpkfs_remove(struct device *dev)
{
struct bpkfs_handle *priv = dev->priv;
struct bpkfs_handle_hw *h, *tmp;
@@ -349,9 +351,9 @@ static void bpkfs_remove(struct device_d *dev)
free(priv);
}
-static int bpkfs_probe(struct device_d *dev)
+static int bpkfs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct bpkfs_handle *priv;
struct bpkfs_header *header;
struct bpkfs_data_header data_header;
@@ -381,7 +383,7 @@ static int bpkfs_probe(struct device_d *dev)
ret = read(fd, header, sizeof(*header));
if (ret < 0) {
- dev_err(dev, "could not read: %s (ret = %d)\n", errno_str(), ret);
+ dev_err(dev, "could not read: %m\n");
goto err;
}
@@ -407,7 +409,7 @@ static int bpkfs_probe(struct device_d *dev)
ret = read(fd, &data_header, sizeof(data_header));
if (ret < 0) {
- dev_err(dev, "could not read: %s\n", errno_str());
+ dev_err(dev, "could not read: %m\n");
goto err;
} else if (ret == 0) {
dev_err(dev, "EOF: to_read %llu\n", size);
@@ -456,7 +458,7 @@ static int bpkfs_probe(struct device_d *dev)
priv->nb_data_entries++;
if (lseek(fd, d->size, SEEK_CUR) != d->size) {
- dev_err(dev, "could not seek: %s\n", errno_str());
+ dev_err(dev, "could not seek: %m\n");
ret = -errno;
goto err;
}
@@ -489,7 +491,7 @@ err:
return ret;
}
-static struct fs_driver_d bpkfs_driver = {
+static struct fs_driver bpkfs_driver = {
.open = bpkfs_open,
.close = bpkfs_close,
.read = bpkfs_read,
diff --git a/fs/cramfs/Makefile b/fs/cramfs/Makefile
index 4e84a98fe1..1b54096664 100644
--- a/fs/cramfs/Makefile
+++ b/fs/cramfs/Makefile
@@ -1,2 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += cramfs.o
obj-y += uncompress.o
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index 3ea6bd437e..2d1070f1a7 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -118,7 +118,8 @@ static int cramfs_read_file(struct inode *inode, unsigned long offset,
{
struct cramfs_inode_info *info = to_cramfs_inode_info(inode);
struct cramfs_inode *cramfs_inode = &info->inode;
- struct fs_device_d *fsdev = container_of(inode->i_sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(inode->i_sb, struct fs_device,
+ sb);
struct cramfs_priv *priv = fsdev->dev.priv;
unsigned int blocknr;
int outsize = 0;
@@ -161,13 +162,13 @@ static int cramfs_read_file(struct inode *inode, unsigned long offset,
return outsize;
}
-static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
+static int cramfs_read(struct device *_dev, FILE *f, void *buf, size_t size)
{
return cramfs_read_file(f->f_inode, f->pos, buf, size);
}
#if 0
-static int cramfs_info (struct device_d *dev)
+static int cramfs_info (struct device *dev)
{
if (cramfs_read_super (dev))
return 0;
@@ -274,7 +275,8 @@ static struct dentry *cramfs_lookup(struct inode *dir, struct dentry *dentry,
struct cramfs_inode *de;
unsigned int offset = 0;
struct inode *inode = NULL;
- struct fs_device_d *fsdev = container_of(dir->i_sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(dir->i_sb, struct fs_device,
+ sb);
struct cramfs_priv *priv = fsdev->dev.priv;
de = xmalloc(sizeof(*de) + CRAMFS_MAXPATHLEN);
@@ -346,7 +348,8 @@ static int cramfs_iterate(struct file *file, struct dir_context *ctx)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *dir = d_inode(dentry);
- struct fs_device_d *fsdev = container_of(dir->i_sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(dir->i_sb, struct fs_device,
+ sb);
struct cramfs_priv *priv = fsdev->dev.priv;
char *buf;
unsigned int offset;
@@ -439,9 +442,9 @@ static const struct super_operations cramfs_ops = {
.destroy_inode = cramfs_destroy_inode,
};
-static int cramfs_probe(struct device_d *dev)
+static int cramfs_probe(struct device *dev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
struct cramfs_priv *priv;
int ret;
struct super_block *sb;
@@ -485,7 +488,7 @@ err_out:
return ret;
}
-static void cramfs_remove(struct device_d *dev)
+static void cramfs_remove(struct device *dev)
{
struct cramfs_priv *priv = dev->priv;
@@ -493,7 +496,7 @@ static void cramfs_remove(struct device_d *dev)
free(priv);
}
-static struct fs_driver_d cramfs_driver = {
+static struct fs_driver cramfs_driver = {
.read = cramfs_read,
.drv = {
.probe = cramfs_probe,
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index b7887bd654..82c82adf04 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/*
* uncompress.c
*
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index f804f96974..376c62be9e 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -37,8 +37,8 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
len = strlen(instr);
- list_for_each_entry(cdev, &cdev_list, list) {
- if (cdev->master &&
+ for_each_cdev(cdev) {
+ if (cdev_is_partition(cdev) &&
!strncmp(instr, cdev->name, len)) {
string_list_add_asprintf(sl, "%s ", cdev->name);
}
@@ -49,6 +49,9 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
struct cdev *cdev_readlink(struct cdev *cdev)
{
+ if (!cdev)
+ return NULL;
+
if (cdev->link)
cdev = cdev->link;
@@ -62,7 +65,7 @@ struct cdev *lcdev_by_name(const char *filename)
{
struct cdev *cdev;
- list_for_each_entry(cdev, &cdev_list, list) {
+ for_each_cdev(cdev) {
if (!strcmp(cdev->name, filename))
return cdev;
}
@@ -84,10 +87,11 @@ struct cdev *cdev_by_device_node(struct device_node *node)
{
struct cdev *cdev;
- list_for_each_entry(cdev, &cdev_list, list) {
- if (!cdev->device_node)
- continue;
- if (cdev->device_node == node)
+ if (!node)
+ return NULL;
+
+ for_each_cdev(cdev) {
+ if (cdev_of_node(cdev) == node)
return cdev_readlink(cdev);
}
return NULL;
@@ -100,8 +104,22 @@ struct cdev *cdev_by_partuuid(const char *partuuid)
if (!partuuid)
return NULL;
- list_for_each_entry(cdev, &cdev_list, list) {
- if (!strcasecmp(cdev->partuuid, partuuid))
+ for_each_cdev(cdev) {
+ if (cdev_is_partition(cdev) && !strcasecmp(cdev->partuuid, partuuid))
+ return cdev;
+ }
+ return NULL;
+}
+
+struct cdev *cdev_by_diskuuid(const char *diskuuid)
+{
+ struct cdev *cdev;
+
+ if (!diskuuid)
+ return NULL;
+
+ for_each_cdev(cdev) {
+ if (!cdev_is_partition(cdev) && !strcasecmp(cdev->diskuuid, diskuuid))
return cdev;
}
return NULL;
@@ -113,10 +131,10 @@ struct cdev *cdev_by_partuuid(const char *partuuid)
* @dev: the device which should be searched for partitions
* @name: the partition name
*/
-struct cdev *device_find_partition(struct device_d *dev, const char *name)
+struct cdev *device_find_partition(struct device *dev, const char *name)
{
struct cdev *cdev;
- struct device_d *child;
+ struct device *child;
list_for_each_entry(cdev, &dev->cdevs, devices_list) {
struct cdev *cdevl;
@@ -155,7 +173,42 @@ int cdev_find_free_index(const char *basename)
return -EBUSY; /* all indexes are used */
}
-struct cdev *cdev_open(const char *name, unsigned long flags)
+int cdev_open(struct cdev *cdev, unsigned long flags)
+{
+ int ret;
+
+ if (cdev->ops->open) {
+ ret = cdev->ops->open(cdev, flags);
+ if (ret)
+ return ret;
+ }
+
+ cdev->open++;
+
+ return 0;
+}
+
+int cdev_fdopen(struct cdev *cdev, unsigned long flags)
+{
+ char *path;
+ int fd;
+
+ if (!cdev)
+ return -ENODEV;
+ if (IS_ERR(cdev))
+ return PTR_ERR(cdev);
+
+ path = basprintf("/dev/%s", cdev->name);
+ if (!path)
+ return -ENOMEM;
+
+ fd = open(path, flags);
+
+ free(path);
+ return fd;
+}
+
+struct cdev *cdev_open_by_name(const char *name, unsigned long flags)
{
struct cdev *cdev;
int ret;
@@ -164,11 +217,9 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
if (!cdev)
return NULL;
- if (cdev->ops->open) {
- ret = cdev->ops->open(cdev, flags);
- if (ret)
- return NULL;
- }
+ ret = cdev_open(cdev, flags);
+ if (ret)
+ return NULL;
return cdev;
}
@@ -177,6 +228,8 @@ void cdev_close(struct cdev *cdev)
{
if (cdev->ops->close)
cdev->ops->close(cdev);
+
+ cdev->open--;
}
ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags)
@@ -219,6 +272,77 @@ int cdev_erase(struct cdev *cdev, loff_t count, loff_t offset)
return cdev->ops->erase(cdev, count, cdev->offset + offset);
}
+int cdev_lseek(struct cdev *cdev, loff_t pos)
+{
+ int ret;
+
+ if (cdev->ops->lseek) {
+ ret = cdev->ops->lseek(cdev, pos + cdev->offset);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int cdev_protect(struct cdev *cdev, size_t count, loff_t offset, int prot)
+{
+ if (!cdev->ops->protect)
+ return -ENOSYS;
+
+ return cdev->ops->protect(cdev, count, offset + cdev->offset, prot);
+}
+
+int cdev_discard_range(struct cdev *cdev, loff_t count, loff_t offset)
+{
+ if (!cdev->ops->discard_range)
+ return -ENOSYS;
+
+ if (cdev->flags & DEVFS_PARTITION_READONLY)
+ return -EPERM;
+
+ if (offset >= cdev->size)
+ return 0;
+
+ if (count + offset > cdev->size)
+ count = cdev->size - offset;
+
+ return cdev->ops->discard_range(cdev, count, offset + cdev->offset);
+}
+
+int cdev_memmap(struct cdev *cdev, void **map, int flags)
+{
+ int ret = -ENOSYS;
+
+ if (!cdev->ops->memmap)
+ return -EINVAL;
+
+ ret = cdev->ops->memmap(cdev, map, flags);
+
+ if (!ret)
+ *map = (void *)((unsigned long)*map + (unsigned long)cdev->offset);
+
+ return ret;
+}
+
+int cdev_truncate(struct cdev *cdev, size_t size)
+{
+ if (cdev->ops->truncate)
+ return cdev->ops->truncate(cdev, size);
+
+ return -EPERM;
+}
+
+static struct cdev *cdev_alloc(const char *name)
+{
+ struct cdev *new;
+
+ new = xzalloc(sizeof(*new));
+ new->name = xstrdup(name);
+
+ return new;
+}
+
int devfs_create(struct cdev *new)
{
struct cdev *cdev;
@@ -234,7 +358,7 @@ int devfs_create(struct cdev *new)
if (new->dev) {
list_add_tail(&new->devices_list, &new->dev->cdevs);
if (!new->device_node)
- new->device_node = new->dev->device_node;
+ new->device_node = new->dev->of_node;
}
return 0;
@@ -253,8 +377,7 @@ int devfs_create_link(struct cdev *cdev, const char *name)
*/
cdev = cdev_readlink(cdev);
- new = xzalloc(sizeof(*new));
- new->name = xstrdup(name);
+ new = cdev_alloc(name);
new->link = cdev;
if (cdev->partname) {
@@ -271,6 +394,7 @@ int devfs_create_link(struct cdev *cdev, const char *name)
}
INIT_LIST_HEAD(&new->links);
+ INIT_LIST_HEAD(&new->partitions);
list_add_tail(&new->list, &cdev_list);
list_add_tail(&new->link_entry, &cdev->links);
@@ -292,7 +416,10 @@ int devfs_remove(struct cdev *cdev)
list_for_each_entry_safe(c, tmp, &cdev->links, link_entry)
devfs_remove(c);
- if (cdev->master)
+ list_for_each_entry_safe(c, tmp, &cdev->partitions, partition_entry)
+ cdevfs_del_partition(c);
+
+ if (cdev_is_partition(cdev))
list_del(&cdev->partition_entry);
if (cdev->link)
@@ -301,11 +428,82 @@ int devfs_remove(struct cdev *cdev)
return 0;
}
+static bool region_identical(loff_t starta, loff_t lena,
+ loff_t startb, loff_t lenb)
+{
+ return starta == startb && lena == lenb;
+}
+
+static bool region_overlap(loff_t starta, loff_t lena,
+ loff_t startb, loff_t lenb)
+{
+ if (starta + lena <= startb)
+ return 0;
+ if (startb + lenb <= starta)
+ return 0;
+ return 1;
+}
+
+/**
+ * check_overlap() - check overlap with existing partitions
+ * @cdev: parent cdev
+ * @name: partition name for informational purposes on conflict
+ * @offset: offset of new partition to be added
+ * @size: size of new partition to be added
+ *
+ * Return: NULL if no overlapping partition found or overlapping
+ * partition if and only if it's identical in offset and size
+ * to an existing partition. Otherwise, PTR_ERR(-EINVAL).
+ */
+static struct cdev *check_overlap(struct cdev *cdev, const char *name, loff_t offset, loff_t size)
+{
+ struct cdev *cpart;
+ loff_t cpart_offset;
+ int ret;
+
+ list_for_each_entry(cpart, &cdev->partitions, partition_entry) {
+ cpart_offset = cpart->offset;
+
+ /*
+ * An mtd partition is represented by a separate cdev and its
+ * cpart is relative to this one. So its .offset is 0 and we
+ * have to consult .master_offset to get its offset.
+ */
+ if (cpart->mtd)
+ cpart_offset = cpart->mtd->master_offset;
+
+ if (region_identical(cpart_offset, cpart->size, offset, size)) {
+ ret = 0;
+ goto identical;
+ }
+
+ if (region_overlap(cpart_offset, cpart->size, offset, size)) {
+ ret = -EINVAL;
+ goto conflict;
+ }
+ }
+
+ return NULL;
+
+identical:
+conflict:
+ __pr_printk(ret ? MSG_WARNING : MSG_DEBUG,
+ "New partition %s (0x%08llx-0x%08llx) on %s "
+ "%s with partition %s (0x%08llx-0x%08llx), not creating it\n",
+ name, offset, offset + size - 1, cdev->name,
+ ret ? "conflicts" : "identical",
+ cpart->name, cpart_offset, cpart_offset + cpart->size - 1);
+
+ return ret ? ERR_PTR(ret) : cpart;
+}
+
static struct cdev *__devfs_add_partition(struct cdev *cdev,
const struct devfs_partition *partinfo, loff_t *end)
{
loff_t offset, size;
+ loff_t _end = end ? *end : 0;
static struct cdev *new;
+ struct cdev *overlap;
if (cdev_by_name(partinfo->name))
return ERR_PTR(-EEXIST);
@@ -314,7 +512,7 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
offset = partinfo->offset;
else if (partinfo->offset == 0)
/* append to previous partition */
- offset = *end;
+ offset = _end;
else
/* relative to end of cdev */
offset = cdev->size + partinfo->offset;
@@ -324,18 +522,30 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
else
size = cdev->size + partinfo->size - offset;
- if (offset >= 0 && offset < *end)
+ if (offset >= 0 && offset < _end)
pr_debug("partition %s not after previous partition\n",
partinfo->name);
- *end = offset + size;
+ _end = offset + size;
+ if (end)
+ *end = _end;
- if (offset < 0 || *end > cdev->size) {
+ if (offset < 0 || _end > cdev->size) {
pr_warn("partition %s not completely inside device %s\n",
partinfo->name, cdev->name);
return ERR_PTR(-EINVAL);
}
+ overlap = check_overlap(cdev, partinfo->name, offset, size);
+ if (overlap) {
+ if (!IS_ERR(overlap)) {
+ /* only fails with -EEXIST, which is fine */
+ (void)devfs_create_link(overlap, partinfo->name);
+ }
+
+ return overlap;
+ }
+
if (IS_ENABLED(CONFIG_MTD) && cdev->mtd) {
struct mtd_info *mtd;
@@ -348,8 +558,7 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
return &mtd->cdev;
}
- new = xzalloc(sizeof(*new));
- new->name = strdup(partinfo->name);
+ new = cdev_alloc(partinfo->name);
if (!strncmp(cdev->name, partinfo->name, strlen(cdev->name)))
new->partname = xstrdup(partinfo->name + strlen(cdev->name) + 1);
@@ -370,11 +579,16 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
return new;
}
+struct cdev *cdevfs_add_partition(struct cdev *cdev,
+ const struct devfs_partition *partinfo)
+{
+ return __devfs_add_partition(cdev, partinfo, NULL);
+}
+
struct cdev *devfs_add_partition(const char *devname, loff_t offset,
loff_t size, unsigned int flags, const char *name)
{
struct cdev *cdev;
- loff_t end = 0;
const struct devfs_partition partinfo = {
.offset = offset,
.size = size,
@@ -386,28 +600,21 @@ struct cdev *devfs_add_partition(const char *devname, loff_t offset,
if (!cdev)
return ERR_PTR(-ENOENT);
- return __devfs_add_partition(cdev, &partinfo, &end);
+ return cdevfs_add_partition(cdev, &partinfo);
}
-int devfs_del_partition(const char *name)
+int cdevfs_del_partition(struct cdev *cdev)
{
- struct cdev *cdev;
int ret;
- cdev = cdev_by_name(name);
- if (!cdev)
- return -ENOENT;
+ if (cdev->flags & DEVFS_PARTITION_FIXED)
+ return -EPERM;
if (IS_ENABLED(CONFIG_MTD) && cdev->mtd) {
ret = mtd_del_partition(cdev->mtd);
return ret;
}
- if (!cdev->master)
- return -EINVAL;
- if (cdev->flags & DEVFS_PARTITION_FIXED)
- return -EPERM;
-
ret = devfs_remove(cdev);
if (ret)
return ret;
@@ -419,6 +626,20 @@ int devfs_del_partition(const char *name)
return 0;
}
+int devfs_del_partition(const char *name)
+{
+ struct cdev *cdev;
+
+ cdev = cdev_by_name(name);
+ if (!cdev)
+ return -ENOENT;
+
+ if (!cdev_is_partition(cdev))
+ return -EINVAL;
+
+ return cdevfs_del_partition(cdev);
+}
+
int devfs_create_partitions(const char *devname,
const struct devfs_partition partinfo[])
{
@@ -481,6 +702,7 @@ static const struct cdev_operations loop_ops = {
struct cdev *cdev_create_loop(const char *path, ulong flags, loff_t offset)
{
+ char str[16];
struct cdev *new;
struct loop_priv *priv;
static int loopno;
@@ -494,10 +716,10 @@ struct cdev *cdev_create_loop(const char *path, ulong flags, loff_t offset)
return NULL;
}
- new = xzalloc(sizeof(*new));
+ snprintf(str, sizeof(str), "loop%u", loopno++);
+ new = cdev_alloc(str);
new->ops = &loop_ops;
- new->name = basprintf("loop%u", loopno++);
new->priv = priv;
ofs = lseek(priv->fd, 0, SEEK_END);
@@ -529,7 +751,7 @@ void cdev_remove_loop(struct cdev *cdev)
free(cdev);
}
-static ssize_t mem_copy(struct device_d *dev, void *dst, const void *src,
+ssize_t mem_copy(struct device *dev, void *dst, const void *src,
resource_size_t count, resource_size_t offset,
unsigned long flags)
{
@@ -539,7 +761,10 @@ static ssize_t mem_copy(struct device_d *dev, void *dst, const void *src,
if (!dev || dev->num_resources < 1)
return -1;
- count = size = min(count, resource_size(&dev->resource[0]) - offset);
+ if (resource_size(&dev->resource[0]) > 0 || offset != 0)
+ count = min(count, resource_size(&dev->resource[0]) - offset);
+
+ size = count;
/* no rwsize specification given. Do whatever memcpy likes best */
if (!rwsize) {
@@ -577,7 +802,7 @@ out:
ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset,
unsigned long flags)
{
- struct device_d *dev = cdev->dev;
+ struct device *dev = cdev->dev;
if (!dev)
return -1;
@@ -590,7 +815,7 @@ EXPORT_SYMBOL(mem_read);
ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count,
loff_t offset, unsigned long flags)
{
- struct device_d *dev = cdev->dev;
+ struct device *dev = cdev->dev;
if (!dev)
return -1;
diff --git a/fs/devfs.c b/fs/devfs.c
index df229cca48..c8ddbbdab0 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -28,23 +28,22 @@
#include <linux/err.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/mtd-abi.h>
-#include <partition.h>
+#include <block.h>
struct devfs_inode {
struct inode inode;
struct cdev *cdev;
};
-extern struct list_head cdev_list;
-
-static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
+static int devfs_read(struct device *_dev, FILE *f, void *buf, size_t size)
{
struct cdev *cdev = f->priv;
return cdev_read(cdev, buf, size, f->pos, f->flags);
}
-static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t size)
+static int devfs_write(struct device *_dev, FILE *f, const void *buf,
+ size_t size)
{
struct cdev *cdev = f->priv;
@@ -54,21 +53,15 @@ static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t s
return cdev_write(cdev, buf, size, f->pos, f->flags);
}
-static int devfs_lseek(struct device_d *_dev, FILE *f, loff_t pos)
+static int devfs_lseek(struct device *_dev, FILE *f, loff_t pos)
{
struct cdev *cdev = f->priv;
- int ret;
-
- if (cdev->ops->lseek) {
- ret = cdev->ops->lseek(cdev, pos + cdev->offset);
- if (ret < 0)
- return ret;
- }
- return 0;
+ return cdev_lseek(cdev, pos);
}
-static int devfs_erase(struct device_d *_dev, FILE *f, loff_t count, loff_t offset)
+static int devfs_erase(struct device *_dev, FILE *f, loff_t count,
+ loff_t offset)
{
struct cdev *cdev = f->priv;
@@ -81,53 +74,30 @@ static int devfs_erase(struct device_d *_dev, FILE *f, loff_t count, loff_t offs
return cdev_erase(cdev, count, offset);
}
-static int devfs_protect(struct device_d *_dev, FILE *f, size_t count, loff_t offset, int prot)
+static int devfs_protect(struct device *dev, FILE *f, size_t count,
+ loff_t offset, int prot)
{
struct cdev *cdev = f->priv;
- if (!cdev->ops->protect)
- return -ENOSYS;
-
- return cdev->ops->protect(cdev, count, offset + cdev->offset, prot);
+ return cdev_protect(cdev, count, offset, prot);
}
-static int devfs_discard_range(struct device_d *dev, FILE *f, loff_t count,
+static int devfs_discard_range(struct device *dev, FILE *f, loff_t count,
loff_t offset)
{
struct cdev *cdev = f->priv;
- if (!cdev->ops->discard_range)
- return -ENOSYS;
-
- if (cdev->flags & DEVFS_PARTITION_READONLY)
- return -EPERM;
-
- if (offset >= cdev->size)
- return 0;
-
- if (count + offset > cdev->size)
- count = cdev->size - offset;
-
- return cdev->ops->discard_range(cdev, count, offset + cdev->offset);
+ return cdev_discard_range(cdev, count, offset);
}
-static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
+static int devfs_memmap(struct device *_dev, FILE *f, void **map, int flags)
{
struct cdev *cdev = f->priv;
- int ret = -ENOSYS;
-
- if (!cdev->ops->memmap)
- return -EINVAL;
-
- ret = cdev->ops->memmap(cdev, map, flags);
- if (!ret)
- *map = (void *)((unsigned long)*map + (unsigned long)cdev->offset);
-
- return ret;
+ return cdev_memmap(cdev, map, flags);
}
-static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
+static int devfs_open(struct device *_dev, FILE *f, const char *filename)
{
struct inode *inode = f->f_inode;
struct devfs_inode *node = container_of(inode, struct devfs_inode, inode);
@@ -144,12 +114,10 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
return ret;
}
- cdev->open++;
-
return 0;
}
-static int devfs_close(struct device_d *_dev, FILE *f)
+static int devfs_close(struct device *_dev, FILE *f)
{
struct cdev *cdev = f->priv;
int ret;
@@ -160,33 +128,28 @@ static int devfs_close(struct device_d *_dev, FILE *f)
return ret;
}
- cdev->open--;
-
return 0;
}
-static int devfs_flush(struct device_d *_dev, FILE *f)
+static int devfs_flush(struct device *_dev, FILE *f)
{
struct cdev *cdev = f->priv;
return cdev_flush(cdev);
}
-static int devfs_ioctl(struct device_d *_dev, FILE *f, int request, void *buf)
+static int devfs_ioctl(struct device *_dev, FILE *f, int request, void *buf)
{
struct cdev *cdev = f->priv;
return cdev_ioctl(cdev, request, buf);
}
-static int devfs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int devfs_truncate(struct device *dev, FILE *f, loff_t size)
{
struct cdev *cdev = f->priv;
- if (cdev->ops->truncate)
- return cdev->ops->truncate(cdev, size);
-
- return -EPERM;
+ return cdev_truncate(cdev, size);
}
static struct inode *devfs_alloc_inode(struct super_block *sb)
@@ -213,7 +176,7 @@ static int devfs_iterate(struct file *file, struct dir_context *ctx)
dir_emit_dots(file, ctx);
- list_for_each_entry(cdev, &cdev_list, list) {
+ for_each_cdev(cdev) {
dir_emit(ctx, cdev->name, strlen(cdev->name),
1 /* FIXME */, DT_REG);
}
@@ -267,6 +230,7 @@ static struct inode *devfs_get_inode(struct super_block *sb, const struct inode
default:
return NULL;
case S_IFCHR:
+ case S_IFBLK:
inode->i_op = &devfs_file_inode_operations;
inode->i_fop = &devfs_file_operations;
break;
@@ -286,12 +250,15 @@ static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry,
struct devfs_inode *dinode;
struct inode *inode;
struct cdev *cdev;
+ umode_t mode;
cdev = cdev_by_name(dentry->name);
if (!cdev)
return ERR_PTR(-ENOENT);
- inode = devfs_get_inode(dir->i_sb, dir, S_IFCHR);
+ mode = cdev_get_block_device(cdev) ? S_IFBLK : S_IFCHR;
+
+ inode = devfs_get_inode(dir->i_sb, dir, mode);
if (!inode)
return ERR_PTR(-ENOMEM);
@@ -324,10 +291,10 @@ static const struct super_operations devfs_ops = {
.destroy_inode = devfs_destroy_inode,
};
-static int devfs_probe(struct device_d *dev)
+static int devfs_probe(struct device *dev)
{
struct inode *inode;
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct super_block *sb = &fsdev->sb;
sb->s_op = &devfs_ops;
@@ -339,11 +306,11 @@ static int devfs_probe(struct device_d *dev)
return 0;
}
-static void devfs_delete(struct device_d *dev)
+static void devfs_delete(struct device *dev)
{
}
-static struct fs_driver_d devfs_driver = {
+static struct fs_driver devfs_driver = {
.read = devfs_read,
.write = devfs_write,
.lseek = devfs_lseek,
diff --git a/fs/efi.c b/fs/efi.c
index edf65179fd..11073e9961 100644
--- a/fs/efi.c
+++ b/fs/efi.c
@@ -28,69 +28,10 @@
#include <wchar.h>
#include <efi.h>
#include <libfile.h>
-#include <efi/efi.h>
+#include <efi/efi-payload.h>
#include <efi/efi-device.h>
#include <linux/stddef.h>
-/* Open modes */
-#define EFI_FILE_MODE_READ 0x0000000000000001
-#define EFI_FILE_MODE_WRITE 0x0000000000000002
-#define EFI_FILE_MODE_CREATE 0x8000000000000000
-
-/* File attributes */
-#define EFI_FILE_READ_ONLY 0x0000000000000001
-#define EFI_FILE_HIDDEN 0x0000000000000002
-#define EFI_FILE_SYSTEM 0x0000000000000004
-#define EFI_FILE_RESERVIED 0x0000000000000008
-#define EFI_FILE_DIRECTORY 0x0000000000000010
-#define EFI_FILE_ARCHIVE 0x0000000000000020
-#define EFI_FILE_VALID_ATTR 0x0000000000000037
-
-#define EFI_FILE_HANDLE_REVISION 0x00010000
-struct efi_file_handle {
- uint64_t Revision;
- efi_status_t(EFIAPI *open)(struct efi_file_handle *File,
- struct efi_file_handle **NewHandle, s16 *FileName,
- uint64_t OpenMode, uint64_t Attributes);
- efi_status_t(EFIAPI *close)(struct efi_file_handle *File);
- efi_status_t(EFIAPI *delete)(struct efi_file_handle *File);
- efi_status_t(EFIAPI *read)(struct efi_file_handle *File, unsigned long *BufferSize,
- void *Buffer);
- efi_status_t(EFIAPI *write)(struct efi_file_handle *File,
- unsigned long *BufferSize, void *Buffer);
- efi_status_t(EFIAPI *get_position)(struct efi_file_handle *File,
- uint64_t *Position);
- efi_status_t(EFIAPI *set_position)(struct efi_file_handle *File,
- uint64_t Position);
- efi_status_t(EFIAPI *get_info)(struct efi_file_handle *File,
- efi_guid_t *InformationType, unsigned long *BufferSize,
- void *Buffer);
- efi_status_t(EFIAPI *set_info)(struct efi_file_handle *File,
- efi_guid_t *InformationType, unsigned long BufferSize,
- void *Buffer);
- efi_status_t(EFIAPI *flush)(struct efi_file_handle *File);
-};
-
-#define EFI_FILE_IO_INTERFACE_REVISION 0x00010000
-
-struct efi_file_io_interface {
- uint64_t Revision;
- efi_status_t(EFIAPI *open_volume)(
- struct efi_file_io_interface *This,
- struct efi_file_handle **Root);
-};
-
-struct efi_file_info {
- uint64_t Size;
- uint64_t FileSize;
- uint64_t PhysicalSize;
- efi_time_t CreateTime;
- efi_time_t LastAccessTime;
- efi_time_t ModificationTime;
- uint64_t Attribute;
- s16 FileName[1];
-};
-
struct efifs_priv {
struct efi_file_handle *root_dir;
struct efi_file_io_interface *protocol;
@@ -128,7 +69,7 @@ static wchar_t *path_to_efi(const char *path)
return ret;
}
-static int efifs_create(struct device_d *dev, const char *pathname, mode_t mode)
+static int efifs_create(struct device *dev, const char *pathname, mode_t mode)
{
struct efifs_priv *priv = dev->priv;
wchar_t *efi_path = path_to_efi(pathname);
@@ -151,7 +92,7 @@ static int efifs_create(struct device_d *dev, const char *pathname, mode_t mode)
return 0;
}
-static int efifs_unlink(struct device_d *dev, const char *pathname)
+static int efifs_unlink(struct device *dev, const char *pathname)
{
struct efifs_priv *priv = dev->priv;
wchar_t *efi_path = path_to_efi(pathname);
@@ -173,7 +114,7 @@ static int efifs_unlink(struct device_d *dev, const char *pathname)
return 0;
}
-static int efifs_mkdir(struct device_d *dev, const char *pathname)
+static int efifs_mkdir(struct device *dev, const char *pathname)
{
struct efifs_priv *priv = dev->priv;
wchar_t *efi_path = path_to_efi(pathname);
@@ -196,12 +137,12 @@ static int efifs_mkdir(struct device_d *dev, const char *pathname)
return 0;
}
-static int efifs_rmdir(struct device_d *dev, const char *pathname)
+static int efifs_rmdir(struct device *dev, const char *pathname)
{
return efifs_unlink(dev, pathname);
}
-static int efifs_open(struct device_d *dev, FILE *f, const char *filename)
+static int efifs_open(struct device *dev, FILE *f, const char *filename)
{
struct efifs_priv *priv = dev->priv;
efi_status_t efiret;
@@ -249,7 +190,7 @@ out:
return ret;
}
-static int efifs_close(struct device_d *dev, FILE *f)
+static int efifs_close(struct device *dev, FILE *f)
{
struct efifs_file *ufile = f->priv;
@@ -260,7 +201,7 @@ static int efifs_close(struct device_d *dev, FILE *f)
return 0;
}
-static int efifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int efifs_read(struct device *_dev, FILE *f, void *buf, size_t insize)
{
struct efifs_file *ufile = f->priv;
efi_status_t efiret;
@@ -274,7 +215,8 @@ static int efifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
return bufsize;
}
-static int efifs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+static int efifs_write(struct device *_dev, FILE *f, const void *buf,
+ size_t insize)
{
struct efifs_file *ufile = f->priv;
efi_status_t efiret;
@@ -289,7 +231,7 @@ static int efifs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
return bufsize;
}
-static int efifs_lseek(struct device_d *dev, FILE *f, loff_t pos)
+static int efifs_lseek(struct device *dev, FILE *f, loff_t pos)
{
struct efifs_file *ufile = f->priv;
efi_status_t efiret;
@@ -302,7 +244,7 @@ static int efifs_lseek(struct device_d *dev, FILE *f, loff_t pos)
return 0;
}
-static int efifs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int efifs_truncate(struct device *dev, FILE *f, loff_t size)
{
struct efifs_file *ufile = f->priv;
efi_status_t efiret;
@@ -336,7 +278,7 @@ out:
return ret;
}
-static DIR *efifs_opendir(struct device_d *dev, const char *pathname)
+static DIR *efifs_opendir(struct device *dev, const char *pathname)
{
struct efifs_priv *priv = dev->priv;
efi_status_t efiret;
@@ -356,7 +298,7 @@ static DIR *efifs_opendir(struct device_d *dev, const char *pathname)
return &udir->dir;
}
-static struct dirent *efifs_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *efifs_readdir(struct device *dev, DIR *dir)
{
struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
efi_status_t efiret;
@@ -375,7 +317,7 @@ static struct dirent *efifs_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int efifs_closedir(struct device_d *dev, DIR *dir)
+static int efifs_closedir(struct device *dev, DIR *dir)
{
struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
@@ -386,7 +328,8 @@ static int efifs_closedir(struct device_d *dev, DIR *dir)
return 0;
}
-static int efifs_stat(struct device_d *dev, const char *filename, struct stat *s)
+static int efifs_stat(struct device *dev, const char *filename,
+ struct stat *s)
{
struct efifs_priv *priv = dev->priv;
wchar_t *efi_path;
@@ -435,25 +378,25 @@ out_free:
return ret;
}
-static int efifs_symlink(struct device_d *dev, const char *pathname,
- const char *newpath)
+static int efifs_symlink(struct device *dev, const char *pathname,
+ const char *newpath)
{
return -EROFS;
}
-static int efifs_readlink(struct device_d *dev, const char *pathname,
- char *buf, size_t bufsiz)
+static int efifs_readlink(struct device *dev, const char *pathname,
+ char *buf, size_t bufsiz)
{
return -ENOENT;
}
-static int efifs_probe(struct device_d *dev)
+static int efifs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct efifs_priv *priv;
efi_status_t efiret;
struct efi_file_handle *file;
- struct device_d *efi = get_device_by_name(fsdev->backingstore);
+ struct device *efi = get_device_by_name(fsdev->backingstore);
struct efi_device *udev = container_of(efi, struct efi_device, dev);
priv = xzalloc(sizeof(struct efifs_priv));
@@ -472,12 +415,12 @@ static int efifs_probe(struct device_d *dev)
return 0;
}
-static void efifs_remove(struct device_d *dev)
+static void efifs_remove(struct device *dev)
{
free(dev->priv);
}
-static struct fs_driver_d efifs_driver = {
+static struct fs_driver efifs_driver = {
.create = efifs_create,
.unlink = efifs_unlink,
.open = efifs_open,
diff --git a/fs/efivarfs.c b/fs/efivarfs.c
index 659716f845..b199318061 100644
--- a/fs/efivarfs.c
+++ b/fs/efivarfs.c
@@ -28,7 +28,7 @@
#include <wchar.h>
#include <linux/err.h>
#include <linux/ctype.h>
-#include <efi/efi.h>
+#include <efi/efi-payload.h>
#include <efi/efi-device.h>
struct efivarfs_inode {
@@ -47,83 +47,8 @@ struct efivarfs_priv {
struct list_head inodes;
};
-static int char_to_nibble(char c)
-{
- int ret = tolower(c);
-
- return ret <= '9' ? ret - '0' : ret - 'a' + 10;
-}
-
-static int read_byte_str(const char *str, u8 *out)
-{
- if (!isxdigit(*str) || !isxdigit(*(str + 1)))
- return -EINVAL;
-
- *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1));
-
- return 0;
-}
-
-static int efi_guid_parse(const char *str, efi_guid_t *guid)
-{
- int i, ret;
- u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
-
- for (i = 0; i < 16; i++) {
- ret = read_byte_str(str, &guid->b[idx[i]]);
- if (ret)
- return ret;
- str += 2;
-
- switch (i) {
- case 3:
- case 5:
- case 7:
- case 9:
- if (*str != '-')
- return -EINVAL;
- str++;
- break;
- }
- }
-
- return 0;
-}
-
-static int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name)
-{
- int len, ret;
- const char *guidstr;
- s16 *varname;
- int i;
-
- if (*filename == '/')
- filename++;
-
- len = strlen(filename);
-
- if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"))
- return -EINVAL;
-
- guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
- if (*guidstr != '-')
- return -EINVAL;
-
- guidstr++;
-
- ret = efi_guid_parse(guidstr, vendor);
-
- varname = xzalloc((guidstr - filename) * sizeof(s16));
-
- for (i = 0; i < guidstr - filename - 1; i++)
- varname[i] = filename[i];
-
- *name = varname;
-
- return 0;
-}
-
-static int efivars_create(struct device_d *dev, const char *pathname, mode_t mode)
+static int efivars_create(struct device *dev, const char *pathname,
+ mode_t mode)
{
struct efivarfs_priv *priv = dev->priv;
struct efivarfs_inode *inode;
@@ -169,7 +94,7 @@ static int efivars_create(struct device_d *dev, const char *pathname, mode_t mod
return 0;
}
-static int efivars_unlink(struct device_d *dev, const char *pathname)
+static int efivars_unlink(struct device *dev, const char *pathname)
{
struct efivarfs_priv *priv = dev->priv;
struct efivarfs_inode *inode, *tmp;
@@ -200,7 +125,7 @@ struct efivars_file {
u32 attributes;
};
-static int efivarfs_open(struct device_d *dev, FILE *f, const char *filename)
+static int efivarfs_open(struct device *dev, FILE *f, const char *filename)
{
struct efivars_file *efile;
efi_status_t efiret;
@@ -245,7 +170,7 @@ out:
return ret;
}
-static int efivarfs_close(struct device_d *dev, FILE *f)
+static int efivarfs_close(struct device *dev, FILE *f)
{
struct efivars_file *efile = f->priv;
@@ -255,7 +180,8 @@ static int efivarfs_close(struct device_d *dev, FILE *f)
return 0;
}
-static int efivarfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int efivarfs_read(struct device *_dev, FILE *f, void *buf,
+ size_t insize)
{
struct efivars_file *efile = f->priv;
@@ -264,7 +190,8 @@ static int efivarfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insiz
return insize;
}
-static int efivarfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+static int efivarfs_write(struct device *_dev, FILE *f, const void *buf,
+ size_t insize)
{
struct efivars_file *efile = f->priv;
efi_status_t efiret;
@@ -285,7 +212,7 @@ static int efivarfs_write(struct device_d *_dev, FILE *f, const void *buf, size_
return insize;
}
-static int efivarfs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int efivarfs_truncate(struct device *dev, FILE *f, loff_t size)
{
struct efivars_file *efile = f->priv;
efi_status_t efiret;
@@ -304,7 +231,7 @@ static int efivarfs_truncate(struct device_d *dev, FILE *f, loff_t size)
return 0;
}
-static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname)
+static DIR *efivarfs_opendir(struct device *dev, const char *pathname)
{
struct efivarfs_priv *priv = dev->priv;
struct efivarfs_dir *edir;
@@ -315,7 +242,7 @@ static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname)
return &edir->dir;
}
-static struct dirent *efivarfs_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *efivarfs_readdir(struct device *dev, DIR *dir)
{
struct efivarfs_priv *priv = dev->priv;
struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
@@ -333,7 +260,7 @@ static struct dirent *efivarfs_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int efivarfs_closedir(struct device_d *dev, DIR *dir)
+static int efivarfs_closedir(struct device *dev, DIR *dir)
{
struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
@@ -342,7 +269,8 @@ static int efivarfs_closedir(struct device_d *dev, DIR *dir)
return 0;
}
-static int efivarfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+static int efivarfs_stat(struct device *dev, const char *filename,
+ struct stat *s)
{
efi_guid_t vendor;
s16 *name;
@@ -367,7 +295,7 @@ static int efivarfs_stat(struct device_d *dev, const char *filename, struct stat
return 0;
}
-static int efivarfs_probe(struct device_d *dev)
+static int efivarfs_probe(struct device *dev)
{
efi_status_t efiret;
efi_guid_t vendor;
@@ -406,7 +334,7 @@ static int efivarfs_probe(struct device_d *dev)
return 0;
}
-static void efivarfs_remove(struct device_d *dev)
+static void efivarfs_remove(struct device *dev)
{
struct efivarfs_priv *priv = dev->priv;
struct efivarfs_inode *inode, *tmp;
@@ -419,7 +347,7 @@ static void efivarfs_remove(struct device_d *dev)
free(priv);
}
-static struct fs_driver_d efivarfs_driver = {
+static struct fs_driver efivarfs_driver = {
.create = efivars_create,
.unlink = efivars_unlink,
.open = efivarfs_open,
@@ -443,4 +371,4 @@ static int efivarfs_init(void)
return register_fs_driver(&efivarfs_driver);
}
-coredevice_initcall(efivarfs_init);
+coredevice_efi_initcall(efivarfs_init);
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index f36043d9a7..cb01675507 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
config FS_EXT4
bool
prompt "ext4 filesystem support"
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 5084e3fb25..223f50e470 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -1 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-$(CONFIG_FS_EXT4) += ext4fs.o ext4_common.o ext_barebox.o
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index c9f27f1278..4bfb55ad0d 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -43,10 +43,11 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
uint32_t fileblock, int log2_blksz)
{
struct ext4_extent_idx *index;
- unsigned long long block;
+ sector_t block;
struct ext_filesystem *fs = data->fs;
int blksz = EXT2_BLOCK_SIZE(data);
- int i, ret;
+ ssize_t ret;
+ int i;
while (1) {
index = (struct ext4_extent_idx *)(ext_block + 1);
@@ -77,10 +78,10 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
}
}
-static int ext4fs_blockgroup(struct ext2_data *data, int group,
+static ssize_t ext4fs_blockgroup(struct ext2_data *data, int group,
struct ext2_block_group *blkgrp)
{
- long int blkno;
+ sector_t blkno;
unsigned int blkoff, desc_per_blk;
struct ext_filesystem *fs = data->fs;
int desc_size = fs->gdsize;
@@ -91,7 +92,7 @@ static int ext4fs_blockgroup(struct ext2_data *data, int group,
group / desc_per_blk;
blkoff = (group % desc_per_blk) * desc_size;
- dev_dbg(fs->dev, "read %d group descriptor (blkno %ld blkoff %u)\n",
+ dev_dbg(fs->dev, "read %d group descriptor (blkno %llu blkoff %u)\n",
group, blkno, blkoff);
return ext4fs_devread(fs, blkno << LOG2_EXT2_BLOCK_SIZE(data),
@@ -103,8 +104,9 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
struct ext2_block_group blkgrp;
struct ext2_sblock *sblock = &data->sblock;
struct ext_filesystem *fs = data->fs;
- int inodes_per_block, ret;
- long int blkno;
+ int inodes_per_block;
+ ssize_t ret;
+ sector_t blkno;
unsigned int blkoff;
/* It is easier to calculate if the first inode is 0. */
@@ -128,11 +130,11 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
}
static int ext4fs_get_indir_block(struct ext2fs_node *node,
- struct ext4fs_indir_block *indir, int blkno)
+ struct ext4fs_indir_block *indir, sector_t blkno)
{
struct ext_filesystem *fs = node->data->fs;
int blksz;
- int ret;
+ ssize_t ret;
blksz = EXT2_BLOCK_SIZE(node->data);
@@ -488,7 +490,8 @@ fail:
int ext4fs_mount(struct ext_filesystem *fs)
{
struct ext2_data *data;
- int ret, blksz;
+ ssize_t ret;
+ int blksz;
data = zalloc(sizeof(struct ext2_data));
if (!data)
diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
index 81fb67ef4c..f8ebd76266 100644
--- a/fs/ext4/ext4_common.h
+++ b/fs/ext4/ext4_common.h
@@ -48,8 +48,8 @@ static inline void *zalloc(size_t size)
int ext4fs_read_inode(struct ext2_data *data, int ino,
struct ext2_inode *inode);
-int ext4fs_read_file(struct ext2fs_node *node, int pos,
- unsigned int len, char *buf);
+loff_t ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
+ unsigned int len, char *buf);
int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
struct ext2fs_node **foundnode, int *foundtype);
int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 2d231d273a..344d423fd9 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -47,38 +47,42 @@ void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
* Optimized read file API : collects and defers contiguous sector
* reads into one potentially more efficient larger sequential read action
*/
-int ext4fs_read_file(struct ext2fs_node *node, int pos,
+loff_t ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
unsigned int len, char *buf)
{
- int i;
- int blockcnt;
+ loff_t i;
+ blkcnt_t blockcnt;
int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data);
- int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
- unsigned int filesize = le32_to_cpu(node->inode.size);
- short ret;
+ const int blockshift = log2blocksize + DISK_SECTOR_BITS;
+ const int blocksize = 1 << blockshift;
+ loff_t filesize = ext4_isize(node);
+ ssize_t ret;
struct ext_filesystem *fs = node->data->fs;
/* Adjust len so it we can't read past the end of the file. */
- if (len > filesize)
- len = filesize;
+ if (len + pos > filesize)
+ len = filesize - pos;
- blockcnt = ((len + pos) + blocksize - 1) / blocksize;
+ if (filesize <= pos)
+ return -EINVAL;
- for (i = pos / blocksize; i < blockcnt; i++) {
- int blknr;
- int blockoff = pos % blocksize;
- int blockend = blocksize;
- int skipfirst = 0;
+ blockcnt = ((len + pos) + blocksize - 1) >> blockshift;
- blknr = read_allocated_block(node, i);
- if (blknr < 0)
- return blknr;
+ for (i = pos >> blockshift; i < blockcnt; i++) {
+ sector_t blknr;
+ loff_t blockoff = pos - (blocksize * i);
+ loff_t blockend = blocksize;
+ loff_t skipfirst = 0;
- blknr = blknr << log2blocksize;
+ ret = read_allocated_block(node, i);
+ if (ret < 0)
+ return ret;
+
+ blknr = ret << log2blocksize;
/* Last block. */
if (i == blockcnt - 1) {
- blockend = (len + pos) % blocksize;
+ blockend = (len + pos) - (blocksize * i);
/* The last portion is exactly blocksize. */
if (!blockend)
@@ -86,7 +90,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos,
}
/* First block. */
- if (i == pos / blocksize) {
+ if (i == pos >> blockshift) {
skipfirst = blockoff;
blockend -= skipfirst;
}
diff --git a/fs/ext4/ext4fs.h b/fs/ext4/ext4fs.h
index 17a490a943..707565e671 100644
--- a/fs/ext4/ext4fs.h
+++ b/fs/ext4/ext4fs.h
@@ -74,46 +74,17 @@ struct ext4_extent_header {
};
struct ext_filesystem {
- /* Total Sector of partition */
- uint64_t total_sect;
- /* Block size of partition */
- uint32_t blksz;
/* Inode size of partition */
uint32_t inodesz;
- /* Sectors per Block */
- uint32_t sect_perblk;
/* Group Descriptor size */
uint16_t gdsize;
- /* Group Descriptor Block Number */
- uint32_t gdtable_blkno;
- /* Total block groups of partition */
- uint32_t no_blkgrp;
- /* No of blocks required for bgdtable */
- uint32_t no_blk_pergdt;
- /* Superblock */
- struct ext2_sblock *sb;
- /* Block group descritpor table */
- struct ext2_block_group *bgd;
- char *gdtable;
-
- /* Block Bitmap Related */
- unsigned char **blk_bmaps;
- long int curr_blkno;
- uint16_t first_pass_bbmap;
-
- /* Inode Bitmap Related */
- unsigned char **inode_bmaps;
- int curr_inode_no;
- uint16_t first_pass_ibmap;
-
- /* Journal Related */
/* Block Device Descriptor */
struct cdev *cdev;
struct ext2_data *data;
- struct device_d *dev;
+ struct device *dev;
};
struct ext2fs_node;
@@ -124,7 +95,7 @@ int ext4fs_mount(struct ext_filesystem *fs);
void ext4fs_umount(struct ext_filesystem *fs);
char *ext4fs_read_symlink(struct ext2fs_node *node);
void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
-int ext4fs_devread(struct ext_filesystem *fs, int sector, int byte_offset, int byte_len, char *buf);
+ssize_t ext4fs_devread(struct ext_filesystem *fs, sector_t sector, int byte_offset, size_t byte_len, char *buf);
long int read_allocated_block(struct ext2fs_node *node, int fileblock);
#endif
diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c
index 353ab44b29..df82b629cd 100644
--- a/fs/ext4/ext_barebox.c
+++ b/fs/ext4/ext_barebox.c
@@ -27,15 +27,15 @@
#include <fcntl.h>
#include "ext4_common.h"
-int ext4fs_devread(struct ext_filesystem *fs, int __sector, int byte_offset,
- int byte_len, char *buf)
+ssize_t ext4fs_devread(struct ext_filesystem *fs, sector_t __sector, int byte_offset,
+ size_t byte_len, char *buf)
{
ssize_t size;
uint64_t sector = __sector;
size = cdev_read(fs->cdev, buf, byte_len, sector * SECTOR_SIZE + byte_offset, 0);
if (size < 0) {
- dev_err(fs->dev, "read error at sector %d: %s\n", __sector,
+ dev_err(fs->dev, "read error at sector %llu: %s\n", __sector,
strerror(-size));
return size;
}
@@ -48,7 +48,7 @@ static inline struct ext2fs_node *to_ext2_node(struct inode *inode)
return container_of(inode, struct ext2fs_node, i);
}
-static int ext_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int ext_read(struct device *_dev, FILE *f, void *buf, size_t insize)
{
struct inode *inode = f->f_inode;
struct ext2fs_node *node = to_ext2_node(inode);
@@ -58,7 +58,7 @@ static int ext_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
static struct inode *ext_alloc_inode(struct super_block *sb)
{
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct ext_filesystem *fs = fsdev->dev.priv;
struct ext2fs_node *node;
@@ -118,7 +118,7 @@ static struct dentry *ext_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
struct ext2fs_node *e2dir = to_ext2_node(dir);
- int ret, ino;
+ int ret, ino = 0;
struct inode *inode;
ret = ext4fs_get_ino(e2dir, &dentry->d_name, &ino);
@@ -127,8 +127,8 @@ static struct dentry *ext_lookup(struct inode *dir, struct dentry *dentry,
if (ino) {
inode = ext_get_inode(dir->i_sb, ino);
-
- d_add(dentry, inode);
+ if (inode)
+ d_add(dentry, inode);
}
return NULL;
@@ -209,7 +209,7 @@ struct inode *ext_get_inode(struct super_block *sb, int ino)
{
struct inode *inode;
struct ext2fs_node *node;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct ext_filesystem *fs = fsdev->dev.priv;
int ret;
@@ -218,10 +218,12 @@ struct inode *ext_get_inode(struct super_block *sb, int ino)
node = container_of(inode, struct ext2fs_node, i);
ret = ext4fs_read_inode(fs->data, ino, &node->inode);
+ if (ret)
+ return NULL;
inode->i_ino = ino;
inode->i_mode = le16_to_cpu(node->inode.mode);
- inode->i_size = le32_to_cpu(node->inode.size);
+ inode->i_size = ext4_isize(node);
switch (inode->i_mode & S_IFMT) {
default:
@@ -247,9 +249,9 @@ struct inode *ext_get_inode(struct super_block *sb, int ino)
return inode;
}
-static int ext_probe(struct device_d *dev)
+static int ext_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
int ret;
struct ext_filesystem *fs;
struct super_block *sb = &fsdev->sb;
@@ -262,29 +264,33 @@ static int ext_probe(struct device_d *dev)
ret = fsdev_open_cdev(fsdev);
if (ret)
- goto err_open;
+ goto err;
fs->cdev = fsdev->cdev;
ret = ext4fs_mount(fs);
if (ret)
- goto err_mount;
+ goto err;
sb->s_op = &ext_ops;
inode = ext_get_inode(sb, 2);
+ if (!inode) {
+ ret = -EINVAL;
+ goto err;
+ }
+
sb->s_root = d_make_root(inode);
return 0;
-err_mount:
-err_open:
+err:
free(fs);
return ret;
}
-static void ext_remove(struct device_d *dev)
+static void ext_remove(struct device *dev)
{
struct ext_filesystem *fs = dev->priv;
@@ -292,7 +298,7 @@ static void ext_remove(struct device_d *dev)
free(fs);
}
-static struct fs_driver_d ext_driver = {
+static struct fs_driver ext_driver = {
.read = ext_read,
.type = filetype_ext,
.flags = 0,
diff --git a/fs/ext4/ext_common.h b/fs/ext4/ext_common.h
index a28f591bc4..37575d2a1a 100644
--- a/fs/ext4/ext_common.h
+++ b/fs/ext4/ext_common.h
@@ -232,5 +232,13 @@ struct ext2_data {
struct ext4fs_indir_block indir1, indir2, indir3;
};
-extern unsigned long part_offset;
+static inline loff_t ext4_isize(struct ext2fs_node *node)
+{
+ if (S_ISREG(le16_to_cpu(node->inode.mode)))
+ return ((loff_t)le32_to_cpu(node->inode.size_high) << 32) |
+ le32_to_cpu(node->inode.size);
+
+ return (loff_t) le32_to_cpu(node->inode.size);
+}
+
#endif
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index bc3b4b69e8..53f784ee54 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig FS_FAT
bool
select FS_LEGACY
@@ -14,7 +16,7 @@ config FS_FAT_WRITE
config FS_FAT_LFN
- bool
+ def_bool y
prompt "Support long filenames"
help
Enable support for file names other than 8.3.
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index fe47569bda..7a7a5ccdc6 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += fat.o
pbl-y += fat-pbl.o
obj-pbl-y += ff.o fat-diskio.o
diff --git a/fs/fat/diskio.h b/fs/fat/diskio.h
index aee1ce2b0b..57626d2fbd 100644
--- a/fs/fat/diskio.h
+++ b/fs/fat/diskio.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file
/-----------------------------------------------------------------------*/
diff --git a/fs/fat/fat-pbl.c b/fs/fat/fat-pbl.c
index 93cd6decbc..6b8a807657 100644
--- a/fs/fat/fat-pbl.c
+++ b/fs/fat/fat-pbl.c
@@ -8,10 +8,10 @@
#define pr_fmt(fmt) "fat-pbl: " fmt
#include <common.h>
+#include <pbl/bio.h>
#include "integer.h"
#include "ff.h"
#include "diskio.h"
-#include "pbl.h"
DRESULT disk_read(FATFS *fat, BYTE *buf, DWORD sector, BYTE count)
{
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 84bfe69089..f3c7f9b863 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -68,7 +68,7 @@ DRESULT disk_write(FATFS *fat, const BYTE *buf, DWORD sector, BYTE count)
/* ---------------------------------------------------------------*/
#ifdef CONFIG_FS_FAT_WRITE
-static int fat_create(struct device_d *dev, const char *pathname, mode_t mode)
+static int fat_create(struct device *dev, const char *pathname, mode_t mode)
{
struct fat_priv *priv = dev->priv;
FIL f_file;
@@ -83,7 +83,7 @@ static int fat_create(struct device_d *dev, const char *pathname, mode_t mode)
return 0;
}
-static int fat_unlink(struct device_d *dev, const char *pathname)
+static int fat_unlink(struct device *dev, const char *pathname)
{
struct fat_priv *priv = dev->priv;
int ret;
@@ -97,7 +97,7 @@ static int fat_unlink(struct device_d *dev, const char *pathname)
return 0;
}
-static int fat_mkdir(struct device_d *dev, const char *pathname)
+static int fat_mkdir(struct device *dev, const char *pathname)
{
struct fat_priv *priv = dev->priv;
int ret;
@@ -111,7 +111,7 @@ static int fat_mkdir(struct device_d *dev, const char *pathname)
return 0;
}
-static int fat_rmdir(struct device_d *dev, const char *pathname)
+static int fat_rmdir(struct device *dev, const char *pathname)
{
struct fat_priv *priv = dev->priv;
int ret;
@@ -125,7 +125,8 @@ static int fat_rmdir(struct device_d *dev, const char *pathname)
return 0;
}
-static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+static int fat_write(struct device *_dev, FILE *f, const void *buf,
+ size_t insize)
{
FIL *f_file = f->priv;
int outsize;
@@ -143,7 +144,7 @@ static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t ins
return outsize;
}
-static int fat_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int fat_truncate(struct device *dev, FILE *f, loff_t size)
{
FIL *f_file = f->priv;
unsigned long lastofs;
@@ -167,7 +168,7 @@ static int fat_truncate(struct device_d *dev, FILE *f, loff_t size)
}
#endif /* CONFIG_FS_FAT_WRITE */
-static int fat_open(struct device_d *dev, FILE *file, const char *filename)
+static int fat_open(struct device *dev, FILE *file, const char *filename)
{
struct fat_priv *priv = dev->priv;
FIL *f_file;
@@ -196,6 +197,11 @@ static int fat_open(struct device_d *dev, FILE *file, const char *filename)
if (file->flags & O_APPEND) {
ret = f_lseek(f_file, f_file->fsize);
+ if (ret) {
+ f_close(f_file);
+ free(f_file);
+ return -EINVAL;
+ }
}
file->priv = f_file;
@@ -204,7 +210,7 @@ static int fat_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int fat_close(struct device_d *dev, FILE *f)
+static int fat_close(struct device *dev, FILE *f)
{
struct fat_priv *priv = dev->priv;
FIL *f_file = f->priv;
@@ -218,7 +224,7 @@ static int fat_close(struct device_d *dev, FILE *f)
return 0;
}
-static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int fat_read(struct device *_dev, FILE *f, void *buf, size_t insize)
{
int ret;
FIL *f_file = f->priv;
@@ -234,7 +240,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
return outsize;
}
-static int fat_lseek(struct device_d *dev, FILE *f, loff_t pos)
+static int fat_lseek(struct device *dev, FILE *f, loff_t pos)
{
FIL *f_file = f->priv;
int ret;
@@ -246,7 +252,7 @@ static int fat_lseek(struct device_d *dev, FILE *f, loff_t pos)
return 0;
}
-static DIR* fat_opendir(struct device_d *dev, const char *pathname)
+static DIR* fat_opendir(struct device *dev, const char *pathname)
{
struct fat_priv *priv = dev->priv;
DIR *dir;
@@ -271,7 +277,7 @@ static DIR* fat_opendir(struct device_d *dev, const char *pathname)
return dir;
}
-static struct dirent* fat_readdir(struct device_d *dev, DIR *dir)
+static struct dirent* fat_readdir(struct device *dev, DIR *dir)
{
FF_DIR *ff_dir = dir->priv;
FILINFO finfo;
@@ -301,7 +307,7 @@ static struct dirent* fat_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int fat_closedir(struct device_d *dev, DIR *dir)
+static int fat_closedir(struct device *dev, DIR *dir)
{
FF_DIR *ff_dir = dir->priv;
@@ -311,7 +317,7 @@ static int fat_closedir(struct device_d *dev, DIR *dir)
return 0;
}
-static int fat_stat(struct device_d *dev, const char *filename, struct stat *s)
+static int fat_stat(struct device *dev, const char *filename, struct stat *s)
{
struct fat_priv *priv = dev->priv;
FILINFO finfo;
@@ -334,9 +340,9 @@ static int fat_stat(struct device_d *dev, const char *filename, struct stat *s)
return 0;
}
-static int fat_probe(struct device_d *dev)
+static int fat_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct fat_priv *priv = xzalloc(sizeof(struct fat_priv));
int ret;
@@ -362,12 +368,12 @@ err_open:
return ret;
}
-static void fat_remove(struct device_d *dev)
+static void fat_remove(struct device *dev)
{
free(dev->priv);
}
-static struct fs_driver_d fat_driver = {
+static struct fs_driver fat_driver = {
.open = fat_open,
.close = fat_close,
.read = fat_read,
diff --git a/fs/fat/ffconf.h b/fs/fat/ffconf.h
index 2f6a6c1544..abf7d1e92e 100644
--- a/fs/fat/ffconf.h
+++ b/fs/fat/ffconf.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011
/----------------------------------------------------------------------------/
diff --git a/fs/fat/integer.h b/fs/fat/integer.h
index 04956aa775..fe94e374f3 100644
--- a/fs/fat/integer.h
+++ b/fs/fat/integer.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
diff --git a/fs/fs.c b/fs/fs.c
index e04cadfe5d..3a5298649c 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -31,6 +31,7 @@
#include <environment.h>
#include <libgen.h>
#include <block.h>
+#include <slice.h>
#include <libfile.h>
#include <parseopt.h>
#include <linux/namei.h>
@@ -66,6 +67,150 @@ char *mkmodestr(unsigned long mode, char *str)
}
EXPORT_SYMBOL(mkmodestr);
+void cdev_print(const struct cdev *cdev)
+{
+ struct device_node *np;
+ int nbytes;
+
+ if (cdev->dev || cdev->master || cdev->partname) {
+ printf("Origin: %s", dev_name(cdev->dev) ?: "None");
+ if (cdev->master)
+ printf("\tMaster: %s", cdev->master->name);
+ if (cdev->partname)
+ printf("\tPartition: %s", cdev->partname);
+ printf("\n");
+ }
+ printf("Ocount: %d\tFlags: 0x%02x", cdev->open, cdev->flags);
+ if (cdev->flags) {
+ printf(" (");
+ if (cdev->flags & DEVFS_IS_CHARACTER_DEV)
+ printf(" cdev");
+ if (cdev->flags & DEVFS_PARTITION_FIXED)
+ printf(" fixed-partition");
+ if (cdev->flags & DEVFS_PARTITION_READONLY)
+ printf(" readonly-partition");
+ if (cdev->flags & DEVFS_PARTITION_FROM_OF)
+ printf(" of-partition");
+ if (cdev->flags & DEVFS_PARTITION_FROM_TABLE)
+ printf(" table-partition");
+ if (cdev->flags & DEVFS_PARTITION_FOR_FIXUP)
+ printf(" fixup");
+ if (cdev->flags & DEVFS_IS_MCI_MAIN_PART_DEV)
+ printf(" mci-main-partition");
+ if (cdev->flags & DEVFS_IS_MBR_PARTITIONED)
+ printf(" mbr-partitioned");
+ if (cdev->flags & DEVFS_IS_GPT_PARTITIONED)
+ printf(" gpt-partitioned");
+ if (cdev->mtd)
+ printf(" mtd");
+ if (cdev->flags & DEVFS_PARTITION_BOOTABLE_ESP)
+ printf(" boot-esp");
+ if (cdev->flags & DEVFS_PARTITION_BOOTABLE_LEGACY)
+ printf(" boot-legacy");
+ printf(" )");
+ }
+ printf("\n");
+
+ nbytes = 0;
+
+ if (cdev->filetype)
+ nbytes += printf("Filetype: %s\t", file_type_to_string(cdev->filetype));
+ if (cdev_is_mbr_partitioned(cdev->master))
+ nbytes += printf("DOS parttype: 0x%02x\t", cdev->dos_partition_type);
+ else if (cdev_is_gpt_partitioned(cdev->master))
+ nbytes += printf("GPT typeuuid: %pUl\t", &cdev->typeuuid);
+ if (*cdev->partuuid || *cdev->diskuuid)
+ nbytes += printf("%sUUID: %s", cdev_is_partition(cdev) ? "PART" : "DISK",
+ cdev_is_partition(cdev) ? cdev->partuuid : cdev->diskuuid);
+
+ if (nbytes)
+ printf("\n");
+
+ np = cdev_of_node(cdev);
+ if (np)
+ printf("DT node: %pOF\n", np);
+}
+EXPORT_SYMBOL(cdev_print);
+
+void stat_print(int dirfd, const char *filename, const struct stat *st)
+{
+ struct block_device *bdev = NULL;
+ struct fs_device *fdev;
+ struct cdev *cdev = NULL;
+ const char *type = NULL, *typeprefix = "";
+ bool is_cdev_link = false;
+ char modestr[11];
+
+ mkmodestr(st->st_mode, modestr);
+
+ switch (st->st_mode & S_IFMT) {
+ case S_IFDIR: type = "directory"; break;
+ case S_IFBLK: type = "block special file"; break;
+ case S_IFCHR: type = "character special file"; break;
+ case S_IFIFO: type = "fifo"; break;
+ case S_IFLNK: type = "symbolic link"; break;
+ case S_IFSOCK: type = "socket"; break;
+ case S_IFREG: type = "regular file"; break;
+ }
+
+ if (st->st_mode & S_IFCHR) {
+ char *path;
+
+ path = canonicalize_path(dirfd, filename);
+ if (path) {
+ const char *devicefile = devpath_to_name(path);
+ struct cdev *lcdev;
+
+ lcdev = lcdev_by_name(devicefile);
+ cdev = cdev_readlink(lcdev);
+ if (cdev != lcdev)
+ is_cdev_link = true;
+ if (cdev)
+ bdev = cdev_get_block_device(cdev);
+
+ free(path);
+ }
+ }
+
+ printf(" File: %s", filename);
+
+ if (S_ISLNK(st->st_mode)) {
+ char realname[PATH_MAX] = {};
+ int ret;
+
+ ret = readlinkat(dirfd, filename, realname, PATH_MAX - 1);
+ if (ret)
+ printf(" -> <readlink error %pe>", ERR_PTR(ret));
+ else
+ printf(" -> %s", realname);
+ } else if (is_cdev_link) {
+ printf(" ~> %s", cdev->name);
+ typeprefix = "cdev link to ";
+ }
+
+ printf("\n");
+
+ printf(" Size: %-20llu", st->st_size);
+ if (bdev)
+ printf("Blocks: %llu\tIO Block: %u\t",
+ (u64)bdev->num_blocks, 1 << bdev->blockbits);
+
+ if (type)
+ printf(" %s%s", typeprefix, type);
+
+ fdev = get_fsdevice_by_path(dirfd, filename);
+
+ printf("\nDevice: %s\tInode: %lu\n",
+ fdev ? dev_name(&fdev->dev) : "<unknown>",
+ st->st_ino);
+ printf("Access: (%04o/%s)\tUid: (%u)\tGid: (%u)\n",
+ st->st_mode & 07777, modestr, st->st_uid, st->st_gid);
+
+ if (cdev)
+ cdev_print(cdev);
+}
+EXPORT_SYMBOL(stat_print);
+
static char *cwd;
static struct dentry *cwd_dentry;
static struct vfsmount *cwd_mnt;
@@ -74,6 +219,8 @@ static FILE *files;
static struct dentry *d_root;
static struct vfsmount *mnt_root;
+static struct fs_driver *ramfs_driver;
+
static int init_fs(void)
{
cwd = xzalloc(PATH_MAX);
@@ -86,7 +233,12 @@ static int init_fs(void)
postcore_initcall(init_fs);
-static struct fs_device_d *get_fsdevice_by_path(const char *path);
+struct filename;
+
+static int filename_lookup(int dirfd, struct filename *name, unsigned flags,
+ struct path *path);;
+static struct filename *getname(const char *filename);
+static void path_put(const struct path *path);
LIST_HEAD(fs_device_list);
@@ -110,7 +262,7 @@ static void mntput(struct vfsmount *mnt)
static struct vfsmount *lookup_mnt(struct path *path)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
for_each_fs_device(fsdev) {
if (path->dentry == fsdev->vfsmount.mountpoint) {
@@ -128,18 +280,22 @@ static struct vfsmount *lookup_mnt(struct path *path)
*/
struct cdev *get_cdev_by_mountpath(const char *path)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
- fsdev = get_fsdevice_by_path(path);
+ fsdev = get_fsdevice_by_path(AT_FDCWD, path);
+ if (!fsdev)
+ return NULL;
return fsdev->cdev;
}
char *get_mounted_path(const char *path)
{
- struct fs_device_d *fdev;
+ struct fs_device *fdev;
- fdev = get_fsdevice_by_path(path);
+ fdev = get_fsdevice_by_path(AT_FDCWD, path);
+ if (!fdev)
+ return NULL;
return fdev->path;
}
@@ -168,12 +324,16 @@ static void put_file(FILE *f)
dput(f->dentry);
}
-static FILE *fd_to_file(int fd)
+static FILE *fd_to_file(int fd, bool o_path_ok)
{
if (fd < 0 || fd >= MAX_FILES || !files[fd].in_use) {
errno = EBADF;
return ERR_PTR(-errno);
}
+ if (!o_path_ok && (files[fd].flags & O_PATH)) {
+ errno = EINVAL;
+ return ERR_PTR(-errno);
+ }
return &files[fd];
}
@@ -193,16 +353,16 @@ static int create(struct dentry *dir, struct dentry *dentry)
return inode->i_op->create(inode, dentry, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
}
-int creat(const char *pathname, mode_t mode)
+static int fsdev_truncate(struct device *dev, FILE *f, loff_t length)
{
- return open(pathname, O_CREAT | O_WRONLY | O_TRUNC);
+ struct fs_driver *fsdrv = f->fsdev->driver;
+
+ return fsdrv->truncate ? fsdrv->truncate(dev, f, length) : -EROFS;
}
-EXPORT_SYMBOL(creat);
int ftruncate(int fd, loff_t length)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -211,13 +371,9 @@ int ftruncate(int fd, loff_t length)
if (f->size == FILE_SIZE_STREAM)
return 0;
- fsdrv = f->fsdev->driver;
-
- ret = fsdrv->truncate(&f->fsdev->dev, f, length);
- if (ret) {
- errno = -ret;
- return ret;
- }
+ ret = fsdev_truncate(&f->fsdev->dev, f, length);
+ if (ret)
+ return errno_set(ret);
f->size = length;
f->f_inode->i_size = f->size;
@@ -227,8 +383,8 @@ int ftruncate(int fd, loff_t length)
int ioctl(int fd, int request, void *buf)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -240,14 +396,13 @@ int ioctl(int fd, int request, void *buf)
ret = fsdrv->ioctl(&f->fsdev->dev, f, request, buf);
else
ret = -ENOSYS;
- if (ret)
- errno = -ret;
- return ret;
+
+ return errno_set(ret);
}
static ssize_t __read(FILE *f, void *buf, size_t count)
{
- struct fs_driver_d *fsdrv;
+ struct fs_driver *fsdrv;
int ret;
if ((f->flags & O_ACCMODE) == O_WRONLY) {
@@ -257,6 +412,9 @@ static ssize_t __read(FILE *f, void *buf, size_t count)
fsdrv = f->fsdev->driver;
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size)
count = f->size - f->pos;
@@ -265,15 +423,13 @@ static ssize_t __read(FILE *f, void *buf, size_t count)
ret = fsdrv->read(&f->fsdev->dev, f, buf, count);
out:
- if (ret < 0)
- errno = -ret;
- return ret;
+ return errno_set(ret);
}
ssize_t pread(int fd, void *buf, size_t count, loff_t offset)
{
loff_t pos;
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -290,7 +446,7 @@ EXPORT_SYMBOL(pread);
ssize_t read(int fd, void *buf, size_t count)
{
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -306,18 +462,24 @@ EXPORT_SYMBOL(read);
static ssize_t __write(FILE *f, const void *buf, size_t count)
{
- struct fs_driver_d *fsdrv;
+ struct fs_driver *fsdrv;
int ret;
- if (!(f->flags & O_ACCMODE)) {
+ fsdrv = f->fsdev->driver;
+
+ if ((f->flags & O_ACCMODE) == O_RDONLY || !fsdrv->write) {
ret = -EBADF;
goto out;
}
- fsdrv = f->fsdev->driver;
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) {
- ret = fsdrv->truncate(&f->fsdev->dev, f, f->pos + count);
+ ret = fsdev_truncate(&f->fsdev->dev, f, f->pos + count);
if (ret) {
+ if (ret == -EPERM)
+ ret = -ENOSPC;
if (ret != -ENOSPC)
goto out;
count = f->size - f->pos;
@@ -330,15 +492,13 @@ static ssize_t __write(FILE *f, const void *buf, size_t count)
}
ret = fsdrv->write(&f->fsdev->dev, f, buf, count);
out:
- if (ret < 0)
- errno = -ret;
- return ret;
+ return errno_set(ret);
}
ssize_t pwrite(int fd, const void *buf, size_t count, loff_t offset)
{
loff_t pos;
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -355,7 +515,7 @@ EXPORT_SYMBOL(pwrite);
ssize_t write(int fd, const void *buf, size_t count)
{
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -371,8 +531,8 @@ EXPORT_SYMBOL(write);
int flush(int fd)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -384,16 +544,13 @@ int flush(int fd)
else
ret = 0;
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
loff_t lseek(int fd, loff_t offset, int whence)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
loff_t pos;
int ret;
@@ -402,6 +559,9 @@ loff_t lseek(int fd, loff_t offset, int whence)
fsdrv = f->fsdev->driver;
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
ret = -EINVAL;
switch (whence) {
@@ -434,8 +594,7 @@ loff_t lseek(int fd, loff_t offset, int whence)
return pos;
out:
- if (ret)
- errno = -ret;
+ errno_set(ret);
return -1;
}
@@ -443,8 +602,8 @@ EXPORT_SYMBOL(lseek);
int erase(int fd, loff_t count, loff_t offset)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -457,22 +616,23 @@ int erase(int fd, loff_t count, loff_t offset)
return -EINVAL;
fsdrv = f->fsdev->driver;
+
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (fsdrv->erase)
ret = fsdrv->erase(&f->fsdev->dev, f, count, offset);
else
ret = -ENOSYS;
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
EXPORT_SYMBOL(erase);
int protect(int fd, size_t count, loff_t offset, int prot)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -483,22 +643,23 @@ int protect(int fd, size_t count, loff_t offset, int prot)
count = f->size - offset;
fsdrv = f->fsdev->driver;
+
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (fsdrv->protect)
ret = fsdrv->protect(&f->fsdev->dev, f, count, offset, prot);
else
ret = -ENOSYS;
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
EXPORT_SYMBOL(protect);
int discard_range(int fd, loff_t count, loff_t offset)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
int ret;
if (IS_ERR(f))
@@ -509,15 +670,16 @@ int discard_range(int fd, loff_t count, loff_t offset)
count = f->size - offset;
fsdrv = f->fsdev->driver;
+
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (fsdrv->discard_range)
ret = fsdrv->discard_range(&f->fsdev->dev, f, count, offset);
else
ret = -ENOSYS;
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
int protect_file(const char *file, int prot)
@@ -537,8 +699,8 @@ int protect_file(const char *file, int prot)
void *memmap(int fd, int flags)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ struct fs_driver *fsdrv;
+ FILE *f = fd_to_file(fd, false);
void *retp = MAP_FAILED;
int ret;
@@ -547,51 +709,55 @@ void *memmap(int fd, int flags)
fsdrv = f->fsdev->driver;
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
+
if (fsdrv->memmap)
ret = fsdrv->memmap(&f->fsdev->dev, f, &retp, flags);
else
ret = -EINVAL;
- if (ret)
- errno = -ret;
-
+ errno_set(ret);
return retp;
}
EXPORT_SYMBOL(memmap);
int close(int fd)
{
- struct fs_driver_d *fsdrv;
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, true);
int ret = 0;
if (IS_ERR(f))
return -errno;
- fsdrv = f->fsdev->driver;
+ if (!(f->flags & O_PATH)) {
+ struct fs_driver *fsdrv;
- if (fsdrv->close)
- ret = fsdrv->close(&f->fsdev->dev, f);
+ fsdrv = f->fsdev->driver;
- put_file(f);
+ if (fsdrv != ramfs_driver)
+ assert_command_context();
- if (ret)
- errno = -ret;
+ if (fsdrv->close)
+ ret = fsdrv->close(&f->fsdev->dev, f);
+ }
- return ret;
+ put_file(f);
+
+ return errno_set(ret);
}
EXPORT_SYMBOL(close);
-static int fs_match(struct device_d *dev, struct driver_d *drv)
+static int fs_match(struct device *dev, struct driver *drv)
{
return strcmp(dev->name, drv->name) ? -1 : 0;
}
-static int fs_probe(struct device_d *dev)
+static int fs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
- struct driver_d *drv = dev->driver;
- struct fs_driver_d *fsdrv = container_of(drv, struct fs_driver_d, drv);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
+ struct driver *drv = dev->driver;
+ struct fs_driver *fsdrv = container_of(drv, struct fs_driver, drv);
int ret;
ret = dev->driver->probe(dev);
@@ -647,11 +813,13 @@ static void destroy_inode(struct inode *inode)
free(inode);
}
-static void fs_remove(struct device_d *dev)
+static void fs_remove(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct super_block *sb = &fsdev->sb;
struct inode *inode, *tmp;
+ struct path path;
+ int ret;
if (fsdev->dev.driver) {
dev->driver->remove(dev);
@@ -664,22 +832,28 @@ static void fs_remove(struct device_d *dev)
if (fsdev->cdev)
cdev_close(fsdev->cdev);
- if (fsdev->loop && fsdev->cdev)
+ if (fsdev->loop && fsdev->cdev) {
cdev_remove_loop(fsdev->cdev);
- dput(sb->s_root);
+ ret = filename_lookup(AT_FDCWD, getname(fsdev->backingstore),
+ LOOKUP_FOLLOW, &path);
+ if (!ret) {
+ mntput(path.mnt);
+ path_put(&path);
+ }
+ }
+
+ if (fsdev->vfsmount.mountpoint)
+ fsdev->vfsmount.mountpoint->d_flags &= ~DCACHE_MOUNTED;
+
dentry_delete_subtree(sb, sb->s_root);
list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list)
destroy_inode(inode);
- if (fsdev->vfsmount.mountpoint)
- fsdev->vfsmount.mountpoint->d_flags &= ~DCACHE_MOUNTED;
-
mntput(fsdev->vfsmount.parent);
free(fsdev->backingstore);
- free(fsdev);
}
struct bus_type fs_bus = {
@@ -695,31 +869,43 @@ static int fs_bus_init(void)
}
pure_initcall(fs_bus_init);
-int register_fs_driver(struct fs_driver_d *fsdrv)
+int register_fs_driver(struct fs_driver *fsdrv)
{
fsdrv->drv.bus = &fs_bus;
register_driver(&fsdrv->drv);
+ if (!strcmp(fsdrv->drv.name, "ramfs"))
+ ramfs_driver = fsdrv;
+
return 0;
}
EXPORT_SYMBOL(register_fs_driver);
-static const char *detect_fs(const char *filename, const char *fsoptions)
+const char *fs_detect(const char *filename, const char *fsoptions)
{
enum filetype type;
- struct driver_d *drv;
- struct fs_driver_d *fdrv;
+ struct driver *drv;
+ struct fs_driver *fdrv;
bool loop = false;
unsigned long long offset = 0;
+ int ret;
parseopt_b(fsoptions, "loop", &loop);
parseopt_llu_suffix(fsoptions, "offset", &offset);
- if (loop)
- type = file_name_detect_type_offset(filename, offset);
- else
- type = cdev_detect_type(filename);
- if (type == filetype_unknown)
+ if (loop) {
+ ret = file_name_detect_type_offset(filename, offset, &type);
+ } else {
+ struct cdev *cdev = cdev_open_by_name(filename, O_RDONLY);
+ if (cdev) {
+ ret = cdev_detect_type(cdev, &type);
+ cdev_close(cdev);
+ } else {
+ ret = -ENOENT;
+ }
+ }
+
+ if (ret || type == filetype_unknown)
return NULL;
bus_for_each_driver(&fs_bus, drv) {
@@ -732,22 +918,35 @@ static const char *detect_fs(const char *filename, const char *fsoptions)
return NULL;
}
-int fsdev_open_cdev(struct fs_device_d *fsdev)
+int fsdev_open_cdev(struct fs_device *fsdev)
{
unsigned long long offset = 0;
+ struct path path = {};
+ int ret;
parseopt_b(fsdev->options, "loop", &fsdev->loop);
parseopt_llu_suffix(fsdev->options, "offset", &offset);
- if (fsdev->loop)
- fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR,
- offset);
- else
- fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR);
- if (!fsdev->cdev)
+ if (fsdev->loop) {
+ ret = filename_lookup(AT_FDCWD, getname(fsdev->backingstore),
+ LOOKUP_FOLLOW, &path);
+ if (ret)
+ return ret;
+
+ fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR, offset);
+ } else {
+ fsdev->cdev = cdev_open_by_name(fsdev->backingstore, O_RDWR);
+ }
+ if (!fsdev->cdev) {
+ path_put(&path);
return -EINVAL;
+ }
+
+ if (path.mnt) {
+ mntget(path.mnt);
+ path_put(&path);
+ }
fsdev->dev.parent = fsdev->cdev->dev;
- fsdev->parent_device = fsdev->cdev->dev;
return 0;
}
@@ -757,12 +956,20 @@ static void init_super(struct super_block *sb)
INIT_LIST_HEAD(&sb->s_inodes);
}
-static int fsdev_umount(struct fs_device_d *fsdev)
+static int fsdev_umount(struct fs_device *fsdev)
{
+ int ret;
+
if (fsdev->vfsmount.ref)
return -EBUSY;
- return unregister_device(&fsdev->dev);
+ ret = unregister_device(&fsdev->dev);
+ if (ret)
+ return ret;
+
+ free(fsdev);
+
+ return 0;
}
/**
@@ -772,8 +979,8 @@ static int fsdev_umount(struct fs_device_d *fsdev)
*/
int umount_by_cdev(struct cdev *cdev)
{
- struct fs_device_d *fs;
- struct fs_device_d *fs_tmp;
+ struct fs_device *fs;
+ struct fs_device *fs_tmp;
int first_error = 0;
for_each_fs_device_safe(fs_tmp, fs) {
@@ -817,6 +1024,21 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
return 0;
}
+int unreaddir(DIR *dir, const struct dirent *d)
+{
+ struct readdir_entry *entry;
+
+ if (d != &dir->d)
+ return -EINVAL;
+
+ entry = xzalloc(sizeof(*entry));
+ entry->d = *d;
+ list_add(&entry->list, &dir->entries);
+
+ return 0;
+}
+EXPORT_SYMBOL(unreaddir);
+
struct dirent *readdir(DIR *dir)
{
struct readdir_entry *entry;
@@ -839,7 +1061,6 @@ EXPORT_SYMBOL(readdir);
static void stat_inode(struct inode *inode, struct stat *s)
{
- s->st_dev = 0;
s->st_ino = inode->i_ino;
s->st_mode = inode->i_mode;
s->st_uid = inode->i_uid;
@@ -849,7 +1070,7 @@ static void stat_inode(struct inode *inode, struct stat *s)
int fstat(int fd, struct stat *s)
{
- FILE *f = fd_to_file(fd);
+ FILE *f = fd_to_file(fd, true);
if (IS_ERR(f))
return -errno;
@@ -868,7 +1089,7 @@ EXPORT_SYMBOL(fstat);
*/
const char *cdev_get_mount_path(struct cdev *cdev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
for_each_fs_device(fsdev) {
if (fsdev->cdev && fsdev->cdev == cdev)
@@ -881,9 +1102,10 @@ const char *cdev_get_mount_path(struct cdev *cdev)
/*
* cdev_mount_default - mount a cdev to the default path
*
- * If a cdev is already mounted return the path it's mounted on, otherwise
- * mount it to /mnt/<cdevname> and return the path. Returns an error pointer
- * on failure.
+ * If a cdev is already mounted to the default mount path return the path
+ * it's mounted on. If it is mounted to any other path return EBUSY.
+ * Otherwise mount it to /mnt/<cdevname> and return the path. Returns an
+ * error pointer on failure.
*/
const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
{
@@ -892,15 +1114,24 @@ const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
int ret;
/*
- * If this cdev is already mounted somewhere use this path
- * instead of mounting it again to avoid corruption on the
- * filesystem. Note this ignores eventual fsoptions though.
+ * If this cdev is already mounted somewhere other than the
+ * default mount path return -EBUSY instead of mounting it
+ * again to avoid corruption on the filesystem. Note this
+ * ignores eventual fsoptions though. If the cdev is already
+ * mounted on the default path just return that path.
*/
path = cdev_get_mount_path(cdev);
- if (path)
- return path;
-
newpath = basprintf("/mnt/%s", cdev->name);
+
+ if (path) {
+ if (strcmp(newpath, path)) {
+ free(newpath);
+ return ERR_PTR(-EBUSY);
+ } else {
+ return path;
+ }
+ }
+
make_directory(newpath);
devpath = basprintf("/dev/%s", cdev->name);
@@ -918,11 +1149,30 @@ const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
}
/*
+ * cdev_mount - return existing mount or mount a cdev to the default path
+ *
+ * If a cdev is already mounted anywhere return the path
+ * it's mounted on.
+ * Otherwise mount it to /mnt/<cdevname> and return the path. Returns an
+ * error pointer on failure.
+ */
+const char *cdev_mount(struct cdev *cdev)
+{
+ const char *path;
+
+ path = cdev_get_mount_path(cdev);
+ if (path)
+ return path;
+
+ return cdev_mount_default(cdev, NULL);
+}
+
+/*
* mount_all - iterate over block devices and mount all devices we are able to
*/
void mount_all(void)
{
- struct device_d *dev;
+ struct device *dev;
struct block_device *bdev;
if (!IS_ENABLED(CONFIG_BLOCK))
@@ -932,14 +1182,14 @@ void mount_all(void)
device_detect(dev);
for_each_block_device(bdev) {
- struct cdev *cdev = &bdev->cdev;
+ struct cdev *cdev;
list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list)
cdev_mount_default(cdev, NULL);
}
}
-void fsdev_set_linux_rootarg(struct fs_device_d *fsdev, const char *str)
+void fsdev_set_linux_rootarg(struct fs_device *fsdev, const char *str)
{
fsdev->linux_rootarg = xstrdup(str);
@@ -956,10 +1206,10 @@ void fsdev_set_linux_rootarg(struct fs_device_d *fsdev, const char *str)
*/
char *path_get_linux_rootarg(const char *path)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
const char *str;
- fsdev = get_fsdevice_by_path(path);
+ fsdev = get_fsdevice_by_path(AT_FDCWD, path);
if (!fsdev)
return ERR_PTR(-EINVAL);
@@ -980,9 +1230,9 @@ char *path_get_linux_rootarg(const char *path)
*/
bool __is_tftp_fs(const char *path)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
- fsdev = get_fsdevice_by_path(path);
+ fsdev = get_fsdevice_by_path(AT_FDCWD, path);
if (!fsdev)
return false;
@@ -1261,7 +1511,6 @@ void d_add(struct dentry *dentry, struct inode *inode)
}
static bool d_same_name(const struct dentry *dentry,
- const struct dentry *parent,
const struct qstr *name)
{
if (dentry->d_name.len != name->len)
@@ -1270,17 +1519,16 @@ static bool d_same_name(const struct dentry *dentry,
return strncmp(dentry->d_name.name, name->name, name->len) == 0;
}
-static struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
+static struct dentry *d_lookup(struct dentry *parent, const struct qstr *name)
{
struct dentry *dentry;
- list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
- if (!d_same_name(dentry, parent, name))
- continue;
-
- dget(dentry);
+ if (d_same_name(parent, name))
+ return dget(parent);
- return dentry;
+ list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
+ if (d_same_name(dentry, name))
+ return dget(dentry);
}
return NULL;
@@ -1370,22 +1618,17 @@ enum {WALK_FOLLOW = 1, WALK_MORE = 2};
struct nameidata {
struct path path;
struct qstr last;
- struct inode *inode; /* path.dentry.d_inode */
unsigned int flags;
- unsigned seq, m_seq;
int last_type;
unsigned depth;
int total_link_count;
struct saved {
struct path link;
const char *name;
- unsigned seq;
} *stack, internal[EMBEDDED_LEVELS];
struct filename *name;
- struct nameidata *saved;
struct inode *link_inode;
- unsigned root_seq;
- int dfd;
+ struct dentry *d_root;
};
struct filename {
@@ -1393,12 +1636,13 @@ struct filename {
int refcnt;
};
-static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
+static void set_nameidata(struct nameidata *p, struct filename *name)
{
+ p->last = slash_name;
p->stack = p->internal;
- p->dfd = dfd;
p->name = name;
p->total_link_count = 0;
+ p->d_root = d_root;
}
static void path_get(const struct path *path)
@@ -1423,11 +1667,6 @@ static inline void get_root(struct path *root)
static inline void get_pwd(struct path *pwd)
{
- if (!cwd_dentry) {
- cwd_dentry = d_root;
- cwd_mnt = mnt_root;
- }
-
pwd->dentry = cwd_dentry;
pwd->mnt = cwd_mnt;
@@ -1463,9 +1702,7 @@ static int follow_automount(struct path *path, struct nameidata *nd,
* as being automount points. These will need the attentions
* of the daemon to instantiate them before they can be used.
*/
- if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
- LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
- path->dentry->d_inode)
+ if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && path->dentry->d_inode)
return -EISDIR;
return automount_mount(path->dentry);
@@ -1591,16 +1828,16 @@ static int lookup_fast(struct nameidata *nd, struct path *path)
* Return 1 if we went up a level and 0 if we were already at the
* root.
*/
-static int follow_up(struct path *path)
+static int follow_up(struct nameidata *nd)
{
- struct vfsmount *parent, *mnt = path->mnt;
+ struct path *path = &nd->path;
+ struct vfsmount *mnt = path->mnt;
struct dentry *mountpoint;
- parent = mnt->parent;
- if (parent == mnt)
+ if (nd->d_root == path->dentry)
return 0;
- mntget(parent);
+ mntget(mnt->parent);
mountpoint = dget(mnt->mountpoint);
dput(path->dentry);
path->dentry = mountpoint;
@@ -1642,14 +1879,12 @@ static int follow_dotdot(struct nameidata *nd)
break;
}
- if (!follow_up(&nd->path))
+ if (!follow_up(nd))
break;
}
follow_mount(&nd->path);
- nd->inode = nd->path.dentry->d_inode;
-
return 0;
}
@@ -1730,7 +1965,6 @@ static inline int step_into(struct nameidata *nd, struct path *path,
!(flags & WALK_FOLLOW || nd->flags & LOOKUP_FOLLOW)) {
/* not a symlink or should not follow */
path_to_nameidata(path, nd);
- nd->inode = inode;
return 0;
}
@@ -1739,7 +1973,7 @@ static inline int step_into(struct nameidata *nd, struct path *path,
static int walk_component(struct nameidata *nd, int flags)
{
- struct path path;
+ struct path path = {};
int err;
/*
@@ -1758,16 +1992,9 @@ static int walk_component(struct nameidata *nd, int flags)
if (err < 0)
return err;
- if (err == 0) {
- path.mnt = nd->path.mnt;
- err = follow_managed(&path, nd);
- if (err < 0)
- return err;
-
- if (d_is_negative(path.dentry)) {
- path_to_nameidata(&path, nd);
- return -ENOENT;
- }
+ if (err == 0 && d_is_negative(path.dentry)) {
+ path_to_nameidata(&path, nd);
+ return -ENOENT;
}
return step_into(nd, &path, flags, d_inode(path.dentry));
@@ -1787,14 +2014,17 @@ static struct filename *getname(const char *filename)
{
struct filename *result;
+ if (!*filename)
+ return ERR_PTR(-ENOENT);
+
result = malloc(sizeof(*result));
if (!result)
- return NULL;
+ return ERR_PTR(-ENOMEM);
result->name = strdup(filename);
if (!result->name) {
free(result);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
result->refcnt = 1;
@@ -1813,18 +2043,18 @@ static void putname(struct filename *name)
free(name);
}
-static struct fs_device_d *get_fsdevice_by_dentry(struct dentry *dentry)
+static struct fs_device *get_fsdevice_by_dentry(struct dentry *dentry)
{
struct super_block *sb;
sb = dentry->d_sb;
- return container_of(sb, struct fs_device_d, sb);
+ return container_of(sb, struct fs_device, sb);
}
static bool dentry_is_tftp(struct dentry *dentry)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
fsdev = get_fsdevice_by_dentry(dentry);
if (!fsdev)
@@ -1849,6 +2079,8 @@ static int link_path_walk(const char *name, struct nameidata *nd)
int err;
char separator = '/';
+ if (!*name)
+ return -ENOENT;
while (*name=='/')
name++;
if (!*name)
@@ -1940,9 +2172,18 @@ OK:
}
}
-static const char *path_init(struct nameidata *nd, unsigned flags)
+static bool file_has_flag(FILE *f, unsigned flag)
+{
+ if (IS_ERR_OR_NULL(f))
+ return false;
+ return (f->flags & flag) == flag;
+}
+
+static const char *path_init(int dirfd, struct nameidata *nd, unsigned flags)
{
const char *s = nd->name->name;
+ bool chroot = false;
+ FILE *f = NULL;
nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
@@ -1951,13 +2192,30 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
nd->path.mnt = NULL;
nd->path.dentry = NULL;
- if (*s == '/') {
+ /* We don't check for error here yet, as POSIX allows checking
+ * whether paths are absolute with openat(-1, path, O_PATH)
+ */
+ if (dirfd != AT_FDCWD) {
+ f = fd_to_file(dirfd, true);
+ chroot = file_has_flag(f, O_CHROOT);
+ }
+
+ if (*s == '/' && !chroot) {
get_root(&nd->path);
- return s;
- } else if (nd->dfd == AT_FDCWD) {
+ } else if (dirfd == AT_FDCWD) {
get_pwd(&nd->path);
- nd->inode = nd->path.dentry->d_inode;
- return s;
+ } else {
+ if (IS_ERR(f))
+ return ERR_CAST(f);
+
+ nd->path.mnt = &f->fsdev->vfsmount;
+ nd->path.dentry = f->dentry;
+ follow_mount(&nd->path);
+
+ if (*s == '/')
+ nd->path.dentry = nd->path.mnt->mnt_root;
+ if (chroot)
+ nd->d_root = nd->path.mnt->mnt_root;
}
return s;
@@ -1995,10 +2253,10 @@ static void terminate_walk(struct nameidata *nd)
}
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-static int path_parentat(struct nameidata *nd, unsigned flags,
+static int path_parentat(int dirfd, struct nameidata *nd, unsigned flags,
struct path *parent)
{
- const char *s = path_init(nd, flags);
+ const char *s = path_init(dirfd, nd, flags);
int err;
if (IS_ERR(s))
@@ -2014,7 +2272,8 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
return err;
}
-static struct filename *filename_parentat(int dfd, struct filename *name,
+static struct filename *filename_parentat(int dirfd,
+ struct filename *name,
unsigned int flags, struct path *parent,
struct qstr *last, int *type)
{
@@ -2024,9 +2283,9 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
if (IS_ERR(name))
return name;
- set_nameidata(&nd, dfd, name);
+ set_nameidata(&nd, name);
- retval = path_parentat(&nd, flags, parent);
+ retval = path_parentat(dirfd, &nd, flags, parent);
if (likely(!retval)) {
*last = nd.last;
*type = nd.last_type;
@@ -2038,7 +2297,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
return name;
}
-static struct dentry *filename_create(int dfd, struct filename *name,
+static struct dentry *filename_create(int dirfd, struct filename *name,
struct path *path, unsigned int lookup_flags)
{
struct dentry *dentry = ERR_PTR(-EEXIST);
@@ -2047,13 +2306,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
int error;
bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
- /*
- * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
- * other flags passed in are ignored!
- */
- lookup_flags &= LOOKUP_REVAL;
-
- name = filename_parentat(dfd, name, 0, path, &last, &type);
+ name = filename_parentat(dirfd, name, 0, path, &last, &type);
if (IS_ERR(name))
return ERR_CAST(name);
@@ -2067,7 +2320,6 @@ static struct dentry *filename_create(int dfd, struct filename *name,
/*
* Do the final lookup.
*/
- lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
dentry = __lookup_hash(&last, path->dentry, lookup_flags);
if (IS_ERR(dentry))
goto unlock;
@@ -2098,16 +2350,21 @@ out:
return dentry;
}
-static int filename_lookup(int dfd, struct filename *name, unsigned flags,
+static int filename_lookup(int dirfd, struct filename *name, unsigned flags,
struct path *path)
{
int err;
struct nameidata nd;
const char *s;
- set_nameidata(&nd, dfd, name);
+ if (IS_ERR(name))
+ return PTR_ERR(name);
+
+ set_nameidata(&nd, name);
- s = path_init(&nd, flags);
+ s = path_init(dirfd, &nd, flags);
+ if (IS_ERR(s))
+ return PTR_ERR(s);
while (!(err = link_path_walk(s, &nd)) && ((err = lookup_last(&nd)) > 0)) {
s = trailing_symlink(&nd);
@@ -2132,13 +2389,13 @@ static int filename_lookup(int dfd, struct filename *name, unsigned flags,
return err;
}
-static struct fs_device_d *get_fsdevice_by_path(const char *pathname)
+struct fs_device *get_fsdevice_by_path(int dirfd, const char *pathname)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
struct path path;
int ret;
- ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
+ ret = filename_lookup(dirfd, getname(pathname), 0, &path);
if (ret)
return NULL;
@@ -2190,14 +2447,14 @@ static int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
/* libfs.c */
/* ---------------------------------------------------------------- */
-int mkdir (const char *pathname, mode_t mode)
+int mkdirat(int dirfd, const char *pathname, mode_t mode)
{
struct dentry *dentry;
struct path path;
int error;
unsigned int lookup_flags = LOOKUP_DIRECTORY;
- dentry = filename_create(AT_FDCWD, getname(pathname), &path, lookup_flags);
+ dentry = filename_create(dirfd, getname(pathname), &path, lookup_flags);
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
goto out;
@@ -2208,14 +2465,11 @@ int mkdir (const char *pathname, mode_t mode)
dput(dentry);
path_put(&path);
out:
- if (error)
- errno = -error;
-
- return error;
+ return errno_set(error);
}
-EXPORT_SYMBOL(mkdir);
+EXPORT_SYMBOL(mkdirat);
-int rmdir (const char *pathname)
+static int rmdirat(int dirfd, const char *pathname)
{
int error = 0;
struct filename *name;
@@ -2224,7 +2478,7 @@ int rmdir (const char *pathname)
struct qstr last;
int type;
- name = filename_parentat(AT_FDCWD, getname(pathname), 0,
+ name = filename_parentat(dirfd, getname(pathname), 0,
&path, &last, &type);
if (IS_ERR(name))
return PTR_ERR(name);
@@ -2263,17 +2517,13 @@ out:
path_put(&path);
putname(name);
- if (error)
- errno = -error;
-
- return error;
+ return errno_set(error);
}
-EXPORT_SYMBOL(rmdir);
-int open(const char *pathname, int flags, ...)
+int openat(int dirfd, const char *pathname, int flags)
{
- struct fs_device_d *fsdev;
- struct fs_driver_d *fsdrv;
+ struct fs_device *fsdev;
+ struct fs_driver *fsdrv;
struct super_block *sb;
FILE *f;
int error = 0;
@@ -2281,9 +2531,46 @@ int open(const char *pathname, int flags, ...)
struct dentry *dentry = NULL;
struct nameidata nd;
const char *s;
+ struct filename *filename;
- set_nameidata(&nd, AT_FDCWD, getname(pathname));
- s = path_init(&nd, LOOKUP_FOLLOW);
+ if (flags & O_TMPFILE) {
+ fsdev = get_fsdevice_by_path(dirfd, pathname);
+ if (!fsdev) {
+ errno = ENOENT;
+ return -errno;
+ }
+
+ if (fsdev->driver != ramfs_driver) {
+ errno = EOPNOTSUPP;
+ return -errno;
+ }
+
+ f = get_file();
+ if (!f) {
+ errno = EMFILE;
+ return -errno;
+ }
+
+ f->path = NULL;
+ f->dentry = NULL;
+ f->f_inode = new_inode(&fsdev->sb);
+ f->f_inode->i_mode = S_IFREG;
+ f->flags = flags;
+ f->size = 0;
+ f->fsdev = fsdev;
+
+ return f->no;
+ }
+
+ filename = getname(pathname);
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
+
+ set_nameidata(&nd, filename);
+
+ s = path_init(dirfd, &nd, LOOKUP_FOLLOW);
+ if (IS_ERR(s))
+ return PTR_ERR(s);
while (1) {
error = link_path_walk(s, &nd);
@@ -2333,7 +2620,7 @@ int open(const char *pathname, int flags, ...)
error = -ENOENT;
goto out1;
}
- } else {
+ } else if (!(flags & O_PATH)) {
if (d_is_dir(dentry) && !dentry_is_tftp(dentry)) {
error = -EISDIR;
goto out1;
@@ -2348,18 +2635,21 @@ int open(const char *pathname, int flags, ...)
goto out1;
}
- f->path = xstrdup(pathname);
+ f->path = dpath(dentry, d_root);
f->dentry = dentry;
f->f_inode = iget(inode);
f->flags = flags;
f->size = inode->i_size;
sb = inode->i_sb;
- fsdev = container_of(sb, struct fs_device_d, sb);
+ fsdev = container_of(sb, struct fs_device, sb);
fsdrv = fsdev->driver;
f->fsdev = fsdev;
+ if (flags & O_PATH)
+ return f->no;
+
if (fsdrv->open) {
char *pathname = dpath(dentry, fsdev->vfsmount.mnt_root);
@@ -2370,7 +2660,7 @@ int open(const char *pathname, int flags, ...)
}
if (flags & O_TRUNC) {
- error = fsdrv->truncate(&fsdev->dev, f, 0);
+ error = fsdev_truncate(&fsdev->dev, f, 0);
f->size = 0;
inode->i_size = 0;
if (error)
@@ -2385,21 +2675,37 @@ int open(const char *pathname, int flags, ...)
out:
put_file(f);
out1:
+ return errno_set(error);
+}
+EXPORT_SYMBOL(openat);
- if (error)
- errno = -error;
- return error;
+static const char *fd_getpath(int fd)
+{
+ FILE *f;
+
+ if (fd < 0)
+ return ERR_PTR(errno_set(fd));
+
+ f = fd_to_file(fd, true);
+ if (IS_ERR(f))
+ return ERR_CAST(f);
+
+ return f->path;
}
-EXPORT_SYMBOL(open);
-int unlink(const char *pathname)
+int unlinkat(int dirfd, const char *pathname, int flags)
{
int ret;
struct dentry *dentry;
struct inode *inode;
struct path path;
- ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
+ if (flags == AT_REMOVEDIR)
+ return rmdirat(dirfd, pathname);
+ if (flags)
+ return -EINVAL;
+
+ ret = filename_lookup(dirfd, getname(pathname), 0, &path);
if (ret)
goto out;
@@ -2426,11 +2732,9 @@ int unlink(const char *pathname)
out_put:
path_put(&path);
out:
- if (ret)
- errno = -ret;
- return ret;
+ return errno_set(ret);
}
-EXPORT_SYMBOL(unlink);
+EXPORT_SYMBOL(unlinkat);
static int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
@@ -2455,38 +2759,55 @@ int symlink(const char *pathname, const char *newpath)
error = vfs_symlink(path.dentry->d_inode, dentry, pathname);
out:
- if (error)
- errno = -error;
-
- return error;
+ return errno_set(error);
}
EXPORT_SYMBOL(symlink);
-static void release_dir(DIR *d)
+static void __release_dir(DIR *d)
{
- struct readdir_entry *entry, *tmp;
+ while (!list_empty(&d->entries)) {
+ struct readdir_entry *entry =
+ list_first_entry(&d->entries, struct readdir_entry, list);
- list_for_each_entry_safe(entry, tmp, &d->entries, list) {
+ list_del(&entry->list);
free(entry);
}
-
- free(d);
}
-DIR *opendir(const char *pathname)
+static int __opendir(DIR *d)
{
int ret;
- struct dentry *dir;
- struct inode *inode;
struct file file = {};
- DIR *d;
- struct path path = {};
+ struct path *path = &d->path;
+ struct dentry *dir = path->dentry;
struct readdir_callback rd = {
.ctx = {
.actor = fillonedir,
},
};
+ file.f_path.dentry = dir;
+ file.f_inode = d_inode(dir);
+ file.f_op = dir->d_inode->i_fop;
+
+ INIT_LIST_HEAD(&d->entries);
+ rd.dir = d;
+
+ ret = file.f_op->iterate(&file, &rd.ctx);
+ if (ret)
+ __release_dir(d);
+
+ return ret;
+}
+
+DIR *opendir(const char *pathname)
+{
+ int ret;
+ struct dentry *dir;
+ struct inode *inode;
+ DIR *d;
+ struct path path = {};
+
ret = filename_lookup(AT_FDCWD, getname(pathname),
LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
if (ret)
@@ -2506,48 +2827,75 @@ DIR *opendir(const char *pathname)
goto out_put;
}
- file.f_path.dentry = dir;
- file.f_inode = d_inode(dir);
- file.f_op = dir->d_inode->i_fop;
-
d = xzalloc(sizeof(*d));
+ d->path = path;
+ d->fd = -ENOENT;
- INIT_LIST_HEAD(&d->entries);
- rd.dir = d;
-
- ret = file.f_op->iterate(&file, &rd.ctx);
+ ret = __opendir(d);
if (ret)
- goto out_release;
-
- path_put(&path);
+ goto out_free;
return d;
-out_release:
- release_dir(d);
+out_free:
+ free(d);
out_put:
path_put(&path);
out:
- errno = -ret;
+ errno_set(ret);
return NULL;
}
EXPORT_SYMBOL(opendir);
+DIR *fdopendir(int fd)
+{
+ const char *path;
+ DIR *dir;
+
+ path = fd_getpath(fd);
+ if (IS_ERR(path))
+ return NULL;
+
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+
+ /* we intentionally don't increment the reference count,
+ * as POSIX specifies that fd ownership is transferred
+ */
+ dir->fd = fd;
+ return dir;
+}
+EXPORT_SYMBOL(fdopendir);
+
int closedir(DIR *dir)
{
- if (!dir) {
- errno = EBADF;
- return -EBADF;
- }
+ if (!dir)
+ return errno_set(-EBADF);
- release_dir(dir);
+ path_put(&dir->path);
+ __release_dir(dir);
+ if (dir->fd >= 0)
+ close(dir->fd);
+ free(dir);
return 0;
}
EXPORT_SYMBOL(closedir);
-int readlink(const char *pathname, char *buf, size_t bufsiz)
+int rewinddir(DIR *dir)
+{
+ if (!dir)
+ return errno_set(-EBADF);
+
+ __release_dir(dir);
+
+ return __opendir(dir);
+}
+EXPORT_SYMBOL(rewinddir);
+
+int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
{
int ret;
struct dentry *dentry;
@@ -2555,7 +2903,7 @@ int readlink(const char *pathname, char *buf, size_t bufsiz)
const char *link;
struct path path = {};
- ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
+ ret = filename_lookup(dirfd, getname(pathname), 0, &path);
if (ret)
goto out;
@@ -2585,21 +2933,18 @@ int readlink(const char *pathname, char *buf, size_t bufsiz)
out_put:
path_put(&path);
out:
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
-EXPORT_SYMBOL(readlink);
+EXPORT_SYMBOL(readlinkat);
-static int stat_filename(const char *filename, struct stat *s, unsigned int flags)
+static int stat_filename(int dirfd, const char *filename, struct stat *s, unsigned int flags)
{
int ret;
struct dentry *dentry;
struct inode *inode;
struct path path = {};
- ret = filename_lookup(AT_FDCWD, getname(filename), flags, &path);
+ ret = filename_lookup(dirfd, getname(filename), flags, &path);
if (ret)
goto out;
@@ -2618,23 +2963,20 @@ static int stat_filename(const char *filename, struct stat *s, unsigned int flag
out_put:
path_put(&path);
out:
- if (ret)
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
-int stat(const char *filename, struct stat *s)
+int statat(int dirfd, const char *filename, struct stat *s)
{
- return stat_filename(filename, s, LOOKUP_FOLLOW);
+ return stat_filename(dirfd, filename, s, LOOKUP_FOLLOW);
}
-EXPORT_SYMBOL(stat);
+EXPORT_SYMBOL(statat);
-int lstat(const char *filename, struct stat *s)
+int lstatat(int dirfd, const char *filename, struct stat *s)
{
- return stat_filename(filename, s, 0);
+ return stat_filename(dirfd, filename, s, 0);
}
-EXPORT_SYMBOL(lstat);
+EXPORT_SYMBOL(lstatat);
static char *__dpath(struct dentry *dentry, struct dentry *root)
{
@@ -2646,7 +2988,7 @@ static char *__dpath(struct dentry *dentry, struct dentry *root)
return NULL;
while (IS_ROOT(dentry)) {
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
for_each_fs_device(fsdev) {
if (dentry == fsdev->vfsmount.mnt_root) {
@@ -2690,6 +3032,8 @@ char *dpath(struct dentry *dentry, struct dentry *root)
/**
* canonicalize_path - resolve links in path
+ *
+ * @dirfd: directory file descriptor to look up relative to
* @pathname: The input path
*
* This function resolves all links in @pathname and returns
@@ -2697,21 +3041,19 @@ char *dpath(struct dentry *dentry, struct dentry *root)
*
* Return: Path with links resolved. Allocated, must be freed after use.
*/
-char *canonicalize_path(const char *pathname)
+char *canonicalize_path(int dirfd, const char *pathname)
{
char *res = NULL;
struct path path;
int ret;
- ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+ ret = filename_lookup(dirfd, getname(pathname), LOOKUP_FOLLOW, &path);
if (ret)
goto out;
res = dpath(path.dentry, d_root);
out:
- if (ret)
- errno = -ret;
-
+ errno_set(ret);
return res;
}
@@ -2745,12 +3087,93 @@ int chdir(const char *pathname)
ret = 0;
out:
- if (ret)
- errno = -ret;
+ return errno_set(ret);
+}
+EXPORT_SYMBOL(chdir);
+
+char *pushd(const char *dir)
+{
+ char *oldcwd;
+ int ret;
+
+ oldcwd = strdup(getcwd());
+ if (!oldcwd)
+ return NULL;
+
+ ret = chdir(dir);
+ if (ret) {
+ free(oldcwd);
+ return NULL;
+ }
+
+ return oldcwd;
+}
+int popd(char *oldcwd)
+{
+ int ret;
+
+ if (!oldcwd)
+ return 0;
+
+ ret = chdir(oldcwd);
+ free(oldcwd);
return ret;
}
-EXPORT_SYMBOL(chdir);
+
+static bool cdev_partname_equal(const struct cdev *a,
+ const struct cdev *b)
+{
+ return a->partname && b->partname &&
+ !strcmp(a->partname, b->partname);
+}
+
+static char *get_linux_mmcblkdev(const struct cdev *root_cdev)
+{
+ struct cdev *cdevm = root_cdev->master, *cdev;
+ int id, partnum;
+
+ if (!IS_ENABLED(CONFIG_MMCBLKDEV_ROOTARG))
+ return NULL;
+ if (!cdevm || !cdev_is_mci_main_part_dev(cdevm))
+ return NULL;
+
+ id = of_alias_get_id(cdev_of_node(cdevm), "mmc");
+ if (id < 0)
+ return NULL;
+
+ partnum = 1; /* linux partitions are 1 based */
+ list_for_each_entry(cdev, &cdevm->partitions, partition_entry) {
+
+ /*
+ * Partname is not guaranteed but this partition cdev is listed
+ * in the partitions list so we need to count it instead of
+ * skipping it.
+ */
+ if (cdev_partname_equal(root_cdev, cdev))
+ return basprintf("root=/dev/mmcblk%dp%d", id, partnum);
+ partnum++;
+ }
+
+ return NULL;
+}
+
+char *cdev_get_linux_rootarg(const struct cdev *cdev)
+{
+ char *str;
+
+ if (!cdev)
+ return NULL;
+
+ str = get_linux_mmcblkdev(cdev);
+ if (str)
+ return str;
+
+ if (cdev->partuuid[0] != 0)
+ return basprintf("root=PARTUUID=%s", cdev->partuuid);
+
+ return NULL;
+}
/*
* Mount a device to a directory.
@@ -2760,7 +3183,7 @@ EXPORT_SYMBOL(chdir);
int mount(const char *device, const char *fsname, const char *pathname,
const char *fsoptions)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
int ret;
struct path path = {};
@@ -2790,14 +3213,14 @@ int mount(const char *device, const char *fsname, const char *pathname,
device, pathname, fsname, fsoptions);
if (!fsname)
- fsname = detect_fs(device, fsoptions);
+ fsname = fs_detect(device, fsoptions);
if (!fsname) {
ret = -ENOENT;
goto out;
}
- fsdev = xzalloc(sizeof(struct fs_device_d));
+ fsdev = xzalloc(sizeof(struct fs_device));
fsdev->backingstore = xstrdup(device);
dev_set_name(&fsdev->dev, fsname);
fsdev->dev.id = get_free_deviceid(fsdev->dev.name);
@@ -2836,15 +3259,19 @@ int mount(const char *device, const char *fsname, const char *pathname,
fsdev->vfsmount.mountpoint = d_root;
fsdev->vfsmount.parent = &fsdev->vfsmount;
fsdev->path = xstrdup("/");
+
+ cwd_dentry = d_root;
+ cwd_mnt = mnt_root;
}
fsdev->vfsmount.mnt_root = fsdev->sb.s_root;
- if (!fsdev->linux_rootarg && fsdev->cdev && fsdev->cdev->partuuid[0] != 0) {
- char *str = basprintf("root=PARTUUID=%s",
- fsdev->cdev->partuuid);
+ if (!fsdev->linux_rootarg) {
+ char *str;
- fsdev_set_linux_rootarg(fsdev, str);
+ str = cdev_get_linux_rootarg(fsdev->cdev);
+ if (str)
+ fsdev_set_linux_rootarg(fsdev, str);
}
path_put(&path);
@@ -2858,15 +3285,13 @@ err_register:
out:
path_put(&path);
- errno = -ret;
-
- return ret;
+ return errno_set(ret);
}
EXPORT_SYMBOL(mount);
int umount(const char *pathname)
{
- struct fs_device_d *fsdev = NULL, *f;
+ struct fs_device *fsdev = NULL, *f;
struct path path = {};
int ret;
@@ -2889,7 +3314,7 @@ int umount(const char *pathname)
path_put(&path);
if (!fsdev) {
- struct cdev *cdev = cdev_open(pathname, O_RDWR);
+ struct cdev *cdev = cdev_open_by_name(pathname, O_RDWR);
if (cdev) {
cdev_close(cdev);
@@ -2897,10 +3322,8 @@ int umount(const char *pathname)
}
}
- if (!fsdev) {
- errno = EFAULT;
- return -EFAULT;
- }
+ if (!fsdev)
+ return errno_set(-EFAULT);
return fsdev_umount(fsdev);
}
@@ -3026,12 +3449,16 @@ static int automount_mount(struct dentry *dentry)
setenv("automount_path", am->path);
export("automount_path");
ret = run_command(am->cmd);
- setenv("automount_path", NULL);
+ unsetenv("automount_path");
if (ret) {
printf("running automount command '%s' failed\n",
am->cmd);
ret = -ENODEV;
+ } else if (!(dentry->d_flags & DCACHE_MOUNTED)) {
+ printf("automount command '%s' didn't mount anything\n",
+ am->cmd);
+ ret = -ENODEV;
}
break;
@@ -3056,7 +3483,6 @@ static int automount_mount(struct dentry *dentry)
/*
* Some debug commands, helpful to debug the dcache implementation
*/
-#include <command.h>
static int do_lookup_dentry(int argc, char *argv[])
{
@@ -3075,7 +3501,7 @@ static int do_lookup_dentry(int argc, char *argv[])
return 1;
}
- canon = canonicalize_path(argv[1]);
+ canon = canonicalize_path(AT_FDCWD, argv[1]);
printf("path \"%s\":\n", argv[1]);
printf("dentry: 0x%p\n", path.dentry);
@@ -3096,11 +3522,12 @@ static int do_lookup_dentry(int argc, char *argv[])
BAREBOX_CMD_START(lookup_dentry)
.cmd = do_lookup_dentry,
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_END
static struct dentry *debug_follow_mount(struct dentry *dentry)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
unsigned managed = dentry->d_flags;
if (managed & DCACHE_MOUNTED) {
@@ -3150,5 +3577,6 @@ static int do_debug_fs_dump(int argc, char *argv[])
BAREBOX_CMD_START(debug_fs_dump)
.cmd = do_debug_fs_dump,
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_END
#endif
diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
index 3121d369b4..329e7b806a 100644
--- a/fs/jffs2/Kconfig
+++ b/fs/jffs2/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig FS_JFFS2
bool
select CRC32
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index a4da48d3c3..3c5bfd261c 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += compr.o dir.o nodelist.o malloc.o
obj-y += read.o readinode.o scan.o
obj-y += build.o fs.o
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 12d0271bdd..2e1794f5ae 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
struct jffs2_acl_entry {
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index f3fc0ade20..d5757d100b 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 1c5a7d9137..04b014199f 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -7,9 +8,6 @@
* University of Szeged, Hungary
*
* Created by Arjan van de Ven <arjan@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 2e3c368ace..20267beeca 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef __JFFS2_COMPR_H__
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c
index 1be30dc604..643b83fa74 100644
--- a/fs/jffs2/compr_lzo.c
+++ b/fs/jffs2/compr_lzo.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by Richard Purdie <rpurdie@openedhand.com>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#include <common.h>
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index d74d7d3d79..f8bc4ab114 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -6,10 +7,6 @@
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
- * For licensing information, see the file 'LICENCE' in this directory.
- *
- *
- *
* Very simple lz77-ish encoder.
*
* Theory of operation: Both encoder and decoder have a list of "last
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index 3e4faa739a..91a500f4fb 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by Arjan van de Ven <arjanv@redhat.com>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 222e0d6e5f..2b7914f1f5 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 536a1786c1..edf8539762 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 97733ecca7..d40569e6fe 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +7,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef _JFFS2_DEBUG_H_
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 4d28d2b553..34f8d141f2 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index f094291aa4..6f2cbff6c9 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
@@ -42,7 +40,7 @@ static inline void i_gid_write(struct inode *inode, gid_t gid)
const struct file_operations jffs2_file_operations;
const struct inode_operations jffs2_file_inode_operations;
-static int jffs2_open(struct device_d *dev, FILE *file, const char *filename)
+static int jffs2_open(struct device *dev, FILE *file, const char *filename)
{
struct inode *inode = file->f_inode;
struct jffs2_file *jf;
@@ -58,7 +56,7 @@ static int jffs2_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int jffs2_close(struct device_d *dev, FILE *f)
+static int jffs2_close(struct device *dev, FILE *f)
{
struct jffs2_file *jf = f->priv;
@@ -74,6 +72,9 @@ static int jffs2_get_block(struct jffs2_file *jf, unsigned int pos)
struct jffs2_inode_info *f = JFFS2_INODE_INFO(jf->inode);
int ret;
+ /* pos always has to be 4096 bytes aligned here */
+ WARN_ON(pos % JFFS2_BLOCK_SIZE != 0);
+
if (pos != jf->offset) {
ret = jffs2_read_inode_range(c, f, jf->buf, pos,
JFFS2_BLOCK_SIZE);
@@ -85,7 +86,7 @@ static int jffs2_get_block(struct jffs2_file *jf, unsigned int pos)
return 0;
}
-static int jffs2_read(struct device_d *_dev, FILE *f, void *buf,
+static int jffs2_read(struct device *_dev, FILE *f, void *buf,
size_t insize)
{
struct jffs2_file *jf = f->priv;
@@ -98,12 +99,13 @@ static int jffs2_read(struct device_d *_dev, FILE *f, void *buf,
/* Read till end of current block */
ofs = f->pos % JFFS2_BLOCK_SIZE;
if (ofs) {
- ret = jffs2_get_block(jf, pos);
+ ret = jffs2_get_block(jf, f->pos - ofs); /* Align down block */
if (ret)
return ret;
now = min(size, JFFS2_BLOCK_SIZE - ofs);
+ /* Complete block has been read, re-apply ofset now */
memcpy(buf, jf->buf + ofs, now);
size -= now;
pos += now;
@@ -397,9 +399,11 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
}
}
-static int jffs2_probe(struct device_d *dev)
+static int jffs2_probe_cnt;
+
+static int jffs2_probe(struct device *dev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
struct super_block *sb;
struct jffs2_sb_info *ctx;
int ret;
@@ -419,28 +423,24 @@ static int jffs2_probe(struct device_d *dev)
sb->s_fs_info = ctx;
- ret = jffs2_compressors_init();
- if (ret) {
- pr_err("error: Failed to initialise compressors\n");
- goto err_out;
- }
-
- ret = jffs2_create_slab_caches();
- if (ret) {
- pr_err("error: Failed to initialise slab caches\n");
- goto err_compressors;
- }
+ if (!jffs2_probe_cnt) {
+ ret = jffs2_compressors_init();
+ if (ret) {
+ pr_err("error: Failed to initialise compressors\n");
+ goto err_out;
+ }
+ }
if (jffs2_fill_super(fsdev, 0)) {
dev_err(dev, "no valid jffs2 found\n");
ret = -EINVAL;
- goto err_slab;
+ goto err_compressors;
}
+ jffs2_probe_cnt++;
+
return 0;
-err_slab:
- jffs2_destroy_slab_caches();
err_compressors:
jffs2_compressors_exit();
err_out:
@@ -448,22 +448,25 @@ err_out:
return ret;
}
-static void jffs2_remove(struct device_d *dev)
+static void jffs2_remove(struct device *dev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
struct super_block *sb;
fsdev = dev_to_fs_device(dev);
sb = &fsdev->sb;
- jffs2_destroy_slab_caches();
- jffs2_compressors_exit();
+ jffs2_probe_cnt--;
+
+ if (!jffs2_probe_cnt) {
+ jffs2_compressors_exit();
+ }
jffs2_put_super(sb);
}
-static struct fs_driver_d jffs2_driver = {
+static struct fs_driver jffs2_driver = {
.open = jffs2_open,
.close = jffs2_close,
.read = jffs2_read,
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
index 2d4b03040f..5d420a926d 100644
--- a/fs/jffs2/jffs2_fs_i.h
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +7,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef _JFFS2_FS_I
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 84d118c2e9..20fa9a26a4 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +7,6 @@
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef _JFFS2_FS_SB
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index b7afc68cea..202191be94 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -17,103 +15,10 @@
#include <linux/jffs2.h>
#include "nodelist.h"
-/* These are initialised to NULL in the kernel startup code.
- If you're porting to other operating systems, beware */
-static struct kmem_cache *full_dnode_slab;
-static struct kmem_cache *raw_dirent_slab;
-static struct kmem_cache *raw_inode_slab;
-static struct kmem_cache *tmp_dnode_info_slab;
-static struct kmem_cache *raw_node_ref_slab;
-static struct kmem_cache *node_frag_slab;
-static struct kmem_cache *inode_cache_slab;
-#ifdef CONFIG_JFFS2_FS_XATTR
-static struct kmem_cache *xattr_datum_cache;
-static struct kmem_cache *xattr_ref_cache;
-#endif
-
-int __init jffs2_create_slab_caches(void)
-{
- full_dnode_slab = kmem_cache_create("jffs2_full_dnode",
- sizeof(struct jffs2_full_dnode),
- 0, 0, NULL);
- if (!full_dnode_slab)
- goto err;
-
- raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent",
- sizeof(struct jffs2_raw_dirent),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!raw_dirent_slab)
- goto err;
-
- raw_inode_slab = kmem_cache_create("jffs2_raw_inode",
- sizeof(struct jffs2_raw_inode),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!raw_inode_slab)
- goto err;
-
- tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode",
- sizeof(struct jffs2_tmp_dnode_info),
- 0, 0, NULL);
- if (!tmp_dnode_info_slab)
- goto err;
-
- raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
- sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
- 0, 0, NULL);
- if (!raw_node_ref_slab)
- goto err;
-
- node_frag_slab = kmem_cache_create("jffs2_node_frag",
- sizeof(struct jffs2_node_frag),
- 0, 0, NULL);
- if (!node_frag_slab)
- goto err;
-
- inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
- sizeof(struct jffs2_inode_cache),
- 0, 0, NULL);
- if (!inode_cache_slab)
- goto err;
-
-#ifdef CONFIG_JFFS2_FS_XATTR
- xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
- sizeof(struct jffs2_xattr_datum),
- 0, 0, NULL);
- if (!xattr_datum_cache)
- goto err;
-
- xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
- sizeof(struct jffs2_xattr_ref),
- 0, 0, NULL);
- if (!xattr_ref_cache)
- goto err;
-#endif
-
- return 0;
- err:
- jffs2_destroy_slab_caches();
- return -ENOMEM;
-}
-
-void jffs2_destroy_slab_caches(void)
-{
- kmem_cache_destroy(full_dnode_slab);
- kmem_cache_destroy(raw_dirent_slab);
- kmem_cache_destroy(raw_inode_slab);
- kmem_cache_destroy(tmp_dnode_info_slab);
- kmem_cache_destroy(raw_node_ref_slab);
- kmem_cache_destroy(node_frag_slab);
- kmem_cache_destroy(inode_cache_slab);
-#ifdef CONFIG_JFFS2_FS_XATTR
- kmem_cache_destroy(xattr_datum_cache);
- kmem_cache_destroy(xattr_ref_cache);
-#endif
-}
-
struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
{
struct jffs2_full_dirent *ret;
- ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL);
+ ret = kmalloc(sizeof(*ret) + namesize, GFP_KERNEL);
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -127,7 +32,7 @@ void jffs2_free_full_dirent(struct jffs2_full_dirent *x)
struct jffs2_full_dnode *jffs2_alloc_full_dnode(void)
{
struct jffs2_full_dnode *ret;
- ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -135,13 +40,13 @@ struct jffs2_full_dnode *jffs2_alloc_full_dnode(void)
void jffs2_free_full_dnode(struct jffs2_full_dnode *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(full_dnode_slab, x);
+ free(x);
}
struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void)
{
struct jffs2_raw_dirent *ret;
- ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -149,13 +54,13 @@ struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void)
void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(raw_dirent_slab, x);
+ free(x);
}
struct jffs2_raw_inode *jffs2_alloc_raw_inode(void)
{
struct jffs2_raw_inode *ret;
- ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -163,13 +68,13 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void)
void jffs2_free_raw_inode(struct jffs2_raw_inode *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(raw_inode_slab, x);
+ free(x);
}
struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void)
{
struct jffs2_tmp_dnode_info *ret;
- ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n",
ret);
return ret;
@@ -178,14 +83,14 @@ struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void)
void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(tmp_dnode_info_slab, x);
+ free(x);
}
static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
{
struct jffs2_raw_node_ref *ret;
- ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret) * (REFS_PER_BLOCK + 1));
if (ret) {
int i = 0;
for (i=0; i < REFS_PER_BLOCK; i++) {
@@ -242,13 +147,13 @@ int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(raw_node_ref_slab, x);
+ free(x);
}
struct jffs2_node_frag *jffs2_alloc_node_frag(void)
{
struct jffs2_node_frag *ret;
- ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -256,13 +161,13 @@ struct jffs2_node_frag *jffs2_alloc_node_frag(void)
void jffs2_free_node_frag(struct jffs2_node_frag *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(node_frag_slab, x);
+ free(x);
}
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
{
struct jffs2_inode_cache *ret;
- ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL);
+ ret = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ret);
return ret;
}
@@ -270,14 +175,14 @@ struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
void jffs2_free_inode_cache(struct jffs2_inode_cache *x)
{
dbg_memalloc("%p\n", x);
- kmem_cache_free(inode_cache_slab, x);
+ free(x);
}
#ifdef CONFIG_JFFS2_FS_XATTR
struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
{
struct jffs2_xattr_datum *xd;
- xd = kmem_cache_zalloc(xattr_datum_cache, GFP_KERNEL);
+ xd = malloc(sizeof(*ret));
dbg_memalloc("%p\n", xd);
if (!xd)
return NULL;
@@ -291,13 +196,13 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
{
dbg_memalloc("%p\n", xd);
- kmem_cache_free(xattr_datum_cache, xd);
+ free(xd);
}
struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
{
struct jffs2_xattr_ref *ref;
- ref = kmem_cache_zalloc(xattr_ref_cache, GFP_KERNEL);
+ ref = malloc(sizeof(*ret));
dbg_memalloc("%p\n", ref);
if (!ref)
return NULL;
@@ -310,6 +215,6 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
{
dbg_memalloc("%p\n", ref);
- kmem_cache_free(xattr_ref_cache, ref);
+ free(ref);
}
#endif
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 446407e138..94753e1995 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index f78e176e77..b5f7716ce2 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef __JFFS2_NODELIST_H__
@@ -441,8 +439,6 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f);
/* malloc.c */
-int jffs2_create_slab_caches(void);
-void jffs2_destroy_slab_caches(void);
struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize);
void jffs2_free_full_dirent(struct jffs2_full_dirent *);
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index b86a55e482..29915715bb 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -1,12 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef __JFFS2_OS_LINUX_H__
@@ -18,7 +17,7 @@
struct kstatfs;
struct kvec;
-struct fs_device_d;
+struct fs_device;
#define JFFS2_BLOCK_SIZE PAGE_SIZE
@@ -181,7 +180,7 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
void jffs2_flash_cleanup(struct jffs2_sb_info *c);
/* super.c */
-int jffs2_fill_super(struct fs_device_d *fsdev, int silent);
+int jffs2_fill_super(struct fs_device *fsdev, int silent);
/* writev.c */
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c
index 2848e4d1d8..a1c3b9d47b 100644
--- a/fs/jffs2/read.c
+++ b/fs/jffs2/read.c
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 0fe67cbb6b..aaf2619613 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 64a5e02c21..0d74a8f51f 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index a4b4747825..87a782f11e 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
@@ -5,9 +6,6 @@
* Zoltan Sogor <weth@inf.u-szeged.hu>,
* Patrik Kluba <pajko@halom.u-szeged.hu>,
* University of Szeged, Hungary
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef JFFS2_SUMMARY_H
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index d9bb6d0bff..37b3f328c6 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -1,12 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
@@ -69,7 +68,7 @@ static const struct super_operations jffs2_super_operations =
/*
* fill in the superblock
*/
-int jffs2_fill_super(struct fs_device_d *fsdev, int silent)
+int jffs2_fill_super(struct fs_device *fsdev, int silent)
{
struct super_block *sb = &fsdev->sb;
struct jffs2_sb_info *c = sb->s_fs_info;
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index dced873766..e348190bd3 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
*/
#ifndef _JFFS2_FS_XATTR_H_
diff --git a/fs/legacy.c b/fs/legacy.c
index fc6a18f408..7e886e7ae9 100644
--- a/fs/legacy.c
+++ b/fs/legacy.c
@@ -19,7 +19,7 @@ static int legacy_iterate(struct file *file, struct dir_context *ctx)
struct dentry *dentry = file->f_path.dentry;
struct inode *dir = d_inode(dentry);
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct dir *d;
struct dirent *dirent;
char *pathname;
@@ -48,7 +48,7 @@ static struct dentry *legacy_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct inode *inode;
char *pathname;
struct stat s;
@@ -72,7 +72,7 @@ static struct dentry *legacy_lookup(struct inode *dir, struct dentry *dentry,
static int legacy_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct inode *inode;
char *pathname;
int ret;
@@ -99,7 +99,7 @@ static int legacy_create(struct inode *dir, struct dentry *dentry, umode_t mode)
static int legacy_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct inode *inode;
char *pathname;
int ret;
@@ -127,7 +127,7 @@ static int legacy_dir_is_empty(struct dentry *dentry)
{
struct inode *dir = d_inode(dentry);
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct dir *d;
struct dirent *dirent;
char *pathname;
@@ -147,7 +147,7 @@ static int legacy_dir_is_empty(struct dentry *dentry)
static int legacy_rmdir(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
char *pathname;
int ret;
@@ -176,7 +176,7 @@ static int legacy_rmdir(struct inode *dir, struct dentry *dentry)
static int legacy_unlink(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
char *pathname;
int ret;
@@ -202,7 +202,7 @@ static int legacy_symlink(struct inode *dir, struct dentry *dentry,
const char *dest)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct inode *inode;
char *pathname;
int ret;
@@ -230,7 +230,7 @@ static int legacy_symlink(struct inode *dir, struct dentry *dentry,
static const char *legacy_get_link(struct dentry *dentry, struct inode *inode)
{
struct super_block *sb = inode->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
char *pathname;
int ret;
char link[PATH_MAX] = {};
@@ -288,6 +288,7 @@ static struct inode *legacy_get_inode(struct super_block *sb, const struct inode
return NULL;
case S_IFREG:
case S_IFCHR:
+ case S_IFBLK:
inode->i_op = &legacy_file_inode_operations;
break;
case S_IFDIR:
@@ -303,7 +304,7 @@ static struct inode *legacy_get_inode(struct super_block *sb, const struct inode
return inode;
}
-int fs_init_legacy(struct fs_device_d *fsdev)
+int fs_init_legacy(struct fs_device *fsdev)
{
struct inode *inode;
diff --git a/fs/nfs.c b/fs/nfs.c
index 6c4637281d..1a0b28442d 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -26,7 +26,6 @@
#include <errno.h>
#include <libgen.h>
#include <fcntl.h>
-#include <fs.h>
#include <init.h>
#include <linux/stat.h>
#include <linux/err.h>
@@ -119,8 +118,8 @@ struct rpc_reply {
uint32_t data[0];
};
-#define NFS_TIMEOUT (2 * SECOND)
-#define NFS_MAX_RESEND 5
+#define NFS_TIMEOUT (100 * MSECOND)
+#define NFS_MAX_RESEND 100
struct nfs_fh {
unsigned short size;
@@ -263,6 +262,74 @@ struct nfs_dir {
struct nfs_fh fh;
};
+struct nfserror {
+ int ne;
+ int e;
+ const char *name;
+};
+
+static struct nfserror nfserrors[] = {
+ { .ne = NFS3ERR_PERM, .e = EPERM },
+ { .ne = NFS3ERR_NOENT, .e = ENOENT },
+ { .ne = NFS3ERR_IO, .e = EIO },
+ { .ne = NFS3ERR_NXIO, .e = ENXIO },
+ { .ne = NFS3ERR_ACCES, .e = EACCES },
+ { .ne = NFS3ERR_EXIST, .e = EEXIST },
+ { .ne = NFS3ERR_XDEV, .e = EXDEV },
+ { .ne = NFS3ERR_NODEV, .e = ENODEV },
+ { .ne = NFS3ERR_NOTDIR, .e = ENOTDIR },
+ { .ne = NFS3ERR_ISDIR, .e = EISDIR },
+ { .ne = NFS3ERR_INVAL, .e = EINVAL },
+ { .ne = NFS3ERR_FBIG, .e = EFBIG },
+ { .ne = NFS3ERR_NOSPC, .e = ENOSPC },
+ { .ne = NFS3ERR_ROFS, .e = EROFS },
+ { .ne = NFS3ERR_MLINK, .e = EMLINK },
+ { .ne = NFS3ERR_NAMETOOLONG, .e = ENAMETOOLONG },
+ { .ne = NFS3ERR_NOTEMPTY, .e = ENOTEMPTY },
+ { .ne = NFS3ERR_DQUOT, .e = EDQUOT },
+ { .ne = NFS3ERR_STALE, .e = ESTALE },
+ { .ne = NFS3ERR_REMOTE, .e = EREMOTE },
+ { .ne = NFS3ERR_NOTSUPP, .e = EOPNOTSUPP },
+ { .ne = NFS3ERR_BADHANDLE, .e = EINVAL, .name = "BADHANDLE"},
+ { .ne = NFS3ERR_NOT_SYNC, .e = EINVAL, .name = "NOT_SYNC" },
+ { .ne = NFS3ERR_BAD_COOKIE, .e = EINVAL, .name = "BAD_COOKIE" },
+ { .ne = NFS3ERR_TOOSMALL, .e = EINVAL, .name = "TOOSMALL" },
+ { .ne = NFS3ERR_SERVERFAULT, .e = EINVAL, .name = "SERVERFAULT" },
+ { .ne = NFS3ERR_BADTYPE, .e = EINVAL, .name = "BADTYPE" },
+ { .ne = NFS3ERR_JUKEBOX, .e = EINVAL, .name = "JUKEBOX" },
+};
+
+static const char *nfserrstr(u32 nfserror, int *errcode)
+{
+ static char str[32];
+ int i;
+
+ /*
+ * Most NFS errors have a corresponding POSIX error code. But not all of
+ * them have one, so some must be mapped to a different code here.
+ */
+ for (i = 0; i < ARRAY_SIZE(nfserrors); i++) {
+ struct nfserror *err = &nfserrors[i];
+
+ if (nfserror == err->ne) {
+ if (errcode)
+ *errcode = -err->e;
+
+ if (err->name) {
+ snprintf(str, sizeof(str), "NFS3ERR_%s", err->name);
+ return str;
+ } else
+ return strerror(err->e);
+ }
+ }
+
+ if (errcode)
+ *errcode = -EINVAL;
+
+ snprintf(str, sizeof(str), "Unknown NFS error %d", nfserror);
+ return str;
+}
+
static void xdr_init(struct xdr_stream *stream, void *buf, int len)
{
stream->p = stream->buf = buf;
@@ -504,6 +571,12 @@ static int rpc_lookup_req(struct nfs_priv *npriv, uint32_t prog, uint32_t ver)
nfs_free_packet(nfs_packet);
+ if (port == 0) {
+ pr_warn("No UDP port for RPC program %i! "
+ "Is your NFS server TCP only?\n", prog);
+ return -ENOENT;
+ }
+
return port;
}
@@ -642,7 +715,7 @@ static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct inode *inode)
static int nfs_mount_req(struct nfs_priv *npriv)
{
uint32_t data[1024];
- uint32_t *p;
+ uint32_t *p, status;
int len;
int pathlen;
struct packet *nfs_packet;
@@ -667,7 +740,18 @@ static int nfs_mount_req(struct nfs_priv *npriv)
if (IS_ERR(nfs_packet))
return PTR_ERR(nfs_packet);
- p = (void *)nfs_packet->data + sizeof(struct rpc_reply) + 4;
+ p = (void *)nfs_packet->data + sizeof(struct rpc_reply);
+
+ /*
+ * Theoretically the error status is one of MNT3ERR_..., but the NFS
+ * constants are identical.
+ */
+ status = ntoh32(net_read_uint32(p++));
+ if (status != NFS3_OK) {
+ int ret;
+ pr_err("Mounting failed: %s\n", nfserrstr(status, &ret));
+ return ret;
+ }
npriv->rootfh.size = ntoh32(net_read_uint32(p++));
if (npriv->rootfh.size > NFS3_FHSIZE) {
@@ -719,7 +803,7 @@ static int nfs_lookup_req(struct nfs_priv *npriv, struct nfs_fh *fh,
{
struct nfs_inode *ninode = nfsi(inode);
uint32_t data[1024];
- uint32_t *p;
+ uint32_t *p, status;
int len;
struct packet *nfs_packet;
@@ -761,7 +845,13 @@ static int nfs_lookup_req(struct nfs_priv *npriv, struct nfs_fh *fh,
if (IS_ERR(nfs_packet))
return PTR_ERR(nfs_packet);
- p = (void *)nfs_packet->data + sizeof(struct rpc_reply) + 4;
+ p = (void *)nfs_packet->data + sizeof(struct rpc_reply);
+ status = ntoh32(net_read_uint32(p++));
+ if (status != NFS3_OK) {
+ int ret;
+ pr_err("Lookup failed: %s\n", nfserrstr(status, &ret));
+ return ret;
+ }
ninode->fh.size = ntoh32(net_read_uint32(p++));
if (ninode->fh.size > NFS3_FHSIZE) {
@@ -787,7 +877,7 @@ static int nfs_lookup_req(struct nfs_priv *npriv, struct nfs_fh *fh,
static void *nfs_readdirattr_req(struct nfs_priv *npriv, struct nfs_dir *dir)
{
uint32_t data[1024];
- uint32_t *p;
+ uint32_t *p, status;
int len;
struct packet *nfs_packet;
void *buf;
@@ -845,7 +935,13 @@ static void *nfs_readdirattr_req(struct nfs_priv *npriv, struct nfs_dir *dir)
if (IS_ERR(nfs_packet))
return NULL;
- p = (void *)nfs_packet->data + sizeof(struct rpc_reply) + 4;
+ p = (void *)nfs_packet->data + sizeof(struct rpc_reply);
+ status = ntoh32(net_read_uint32(p++));
+ if (status != NFS3_OK) {
+ pr_err("Readdir failed: %s\n", nfserrstr(status, NULL));
+ return NULL;
+ }
+
p = nfs_read_post_op_attr(p, NULL);
/* update cookieverf */
@@ -879,8 +975,8 @@ static int nfs_read_req(struct file_priv *priv, uint64_t offset,
uint32_t readlen)
{
uint32_t data[1024];
- uint32_t *p;
- int len;
+ uint32_t *p, status;
+ int len, ret;
struct packet *nfs_packet;
uint32_t rlen, eof;
@@ -922,7 +1018,12 @@ static int nfs_read_req(struct file_priv *priv, uint64_t offset,
if (IS_ERR(nfs_packet))
return PTR_ERR(nfs_packet);
- p = (void *)nfs_packet->data + sizeof(struct rpc_reply) + 4;
+ p = (void *)nfs_packet->data + sizeof(struct rpc_reply);
+ status = ntoh32(net_read_uint32(p++));
+ if (status != NFS3_OK) {
+ pr_err("Read failed: %s\n", nfserrstr(status, &ret));
+ return ret;
+ }
p = nfs_read_post_op_attr(p, NULL);
@@ -964,7 +1065,7 @@ static void nfs_handler(void *ctx, char *p, unsigned len)
list_add_tail(&packet->list, &npriv->packets);
}
-static int nfs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int nfs_truncate(struct device *dev, FILE *f, loff_t size)
{
return -ENOSYS;
}
@@ -981,7 +1082,7 @@ static int nfs_readlink_req(struct nfs_priv *npriv, struct nfs_fh *fh,
char **target)
{
uint32_t data[1024];
- uint32_t *p;
+ uint32_t *p, status;
uint32_t len;
struct packet *nfs_packet;
@@ -1017,13 +1118,19 @@ static int nfs_readlink_req(struct nfs_priv *npriv, struct nfs_fh *fh,
if (IS_ERR(nfs_packet))
return PTR_ERR(nfs_packet);
- p = (void *)nfs_packet->data + sizeof(struct rpc_reply) + 4;
+ p = (void *)nfs_packet->data + sizeof(struct rpc_reply);
+ status = ntoh32(net_read_uint32(p++));
+ if (status != NFS3_OK) {
+ int ret;
+ pr_err("Readlink failed: %s\n", nfserrstr(status, &ret));
+ return ret;
+ }
p = nfs_read_post_op_attr(p, NULL);
len = ntoh32(net_read_uint32(p)); /* new path length */
- len = max_t(unsigned int, len,
+ len = min_t(unsigned int, len,
nfs_packet->len - sizeof(struct rpc_reply) - sizeof(uint32_t));
p++;
@@ -1049,7 +1156,7 @@ static const char *nfs_get_link(struct dentry *dentry, struct inode *inode)
return inode->i_link;
}
-static int nfs_open(struct device_d *dev, FILE *file, const char *filename)
+static int nfs_open(struct device *dev, FILE *file, const char *filename)
{
struct inode *inode = file->f_inode;
struct nfs_inode *ninode = nfsi(inode);
@@ -1071,7 +1178,7 @@ static int nfs_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int nfs_close(struct device_d *dev, FILE *file)
+static int nfs_close(struct device *dev, FILE *file)
{
struct file_priv *priv = file->priv;
@@ -1080,13 +1187,13 @@ static int nfs_close(struct device_d *dev, FILE *file)
return 0;
}
-static int nfs_write(struct device_d *_dev, FILE *file, const void *inbuf,
- size_t insize)
+static int nfs_write(struct device *_dev, FILE *file, const void *inbuf,
+ size_t insize)
{
return -ENOSYS;
}
-static int nfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
+static int nfs_read(struct device *dev, FILE *file, void *buf, size_t insize)
{
struct file_priv *priv = file->priv;
@@ -1102,7 +1209,7 @@ static int nfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
return kfifo_get(priv->fifo, buf, insize);
}
-static int nfs_lseek(struct device_d *dev, FILE *file, loff_t pos)
+static int nfs_lseek(struct device *dev, FILE *file, loff_t pos)
{
struct file_priv *priv = file->priv;
@@ -1285,7 +1392,7 @@ static const struct super_operations nfs_ops = {
static char *rootnfsopts;
-static void nfs_set_rootarg(struct nfs_priv *npriv, struct fs_device_d *fsdev)
+static void nfs_set_rootarg(struct nfs_priv *npriv, struct fs_device *fsdev)
{
char *str, *tmp;
const char *bootargs;
@@ -1318,9 +1425,9 @@ static void nfs_set_rootarg(struct nfs_priv *npriv, struct fs_device_d *fsdev)
free(str);
}
-static int nfs_probe(struct device_d *dev)
+static int nfs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct nfs_priv *npriv = xzalloc(sizeof(struct nfs_priv));
struct super_block *sb = &fsdev->sb;
char *tmp = xstrdup(fsdev->backingstore);
@@ -1418,7 +1525,7 @@ err:
return ret;
}
-static void nfs_remove(struct device_d *dev)
+static void nfs_remove(struct device *dev)
{
struct nfs_priv *npriv = dev->priv;
@@ -1429,7 +1536,7 @@ static void nfs_remove(struct device_d *dev)
free(npriv);
}
-static struct fs_driver_d nfs_driver = {
+static struct fs_driver nfs_driver = {
.open = nfs_open,
.close = nfs_close,
.read = nfs_read,
diff --git a/fs/omap4_usbbootfs.c b/fs/omap4_usbbootfs.c
index 4f159210d1..30392d1192 100644
--- a/fs/omap4_usbbootfs.c
+++ b/fs/omap4_usbbootfs.c
@@ -17,7 +17,7 @@
#include <init.h>
#include <linux/stat.h>
#include <linux/err.h>
-#include <mach/omap4_rom_usb.h>
+#include <mach/omap/omap4_rom_usb.h>
#define OMAP4_USBBOOT_FS_MAGIC 0x5562464D
#define OMAP4_USBBOOT_FS_CMD_OPEN 0x46530000
@@ -30,8 +30,9 @@ struct file_priv {
u32 size;
};
-static struct file_priv *omap4_usbbootfs_do_open(
- struct device_d *dev, int accmode, const char *filename)
+static struct file_priv *omap4_usbbootfs_do_open(struct device *dev,
+ int accmode,
+ const char *filename)
{
struct file_priv *priv;
u32 data;
@@ -60,8 +61,8 @@ static struct file_priv *omap4_usbbootfs_do_open(
return priv;
}
-static int omap4_usbbootfs_open(
- struct device_d *dev, FILE *file, const char *filename)
+static int omap4_usbbootfs_open(struct device *dev, FILE *file,
+ const char *filename)
{
struct file_priv *priv;
@@ -86,14 +87,14 @@ static int omap4_usbbootfs_do_close(struct file_priv *priv)
return 0;
}
-static int omap4_usbbootfs_close(struct device_d *dev, FILE *f)
+static int omap4_usbbootfs_close(struct device *dev, FILE *f)
{
struct file_priv *priv = f->priv;
return omap4_usbbootfs_do_close(priv);
}
-static int omap4_usbbootfs_read(
- struct device_d *dev, FILE *f, void *buf, size_t size)
+static int omap4_usbbootfs_read(struct device *dev, FILE *f, void *buf,
+ size_t size)
{
struct file_priv *priv = f->priv;
u32 data;
@@ -116,13 +117,13 @@ static int omap4_usbbootfs_read(
return size;
}
-static DIR *omap4_usbbootfs_opendir(struct device_d *dev, const char *pathname)
+static DIR *omap4_usbbootfs_opendir(struct device *dev, const char *pathname)
{
return NULL;
}
-static int omap4_usbbootfs_stat(
- struct device_d *dev, const char *filename, struct stat *s)
+static int omap4_usbbootfs_stat(struct device *dev, const char *filename,
+ struct stat *s)
{
struct file_priv *priv;
@@ -140,15 +141,16 @@ static int omap4_usbbootfs_stat(
return 0;
}
-static int omap4_usbbootfs_probe(struct device_d *dev)
+static int omap4_usbbootfs_probe(struct device *dev)
{
- return 0;
+ return omap4_usbboot_open();
}
-static void omap4_usbbootfs_remove(struct device_d *dev)
+
+static void omap4_usbbootfs_remove(struct device *dev)
{
}
-static struct fs_driver_d omap4_usbbootfs_driver = {
+static struct fs_driver omap4_usbbootfs_driver = {
.open = omap4_usbbootfs_open,
.close = omap4_usbbootfs_close,
.read = omap4_usbbootfs_read,
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index 30c2de19c8..ff9091d3f3 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig FS_PSTORE
select FS_LEGACY
bool
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
index c4043e1a8f..18475497a3 100644
--- a/fs/pstore/Makefile
+++ b/fs/pstore/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
#
# Makefile for the linux pstorefs routines.
#
diff --git a/fs/pstore/fs.c b/fs/pstore/fs.c
index e9c7ae7adb..777e2448cc 100644
--- a/fs/pstore/fs.c
+++ b/fs/pstore/fs.c
@@ -21,7 +21,6 @@
#include <fs.h>
#include <errno.h>
#include <fcntl.h>
-#include <fs.h>
#include <malloc.h>
#include <init.h>
#include <linux/stat.h>
@@ -30,7 +29,6 @@
#include <libbb.h>
#include <rtc.h>
#include <libfile.h>
-#include <linux/pstore.h>
#include "internal.h"
struct list_head allpstore = LIST_HEAD_INIT(allpstore);
@@ -140,7 +138,7 @@ static struct pstore_private *pstore_get_by_name(struct list_head *head,
return NULL;
}
-static int pstore_open(struct device_d *dev, FILE *file, const char *filename)
+static int pstore_open(struct device *dev, FILE *file, const char *filename)
{
struct list_head *head = dev->priv;
struct pstore_private *d;
@@ -159,12 +157,12 @@ static int pstore_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int pstore_close(struct device_d *dev, FILE *file)
+static int pstore_close(struct device *dev, FILE *file)
{
return 0;
}
-static int pstore_read(struct device_d *dev, FILE *file, void *buf,
+static int pstore_read(struct device *dev, FILE *file, void *buf,
size_t insize)
{
struct pstore_private *d = file->priv;
@@ -175,7 +173,7 @@ static int pstore_read(struct device_d *dev, FILE *file, void *buf,
return insize;
}
-static int pstore_lseek(struct device_d *dev, FILE *file, loff_t pos)
+static int pstore_lseek(struct device *dev, FILE *file, loff_t pos)
{
struct pstore_private *d = file->priv;
@@ -184,7 +182,7 @@ static int pstore_lseek(struct device_d *dev, FILE *file, loff_t pos)
return 0;
}
-static DIR *pstore_opendir(struct device_d *dev, const char *pathname)
+static DIR *pstore_opendir(struct device *dev, const char *pathname)
{
DIR *dir;
@@ -198,7 +196,7 @@ static DIR *pstore_opendir(struct device_d *dev, const char *pathname)
return dir;
}
-static struct dirent *pstore_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *pstore_readdir(struct device *dev, DIR *dir)
{
struct pstore_private *d = dir->priv;
@@ -211,14 +209,14 @@ static struct dirent *pstore_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int pstore_closedir(struct device_d *dev, DIR *dir)
+static int pstore_closedir(struct device *dev, DIR *dir)
{
free(dir);
return 0;
}
-static int pstore_stat(struct device_d *dev, const char *filename,
+static int pstore_stat(struct device *dev, const char *filename,
struct stat *s)
{
struct pstore_private *d;
@@ -236,7 +234,7 @@ static int pstore_stat(struct device_d *dev, const char *filename,
return 0;
}
-static void pstore_remove(struct device_d *dev)
+static void pstore_remove(struct device *dev)
{
struct pstore_private *d, *tmp;
@@ -245,7 +243,7 @@ static void pstore_remove(struct device_d *dev)
}
}
-static int pstore_probe(struct device_d *dev)
+static int pstore_probe(struct device *dev)
{
struct list_head *priv = &allpstore;
@@ -256,7 +254,7 @@ static int pstore_probe(struct device_d *dev)
return 0;
}
-static struct fs_driver_d pstore_driver = {
+static struct fs_driver pstore_driver = {
.open = pstore_open,
.close = pstore_close,
.read = pstore_read,
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 6b507e4bd3..d233ee7e8c 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __PSTORE_INTERNAL_H__
#define __PSTORE_INTERNAL_H__
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index f4b77226d9..50a1bffdd0 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -27,7 +27,7 @@
#include <linux/mutex.h>
#include <console.h>
#include <malloc.h>
-#include <printk.h>
+#include <linux/printk.h>
#include <module.h>
#include "internal.h"
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 958f46b0ea..4732bd4e31 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -31,7 +31,7 @@
#include <linux/log2.h>
#include <linux/spinlock.h>
#include <malloc.h>
-#include <printk.h>
+#include <linux/printk.h>
#include <stdio.h>
#include <globalvar.h>
#include <init.h>
@@ -410,13 +410,13 @@ static int ramoops_init_prz(const char *name,
return 0;
}
-static int ramoops_parse_dt_size(struct device_d *dev,
+static int ramoops_parse_dt_size(struct device *dev,
const char *propname, u32 *value)
{
u32 val32 = 0;
int ret;
- ret = of_property_read_u32(dev->device_node, propname, &val32);
+ ret = of_property_read_u32(dev->of_node, propname, &val32);
if (ret < 0 && ret != -EINVAL) {
dev_err(dev, "failed to parse property %s: %d\n",
propname, ret);
@@ -432,10 +432,10 @@ static int ramoops_parse_dt_size(struct device_d *dev,
return 0;
}
-static int ramoops_parse_dt(struct device_d *dev,
+static int ramoops_parse_dt(struct device *dev,
struct ramoops_platform_data *pdata)
{
- struct device_node *of_node = dev->device_node;
+ struct device_node *of_node = dev->of_node;
struct resource *res;
u32 value;
int ret;
@@ -474,37 +474,24 @@ static int ramoops_of_fixup(struct device_node *root, void *data)
{
struct ramoops_platform_data *pdata = data;
struct device_node *node;
- u32 reg[2];
+ struct resource res = {};
int ret;
- node = of_get_child_by_name(root, "reserved-memory");
- if (!node) {
- pr_info("Adding reserved-memory node\n");
- node = of_create_node(root, "/reserved-memory");
- if (!node)
- return -ENOMEM;
+ res.start = pdata->mem_address;
+ res.end = res.start + pdata->mem_size;
+ res.name = "ramoops";
- of_property_write_u32(node, "#address-cells", 1);
- of_property_write_u32(node, "#size-cells", 1);
- of_new_property(node, "ranges", NULL, 0);
- }
+ ret = of_fixup_reserved_memory(root, &res);
+ if (ret)
+ return ret;
- node = of_get_child_by_name(node, "ramoops");
- if (!node) {
- pr_info("Adding ramoops node\n");
- node = of_create_node(root, "/reserved-memory/ramoops");
- if (!node)
- return -ENOMEM;
- }
+ node = of_find_node_by_path_from(root, "/reserved-memory/ramoops");
+ if (!node)
+ return -ENOMEM;
ret = of_property_write_string(node, "compatible", "ramoops");
if (ret)
return ret;
- reg[0] = pdata->mem_address;
- reg[1] = pdata->mem_size;
- ret = of_property_write_u32_array(node, "reg", reg, 2);
- if (ret)
- return ret;
ret = of_property_write_bool(node, "unbuffered", pdata->mem_type);
if (ret)
@@ -530,7 +517,7 @@ static int ramoops_of_fixup(struct device_node *root, void *data)
return 0;
}
-static int ramoops_probe(struct device_d *dev)
+static int ramoops_probe(struct device *dev)
{
struct ramoops_platform_data *pdata = dummy_data;
struct ramoops_context *cxt = &oops_cxt;
@@ -639,7 +626,6 @@ static int ramoops_probe(struct device_d *dev)
ramoops_ecc);
globalvar_add_simple("linux.bootargs.ramoops", kernelargs);
} else {
- of_add_reserve_entry(cxt->phys_addr, cxt->phys_addr + mem_size);
of_register_fixup(ramoops_of_fixup, pdata);
}
@@ -689,8 +675,9 @@ static const struct of_device_id ramoops_dt_ids[] = {
{ .compatible = "ramoops" },
{ },
};
+MODULE_DEVICE_TABLE(of, ramoops_dt_ids);
-static struct driver_d ramoops_driver = {
+static struct driver ramoops_driver = {
.name = "ramoops",
.probe = ramoops_probe,
.of_compatible = DRV_OF_COMPAT(ramoops_dt_ids),
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 06be47ce53..76b8a109be 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -20,7 +20,6 @@
#include <linux/rslib.h>
#include <linux/pstore_ram.h>
#include <linux/string.h>
-#include <linux/rslib.h>
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
diff --git a/fs/ramfs.c b/fs/ramfs.c
index 14ba877660..117e69b70c 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -221,7 +221,7 @@ static struct ramfs_chunk *ramfs_find_chunk(struct ramfs_inode *node,
return NULL;
}
-static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int ramfs_read(struct device *_dev, FILE *f, void *buf, size_t insize)
{
struct inode *inode = f->f_inode;
struct ramfs_inode *node = to_ramfs_inode(inode);
@@ -251,7 +251,8 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
return insize;
}
-static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+static int ramfs_write(struct device *_dev, FILE *f, const void *buf,
+ size_t insize)
{
struct inode *inode = f->f_inode;
struct ramfs_inode *node = to_ramfs_inode(inode);
@@ -355,7 +356,7 @@ out:
return -ENOSPC;
}
-static int ramfs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int ramfs_truncate(struct device *dev, FILE *f, loff_t size)
{
struct inode *inode = f->f_inode;
struct ramfs_inode *node = to_ramfs_inode(inode);
@@ -387,7 +388,7 @@ static int ramfs_truncate(struct device_d *dev, FILE *f, loff_t size)
return 0;
}
-static int ramfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
+static int ramfs_memmap(struct device *_dev, FILE *f, void **map, int flags)
{
struct inode *inode = f->f_inode;
struct ramfs_inode *node = to_ramfs_inode(inode);
@@ -431,10 +432,10 @@ static const struct super_operations ramfs_ops = {
.destroy_inode = ramfs_destroy_inode,
};
-static int ramfs_probe(struct device_d *dev)
+static int ramfs_probe(struct device *dev)
{
struct inode *inode;
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct super_block *sb = &fsdev->sb;
sb->s_op = &ramfs_ops;
@@ -445,12 +446,11 @@ static int ramfs_probe(struct device_d *dev)
return 0;
}
-static void ramfs_remove(struct device_d *dev)
+static void ramfs_remove(struct device *dev)
{
- free(dev->priv);
}
-static struct fs_driver_d ramfs_driver = {
+static struct fs_driver ramfs_driver = {
.read = ramfs_read,
.write = ramfs_write,
.memmap = ramfs_memmap,
diff --git a/fs/ratpfs.c b/fs/ratpfs.c
index b6857c6016..9e85fc596e 100644
--- a/fs/ratpfs.c
+++ b/fs/ratpfs.c
@@ -48,25 +48,25 @@ struct ratpfs_dir {
DIR dir;
};
-static int ratpfs_create(struct device_d __always_unused *dev,
- const char __always_unused *pathname,
- mode_t __always_unused mode)
+static int ratpfs_create(struct device __always_unused *dev,
+ const char __always_unused *pathname,
+ mode_t __always_unused mode)
{
pr_debug("%s\n", __func__);
return 0;
}
-static int ratpfs_mkdir(struct device_d __always_unused *dev,
- const char __always_unused *pathname)
+static int ratpfs_mkdir(struct device __always_unused *dev,
+ const char __always_unused *pathname)
{
pr_debug("%s\n", __func__);
return -ENOSYS;
}
-static int ratpfs_rm(struct device_d __always_unused *dev,
- const char *pathname)
+static int ratpfs_rm(struct device __always_unused *dev,
+ const char *pathname)
{
pr_debug("%s\n", __func__);
@@ -76,8 +76,8 @@ static int ratpfs_rm(struct device_d __always_unused *dev,
return 0;
}
-static int ratpfs_truncate(struct device_d __always_unused *dev,
- FILE *f, loff_t size)
+static int ratpfs_truncate(struct device __always_unused *dev,
+ FILE *f, loff_t size)
{
int len_tx = 1 /* type */
+ 4 /* handle */
@@ -114,8 +114,8 @@ out:
return ret;
}
-static int ratpfs_open(struct device_d __always_unused *dev,
- FILE *file, const char *filename)
+static int ratpfs_open(struct device __always_unused *dev,
+ FILE *file, const char *filename)
{
int len_name = strlen(filename);
int len_tx = 1 /* type */
@@ -163,7 +163,7 @@ out:
return ret;
}
-static int ratpfs_close(struct device_d __always_unused *dev,
+static int ratpfs_close(struct device __always_unused *dev,
FILE *f)
{
int len_tx = 1 /* type */
@@ -198,7 +198,7 @@ out:
return ret;
}
-static int ratpfs_write(struct device_d __always_unused *dev,
+static int ratpfs_write(struct device __always_unused *dev,
FILE *f, const void *buf, size_t orig_size)
{
int size = min((int)orig_size, 4096);
@@ -241,7 +241,7 @@ out:
return ret;
}
-static int ratpfs_read(struct device_d __always_unused *dev,
+static int ratpfs_read(struct device __always_unused *dev,
FILE *f, void *buf, size_t orig_size)
{
int size = min((int)orig_size, 4096);
@@ -284,8 +284,8 @@ out:
return ret;
}
-static DIR* ratpfs_opendir(struct device_d __always_unused *dev,
- const char *pathname)
+static DIR* ratpfs_opendir(struct device __always_unused *dev,
+ const char *pathname)
{
int len_name = strlen(pathname);
int len_tx = 1 /* type */
@@ -318,7 +318,7 @@ static DIR* ratpfs_opendir(struct device_d __always_unused *dev,
}
}
-static struct dirent *ratpfs_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *ratpfs_readdir(struct device *dev, DIR *dir)
{
struct ratpfs_dir *rdir = container_of(dir, struct ratpfs_dir, dir);
int i;
@@ -338,7 +338,7 @@ static struct dirent *ratpfs_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int ratpfs_closedir(struct device_d *dev, DIR *dir)
+static int ratpfs_closedir(struct device *dev, DIR *dir)
{
struct ratpfs_dir *rdir = container_of(dir, struct ratpfs_dir, dir);
@@ -350,8 +350,8 @@ static int ratpfs_closedir(struct device_d *dev, DIR *dir)
return 0;
}
-static int ratpfs_stat(struct device_d __always_unused *dev,
- const char *filename, struct stat *s)
+static int ratpfs_stat(struct device __always_unused *dev,
+ const char *filename, struct stat *s)
{
int len_name = strlen(filename);
int len_tx = 1 /* type */
@@ -395,13 +395,13 @@ out:
return ret;
}
-static int ratpfs_probe(struct device_d *dev)
+static int ratpfs_probe(struct device *dev)
{
int len_tx = 1; /* type */
struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
struct ratp_bb_pkt *pkt_rx = NULL;
int ret;
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
pr_debug("%s\n", __func__);
@@ -431,14 +431,14 @@ out:
return ret;
}
-static void ratpfs_remove(struct device_d __always_unused *dev)
+static void ratpfs_remove(struct device __always_unused *dev)
{
pr_debug("%s\n", __func__);
barebox_ratp_fs_mount(NULL);
}
-static struct fs_driver_d ratpfs_driver = {
+static struct fs_driver ratpfs_driver = {
.open = ratpfs_open,
.close = ratpfs_close,
.read = ratpfs_read,
diff --git a/fs/smhfs.c b/fs/smhfs.c
index 2e99b05979..5165bf9394 100644
--- a/fs/smhfs.c
+++ b/fs/smhfs.c
@@ -29,20 +29,20 @@ static int file_to_fd(const FILE *f)
return (int)f->priv;
}
-static int smhfs_create(struct device_d __always_unused *dev,
+static int smhfs_create(struct device __always_unused *dev,
const char __always_unused *pathname,
mode_t __always_unused mode)
{
return 0;
}
-static int smhfs_mkdir(struct device_d __always_unused *dev,
+static int smhfs_mkdir(struct device __always_unused *dev,
const char __always_unused *pathname)
{
return -ENOSYS;
}
-static int smhfs_rm(struct device_d __always_unused *dev,
+static int smhfs_rm(struct device __always_unused *dev,
const char *pathname)
{
/* Get rid of leading '/' */
@@ -54,14 +54,14 @@ static int smhfs_rm(struct device_d __always_unused *dev,
return 0;
}
-static int smhfs_truncate(struct device_d __always_unused *dev,
+static int smhfs_truncate(struct device __always_unused *dev,
FILE __always_unused *f,
loff_t __always_unused size)
{
return 0;
}
-static int smhfs_open(struct device_d __always_unused *dev,
+static int smhfs_open(struct device __always_unused *dev,
FILE *file, const char *filename)
{
int fd;
@@ -82,7 +82,7 @@ error:
return -semihosting_errno();
}
-static int smhfs_close(struct device_d __always_unused *dev,
+static int smhfs_close(struct device __always_unused *dev,
FILE *f)
{
if (semihosting_close(file_to_fd(f)))
@@ -91,7 +91,7 @@ static int smhfs_close(struct device_d __always_unused *dev,
return 0;
}
-static int smhfs_write(struct device_d __always_unused *dev,
+static int smhfs_write(struct device __always_unused *dev,
FILE *f, const void *inbuf, size_t insize)
{
if (semihosting_write(file_to_fd(f), inbuf, insize))
@@ -100,7 +100,7 @@ static int smhfs_write(struct device_d __always_unused *dev,
return insize;
}
-static int smhfs_read(struct device_d __always_unused *dev,
+static int smhfs_read(struct device __always_unused *dev,
FILE *f, void *buf, size_t insize)
{
if (!semihosting_read(file_to_fd(f), buf, insize))
@@ -109,7 +109,7 @@ static int smhfs_read(struct device_d __always_unused *dev,
return -semihosting_errno();
}
-static int smhfs_lseek(struct device_d __always_unused *dev,
+static int smhfs_lseek(struct device __always_unused *dev,
FILE *f, loff_t pos)
{
if (semihosting_seek(file_to_fd(f), pos))
@@ -118,13 +118,13 @@ static int smhfs_lseek(struct device_d __always_unused *dev,
return 0;
}
-static DIR* smhfs_opendir(struct device_d __always_unused *dev,
+static DIR* smhfs_opendir(struct device __always_unused *dev,
const char __always_unused *pathname)
{
return NULL;
}
-static int smhfs_stat(struct device_d __always_unused *dev,
+static int smhfs_stat(struct device __always_unused *dev,
const char *filename, struct stat *s)
{
FILE file;
@@ -138,17 +138,17 @@ static int smhfs_stat(struct device_d __always_unused *dev,
return 0;
}
-static int smhfs_probe(struct device_d __always_unused *dev)
+static int smhfs_probe(struct device __always_unused *dev)
{
/* TODO: Add provisions to detect if debugger is connected */
return 0;
}
-static void smhfs_remove(struct device_d __always_unused *dev)
+static void smhfs_remove(struct device __always_unused *dev)
{
}
-static struct fs_driver_d smhfs_driver = {
+static struct fs_driver smhfs_driver = {
.open = smhfs_open,
.close = smhfs_close,
.read = smhfs_read,
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 19b8297af6..af187a2a8a 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig FS_SQUASHFS
bool
prompt "squashfs support"
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 81fc7e570d..59a78a24b0 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += squashfs.o
obj-y += block.o
obj-y += cache.o
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 470536e589..f702f6c0a2 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -44,22 +44,6 @@
#include "squashfs_fs_i.h"
#include "squashfs.h"
-struct inode *iget_locked_squashfs(struct super_block *sb, unsigned long ino)
-{
- struct inode *inode;
- struct squashfs_inode_info *ei;
-
- ei = malloc(sizeof(struct squashfs_inode_info));
- inode = &ei->vfs_inode;
- if (inode) {
- inode->i_ino = ino;
- inode->i_sb = sb;
- inode->i_state = I_SYNC | I_NEW;
- }
-
- return inode;
-}
-
/*
* Initialise VFS inode with the base inode information common to all
* Squashfs inode types. Sqsh_ino contains the unswapped base inode
@@ -94,7 +78,7 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
struct inode *squashfs_iget(struct super_block *sb, long long ino,
unsigned int ino_number)
{
- struct inode *inode = iget_locked_squashfs(sb, ino_number);
+ struct inode *inode = iget_locked(sb, ino_number);
int err;
TRACE("Entered squashfs_iget\n");
@@ -124,7 +108,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
union squashfs_inode squashfs_ino;
struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
- int xattr_id = SQUASHFS_INVALID_XATTR;
TRACE("Entered squashfs_read_inode: %lld\n", ino);
@@ -213,7 +196,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
frag_offset = 0;
}
- xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_size = le64_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_inode_ops;
inode->i_mode |= S_IFREG;
@@ -265,7 +247,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
if (err < 0)
goto failed_read;
- xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_size = le32_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_dir_inode_ops;
inode->i_fop = &squashfs_dir_ops;
@@ -310,7 +291,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
&offset, sizeof(xattr));
if (err < 0)
goto failed_read;
- xattr_id = le32_to_cpu(xattr);
}
TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
@@ -354,7 +334,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFCHR;
else
inode->i_mode |= S_IFBLK;
- xattr_id = le32_to_cpu(sqsh_ino->xattr);
rdev = le32_to_cpu(sqsh_ino->rdev);
TRACE("Device inode %x:%x, rdev %x\n",
@@ -391,7 +370,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFIFO;
else
inode->i_mode |= S_IFSOCK;
- xattr_id = le32_to_cpu(sqsh_ino->xattr);
break;
}
default:
diff --git a/fs/squashfs/squashfs.c b/fs/squashfs/squashfs.c
index 69451f7b84..f2e5769a19 100644
--- a/fs/squashfs/squashfs.c
+++ b/fs/squashfs/squashfs.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <malloc.h>
#include <driver.h>
@@ -39,7 +41,7 @@ char *squashfs_devread(struct squashfs_sb_info *fs, int byte_offset,
return buf;
}
-static void squashfs_set_rootarg(struct fs_device_d *fsdev)
+static void squashfs_set_rootarg(struct fs_device *fsdev)
{
struct ubi_volume_desc *ubi_vol;
struct ubi_volume_info vi = {};
@@ -88,9 +90,9 @@ static const struct super_operations squashfs_super_ops = {
.destroy_inode = squashfs_destroy_inode,
};
-static int squashfs_probe(struct device_d *dev)
+static int squashfs_probe(struct device *dev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
int ret;
struct super_block *sb;
@@ -101,6 +103,7 @@ static int squashfs_probe(struct device_d *dev)
if (ret)
goto err_out;
+ sb->s_op = &squashfs_super_ops;
ret = squashfs_mount(fsdev, 0);
if (ret) {
@@ -110,8 +113,6 @@ static int squashfs_probe(struct device_d *dev)
squashfs_set_rootarg(fsdev);
- sb->s_op = &squashfs_super_ops;
-
return 0;
err_out:
@@ -119,9 +120,9 @@ err_out:
return ret;
}
-static void squashfs_remove(struct device_d *dev)
+static void squashfs_remove(struct device *dev)
{
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
struct super_block *sb;
fsdev = dev_to_fs_device(dev);
@@ -130,7 +131,7 @@ static void squashfs_remove(struct device_d *dev)
squashfs_put_super(sb);
}
-static int squashfs_open(struct device_d *dev, FILE *file, const char *filename)
+static int squashfs_open(struct device *dev, FILE *file, const char *filename)
{
struct inode *inode = file->f_inode;
struct squashfs_page *page;
@@ -164,7 +165,7 @@ error:
return -ENOMEM;
}
-static int squashfs_close(struct device_d *dev, FILE *f)
+static int squashfs_close(struct device *dev, FILE *f)
{
struct squashfs_page *page = f->priv;
int i;
@@ -196,8 +197,8 @@ static int squashfs_read_buf(struct squashfs_page *page, int pos, void **buf)
return 0;
}
-static int squashfs_read(struct device_d *_dev, FILE *f, void *buf,
- size_t insize)
+static int squashfs_read(struct device *_dev, FILE *f, void *buf,
+ size_t insize)
{
unsigned int size = insize;
unsigned int pos = f->pos;
@@ -250,7 +251,7 @@ struct squashfs_dir {
char root_d_name[256];
};
-static struct fs_driver_d squashfs_driver = {
+static struct fs_driver squashfs_driver = {
.open = squashfs_open,
.close = squashfs_close,
.read = squashfs_read,
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 31c9bc454e..d22e83dc3c 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -17,7 +17,7 @@
* squashfs.h
*/
-#include <printk.h>
+#include <linux/printk.h>
#include <fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
@@ -52,11 +52,10 @@ static inline struct squashfs_page *squashfs_page(struct page *page)
#define WARNING(s, args...) pr_warn("SQUASHFS: "s, ## args)
-struct inode *iget_locked_squashfs(struct super_block *sb, unsigned long ino);
char *squashfs_devread(struct squashfs_sb_info *fs, int byte_offset,
int byte_len);
-extern int squashfs_mount(struct fs_device_d *fsdev,
- int silent);
+extern int squashfs_mount(struct fs_device *fsdev,
+ int silent);
extern void squashfs_put_super(struct super_block *sb);
/* block.c */
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 2b6f81d33a..c6fc37d48f 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -77,6 +77,6 @@ struct squashfs_sb_info {
unsigned int inodes;
int xattr_ids;
struct cdev *cdev;
- struct device_d *dev;
+ struct device *dev;
};
#endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index e2b7b8d5a1..2e34c0e540 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -83,7 +83,6 @@ void squashfs_put_super(struct super_block *sb)
}
if (sb->s_root) {
- kfree(squashfs_i(sb->s_root->d_inode));
kfree(sb->s_root);
sb->s_root = NULL;
}
@@ -92,7 +91,7 @@ void squashfs_put_super(struct super_block *sb)
static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct squashfs_sb_info *msblk;
- struct fs_device_d *fsdev = (struct fs_device_d *)data;
+ struct fs_device *fsdev = (struct fs_device *)data;
struct squashfs_super_block *sblk = NULL;
struct inode *root;
long long root_inode;
@@ -322,7 +321,7 @@ failed_mount:
}
-int squashfs_mount(struct fs_device_d *fsdev, int silent)
+int squashfs_mount(struct fs_device *fsdev, int silent)
{
struct super_block *sb = &fsdev->sb;
diff --git a/fs/tftp-selftest.h b/fs/tftp-selftest.h
new file mode 100644
index 0000000000..2406ed329e
--- /dev/null
+++ b/fs/tftp-selftest.h
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+// SPDX-FileCopyrightText: 2022 Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
+
+#ifndef H_BAREBOX_FS_TFTP_SELFTEST_H
+#define H_BAREBOX_FS_TFTP_SELFTEST_H
+
+#include <bselftest.h>
+
+#define _expect_fmt(_v) _Generic(_v, \
+ void const *: "%p", \
+ void *: "%p", \
+ bool: "%d", \
+ long int: "%lld", \
+ long unsigned int: "%llu", \
+ unsigned short: "%h", \
+ signed int: "%d", \
+ unsigned int: "%u")
+
+#define _expect_op(_a, _b, _op) \
+ ({ \
+ __typeof__(_a) __a = (_a); \
+ __typeof__(_b) __b = (_b); \
+ \
+ total_tests++; \
+ \
+ if (!(__a _op __b)) { \
+ char fmt[sizeof "%s:%d: failed: %XXX %XXX\n" # _op]; \
+ strcpy(fmt, "%s:%d: failed: "); \
+ strcat(fmt, _expect_fmt(__a)); \
+ strcat(fmt, " " # _op " "); \
+ strcat(fmt, _expect_fmt(__b)); \
+ strcat(fmt, "\n"); \
+ \
+ failed_tests++; \
+ printf(fmt, __func__, __LINE__, __a, __b); \
+ } \
+ })
+
+#define _as_void(_p) ({ \
+ void const *__res = (_p); \
+ __res; \
+ })
+
+#define expect_eq(_a, _b) _expect_op(_a, _b, ==);
+#define expect_ne(_a, _b) _expect_op(_a, _b, !=);
+#define expect_it(_a) _expect_op(_a, true, ==);
+
+#define expect_err(_a) _expect_op(_a, 0, <);
+#define expect_ok(_a) _expect_op(_a, 0, ==);
+
+/* _Generic() does not match 'void *' for typed pointers; cast them to raw
+ 'void *' first */
+#define expect_NULL(_a) _expect_op(_as_void(_a), NULL, ==);
+#define expect_PTR(_a) _expect_op(_as_void(_a), NULL, !=);
+
+#endif /* H_BAREBOX_FS_TFTP_SELFTEST_H */
diff --git a/fs/tftp.c b/fs/tftp.c
index d186e7983a..c6edc9969f 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -26,12 +26,18 @@
#include <libgen.h>
#include <fcntl.h>
#include <getopt.h>
+#include <globalvar.h>
#include <init.h>
+#include <linux/bitmap.h>
#include <linux/stat.h>
#include <linux/err.h>
+#include <linux/kernel.h>
#include <kfifo.h>
+#include <parseopt.h>
#include <linux/sizes.h>
+#include "tftp-selftest.h"
+
#define TFTP_PORT 69 /* Well known TFTP port number */
/* Seconds to wait before remote server is allowed to resend a lost packet */
@@ -58,21 +64,54 @@
#define STATE_WRQ 2
#define STATE_RDATA 3
#define STATE_WDATA 4
-#define STATE_OACK 5
+/* OACK from server has been received and we can begin to sent either the ACK
+ (for RRQ) or data (for WRQ) */
+#define STATE_START 5
#define STATE_WAITACK 6
#define STATE_LAST 7
#define STATE_DONE 8
#define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
-#define TFTP_FIFO_SIZE 4096
+#define TFTP_MTU_SIZE 1432 /* MTU based block size */
+#define TFTP_MAX_WINDOW_SIZE CONFIG_FS_TFTP_MAX_WINDOW_SIZE
+
+/* allocate this number of blocks more than needed in the fifo */
+#define TFTP_EXTRA_BLOCKS 2
+
+/* marker for an emtpy 'tftp_cache' */
+#define TFTP_CACHE_NO_ID (-1)
#define TFTP_ERR_RESEND 1
+#if defined(DEBUG) || IS_ENABLED(CONFIG_SELFTEST_TFTP)
+# define debug_assert(_cond) BUG_ON(!(_cond))
+#else
+# define debug_assert(_cond) do { \
+ if (!(_cond)) \
+ __builtin_unreachable(); \
+ } while (0)
+#endif
+
+static int g_tftp_window_size = DIV_ROUND_UP(TFTP_MAX_WINDOW_SIZE, 2);
+
+struct tftp_block {
+ uint16_t id;
+ uint16_t len;
+
+ struct list_head list;
+ uint8_t data[];
+};
+
+struct tftp_cache {
+ struct list_head blocks;
+};
+
struct file_priv {
struct net_connection *tftp_con;
int push;
uint16_t block;
uint16_t last_block;
+ uint16_t ack_block;
int state;
int err;
char *filename;
@@ -82,28 +121,78 @@ struct file_priv {
struct kfifo *fifo;
void *buf;
int blocksize;
- int block_requested;
+ unsigned int windowsize;
+ bool is_getattr;
+ struct tftp_cache cache;
};
struct tftp_priv {
IPaddr_t server;
};
-static int tftp_truncate(struct device_d *dev, FILE *f, loff_t size)
+static inline bool is_block_before(uint16_t a, uint16_t b)
+{
+ return (int16_t)(b - a) > 0;
+}
+
+static bool in_window(uint16_t block, uint16_t start, uint16_t end)
+{
+ /* handle the three cases:
+ - [ ......... | start | .. | BLOCK | .. | end | ......... ]
+ - [ ..| BLOCK | .. | end | ................. | start | .. ]
+ - [ ..| end | ................. | start | .. | BLOCK | .. ]
+ */
+ return ((start <= block && block <= end) ||
+ (block <= end && end <= start) ||
+ (end <= start && start <= block));
+}
+
+static void tftp_window_cache_free(struct tftp_cache *cache)
+{
+ struct tftp_block *block, *tmp;
+
+ list_for_each_entry_safe(block, tmp, &cache->blocks, list)
+ free(block);
+}
+
+static int tftp_window_cache_insert(struct tftp_cache *cache, uint16_t id,
+ void const *data, size_t len)
+{
+ struct tftp_block *block, *new;
+
+ list_for_each_entry(block, &cache->blocks, list) {
+ if (block->id == id)
+ return 0;
+ if (is_block_before(block->id, id))
+ continue;
+
+ break;
+ }
+
+ new = xzalloc(sizeof(*new) + len);
+ memcpy(new->data, data, len);
+ new->id = id;
+ new->len = len;
+ list_add_tail(&new->list, &block->list);
+
+ return 0;
+}
+
+static int tftp_truncate(struct device *dev, FILE *f, loff_t size)
{
return 0;
}
-static char *tftp_states[] = {
+static char const * const tftp_states[] = {
[STATE_INVALID] = "INVALID",
[STATE_RRQ] = "RRQ",
[STATE_WRQ] = "WRQ",
[STATE_RDATA] = "RDATA",
[STATE_WDATA] = "WDATA",
- [STATE_OACK] = "OACK",
[STATE_WAITACK] = "WAITACK",
[STATE_LAST] = "LAST",
[STATE_DONE] = "DONE",
+ [STATE_START] = "START",
};
static int tftp_send(struct file_priv *priv)
@@ -112,6 +201,7 @@ static int tftp_send(struct file_priv *priv)
int len = 0;
uint16_t *s;
unsigned char *pkt = net_udp_get_payload(priv->tftp_con);
+ unsigned int window_size;
int ret;
pr_vdebug("%s: state %s\n", __func__, tftp_states[priv->state]);
@@ -119,6 +209,15 @@ static int tftp_send(struct file_priv *priv)
switch (priv->state) {
case STATE_RRQ:
case STATE_WRQ:
+ if (priv->push || priv->is_getattr)
+ /* atm, windowsize is supported only for RRQ and there
+ is no need to request a full window when we are
+ just looking up file attributes */
+ window_size = 1;
+ else
+ window_size = min_t(unsigned int, g_tftp_window_size,
+ TFTP_MAX_WINDOW_SIZE);
+
xp = pkt;
s = (uint16_t *)pkt;
if (priv->state == STATE_RRQ)
@@ -131,30 +230,42 @@ static int tftp_send(struct file_priv *priv)
"octet%c"
"timeout%c"
"%d%c"
- "tsize%c"
- "%lld%c"
"blksize%c"
- "1432",
- priv->filename + 1, 0,
- 0,
- 0,
- TIMEOUT, 0,
- 0,
- priv->filesize, 0,
- 0);
+ "%u",
+ priv->filename + 1, '\0',
+ '\0', /* "octet" */
+ '\0', /* "timeout" */
+ TIMEOUT, '\0',
+ '\0', /* "blksize" */
+ /* use only a minimal blksize for getattr
+ operations, */
+ priv->is_getattr ? TFTP_BLOCK_SIZE : TFTP_MTU_SIZE);
pkt++;
+
+ if (!priv->push)
+ /* we do not know the filesize in WRQ requests and
+ 'priv->filesize' will always be zero */
+ pkt += sprintf((unsigned char *)pkt,
+ "tsize%c%lld%c",
+ '\0', priv->filesize,
+ '\0');
+
+ if (window_size > 1)
+ pkt += sprintf((unsigned char *)pkt,
+ "windowsize%c%u%c",
+ '\0', window_size,
+ '\0');
+
len = pkt - xp;
break;
case STATE_RDATA:
- if (priv->block == priv->block_requested)
- return 0;
- case STATE_OACK:
xp = pkt;
s = (uint16_t *)pkt;
*s++ = htons(TFTP_ACK);
- *s++ = htons(priv->block);
- priv->block_requested = priv->block;
+ *s++ = htons(priv->last_block);
+ priv->ack_block = priv->last_block;
+ priv->ack_block += priv->windowsize;
pkt = (unsigned char *)s;
len = pkt - xp;
break;
@@ -197,7 +308,6 @@ static int tftp_poll(struct file_priv *priv)
if (is_timeout(priv->resend_timeout, TFTP_RESEND_TIMEOUT)) {
printf("T ");
priv->resend_timeout = get_time_ns();
- priv->block_requested = -1;
return TFTP_ERR_RESEND;
}
@@ -212,7 +322,7 @@ static int tftp_poll(struct file_priv *priv)
return 0;
}
-static void tftp_parse_oack(struct file_priv *priv, unsigned char *pkt, int len)
+static int tftp_parse_oack(struct file_priv *priv, unsigned char *pkt, int len)
{
unsigned char *opt, *val, *s;
@@ -229,14 +339,25 @@ static void tftp_parse_oack(struct file_priv *priv, unsigned char *pkt, int len)
opt = s;
val = s + strlen(s) + 1;
if (val > s + len)
- return;
+ break;
if (!strcmp(opt, "tsize"))
priv->filesize = simple_strtoull(val, NULL, 10);
if (!strcmp(opt, "blksize"))
priv->blocksize = simple_strtoul(val, NULL, 10);
+ if (!strcmp(opt, "windowsize"))
+ priv->windowsize = simple_strtoul(val, NULL, 10);
pr_debug("OACK opt: %s val: %s\n", opt, val);
s = val + strlen(val) + 1;
}
+
+ if (priv->blocksize > TFTP_MTU_SIZE ||
+ priv->windowsize > TFTP_MAX_WINDOW_SIZE ||
+ priv->windowsize == 0) {
+ pr_warn("tftp: invalid oack response\n");
+ return -EINVAL;
+ }
+
+ return 0;
}
static void tftp_timer_reset(struct file_priv *priv)
@@ -244,10 +365,140 @@ static void tftp_timer_reset(struct file_priv *priv)
priv->progress_timeout = priv->resend_timeout = get_time_ns();
}
+static int tftp_allocate_transfer(struct file_priv *priv)
+{
+ debug_assert(!priv->fifo);
+ debug_assert(!priv->buf);
+
+ /* multiplication is safe; both operands were checked in tftp_parse_oack()
+ and are small integers */
+ priv->fifo = kfifo_alloc(priv->blocksize *
+ (priv->windowsize + TFTP_EXTRA_BLOCKS));
+ if (!priv->fifo)
+ goto err;
+
+ if (priv->push) {
+ priv->buf = xmalloc(priv->blocksize);
+ if (!priv->buf) {
+ kfifo_free(priv->fifo);
+ priv->fifo = NULL;
+ goto err;
+ }
+ }
+
+ INIT_LIST_HEAD(&priv->cache.blocks);
+
+ return 0;
+
+err:
+ priv->err = -ENOMEM;
+ priv->state = STATE_DONE;
+
+ return priv->err;
+}
+
+static void tftp_put_data(struct file_priv *priv, uint16_t block,
+ void const *pkt, size_t len)
+{
+ unsigned int sz;
+
+ if (len > priv->blocksize) {
+ pr_warn("tftp: oversized packet (%zu > %d) received\n",
+ len, priv->blocksize);
+ return;
+ }
+
+ priv->last_block = block;
+
+ sz = kfifo_put(priv->fifo, pkt, len);
+
+ if (sz != len) {
+ pr_err("tftp: not enough room in kfifo (only %u out of %zu written)\n",
+ sz, len);
+ priv->err = -ENOMEM;
+ priv->state = STATE_DONE;
+ } else if (len < priv->blocksize) {
+ tftp_send(priv);
+ priv->err = 0;
+ priv->state = STATE_DONE;
+ }
+}
+
+static void tftp_apply_window_cache(struct file_priv *priv)
+{
+ struct tftp_cache *cache = &priv->cache;
+
+ while (1) {
+ struct tftp_block *block;
+
+ /* can be changed by tftp_put_data() below and must be
+ checked in each loop */
+ if (priv->state != STATE_RDATA)
+ return;
+
+ if (list_empty(&cache->blocks))
+ return;
+
+ block = list_first_entry(&cache->blocks, struct tftp_block, list);
+
+ if (is_block_before(block->id, priv->last_block + 1)) {
+ /* shouldn't happen, but be sure */
+ list_del(&block->list);
+ free(block);
+ continue;
+ }
+
+ if (block->id != (uint16_t)(priv->last_block + 1))
+ return;
+
+ tftp_put_data(priv, block->id, block->data, block->len);
+
+ list_del(&block->list);
+
+ free(block);
+ }
+}
+
+static void tftp_handle_data(struct file_priv *priv, uint16_t block,
+ void const *data, size_t len)
+{
+ uint16_t exp_block;
+ int rc;
+
+ exp_block = priv->last_block + 1;
+
+ if (exp_block == block) {
+ /* datagram over network is the expected one; put it in the
+ fifo directly and try to apply cached items then */
+ tftp_timer_reset(priv);
+ tftp_put_data(priv, block, data, len);
+ tftp_apply_window_cache(priv);
+ } else if (!in_window(block, exp_block, priv->ack_block)) {
+ /* completely unexpected and unrelated to actual window;
+ ignore the packet. */
+ printf("B");
+ if (g_tftp_window_size > 1)
+ pr_warn_once("Unexpected packet. global.tftp.windowsize set too high?\n");
+ } else {
+ /* The 'rc < 0' below happens e.g. when datagrams in the first
+ part of the transfer window are dropped.
+
+ TODO: this will usually result in a timeout
+ (TFTP_RESEND_TIMEOUT). It should be possible to bypass
+ this timeout by acknowledging the last packet (e.g. by
+ doing 'priv->ack_block = priv->last_block' here). */
+ rc = tftp_window_cache_insert(&priv->cache, block, data, len);
+ if (rc < 0)
+ printf("M");
+ }
+}
+
static void tftp_recv(struct file_priv *priv,
uint8_t *pkt, unsigned len, uint16_t uh_sport)
{
uint16_t opcode;
+ uint16_t block;
+ int rc;
/* according to RFC1350 minimal tftp packet length is 4 bytes */
if (len < 4)
@@ -270,75 +521,80 @@ static void tftp_recv(struct file_priv *priv,
if (!priv->push)
break;
- priv->block = ntohs(*(uint16_t *)pkt);
- if (priv->block != priv->last_block) {
- pr_vdebug("ack %d != %d\n", priv->block, priv->last_block);
+ block = ntohs(*(uint16_t *)pkt);
+ if (block != priv->last_block) {
+ pr_vdebug("ack %d != %d\n", block, priv->last_block);
break;
}
- priv->block++;
+ switch (priv->state) {
+ case STATE_WRQ:
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ priv->state = STATE_START;
+ break;
- tftp_timer_reset(priv);
+ case STATE_WAITACK:
+ priv->state = STATE_WDATA;
+ break;
- if (priv->state == STATE_LAST) {
+ case STATE_LAST:
priv->state = STATE_DONE;
break;
+
+ default:
+ pr_warn("ACK packet in %s state\n",
+ tftp_states[priv->state]);
+ goto ack_out;
}
- priv->tftp_con->udp->uh_dport = uh_sport;
- priv->state = STATE_WDATA;
+
+ priv->block = block + 1;
+ tftp_timer_reset(priv);
+
+ ack_out:
break;
case TFTP_OACK:
- tftp_parse_oack(priv, pkt, len);
+ if (priv->state != STATE_RRQ && priv->state != STATE_WRQ) {
+ pr_warn("OACK packet in %s state\n",
+ tftp_states[priv->state]);
+ break;
+ }
+
priv->tftp_con->udp->uh_dport = uh_sport;
- if (priv->push) {
- /* send first block */
- priv->state = STATE_WDATA;
- priv->block = 1;
- } else {
- /* send ACK */
- priv->state = STATE_OACK;
- priv->block = 0;
- tftp_send(priv);
+ if (tftp_parse_oack(priv, pkt, len) < 0) {
+ priv->err = -EINVAL;
+ priv->state = STATE_DONE;
+ break;
}
+ priv->state = STATE_START;
break;
+
case TFTP_DATA:
len -= 2;
- priv->block = ntohs(*(uint16_t *)pkt);
+ block = ntohs(*(uint16_t *)pkt);
- if (priv->state == STATE_RRQ || priv->state == STATE_OACK) {
- /* first block received */
- priv->state = STATE_RDATA;
+ if (priv->state == STATE_RRQ) {
+ /* first block received; entered only with non rfc
+ 2347 (TFTP Option extension) compliant servers */
priv->tftp_con->udp->uh_dport = uh_sport;
+ priv->state = STATE_RDATA;
priv->last_block = 0;
+ priv->ack_block = priv->windowsize;
- if (priv->block != 1) { /* Assertion */
- pr_err("error: First block is not block 1 (%d)\n",
- priv->block);
- priv->err = -EINVAL;
- priv->state = STATE_DONE;
+ rc = tftp_allocate_transfer(priv);
+ if (rc < 0)
break;
- }
}
- if (priv->block == priv->last_block)
- /* Same block again; ignore it. */
+ if (priv->state != STATE_RDATA) {
+ pr_warn("DATA packet in %s state\n",
+ tftp_states[priv->state]);
break;
-
- priv->last_block = priv->block;
-
- tftp_timer_reset(priv);
-
- kfifo_put(priv->fifo, pkt + 2, len);
-
- if (len < priv->blocksize) {
- tftp_send(priv);
- priv->err = 0;
- priv->state = STATE_DONE;
}
+ tftp_handle_data(priv, block, pkt + 2, len);
break;
case TFTP_ERROR:
@@ -369,13 +625,39 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
tftp_recv(priv, pkt, net_eth_to_udplen(packet), udp->uh_sport);
}
-static struct file_priv *tftp_do_open(struct device_d *dev,
- int accmode, struct dentry *dentry)
+static int tftp_start_transfer(struct file_priv *priv)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ int rc;
+
+ rc = tftp_allocate_transfer(priv);
+ if (rc < 0)
+ /* function sets 'priv->state = STATE_DONE' and 'priv->err' in
+ error case */
+ return rc;
+
+ if (priv->push) {
+ /* send first block */
+ priv->state = STATE_WDATA;
+ priv->block = 1;
+ } else {
+ /* send ACK */
+ priv->state = STATE_RDATA;
+ priv->last_block = 0;
+ tftp_send(priv);
+ }
+
+ return 0;
+}
+
+static struct file_priv *tftp_do_open(struct device *dev,
+ int accmode, struct dentry *dentry,
+ bool is_getattr)
+{
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct file_priv *priv;
struct tftp_priv *tpriv = dev->priv;
int ret;
+ unsigned short port = TFTP_PORT;
priv = xzalloc(sizeof(*priv));
@@ -397,59 +679,87 @@ static struct file_priv *tftp_do_open(struct device_d *dev,
priv->err = -EINVAL;
priv->filename = dpath(dentry, fsdev->vfsmount.mnt_root);
priv->blocksize = TFTP_BLOCK_SIZE;
- priv->block_requested = -1;
+ priv->windowsize = 1;
+ priv->is_getattr = is_getattr;
- priv->fifo = kfifo_alloc(TFTP_FIFO_SIZE);
- if (!priv->fifo) {
- ret = -ENOMEM;
- goto out;
- }
+ parseopt_hu(fsdev->options, "port", &port);
- priv->tftp_con = net_udp_new(tpriv->server, TFTP_PORT, tftp_handler,
- priv);
+ priv->tftp_con = net_udp_new(tpriv->server, port, tftp_handler, priv);
if (IS_ERR(priv->tftp_con)) {
ret = PTR_ERR(priv->tftp_con);
- goto out1;
+ goto out;
}
ret = tftp_send(priv);
if (ret)
- goto out2;
+ goto out1;
tftp_timer_reset(priv);
- while (priv->state != STATE_RDATA &&
- priv->state != STATE_DONE &&
- priv->state != STATE_WDATA) {
- ret = tftp_poll(priv);
- if (ret == TFTP_ERR_RESEND)
- tftp_send(priv);
- if (ret < 0)
- goto out2;
- }
- if (priv->state == STATE_DONE && priv->err) {
- ret = priv->err;
- goto out2;
- }
+ /* - 'ret < 0' ... error
+ - 'ret == 0' ... further tftp_poll() required
+ - 'ret == 1' ... startup finished */
+ do {
+ switch (priv->state) {
+ case STATE_DONE:
+ /* branch is entered in two situations:
+ - non rfc 2347 compliant servers finished the
+ transfer by sending a small file
+ - some error occurred */
+ if (priv->err < 0)
+ ret = priv->err;
+ else
+ ret = 1;
+ break;
- priv->buf = xmalloc(priv->blocksize);
+ case STATE_START:
+ ret = tftp_start_transfer(priv);
+ if (!ret)
+ ret = 1;
+ break;
+
+ case STATE_RDATA:
+ /* first data block of non rfc 2347 servers */
+ ret = 1;
+ break;
+
+ case STATE_RRQ:
+ case STATE_WRQ:
+ ret = tftp_poll(priv);
+ if (ret == TFTP_ERR_RESEND) {
+ tftp_send(priv);
+ ret = 0;
+ }
+ break;
+
+ default:
+ debug_assert(false);
+ break;
+ }
+ } while (ret == 0);
+
+ if (ret < 0)
+ goto out1;
return priv;
-out2:
- net_unregister(priv->tftp_con);
out1:
- kfifo_free(priv->fifo);
+ net_unregister(priv->tftp_con);
out:
+ if (priv->fifo)
+ kfifo_free(priv->fifo);
+
+ free(priv->filename);
+ free(priv->buf);
free(priv);
return ERR_PTR(ret);
}
-static int tftp_open(struct device_d *dev, FILE *file, const char *filename)
+static int tftp_open(struct device *dev, FILE *file, const char *filename)
{
struct file_priv *priv;
- priv = tftp_do_open(dev, file->flags, file->dentry);
+ priv = tftp_do_open(dev, file->flags, file->dentry, false);
if (IS_ERR(priv))
return PTR_ERR(priv);
@@ -489,6 +799,7 @@ static int tftp_do_close(struct file_priv *priv)
}
net_unregister(priv->tftp_con);
+ tftp_window_cache_free(&priv->cache);
kfifo_free(priv->fifo);
free(priv->filename);
free(priv->buf);
@@ -497,15 +808,15 @@ static int tftp_do_close(struct file_priv *priv)
return 0;
}
-static int tftp_close(struct device_d *dev, FILE *f)
+static int tftp_close(struct device *dev, FILE *f)
{
struct file_priv *priv = f->priv;
return tftp_do_close(priv);
}
-static int tftp_write(struct device_d *_dev, FILE *f, const void *inbuf,
- size_t insize)
+static int tftp_write(struct device *_dev, FILE *f, const void *inbuf,
+ size_t insize)
{
struct file_priv *priv = f->priv;
size_t size, now;
@@ -540,11 +851,11 @@ static int tftp_write(struct device_d *_dev, FILE *f, const void *inbuf,
return insize;
}
-static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
+static int tftp_read(struct device *dev, FILE *f, void *buf, size_t insize)
{
struct file_priv *priv = f->priv;
size_t outsize = 0, now;
- int ret;
+ int ret = 0;
pr_vdebug("%s %zu\n", __func__, insize);
@@ -553,23 +864,34 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
outsize += now;
buf += now;
insize -= now;
- if (priv->state == STATE_DONE)
- return outsize;
- if (TFTP_FIFO_SIZE - kfifo_len(priv->fifo) >= priv->blocksize)
+ if (priv->state == STATE_DONE) {
+ ret = priv->err;
+ break;
+ }
+
+ /* send the ACK only when fifo has been nearly depleted; else,
+ when tftp_read() is called with small 'insize' values, it
+ is possible that there is read more data from the network
+ than consumed by kfifo_get() and the fifo overflows */
+ if (priv->last_block == priv->ack_block &&
+ kfifo_len(priv->fifo) <= TFTP_EXTRA_BLOCKS * priv->blocksize)
tftp_send(priv);
ret = tftp_poll(priv);
if (ret == TFTP_ERR_RESEND)
tftp_send(priv);
if (ret < 0)
- return ret;
+ break;
}
+ if (ret < 0)
+ return ret;
+
return outsize;
}
-static int tftp_lseek(struct device_d *dev, FILE *f, loff_t pos)
+static int tftp_lseek(struct device *dev, FILE *f, loff_t pos)
{
/* We cannot seek backwards without reloading or caching the file */
loff_t f_pos = f->pos;
@@ -660,12 +982,12 @@ static struct dentry *tftp_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct inode *inode;
struct file_priv *priv;
loff_t filesize;
- priv = tftp_do_open(&fsdev->dev, O_RDONLY, dentry);
+ priv = tftp_do_open(&fsdev->dev, O_RDONLY, dentry, true);
if (IS_ERR(priv))
return NULL;
@@ -695,9 +1017,9 @@ static const struct inode_operations tftp_dir_inode_operations =
static const struct super_operations tftp_ops;
-static int tftp_probe(struct device_d *dev)
+static int tftp_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct tftp_priv *priv = xzalloc(sizeof(struct tftp_priv));
struct super_block *sb = &fsdev->sb;
struct inode *inode;
@@ -724,14 +1046,14 @@ err:
return ret;
}
-static void tftp_remove(struct device_d *dev)
+static void tftp_remove(struct device *dev)
{
struct tftp_priv *priv = dev->priv;
free(priv);
}
-static struct fs_driver_d tftp_driver = {
+static struct fs_driver tftp_driver = {
.open = tftp_open,
.close = tftp_close,
.read = tftp_read,
@@ -748,6 +1070,8 @@ static struct fs_driver_d tftp_driver = {
static int tftp_init(void)
{
+ globalvar_add_simple_int("tftp.windowsize", &g_tftp_window_size, "%u");
+
return register_fs_driver(&tftp_driver);
}
coredevice_initcall(tftp_init);
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index 889a2be97a..15fcec4459 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig FS_UBIFS
bool
depends on MTD_UBI
@@ -15,4 +17,9 @@ config FS_UBIFS_COMPRESSION_ZLIB
select ZLIB
prompt "ZLIB compression support"
+config FS_UBIFS_COMPRESSION_ZSTD
+ bool
+ select ZSTD_DECOMPRESS
+ prompt "ZSTD compression support"
+
endif
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index d8c4b2299e..7a1ce4e8fc 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += ubifs.o io.o super.o sb.o master.o
obj-y += scan.o dir.o misc.o
obj-y += tnc.o tnc_misc.o debug.o
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index ea88926163..113c2cf755 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -244,7 +244,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
if (len > 8192)
len = 8192;
ubifs_err(c, "first %d bytes from LEB %d:%d", len, lnum, offs);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
+ print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
}
/**
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b48e21fae6..564ac950eb 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -86,11 +86,6 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
return 1;
}
- if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
- ubifs_err(c, "unknown compression type %d", ui->compr_type);
- return 2;
- }
-
if (ui->xattr_names + ui->xattr_cnt > XATTR_LIST_MAX)
return 3;
@@ -1212,9 +1207,10 @@ out_shrinker:
/* late_initcall to let compressors initialize first */
late_initcall(ubifs_init);
-int ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent)
+int ubifs_get_super(struct device *dev, struct ubi_volume_desc *ubi,
+ int silent)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct super_block *sb;
struct ubifs_info *c;
int err;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 2d7327ad84..72f9b817d8 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1935,7 +1935,12 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
do {
ubifs_assert(c, !ubifs_zn_obsolete(znode));
- ubifs_assert(c, ubifs_zn_dirty(znode));
+ /*
+ * This assertion is invalid in barebox due to the shortcuts we take
+ * in our readonly implementation.
+ *
+ * ubifs_assert(c, ubifs_zn_dirty(znode));
+ */
zp = znode->parent;
n = znode->iip;
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
index 8b7c184401..697b1b8906 100644
--- a/fs/ubifs/ubifs-media.h
+++ b/fs/ubifs/ubifs-media.h
@@ -348,12 +348,14 @@ enum {
* UBIFS_COMPR_NONE: no compression
* UBIFS_COMPR_LZO: LZO compression
* UBIFS_COMPR_ZLIB: ZLIB compression
+ * UBIFS_COMPR_ZSTD: ZSTD compression
* UBIFS_COMPR_TYPES_CNT: count of supported compression types
*/
enum {
UBIFS_COMPR_NONE,
UBIFS_COMPR_LZO,
UBIFS_COMPR_ZLIB,
+ UBIFS_COMPR_ZSTD,
UBIFS_COMPR_TYPES_CNT,
};
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index fd35619246..ad288f4daa 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -19,14 +19,13 @@
#include <magicvar.h>
#include <linux/stat.h>
#include <linux/zlib.h>
+#include <linux/zstd.h>
#include <linux/mtd/mtd.h>
#include "ubifs.h"
#include <linux/err.h>
-struct task_struct *current;
-
struct ubifs_priv {
struct cdev *cdev;
struct ubi_volume_desc *ubi;
@@ -35,6 +34,7 @@ struct ubifs_priv {
static struct z_stream_s ubifs_zlib_stream;
+static ZSTD_DCtx *ubifs_zstd_cctx;
/* compress.c */
@@ -46,7 +46,30 @@ static struct z_stream_s ubifs_zlib_stream;
static int gzip_decompress(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{
- return deflate_decompress(&ubifs_zlib_stream, in, in_len, out, out_len);
+ unsigned int olen;
+ int ret;
+
+ ret = deflate_decompress(&ubifs_zlib_stream, in, in_len, out, &olen);
+
+ *out_len = olen;
+
+ return ret;
+}
+#endif
+
+#if defined(CONFIG_ZSTD_DECOMPRESS)
+static int zstd_decompress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ size_t olen;
+
+ olen = ZSTD_decompressDCtx(ubifs_zstd_cctx, out, *out_len, in, in_len);
+ if (ZSTD_isError(olen))
+ return -EINVAL;
+
+ *out_len = olen;
+
+ return 0;
}
#endif
@@ -76,6 +99,15 @@ static struct ubifs_compressor zlib_compr = {
#endif
};
+static struct ubifs_compressor zstd_compr = {
+ .compr_type = UBIFS_COMPR_ZSTD,
+ .name = "zstd",
+#ifdef CONFIG_ZSTD_DECOMPRESS
+ .capi_name = "zstd",
+ .decompress = zstd_decompress,
+#endif
+};
+
/* All UBIFS compressors */
struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
@@ -100,7 +132,8 @@ static inline struct crypto_comp
i++;
continue;
}
- if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
+ if (comp->capi_name &&
+ strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
ptr->compressor = i;
return ptr;
}
@@ -240,6 +273,10 @@ int __init ubifs_compressors_init(void)
if (err)
return err;
+ err = compr_init(&zstd_compr);
+ if (err)
+ return err;
+
err = compr_init(&none_compr);
if (err)
return err;
@@ -303,7 +340,7 @@ struct ubifs_file {
struct ubifs_data_node *dn;
};
-static int ubifs_open(struct device_d *dev, FILE *file, const char *filename)
+static int ubifs_open(struct device *dev, FILE *file, const char *filename)
{
struct inode *inode = file->f_inode;
struct ubifs_file *uf;
@@ -321,7 +358,7 @@ static int ubifs_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int ubifs_close(struct device_d *dev, FILE *f)
+static int ubifs_close(struct device *dev, FILE *f)
{
struct ubifs_file *uf = f->priv;
@@ -347,7 +384,7 @@ static int ubifs_get_block(struct ubifs_file *uf, unsigned int pos)
return 0;
}
-static int ubifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+static int ubifs_read(struct device *_dev, FILE *f, void *buf, size_t insize)
{
struct ubifs_file *uf = f->priv;
unsigned int pos = f->pos;
@@ -394,7 +431,8 @@ static int ubifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
return insize;
}
-static void ubifs_set_rootarg(struct ubifs_priv *priv, struct fs_device_d *fsdev)
+static void ubifs_set_rootarg(struct ubifs_priv *priv,
+ struct fs_device *fsdev)
{
struct ubi_volume_info vi = {};
struct ubi_device_info di = {};
@@ -414,9 +452,9 @@ static void ubifs_set_rootarg(struct ubifs_priv *priv, struct fs_device_d *fsdev
free(str);
}
-static int ubifs_probe(struct device_d *dev)
+static int ubifs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct ubifs_priv *priv = xzalloc(sizeof(struct ubifs_priv));
int ret;
@@ -430,8 +468,7 @@ static int ubifs_probe(struct device_d *dev)
priv->ubi = ubi_open_volume_cdev(priv->cdev, UBI_READONLY);
if (IS_ERR(priv->ubi)) {
- dev_err(dev, "failed to open ubi volume: %s\n",
- strerrorp(priv->ubi));
+ dev_err(dev, "failed to open ubi volume: %pe\n", priv->ubi);
ret = PTR_ERR(priv->ubi);
goto err_free;
}
@@ -452,7 +489,7 @@ err_free:
return ret;
}
-static void ubifs_remove(struct device_d *dev)
+static void ubifs_remove(struct device *dev)
{
struct ubifs_priv *priv = dev->priv;
struct super_block *sb = priv->sb;
@@ -466,7 +503,7 @@ static void ubifs_remove(struct device_d *dev)
free(priv);
}
-static struct fs_driver_d ubifs_driver = {
+static struct fs_driver ubifs_driver = {
.open = ubifs_open,
.close = ubifs_close,
.read = ubifs_read,
@@ -495,6 +532,21 @@ static int zlib_decomp_init(void)
return 0;
}
+static int zstd_decomp_init(void)
+{
+ const size_t wksp_size = ZSTD_DCtxWorkspaceBound();
+ void *wksp = malloc(wksp_size);
+
+ if (!wksp)
+ return -ENOMEM;
+
+ ubifs_zstd_cctx = ZSTD_initDCtx(wksp, wksp_size);
+ if (!ubifs_zstd_cctx)
+ return -EINVAL;
+
+ return 0;
+}
+
int ubifs_allow_encrypted;
int ubifs_allow_authenticated_unauthenticated;
@@ -508,6 +560,12 @@ static int ubifs_init(void)
return ret;
}
+ if (IS_ENABLED(CONFIG_ZSTD_DECOMPRESS)) {
+ ret = zstd_decomp_init();
+ if (ret)
+ return ret;
+ }
+
globalvar_add_simple_bool("ubifs.allow_encrypted", &ubifs_allow_encrypted);
globalvar_add_simple_bool("ubifs.allow_authenticated_unauthenticated",
&ubifs_allow_authenticated_unauthenticated);
@@ -517,8 +575,7 @@ static int ubifs_init(void)
coredevice_initcall(ubifs_init);
-BAREBOX_MAGICVAR_NAMED(global_ubifs_allow_encrypted, global.ubifs.allow_encrypted,
- "If true, allow to mount UBIFS with encrypted files");
-BAREBOX_MAGICVAR_NAMED(global_ubifs_allow_authenticated_unauthenticated,
- global.ubifs.allow_authenticated_unauthenticated,
- "If true, allow to mount authenticated UBIFS images without doing authentication");
+BAREBOX_MAGICVAR(global.ubifs.allow_encrypted,
+ "If true, allow to mount UBIFS with encrypted files");
+BAREBOX_MAGICVAR(global.ubifs.allow_authenticated_unauthenticated,
+ "If true, allow to mount authenticated UBIFS images without doing authentication");
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index bffaa26fb3..598614efea 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1512,7 +1512,7 @@ struct ubifs_info {
struct rb_root size_tree;
struct ubifs_mount_opts mount_opts;
- struct device_d *dev;
+ struct device *dev;
struct ubifs_debug_info *dbg;
};
@@ -2060,7 +2060,8 @@ int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
/* barebox specific */
void ubifs_umount(struct ubifs_info *c);
/* barebox specific */
-int ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent);
+int ubifs_get_super(struct device *dev, struct ubi_volume_desc *ubi,
+ int silent);
#ifndef CONFIG_UBIFS_FS_ENCRYPTION
static inline int ubifs_encrypt(const struct inode *inode,
diff --git a/fs/ubootvarfs.c b/fs/ubootvarfs.c
index 475e4b7a79..32cf574e57 100644
--- a/fs/ubootvarfs.c
+++ b/fs/ubootvarfs.c
@@ -148,7 +148,7 @@ static struct dentry *ubootvarfs_lookup(struct inode *dir,
unsigned int flags)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct ubootvarfs_data *data = fsdev->dev.priv;
struct ubootvarfs_var *var;
struct inode *inode;
@@ -259,6 +259,7 @@ static int ubootvarfs_unlink(struct inode *dir, struct dentry *dentry)
list_del(&var->list);
free(var);
+ node->var = NULL;
}
return simple_unlink(dir, dentry);
@@ -268,7 +269,7 @@ static int ubootvarfs_create(struct inode *dir, struct dentry *dentry,
umode_t mode)
{
struct super_block *sb = dir->i_sb;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct ubootvarfs_data *data = fsdev->dev.priv;
struct inode *inode;
struct ubootvarfs_var *var;
@@ -310,7 +311,7 @@ static const struct inode_operations ubootvarfs_dir_inode_operations = {
static struct inode *ubootvarfs_alloc_inode(struct super_block *sb)
{
struct ubootvarfs_inode *node;
- struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+ struct fs_device *fsdev = container_of(sb, struct fs_device, sb);
struct ubootvarfs_data *data = fsdev->dev.priv;
node = xzalloc(sizeof(*node));
@@ -332,7 +333,7 @@ static const struct super_operations ubootvarfs_ops = {
.destroy_inode = ubootvarfs_destroy_inode,
};
-static int ubootvarfs_io(struct device_d *dev, FILE *f, void *buf,
+static int ubootvarfs_io(struct device *dev, FILE *f, void *buf,
size_t insize, bool read)
{
struct inode *inode = f->f_inode;
@@ -347,19 +348,19 @@ static int ubootvarfs_io(struct device_d *dev, FILE *f, void *buf,
return insize;
}
-static int ubootvarfs_read(struct device_d *dev, FILE *f, void *buf,
+static int ubootvarfs_read(struct device *dev, FILE *f, void *buf,
size_t insize)
{
return ubootvarfs_io(dev, f, buf, insize, true);
}
-static int ubootvarfs_write(struct device_d *dev, FILE *f, const void *buf,
+static int ubootvarfs_write(struct device *dev, FILE *f, const void *buf,
size_t insize)
{
return ubootvarfs_io(dev, f, (void *)buf, insize, false);
}
-static int ubootvarfs_truncate(struct device_d *dev, FILE *f, loff_t size)
+static int ubootvarfs_truncate(struct device *dev, FILE *f, loff_t size)
{
struct inode *inode = f->f_inode;
struct ubootvarfs_inode *node = inode_to_node(inode);
@@ -422,11 +423,11 @@ static void ubootvarfs_parse(struct ubootvarfs_data *data, char *blob,
data->end = blob;
}
-static int ubootvarfs_probe(struct device_d *dev)
+static int ubootvarfs_probe(struct device *dev)
{
struct inode *inode;
struct ubootvarfs_data *data = xzalloc(sizeof(*data));
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct super_block *sb = &fsdev->sb;
struct stat s;
void *map;
@@ -471,7 +472,7 @@ free_data:
return ret;
}
-static void ubootvarfs_remove(struct device_d *dev)
+static void ubootvarfs_remove(struct device *dev)
{
struct ubootvarfs_data *data = dev->priv;
@@ -480,7 +481,7 @@ static void ubootvarfs_remove(struct device_d *dev)
free(data);
}
-static struct fs_driver_d ubootvarfs_driver = {
+static struct fs_driver ubootvarfs_driver = {
.truncate = ubootvarfs_truncate,
.read = ubootvarfs_read,
.write = ubootvarfs_write,
diff --git a/fs/uimagefs.c b/fs/uimagefs.c
index 72641c58b5..735a35e500 100644
--- a/fs/uimagefs.c
+++ b/fs/uimagefs.c
@@ -9,7 +9,6 @@
#include <fs.h>
#include <errno.h>
#include <fcntl.h>
-#include <fs.h>
#include <malloc.h>
#include <init.h>
#include <linux/stat.h>
@@ -69,7 +68,7 @@ static struct uimagefs_handle_data *uimagefs_get_by_name(
return NULL;
}
-static int uimagefs_open(struct device_d *dev, FILE *file, const char *filename)
+static int uimagefs_open(struct device *dev, FILE *file, const char *filename)
{
struct uimagefs_handle *priv = dev->priv;
struct uimagefs_handle_data *d;
@@ -95,7 +94,7 @@ static int uimagefs_open(struct device_d *dev, FILE *file, const char *filename)
return 0;
}
-static int uimagefs_close(struct device_d *dev, FILE *file)
+static int uimagefs_close(struct device *dev, FILE *file)
{
struct uimagefs_handle_data *d = file->priv;
@@ -104,7 +103,8 @@ static int uimagefs_close(struct device_d *dev, FILE *file)
return 0;
}
-static int uimagefs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
+static int uimagefs_read(struct device *dev, FILE *file, void *buf,
+ size_t insize)
{
struct uimagefs_handle_data *d = file->priv;
@@ -116,7 +116,7 @@ static int uimagefs_read(struct device_d *dev, FILE *file, void *buf, size_t ins
}
}
-static int uimagefs_lseek(struct device_d *dev, FILE *file, loff_t pos)
+static int uimagefs_lseek(struct device *dev, FILE *file, loff_t pos)
{
struct uimagefs_handle_data *d = file->priv;
@@ -128,7 +128,7 @@ static int uimagefs_lseek(struct device_d *dev, FILE *file, loff_t pos)
return 0;
}
-static DIR *uimagefs_opendir(struct device_d *dev, const char *pathname)
+static DIR *uimagefs_opendir(struct device *dev, const char *pathname)
{
struct uimagefs_handle *priv = dev->priv;
DIR *dir;
@@ -143,7 +143,7 @@ static DIR *uimagefs_opendir(struct device_d *dev, const char *pathname)
return dir;
}
-static struct dirent *uimagefs_readdir(struct device_d *dev, DIR *dir)
+static struct dirent *uimagefs_readdir(struct device *dev, DIR *dir)
{
struct uimagefs_handle *priv = dev->priv;
struct uimagefs_handle_data *d = dir->priv;
@@ -156,13 +156,14 @@ static struct dirent *uimagefs_readdir(struct device_d *dev, DIR *dir)
return &dir->d;
}
-static int uimagefs_closedir(struct device_d *dev, DIR *dir)
+static int uimagefs_closedir(struct device *dev, DIR *dir)
{
free(dir);
return 0;
}
-static int uimagefs_stat(struct device_d *dev, const char *filename, struct stat *s)
+static int uimagefs_stat(struct device *dev, const char *filename,
+ struct stat *s)
{
struct uimagefs_handle *priv = dev->priv;
struct uimagefs_handle_data *d;
@@ -180,7 +181,7 @@ static int uimagefs_stat(struct device_d *dev, const char *filename, struct stat
return 0;
}
-static int uimagefs_ioctl(struct device_d *dev, FILE *f, int request, void *buf)
+static int uimagefs_ioctl(struct device *dev, FILE *f, int request, void *buf)
{
struct uimagefs_handle *priv = dev->priv;
@@ -192,7 +193,7 @@ static int uimagefs_ioctl(struct device_d *dev, FILE *f, int request, void *buf)
return 0;
}
-static void uimagefs_remove(struct device_d *dev)
+static void uimagefs_remove(struct device *dev)
{
struct uimagefs_handle *priv = dev->priv;
struct uimagefs_handle_data *d, *tmp;
@@ -296,28 +297,24 @@ static int uimagefs_add_data_entry(struct uimagefs_handle *priv, size_t offset,
return 0;
}
-#if defined(CONFIG_TIMESTAMP)
static int uimagefs_add_time(struct uimagefs_handle *priv)
{
struct image_header *header = &priv->header;
- struct rtc_time tm;
- char *val;
- to_tm(header->ih_time, &tm);
- val = basprintf("%4d-%02d-%02d %2d:%02d:%02d UTC",
- tm.tm_year, tm.tm_mon, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
+ if (IS_ENABLED(CONFIG_TIMESTAMP)) {
+ struct rtc_time tm;
+ char *val;
- return uimagefs_add_str(priv, UIMAGEFS_TIME, val);
-}
-#else
-static int uimagefs_add_time(struct uimagefs_handle *priv)
-{
- struct image_header *header = &priv->header;
+ to_tm(header->ih_time, &tm);
+ val = basprintf("%4d-%02d-%02d %2d:%02d:%02d UTC",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ return uimagefs_add_str(priv, UIMAGEFS_TIME, val);
+ }
return uimagefs_add_hex(priv, UIMAGEFS_TIME, header->ih_time);
}
-#endif
static int uimagefs_add_os(struct uimagefs_handle *priv)
{
@@ -374,7 +371,7 @@ static int __uimage_open(struct uimagefs_handle *priv)
fd = open(filename, O_RDONLY);
if (fd < 0) {
- printf("could not open: %s\n", errno_str());
+ printf("could not open: %m\n");
return fd;
}
@@ -382,7 +379,7 @@ static int __uimage_open(struct uimagefs_handle *priv)
ret = read(fd, header, sizeof(*header));
if (ret < 0) {
- printf("could not read: %s\n", errno_str());
+ printf("could not read: %m\n");
goto err_out;
}
offset += sizeof(*header);
@@ -494,9 +491,9 @@ err_out:
return ret;
}
-static int uimagefs_probe(struct device_d *dev)
+static int uimagefs_probe(struct device *dev)
{
- struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct fs_device *fsdev = dev_to_fs_device(dev);
struct uimagefs_handle *priv;
int ret = 0;
@@ -519,7 +516,7 @@ err:
return ret;
}
-static struct fs_driver_d uimagefs_driver = {
+static struct fs_driver uimagefs_driver = {
.open = uimagefs_open,
.close = uimagefs_close,
.read = uimagefs_read,