18 Dec, 2010

2 commits

  • The current tile rt_sigreturn() syscall pattern uses the common idiom
    of loading up pt_regs with all the saved registers from the time of
    the signal, then anticipating the fact that we will clobber the ABI
    "return value" register (r0) as we return from the syscall by setting
    the rt_sigreturn return value to whatever random value was in the pt_regs
    for r0.

    However, this breaks in our 64-bit kernel when running "compat" tasks,
    since we always sign-extend the "return value" register to properly
    handle returned pointers that are in the upper 2GB of the 32-bit compat
    address space. Doing this to the sigreturn path then causes occasional
    random corruption of the 64-bit r0 register.

    Instead, we stop doing the crazy "load the return-value register"
    hack in sigreturn. We already have some sigreturn-specific assembly
    code that we use to pass the pt_regs pointer to C code. We extend that
    code to also set the link register to point to a spot a few instructions
    after the usual syscall return address so we don't clobber the saved r0.
    Now it no longer matters what the rt_sigreturn syscall returns, and the
    pt_regs structure can be cleanly and completely reloaded.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • Previously we were just setting up the "tp" register in the
    new task as started by clone() in libc. However, this is not
    quite right, since in principle a signal might be delivered to
    the new task before it had its TLS set up. (Of course, this race
    window still exists for resetting the libc getpid() cached value
    in the new task, in principle. But in any case, we are now doing
    this exactly the way all other architectures do it.)

    This change is important for 2.6.37 since the tile glibc we will
    be submitting upstream will not set TLS in user space any more,
    so it will only work on a kernel that has this fix. It should
    also be taken for 2.6.36.x in the stable tree if possible.

    Signed-off-by: Chris Metcalf
    Cc: stable

    Chris Metcalf
     

25 Nov, 2010

