cregit-Linux how code gets into the kernel

Release 4.7 fs/nfs/pnfs.c

Directory: fs/nfs
/*
 *  pNFS functions to call and manage layout drivers.
 *
 *  Copyright (c) 2002 [year of first publication]
 *  The Regents of the University of Michigan
 *  All Rights Reserved
 *
 *  Dean Hildebrand <dhildebz@umich.edu>
 *
 *  Permission is granted to use, copy, create derivative works, and
 *  redistribute this software and such derivative works for any purpose,
 *  so long as the name of the University of Michigan is not used in
 *  any advertising or publicity pertaining to the use or distribution
 *  of this software without specific, written prior authorization. If
 *  the above copyright notice or any other identification of the
 *  University of Michigan is included in any copy of any portion of
 *  this software, then the disclaimer below must also be included.
 *
 *  This software is provided as is, without representation or warranty
 *  of any kind either express or implied, including without limitation
 *  the implied warranties of merchantability, fitness for a particular
 *  purpose, or noninfringement.  The Regents of the University of
 *  Michigan shall not be liable for any damages, including special,
 *  indirect, incidental, or consequential damages, with respect to any
 *  claim arising out of or in connection with the use of the software,
 *  even if it has been or is hereafter advised of the possibility of
 *  such damages.
 */

#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/module.h>
#include "internal.h"
#include "pnfs.h"
#include "iostat.h"
#include "nfs4trace.h"
#include "delegation.h"
#include "nfs42.h"


#define NFSDBG_FACILITY		NFSDBG_PNFS

#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)

/* Locking:
 *
 * pnfs_spinlock:
 *      protects pnfs_modules_tbl.
 */
static DEFINE_SPINLOCK(pnfs_spinlock);

/*
 * pnfs_modules_tbl holds all pnfs modules
 */
static LIST_HEAD(pnfs_modules_tbl);

static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo);

/* Return the registered pnfs layout driver module matching given id */

static struct pnfs_layoutdriver_type * find_pnfs_driver_locked(u32 id) { struct pnfs_layoutdriver_type *local; list_for_each_entry(local, &pnfs_modules_tbl, pnfs_tblid) if (local->id == id) goto out; local = NULL; out: dprintk("%s: Searching for id %u, found %p\n", __func__, id, local); return local; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman55100.00%1100.00%
Total55100.00%1100.00%


static struct pnfs_layoutdriver_type * find_pnfs_driver(u32 id) { struct pnfs_layoutdriver_type *local; spin_lock(&pnfs_spinlock); local = find_pnfs_driver_locked(id); if (local != NULL && !try_module_get(local->owner)) { dprintk("%s: Could not grab reference on module\n", __func__); local = NULL; } spin_unlock(&pnfs_spinlock); return local; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust2741.54%133.33%
fred isamanfred isaman2538.46%133.33%
ricardo labiagaricardo labiaga1320.00%133.33%
Total65100.00%3100.00%


void unset_pnfs_layoutdriver(struct nfs_server *nfss) { if (nfss->pnfs_curr_ld) { if (nfss->pnfs_curr_ld->clear_layoutdriver) nfss->pnfs_curr_ld->clear_layoutdriver(nfss); /* Decrement the MDS count. Purge the deviceid cache if zero */ if (atomic_dec_and_test(&nfss->nfs_client->cl_mds_count)) nfs4_deviceid_purge_client(nfss->nfs_client); module_put(nfss->pnfs_curr_ld->owner); } nfss->pnfs_curr_ld = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust2028.57%125.00%
benny halevybenny halevy1927.14%125.00%
ricardo labiagaricardo labiaga1622.86%125.00%
fred isamanfred isaman1521.43%125.00%
Total70100.00%4100.00%

/* * Try to set the server's pnfs module to the pnfs layout type specified by id. * Currently only one pNFS layout driver per filesystem is supported. * * @id layout type. Zero (illegal layout type) indicates pNFS not in use. */
void set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, u32 id) { struct pnfs_layoutdriver_type *ld_type = NULL; if (id == 0) goto out_no_driver; if (!(server->nfs_client->cl_exchange_flags & (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) { printk(KERN_ERR "NFS: %s: id %u cl_exchange_flags 0x%x\n", __func__, id, server->nfs_client->cl_exchange_flags); goto out_no_driver; } ld_type = find_pnfs_driver(id); if (!ld_type) { request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id); ld_type = find_pnfs_driver(id); if (!ld_type) { dprintk("%s: No pNFS module found for %u.\n", __func__, id); goto out_no_driver; } } server->pnfs_curr_ld = ld_type; if (ld_type->set_layoutdriver && ld_type->set_layoutdriver(server, mntfh)) { printk(KERN_ERR "NFS: %s: Error initializing pNFS layout " "driver %u.\n", __func__, id); module_put(ld_type->owner); goto out_no_driver; } /* Bump the MDS count */ atomic_inc(&server->nfs_client->cl_mds_count); dprintk("%s: pNFS module for %u set\n", __func__, id); return; out_no_driver: dprintk("%s: Using NFSv4 I/O\n", __func__); server->pnfs_curr_ld = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
ricardo labiagaricardo labiaga14672.28%125.00%
benny halevybenny halevy4220.79%125.00%
trond myklebusttrond myklebust115.45%125.00%
weston andros adamsonweston andros adamson31.49%125.00%
Total202100.00%4100.00%


int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type) { int status = -EINVAL; struct pnfs_layoutdriver_type *tmp; if (ld_type->id == 0) { printk(KERN_ERR "NFS: %s id 0 is reserved\n", __func__); return status; } if (!ld_type->alloc_lseg || !ld_type->free_lseg) { printk(KERN_ERR "NFS: %s Layout driver must provide " "alloc_lseg and free_lseg.\n", __func__); return status; } spin_lock(&pnfs_spinlock); tmp = find_pnfs_driver_locked(ld_type->id); if (!tmp) { list_add(&ld_type->pnfs_tblid, &pnfs_modules_tbl); status = 0; dprintk("%s Registering id:%u name:%s\n", __func__, ld_type->id, ld_type->name); } else { printk(KERN_ERR "NFS: %s Module with id %d already loaded!\n", __func__, ld_type->id); } spin_unlock(&pnfs_spinlock); return status; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman11680.56%133.33%
andy adamsonandy adamson2517.36%133.33%
weston andros adamsonweston andros adamson32.08%133.33%
Total144100.00%3100.00%

EXPORT_SYMBOL_GPL(pnfs_register_layoutdriver);
void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type) { dprintk("%s Deregistering id:%u\n", __func__, ld_type->id); spin_lock(&pnfs_spinlock); list_del(&ld_type->pnfs_tblid); spin_unlock(&pnfs_spinlock); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman41100.00%1100.00%
Total41100.00%1100.00%

EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver); /* * pNFS client layout cache */ /* Need to hold i_lock if caller does not already hold reference */
void pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo) { atomic_inc(&lo->plh_refcount); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy1477.78%125.00%
fred isamanfred isaman316.67%250.00%
trond myklebusttrond myklebust15.56%125.00%
Total18100.00%4100.00%


static struct pnfs_layout_hdr * pnfs_alloc_layout_hdr(struct inode *ino, gfp_t gfp_flags) { struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld; return ld->alloc_layout_hdr(ino, gfp_flags); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy38100.00%2100.00%
Total38100.00%2100.00%


static void pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo) { struct nfs_server *server = NFS_SERVER(lo->plh_inode); struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; if (!list_empty(&lo->plh_layouts)) { struct nfs_client *clp = server->nfs_client; spin_lock(&clp->cl_lock); list_del_init(&lo->plh_layouts); spin_unlock(&clp->cl_lock); } put_rpccred(lo->plh_lc_cred); return ld->free_layout_hdr(lo); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust5559.14%133.33%
benny halevybenny halevy3133.33%133.33%
peng taopeng tao77.53%133.33%
Total93100.00%3100.00%


static void pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo) { struct nfs_inode *nfsi = NFS_I(lo->plh_inode); dprintk("%s: freeing layout cache %p\n", __func__, lo); nfsi->layout = NULL; /* Reset MDS Threshold I/O counters */ nfsi->write_io = 0; nfsi->read_io = 0; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust2752.94%250.00%
benny halevybenny halevy2447.06%250.00%
Total51100.00%4100.00%


void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) { struct inode *inode = lo->plh_inode; pnfs_layoutreturn_before_put_layout_hdr(lo); if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { if (!list_empty(&lo->plh_segs)) WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n"); pnfs_detach_layout_hdr(lo); spin_unlock(&inode->i_lock); pnfs_free_layout_hdr(lo); } }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman2329.87%114.29%
peng taopeng tao1823.38%114.29%
andy adamsonandy adamson1215.58%114.29%
benny halevybenny halevy1215.58%114.29%
trond myklebusttrond myklebust1215.58%342.86%
Total77100.00%7100.00%

/* * Mark a pnfs_layout_hdr and all associated layout segments as invalid * * In order to continue using the pnfs_layout_hdr, a full recovery * is required. * Note that caller must hold inode->i_lock. */
static int pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, struct list_head *lseg_list) { struct pnfs_layout_range range = { .iomode = IOMODE_ANY, .offset = 0, .length = NFS4_MAX_UINT64, }; set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range, 0); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust5896.67%266.67%
jeff laytonjeff layton23.33%133.33%
Total60100.00%3100.00%


static int pnfs_iomode_to_fail_bit(u32 iomode) { return iomode == IOMODE_RW ? NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust1794.44%150.00%
andy adamsonandy adamson15.56%150.00%
Total18100.00%2100.00%


static void pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit) { lo->plh_retry_timestamp = jiffies; if (!test_and_set_bit(fail_bit, &lo->plh_flags)) atomic_inc(&lo->plh_refcount); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4097.56%375.00%
yanchuan nianyanchuan nian12.44%125.00%
Total41100.00%4100.00%


static void pnfs_layout_clear_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit) { if (test_and_clear_bit(fail_bit, &lo->plh_flags)) atomic_dec(&lo->plh_refcount); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust34100.00%2100.00%
Total34100.00%2100.00%


static void pnfs_layout_io_set_failed(struct pnfs_layout_hdr *lo, u32 iomode) { struct inode *inode = lo->plh_inode; struct pnfs_layout_range range = { .iomode = iomode, .offset = 0, .length = NFS4_MAX_UINT64, }; LIST_HEAD(head); spin_lock(&inode->i_lock); pnfs_layout_set_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); pnfs_mark_matching_lsegs_invalid(lo, &head, &range, 0); spin_unlock(&inode->i_lock); pnfs_free_lseg_list(&head); dprintk("%s Setting layout IOMODE_%s fail bit\n", __func__, iomode == IOMODE_RW ? "RW" : "READ"); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust10798.17%375.00%
jeff laytonjeff layton21.83%125.00%
Total109100.00%4100.00%


static bool pnfs_layout_io_test_failed(struct pnfs_layout_hdr *lo, u32 iomode) { unsigned long start, end; int fail_bit = pnfs_iomode_to_fail_bit(iomode); if (test_bit(fail_bit, &lo->plh_flags) == 0) return false; end = jiffies; start = end - PNFS_LAYOUTGET_RETRY_TIMEOUT; if (!time_in_range(lo->plh_retry_timestamp, start, end)) { /* It is time to retry the failed layoutgets */ pnfs_layout_clear_fail_bit(lo, fail_bit); return false; } return true; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust85100.00%3100.00%
Total85100.00%3100.00%


static void init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) { INIT_LIST_HEAD(&lseg->pls_list); INIT_LIST_HEAD(&lseg->pls_lc_list); atomic_set(&lseg->pls_refcount, 1); smp_mb(); set_bit(NFS_LSEG_VALID, &lseg->pls_flags); lseg->pls_layout = lo; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson2236.07%116.67%
fred isamanfred isaman1931.15%233.33%
benny halevybenny halevy1118.03%116.67%
peng taopeng tao813.11%116.67%
trond myklebusttrond myklebust11.64%116.67%
Total61100.00%6100.00%


static void pnfs_free_lseg(struct pnfs_layout_segment *lseg) { struct inode *ino = lseg->pls_layout->plh_inode; NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson2676.47%228.57%
fred isamanfred isaman411.76%342.86%
benny halevybenny halevy38.82%114.29%
trond myklebusttrond myklebust12.94%114.29%
Total34100.00%7100.00%


static void pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) { struct inode *inode = lo->plh_inode; WARN_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); list_del_init(&lseg->pls_list); /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ atomic_dec(&lo->plh_refcount); if (list_empty(&lo->plh_segs)) { set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); } rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4848.98%444.44%
fred isamanfred isaman3838.78%333.33%
andy adamsonandy adamson1111.22%111.11%
benny halevybenny halevy11.02%111.11%
Total98100.00%9100.00%


void pnfs_put_lseg(struct pnfs_layout_segment *lseg) { struct pnfs_layout_hdr *lo; struct inode *inode; if (!lseg) return; dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg, atomic_read(&lseg->pls_refcount), test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); lo = lseg->pls_layout; inode = lo->plh_inode; if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { spin_unlock(&inode->i_lock); return; } pnfs_get_layout_hdr(lo); pnfs_layout_remove_lseg(lo, lseg); spin_unlock(&inode->i_lock); pnfs_free_lseg(lseg); pnfs_put_layout_hdr(lo); } }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust5943.70%758.33%
fred isamanfred isaman5641.48%216.67%
peng taopeng tao1914.07%216.67%
andy adamsonandy adamson10.74%18.33%
Total135100.00%12100.00%

EXPORT_SYMBOL_GPL(pnfs_put_lseg);
static void pnfs_free_lseg_async_work(struct work_struct *work) { struct pnfs_layout_segment *lseg; struct pnfs_layout_hdr *lo; lseg = container_of(work, struct pnfs_layout_segment, pls_work); lo = lseg->pls_layout; pnfs_free_lseg(lseg); pnfs_put_layout_hdr(lo); }

Contributors

PersonTokensPropCommitsCommitProp
weston andros adamsonweston andros adamson3163.27%150.00%
trond myklebusttrond myklebust1836.73%150.00%
Total49100.00%2100.00%


static void pnfs_free_lseg_async(struct pnfs_layout_segment *lseg) { INIT_WORK(&lseg->pls_work, pnfs_free_lseg_async_work); schedule_work(&lseg->pls_work); }

Contributors

PersonTokensPropCommitsCommitProp
weston andros adamsonweston andros adamson2689.66%150.00%
trond myklebusttrond myklebust310.34%150.00%
Total29100.00%2100.00%


void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg) { if (!lseg) return; assert_spin_locked(&lseg->pls_layout->plh_inode->i_lock); dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg, atomic_read(&lseg->pls_refcount), test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); if (atomic_dec_and_test(&lseg->pls_refcount)) { struct pnfs_layout_hdr *lo = lseg->pls_layout; if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) return; pnfs_get_layout_hdr(lo); pnfs_layout_remove_lseg(lo, lseg); pnfs_free_lseg_async(lseg); } }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust106100.00%2100.00%
Total106100.00%2100.00%

