* [PATCH] efs: Remove EFS
@ 2026-06-18 21:18 Matthew Wilcox (Oracle)
2026-06-19 9:28 ` Jori Koolstra
2026-06-25 19:42 ` Darrick J. Wong
0 siblings, 2 replies; 7+ messages in thread
From: Matthew Wilcox (Oracle) @ 2026-06-18 21:18 UTC (permalink / raw)
To: Christian Brauner; +Cc: Matthew Wilcox (Oracle), linux-fsdevel
The kernel EFS code has been unmaintained for over twenty years.
It was superseded on IRIX around thirty years ago. I haven't seen an
EFS filesystem in the wild since 1999. Userspace tools to read EFS
filesystems exist, such as https://github.com/jkbenaim/efsextract
There's no benefit to keeping this filesystem in the kernel, and it only
increases the maintenance burden for tree-wide changes.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
MAINTAINERS | 5 -
fs/Kconfig | 1 -
fs/Makefile | 1 -
fs/efs/Kconfig | 16 --
fs/efs/Makefile | 8 -
fs/efs/dir.c | 105 ----------
fs/efs/efs.h | 144 -------------
fs/efs/file.c | 57 -----
fs/efs/inode.c | 315 ----------------------------
fs/efs/namei.c | 120 -----------
fs/efs/super.c | 368 ---------------------------------
fs/efs/symlink.c | 50 -----
include/linux/efs_vh.h | 54 -----
include/uapi/linux/efs_fs_sb.h | 63 ------
14 files changed, 1307 deletions(-)
delete mode 100644 fs/efs/Kconfig
delete mode 100644 fs/efs/Makefile
delete mode 100644 fs/efs/dir.c
delete mode 100644 fs/efs/efs.h
delete mode 100644 fs/efs/file.c
delete mode 100644 fs/efs/inode.c
delete mode 100644 fs/efs/namei.c
delete mode 100644 fs/efs/super.c
delete mode 100644 fs/efs/symlink.c
delete mode 100644 include/linux/efs_vh.h
delete mode 100644 include/uapi/linux/efs_fs_sb.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 629b22c6c21e..3c74e23921d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9427,11 +9427,6 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/efifb.c
-EFS FILESYSTEM
-S: Orphan
-W: http://aeschi.ch.eu.org/efs/
-F: fs/efs/
-
EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
L: netdev@vger.kernel.org
S: Orphan
diff --git a/fs/Kconfig b/fs/Kconfig
index 43cb06de297f..8089639db25c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -315,7 +315,6 @@ source "fs/hfs/Kconfig"
source "fs/hfsplus/Kconfig"
source "fs/befs/Kconfig"
source "fs/bfs/Kconfig"
-source "fs/efs/Kconfig"
source "fs/jffs2/Kconfig"
# UBIFS File system configuration
source "fs/ubifs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index ae1b07f9c6a0..3a11a7d87832 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -93,7 +93,6 @@ obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_NTFS3_FS) += ntfs3/
obj-$(CONFIG_UFS_FS) += ufs/
-obj-$(CONFIG_EFS_FS) += efs/
obj-$(CONFIG_JFFS2_FS) += jffs2/
obj-$(CONFIG_UBIFS_FS) += ubifs/
obj-$(CONFIG_AFFS_FS) += affs/
diff --git a/fs/efs/Kconfig b/fs/efs/Kconfig
deleted file mode 100644
index 0833e533df9d..000000000000
--- a/fs/efs/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config EFS_FS
- tristate "EFS file system support (read only)"
- depends on BLOCK
- select BUFFER_HEAD
- help
- EFS is an older file system used for non-ISO9660 CD-ROMs and hard
- disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
- uses the XFS file system for hard disk partitions however).
-
- This implementation only offers read-only access. If you don't know
- what all this is about, it's safe to say N. For more information
- about EFS see its home page at <http://aeschi.ch.eu.org/efs/>.
-
- To compile the EFS file system support as a module, choose M here: the
- module will be called efs.
diff --git a/fs/efs/Makefile b/fs/efs/Makefile
deleted file mode 100644
index 85e5b88f9471..000000000000
--- a/fs/efs/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the linux efs-filesystem routines.
-#
-
-obj-$(CONFIG_EFS_FS) += efs.o
-
-efs-objs := super.o inode.o namei.o dir.o file.o symlink.o
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
deleted file mode 100644
index 35ad0092c115..000000000000
--- a/fs/efs/dir.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * dir.c
- *
- * Copyright (c) 1999 Al Smith
- */
-
-#include <linux/buffer_head.h>
-#include <linux/filelock.h>
-#include "efs.h"
-
-static int efs_readdir(struct file *, struct dir_context *);
-
-const struct file_operations efs_dir_operations = {
- .llseek = generic_file_llseek,
- .read = generic_read_dir,
- .iterate_shared = efs_readdir,
- .setlease = generic_setlease,
-};
-
-const struct inode_operations efs_dir_inode_operations = {
- .lookup = efs_lookup,
-};
-
-static int efs_readdir(struct file *file, struct dir_context *ctx)
-{
- struct inode *inode = file_inode(file);
- efs_block_t block;
- int slot;
-
- if (inode->i_size & (EFS_DIRBSIZE-1))
- pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
- __func__);
-
- /* work out where this entry can be found */
- block = ctx->pos >> EFS_DIRBSIZE_BITS;
-
- /* each block contains at most 256 slots */
- slot = ctx->pos & 0xff;
-
- /* look at all blocks */
- while (block < inode->i_blocks) {
- struct efs_dir *dirblock;
- struct buffer_head *bh;
-
- /* read the dir block */
- bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
-
- if (!bh) {
- pr_err("%s(): failed to read dir block %d\n",
- __func__, block);
- break;
- }
-
- dirblock = (struct efs_dir *) bh->b_data;
-
- if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
- pr_err("%s(): invalid directory block\n", __func__);
- brelse(bh);
- break;
- }
-
- for (; slot < dirblock->slots; slot++) {
- struct efs_dentry *dirslot;
- efs_ino_t inodenum;
- const char *nameptr;
- int namelen;
-
- if (dirblock->space[slot] == 0)
- continue;
-
- dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
-
- inodenum = be32_to_cpu(dirslot->inode);
- namelen = dirslot->namelen;
- nameptr = dirslot->name;
- pr_debug("%s(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n",
- __func__, block, slot, dirblock->slots-1,
- inodenum, nameptr, namelen);
- if (!namelen)
- continue;
- /* found the next entry */
- ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
-
- /* sanity check */
- if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
- pr_warn("directory entry %d exceeds directory block\n",
- slot);
- continue;
- }
-
- /* copy filename and data in dirslot */
- if (!dir_emit(ctx, nameptr, namelen, inodenum, DT_UNKNOWN)) {
- brelse(bh);
- return 0;
- }
- }
- brelse(bh);
-
- slot = 0;
- block++;
- }
- ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
- return 0;
-}
diff --git a/fs/efs/efs.h b/fs/efs/efs.h
deleted file mode 100644
index 918d2b9abb76..000000000000
--- a/fs/efs/efs.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 1999 Al Smith, <Al.Smith@aeschi.ch.eu.org>
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
- * Portions derived from IRIX header files (c) 1988 Silicon Graphics
- */
-#ifndef _EFS_EFS_H_
-#define _EFS_EFS_H_
-
-#ifdef pr_fmt
-#undef pr_fmt
-#endif
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-
-#define EFS_VERSION "1.0a"
-
-/* 1 block is 512 bytes */
-#define EFS_BLOCKSIZE_BITS 9
-#define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS)
-
-typedef int32_t efs_block_t;
-typedef uint32_t efs_ino_t;
-
-#define EFS_DIRECTEXTENTS 12
-
-/*
- * layout of an extent, in memory and on disk. 8 bytes exactly.
- */
-typedef union extent_u {
- unsigned char raw[8];
- struct extent_s {
- unsigned int ex_magic:8; /* magic # (zero) */
- unsigned int ex_bn:24; /* basic block */
- unsigned int ex_length:8; /* numblocks in this extent */
- unsigned int ex_offset:24; /* logical offset into file */
- } cooked;
-} efs_extent;
-
-typedef struct edevs {
- __be16 odev;
- __be32 ndev;
-} efs_devs;
-
-/*
- * extent based filesystem inode as it appears on disk. The efs inode
- * is exactly 128 bytes long.
- */
-struct efs_dinode {
- __be16 di_mode; /* mode and type of file */
- __be16 di_nlink; /* number of links to file */
- __be16 di_uid; /* owner's user id */
- __be16 di_gid; /* owner's group id */
- __be32 di_size; /* number of bytes in file */
- __be32 di_atime; /* time last accessed */
- __be32 di_mtime; /* time last modified */
- __be32 di_ctime; /* time created */
- __be32 di_gen; /* generation number */
- __be16 di_numextents; /* # of extents */
- u_char di_version; /* version of inode */
- u_char di_spare; /* spare - used by AFS */
- union di_addr {
- efs_extent di_extents[EFS_DIRECTEXTENTS];
- efs_devs di_dev; /* device for IFCHR/IFBLK */
- } di_u;
-};
-
-/* efs inode storage in memory */
-struct efs_inode_info {
- int numextents;
- int lastextent;
-
- efs_extent extents[EFS_DIRECTEXTENTS];
- struct inode vfs_inode;
-};
-
-#include <linux/efs_fs_sb.h>
-
-#define EFS_DIRBSIZE_BITS EFS_BLOCKSIZE_BITS
-#define EFS_DIRBSIZE (1 << EFS_DIRBSIZE_BITS)
-
-struct efs_dentry {
- __be32 inode;
- unsigned char namelen;
- char name[3];
-};
-
-#define EFS_DENTSIZE (sizeof(struct efs_dentry) - 3 + 1)
-#define EFS_MAXNAMELEN ((1 << (sizeof(char) * 8)) - 1)
-
-#define EFS_DIRBLK_HEADERSIZE 4
-#define EFS_DIRBLK_MAGIC 0xbeef /* moo */
-
-struct efs_dir {
- __be16 magic;
- unsigned char firstused;
- unsigned char slots;
-
- unsigned char space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
-};
-
-#define EFS_MAXENTS \
- ((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
- (EFS_DENTSIZE + sizeof(char)))
-
-#define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
-
-#define EFS_REALOFF(offset) ((offset << 1))
-
-
-static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
-{
- return container_of(inode, struct efs_inode_info, vfs_inode);
-}
-
-static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-struct statfs;
-struct fid;
-
-extern const struct inode_operations efs_dir_inode_operations;
-extern const struct file_operations efs_dir_operations;
-extern const struct address_space_operations efs_symlink_aops;
-
-extern struct inode *efs_iget(struct super_block *, unsigned long);
-extern efs_block_t efs_map_block(struct inode *, efs_block_t);
-extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
-
-extern struct dentry *efs_lookup(struct inode *, struct dentry *, unsigned int);
-extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type);
-extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type);
-extern struct dentry *efs_get_parent(struct dentry *);
-extern int efs_bmap(struct inode *, int);
-
-#endif /* _EFS_EFS_H_ */
diff --git a/fs/efs/file.c b/fs/efs/file.c
deleted file mode 100644
index 9e641da6fab2..000000000000
--- a/fs/efs/file.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * file.c
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
- */
-
-#include <linux/buffer_head.h>
-#include "efs.h"
-
-int efs_get_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create)
-{
- int error = -EROFS;
- long phys;
-
- if (create)
- return error;
- if (iblock >= inode->i_blocks) {
-#ifdef DEBUG
- /*
- * i have no idea why this happens as often as it does
- */
- pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
- __func__, block, inode->i_blocks, inode->i_size);
-#endif
- return 0;
- }
- phys = efs_map_block(inode, iblock);
- if (phys)
- map_bh(bh_result, inode->i_sb, phys);
- return 0;
-}
-
-int efs_bmap(struct inode *inode, efs_block_t block) {
-
- if (block < 0) {
- pr_warn("%s(): block < 0\n", __func__);
- return 0;
- }
-
- /* are we about to read past the end of a file ? */
- if (!(block < inode->i_blocks)) {
-#ifdef DEBUG
- /*
- * i have no idea why this happens as often as it does
- */
- pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
- __func__, block, inode->i_blocks, inode->i_size);
-#endif
- return 0;
- }
-
- return efs_map_block(inode, block);
-}
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
deleted file mode 100644
index 4b132729e638..000000000000
--- a/fs/efs/inode.c
+++ /dev/null
@@ -1,315 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * inode.c
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
- * and from work (c) 1998 Mike Shaver.
- */
-
-#include <linux/buffer_head.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include "efs.h"
-#include <linux/efs_fs_sb.h>
-
-static int efs_read_folio(struct file *file, struct folio *folio)
-{
- return block_read_full_folio(folio, efs_get_block);
-}
-
-static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
-{
- return generic_block_bmap(mapping,block,efs_get_block);
-}
-
-static const struct address_space_operations efs_aops = {
- .read_folio = efs_read_folio,
- .bmap = _efs_bmap
-};
-
-static inline void extent_copy(efs_extent *src, efs_extent *dst) {
- /*
- * this is slightly evil. it doesn't just copy
- * efs_extent from src to dst, it also mangles
- * the bits so that dst ends up in cpu byte-order.
- */
-
- dst->cooked.ex_magic = (unsigned int) src->raw[0];
- dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) |
- ((unsigned int) src->raw[2] << 8) |
- ((unsigned int) src->raw[3] << 0);
- dst->cooked.ex_length = (unsigned int) src->raw[4];
- dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
- ((unsigned int) src->raw[6] << 8) |
- ((unsigned int) src->raw[7] << 0);
- return;
-}
-
-struct inode *efs_iget(struct super_block *super, unsigned long ino)
-{
- int i, inode_index;
- dev_t device;
- u32 rdev;
- struct buffer_head *bh;
- struct efs_sb_info *sb = SUPER_INFO(super);
- struct efs_inode_info *in;
- efs_block_t block, offset;
- struct efs_dinode *efs_inode;
- struct inode *inode;
-
- inode = iget_locked(super, ino);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- if (!(inode_state_read_once(inode) & I_NEW))
- return inode;
-
- in = INODE_INFO(inode);
-
- /*
- ** EFS layout:
- **
- ** | cylinder group | cylinder group | cylinder group ..etc
- ** |inodes|data |inodes|data |inodes|data ..etc
- **
- ** work out the inode block index, (considering initially that the
- ** inodes are stored as consecutive blocks). then work out the block
- ** number of that inode given the above layout, and finally the
- ** offset of the inode within that block.
- */
-
- inode_index = inode->i_ino /
- (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
-
- block = sb->fs_start + sb->first_block +
- (sb->group_size * (inode_index / sb->inode_blocks)) +
- (inode_index % sb->inode_blocks);
-
- offset = (inode->i_ino %
- (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
- sizeof(struct efs_dinode);
-
- bh = sb_bread(inode->i_sb, block);
- if (!bh) {
- pr_warn("%s() failed at block %d\n", __func__, block);
- goto read_inode_error;
- }
-
- efs_inode = (struct efs_dinode *) (bh->b_data + offset);
-
- inode->i_mode = be16_to_cpu(efs_inode->di_mode);
- set_nlink(inode, be16_to_cpu(efs_inode->di_nlink));
- i_uid_write(inode, (uid_t)be16_to_cpu(efs_inode->di_uid));
- i_gid_write(inode, (gid_t)be16_to_cpu(efs_inode->di_gid));
- inode->i_size = be32_to_cpu(efs_inode->di_size);
- inode_set_atime(inode, be32_to_cpu(efs_inode->di_atime), 0);
- inode_set_mtime(inode, be32_to_cpu(efs_inode->di_mtime), 0);
- inode_set_ctime(inode, be32_to_cpu(efs_inode->di_ctime), 0);
-
- /* this is the number of blocks in the file */
- if (inode->i_size == 0) {
- inode->i_blocks = 0;
- } else {
- inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
- }
-
- rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev);
- if (rdev == 0xffff) {
- rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev);
- if (sysv_major(rdev) > 0xfff)
- device = 0;
- else
- device = MKDEV(sysv_major(rdev), sysv_minor(rdev));
- } else
- device = old_decode_dev(rdev);
-
- /* get the number of extents for this object */
- in->numextents = be16_to_cpu(efs_inode->di_numextents);
- in->lastextent = 0;
-
- /* copy the extents contained within the inode to memory */
- for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
- extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
- if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
- pr_warn("extent %d has bad magic number in inode %llu\n",
- i, inode->i_ino);
- brelse(bh);
- goto read_inode_error;
- }
- }
-
- brelse(bh);
- pr_debug("efs_iget(): inode %llu, extents %d, mode %o\n",
- inode->i_ino, in->numextents, inode->i_mode);
- switch (inode->i_mode & S_IFMT) {
- case S_IFDIR:
- inode->i_op = &efs_dir_inode_operations;
- inode->i_fop = &efs_dir_operations;
- break;
- case S_IFREG:
- inode->i_fop = &generic_ro_fops;
- inode->i_data.a_ops = &efs_aops;
- break;
- case S_IFLNK:
- inode->i_op = &page_symlink_inode_operations;
- inode_nohighmem(inode);
- inode->i_data.a_ops = &efs_symlink_aops;
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- init_special_inode(inode, inode->i_mode, device);
- break;
- default:
- pr_warn("unsupported inode mode %o\n", inode->i_mode);
- goto read_inode_error;
- break;
- }
-
- unlock_new_inode(inode);
- return inode;
-
-read_inode_error:
- pr_warn("failed to read inode %llu\n", inode->i_ino);
- iget_failed(inode);
- return ERR_PTR(-EIO);
-}
-
-static inline efs_block_t
-efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
- efs_block_t start;
- efs_block_t length;
- efs_block_t offset;
-
- /*
- * given an extent and a logical block within a file,
- * can this block be found within this extent ?
- */
- start = ptr->cooked.ex_bn;
- length = ptr->cooked.ex_length;
- offset = ptr->cooked.ex_offset;
-
- if ((block >= offset) && (block < offset+length)) {
- return(sb->fs_start + start + block - offset);
- } else {
- return 0;
- }
-}
-
-efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
- struct efs_sb_info *sb = SUPER_INFO(inode->i_sb);
- struct efs_inode_info *in = INODE_INFO(inode);
- struct buffer_head *bh = NULL;
-
- int cur, last, first = 1;
- int ibase, ioffset, dirext, direxts, indext, indexts;
- efs_block_t iblock, result = 0, lastblock = 0;
- efs_extent ext, *exts;
-
- last = in->lastextent;
-
- if (in->numextents <= EFS_DIRECTEXTENTS) {
- /* first check the last extent we returned */
- if ((result = efs_extent_check(&in->extents[last], block, sb)))
- return result;
-
- /* if we only have one extent then nothing can be found */
- if (in->numextents == 1) {
- pr_err("%s() failed to map (1 extent)\n", __func__);
- return 0;
- }
-
- direxts = in->numextents;
-
- /*
- * check the stored extents in the inode
- * start with next extent and check forwards
- */
- for(dirext = 1; dirext < direxts; dirext++) {
- cur = (last + dirext) % in->numextents;
- if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
- in->lastextent = cur;
- return result;
- }
- }
-
- pr_err("%s() failed to map block %u (dir)\n", __func__, block);
- return 0;
- }
-
- pr_debug("%s(): indirect search for logical block %u\n",
- __func__, block);
- direxts = in->extents[0].cooked.ex_offset;
- indexts = in->numextents;
-
- for(indext = 0; indext < indexts; indext++) {
- cur = (last + indext) % indexts;
-
- /*
- * work out which direct extent contains `cur'.
- *
- * also compute ibase: i.e. the number of the first
- * indirect extent contained within direct extent `cur'.
- *
- */
- ibase = 0;
- for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
- ibase += in->extents[dirext].cooked.ex_length *
- (EFS_BLOCKSIZE / sizeof(efs_extent));
- }
-
- if (dirext == direxts) {
- /* should never happen */
- pr_err("couldn't find direct extent for indirect extent %d (block %u)\n",
- cur, block);
- if (bh) brelse(bh);
- return 0;
- }
-
- /* work out block number and offset of this indirect extent */
- iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
- (cur - ibase) /
- (EFS_BLOCKSIZE / sizeof(efs_extent));
- ioffset = (cur - ibase) %
- (EFS_BLOCKSIZE / sizeof(efs_extent));
-
- if (first || lastblock != iblock) {
- if (bh) brelse(bh);
-
- bh = sb_bread(inode->i_sb, iblock);
- if (!bh) {
- pr_err("%s() failed at block %d\n",
- __func__, iblock);
- return 0;
- }
- pr_debug("%s(): read indirect extent block %d\n",
- __func__, iblock);
- first = 0;
- lastblock = iblock;
- }
-
- exts = (efs_extent *) bh->b_data;
-
- extent_copy(&(exts[ioffset]), &ext);
-
- if (ext.cooked.ex_magic != 0) {
- pr_err("extent %d has bad magic number in block %d\n",
- cur, iblock);
- if (bh) brelse(bh);
- return 0;
- }
-
- if ((result = efs_extent_check(&ext, block, sb))) {
- if (bh) brelse(bh);
- in->lastextent = cur;
- return result;
- }
- }
- if (bh) brelse(bh);
- pr_err("%s() failed to map block %u (indir)\n", __func__, block);
- return 0;
-}
-
-MODULE_DESCRIPTION("Extent File System (efs)");
-MODULE_LICENSE("GPL");
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
deleted file mode 100644
index 38961ee1d1af..000000000000
--- a/fs/efs/namei.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * namei.c
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
- */
-
-#include <linux/buffer_head.h>
-#include <linux/string.h>
-#include <linux/exportfs.h>
-#include "efs.h"
-
-
-static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
-{
- struct buffer_head *bh;
-
- int slot, namelen;
- char *nameptr;
- struct efs_dir *dirblock;
- struct efs_dentry *dirslot;
- efs_ino_t inodenum;
- efs_block_t block;
-
- if (inode->i_size & (EFS_DIRBSIZE-1))
- pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
- __func__);
-
- for(block = 0; block < inode->i_blocks; block++) {
-
- bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
- if (!bh) {
- pr_err("%s(): failed to read dir block %d\n",
- __func__, block);
- return 0;
- }
-
- dirblock = (struct efs_dir *) bh->b_data;
-
- if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
- pr_err("%s(): invalid directory block\n", __func__);
- brelse(bh);
- return 0;
- }
-
- for (slot = 0; slot < dirblock->slots; slot++) {
- dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
-
- namelen = dirslot->namelen;
- nameptr = dirslot->name;
-
- if ((namelen == len) && (!memcmp(name, nameptr, len))) {
- inodenum = be32_to_cpu(dirslot->inode);
- brelse(bh);
- return inodenum;
- }
- }
- brelse(bh);
- }
- return 0;
-}
-
-struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
-{
- efs_ino_t inodenum;
- struct inode *inode = NULL;
-
- inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
- if (inodenum)
- inode = efs_iget(dir->i_sb, inodenum);
-
- return d_splice_alias(inode, dentry);
-}
-
-static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
- u32 generation)
-{
- struct inode *inode;
-
- if (ino == 0)
- return ERR_PTR(-ESTALE);
- inode = efs_iget(sb, ino);
- if (IS_ERR(inode))
- return ERR_CAST(inode);
-
- if (generation && inode->i_generation != generation) {
- iput(inode);
- return ERR_PTR(-ESTALE);
- }
-
- return inode;
-}
-
-struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type)
-{
- return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
- efs_nfs_get_inode);
-}
-
-struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
- int fh_len, int fh_type)
-{
- return generic_fh_to_parent(sb, fid, fh_len, fh_type,
- efs_nfs_get_inode);
-}
-
-struct dentry *efs_get_parent(struct dentry *child)
-{
- struct dentry *parent = ERR_PTR(-ENOENT);
- efs_ino_t ino;
-
- ino = efs_find_entry(d_inode(child), "..", 2);
- if (ino)
- parent = d_obtain_alias(efs_iget(child->d_sb, ino));
-
- return parent;
-}
diff --git a/fs/efs/super.c b/fs/efs/super.c
deleted file mode 100644
index 11fea3bbce7c..000000000000
--- a/fs/efs/super.c
+++ /dev/null
@@ -1,368 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * super.c
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/exportfs.h>
-#include <linux/slab.h>
-#include <linux/buffer_head.h>
-#include <linux/vfs.h>
-#include <linux/blkdev.h>
-#include <linux/fs_context.h>
-#include "efs.h"
-#include <linux/efs_vh.h>
-#include <linux/efs_fs_sb.h>
-
-static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
-static int efs_init_fs_context(struct fs_context *fc);
-
-static void efs_kill_sb(struct super_block *s)
-{
- struct efs_sb_info *sbi = SUPER_INFO(s);
- kill_block_super(s);
- kfree(sbi);
-}
-
-static struct pt_types sgi_pt_types[] = {
- {0x00, "SGI vh"},
- {0x01, "SGI trkrepl"},
- {0x02, "SGI secrepl"},
- {0x03, "SGI raw"},
- {0x04, "SGI bsd"},
- {SGI_SYSV, "SGI sysv"},
- {0x06, "SGI vol"},
- {SGI_EFS, "SGI efs"},
- {0x08, "SGI lv"},
- {0x09, "SGI rlv"},
- {0x0A, "SGI xfs"},
- {0x0B, "SGI xfslog"},
- {0x0C, "SGI xlv"},
- {0x82, "Linux swap"},
- {0x83, "Linux native"},
- {0, NULL}
-};
-
-/*
- * File system definition and registration.
- */
-static struct file_system_type efs_fs_type = {
- .owner = THIS_MODULE,
- .name = "efs",
- .kill_sb = efs_kill_sb,
- .fs_flags = FS_REQUIRES_DEV,
- .init_fs_context = efs_init_fs_context,
-};
-MODULE_ALIAS_FS("efs");
-
-static struct kmem_cache * efs_inode_cachep;
-
-static struct inode *efs_alloc_inode(struct super_block *sb)
-{
- struct efs_inode_info *ei;
- ei = alloc_inode_sb(sb, efs_inode_cachep, GFP_KERNEL);
- if (!ei)
- return NULL;
- return &ei->vfs_inode;
-}
-
-static void efs_free_inode(struct inode *inode)
-{
- kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
-}
-
-static void init_once(void *foo)
-{
- struct efs_inode_info *ei = (struct efs_inode_info *) foo;
-
- inode_init_once(&ei->vfs_inode);
-}
-
-static int __init init_inodecache(void)
-{
- efs_inode_cachep = kmem_cache_create("efs_inode_cache",
- sizeof(struct efs_inode_info), 0,
- SLAB_RECLAIM_ACCOUNT|SLAB_ACCOUNT,
- init_once);
- if (efs_inode_cachep == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static void destroy_inodecache(void)
-{
- /*
- * Make sure all delayed rcu free inodes are flushed before we
- * destroy cache.
- */
- rcu_barrier();
- kmem_cache_destroy(efs_inode_cachep);
-}
-
-static const struct super_operations efs_superblock_operations = {
- .alloc_inode = efs_alloc_inode,
- .free_inode = efs_free_inode,
- .statfs = efs_statfs,
-};
-
-static const struct export_operations efs_export_ops = {
- .encode_fh = generic_encode_ino32_fh,
- .fh_to_dentry = efs_fh_to_dentry,
- .fh_to_parent = efs_fh_to_parent,
- .get_parent = efs_get_parent,
-};
-
-static int __init init_efs_fs(void) {
- int err;
- pr_info(EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
- err = init_inodecache();
- if (err)
- goto out1;
- err = register_filesystem(&efs_fs_type);
- if (err)
- goto out;
- return 0;
-out:
- destroy_inodecache();
-out1:
- return err;
-}
-
-static void __exit exit_efs_fs(void) {
- unregister_filesystem(&efs_fs_type);
- destroy_inodecache();
-}
-
-module_init(init_efs_fs)
-module_exit(exit_efs_fs)
-
-static efs_block_t efs_validate_vh(struct volume_header *vh) {
- int i;
- __be32 cs, *ui;
- int csum;
- efs_block_t sblock = 0; /* shuts up gcc */
- struct pt_types *pt_entry;
- int pt_type, slice = -1;
-
- if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
- /*
- * assume that we're dealing with a partition and allow
- * read_super() to try and detect a valid superblock
- * on the next block.
- */
- return 0;
- }
-
- ui = ((__be32 *) (vh + 1)) - 1;
- for(csum = 0; ui >= ((__be32 *) vh);) {
- cs = *ui--;
- csum += be32_to_cpu(cs);
- }
- if (csum) {
- pr_warn("SGI disklabel: checksum bad, label corrupted\n");
- return 0;
- }
-
-#ifdef DEBUG
- pr_debug("bf: \"%16s\"\n", vh->vh_bootfile);
-
- for(i = 0; i < NVDIR; i++) {
- int j;
- char name[VDNAMESIZE+1];
-
- for(j = 0; j < VDNAMESIZE; j++) {
- name[j] = vh->vh_vd[i].vd_name[j];
- }
- name[j] = (char) 0;
-
- if (name[0]) {
- pr_debug("vh: %8s block: 0x%08x size: 0x%08x\n",
- name, (int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
- (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
- }
- }
-#endif
-
- for(i = 0; i < NPARTAB; i++) {
- pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
- for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
- if (pt_type == pt_entry->pt_type) break;
- }
-#ifdef DEBUG
- if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
- pr_debug("pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
- i, (int)be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
- (int)be32_to_cpu(vh->vh_pt[i].pt_nblks),
- pt_type, (pt_entry->pt_name) ?
- pt_entry->pt_name : "unknown");
- }
-#endif
- if (IS_EFS(pt_type)) {
- sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
- slice = i;
- }
- }
-
- if (slice == -1) {
- pr_notice("partition table contained no EFS partitions\n");
-#ifdef DEBUG
- } else {
- pr_info("using slice %d (type %s, offset 0x%x)\n", slice,
- (pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
- sblock);
-#endif
- }
- return sblock;
-}
-
-static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
-
- if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic)))
- return -1;
-
- sb->fs_magic = be32_to_cpu(super->fs_magic);
- sb->total_blocks = be32_to_cpu(super->fs_size);
- sb->first_block = be32_to_cpu(super->fs_firstcg);
- sb->group_size = be32_to_cpu(super->fs_cgfsize);
- sb->data_free = be32_to_cpu(super->fs_tfree);
- sb->inode_free = be32_to_cpu(super->fs_tinode);
- sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
- sb->total_groups = be16_to_cpu(super->fs_ncg);
-
- return 0;
-}
-
-static int efs_fill_super(struct super_block *s, struct fs_context *fc)
-{
- struct efs_sb_info *sb;
- struct buffer_head *bh;
- struct inode *root;
-
- sb = kzalloc_obj(struct efs_sb_info);
- if (!sb)
- return -ENOMEM;
- s->s_fs_info = sb;
- s->s_time_min = 0;
- s->s_time_max = U32_MAX;
-
- s->s_magic = EFS_SUPER_MAGIC;
- if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
- pr_err("device does not support %d byte blocks\n",
- EFS_BLOCKSIZE);
- return invalf(fc, "device does not support %d byte blocks\n",
- EFS_BLOCKSIZE);
- }
-
- /* read the vh (volume header) block */
- bh = sb_bread(s, 0);
-
- if (!bh) {
- pr_err("cannot read volume header\n");
- return -EIO;
- }
-
- /*
- * if this returns zero then we didn't find any partition table.
- * this isn't (yet) an error - just assume for the moment that
- * the device is valid and go on to search for a superblock.
- */
- sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
- brelse(bh);
-
- if (sb->fs_start == -1) {
- return -EINVAL;
- }
-
- bh = sb_bread(s, sb->fs_start + EFS_SUPER);
- if (!bh) {
- pr_err("cannot read superblock\n");
- return -EIO;
- }
-
- if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
-#ifdef DEBUG
- pr_warn("invalid superblock at block %u\n",
- sb->fs_start + EFS_SUPER);
-#endif
- brelse(bh);
- return -EINVAL;
- }
- brelse(bh);
-
- if (!sb_rdonly(s)) {
-#ifdef DEBUG
- pr_info("forcing read-only mode\n");
-#endif
- s->s_flags |= SB_RDONLY;
- }
- s->s_op = &efs_superblock_operations;
- s->s_export_op = &efs_export_ops;
- root = efs_iget(s, EFS_ROOTINODE);
- if (IS_ERR(root)) {
- pr_err("get root inode failed\n");
- return PTR_ERR(root);
- }
-
- s->s_root = d_make_root(root);
- if (!(s->s_root)) {
- pr_err("get root dentry failed\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int efs_get_tree(struct fs_context *fc)
-{
- return get_tree_bdev(fc, efs_fill_super);
-}
-
-static int efs_reconfigure(struct fs_context *fc)
-{
- sync_filesystem(fc->root->d_sb);
- fc->sb_flags |= SB_RDONLY;
-
- return 0;
-}
-
-static const struct fs_context_operations efs_context_opts = {
- .get_tree = efs_get_tree,
- .reconfigure = efs_reconfigure,
-};
-
-/*
- * Set up the filesystem mount context.
- */
-static int efs_init_fs_context(struct fs_context *fc)
-{
- fc->ops = &efs_context_opts;
-
- return 0;
-}
-
-static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
- struct super_block *sb = dentry->d_sb;
- struct efs_sb_info *sbi = SUPER_INFO(sb);
- u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
-
- buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
- buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
- buf->f_blocks = sbi->total_groups * /* total data blocks */
- (sbi->group_size - sbi->inode_blocks);
- buf->f_bfree = sbi->data_free; /* free data blocks */
- buf->f_bavail = sbi->data_free; /* free blocks for non-root */
- buf->f_files = sbi->total_groups * /* total inodes */
- sbi->inode_blocks *
- (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
- buf->f_ffree = sbi->inode_free; /* free inodes */
- buf->f_fsid = u64_to_fsid(id);
- buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */
-
- return 0;
-}
-
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
deleted file mode 100644
index 7749feded722..000000000000
--- a/fs/efs/symlink.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * symlink.c
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
- */
-
-#include <linux/string.h>
-#include <linux/pagemap.h>
-#include <linux/buffer_head.h>
-#include "efs.h"
-
-static int efs_symlink_read_folio(struct file *file, struct folio *folio)
-{
- char *link = folio_address(folio);
- struct buffer_head *bh;
- struct inode *inode = folio->mapping->host;
- efs_block_t size = inode->i_size;
- int err;
-
- err = -ENAMETOOLONG;
- if (size > 2 * EFS_BLOCKSIZE)
- goto fail;
-
- /* read first 512 bytes of link target */
- err = -EIO;
- bh = sb_bread(inode->i_sb, efs_bmap(inode, 0));
- if (!bh)
- goto fail;
- memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
- brelse(bh);
- if (size > EFS_BLOCKSIZE) {
- bh = sb_bread(inode->i_sb, efs_bmap(inode, 1));
- if (!bh)
- goto fail;
- memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
- brelse(bh);
- }
- link[size] = '\0';
- err = 0;
-fail:
- folio_end_read(folio, err == 0);
- return err;
-}
-
-const struct address_space_operations efs_symlink_aops = {
- .read_folio = efs_symlink_read_folio
-};
diff --git a/include/linux/efs_vh.h b/include/linux/efs_vh.h
deleted file mode 100644
index 206c5270f7b8..000000000000
--- a/include/linux/efs_vh.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * efs_vh.h
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from IRIX header files (c) 1985 MIPS Computer Systems, Inc.
- */
-
-#ifndef __EFS_VH_H__
-#define __EFS_VH_H__
-
-#define VHMAGIC 0xbe5a941 /* volume header magic number */
-#define NPARTAB 16 /* 16 unix partitions */
-#define NVDIR 15 /* max of 15 directory entries */
-#define BFNAMESIZE 16 /* max 16 chars in boot file name */
-#define VDNAMESIZE 8
-
-struct volume_directory {
- char vd_name[VDNAMESIZE]; /* name */
- __be32 vd_lbn; /* logical block number */
- __be32 vd_nbytes; /* file length in bytes */
-};
-
-struct partition_table { /* one per logical partition */
- __be32 pt_nblks; /* # of logical blks in partition */
- __be32 pt_firstlbn; /* first lbn of partition */
- __be32 pt_type; /* use of partition */
-};
-
-struct volume_header {
- __be32 vh_magic; /* identifies volume header */
- __be16 vh_rootpt; /* root partition number */
- __be16 vh_swappt; /* swap partition number */
- char vh_bootfile[BFNAMESIZE]; /* name of file to boot */
- char pad[48]; /* device param space */
- struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
- struct partition_table vh_pt[NPARTAB]; /* device partition layout */
- __be32 vh_csum; /* volume header checksum */
- __be32 vh_fill; /* fill out to 512 bytes */
-};
-
-/* partition type sysv is used for EFS format CD-ROM partitions */
-#define SGI_SYSV 0x05
-#define SGI_EFS 0x07
-#define IS_EFS(x) (((x) == SGI_EFS) || ((x) == SGI_SYSV))
-
-struct pt_types {
- int pt_type;
- char *pt_name;
-};
-
-#endif /* __EFS_VH_H__ */
-
diff --git a/include/uapi/linux/efs_fs_sb.h b/include/uapi/linux/efs_fs_sb.h
deleted file mode 100644
index 6bad29a10faa..000000000000
--- a/include/uapi/linux/efs_fs_sb.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * efs_fs_sb.h
- *
- * Copyright (c) 1999 Al Smith
- *
- * Portions derived from IRIX header files (c) 1988 Silicon Graphics
- */
-
-#ifndef __EFS_FS_SB_H__
-#define __EFS_FS_SB_H__
-
-#include <linux/types.h>
-#include <linux/magic.h>
-
-/* EFS superblock magic numbers */
-#define EFS_MAGIC 0x072959
-#define EFS_NEWMAGIC 0x07295a
-
-#define IS_EFS_MAGIC(x) ((x == EFS_MAGIC) || (x == EFS_NEWMAGIC))
-
-#define EFS_SUPER 1
-#define EFS_ROOTINODE 2
-
-/* efs superblock on disk */
-struct efs_super {
- __be32 fs_size; /* size of filesystem, in sectors */
- __be32 fs_firstcg; /* bb offset to first cg */
- __be32 fs_cgfsize; /* size of cylinder group in bb's */
- __be16 fs_cgisize; /* bb's of inodes per cylinder group */
- __be16 fs_sectors; /* sectors per track */
- __be16 fs_heads; /* heads per cylinder */
- __be16 fs_ncg; /* # of cylinder groups in filesystem */
- __be16 fs_dirty; /* fs needs to be fsck'd */
- __be32 fs_time; /* last super-block update */
- __be32 fs_magic; /* magic number */
- char fs_fname[6]; /* file system name */
- char fs_fpack[6]; /* file system pack name */
- __be32 fs_bmsize; /* size of bitmap in bytes */
- __be32 fs_tfree; /* total free data blocks */
- __be32 fs_tinode; /* total free inodes */
- __be32 fs_bmblock; /* bitmap location. */
- __be32 fs_replsb; /* Location of replicated superblock. */
- __be32 fs_lastialloc; /* last allocated inode */
- char fs_spare[20]; /* space for expansion - MUST BE ZERO */
- __be32 fs_checksum; /* checksum of volume portion of fs */
-};
-
-/* efs superblock information in memory */
-struct efs_sb_info {
- __u32 fs_magic; /* superblock magic number */
- __u32 fs_start; /* first block of filesystem */
- __u32 first_block; /* first data block in filesystem */
- __u32 total_blocks; /* total number of blocks in filesystem */
- __u32 group_size; /* # of blocks a group consists of */
- __u32 data_free; /* # of free data blocks */
- __u32 inode_free; /* # of free inodes */
- __u16 inode_blocks; /* # of blocks used for inodes in every grp */
- __u16 total_groups; /* # of groups */
-};
-
-#endif /* __EFS_FS_SB_H__ */
-
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] efs: Remove EFS
2026-06-18 21:18 [PATCH] efs: Remove EFS Matthew Wilcox (Oracle)
@ 2026-06-19 9:28 ` Jori Koolstra
2026-06-19 10:06 ` Pedro Falcato
2026-06-25 19:42 ` Darrick J. Wong
1 sibling, 1 reply; 7+ messages in thread
From: Jori Koolstra @ 2026-06-19 9:28 UTC (permalink / raw)
To: Matthew Wilcox (Oracle); +Cc: Christian Brauner, linux-fsdevel
This seems like a good idea. A couple of thoughts: should this maybe be
CC-ed to Linus? He has in the past been critical of removing old
filesystems. There is also something arbitrary about removing efs, but
not minix for instance. It would be great if we had some more objective
criteria for removal. I have also been thinking whether there is some
use to keep at least one old simple filesystem maintained and up to date
with modern API. It could function as a reference.
But to come back to the removal; we cannot know if there are users until
we remove support. So if we don't want to keep efs around indefinitely,
there is not really an alternative to just removing it. If it turns out
(very unlikely) that there are users that absolutely need it to be in the
kernel, then we can always move it back in. This would be work, but
recognizing that this chance is *very* small, it seems like a good
proposition.
Acked-by: Jori Koolstra <jkoolstra@xs4all.nl>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] efs: Remove EFS
2026-06-19 9:28 ` Jori Koolstra
@ 2026-06-19 10:06 ` Pedro Falcato
2026-06-19 10:19 ` Jori Koolstra
0 siblings, 1 reply; 7+ messages in thread
From: Pedro Falcato @ 2026-06-19 10:06 UTC (permalink / raw)
To: Jori Koolstra, Matthew Wilcox (Oracle), Christian Brauner,
linux-fsdevel
On Fri, Jun 19, 2026 at 11:28:03AM +0200, Jori Koolstra wrote:
> This seems like a good idea. A couple of thoughts: should this maybe be
> CC-ed to Linus? He has in the past been critical of removing old
> filesystems. There is also something arbitrary about removing efs, but
> not minix for instance. It would be great if we had some more objective
I'm fairly sure minix is staying for the same reason alpha is staying[1]. I
don't think it's productive to unearth that particular debate at this
moment.
> criteria for removal. I have also been thinking whether there is some
> use to keep at least one old simple filesystem maintained and up to date
> with modern API. It could function as a reference.
We already have one - it's fs/ext2.
(modern API? maybe not so much. still has buffer heads, uses mpage, etc.
alas.)
[1] or that our old simple reference filesystem is ext2 and not e.g fat[2] :)
[2] i may or may not feel sick after suggesting that
--
Pedro
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] efs: Remove EFS
2026-06-19 10:06 ` Pedro Falcato
@ 2026-06-19 10:19 ` Jori Koolstra
2026-06-21 21:44 ` Matthew Wilcox
0 siblings, 1 reply; 7+ messages in thread
From: Jori Koolstra @ 2026-06-19 10:19 UTC (permalink / raw)
To: Pedro Falcato, Matthew Wilcox (Oracle), Christian Brauner,
linux-fsdevel
> Op 19-06-2026 12:06 CEST schreef Pedro Falcato <pfalcato@suse.de>:
>
>
> On Fri, Jun 19, 2026 at 11:28:03AM +0200, Jori Koolstra wrote:
> > This seems like a good idea. A couple of thoughts: should this maybe be
> > CC-ed to Linus? He has in the past been critical of removing old
> > filesystems. There is also something arbitrary about removing efs, but
> > not minix for instance. It would be great if we had some more objective
>
> I'm fairly sure minix is staying for the same reason alpha is staying[1]. I
> don't think it's productive to unearth that particular debate at this
> moment.
I wasn't around back then, but why was ReiserFS removed? I'm just curious about
to what degree the arguments used back then apply to all kinda-maintained-but-not-really
filesystems. jfs is totally unmaintained, despite its MAINTAINERS file entry. And
David has said multiple times he would rather get rid of it.
>
> > criteria for removal. I have also been thinking whether there is some
> > use to keep at least one old simple filesystem maintained and up to date
> > with modern API. It could function as a reference.
>
> We already have one - it's fs/ext2.
> (modern API? maybe not so much. still has buffer heads, uses mpage, etc.
> alas.)
When I wrote this I was also thinking about ext2, but it is significantly
more code. Still, I think you're right. I have a special attachment to fs/minix
because it was the first kernel code that I studied in detail :)
>
> [1] or that our old simple reference filesystem is ext2 and not e.g fat[2] :)
> [2] i may or may not feel sick after suggesting that
> --
> Pedro
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] efs: Remove EFS
2026-06-19 10:19 ` Jori Koolstra
@ 2026-06-21 21:44 ` Matthew Wilcox
2026-06-23 9:17 ` Jori Koolstra
0 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox @ 2026-06-21 21:44 UTC (permalink / raw)
To: Jori Koolstra; +Cc: Pedro Falcato, Christian Brauner, linux-fsdevel
On Fri, Jun 19, 2026 at 12:19:38PM +0200, Jori Koolstra wrote:
> I wasn't around back then, but why was ReiserFS removed? I'm just curious about
You can read the discussion:
https://lore.kernel.org/linux-fsdevel/YhIwUEpymVzmytdp@casper.infradead.org/
> to what degree the arguments used back then apply to all kinda-maintained-but-not-really
> filesystems. jfs is totally unmaintained, despite its MAINTAINERS file entry. And
What? Dave absolutely does maintain it. Commit 1d51b370a0f8 for
example.
> David has said multiple times he would rather get rid of it.
Rather get rid of it ... than what?
> > We already have one - it's fs/ext2.
> > (modern API? maybe not so much. still has buffer heads, uses mpage, etc.
> > alas.)
>
> When I wrote this I was also thinking about ext2, but it is significantly
> more code. Still, I think you're right. I have a special attachment to fs/minix
> because it was the first kernel code that I studied in detail :)
We've had extensive discussions before about converting, eg, ext2 to
iomap. Maybe now ext4 has been started, there's finally enough examples
to get ext2 done. If you're interested in contributing, that would be a
great project.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] efs: Remove EFS
2026-06-21 21:44 ` Matthew Wilcox
@ 2026-06-23 9:17 ` Jori Koolstra
0 siblings, 0 replies; 7+ messages in thread
From: Jori Koolstra @ 2026-06-23 9:17 UTC (permalink / raw)
To: Matthew Wilcox; +Cc: Pedro Falcato, Christian Brauner, linux-fsdevel
> Op 21-06-2026 23:44 CEST schreef Matthew Wilcox <willy@infradead.org>:
>
> > to what degree the arguments used back then apply to all kinda-maintained-but-not-really
> > filesystems. jfs is totally unmaintained, despite its MAINTAINERS file entry. And
>
> What? Dave absolutely does maintain it. Commit 1d51b370a0f8 for
> example.
>
You're right, I was way too strong in my wording, and I didn't bother to check.
Sorry about that. I just remember trying to merge 2 syzbot fixes for jfs and it
was a frustrating experience to get them merged or rejected. Then again, looking
back at it those were exactly the type of fs corruptions the fs community has
de-prioritized.
>
> > > We already have one - it's fs/ext2.
> > > (modern API? maybe not so much. still has buffer heads, uses mpage, etc.
> > > alas.)
> >
> > When I wrote this I was also thinking about ext2, but it is significantly
> > more code. Still, I think you're right. I have a special attachment to fs/minix
> > because it was the first kernel code that I studied in detail :)
>
> We've had extensive discussions before about converting, eg, ext2 to
> iomap. Maybe now ext4 has been started, there's finally enough examples
> to get ext2 done. If you're interested in contributing, that would be a
> great project.
I am definitely interested to get my hands dirty with iomap. I do remember skimming
through the iomap docs, which I found then to be not very helpful, so some examples
would likely be useful. I just saw someone may be willing to do the conversion for
minix too.
That being said, I first want to try to finish O_CREAT|O_DIRECTORY and some other
vfs stuff I've been working on. Also, going to OSS Korea, Recipes, and Plumbers
(maybe give a short talk there), so it's a busy couple on months :)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] efs: Remove EFS
2026-06-18 21:18 [PATCH] efs: Remove EFS Matthew Wilcox (Oracle)
2026-06-19 9:28 ` Jori Koolstra
@ 2026-06-25 19:42 ` Darrick J. Wong
1 sibling, 0 replies; 7+ messages in thread
From: Darrick J. Wong @ 2026-06-25 19:42 UTC (permalink / raw)
To: Matthew Wilcox (Oracle); +Cc: Christian Brauner, linux-fsdevel
On Thu, Jun 18, 2026 at 10:18:19PM +0100, Matthew Wilcox (Oracle) wrote:
> The kernel EFS code has been unmaintained for over twenty years.
> It was superseded on IRIX around thirty years ago. I haven't seen an
> EFS filesystem in the wild since 1999. Userspace tools to read EFS
> filesystems exist, such as https://github.com/jkbenaim/efsextract
>
> There's no benefit to keeping this filesystem in the kernel, and it only
> increases the maintenance burden for tree-wide changes.
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Fine with me! It's a great thing to remove orphaned code when we have
safer alternatives available.
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> MAINTAINERS | 5 -
> fs/Kconfig | 1 -
> fs/Makefile | 1 -
> fs/efs/Kconfig | 16 --
> fs/efs/Makefile | 8 -
> fs/efs/dir.c | 105 ----------
> fs/efs/efs.h | 144 -------------
> fs/efs/file.c | 57 -----
> fs/efs/inode.c | 315 ----------------------------
> fs/efs/namei.c | 120 -----------
> fs/efs/super.c | 368 ---------------------------------
> fs/efs/symlink.c | 50 -----
> include/linux/efs_vh.h | 54 -----
> include/uapi/linux/efs_fs_sb.h | 63 ------
> 14 files changed, 1307 deletions(-)
> delete mode 100644 fs/efs/Kconfig
> delete mode 100644 fs/efs/Makefile
> delete mode 100644 fs/efs/dir.c
> delete mode 100644 fs/efs/efs.h
> delete mode 100644 fs/efs/file.c
> delete mode 100644 fs/efs/inode.c
> delete mode 100644 fs/efs/namei.c
> delete mode 100644 fs/efs/super.c
> delete mode 100644 fs/efs/symlink.c
> delete mode 100644 include/linux/efs_vh.h
> delete mode 100644 include/uapi/linux/efs_fs_sb.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 629b22c6c21e..3c74e23921d2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9427,11 +9427,6 @@ L: linux-fbdev@vger.kernel.org
> S: Maintained
> F: drivers/video/fbdev/efifb.c
>
> -EFS FILESYSTEM
> -S: Orphan
> -W: http://aeschi.ch.eu.org/efs/
> -F: fs/efs/
> -
> EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
> L: netdev@vger.kernel.org
> S: Orphan
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 43cb06de297f..8089639db25c 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -315,7 +315,6 @@ source "fs/hfs/Kconfig"
> source "fs/hfsplus/Kconfig"
> source "fs/befs/Kconfig"
> source "fs/bfs/Kconfig"
> -source "fs/efs/Kconfig"
> source "fs/jffs2/Kconfig"
> # UBIFS File system configuration
> source "fs/ubifs/Kconfig"
> diff --git a/fs/Makefile b/fs/Makefile
> index ae1b07f9c6a0..3a11a7d87832 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -93,7 +93,6 @@ obj-$(CONFIG_HPFS_FS) += hpfs/
> obj-$(CONFIG_NTFS_FS) += ntfs/
> obj-$(CONFIG_NTFS3_FS) += ntfs3/
> obj-$(CONFIG_UFS_FS) += ufs/
> -obj-$(CONFIG_EFS_FS) += efs/
> obj-$(CONFIG_JFFS2_FS) += jffs2/
> obj-$(CONFIG_UBIFS_FS) += ubifs/
> obj-$(CONFIG_AFFS_FS) += affs/
> diff --git a/fs/efs/Kconfig b/fs/efs/Kconfig
> deleted file mode 100644
> index 0833e533df9d..000000000000
> --- a/fs/efs/Kconfig
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -config EFS_FS
> - tristate "EFS file system support (read only)"
> - depends on BLOCK
> - select BUFFER_HEAD
> - help
> - EFS is an older file system used for non-ISO9660 CD-ROMs and hard
> - disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
> - uses the XFS file system for hard disk partitions however).
> -
> - This implementation only offers read-only access. If you don't know
> - what all this is about, it's safe to say N. For more information
> - about EFS see its home page at <http://aeschi.ch.eu.org/efs/>.
> -
> - To compile the EFS file system support as a module, choose M here: the
> - module will be called efs.
> diff --git a/fs/efs/Makefile b/fs/efs/Makefile
> deleted file mode 100644
> index 85e5b88f9471..000000000000
> --- a/fs/efs/Makefile
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -# Makefile for the linux efs-filesystem routines.
> -#
> -
> -obj-$(CONFIG_EFS_FS) += efs.o
> -
> -efs-objs := super.o inode.o namei.o dir.o file.o symlink.o
> diff --git a/fs/efs/dir.c b/fs/efs/dir.c
> deleted file mode 100644
> index 35ad0092c115..000000000000
> --- a/fs/efs/dir.c
> +++ /dev/null
> @@ -1,105 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * dir.c
> - *
> - * Copyright (c) 1999 Al Smith
> - */
> -
> -#include <linux/buffer_head.h>
> -#include <linux/filelock.h>
> -#include "efs.h"
> -
> -static int efs_readdir(struct file *, struct dir_context *);
> -
> -const struct file_operations efs_dir_operations = {
> - .llseek = generic_file_llseek,
> - .read = generic_read_dir,
> - .iterate_shared = efs_readdir,
> - .setlease = generic_setlease,
> -};
> -
> -const struct inode_operations efs_dir_inode_operations = {
> - .lookup = efs_lookup,
> -};
> -
> -static int efs_readdir(struct file *file, struct dir_context *ctx)
> -{
> - struct inode *inode = file_inode(file);
> - efs_block_t block;
> - int slot;
> -
> - if (inode->i_size & (EFS_DIRBSIZE-1))
> - pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
> - __func__);
> -
> - /* work out where this entry can be found */
> - block = ctx->pos >> EFS_DIRBSIZE_BITS;
> -
> - /* each block contains at most 256 slots */
> - slot = ctx->pos & 0xff;
> -
> - /* look at all blocks */
> - while (block < inode->i_blocks) {
> - struct efs_dir *dirblock;
> - struct buffer_head *bh;
> -
> - /* read the dir block */
> - bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
> -
> - if (!bh) {
> - pr_err("%s(): failed to read dir block %d\n",
> - __func__, block);
> - break;
> - }
> -
> - dirblock = (struct efs_dir *) bh->b_data;
> -
> - if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
> - pr_err("%s(): invalid directory block\n", __func__);
> - brelse(bh);
> - break;
> - }
> -
> - for (; slot < dirblock->slots; slot++) {
> - struct efs_dentry *dirslot;
> - efs_ino_t inodenum;
> - const char *nameptr;
> - int namelen;
> -
> - if (dirblock->space[slot] == 0)
> - continue;
> -
> - dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
> -
> - inodenum = be32_to_cpu(dirslot->inode);
> - namelen = dirslot->namelen;
> - nameptr = dirslot->name;
> - pr_debug("%s(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n",
> - __func__, block, slot, dirblock->slots-1,
> - inodenum, nameptr, namelen);
> - if (!namelen)
> - continue;
> - /* found the next entry */
> - ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
> -
> - /* sanity check */
> - if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
> - pr_warn("directory entry %d exceeds directory block\n",
> - slot);
> - continue;
> - }
> -
> - /* copy filename and data in dirslot */
> - if (!dir_emit(ctx, nameptr, namelen, inodenum, DT_UNKNOWN)) {
> - brelse(bh);
> - return 0;
> - }
> - }
> - brelse(bh);
> -
> - slot = 0;
> - block++;
> - }
> - ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
> - return 0;
> -}
> diff --git a/fs/efs/efs.h b/fs/efs/efs.h
> deleted file mode 100644
> index 918d2b9abb76..000000000000
> --- a/fs/efs/efs.h
> +++ /dev/null
> @@ -1,144 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * Copyright (c) 1999 Al Smith, <Al.Smith@aeschi.ch.eu.org>
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
> - * Portions derived from IRIX header files (c) 1988 Silicon Graphics
> - */
> -#ifndef _EFS_EFS_H_
> -#define _EFS_EFS_H_
> -
> -#ifdef pr_fmt
> -#undef pr_fmt
> -#endif
> -
> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -
> -#include <linux/fs.h>
> -#include <linux/uaccess.h>
> -
> -#define EFS_VERSION "1.0a"
> -
> -/* 1 block is 512 bytes */
> -#define EFS_BLOCKSIZE_BITS 9
> -#define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS)
> -
> -typedef int32_t efs_block_t;
> -typedef uint32_t efs_ino_t;
> -
> -#define EFS_DIRECTEXTENTS 12
> -
> -/*
> - * layout of an extent, in memory and on disk. 8 bytes exactly.
> - */
> -typedef union extent_u {
> - unsigned char raw[8];
> - struct extent_s {
> - unsigned int ex_magic:8; /* magic # (zero) */
> - unsigned int ex_bn:24; /* basic block */
> - unsigned int ex_length:8; /* numblocks in this extent */
> - unsigned int ex_offset:24; /* logical offset into file */
> - } cooked;
> -} efs_extent;
> -
> -typedef struct edevs {
> - __be16 odev;
> - __be32 ndev;
> -} efs_devs;
> -
> -/*
> - * extent based filesystem inode as it appears on disk. The efs inode
> - * is exactly 128 bytes long.
> - */
> -struct efs_dinode {
> - __be16 di_mode; /* mode and type of file */
> - __be16 di_nlink; /* number of links to file */
> - __be16 di_uid; /* owner's user id */
> - __be16 di_gid; /* owner's group id */
> - __be32 di_size; /* number of bytes in file */
> - __be32 di_atime; /* time last accessed */
> - __be32 di_mtime; /* time last modified */
> - __be32 di_ctime; /* time created */
> - __be32 di_gen; /* generation number */
> - __be16 di_numextents; /* # of extents */
> - u_char di_version; /* version of inode */
> - u_char di_spare; /* spare - used by AFS */
> - union di_addr {
> - efs_extent di_extents[EFS_DIRECTEXTENTS];
> - efs_devs di_dev; /* device for IFCHR/IFBLK */
> - } di_u;
> -};
> -
> -/* efs inode storage in memory */
> -struct efs_inode_info {
> - int numextents;
> - int lastextent;
> -
> - efs_extent extents[EFS_DIRECTEXTENTS];
> - struct inode vfs_inode;
> -};
> -
> -#include <linux/efs_fs_sb.h>
> -
> -#define EFS_DIRBSIZE_BITS EFS_BLOCKSIZE_BITS
> -#define EFS_DIRBSIZE (1 << EFS_DIRBSIZE_BITS)
> -
> -struct efs_dentry {
> - __be32 inode;
> - unsigned char namelen;
> - char name[3];
> -};
> -
> -#define EFS_DENTSIZE (sizeof(struct efs_dentry) - 3 + 1)
> -#define EFS_MAXNAMELEN ((1 << (sizeof(char) * 8)) - 1)
> -
> -#define EFS_DIRBLK_HEADERSIZE 4
> -#define EFS_DIRBLK_MAGIC 0xbeef /* moo */
> -
> -struct efs_dir {
> - __be16 magic;
> - unsigned char firstused;
> - unsigned char slots;
> -
> - unsigned char space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
> -};
> -
> -#define EFS_MAXENTS \
> - ((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
> - (EFS_DENTSIZE + sizeof(char)))
> -
> -#define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
> -
> -#define EFS_REALOFF(offset) ((offset << 1))
> -
> -
> -static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
> -{
> - return container_of(inode, struct efs_inode_info, vfs_inode);
> -}
> -
> -static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
> -{
> - return sb->s_fs_info;
> -}
> -
> -struct statfs;
> -struct fid;
> -
> -extern const struct inode_operations efs_dir_inode_operations;
> -extern const struct file_operations efs_dir_operations;
> -extern const struct address_space_operations efs_symlink_aops;
> -
> -extern struct inode *efs_iget(struct super_block *, unsigned long);
> -extern efs_block_t efs_map_block(struct inode *, efs_block_t);
> -extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
> -
> -extern struct dentry *efs_lookup(struct inode *, struct dentry *, unsigned int);
> -extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
> - int fh_len, int fh_type);
> -extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
> - int fh_len, int fh_type);
> -extern struct dentry *efs_get_parent(struct dentry *);
> -extern int efs_bmap(struct inode *, int);
> -
> -#endif /* _EFS_EFS_H_ */
> diff --git a/fs/efs/file.c b/fs/efs/file.c
> deleted file mode 100644
> index 9e641da6fab2..000000000000
> --- a/fs/efs/file.c
> +++ /dev/null
> @@ -1,57 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * file.c
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
> - */
> -
> -#include <linux/buffer_head.h>
> -#include "efs.h"
> -
> -int efs_get_block(struct inode *inode, sector_t iblock,
> - struct buffer_head *bh_result, int create)
> -{
> - int error = -EROFS;
> - long phys;
> -
> - if (create)
> - return error;
> - if (iblock >= inode->i_blocks) {
> -#ifdef DEBUG
> - /*
> - * i have no idea why this happens as often as it does
> - */
> - pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
> - __func__, block, inode->i_blocks, inode->i_size);
> -#endif
> - return 0;
> - }
> - phys = efs_map_block(inode, iblock);
> - if (phys)
> - map_bh(bh_result, inode->i_sb, phys);
> - return 0;
> -}
> -
> -int efs_bmap(struct inode *inode, efs_block_t block) {
> -
> - if (block < 0) {
> - pr_warn("%s(): block < 0\n", __func__);
> - return 0;
> - }
> -
> - /* are we about to read past the end of a file ? */
> - if (!(block < inode->i_blocks)) {
> -#ifdef DEBUG
> - /*
> - * i have no idea why this happens as often as it does
> - */
> - pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
> - __func__, block, inode->i_blocks, inode->i_size);
> -#endif
> - return 0;
> - }
> -
> - return efs_map_block(inode, block);
> -}
> diff --git a/fs/efs/inode.c b/fs/efs/inode.c
> deleted file mode 100644
> index 4b132729e638..000000000000
> --- a/fs/efs/inode.c
> +++ /dev/null
> @@ -1,315 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * inode.c
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
> - * and from work (c) 1998 Mike Shaver.
> - */
> -
> -#include <linux/buffer_head.h>
> -#include <linux/module.h>
> -#include <linux/fs.h>
> -#include "efs.h"
> -#include <linux/efs_fs_sb.h>
> -
> -static int efs_read_folio(struct file *file, struct folio *folio)
> -{
> - return block_read_full_folio(folio, efs_get_block);
> -}
> -
> -static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
> -{
> - return generic_block_bmap(mapping,block,efs_get_block);
> -}
> -
> -static const struct address_space_operations efs_aops = {
> - .read_folio = efs_read_folio,
> - .bmap = _efs_bmap
> -};
> -
> -static inline void extent_copy(efs_extent *src, efs_extent *dst) {
> - /*
> - * this is slightly evil. it doesn't just copy
> - * efs_extent from src to dst, it also mangles
> - * the bits so that dst ends up in cpu byte-order.
> - */
> -
> - dst->cooked.ex_magic = (unsigned int) src->raw[0];
> - dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) |
> - ((unsigned int) src->raw[2] << 8) |
> - ((unsigned int) src->raw[3] << 0);
> - dst->cooked.ex_length = (unsigned int) src->raw[4];
> - dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
> - ((unsigned int) src->raw[6] << 8) |
> - ((unsigned int) src->raw[7] << 0);
> - return;
> -}
> -
> -struct inode *efs_iget(struct super_block *super, unsigned long ino)
> -{
> - int i, inode_index;
> - dev_t device;
> - u32 rdev;
> - struct buffer_head *bh;
> - struct efs_sb_info *sb = SUPER_INFO(super);
> - struct efs_inode_info *in;
> - efs_block_t block, offset;
> - struct efs_dinode *efs_inode;
> - struct inode *inode;
> -
> - inode = iget_locked(super, ino);
> - if (!inode)
> - return ERR_PTR(-ENOMEM);
> - if (!(inode_state_read_once(inode) & I_NEW))
> - return inode;
> -
> - in = INODE_INFO(inode);
> -
> - /*
> - ** EFS layout:
> - **
> - ** | cylinder group | cylinder group | cylinder group ..etc
> - ** |inodes|data |inodes|data |inodes|data ..etc
> - **
> - ** work out the inode block index, (considering initially that the
> - ** inodes are stored as consecutive blocks). then work out the block
> - ** number of that inode given the above layout, and finally the
> - ** offset of the inode within that block.
> - */
> -
> - inode_index = inode->i_ino /
> - (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
> -
> - block = sb->fs_start + sb->first_block +
> - (sb->group_size * (inode_index / sb->inode_blocks)) +
> - (inode_index % sb->inode_blocks);
> -
> - offset = (inode->i_ino %
> - (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
> - sizeof(struct efs_dinode);
> -
> - bh = sb_bread(inode->i_sb, block);
> - if (!bh) {
> - pr_warn("%s() failed at block %d\n", __func__, block);
> - goto read_inode_error;
> - }
> -
> - efs_inode = (struct efs_dinode *) (bh->b_data + offset);
> -
> - inode->i_mode = be16_to_cpu(efs_inode->di_mode);
> - set_nlink(inode, be16_to_cpu(efs_inode->di_nlink));
> - i_uid_write(inode, (uid_t)be16_to_cpu(efs_inode->di_uid));
> - i_gid_write(inode, (gid_t)be16_to_cpu(efs_inode->di_gid));
> - inode->i_size = be32_to_cpu(efs_inode->di_size);
> - inode_set_atime(inode, be32_to_cpu(efs_inode->di_atime), 0);
> - inode_set_mtime(inode, be32_to_cpu(efs_inode->di_mtime), 0);
> - inode_set_ctime(inode, be32_to_cpu(efs_inode->di_ctime), 0);
> -
> - /* this is the number of blocks in the file */
> - if (inode->i_size == 0) {
> - inode->i_blocks = 0;
> - } else {
> - inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
> - }
> -
> - rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev);
> - if (rdev == 0xffff) {
> - rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev);
> - if (sysv_major(rdev) > 0xfff)
> - device = 0;
> - else
> - device = MKDEV(sysv_major(rdev), sysv_minor(rdev));
> - } else
> - device = old_decode_dev(rdev);
> -
> - /* get the number of extents for this object */
> - in->numextents = be16_to_cpu(efs_inode->di_numextents);
> - in->lastextent = 0;
> -
> - /* copy the extents contained within the inode to memory */
> - for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
> - extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
> - if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
> - pr_warn("extent %d has bad magic number in inode %llu\n",
> - i, inode->i_ino);
> - brelse(bh);
> - goto read_inode_error;
> - }
> - }
> -
> - brelse(bh);
> - pr_debug("efs_iget(): inode %llu, extents %d, mode %o\n",
> - inode->i_ino, in->numextents, inode->i_mode);
> - switch (inode->i_mode & S_IFMT) {
> - case S_IFDIR:
> - inode->i_op = &efs_dir_inode_operations;
> - inode->i_fop = &efs_dir_operations;
> - break;
> - case S_IFREG:
> - inode->i_fop = &generic_ro_fops;
> - inode->i_data.a_ops = &efs_aops;
> - break;
> - case S_IFLNK:
> - inode->i_op = &page_symlink_inode_operations;
> - inode_nohighmem(inode);
> - inode->i_data.a_ops = &efs_symlink_aops;
> - break;
> - case S_IFCHR:
> - case S_IFBLK:
> - case S_IFIFO:
> - init_special_inode(inode, inode->i_mode, device);
> - break;
> - default:
> - pr_warn("unsupported inode mode %o\n", inode->i_mode);
> - goto read_inode_error;
> - break;
> - }
> -
> - unlock_new_inode(inode);
> - return inode;
> -
> -read_inode_error:
> - pr_warn("failed to read inode %llu\n", inode->i_ino);
> - iget_failed(inode);
> - return ERR_PTR(-EIO);
> -}
> -
> -static inline efs_block_t
> -efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
> - efs_block_t start;
> - efs_block_t length;
> - efs_block_t offset;
> -
> - /*
> - * given an extent and a logical block within a file,
> - * can this block be found within this extent ?
> - */
> - start = ptr->cooked.ex_bn;
> - length = ptr->cooked.ex_length;
> - offset = ptr->cooked.ex_offset;
> -
> - if ((block >= offset) && (block < offset+length)) {
> - return(sb->fs_start + start + block - offset);
> - } else {
> - return 0;
> - }
> -}
> -
> -efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
> - struct efs_sb_info *sb = SUPER_INFO(inode->i_sb);
> - struct efs_inode_info *in = INODE_INFO(inode);
> - struct buffer_head *bh = NULL;
> -
> - int cur, last, first = 1;
> - int ibase, ioffset, dirext, direxts, indext, indexts;
> - efs_block_t iblock, result = 0, lastblock = 0;
> - efs_extent ext, *exts;
> -
> - last = in->lastextent;
> -
> - if (in->numextents <= EFS_DIRECTEXTENTS) {
> - /* first check the last extent we returned */
> - if ((result = efs_extent_check(&in->extents[last], block, sb)))
> - return result;
> -
> - /* if we only have one extent then nothing can be found */
> - if (in->numextents == 1) {
> - pr_err("%s() failed to map (1 extent)\n", __func__);
> - return 0;
> - }
> -
> - direxts = in->numextents;
> -
> - /*
> - * check the stored extents in the inode
> - * start with next extent and check forwards
> - */
> - for(dirext = 1; dirext < direxts; dirext++) {
> - cur = (last + dirext) % in->numextents;
> - if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
> - in->lastextent = cur;
> - return result;
> - }
> - }
> -
> - pr_err("%s() failed to map block %u (dir)\n", __func__, block);
> - return 0;
> - }
> -
> - pr_debug("%s(): indirect search for logical block %u\n",
> - __func__, block);
> - direxts = in->extents[0].cooked.ex_offset;
> - indexts = in->numextents;
> -
> - for(indext = 0; indext < indexts; indext++) {
> - cur = (last + indext) % indexts;
> -
> - /*
> - * work out which direct extent contains `cur'.
> - *
> - * also compute ibase: i.e. the number of the first
> - * indirect extent contained within direct extent `cur'.
> - *
> - */
> - ibase = 0;
> - for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
> - ibase += in->extents[dirext].cooked.ex_length *
> - (EFS_BLOCKSIZE / sizeof(efs_extent));
> - }
> -
> - if (dirext == direxts) {
> - /* should never happen */
> - pr_err("couldn't find direct extent for indirect extent %d (block %u)\n",
> - cur, block);
> - if (bh) brelse(bh);
> - return 0;
> - }
> -
> - /* work out block number and offset of this indirect extent */
> - iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
> - (cur - ibase) /
> - (EFS_BLOCKSIZE / sizeof(efs_extent));
> - ioffset = (cur - ibase) %
> - (EFS_BLOCKSIZE / sizeof(efs_extent));
> -
> - if (first || lastblock != iblock) {
> - if (bh) brelse(bh);
> -
> - bh = sb_bread(inode->i_sb, iblock);
> - if (!bh) {
> - pr_err("%s() failed at block %d\n",
> - __func__, iblock);
> - return 0;
> - }
> - pr_debug("%s(): read indirect extent block %d\n",
> - __func__, iblock);
> - first = 0;
> - lastblock = iblock;
> - }
> -
> - exts = (efs_extent *) bh->b_data;
> -
> - extent_copy(&(exts[ioffset]), &ext);
> -
> - if (ext.cooked.ex_magic != 0) {
> - pr_err("extent %d has bad magic number in block %d\n",
> - cur, iblock);
> - if (bh) brelse(bh);
> - return 0;
> - }
> -
> - if ((result = efs_extent_check(&ext, block, sb))) {
> - if (bh) brelse(bh);
> - in->lastextent = cur;
> - return result;
> - }
> - }
> - if (bh) brelse(bh);
> - pr_err("%s() failed to map block %u (indir)\n", __func__, block);
> - return 0;
> -}
> -
> -MODULE_DESCRIPTION("Extent File System (efs)");
> -MODULE_LICENSE("GPL");
> diff --git a/fs/efs/namei.c b/fs/efs/namei.c
> deleted file mode 100644
> index 38961ee1d1af..000000000000
> --- a/fs/efs/namei.c
> +++ /dev/null
> @@ -1,120 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * namei.c
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
> - */
> -
> -#include <linux/buffer_head.h>
> -#include <linux/string.h>
> -#include <linux/exportfs.h>
> -#include "efs.h"
> -
> -
> -static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
> -{
> - struct buffer_head *bh;
> -
> - int slot, namelen;
> - char *nameptr;
> - struct efs_dir *dirblock;
> - struct efs_dentry *dirslot;
> - efs_ino_t inodenum;
> - efs_block_t block;
> -
> - if (inode->i_size & (EFS_DIRBSIZE-1))
> - pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
> - __func__);
> -
> - for(block = 0; block < inode->i_blocks; block++) {
> -
> - bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
> - if (!bh) {
> - pr_err("%s(): failed to read dir block %d\n",
> - __func__, block);
> - return 0;
> - }
> -
> - dirblock = (struct efs_dir *) bh->b_data;
> -
> - if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
> - pr_err("%s(): invalid directory block\n", __func__);
> - brelse(bh);
> - return 0;
> - }
> -
> - for (slot = 0; slot < dirblock->slots; slot++) {
> - dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
> -
> - namelen = dirslot->namelen;
> - nameptr = dirslot->name;
> -
> - if ((namelen == len) && (!memcmp(name, nameptr, len))) {
> - inodenum = be32_to_cpu(dirslot->inode);
> - brelse(bh);
> - return inodenum;
> - }
> - }
> - brelse(bh);
> - }
> - return 0;
> -}
> -
> -struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
> -{
> - efs_ino_t inodenum;
> - struct inode *inode = NULL;
> -
> - inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
> - if (inodenum)
> - inode = efs_iget(dir->i_sb, inodenum);
> -
> - return d_splice_alias(inode, dentry);
> -}
> -
> -static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
> - u32 generation)
> -{
> - struct inode *inode;
> -
> - if (ino == 0)
> - return ERR_PTR(-ESTALE);
> - inode = efs_iget(sb, ino);
> - if (IS_ERR(inode))
> - return ERR_CAST(inode);
> -
> - if (generation && inode->i_generation != generation) {
> - iput(inode);
> - return ERR_PTR(-ESTALE);
> - }
> -
> - return inode;
> -}
> -
> -struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
> - int fh_len, int fh_type)
> -{
> - return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
> - efs_nfs_get_inode);
> -}
> -
> -struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
> - int fh_len, int fh_type)
> -{
> - return generic_fh_to_parent(sb, fid, fh_len, fh_type,
> - efs_nfs_get_inode);
> -}
> -
> -struct dentry *efs_get_parent(struct dentry *child)
> -{
> - struct dentry *parent = ERR_PTR(-ENOENT);
> - efs_ino_t ino;
> -
> - ino = efs_find_entry(d_inode(child), "..", 2);
> - if (ino)
> - parent = d_obtain_alias(efs_iget(child->d_sb, ino));
> -
> - return parent;
> -}
> diff --git a/fs/efs/super.c b/fs/efs/super.c
> deleted file mode 100644
> index 11fea3bbce7c..000000000000
> --- a/fs/efs/super.c
> +++ /dev/null
> @@ -1,368 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * super.c
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
> - */
> -
> -#include <linux/init.h>
> -#include <linux/module.h>
> -#include <linux/exportfs.h>
> -#include <linux/slab.h>
> -#include <linux/buffer_head.h>
> -#include <linux/vfs.h>
> -#include <linux/blkdev.h>
> -#include <linux/fs_context.h>
> -#include "efs.h"
> -#include <linux/efs_vh.h>
> -#include <linux/efs_fs_sb.h>
> -
> -static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
> -static int efs_init_fs_context(struct fs_context *fc);
> -
> -static void efs_kill_sb(struct super_block *s)
> -{
> - struct efs_sb_info *sbi = SUPER_INFO(s);
> - kill_block_super(s);
> - kfree(sbi);
> -}
> -
> -static struct pt_types sgi_pt_types[] = {
> - {0x00, "SGI vh"},
> - {0x01, "SGI trkrepl"},
> - {0x02, "SGI secrepl"},
> - {0x03, "SGI raw"},
> - {0x04, "SGI bsd"},
> - {SGI_SYSV, "SGI sysv"},
> - {0x06, "SGI vol"},
> - {SGI_EFS, "SGI efs"},
> - {0x08, "SGI lv"},
> - {0x09, "SGI rlv"},
> - {0x0A, "SGI xfs"},
> - {0x0B, "SGI xfslog"},
> - {0x0C, "SGI xlv"},
> - {0x82, "Linux swap"},
> - {0x83, "Linux native"},
> - {0, NULL}
> -};
> -
> -/*
> - * File system definition and registration.
> - */
> -static struct file_system_type efs_fs_type = {
> - .owner = THIS_MODULE,
> - .name = "efs",
> - .kill_sb = efs_kill_sb,
> - .fs_flags = FS_REQUIRES_DEV,
> - .init_fs_context = efs_init_fs_context,
> -};
> -MODULE_ALIAS_FS("efs");
> -
> -static struct kmem_cache * efs_inode_cachep;
> -
> -static struct inode *efs_alloc_inode(struct super_block *sb)
> -{
> - struct efs_inode_info *ei;
> - ei = alloc_inode_sb(sb, efs_inode_cachep, GFP_KERNEL);
> - if (!ei)
> - return NULL;
> - return &ei->vfs_inode;
> -}
> -
> -static void efs_free_inode(struct inode *inode)
> -{
> - kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
> -}
> -
> -static void init_once(void *foo)
> -{
> - struct efs_inode_info *ei = (struct efs_inode_info *) foo;
> -
> - inode_init_once(&ei->vfs_inode);
> -}
> -
> -static int __init init_inodecache(void)
> -{
> - efs_inode_cachep = kmem_cache_create("efs_inode_cache",
> - sizeof(struct efs_inode_info), 0,
> - SLAB_RECLAIM_ACCOUNT|SLAB_ACCOUNT,
> - init_once);
> - if (efs_inode_cachep == NULL)
> - return -ENOMEM;
> - return 0;
> -}
> -
> -static void destroy_inodecache(void)
> -{
> - /*
> - * Make sure all delayed rcu free inodes are flushed before we
> - * destroy cache.
> - */
> - rcu_barrier();
> - kmem_cache_destroy(efs_inode_cachep);
> -}
> -
> -static const struct super_operations efs_superblock_operations = {
> - .alloc_inode = efs_alloc_inode,
> - .free_inode = efs_free_inode,
> - .statfs = efs_statfs,
> -};
> -
> -static const struct export_operations efs_export_ops = {
> - .encode_fh = generic_encode_ino32_fh,
> - .fh_to_dentry = efs_fh_to_dentry,
> - .fh_to_parent = efs_fh_to_parent,
> - .get_parent = efs_get_parent,
> -};
> -
> -static int __init init_efs_fs(void) {
> - int err;
> - pr_info(EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
> - err = init_inodecache();
> - if (err)
> - goto out1;
> - err = register_filesystem(&efs_fs_type);
> - if (err)
> - goto out;
> - return 0;
> -out:
> - destroy_inodecache();
> -out1:
> - return err;
> -}
> -
> -static void __exit exit_efs_fs(void) {
> - unregister_filesystem(&efs_fs_type);
> - destroy_inodecache();
> -}
> -
> -module_init(init_efs_fs)
> -module_exit(exit_efs_fs)
> -
> -static efs_block_t efs_validate_vh(struct volume_header *vh) {
> - int i;
> - __be32 cs, *ui;
> - int csum;
> - efs_block_t sblock = 0; /* shuts up gcc */
> - struct pt_types *pt_entry;
> - int pt_type, slice = -1;
> -
> - if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
> - /*
> - * assume that we're dealing with a partition and allow
> - * read_super() to try and detect a valid superblock
> - * on the next block.
> - */
> - return 0;
> - }
> -
> - ui = ((__be32 *) (vh + 1)) - 1;
> - for(csum = 0; ui >= ((__be32 *) vh);) {
> - cs = *ui--;
> - csum += be32_to_cpu(cs);
> - }
> - if (csum) {
> - pr_warn("SGI disklabel: checksum bad, label corrupted\n");
> - return 0;
> - }
> -
> -#ifdef DEBUG
> - pr_debug("bf: \"%16s\"\n", vh->vh_bootfile);
> -
> - for(i = 0; i < NVDIR; i++) {
> - int j;
> - char name[VDNAMESIZE+1];
> -
> - for(j = 0; j < VDNAMESIZE; j++) {
> - name[j] = vh->vh_vd[i].vd_name[j];
> - }
> - name[j] = (char) 0;
> -
> - if (name[0]) {
> - pr_debug("vh: %8s block: 0x%08x size: 0x%08x\n",
> - name, (int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
> - (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
> - }
> - }
> -#endif
> -
> - for(i = 0; i < NPARTAB; i++) {
> - pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
> - for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
> - if (pt_type == pt_entry->pt_type) break;
> - }
> -#ifdef DEBUG
> - if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
> - pr_debug("pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
> - i, (int)be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
> - (int)be32_to_cpu(vh->vh_pt[i].pt_nblks),
> - pt_type, (pt_entry->pt_name) ?
> - pt_entry->pt_name : "unknown");
> - }
> -#endif
> - if (IS_EFS(pt_type)) {
> - sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
> - slice = i;
> - }
> - }
> -
> - if (slice == -1) {
> - pr_notice("partition table contained no EFS partitions\n");
> -#ifdef DEBUG
> - } else {
> - pr_info("using slice %d (type %s, offset 0x%x)\n", slice,
> - (pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
> - sblock);
> -#endif
> - }
> - return sblock;
> -}
> -
> -static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
> -
> - if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic)))
> - return -1;
> -
> - sb->fs_magic = be32_to_cpu(super->fs_magic);
> - sb->total_blocks = be32_to_cpu(super->fs_size);
> - sb->first_block = be32_to_cpu(super->fs_firstcg);
> - sb->group_size = be32_to_cpu(super->fs_cgfsize);
> - sb->data_free = be32_to_cpu(super->fs_tfree);
> - sb->inode_free = be32_to_cpu(super->fs_tinode);
> - sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
> - sb->total_groups = be16_to_cpu(super->fs_ncg);
> -
> - return 0;
> -}
> -
> -static int efs_fill_super(struct super_block *s, struct fs_context *fc)
> -{
> - struct efs_sb_info *sb;
> - struct buffer_head *bh;
> - struct inode *root;
> -
> - sb = kzalloc_obj(struct efs_sb_info);
> - if (!sb)
> - return -ENOMEM;
> - s->s_fs_info = sb;
> - s->s_time_min = 0;
> - s->s_time_max = U32_MAX;
> -
> - s->s_magic = EFS_SUPER_MAGIC;
> - if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
> - pr_err("device does not support %d byte blocks\n",
> - EFS_BLOCKSIZE);
> - return invalf(fc, "device does not support %d byte blocks\n",
> - EFS_BLOCKSIZE);
> - }
> -
> - /* read the vh (volume header) block */
> - bh = sb_bread(s, 0);
> -
> - if (!bh) {
> - pr_err("cannot read volume header\n");
> - return -EIO;
> - }
> -
> - /*
> - * if this returns zero then we didn't find any partition table.
> - * this isn't (yet) an error - just assume for the moment that
> - * the device is valid and go on to search for a superblock.
> - */
> - sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
> - brelse(bh);
> -
> - if (sb->fs_start == -1) {
> - return -EINVAL;
> - }
> -
> - bh = sb_bread(s, sb->fs_start + EFS_SUPER);
> - if (!bh) {
> - pr_err("cannot read superblock\n");
> - return -EIO;
> - }
> -
> - if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
> -#ifdef DEBUG
> - pr_warn("invalid superblock at block %u\n",
> - sb->fs_start + EFS_SUPER);
> -#endif
> - brelse(bh);
> - return -EINVAL;
> - }
> - brelse(bh);
> -
> - if (!sb_rdonly(s)) {
> -#ifdef DEBUG
> - pr_info("forcing read-only mode\n");
> -#endif
> - s->s_flags |= SB_RDONLY;
> - }
> - s->s_op = &efs_superblock_operations;
> - s->s_export_op = &efs_export_ops;
> - root = efs_iget(s, EFS_ROOTINODE);
> - if (IS_ERR(root)) {
> - pr_err("get root inode failed\n");
> - return PTR_ERR(root);
> - }
> -
> - s->s_root = d_make_root(root);
> - if (!(s->s_root)) {
> - pr_err("get root dentry failed\n");
> - return -ENOMEM;
> - }
> -
> - return 0;
> -}
> -
> -static int efs_get_tree(struct fs_context *fc)
> -{
> - return get_tree_bdev(fc, efs_fill_super);
> -}
> -
> -static int efs_reconfigure(struct fs_context *fc)
> -{
> - sync_filesystem(fc->root->d_sb);
> - fc->sb_flags |= SB_RDONLY;
> -
> - return 0;
> -}
> -
> -static const struct fs_context_operations efs_context_opts = {
> - .get_tree = efs_get_tree,
> - .reconfigure = efs_reconfigure,
> -};
> -
> -/*
> - * Set up the filesystem mount context.
> - */
> -static int efs_init_fs_context(struct fs_context *fc)
> -{
> - fc->ops = &efs_context_opts;
> -
> - return 0;
> -}
> -
> -static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
> - struct super_block *sb = dentry->d_sb;
> - struct efs_sb_info *sbi = SUPER_INFO(sb);
> - u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
> -
> - buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
> - buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
> - buf->f_blocks = sbi->total_groups * /* total data blocks */
> - (sbi->group_size - sbi->inode_blocks);
> - buf->f_bfree = sbi->data_free; /* free data blocks */
> - buf->f_bavail = sbi->data_free; /* free blocks for non-root */
> - buf->f_files = sbi->total_groups * /* total inodes */
> - sbi->inode_blocks *
> - (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
> - buf->f_ffree = sbi->inode_free; /* free inodes */
> - buf->f_fsid = u64_to_fsid(id);
> - buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */
> -
> - return 0;
> -}
> -
> diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
> deleted file mode 100644
> index 7749feded722..000000000000
> --- a/fs/efs/symlink.c
> +++ /dev/null
> @@ -1,50 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * symlink.c
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
> - */
> -
> -#include <linux/string.h>
> -#include <linux/pagemap.h>
> -#include <linux/buffer_head.h>
> -#include "efs.h"
> -
> -static int efs_symlink_read_folio(struct file *file, struct folio *folio)
> -{
> - char *link = folio_address(folio);
> - struct buffer_head *bh;
> - struct inode *inode = folio->mapping->host;
> - efs_block_t size = inode->i_size;
> - int err;
> -
> - err = -ENAMETOOLONG;
> - if (size > 2 * EFS_BLOCKSIZE)
> - goto fail;
> -
> - /* read first 512 bytes of link target */
> - err = -EIO;
> - bh = sb_bread(inode->i_sb, efs_bmap(inode, 0));
> - if (!bh)
> - goto fail;
> - memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
> - brelse(bh);
> - if (size > EFS_BLOCKSIZE) {
> - bh = sb_bread(inode->i_sb, efs_bmap(inode, 1));
> - if (!bh)
> - goto fail;
> - memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
> - brelse(bh);
> - }
> - link[size] = '\0';
> - err = 0;
> -fail:
> - folio_end_read(folio, err == 0);
> - return err;
> -}
> -
> -const struct address_space_operations efs_symlink_aops = {
> - .read_folio = efs_symlink_read_folio
> -};
> diff --git a/include/linux/efs_vh.h b/include/linux/efs_vh.h
> deleted file mode 100644
> index 206c5270f7b8..000000000000
> --- a/include/linux/efs_vh.h
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * efs_vh.h
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from IRIX header files (c) 1985 MIPS Computer Systems, Inc.
> - */
> -
> -#ifndef __EFS_VH_H__
> -#define __EFS_VH_H__
> -
> -#define VHMAGIC 0xbe5a941 /* volume header magic number */
> -#define NPARTAB 16 /* 16 unix partitions */
> -#define NVDIR 15 /* max of 15 directory entries */
> -#define BFNAMESIZE 16 /* max 16 chars in boot file name */
> -#define VDNAMESIZE 8
> -
> -struct volume_directory {
> - char vd_name[VDNAMESIZE]; /* name */
> - __be32 vd_lbn; /* logical block number */
> - __be32 vd_nbytes; /* file length in bytes */
> -};
> -
> -struct partition_table { /* one per logical partition */
> - __be32 pt_nblks; /* # of logical blks in partition */
> - __be32 pt_firstlbn; /* first lbn of partition */
> - __be32 pt_type; /* use of partition */
> -};
> -
> -struct volume_header {
> - __be32 vh_magic; /* identifies volume header */
> - __be16 vh_rootpt; /* root partition number */
> - __be16 vh_swappt; /* swap partition number */
> - char vh_bootfile[BFNAMESIZE]; /* name of file to boot */
> - char pad[48]; /* device param space */
> - struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
> - struct partition_table vh_pt[NPARTAB]; /* device partition layout */
> - __be32 vh_csum; /* volume header checksum */
> - __be32 vh_fill; /* fill out to 512 bytes */
> -};
> -
> -/* partition type sysv is used for EFS format CD-ROM partitions */
> -#define SGI_SYSV 0x05
> -#define SGI_EFS 0x07
> -#define IS_EFS(x) (((x) == SGI_EFS) || ((x) == SGI_SYSV))
> -
> -struct pt_types {
> - int pt_type;
> - char *pt_name;
> -};
> -
> -#endif /* __EFS_VH_H__ */
> -
> diff --git a/include/uapi/linux/efs_fs_sb.h b/include/uapi/linux/efs_fs_sb.h
> deleted file mode 100644
> index 6bad29a10faa..000000000000
> --- a/include/uapi/linux/efs_fs_sb.h
> +++ /dev/null
> @@ -1,63 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> -/*
> - * efs_fs_sb.h
> - *
> - * Copyright (c) 1999 Al Smith
> - *
> - * Portions derived from IRIX header files (c) 1988 Silicon Graphics
> - */
> -
> -#ifndef __EFS_FS_SB_H__
> -#define __EFS_FS_SB_H__
> -
> -#include <linux/types.h>
> -#include <linux/magic.h>
> -
> -/* EFS superblock magic numbers */
> -#define EFS_MAGIC 0x072959
> -#define EFS_NEWMAGIC 0x07295a
> -
> -#define IS_EFS_MAGIC(x) ((x == EFS_MAGIC) || (x == EFS_NEWMAGIC))
> -
> -#define EFS_SUPER 1
> -#define EFS_ROOTINODE 2
> -
> -/* efs superblock on disk */
> -struct efs_super {
> - __be32 fs_size; /* size of filesystem, in sectors */
> - __be32 fs_firstcg; /* bb offset to first cg */
> - __be32 fs_cgfsize; /* size of cylinder group in bb's */
> - __be16 fs_cgisize; /* bb's of inodes per cylinder group */
> - __be16 fs_sectors; /* sectors per track */
> - __be16 fs_heads; /* heads per cylinder */
> - __be16 fs_ncg; /* # of cylinder groups in filesystem */
> - __be16 fs_dirty; /* fs needs to be fsck'd */
> - __be32 fs_time; /* last super-block update */
> - __be32 fs_magic; /* magic number */
> - char fs_fname[6]; /* file system name */
> - char fs_fpack[6]; /* file system pack name */
> - __be32 fs_bmsize; /* size of bitmap in bytes */
> - __be32 fs_tfree; /* total free data blocks */
> - __be32 fs_tinode; /* total free inodes */
> - __be32 fs_bmblock; /* bitmap location. */
> - __be32 fs_replsb; /* Location of replicated superblock. */
> - __be32 fs_lastialloc; /* last allocated inode */
> - char fs_spare[20]; /* space for expansion - MUST BE ZERO */
> - __be32 fs_checksum; /* checksum of volume portion of fs */
> -};
> -
> -/* efs superblock information in memory */
> -struct efs_sb_info {
> - __u32 fs_magic; /* superblock magic number */
> - __u32 fs_start; /* first block of filesystem */
> - __u32 first_block; /* first data block in filesystem */
> - __u32 total_blocks; /* total number of blocks in filesystem */
> - __u32 group_size; /* # of blocks a group consists of */
> - __u32 data_free; /* # of free data blocks */
> - __u32 inode_free; /* # of free inodes */
> - __u16 inode_blocks; /* # of blocks used for inodes in every grp */
> - __u16 total_groups; /* # of groups */
> -};
> -
> -#endif /* __EFS_FS_SB_H__ */
> -
> --
> 2.47.3
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-25 19:42 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 21:18 [PATCH] efs: Remove EFS Matthew Wilcox (Oracle)
2026-06-19 9:28 ` Jori Koolstra
2026-06-19 10:06 ` Pedro Falcato
2026-06-19 10:19 ` Jori Koolstra
2026-06-21 21:44 ` Matthew Wilcox
2026-06-23 9:17 ` Jori Koolstra
2026-06-25 19:42 ` Darrick J. Wong
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.