7 commits

  • * git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
    arch/tile: fix memchr() not to dereference memory for zero length
    arch/tile: make glibc's sysconf(_SC_NPROCESSORS_CONF) work correctly
    arch/tile: fix rwlock so would-be write lockers don't block new readers

    Linus Torvalds
     
  • * 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
    pci root complex: support for tile architecture
    drivers/net/tile/: on-chip network drivers for the tile architecture
    MAINTAINERS: add drivers/char/hvc_tile.c as maintained by tile

    Linus Torvalds
     
  • This change fixes a bug that memchr() will read the first word
    of the source even if the length is zero. Ironically, the code
    was originally written with a test to avoid exactly this problem,
    but to make the code conform to Linux coding standards with all
    declarations preceding all statements, the first load from memory
    was moved up above that test as the initial value for a variable.

    The change just moves all the variable declarations to the top
    of the file, with no initializers, so that the test can also be
    at the top of the file.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • glibc assumes that it can count /sys/devices/system/cpu/cpu* to get
    the number of configured cpus. For this to be valid on tile, we need
    to generate a "cpu" entry for all cpus, including the ones that are
    not currently allocated for Linux's use.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • Chris Metcalf
     
  • This change enables PCI root complex support for TILEPro. Unlike
    TILE-Gx, TILEPro has no support for memory-mapped I/O, so the PCI
    support consists of hypervisor upcalls for PIO, DMA, etc. However,
    the performance is fine for the devices we have tested with so far
    (1Gb Ethernet, SATA, etc.).

    The header was tweaked to be a little bit more aggressive
    about disabling attempts to map/unmap IO port space. The hacky
    header was rolled into the header
    and the result was simplified. Both of the latter two headers were
    preliminary versions not meant for release before now - oh well.

    There is one quirk for our TILEmpower platform, which accidentally
    negotiates up to 5GT and needs to be kicked down to 2.5GT.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • This change adds the first network driver for the tile architecture,
    supporting the on-chip XGBE and GBE shims.

    The infrastructure is present for the TILE-Gx networking drivers (another
    three source files in the new directory) but for now the the actual
    tilegx sources are waiting on releasing hardware to initial customers.

    Note that arch/tile/include/hv/* are "upstream" headers from the
    Tilera hypervisor and will probably benefit less from LKML review.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     

18 Nov, 2010

1 commit


15 Nov, 2010

1 commit

  • This avoids a deadlock in the IGMP code where one core gets a read
    lock, another core starts trying to get a write lock (thus blocking
    new readers), and then the first core tries to recursively re-acquire
    the read lock.

    We still try to preserve some degree of balance by giving priority
    to additional write lockers that come along while the lock is held
    for write, so they can all complete quickly and return the lock to
    the readers.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     

02 Nov, 2010

7 commits

  • Arnd's recent patch series tagged this device with noop_llseek,
    conservatively. In fact, it should be no_llseek, which we arrange
    for by opening the device with nonseekable_open().

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • The existing asm-generic/stat.h specifies st_mtime, etc., as a 32-value,
    and works well for 32-bit architectures (currently microblaze, score,
    and 32-bit tile). However, for 64-bit architectures it isn't sufficient
    to return 32 bits of time_t; this isn't good insurance against the 2037
    rollover. (It also makes glibc support less convenient, since we can't
    use glibc's handy STAT_IS_KERNEL_STAT mode.)

    This change extends the two "timespec" fields for each of the three atime,
    mtime, and ctime fields from "int" to "long". As a result, on 32-bit
    platforms nothing changes, and 64-bit platforms will now work as expected.

    The only wrinkle is 32-bit userspace under 64-bit kernels taking advantage
    of COMPAT mode. For these, we leave the "struct stat64" definitions with
    the "int" versions of the time_t and nsec fields, so that architectures
    can implement compat_sys_stat64() and friends with sys_stat64(), etc.,
    and get the expected 32-bit structure layout. This requires a
    field-by-field copy in the kernel, implemented by the code guarded
    under __ARCH_WANT_STAT64.

    This does mean that the shape of the "struct stat" and "struct stat64"
    structures is different on a 64-bit kernel, but only one of the two
    structures should ever be used by any given process: "struct stat"
    is meant for 64-bit userspace only, and "struct stat64" for 32-bit
    userspace only. (On a 32-bit kernel the two structures continue to have
    the same shape, since "long" is 32 bits.)

    The alternative is keeping the two structures the same shape on 64-bit
    kernels, which means a 64-bit time_t in "struct stat64" for 32-bit
    processes. This is a little unnatural since 32-bit userspace can't
    do anything with 64 bits of time_t information, since time_t is just
    "long", not "int64_t"; and in any case 32-bit userspace might expect
    to be running under a 32-bit kernel, which can't provide the high 32
    bits anyway. In the case of a 32-bit kernel we'd then be extending the
    kernel's 32-bit time_t to 64 bits, then truncating it back to 32 bits
    again in userspace, for no particular reason. And, as mentioned above,
    if we have 64-bit time_t for 32-bit processes we can't easily use glibc's
    STAT_IS_KERNEL_STAT, since glibc's stat structure requires an embedded
    "struct timespec", which is a pair of "long" (32-bit) values in a 32-bit
    userspace. "Inventive" solutions are possible, but are pretty hacky.

    Signed-off-by: Chris Metcalf
    Acked-by: Arnd Bergmann

    Chris Metcalf
     
  • The kernel was allowing any component of the pt_regs to be updated either
    by signal handlers writing to the stack, or by processes writing via
    PTRACE_POKEUSR or PTRACE_SETREGS, which meant they could set their PL
    up from 0 to 1 and get access to kernel code and data (or, in practice,
    cause a kernel panic). We now always reset the ex1 field, allowing the
    user to set their ICS bit only.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • This change is modelled on similar fixes for other architectures.
    The pt_regs "faultnum" member is set to the trap (fault) number that
    caused us to enter the kernel, and is INT_SWINT_1 for the syscall software
    interrupt. We already supported a pseudo value, INT_SWINT_1_SIGRETURN,
    that we used for the rt_sigreturn syscall; it avoided the case where
    one signal was handled, then we "tail-called" to another handler.

    This change avoids the similar case where we start to call one handler,
    then are preempted into another handler when we start trying to run
    the first handler. We clear ->faultnum after calling handle_signal(),
    and to be paranoid also in the case where there was no signal to deliver.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • For the "initfree" boot argument it's not that big a deal, but
    to avoid warnings in the code, we check for a valid value before
    allowing the specified argument to override the kernel default.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • This completes the tile migration to the new naming scheme for
    the architecture-specific irq management code.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     
  • This change makes KM_TYPE_NR independent of the actual deprecated
    list of km_type values, which are no longer used in tile code anywhere.
    For now we leave it set to 8, allowing that many nested mappings,
    and thus reserving 32MB of address space.

    A few remaining places using KM_* values were cleaned up as well.

    Signed-off-by: Chris Metcalf

    Chris Metcalf
     

29 Oct, 2010

2 commits

  • * 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6: (38 commits)
    kbuild: convert `arch/tile' to the kconfig mainmenu upgrade
    README: cite nconfig
    Revert "kconfig: Temporarily disable dependency warnings"
    kconfig: Use PATH_MAX instead of 128 for path buffer sizes.
    kconfig: Fix realloc usage()
    kconfig: Propagate const
    kconfig: Don't go out from read config loop when you read new symbol
    kconfig: fix menuconfig on debian lenny
    kbuild: migrate all arch to the kconfig mainmenu upgrade
    kconfig: expand file names
    kconfig: use the file's name of sourced file
    kconfig: constify file name
    kconfig: don't emit warning upon rootmenu's prompt redefinition
    kconfig: replace KERNELVERSION usage by the mainmenu's prompt
    kconfig: delay gconf window initialization
    kconfig: expand by default the rootmenu's prompt
    kconfig: add a symbol string expansion helper
    kconfig: regen parser
    kconfig: implement the `mainmenu' directive
    kconfig: allow PACKAGE to be defined on the compiler's command-line
    ...

    Fix up trivial conflict in arch/mn10300/Kconfig

    Linus Torvalds
     
  • Signed-off-by: Arnaud Lacombe
    Signed-off-by: Michal Marek

    Arnaud Lacombe
     

28 Oct, 2010

5 commits

  • Signed-off-by: Zimny Lech
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Zimny Lech
     
  • Remove checking @addr less than 0 because @addr is now unsigned.

    Signed-off-by: Namhyung Kim
    Acked-by: Chris Metcalf
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Namhyung Kim
     
  • Fix up the arguments to arch_ptrace() to take account of the fact that
    @addr and @data are now unsigned long rather than long as of a preceding
    patch in this series.

    Signed-off-by: Namhyung Kim
    Cc:
    Acked-by: Roland McGrath
    Acked-by: David Howells
    Acked-by: Geert Uytterhoeven
    Acked-by: David S. Miller
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Namhyung Kim
     
  • Signed-off-by: FUJITA Tomonori
    Acked-by: Chris Metcalf
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    FUJITA Tomonori
     
  • Christoph reported a nice splat which illustrated a race in the new stack
    based kmap_atomic implementation.

    The problem is that we pop our stack slot before we're completely done
    resetting its state -- in particular clearing the PTE (sometimes that's
    CONFIG_DEBUG_HIGHMEM). If an interrupt happens before we actually clear
    the PTE used for the last slot, that interrupt can reuse the slot in a
    dirty state, which triggers a BUG in kmap_atomic().

    Fix this by introducing kmap_atomic_idx() which reports the current slot
    index without actually releasing it and use that to find the PTE and delay
    the _pop() until after we're completely done.

    Signed-off-by: Peter Zijlstra
    Reported-by: Christoph Hellwig
    Acked-by: Rik van Riel
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Peter Zijlstra
     

27 Oct, 2010

3 commits

  • * git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
    arch/tile: convert a BUG_ON to BUILD_BUG_ON
    arch/tile: make ptrace() work properly for TILE-Gx COMPAT mode
    arch/tile: support new info op generated by compiler
    arch/tile: minor whitespace/naming changes for string support files
    arch/tile: enable single-step support for TILE-Gx
    arch/tile: parameterize system PLs to support KVM port
    arch/tile: add Tilera's header as an open-source header
    arch/tile: Bomb C99 comments to C89 comments in tile's
    arch/tile: prevent corrupt top frame from causing backtracer runaway
    arch/tile: various top-level Makefile cleanups
    arch/tile: change lower bound on syscall error return to -4095
    arch/tile: properly export __mb_incoherent for modules
    arch/tile: provide a definition of MAP_STACK
    kmemleak: add TILE to the list of supported architectures.
    char: hvc: check for error case
    arch/tile: Add a warning if we try to allocate too much vmalloc memory.
    arch/tile: update some comments to clarify register usage.
    arch/tile: use better "punctuation" for VMSPLIT_3_5G and friends
    arch/tile: Use
    tile: replace some BUG_ON checks with BUILD_BUG_ON checks

    Linus Torvalds
     
  • Since we no longer need to provide KM_type, the whole pte_*map_nested()
    API is now redundant, remove it.

    Signed-off-by: Peter Zijlstra
    Acked-by: Chris Metcalf
    Cc: David Howells
    Cc: Hugh Dickins
    Cc: Rik van Riel
    Cc: Ingo Molnar
    Cc: Thomas Gleixner
    Cc: "H. Peter Anvin"
    Cc: Steven Rostedt
    Cc: Russell King
    Cc: Ralf Baechle
    Cc: David Miller
    Cc: Paul Mackerras
    Cc: Benjamin Herrenschmidt
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Peter Zijlstra
     
  • Keep the current interface but ignore the KM_type and use a stack based
    approach.

    The advantage is that we get rid of crappy code like:

    #define __KM_PTE \
    (in_nmi() ? KM_NMI_PTE : \
    in_irq() ? KM_IRQ_PTE : \
    KM_PTE0)

    and in general can stop worrying about what context we're in and what kmap
    slots might be appropriate for that.

    The downside is that FRV kmap_atomic() gets more expensive.

    For now we use a CPP trick suggested by Andrew:

    #define kmap_atomic(page, args...) __kmap_atomic(page)

    to avoid having to touch all kmap_atomic() users in a single patch.

    [ not compiled on:
    - mn10300: the arch doesn't actually build with highmem to begin with ]

    [akpm@linux-foundation.org: coding-style fixes]
    [akpm@linux-foundation.org: fix up drivers/gpu/drm/i915/intel_overlay.c]
    Acked-by: Rik van Riel
    Signed-off-by: Peter Zijlstra
    Acked-by: Chris Metcalf
    Cc: David Howells
    Cc: Hugh Dickins
    Cc: Ingo Molnar
    Cc: Thomas Gleixner
    Cc: "H. Peter Anvin"
    Cc: Steven Rostedt
    Cc: Russell King
    Cc: Ralf Baechle
    Cc: David Miller
    Cc: Paul Mackerras
    Cc: Benjamin Herrenschmidt
    Cc: Dave Airlie
    Cc: Li Zefan
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Peter Zijlstra
     

23 Oct, 2010

2 commits

  • * git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic:
    asm-generic/io.h: allow people to override individual funcs
    bitops: remove duplicated extern declarations
    bitops: make asm-generic/bitops/find.h more generic
    asm-generic: kdebug.h: Checkpatch cleanup
    asm-generic: fcntl: make exported headers use strict posix types
    asm-generic: cmpxchg does not handle non-long arguments
    asm-generic: make atomic_add_unless a function

    Linus Torvalds
     
  • * 'llseek' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl:
    vfs: make no_llseek the default
    vfs: don't use BKL in default_llseek
    llseek: automatically add .llseek fop
    libfs: use generic_file_llseek for simple_attr
    mac80211: disallow seeks in minstrel debug code
    lirc: make chardev nonseekable
    viotape: use noop_llseek
    raw: use explicit llseek file operations
    ibmasmfs: use generic_file_llseek
    spufs: use llseek in all file operations
    arm/omap: use generic_file_llseek in iommu_debug
    lkdtm: use generic_file_llseek in debugfs
    net/wireless: use generic_file_llseek in debugfs
    drm: use noop_llseek

    Linus Torvalds
     

22 Oct, 2010

1 commit

  • * git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-irqflags:
    Fix IRQ flag handling naming
    MIPS: Add missing #inclusions of
    smc91x: Add missing #inclusion of
    Drop a couple of unnecessary asm/system.h inclusions
    SH: Add missing consts to sys_execve() declaration
    Blackfin: Rename IRQ flags handling functions
    Blackfin: Add missing dep to asm/irqflags.h
    Blackfin: Rename DES PC2() symbol to avoid collision
    Blackfin: Split the BF532 BFIN_*_FIO_FLAG() functions to their own header
    Blackfin: Split PLL code from mach-specific cdef headers

    Linus Torvalds
     

16 Oct, 2010

8 commits


15 Oct, 2010

1 commit

  • All file_operations should get a .llseek operation so we can make
    nonseekable_open the default for future file operations without a
    .llseek pointer.

    The three cases that we can automatically detect are no_llseek, seq_lseek
    and default_llseek. For cases where we can we can automatically prove that
    the file offset is always ignored, we use noop_llseek, which maintains
    the current behavior of not returning an error from a seek.

    New drivers should normally not use noop_llseek but instead use no_llseek
    and call nonseekable_open at open time. Existing drivers can be converted
    to do the same when the maintainer knows for certain that no user code
    relies on calling seek on the device file.

    The generated code is often incorrectly indented and right now contains
    comments that clarify for each added line why a specific variant was
    chosen. In the version that gets submitted upstream, the comments will
    be gone and I will manually fix the indentation, because there does not
    seem to be a way to do that using coccinelle.

    Some amount of new code is currently sitting in linux-next that should get
    the same modifications, which I will do at the end of the merge window.

    Many thanks to Julia Lawall for helping me learn to write a semantic
    patch that does all this.

    ===== begin semantic patch =====
    // This adds an llseek= method to all file operations,
    // as a preparation for making no_llseek the default.
    //
    // The rules are
    // - use no_llseek explicitly if we do nonseekable_open
    // - use seq_lseek for sequential files
    // - use default_llseek if we know we access f_pos
    // - use noop_llseek if we know we don't access f_pos,
    // but we still want to allow users to call lseek
    //
    @ open1 exists @
    identifier nested_open;
    @@
    nested_open(...)
    {

    }

    @ open exists@
    identifier open_f;
    identifier i, f;
    identifier open1.nested_open;
    @@
    int open_f(struct inode *i, struct file *f)
    {

    }

    @ read disable optional_qualifier exists @
    identifier read_f;
    identifier f, p, s, off;
    type ssize_t, size_t, loff_t;
    expression E;
    identifier func;
    @@
    ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
    {

    }

    @ read_no_fpos disable optional_qualifier exists @
    identifier read_f;
    identifier f, p, s, off;
    type ssize_t, size_t, loff_t;
    @@
    ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
    {
    ... when != off
    }

    @ write @
    identifier write_f;
    identifier f, p, s, off;
    type ssize_t, size_t, loff_t;
    expression E;
    identifier func;
    @@
    ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
    {

    }

    @ write_no_fpos @
    identifier write_f;
    identifier f, p, s, off;
    type ssize_t, size_t, loff_t;
    @@
    ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
    {
    ... when != off
    }

    @ fops0 @
    identifier fops;
    @@
    struct file_operations fops = {
    ...
    };

    @ has_llseek depends on fops0 @
    identifier fops0.fops;
    identifier llseek_f;
    @@
    struct file_operations fops = {
    ...
    .llseek = llseek_f,
    ...
    };

    @ has_read depends on fops0 @
    identifier fops0.fops;
    identifier read_f;
    @@
    struct file_operations fops = {
    ...
    .read = read_f,
    ...
    };

    @ has_write depends on fops0 @
    identifier fops0.fops;
    identifier write_f;
    @@
    struct file_operations fops = {
    ...
    .write = write_f,
    ...
    };

    @ has_open depends on fops0 @
    identifier fops0.fops;
    identifier open_f;
    @@
    struct file_operations fops = {
    ...
    .open = open_f,
    ...
    };

    // use no_llseek if we call nonseekable_open
    ////////////////////////////////////////////
    @ nonseekable1 depends on !has_llseek && has_open @
    identifier fops0.fops;
    identifier nso ~= "nonseekable_open";
    @@
    struct file_operations fops = {
    ... .open = nso, ...
    +.llseek = no_llseek, /* nonseekable */
    };

    @ nonseekable2 depends on !has_llseek @
    identifier fops0.fops;
    identifier open.open_f;
    @@
    struct file_operations fops = {
    ... .open = open_f, ...
    +.llseek = no_llseek, /* open uses nonseekable */
    };

    // use seq_lseek for sequential files
    /////////////////////////////////////
    @ seq depends on !has_llseek @
    identifier fops0.fops;
    identifier sr ~= "seq_read";
    @@
    struct file_operations fops = {
    ... .read = sr, ...
    +.llseek = seq_lseek, /* we have seq_read */
    };

    // use default_llseek if there is a readdir
    ///////////////////////////////////////////
    @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier readdir_e;
    @@
    // any other fop is used that changes pos
    struct file_operations fops = {
    ... .readdir = readdir_e, ...
    +.llseek = default_llseek, /* readdir is present */
    };

    // use default_llseek if at least one of read/write touches f_pos
    /////////////////////////////////////////////////////////////////
    @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier read.read_f;
    @@
    // read fops use offset
    struct file_operations fops = {
    ... .read = read_f, ...
    +.llseek = default_llseek, /* read accesses f_pos */
    };

    @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier write.write_f;
    @@
    // write fops use offset
    struct file_operations fops = {
    ... .write = write_f, ...
    + .llseek = default_llseek, /* write accesses f_pos */
    };

    // Use noop_llseek if neither read nor write accesses f_pos
    ///////////////////////////////////////////////////////////

    @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier read_no_fpos.read_f;
    identifier write_no_fpos.write_f;
    @@
    // write fops use offset
    struct file_operations fops = {
    ...
    .write = write_f,
    .read = read_f,
    ...
    +.llseek = noop_llseek, /* read and write both use no f_pos */
    };

    @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier write_no_fpos.write_f;
    @@
    struct file_operations fops = {
    ... .write = write_f, ...
    +.llseek = noop_llseek, /* write uses no f_pos */
    };

    @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    identifier read_no_fpos.read_f;
    @@
    struct file_operations fops = {
    ... .read = read_f, ...
    +.llseek = noop_llseek, /* read uses no f_pos */
    };

    @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
    identifier fops0.fops;
    @@
    struct file_operations fops = {
    ...
    +.llseek = noop_llseek, /* no read or write fn */
    };
    ===== End semantic patch =====

    Signed-off-by: Arnd Bergmann
    Cc: Julia Lawall
    Cc: Christoph Hellwig

    Arnd Bergmann