EXPORT_SYMBOL_GPL(pnfs_put_lseg_locked);
static u64 end_offset(u64 start, u64 len) { u64 end; end = start + len; return end >= start ? end : NFS4_MAX_UINT64; }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy2996.67%150.00%
andy adamsonandy adamson13.33%150.00%
Total30100.00%2100.00%

/* * is l2 fully contained in l1? * start1 end1 * [----------------------------------) * start2 end2 * [----------------) */
static bool pnfs_lseg_range_contained(const struct pnfs_layout_range *l1, const struct pnfs_layout_range *l2) { u64 start1 = l1->offset; u64 end1 = end_offset(start1, l1->length); u64 start2 = l2->offset; u64 end2 = end_offset(start2, l2->length); return (start1 <= start2) && (end1 >= end2); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy6594.20%133.33%
trond myklebusttrond myklebust45.80%266.67%
Total69100.00%3100.00%

/* * is l1 and l2 intersecting? * start1 end1 * [----------------------------------) * start2 end2 * [----------------) */
static bool pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, const struct pnfs_layout_range *l2) { u64 start1 = l1->offset; u64 end1 = end_offset(start1, l1->length); u64 start2 = l2->offset; u64 end2 = end_offset(start2, l2->length); return (end1 == NFS4_MAX_UINT64 || end1 > start2) && (end2 == NFS4_MAX_UINT64 || end2 > start1); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy7394.81%133.33%
trond myklebusttrond myklebust45.19%266.67%
Total77100.00%3100.00%


static bool should_free_lseg(const struct pnfs_layout_range *lseg_range, const struct pnfs_layout_range *recall_range) { return (recall_range->iomode == IOMODE_ANY || lseg_range->iomode == recall_range->iomode) && pnfs_lseg_range_intersecting(lseg_range, recall_range); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy2457.14%240.00%
fred isamanfred isaman1535.71%120.00%
trond myklebusttrond myklebust37.14%240.00%
Total42100.00%5100.00%


static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, struct list_head *tmp_list) { if (!atomic_dec_and_test(&lseg->pls_refcount)) return false; pnfs_layout_remove_lseg(lseg->pls_layout, lseg); list_add(&lseg->pls_list, tmp_list); return true; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust52100.00%1100.00%
Total52100.00%1100.00%

/* Returns 1 if lseg is removed from list, 0 otherwise */
static int mark_lseg_invalid(struct pnfs_layout_segment *lseg, struct list_head *tmp_list) { int rv = 0; if (test_and_clear_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { /* Remove the reference keeping the lseg in the * list. It will now be removed when all * outstanding io is finished. */ dprintk("%s: lseg %p ref %d\n", __func__, lseg, atomic_read(&lseg->pls_refcount)); if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list)) rv = 1; } return rv; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman6797.10%266.67%
trond myklebusttrond myklebust22.90%133.33%
Total69100.00%3100.00%

/* * Compare 2 layout stateid sequence ids, to see which is newer, * taking into account wraparound issues. */
static bool pnfs_seqid_is_newer(u32 s1, u32 s2) { return (s32)(s1 - s2) > 0; }

Contributors

PersonTokensPropCommitsCommitProp
jeff laytonjeff layton24100.00%1100.00%
Total24100.00%1100.00%

/** * pnfs_mark_matching_lsegs_invalid - tear down lsegs or mark them for later * @lo: layout header containing the lsegs * @tmp_list: list head where doomed lsegs should go * @recall_range: optional recall range argument to match (may be NULL) * @seq: only invalidate lsegs obtained prior to this sequence (may be 0) * * Walk the list of lsegs in the layout header, and tear down any that should * be destroyed. If "recall_range" is specified then the segment must match * that range. If "seq" is non-zero, then only match segments that were handed * out at or before that sequence. * * Returns number of matching invalid lsegs remaining in list after scanning * it and purging them. */
int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, struct list_head *tmp_list, const struct pnfs_layout_range *recall_range, u32 seq) { struct pnfs_layout_segment *lseg, *next; int remaining = 0; dprintk("%s:Begin lo %p\n", __func__, lo); if (list_empty(&lo->plh_segs)) return 0; list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) if (!recall_range || should_free_lseg(&lseg->pls_range, recall_range)) { if (seq && pnfs_seqid_is_newer(lseg->pls_seq, seq)) continue; dprintk("%s: freeing lseg %p iomode %d seq %u" "offset %llu length %llu\n", __func__, lseg, lseg->pls_range.iomode, lseg->pls_seq, lseg->pls_range.offset, lseg->pls_range.length); if (!mark_lseg_invalid(lseg, tmp_list)) remaining++; } dprintk("%s:Return %i\n", __func__, remaining); return remaining; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman5333.76%436.36%
andy adamsonandy adamson4025.48%19.09%
benny halevybenny halevy3119.75%218.18%
jeff laytonjeff layton2214.01%19.09%
trond myklebusttrond myklebust117.01%327.27%
Total157100.00%11100.00%

/* note free_me must contain lsegs from a single layout_hdr */
void pnfs_free_lseg_list(struct list_head *free_me) { struct pnfs_layout_segment *lseg, *tmp; if (list_empty(free_me)) return; list_for_each_entry_safe(lseg, tmp, free_me, pls_list) { list_del(&lseg->pls_list); pnfs_free_lseg(lseg); } }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson2345.10%116.67%
fred isamanfred isaman1937.25%350.00%
benny halevybenny halevy815.69%116.67%
trond myklebusttrond myklebust11.96%116.67%
Total51100.00%6100.00%


void pnfs_destroy_layout(struct nfs_inode *nfsi) { struct pnfs_layout_hdr *lo; LIST_HEAD(tmp_list); spin_lock(&nfsi->vfs_inode.i_lock); lo = nfsi->layout; if (lo) { pnfs_get_layout_hdr(lo); pnfs_mark_layout_stateid_invalid(lo, &tmp_list); pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); spin_unlock(&nfsi->vfs_inode.i_lock); pnfs_free_lseg_list(&tmp_list); pnfs_put_layout_hdr(lo); } else spin_unlock(&nfsi->vfs_inode.i_lock); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson6261.39%120.00%
trond myklebusttrond myklebust3736.63%240.00%
fred isamanfred isaman21.98%240.00%
Total101100.00%5100.00%

EXPORT_SYMBOL_GPL(pnfs_destroy_layout);
static bool pnfs_layout_add_bulk_destroy_list(struct inode *inode, struct list_head *layout_list) { struct pnfs_layout_hdr *lo; bool ret = false; spin_lock(&inode->i_lock); lo = NFS_I(inode)->layout; if (lo != NULL && list_empty(&lo->plh_bulk_destroy)) { pnfs_get_layout_hdr(lo); list_add(&lo->plh_bulk_destroy, layout_list); ret = true; } spin_unlock(&inode->i_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust6370.79%125.00%
andy adamsonandy adamson2224.72%250.00%
weston andros adamsonweston andros adamson44.49%125.00%
Total89100.00%4100.00%

/* Caller must hold rcu_read_lock and clp->cl_lock */
static int pnfs_layout_bulk_destroy_byserver_locked(struct nfs_client *clp, struct nfs_server *server, struct list_head *layout_list) { struct pnfs_layout_hdr *lo, *next; struct inode *inode; list_for_each_entry_safe(lo, next, &server->layouts, plh_layouts) { inode = igrab(lo->plh_inode); if (inode == NULL) continue; list_del_init(&lo->plh_layouts); if (pnfs_layout_add_bulk_destroy_list(inode, layout_list)) continue; rcu_read_unlock(); spin_unlock(&clp->cl_lock); iput(inode); spin_lock(&clp->cl_lock); rcu_read_lock(); return -EAGAIN; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust9078.95%133.33%
andy adamsonandy adamson1311.40%133.33%
weston andros adamsonweston andros adamson119.65%133.33%
Total114100.00%3100.00%


static int pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, bool is_bulk_recall) { struct pnfs_layout_hdr *lo; struct inode *inode; LIST_HEAD(lseg_list); int ret = 0; while (!list_empty(layout_list)) { lo = list_entry(layout_list->next, struct pnfs_layout_hdr, plh_bulk_destroy); dprintk("%s freeing layout for inode %lu\n", __func__, lo->plh_inode->i_ino); inode = lo->plh_inode; pnfs_layoutcommit_inode(inode, false); spin_lock(&inode->i_lock); list_del_init(&lo->plh_bulk_destroy); if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) { if (is_bulk_recall) set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); ret = -EAGAIN; } spin_unlock(&inode->i_lock); pnfs_free_lseg_list(&lseg_list); /* Free all lsegs that are attached to commit buckets */ nfs_commit_inode(inode, 0); pnfs_put_layout_hdr(lo); iput(inode); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust11971.69%342.86%
andy adamsonandy adamson3923.49%228.57%
christoph hellwigchristoph hellwig74.22%114.29%
fred isamanfred isaman10.60%114.29%
Total166100.00%7100.00%


int pnfs_destroy_layouts_byfsid(struct nfs_client *clp, struct nfs_fsid *fsid, bool is_recall) { struct nfs_server *server; LIST_HEAD(layout_list); spin_lock(&clp->cl_lock); rcu_read_lock(); restart: list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { if (memcmp(&server->fsid, fsid, sizeof(*fsid)) != 0) continue; if (pnfs_layout_bulk_destroy_byserver_locked(clp, server, &layout_list) != 0) goto restart; } rcu_read_unlock(); spin_unlock(&clp->cl_lock); if (list_empty(&layout_list)) return 0; return pnfs_layout_free_bulk_destroy_list(&layout_list, is_recall); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust120100.00%1100.00%
Total120100.00%1100.00%


int pnfs_destroy_layouts_byclid(struct nfs_client *clp, bool is_recall) { struct nfs_server *server; LIST_HEAD(layout_list); spin_lock(&clp->cl_lock); rcu_read_lock(); restart: list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { if (pnfs_layout_bulk_destroy_byserver_locked(clp, server, &layout_list) != 0) goto restart; } rcu_read_unlock(); spin_unlock(&clp->cl_lock); if (list_empty(&layout_list)) return 0; return pnfs_layout_free_bulk_destroy_list(&layout_list, is_recall); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust94100.00%1100.00%
Total94100.00%1100.00%

/* * Called by the state manger to remove all layouts established under an * expired lease. */
void pnfs_destroy_all_layouts(struct nfs_client *clp) { nfs4_deviceid_mark_client_invalid(clp); nfs4_deviceid_purge_client(clp); pnfs_destroy_layouts_byclid(clp, false); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust2488.89%150.00%
andy adamsonandy adamson311.11%150.00%
Total27100.00%2100.00%

/* update lo->plh_stateid with new if is more recent */
void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, bool update_barrier) { u32 oldseq, newseq, new_barrier; int empty = list_empty(&lo->plh_segs); oldseq = be32_to_cpu(lo->plh_stateid.seqid); newseq = be32_to_cpu(new->seqid); if (empty || pnfs_seqid_is_newer(newseq, oldseq)) { nfs4_stateid_copy(&lo->plh_stateid, new); if (update_barrier) { new_barrier = be32_to_cpu(new->seqid); } else { /* Because of wraparound, we want to keep the barrier * "close" to the current seqids. */ new_barrier = newseq - atomic_read(&lo->plh_outstanding); } if (empty || pnfs_seqid_is_newer(new_barrier, lo->plh_barrier)) lo->plh_barrier = new_barrier; } }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson5038.76%225.00%
fred isamanfred isaman4232.56%225.00%
trond myklebusttrond myklebust3728.68%450.00%
Total129100.00%8100.00%


static bool pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid) { u32 seqid = be32_to_cpu(stateid->seqid); return !pnfs_seqid_is_newer(seqid, lo->plh_barrier); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman2155.26%250.00%
trond myklebusttrond myklebust1744.74%250.00%
Total38100.00%4100.00%

/* lget is set to 1 if called from inside send_layoutget call chain */
static bool pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo) { return lo->plh_block_lgets || test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman1659.26%375.00%
trond myklebusttrond myklebust1140.74%125.00%
Total27100.00%4100.00%

/* * Get layout from server. * for now, assume that whole file layouts are requested. * arg->offset: 0 * arg->length: all ones */
static struct pnfs_layout_segment * send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_open_context *ctx, nfs4_stateid *stateid, const struct pnfs_layout_range *range, long *timeout, gfp_t gfp_flags) { struct inode *ino = lo->plh_inode; struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; loff_t i_size; dprintk("--> %s\n", __func__); /* * Synchronously retrieve layout information from server and * store in lseg. If we race with a concurrent seqid morphing * op, then re-send the LAYOUTGET. */ lgp = kzalloc(sizeof(*lgp), gfp_flags); if (lgp == NULL) return ERR_PTR(-ENOMEM); i_size = i_size_read(ino); lgp->args.minlength = PAGE_SIZE; if (lgp->args.minlength > range->length) lgp->args.minlength = range->length; if (range->iomode == IOMODE_READ) { if (range->offset >= i_size) lgp->args.minlength = 0; else if (i_size - range->offset < lgp->args.minlength) lgp->args.minlength = i_size - range->offset; } lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; pnfs_copy_range(&lgp->args.range, range); lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); nfs4_stateid_copy(&lgp->args.stateid, stateid); lgp->gfp_flags = gfp_flags; lgp->cred = lo->plh_lc_cred; return nfs4_proc_layoutget(lgp, timeout, gfp_flags); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson9534.80%17.69%
trond myklebusttrond myklebust8531.14%430.77%
benny halevybenny halevy6021.98%215.38%
jeff laytonjeff layton2910.62%323.08%
idan kedaridan kedar20.73%17.69%
kirill a. shutemovkirill a. shutemov10.37%17.69%
fred isamanfred isaman10.37%17.69%
Total273100.00%13100.00%


static void pnfs_clear_layoutcommit(struct inode *inode, struct list_head *head) { struct nfs_inode *nfsi = NFS_I(inode); struct pnfs_layout_segment *lseg, *tmp; if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) return; list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) { if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) continue; pnfs_lseg_dec_and_remove_zero(lseg, head); } }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust81100.00%1100.00%
Total81100.00%1100.00%


void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo) { clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags); smp_mb__after_atomic(); wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); }

