@@ -7,6 +7,6 @@ obj-y := interface.o stub.o
obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsync.o hash.o ialloc.o \
- indirect.o inode.o \
- super.o xattr_hurd.o xattr_trusted.o \
+ indirect.o inode.o super.o symlink.o \
+ xattr_hurd.o xattr_trusted.o \
xattr_user.o orphan.o
@@ -816,6 +816,7 @@ struct inode {
const struct file_operations *i_fop;
atomic_t i_writecount; /* Count of writers */
struct rw_semaphore i_rwsem; /* inode lock */
+ const char *i_link; /* Symlink target for fast symlinks */
};
/* Inode time accessors */
@@ -916,6 +917,16 @@ static inline u64 fscrypt_fname_siphash(const struct inode *dir,
#define WARN_ON_ONCE(cond) ({ (void)(cond); 0; })
#define WARN_ON(cond) ({ (void)(cond); 0; })
+/* strtomem_pad - copy string to fixed-size buffer with padding */
+#define strtomem_pad(dest, src, pad) do { \
+ size_t _len = strlen(src); \
+ if (_len >= sizeof(dest)) \
+ _len = sizeof(dest); \
+ memcpy(dest, src, _len); \
+ if (_len < sizeof(dest)) \
+ memset((char *)(dest) + _len, (pad), sizeof(dest) - _len); \
+} while (0)
+
/* Memory weight - count set bits */
static inline unsigned long memweight(const void *ptr, size_t bytes)
{
@@ -980,6 +991,14 @@ static inline unsigned long memweight(const void *ptr, size_t bytes)
#define file_modified(file) ({ (void)(file); 0; })
#define file_accessed(file) do { (void)(file); } while (0)
+/* Generic file operations - stubs for file.c */
+#define generic_file_read_iter(iocb, to) ({ (void)(iocb); (void)(to); 0L; })
+#define generic_write_checks(iocb, from) ({ (void)(iocb); (void)(from); 0L; })
+#define generic_perform_write(iocb, from) ({ (void)(iocb); (void)(from); 0L; })
+#define generic_write_sync(iocb, count) ({ (void)(iocb); (count); })
+#define generic_atomic_write_valid(iocb, from) ({ (void)(iocb); (void)(from); 0; })
+#define vfs_setpos(file, offset, maxsize) ({ (void)(file); (void)(maxsize); (offset); })
+
/* Security checks - no security in U-Boot */
#define IS_NOSEC(inode) (1)
@@ -1295,6 +1314,7 @@ typedef unsigned int projid_t;
/* Dentry operations - stubs */
#define d_find_any_alias(i) ({ (void)(i); (struct dentry *)NULL; })
#define dget_parent(d) ({ (void)(d); (struct dentry *)NULL; })
+#define dput(d) do { (void)(d); } while (0)
/* Sync operations - stubs */
#define sync_mapping_buffers(m) ({ (void)(m); 0; })
@@ -1393,6 +1413,7 @@ static inline char *d_path(const struct path *path, char *buf, int buflen)
#define try_to_writeback_inodes_sb(sb, r) do { } while (0)
#define mapping_gfp_constraint(m, g) (g)
#define mapping_set_folio_order_range(m, l, h) do { } while (0)
+#define filemap_splice_read(i, p, pi, l, f) ({ (void)(i); (void)(p); (void)(pi); (void)(l); (void)(f); 0L; })
/* Buffer operations - additional */
#define getblk_unmovable(bd, b, s) ((struct buffer_head *)NULL)
@@ -1512,15 +1533,6 @@ static inline unsigned int i_gid_read(const struct inode *inode)
#define file_update_time(f) do { } while (0)
#define vmf_fs_error(e) ((vm_fault_t)VM_FAULT_SIGBUS)
-/* VFS file operations for file.c */
-#define generic_file_read_iter(iocb, to) ({ (void)(iocb); (void)(to); 0; })
-#define filemap_splice_read(f, p, pipe, l, fl) ({ (void)(f); (void)(p); (void)(pipe); (void)(l); (void)(fl); 0; })
-#define generic_write_checks(iocb, from) ({ (void)(iocb); (void)(from); 0; })
-#define generic_perform_write(iocb, from) ({ (void)(iocb); (void)(from); 0; })
-#define generic_write_sync(iocb, count) ({ (void)(iocb); (count); })
-#define generic_atomic_write_valid(iocb, from) ({ (void)(iocb); (void)(from); true; })
-#define vfs_setpos(file, offset, maxsize) ({ (void)(file); (void)(maxsize); (offset); })
-
/* iomap stubs */
#define iomap_bmap(m, b, o) ({ (void)(m); (void)(b); (void)(o); 0UL; })
#define iomap_swapfile_activate(s, f, sp, o) ({ (void)(s); (void)(f); (void)(sp); (void)(o); -EOPNOTSUPP; })
@@ -1578,8 +1590,30 @@ struct file_operations {
int (*release)(struct inode *, struct file *);
};
+/* delayed_call - for delayed freeing of symlink data */
+typedef void (*delayed_call_func_t)(const void *);
+struct delayed_call {
+ delayed_call_func_t fn;
+ const void *arg;
+};
+
+#define set_delayed_call(dc, func, data) do { \
+ (dc)->fn = (func); \
+ (dc)->arg = (data); \
+} while (0)
+
+#define kfree_link kfree
+
+/* nd_terminate_link - terminate symlink string */
+static inline void nd_terminate_link(void *name, loff_t len, int maxlen)
+{
+ ((char *)name)[min_t(loff_t, len, maxlen)] = '\0';
+}
+
/* inode_operations - for file and directory operations */
struct inode_operations {
+ const char *(*get_link)(struct dentry *, struct inode *,
+ struct delayed_call *);
int (*getattr)(struct mnt_idmap *, const struct path *,
struct kstat *, u32, unsigned int);
ssize_t (*listxattr)(struct dentry *, char *, size_t);
@@ -1596,6 +1630,18 @@ struct inode_operations {
/* file open helper */
#define simple_open(i, f) ({ (void)(i); (void)(f); 0; })
+/* simple_get_link - for fast symlinks stored in inode */
+static inline const char *simple_get_link(struct dentry *dentry,
+ struct inode *inode,
+ struct delayed_call *callback)
+{
+ return inode->i_link;
+}
+
+/* fscrypt symlink stubs */
+#define fscrypt_get_symlink(i, c, m, d) ({ (void)(i); (void)(c); (void)(m); (void)(d); ERR_PTR(-EOPNOTSUPP); })
+#define fscrypt_symlink_getattr(p, s) ({ (void)(p); (void)(s); 0; })
+
/*
* Additional stubs for super.c
*/
@@ -2118,23 +2164,10 @@ void set_task_ioprio(void *task, int ioprio);
/* Dentry operations - declarations for stub.c */
void generic_set_sb_d_ops(struct super_block *sb);
struct dentry *d_make_root(struct inode *inode);
-void dput(void *dentry);
/* String operations - declarations for stub.c */
char *strreplace(const char *str, char old, char new);
-/* strtomem_pad - copy string with padding (Linux kernel macro) */
-#define strtomem_pad(dest, src, pad) do { \
- const char *__src = (src); \
- size_t __len = strlen(__src); \
- if (__len >= sizeof(dest)) { \
- memcpy((dest), __src, sizeof(dest)); \
- } else { \
- memcpy((dest), __src, __len); \
- memset((char *)(dest) + __len, (pad), sizeof(dest) - __len); \
- } \
-} while (0)
-
/* Ratelimit - declaration for stub.c */
void ratelimit_state_init(void *rs, int interval, int burst);
@@ -119,7 +119,8 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
}
#endif
-static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t __maybe_unused ext4_file_read_iter(struct kiocb *iocb,
+ struct iov_iter *to)
{
struct inode *inode = file_inode(iocb->ki_filp);
@@ -139,9 +140,11 @@ static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
return generic_file_read_iter(iocb, to);
}
-static ssize_t ext4_file_splice_read(struct file *in, loff_t *ppos,
- struct pipe_inode_info *pipe,
- size_t len, unsigned int flags)
+static ssize_t __maybe_unused ext4_file_splice_read(struct file *in,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
{
struct inode *inode = file_inode(in);
@@ -682,7 +685,7 @@ out:
}
#endif
-static ssize_t
+static ssize_t __maybe_unused
ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
int ret;
@@ -796,7 +799,7 @@ static const struct vm_operations_struct ext4_file_vm_ops = {
.page_mkwrite = ext4_page_mkwrite,
};
-static int ext4_file_mmap_prepare(struct vm_area_desc *desc)
+static int __maybe_unused ext4_file_mmap_prepare(struct vm_area_desc *desc)
{
int ret;
struct file *file = desc->file;
@@ -429,8 +429,8 @@ int ext4_find_inline_data_nolock(struct inode *inode)
char ext4_dir_inode_operations;
/* ext4_dir_operations is now in dir.c */
char ext4_special_inode_operations;
-char ext4_symlink_inode_operations;
-char ext4_fast_symlink_inode_operations;
+/* ext4_symlink_inode_operations is now in symlink.c */
+/* ext4_fast_symlink_inode_operations is now in symlink.c */
/* ext4_update_dynamic_rev is now in super.c */
@@ -485,6 +485,12 @@ void jbd2_journal_init_jbd_inode(void *jinode, struct inode *inode)
{
}
+/* symlink.c stub */
+void *ext4_read_inline_link(struct inode *inode)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
/*
* Stubs for dir.c
*/
@@ -870,10 +876,7 @@ int ext4_register_sysfs(void *sb)
return 0;
}
-/* dentry put */
-void dput(void *dentry)
-{
-}
+/* dput - now provided as macro in ext4_uboot.h */
/* timer_delete_sync is now a macro in linux/timer.h */
@@ -18,8 +18,7 @@
* ext4 symlink handling code
*/
-#include <linux/fs.h>
-#include <linux/namei.h>
+#include "ext4_uboot.h"
#include "ext4.h"
#include "xattr.h"
@@ -65,9 +64,9 @@ static int ext4_encrypted_symlink_getattr(struct mnt_idmap *idmap,
return fscrypt_symlink_getattr(path, stat);
}
-static void ext4_free_link(void *bh)
+static void ext4_free_link(const void *bh)
{
- brelse(bh);
+ brelse((struct buffer_head *)bh);
}
static const char *ext4_get_link(struct dentry *dentry, struct inode *inode,