Contributors

PersonTokensPropCommitsCommitProp
tom haynestom haynes2860.87%133.33%
trond myklebusttrond myklebust1328.26%133.33%
fred isamanfred isaman510.87%133.33%
Total46100.00%3100.00%


static bool pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo) { if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) return false; lo->plh_return_iomode = 0; lo->plh_return_seq = 0; pnfs_get_layout_hdr(lo); clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); return true; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4987.50%250.00%
jeff laytonjeff layton610.71%125.00%
peng taopeng tao11.79%125.00%
Total56100.00%4100.00%


static int pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid, enum pnfs_iomode iomode, bool sync) { struct inode *ino = lo->plh_inode; struct nfs4_layoutreturn *lrp; int status = 0; lrp = kzalloc(sizeof(*lrp), GFP_NOFS); if (unlikely(lrp == NULL)) { status = -ENOMEM; spin_lock(&ino->i_lock); pnfs_clear_layoutreturn_waitbit(lo); spin_unlock(&ino->i_lock); pnfs_put_layout_hdr(lo); goto out; } nfs4_stateid_copy(&lrp->args.stateid, stateid); lrp->args.layout_type = NFS_SERVER(ino)->pnfs_curr_ld->id; lrp->args.inode = ino; lrp->args.range.iomode = iomode; lrp->args.range.offset = 0; lrp->args.range.length = NFS4_MAX_UINT64; lrp->args.layout = lo; lrp->clp = NFS_SERVER(ino)->nfs_client; lrp->cred = lo->plh_lc_cred; status = nfs4_proc_layoutreturn(lrp, sync); out: dprintk("<-- %s status: %d\n", __func__, status); return status; }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao14969.30%323.08%
fred isamanfred isaman2612.09%215.38%
benny halevybenny halevy188.37%17.69%
trond myklebusttrond myklebust136.05%430.77%
andy adamsonandy adamson52.33%215.38%
tom haynestom haynes41.86%17.69%
Total215100.00%13100.00%

/* Return true if layoutreturn is needed */
static bool pnfs_layout_need_return(struct pnfs_layout_hdr *lo) { struct pnfs_layout_segment *s; if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) return false; /* Defer layoutreturn until all lsegs are done */ list_for_each_entry(s, &lo->plh_segs, pls_list) { if (test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags)) return false; } return true; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust61100.00%2100.00%
Total61100.00%2100.00%


static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo) { struct inode *inode= lo->plh_inode; if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) return; spin_lock(&inode->i_lock); if (pnfs_layout_need_return(lo)) { nfs4_stateid stateid; enum pnfs_iomode iomode; bool send; nfs4_stateid_copy(&stateid, &lo->plh_stateid); stateid.seqid = cpu_to_be32(lo->plh_return_seq); iomode = lo->plh_return_iomode; send = pnfs_prepare_layoutreturn(lo); spin_unlock(&inode->i_lock); if (send) { /* Send an async layoutreturn so we dont deadlock */ pnfs_send_layoutreturn(lo, &stateid, iomode, false); } } else spin_unlock(&inode->i_lock); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust12191.67%266.67%
jeff laytonjeff layton118.33%133.33%
Total132100.00%3100.00%

/* * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr * when the layout segment list is empty. * * Note that a pnfs_layout_hdr can exist with an empty layout segment * list when LAYOUTGET has failed, or when LAYOUTGET succeeded, but the * deviceid is marked invalid. */
int _pnfs_return_layout(struct inode *ino) { struct pnfs_layout_hdr *lo = NULL; struct nfs_inode *nfsi = NFS_I(ino); LIST_HEAD(tmp_list); nfs4_stateid stateid; int status = 0, empty; bool send; dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino); spin_lock(&ino->i_lock); lo = nfsi->layout; if (!lo) { spin_unlock(&ino->i_lock); dprintk("NFS: %s no layout to return\n", __func__); goto out; } nfs4_stateid_copy(&stateid, &nfsi->layout->plh_stateid); /* Reference matched in nfs4_layoutreturn_release */ pnfs_get_layout_hdr(lo); empty = list_empty(&lo->plh_segs); pnfs_clear_layoutcommit(ino, &tmp_list); pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL, 0); if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) { struct pnfs_layout_range range = { .iomode = IOMODE_ANY, .offset = 0, .length = NFS4_MAX_UINT64, }; NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, &range); } /* Don't send a LAYOUTRETURN if list was initially empty */ if (empty) { spin_unlock(&ino->i_lock); dprintk("NFS: %s no layout segments to return\n", __func__); goto out_put_layout_hdr; } set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); send = pnfs_prepare_layoutreturn(lo); spin_unlock(&ino->i_lock); pnfs_free_lseg_list(&tmp_list); if (send) status = pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true); out_put_layout_hdr: pnfs_put_layout_hdr(lo); out: dprintk("<-- %s status: %d\n", __func__, status); return status; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman8128.12%421.05%
christoph hellwigchristoph hellwig5920.49%210.53%
benny halevybenny halevy5820.14%15.26%
andy adamsonandy adamson4515.62%210.53%
trond myklebusttrond myklebust3712.85%631.58%
peng taopeng tao62.08%315.79%
jeff laytonjeff layton20.69%15.26%
Total288100.00%19100.00%

EXPORT_SYMBOL_GPL(_pnfs_return_layout);
int pnfs_commit_and_return_layout(struct inode *inode) { struct pnfs_layout_hdr *lo; int ret; spin_lock(&inode->i_lock); lo = NFS_I(inode)->layout; if (lo == NULL) { spin_unlock(&inode->i_lock); return 0; } pnfs_get_layout_hdr(lo); /* Block new layoutgets and read/write to ds */ lo->plh_block_lgets++; spin_unlock(&inode->i_lock); filemap_fdatawait(inode->i_mapping); ret = pnfs_layoutcommit_inode(inode, true); if (ret == 0) ret = _pnfs_return_layout(inode); spin_lock(&inode->i_lock); lo->plh_block_lgets--; spin_unlock(&inode->i_lock); pnfs_put_layout_hdr(lo); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust131100.00%1100.00%
Total131100.00%1100.00%


bool pnfs_roc(struct inode *ino) { struct nfs_inode *nfsi = NFS_I(ino); struct nfs_open_context *ctx; struct nfs4_state *state; struct pnfs_layout_hdr *lo; struct pnfs_layout_segment *lseg, *tmp; nfs4_stateid stateid; LIST_HEAD(tmp_list); bool found = false, layoutreturn = false, roc = false; spin_lock(&ino->i_lock); lo = nfsi->layout; if (!lo || test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) goto out_noroc; /* no roc if we hold a delegation */ if (nfs4_check_delegation(ino, FMODE_READ)) goto out_noroc; list_for_each_entry(ctx, &nfsi->open_files, list) { state = ctx->state; /* Don't return layout if there is open file state */ if (state != NULL && state->state != 0) goto out_noroc; } nfs4_stateid_copy(&stateid, &lo->plh_stateid); /* always send layoutreturn if being marked so */ if (test_and_clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) layoutreturn = pnfs_prepare_layoutreturn(lo); list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) /* If we are sending layoutreturn, invalidate all valid lsegs */ if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { mark_lseg_invalid(lseg, &tmp_list); found = true; } /* ROC in two conditions: * 1. there are ROC lsegs * 2. we don't send layoutreturn */ if (found && !layoutreturn) { /* lo ref dropped in pnfs_roc_release() */ pnfs_get_layout_hdr(lo); roc = true; } out_noroc: spin_unlock(&ino->i_lock); pnfs_free_lseg_list(&tmp_list); pnfs_layoutcommit_inode(ino, true); if (layoutreturn) pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true); return roc; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman12043.96%110.00%
trond myklebusttrond myklebust8430.77%660.00%
peng taopeng tao6925.27%330.00%
Total273100.00%10100.00%


void pnfs_roc_release(struct inode *ino) { struct pnfs_layout_hdr *lo; spin_lock(&ino->i_lock); lo = NFS_I(ino)->layout; pnfs_clear_layoutreturn_waitbit(lo); if (atomic_dec_and_test(&lo->plh_refcount)) { pnfs_detach_layout_hdr(lo); spin_unlock(&ino->i_lock); pnfs_free_layout_hdr(lo); } else spin_unlock(&ino->i_lock); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman4660.53%133.33%
trond myklebusttrond myklebust3039.47%266.67%
Total76100.00%3100.00%


void pnfs_roc_set_barrier(struct inode *ino, u32 barrier) { struct pnfs_layout_hdr *lo; spin_lock(&ino->i_lock); lo = NFS_I(ino)->layout; pnfs_mark_layout_returned_if_empty(lo); if (pnfs_seqid_is_newer(barrier, lo->plh_barrier)) lo->plh_barrier = barrier; spin_unlock(&ino->i_lock); trace_nfs4_layoutreturn_on_close(ino, 0); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman5880.56%125.00%
trond myklebusttrond myklebust1419.44%375.00%
Total72100.00%4100.00%


void pnfs_roc_get_barrier(struct inode *ino, u32 *barrier) { struct nfs_inode *nfsi = NFS_I(ino); struct pnfs_layout_hdr *lo; u32 current_seqid; spin_lock(&ino->i_lock); lo = nfsi->layout; current_seqid = be32_to_cpu(lo->plh_stateid.seqid); /* Since close does not return a layout stateid for use as * a barrier, we choose the worst-case barrier. */ *barrier = current_seqid + atomic_read(&lo->plh_outstanding); spin_unlock(&ino->i_lock); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman5772.15%125.00%
trond myklebusttrond myklebust2227.85%375.00%
Total79100.00%4100.00%


bool pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task) { struct nfs_inode *nfsi = NFS_I(ino); struct pnfs_layout_hdr *lo; bool sleep = false; /* we might not have grabbed lo reference. so need to check under * i_lock */ spin_lock(&ino->i_lock); lo = nfsi->layout; if (lo && test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) sleep = true; spin_unlock(&ino->i_lock); if (sleep) rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); return sleep; }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao98100.00%1100.00%
Total98100.00%1100.00%

/* * Compare two layout segments for sorting into layout cache. * We want to preferentially return RW over RO layouts, so ensure those * are seen first. */
static s64 pnfs_lseg_range_cmp(const struct pnfs_layout_range *l1, const struct pnfs_layout_range *l2) { s64 d; /* high offset > low offset */ d = l1->offset - l2->offset; if (d) return d; /* short length > long length */ d = l2->length - l1->length; if (d) return d; /* read > read/write */ return (int)(l1->iomode == IOMODE_READ) - (int)(l2->iomode == IOMODE_READ); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy5466.67%240.00%
andy adamsonandy adamson2429.63%120.00%
trond myklebusttrond myklebust33.70%240.00%
Total81100.00%5100.00%


static bool pnfs_lseg_range_is_after(const struct pnfs_layout_range *l1, const struct pnfs_layout_range *l2) { return pnfs_lseg_range_cmp(l1, l2) > 0; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust2796.43%150.00%
andy adamsonandy adamson13.57%150.00%
Total28100.00%2100.00%


static bool pnfs_lseg_no_merge(struct pnfs_layout_segment *lseg, struct pnfs_layout_segment *old) { return false; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust19100.00%1100.00%
Total19100.00%1100.00%


void pnfs_generic_layout_insert_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg, bool (*is_after)(const struct pnfs_layout_range *, const struct pnfs_layout_range *), bool (*do_merge)(struct pnfs_layout_segment *, struct pnfs_layout_segment *), struct list_head *free_me) { struct pnfs_layout_segment *lp, *tmp; dprintk("%s:Begin\n", __func__); list_for_each_entry_safe(lp, tmp, &lo->plh_segs, pls_list) { if (test_bit(NFS_LSEG_VALID, &lp->pls_flags) == 0) continue; if (do_merge(lseg, lp)) { mark_lseg_invalid(lp, free_me); continue; } if (is_after(&lseg->pls_range, &lp->pls_range)) continue; list_add_tail(&lseg->pls_list, &lp->pls_list); dprintk("%s: inserted lseg %p " "iomode %d offset %llu length %llu before " "lp %p iomode %d offset %llu length %llu\n", __func__, lseg, lseg->pls_range.iomode, lseg->pls_range.offset, lseg->pls_range.length, lp, lp->pls_range.iomode, lp->pls_range.offset, lp->pls_range.length); goto out; } list_add_tail(&lseg->pls_list, &lo->plh_segs); dprintk("%s: inserted lseg %p " "iomode %d offset %llu length %llu at tail\n", __func__, lseg, lseg->pls_range.iomode, lseg->pls_range.offset, lseg->pls_range.length); out: pnfs_get_layout_hdr(lo); dprintk("%s:Return\n", __func__); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson13554.22%114.29%
trond myklebusttrond myklebust8032.13%228.57%
fred isamanfred isaman176.83%228.57%
benny halevybenny halevy176.83%228.57%
Total249100.00%7100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_layout_insert_lseg);
static void pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg, struct list_head *free_me) { struct inode *inode = lo->plh_inode; struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; if (ld->add_lseg != NULL) ld->add_lseg(lo, lseg, free_me); else pnfs_generic_layout_insert_lseg(lo, lseg, pnfs_lseg_range_is_after, pnfs_lseg_no_merge, free_me); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust75100.00%1100.00%
Total75100.00%1100.00%


static struct pnfs_layout_hdr * alloc_init_layout_hdr(struct inode *ino, struct nfs_open_context *ctx, gfp_t gfp_flags) { struct pnfs_layout_hdr *lo; lo = pnfs_alloc_layout_hdr(ino, gfp_flags); if (!lo) return NULL; atomic_set(&lo->plh_refcount, 1); INIT_LIST_HEAD(&lo->plh_layouts); INIT_LIST_HEAD(&lo->plh_segs); INIT_LIST_HEAD(&lo->plh_bulk_destroy); lo->plh_inode = ino; lo->plh_lc_cred = get_rpccred(ctx->cred); lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID; return lo; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson5855.24%110.00%
fred isamanfred isaman1615.24%330.00%
peng taopeng tao1514.29%110.00%
trond myklebusttrond myklebust1413.33%440.00%
benny halevybenny halevy21.90%110.00%
Total105100.00%10100.00%


static struct pnfs_layout_hdr * pnfs_find_alloc_layout(struct inode *ino, struct nfs_open_context *ctx, gfp_t gfp_flags) __releases(&ino->i_lock

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson1150.00%125.00%
trond myklebusttrond myklebust627.27%250.00%
peng taopeng tao522.73%125.00%
Total22100.00%4100.00%

) __acquires(&ino->i_lock) { struct nfs_inode *nfsi = NFS_I(ino); struct pnfs_layout_hdr *new = NULL; dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout); if (nfsi->layout != NULL) goto out_existing; spin_unlock(&ino->i_lock); new = alloc_init_layout_hdr(ino, ctx, gfp_flags); spin_lock(&ino->i_lock); if (likely(nfsi->layout == NULL)) { /* Won the race? */ nfsi->layout = new; return new; } else if (new != NULL) pnfs_free_layout_hdr(new); out_existing: pnfs_get_layout_hdr(nfsi->layout); return nfsi->layout; } /* * iomode matching rules: * iomode lseg strict match * iomode * ----- ----- ------ ----- * ANY READ N/A true * ANY RW N/A true * RW READ N/A false * RW RW N/A true * READ READ N/A true * READ RW true false * READ RW false true */
static bool pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, const struct pnfs_layout_range *range, bool strict_iomode) { struct pnfs_layout_range range1; if ((range->iomode == IOMODE_RW && ls_range->iomode != IOMODE_RW) || (range->iomode != ls_range->iomode && strict_iomode == true) || !pnfs_lseg_range_intersecting(ls_range, range)) return 0; /* range1 covers only the first byte in the range */ range1 = *range; range1.length = 1; return pnfs_lseg_range_contained(ls_range, &range1); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy4855.17%120.00%
tom haynestom haynes1719.54%120.00%
andy adamsonandy adamson1618.39%120.00%
trond myklebusttrond myklebust66.90%240.00%
Total87100.00%5100.00%

/* * lookup range in layout */
static struct pnfs_layout_segment * pnfs_find_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_range *range, bool strict_iomode) { struct pnfs_layout_segment *lseg, *ret = NULL; dprintk("%s:Begin\n", __func__); list_for_each_entry(lseg, &lo->plh_segs, pls_list) { if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) && pnfs_lseg_range_match(&lseg->pls_range, range, strict_iomode)) { ret = pnfs_get_lseg(lseg); break; } } dprintk("%s:Return lseg %p ref %d\n", __func__, ret, ret ? atomic_read(&ret->pls_refcount) : 0); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson7564.10%19.09%
fred isamanfred isaman1613.68%545.45%
peng taopeng tao119.40%19.09%
benny halevybenny halevy86.84%19.09%
tom haynestom haynes54.27%19.09%
trond myklebusttrond myklebust21.71%218.18%
Total117100.00%11100.00%

/* * Use mdsthreshold hints set at each OPEN to determine if I/O should go * to the MDS or over pNFS * * The nfs_inode read_io and write_io fields are cumulative counters reset * when there are no layout segments. Note that in pnfs_update_layout iomode * is set to IOMODE_READ for a READ request, and set to IOMODE_RW for a * WRITE request. * * A return of true means use MDS I/O. * * From rfc 5661: * If a file's size is smaller than the file size threshold, data accesses * SHOULD be sent to the metadata server. If an I/O request has a length that * is below the I/O size threshold, the I/O SHOULD be sent to the metadata * server. If both file size and I/O size are provided, the client SHOULD * reach or exceed both thresholds before sending its read or write * requests to the data server. */
static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx, struct inode *ino, int iomode) { struct nfs4_threshold *t = ctx->mdsthreshold; struct nfs_inode *nfsi = NFS_I(ino); loff_t fsize = i_size_read(ino); bool size = false, size_set = false, io = false, io_set = false, ret = false; if (t == NULL) return ret; dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n", __func__, t->bm, t->rd_sz, t->wr_sz, t->rd_io_sz, t->wr_io_sz); switch (iomode) { case IOMODE_READ: if (t->bm & THRESHOLD_RD) { dprintk("%s fsize %llu\n", __func__, fsize); size_set = true; if (fsize < t->rd_sz) size = true; } if (t->bm & THRESHOLD_RD_IO) { dprintk("%s nfsi->read_io %llu\n", __func__, nfsi->read_io); io_set = true; if (nfsi->read_io < t->rd_io_sz) io = true; } break; case IOMODE_RW: if (t->bm & THRESHOLD_WR) { dprintk("%s fsize %llu\n", __func__, fsize); size_set = true; if (fsize < t->wr_sz) size = true; } if (t->bm & THRESHOLD_WR_IO) { dprintk("%s nfsi->write_io %llu\n", __func__, nfsi->write_io); io_set = true; if (nfsi->write_io < t->wr_io_sz) io = true; } break; } if (size_set && io_set) { if (size && io) ret = true; } else if (size || io) ret = true; dprintk("<-- %s size %d io %d ret %d\n", __func__, size, io, ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson310100.00%1100.00%
Total310100.00%1100.00%


static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo) { /* * send layoutcommit as it can hold up layoutreturn due to lseg * reference */ pnfs_layoutcommit_inode(lo->plh_inode, false); return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN, nfs_wait_bit_killable, TASK_UNINTERRUPTIBLE); }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao3697.30%150.00%
trond myklebusttrond myklebust12.70%150.00%
Total37100.00%2100.00%


static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo) { unsigned long *bitlock = &lo->plh_flags; clear_bit_unlock(NFS_LAYOUT_FIRST_LAYOUTGET, bitlock); smp_mb__after_atomic(); wake_up_bit(bitlock, NFS_LAYOUT_FIRST_LAYOUTGET); }

Contributors

PersonTokensPropCommitsCommitProp
tom haynestom haynes2976.32%150.00%
andy adamsonandy adamson923.68%150.00%
Total38100.00%2100.00%

/* * Layout segment is retreived from the server if not cached. * The appropriate layout segment is referenced and returned to the caller. */
struct pnfs_layout_segment * pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, loff_t pos, u64 count, enum pnfs_iomode iomode, bool strict_iomode, gfp_t gfp_flags) { struct pnfs_layout_range arg = { .iomode = iomode, .offset = pos, .length = count, }; unsigned pg_offset, seq; struct nfs_server *server = NFS_SERVER(ino); struct nfs_client *clp = server->nfs_client; struct pnfs_layout_hdr *lo = NULL; struct pnfs_layout_segment *lseg = NULL; nfs4_stateid stateid; long timeout = 0; unsigned long giveup = jiffies + rpc_get_timeout(server->client); bool first; if (!pnfs_enabled_sb(NFS_SERVER(ino))) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_NO_PNFS); goto out; } if (iomode == IOMODE_READ && i_size_read(ino) == 0) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_RD_ZEROLEN); goto out; } if (pnfs_within_mdsthreshold(ctx, ino, iomode)) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_MDSTHRESH); goto out; } lookup_again: first = false; spin_lock(&ino->i_lock); lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags); if (lo == NULL) { spin_unlock(&ino->i_lock); trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_NOMEM); goto out; } /* Do we even need to bother with this? */ if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_BULK_RECALL); dprintk("%s matches recall, use MDS\n", __func__); goto out_unlock; } /* if LAYOUTGET already failed once we don't try again */ if (pnfs_layout_io_test_failed(lo, iomode)) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_IO_TEST_FAIL); goto out_unlock; } lseg = pnfs_find_lseg(lo, &arg, strict_iomode); if (lseg) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_FOUND_CACHED); goto out_unlock; } if (!nfs4_valid_open_stateid(ctx->state)) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_INVALID_OPEN); goto out_unlock; } /* * Choose a stateid for the LAYOUTGET. If we don't have a layout * stateid, or it has been invalidated, then we must use the open * stateid. */ if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { /* * The first layoutget for the file. Need to serialize per * RFC 5661 Errata 3208. */ if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags)) { spin_unlock(&ino->i_lock); wait_on_bit(&lo->plh_flags, NFS_LAYOUT_FIRST_LAYOUTGET, TASK_UNINTERRUPTIBLE); pnfs_put_layout_hdr(lo); dprintk("%s retrying\n", __func__); goto lookup_again; } first = true; do { seq = read_seqbegin(&ctx->state->seqlock); nfs4_stateid_copy(&stateid, &ctx->state->stateid); } while (read_seqretry(&ctx->state->seqlock, seq)); } else { nfs4_stateid_copy(&stateid, &lo->plh_stateid); } /* * Because we free lsegs before sending LAYOUTRETURN, we need to wait * for LAYOUTRETURN even if first is true. */ if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) { spin_unlock(&ino->i_lock); dprintk("%s wait for layoutreturn\n", __func__); if (pnfs_prepare_to_retry_layoutget(lo)) { if (first) pnfs_clear_first_layoutget(lo); pnfs_put_layout_hdr(lo); dprintk("%s retrying\n", __func__); trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_RETRY); goto lookup_again; } trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_RETURN); goto out_put_layout_hdr; } if (pnfs_layoutgets_blocked(lo)) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_BLOCKED); goto out_unlock; } atomic_inc(&lo->plh_outstanding); spin_unlock(&ino->i_lock); if (list_empty(&lo->plh_layouts)) { /* The lo must be on the clp list if there is any * chance of a CB_LAYOUTRECALL(FILE) coming in. */ spin_lock(&clp->cl_lock); if (list_empty(&lo->plh_layouts)) list_add_tail(&lo->plh_layouts, &server->layouts); spin_unlock(&clp->cl_lock); } pg_offset = arg.offset & ~PAGE_MASK; if (pg_offset) { arg.offset -= pg_offset; arg.length += pg_offset; } if (arg.length != NFS4_MAX_UINT64) arg.length = PAGE_ALIGN(arg.length); lseg = send_layoutget(lo, ctx, &stateid, &arg, &timeout, gfp_flags); trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); if (IS_ERR(lseg)) { switch(PTR_ERR(lseg)) { case -ERECALLCONFLICT: if (time_after(jiffies, giveup)) lseg = NULL; /* Fallthrough */ case -EAGAIN: pnfs_put_layout_hdr(lo); if (first) pnfs_clear_first_layoutget(lo); if (lseg) { trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_RETRY); goto lookup_again; } /* Fallthrough */ default: if (!nfs_error_is_fatal(PTR_ERR(lseg))) { pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); lseg = NULL; } } } else { pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); } atomic_dec(&lo->plh_outstanding); out_put_layout_hdr: if (first) pnfs_clear_first_layoutget(lo); pnfs_put_layout_hdr(lo); out: dprintk("%s: inode %s/%llu pNFS layout segment %s for " "(%s, offset: %llu, length: %llu)\n", __func__, ino->i_sb->s_id, (unsigned long long)NFS_FILEID(ino), IS_ERR_OR_NULL(lseg) ? "not found" : "found", iomode==IOMODE_RW ? "read/write" : "read-only", (unsigned long long)pos, (unsigned long long)count); return lseg; out_unlock: spin_unlock(&ino->i_lock); goto out_put_layout_hdr; }

Contributors

PersonTokensPropCommitsCommitProp
jeff laytonjeff layton46043.94%39.68%
andy adamsonandy adamson14914.23%516.13%
peng taopeng tao14613.94%516.13%
fred isamanfred isaman1019.65%516.13%
trond myklebusttrond myklebust938.88%722.58%
benny halevybenny halevy696.59%26.45%
tom haynestom haynes161.53%26.45%
weston andros adamsonweston andros adamson111.05%13.23%
kirill a. shutemovkirill a. shutemov20.19%13.23%
Total1047100.00%31100.00%

EXPORT_SYMBOL_GPL(pnfs_update_layout);
static bool pnfs_sanity_check_layout_range(struct pnfs_layout_range *range) { switch (range->iomode) { case IOMODE_READ: case IOMODE_RW: break; default: return false; } if (range->offset == NFS4_MAX_UINT64) return false; if (range->length == 0) return false; if (range->length != NFS4_MAX_UINT64 && range->length > NFS4_MAX_UINT64 - range->offset) return false; return true; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust76100.00%1100.00%
Total76100.00%1100.00%


struct pnfs_layout_segment * pnfs_layout_process(struct nfs4_layoutget *lgp) { struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout; struct nfs4_layoutget_res *res = &lgp->res; struct pnfs_layout_segment *lseg; struct inode *ino = lo->plh_inode; LIST_HEAD(free_me); if (!pnfs_sanity_check_layout_range(&res->range)) return ERR_PTR(-EINVAL); /* Inject layout blob into I/O device driver */ lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags); if (IS_ERR_OR_NULL(lseg)) { if (!lseg) lseg = ERR_PTR(-ENOMEM); dprintk("%s: Could not allocate layout: error %ld\n", __func__, PTR_ERR(lseg)); return lseg; } init_lseg(lo, lseg); lseg->pls_range = res->range; lseg->pls_seq = be32_to_cpu(res->stateid.seqid); spin_lock(&ino->i_lock); if (pnfs_layoutgets_blocked(lo)) { dprintk("%s forget reply due to state\n", __func__); goto out_forget; } if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { /* existing state ID, make sure the sequence number matches. */ if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { dprintk("%s forget reply due to sequence\n", __func__); goto out_forget; } pnfs_set_layout_stateid(lo, &res->stateid, false); } else { /* * We got an entirely new state ID. Mark all segments for the * inode invalid, and don't bother validating the stateid * sequence number. */ pnfs_mark_matching_lsegs_invalid(lo, &free_me, NULL, 0); nfs4_stateid_copy(&lo->plh_stateid, &res->stateid); lo->plh_barrier = be32_to_cpu(res->stateid.seqid); } clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); pnfs_get_lseg(lseg); pnfs_layout_insert_lseg(lo, lseg, &free_me); if (res->return_on_close) set_bit(NFS_LSEG_ROC, &lseg->pls_flags); spin_unlock(&ino->i_lock); pnfs_free_lseg_list(&free_me); return lseg; out_forget: spin_unlock(&ino->i_lock); lseg->pls_layout = lo; NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg); return ERR_PTR(-EAGAIN); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson11430.24%15.00%
christoph hellwigchristoph hellwig8923.61%315.00%
fred isamanfred isaman6717.77%420.00%
trond myklebusttrond myklebust6316.71%945.00%
jeff laytonjeff layton4411.67%315.00%
Total377100.00%20100.00%


static void pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode, u32 seq) { if (lo->plh_return_iomode == iomode) return; if (lo->plh_return_iomode != 0) iomode = IOMODE_ANY; lo->plh_return_iomode = iomode; set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); if (!lo->plh_return_seq || pnfs_seqid_is_newer(seq, lo->plh_return_seq)) lo->plh_return_seq = seq; }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4963.64%250.00%
jeff laytonjeff layton2633.77%125.00%
peng taopeng tao22.60%125.00%
Total77100.00%4100.00%

/** * pnfs_mark_matching_lsegs_return - Free or return matching layout segments * @lo: pointer to layout header * @tmp_list: list header to be used with pnfs_free_lseg_list() * @return_range: describe layout segment ranges to be returned * * This function is mainly intended for use by layoutrecall. It attempts * to free the layout segment immediately, or else to mark it for return * as soon as its reference count drops to zero. */
int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, struct list_head *tmp_list, const struct pnfs_layout_range *return_range, u32 seq) { struct pnfs_layout_segment *lseg, *next; int remaining = 0; dprintk("%s:Begin lo %p\n", __func__, lo); if (list_empty(&lo->plh_segs)) return 0; assert_spin_locked(&lo->plh_inode->i_lock); list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) if (should_free_lseg(&lseg->pls_range, return_range)) { dprintk("%s: marking lseg %p iomode %d " "offset %llu length %llu\n", __func__, lseg, lseg->pls_range.iomode, lseg->pls_range.offset, lseg->pls_range.length); if (mark_lseg_invalid(lseg, tmp_list)) continue; remaining++; set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); } if (remaining) pnfs_set_plh_return_info(lo, return_range->iomode, seq); return remaining; }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao10262.96%110.00%
trond myklebusttrond myklebust4729.01%660.00%
jeff laytonjeff layton116.79%220.00%
christoph hellwigchristoph hellwig21.23%110.00%
Total162100.00%10100.00%


void pnfs_error_mark_layout_for_return(struct inode *inode, struct pnfs_layout_segment *lseg) { struct pnfs_layout_hdr *lo = NFS_I(inode)->layout; struct pnfs_layout_range range = { .iomode = lseg->pls_range.iomode, .offset = 0, .length = NFS4_MAX_UINT64, }; LIST_HEAD(free_me); bool return_now = false; spin_lock(&inode->i_lock); pnfs_set_plh_return_info(lo, range.iomode, lseg->pls_seq); /* * mark all matching lsegs so that we are sure to have no live * segments at hand when sending layoutreturn. See pnfs_put_lseg() * for how it works. */ if (!pnfs_mark_matching_lsegs_return(lo, &free_me, &range, lseg->pls_seq)) { nfs4_stateid stateid; enum pnfs_iomode iomode = lo->plh_return_iomode; nfs4_stateid_copy(&stateid, &lo->plh_stateid); return_now = pnfs_prepare_layoutreturn(lo); spin_unlock(&inode->i_lock); if (return_now) pnfs_send_layoutreturn(lo, &stateid, iomode, false); } else { spin_unlock(&inode->i_lock); nfs_commit_inode(inode, 0); } pnfs_free_lseg_list(&free_me); }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao8245.30%17.69%
trond myklebusttrond myklebust6133.70%430.77%
fred isamanfred isaman2011.05%323.08%
jeff laytonjeff layton94.97%215.38%
christoph hellwigchristoph hellwig52.76%215.38%
andy adamsonandy adamson42.21%17.69%
Total181100.00%13100.00%

EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) { u64 rd_size = req->wb_bytes; if (pgio->pg_lseg == NULL) { if (pgio->pg_dreq == NULL) rd_size = i_size_read(pgio->pg_inode) - req_offset(req); else rd_size = nfs_dreq_bytes_left(pgio->pg_dreq); pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, req->wb_context, req_offset(req), rd_size, IOMODE_READ, false, GFP_KERNEL); if (IS_ERR(pgio->pg_lseg)) { pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_lseg = NULL; return; } } /* If no lseg, fall back to read through mds */ if (pgio->pg_lseg == NULL) nfs_pageio_reset_read_mds(pgio); }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao7354.07%337.50%
trond myklebusttrond myklebust5842.96%337.50%
fred isamanfred isaman21.48%112.50%
tom haynestom haynes21.48%112.50%
Total135100.00%8100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read);
void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req, u64 wb_size) { if (pgio->pg_lseg == NULL) { pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, req->wb_context, req_offset(req), wb_size, IOMODE_RW, false, GFP_NOFS); if (IS_ERR(pgio->pg_lseg)) { pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_lseg = NULL; return; } } /* If no lseg, fall back to write through mds */ if (pgio->pg_lseg == NULL) nfs_pageio_reset_write_mds(pgio); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust5858.59%342.86%
peng taopeng tao3939.39%342.86%
tom haynestom haynes22.02%114.29%
Total99100.00%7100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
void pnfs_generic_pg_cleanup(struct nfs_pageio_descriptor *desc) { if (desc->pg_lseg) { pnfs_put_lseg(desc->pg_lseg); desc->pg_lseg = NULL; } }

Contributors

PersonTokensPropCommitsCommitProp
weston andros adamsonweston andros adamson2477.42%133.33%
trond myklebusttrond myklebust722.58%266.67%
Total31100.00%3100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_cleanup); /* * Return 0 if @req cannot be coalesced into @pgio, otherwise return the number * of bytes (maximum @req->wb_bytes) that can be coalesced. */
size_t pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req) { unsigned int size; u64 seg_end, req_start, seg_left; size = nfs_generic_pg_test(pgio, prev, req); if (!size) return 0; /* * 'size' contains the number of bytes left in the current page (up * to the original size asked for in @req->wb_bytes). * * Calculate how many bytes are left in the layout segment * and if there are less bytes than 'size', return that instead. * * Please also note that 'end_offset' is actually the offset of the * first byte that lies outside the pnfs_layout_range. FIXME? * */ if (pgio->pg_lseg) { seg_end = end_offset(pgio->pg_lseg->pls_range.offset, pgio->pg_lseg->pls_range.length); req_start = req_offset(req); WARN_ON_ONCE(req_start >= seg_end); /* start of request is past the last byte of this segment */ if (req_start >= seg_end) { /* reference the new lseg */ if (pgio->pg_ops->pg_cleanup) pgio->pg_ops->pg_cleanup(pgio); if (pgio->pg_ops->pg_init) pgio->pg_ops->pg_init(pgio, req); return 0; } /* adjust 'size' iff there are fewer bytes left in the * segment than what nfs_generic_pg_test returned */ seg_left = seg_end - req_start; if (seg_left < size) size = (unsigned int)seg_left; } return size; }

Contributors

PersonTokensPropCommitsCommitProp
weston andros adamsonweston andros adamson10864.67%535.71%
trond myklebusttrond myklebust2615.57%321.43%
fred isamanfred isaman1710.18%321.43%
benny halevybenny halevy169.58%321.43%
Total167100.00%14100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *hdr) { struct nfs_pageio_descriptor pgio; /* Resend all requests through the MDS */ nfs_pageio_init_write(&pgio, hdr->inode, FLUSH_STABLE, true, hdr->completion_ops); set_bit(NFS_CONTEXT_RESEND_WRITES, &hdr->args.context->flags); return nfs_pageio_resend(&pgio, hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4275.00%228.57%
weston andros adamsonweston andros adamson916.07%114.29%
christoph hellwigchristoph hellwig23.57%114.29%
bryan schumakerbryan schumaker11.79%114.29%
fred isamanfred isaman11.79%114.29%
benny halevybenny halevy11.79%114.29%
Total56100.00%7100.00%

EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);
static void pnfs_ld_handle_write_error(struct nfs_pgio_header *hdr) { dprintk("pnfs write error = %d\n", hdr->pnfs_error); if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & PNFS_LAYOUTRET_ON_ERROR) { pnfs_return_layout(hdr->inode); } if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) hdr->task.tk_status = pnfs_write_done_resend_to_mds(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman2536.76%444.44%
boaz harroshboaz harrosh2232.35%111.11%
trond myklebusttrond myklebust913.24%111.11%
peng taopeng tao68.82%111.11%
benny halevybenny halevy34.41%111.11%
weston andros adamsonweston andros adamson34.41%111.11%
Total68100.00%9100.00%

/* * Called by non rpc-based layout drivers */
void pnfs_ld_write_done(struct nfs_pgio_header *hdr) { if (likely(!hdr->pnfs_error)) { pnfs_set_layoutcommit(hdr->inode, hdr->lseg, hdr->mds_offset + hdr->res.count); hdr->mds_ops->rpc_call_done(&hdr->task, hdr); } trace_nfs4_pnfs_write(hdr, hdr->pnfs_error); if (unlikely(hdr->pnfs_error)) pnfs_ld_handle_write_error(hdr); hdr->mds_ops->rpc_release(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman3842.70%337.50%
kinglong meekinglong mee2123.60%112.50%
trond myklebusttrond myklebust1617.98%112.50%
weston andros adamsonweston andros adamson77.87%112.50%
benny halevybenny halevy44.49%112.50%
peng taopeng tao33.37%112.50%
Total89100.00%8100.00%

EXPORT_SYMBOL_GPL(pnfs_ld_write_done);
static void pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr) { struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc); if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { list_splice_tail_init(&hdr->pages, &mirror->pg_list); nfs_pageio_reset_write_mds(desc); mirror->pg_recoalesce = 1; } nfs_pgio_data_destroy(hdr); hdr->release(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4659.74%225.00%
fred isamanfred isaman1519.48%225.00%
weston andros adamsonweston andros adamson1316.88%337.50%
peng taopeng tao33.90%112.50%
Total77100.00%8100.00%


static enum pnfs_try_status pnfs_try_to_write_data(struct nfs_pgio_header *hdr, const struct rpc_call_ops *call_ops, struct pnfs_layout_segment *lseg, int how) { struct inode *inode = hdr->inode; enum pnfs_try_status trypnfs; struct nfs_server *nfss = NFS_SERVER(inode); hdr->mds_ops = call_ops; dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, inode->i_ino, hdr->args.count, hdr->args.offset, how); trypnfs = nfss->pnfs_curr_ld->write_pagelist(hdr, how); if (trypnfs != PNFS_NOT_ATTEMPTED) nfs_inc_stats(inode, NFSIOS_PNFS_WRITE); dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); return trypnfs; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson10488.14%120.00%
trond myklebusttrond myklebust65.08%120.00%
weston andros adamsonweston andros adamson54.24%120.00%
fred isamanfred isaman32.54%240.00%
Total118100.00%5100.00%


static void pnfs_do_write(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr, int how) { const struct rpc_call_ops *call_ops = desc->pg_rpc_callops; struct pnfs_layout_segment *lseg = desc->pg_lseg; enum pnfs_try_status trypnfs; trypnfs = pnfs_try_to_write_data(hdr, call_ops, lseg, how); if (trypnfs == PNFS_NOT_ATTEMPTED) pnfs_write_through_mds(desc, hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust6392.65%133.33%
weston andros adamsonweston andros adamson57.35%266.67%
Total68100.00%3100.00%


static void pnfs_writehdr_free(struct nfs_pgio_header *hdr) { pnfs_put_lseg(hdr->lseg); nfs_pgio_header_free(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman2191.30%133.33%
weston andros adamsonweston andros adamson14.35%133.33%
trond myklebusttrond myklebust14.35%133.33%
Total23100.00%3100.00%


int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) { struct nfs_pgio_header *hdr; int ret; hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); if (!hdr) { desc->pg_error = -ENOMEM; return desc->pg_error; } nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); hdr->lseg = pnfs_get_lseg(desc->pg_lseg); ret = nfs_generic_pgio(desc, hdr); if (!ret) pnfs_do_write(desc, hdr, desc->pg_ioflags); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman4042.55%220.00%
trond myklebusttrond myklebust3638.30%220.00%
peng taopeng tao77.45%110.00%
anna schumakeranna schumaker66.38%220.00%
weston andros adamsonweston andros adamson55.32%330.00%
Total94100.00%10100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
int pnfs_read_done_resend_to_mds(struct nfs_pgio_header *hdr) { struct nfs_pageio_descriptor pgio; /* Resend all requests through the MDS */ nfs_pageio_init_read(&pgio, hdr->inode, true, hdr->completion_ops); return nfs_pageio_resend(&pgio, hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust1845.00%114.29%
weston andros adamsonweston andros adamson922.50%114.29%
fred isamanfred isaman922.50%228.57%
christoph hellwigchristoph hellwig25.00%114.29%
benny halevybenny halevy12.50%114.29%
bryan schumakerbryan schumaker12.50%114.29%
Total40100.00%7100.00%

EXPORT_SYMBOL_GPL(pnfs_read_done_resend_to_mds);
static void pnfs_ld_handle_read_error(struct nfs_pgio_header *hdr) { dprintk("pnfs read error = %d\n", hdr->pnfs_error); if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & PNFS_LAYOUTRET_ON_ERROR) { pnfs_return_layout(hdr->inode); } if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) hdr->task.tk_status = pnfs_read_done_resend_to_mds(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman6494.12%360.00%
weston andros adamsonweston andros adamson34.41%120.00%
trond myklebusttrond myklebust11.47%120.00%
Total68100.00%5100.00%

/* * Called by non rpc-based layout drivers */
void pnfs_ld_read_done(struct nfs_pgio_header *hdr) { if (likely(!hdr->pnfs_error)) { __nfs4_read_done_cb(hdr); hdr->mds_ops->rpc_call_done(&hdr->task, hdr); } trace_nfs4_pnfs_read(hdr, hdr->pnfs_error); if (unlikely(hdr->pnfs_error)) pnfs_ld_handle_read_error(hdr); hdr->mds_ops->rpc_release(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
benny halevybenny halevy3345.21%116.67%
kinglong meekinglong mee1824.66%116.67%
peng taopeng tao810.96%116.67%
weston andros adamsonweston andros adamson79.59%116.67%
fred isamanfred isaman68.22%116.67%
trond myklebusttrond myklebust11.37%116.67%
Total73100.00%6100.00%

EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
static void pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr) { struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc); if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { list_splice_tail_init(&hdr->pages, &mirror->pg_list); nfs_pageio_reset_read_mds(desc); mirror->pg_recoalesce = 1; } nfs_pgio_data_destroy(hdr); hdr->release(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4659.74%225.00%
fred isamanfred isaman1519.48%225.00%
weston andros adamsonweston andros adamson1316.88%337.50%
peng taopeng tao33.90%112.50%
Total77100.00%8100.00%

/* * Call the appropriate parallel I/O subsystem read function. */
static enum pnfs_try_status pnfs_try_to_read_data(struct nfs_pgio_header *hdr, const struct rpc_call_ops *call_ops, struct pnfs_layout_segment *lseg) { struct inode *inode = hdr->inode; struct nfs_server *nfss = NFS_SERVER(inode); enum pnfs_try_status trypnfs; hdr->mds_ops = call_ops; dprintk("%s: Reading ino:%lu %u@%llu\n", __func__, inode->i_ino, hdr->args.count, hdr->args.offset); trypnfs = nfss->pnfs_curr_ld->read_pagelist(hdr); if (trypnfs != PNFS_NOT_ATTEMPTED) nfs_inc_stats(inode, NFSIOS_PNFS_READ); dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); return trypnfs; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson9787.39%120.00%
trond myklebusttrond myklebust65.41%120.00%
weston andros adamsonweston andros adamson54.50%120.00%
fred isamanfred isaman32.70%240.00%
Total111100.00%5100.00%

/* Resend all requests through pnfs. */
void pnfs_read_resend_pnfs(struct nfs_pgio_header *hdr) { struct nfs_pageio_descriptor pgio; if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { nfs_pageio_init_read(&pgio, hdr->inode, false, hdr->completion_ops); hdr->task.tk_status = nfs_pageio_resend(&pgio, hdr); } }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao3661.02%150.00%
weston andros adamsonweston andros adamson2338.98%150.00%
Total59100.00%2100.00%

EXPORT_SYMBOL_GPL(pnfs_read_resend_pnfs);
static void pnfs_do_read(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr) { const struct rpc_call_ops *call_ops = desc->pg_rpc_callops; struct pnfs_layout_segment *lseg = desc->pg_lseg; enum pnfs_try_status trypnfs; trypnfs = pnfs_try_to_read_data(hdr, call_ops, lseg); if (trypnfs == PNFS_TRY_AGAIN) pnfs_read_resend_pnfs(hdr); if (trypnfs == PNFS_NOT_ATTEMPTED || hdr->task.tk_status) pnfs_read_through_mds(desc, hdr); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust5872.50%120.00%
peng taopeng tao1215.00%120.00%
weston andros adamsonweston andros adamson1012.50%360.00%
Total80100.00%5100.00%


static void pnfs_readhdr_free(struct nfs_pgio_header *hdr) { pnfs_put_lseg(hdr->lseg); nfs_pgio_header_free(hdr); }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman2191.30%133.33%
weston andros adamsonweston andros adamson14.35%133.33%
trond myklebusttrond myklebust14.35%133.33%
Total23100.00%3100.00%


int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) { struct nfs_pgio_header *hdr; int ret; hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); if (!hdr) { desc->pg_error = -ENOMEM; return desc->pg_error; } nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); hdr->lseg = pnfs_get_lseg(desc->pg_lseg); ret = nfs_generic_pgio(desc, hdr); if (!ret) pnfs_do_read(desc, hdr); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
fred isamanfred isaman4752.22%220.00%
trond myklebusttrond myklebust2527.78%220.00%
peng taopeng tao77.78%110.00%
anna schumakeranna schumaker66.67%220.00%
weston andros adamsonweston andros adamson55.56%330.00%
Total90100.00%10100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
static void pnfs_clear_layoutcommitting(struct inode *inode) { unsigned long *bitlock = &NFS_I(inode)->flags; clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); smp_mb__after_atomic(); wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust4097.56%150.00%
peter zijlstrapeter zijlstra12.44%150.00%
Total41100.00%2100.00%

/* * There can be multiple RW segments. */
static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp) { struct pnfs_layout_segment *lseg; list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) { if (lseg->pls_range.iomode == IOMODE_RW && test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) list_add(&lseg->pls_lc_list, listp); } }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson3557.38%133.33%
peng taopeng tao2540.98%133.33%
trond myklebusttrond myklebust11.64%133.33%
Total61100.00%3100.00%


static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp) { struct pnfs_layout_segment *lseg, *tmp; /* Matched by references in pnfs_set_layoutcommit */ list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) { list_del_init(&lseg->pls_lc_list); pnfs_put_lseg(lseg); } pnfs_clear_layoutcommitting(inode); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust55100.00%2100.00%
Total55100.00%2100.00%


void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) { pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode); }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao1982.61%150.00%
trond myklebusttrond myklebust417.39%150.00%
Total23100.00%2100.00%

EXPORT_SYMBOL_GPL(pnfs_set_lo_fail);
void pnfs_set_layoutcommit(struct inode *inode, struct pnfs_layout_segment *lseg, loff_t end_pos) { struct nfs_inode *nfsi = NFS_I(inode); bool mark_as_dirty = false; spin_lock(&inode->i_lock); if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { nfsi->layout->plh_lwb = end_pos; mark_as_dirty = true; dprintk("%s: Set layoutcommit for inode %lu ", __func__, inode->i_ino); } else if (end_pos > nfsi->layout->plh_lwb) nfsi->layout->plh_lwb = end_pos; if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) { /* references matched in nfs4_layoutcommit_release */ pnfs_get_lseg(lseg); } spin_unlock(&inode->i_lock); dprintk("%s: lseg %p end_pos %llu\n", __func__, lseg, nfsi->layout->plh_lwb); /* if pnfs_layoutcommit_inode() runs between inode locks, the next one * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ if (mark_as_dirty) mark_inode_dirty_sync(inode); }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao11072.37%120.00%
trond myklebusttrond myklebust3120.39%240.00%
andy adamsonandy adamson74.61%120.00%
fred isamanfred isaman42.63%120.00%
Total152100.00%5100.00%

EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data) { struct nfs_server *nfss = NFS_SERVER(data->args.inode); if (nfss->pnfs_curr_ld->cleanup_layoutcommit) nfss->pnfs_curr_ld->cleanup_layoutcommit(data); pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list); }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson4174.55%150.00%
trond myklebusttrond myklebust1425.45%150.00%
Total55100.00%2100.00%

/* * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough * data to disk to allow the server to recover the data if it crashes. * LAYOUTCOMMIT is only needed when the NFL4_UFLG_COMMIT_THRU_MDS flag * is off, and a COMMIT is sent to a data server, or * if WRITEs to a data server return NFS_DATA_SYNC. */
int pnfs_layoutcommit_inode(struct inode *inode, bool sync) { struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; struct nfs4_layoutcommit_data *data; struct nfs_inode *nfsi = NFS_I(inode); loff_t end_pos; int status; if (!pnfs_layoutcommit_outstanding(inode)) return 0; dprintk("--> %s inode %lu\n", __func__, inode->i_ino); status = -EAGAIN; if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) { if (!sync) goto out; status = wait_on_bit_lock_action(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING, nfs_wait_bit_killable, TASK_KILLABLE); if (status) goto out; } status = -ENOMEM; /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ data = kzalloc(sizeof(*data), GFP_NOFS); if (!data) goto clear_layoutcommitting; status = 0; spin_lock(&inode->i_lock); if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) goto out_unlock; INIT_LIST_HEAD(&data->lseg_list); pnfs_list_write_lseg(inode, &data->lseg_list); end_pos = nfsi->layout->plh_lwb; nfs4_stateid_copy(&data->args.stateid, &nfsi->layout->plh_stateid); spin_unlock(&inode->i_lock); data->args.inode = inode; data->cred = get_rpccred(nfsi->layout->plh_lc_cred); nfs_fattr_init(&data->fattr); data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; data->res.fattr = &data->fattr; data->args.lastbytewritten = end_pos - 1; data->res.server = NFS_SERVER(inode); if (ld->prepare_layoutcommit) { status = ld->prepare_layoutcommit(&data->args); if (status) { put_rpccred(data->cred); spin_lock(&inode->i_lock); set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); if (end_pos > nfsi->layout->plh_lwb) nfsi->layout->plh_lwb = end_pos; goto out_unlock; } } status = nfs4_proc_layoutcommit(data, sync); out: if (status) mark_inode_dirty_sync(inode); dprintk("<-- %s status %d\n", __func__, status); return status; out_unlock: spin_unlock(&inode->i_lock); kfree(data); clear_layoutcommitting: pnfs_clear_layoutcommitting(inode); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson19645.90%323.08%
peng taopeng tao8319.44%430.77%
trond myklebusttrond myklebust7417.33%323.08%
christoph hellwigchristoph hellwig6515.22%17.69%
jeff laytonjeff layton81.87%17.69%
neil brownneil brown10.23%17.69%
Total427100.00%13100.00%

EXPORT_SYMBOL_GPL(pnfs_layoutcommit_inode);
int pnfs_generic_sync(struct inode *inode, bool datasync) { return pnfs_layoutcommit_inode(inode, true); }

Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust21100.00%1100.00%
Total21100.00%1100.00%

EXPORT_SYMBOL_GPL(pnfs_generic_sync);
struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) { struct nfs4_threshold *thp; thp = kzalloc(sizeof(*thp), GFP_NOFS); if (!thp) { dprintk("%s mdsthreshold allocation failed\n", __func__); return NULL; } return thp; }

Contributors

PersonTokensPropCommitsCommitProp
andy adamsonandy adamson47100.00%1100.00%
Total47100.00%1100.00%

#if IS_ENABLED(CONFIG_NFS_V4_2)
int pnfs_report_layoutstat(struct inode *inode, gfp_t gfp_flags) { struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; struct nfs_server *server = NFS_SERVER(inode); struct nfs_inode *nfsi = NFS_I(inode); struct nfs42_layoutstat_data *data; struct pnfs_layout_hdr *hdr; int status = 0; if (!pnfs_enabled_sb(server) || !ld->prepare_layoutstats) goto out; if (!nfs_server_capable(inode, NFS_CAP_LAYOUTSTATS)) goto out; if (test_and_set_bit(NFS_INO_LAYOUTSTATS, &nfsi->flags)) goto out; spin_lock(&inode->i_lock); if (!NFS_I(inode)->layout) { spin_unlock(&inode->i_lock); goto out_clear_layoutstats; } hdr = NFS_I(inode)->layout; pnfs_get_layout_hdr(hdr); spin_unlock(&inode->i_lock); data = kzalloc(sizeof(*data), gfp_flags); if (!data) { status = -ENOMEM; goto out_put; } data->args.fh = NFS_FH(inode); data->args.inode = inode; nfs4_stateid_copy(&data->args.stateid, &hdr->plh_stateid); status = ld->prepare_layoutstats(&data->args); if (status) goto out_free; status = nfs42_proc_layoutstats_generic(NFS_SERVER(inode), data); out: dprintk("%s returns %d\n", __func__, status); return status; out_free: kfree(data); out_put: pnfs_put_layout_hdr(hdr); out_clear_layoutstats: smp_mb__before_atomic(); clear_bit(NFS_INO_LAYOUTSTATS, &nfsi->flags); smp_mb__after_atomic(); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
peng taopeng tao27993.31%240.00%
trond myklebusttrond myklebust206.69%360.00%
Total299100.00%5100.00%

EXPORT_SYMBOL_GPL(pnfs_report_layoutstat); #endif unsigned int layoutstats_timer; module_param(layoutstats_timer, uint, 0644); EXPORT_SYMBOL_GPL(layoutstats_timer);

Overall Contributors

PersonTokensPropCommitsCommitProp
trond myklebusttrond myklebust366832.31%9340.26%
andy adamsonandy adamson205618.11%208.66%
fred isamanfred isaman162714.33%2510.82%
peng taopeng tao153913.56%3414.72%
benny halevybenny halevy8367.36%114.76%
jeff laytonjeff layton6595.81%93.90%
weston andros adamsonweston andros adamson3513.09%156.49%
christoph hellwigchristoph hellwig2312.04%83.46%
ricardo labiagaricardo labiaga1871.65%10.43%
tom haynestom haynes1040.92%20.87%
kinglong meekinglong mee390.34%10.43%
boaz harroshboaz harrosh220.19%10.43%
anna schumakeranna schumaker120.11%20.87%
yanchuan nianyanchuan nian80.07%20.87%
paul gortmakerpaul gortmaker30.03%10.43%
kirill a. shutemovkirill a. shutemov30.03%10.43%
bryan schumakerbryan schumaker20.02%20.87%
idan kedaridan kedar20.02%10.43%
peter zijlstrapeter zijlstra10.01%10.43%
neil brownneil brown10.01%10.43%
Total11351100.00%231100.00%
Directory: fs/nfs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}