Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217192
b: refs/heads/master
c: e5e9401
h: refs/heads/master
v: v3
  • Loading branch information
Benny Halevy authored and Trond Myklebust committed Oct 24, 2010
1 parent 0e21534 commit 43df462
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7ab672ce312133ee4a5d85b71447b2b334403681
refs/heads/master: e5e940170b2136ad4d5483ef293ae284b9cc8d53
5 changes: 5 additions & 0 deletions trunk/fs/nfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
#include "pnfs.h"

#define NFSDBG_FACILITY NFSDBG_FILE

Expand Down Expand Up @@ -386,6 +387,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
file->f_path.dentry->d_name.name,
mapping->host->i_ino, len, (long long) pos);

pnfs_update_layout(mapping->host,
nfs_file_open_context(file),
IOMODE_RW);

start:
/*
* Prevent starvation issues if someone is doing a consistency
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "internal.h"
#include "fscache.h"
#include "dns_resolve.h"
#include "pnfs.h"

#define NFSDBG_FACILITY NFSDBG_VFS

Expand Down Expand Up @@ -1410,6 +1411,7 @@ void nfs4_evict_inode(struct inode *inode)
{
truncate_inode_pages(&inode->i_data, 0);
end_writeback(inode);
pnfs_destroy_layout(NFS_I(inode));
/* If we are holding a delegation, return it! */
nfs_inode_return_delegation_noreclaim(inode);
/* First call standard NFS clear_inode() code */
Expand Down Expand Up @@ -1447,6 +1449,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
nfsi->delegation = NULL;
nfsi->delegation_state = 0;
init_rwsem(&nfsi->rwsem);
nfsi->layout = NULL;
#endif
}

Expand Down
140 changes: 140 additions & 0 deletions trunk/fs/nfs/pnfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,143 @@ pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
spin_unlock(&pnfs_spinlock);
}
EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);

static void
get_layout_hdr_locked(struct pnfs_layout_hdr *lo)
{
assert_spin_locked(&lo->inode->i_lock);
lo->refcount++;
}

static void
put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
{
assert_spin_locked(&lo->inode->i_lock);
BUG_ON(lo->refcount == 0);

lo->refcount--;
if (!lo->refcount) {
dprintk("%s: freeing layout cache %p\n", __func__, lo);
NFS_I(lo->inode)->layout = NULL;
kfree(lo);
}
}

void
pnfs_destroy_layout(struct nfs_inode *nfsi)
{
struct pnfs_layout_hdr *lo;

spin_lock(&nfsi->vfs_inode.i_lock);
lo = nfsi->layout;
if (lo) {
/* Matched by refcount set to 1 in alloc_init_layout_hdr */
put_layout_hdr_locked(lo);
}
spin_unlock(&nfsi->vfs_inode.i_lock);
}

/* STUB - pretend LAYOUTGET to server failed */
static struct pnfs_layout_segment *
send_layoutget(struct pnfs_layout_hdr *lo,
struct nfs_open_context *ctx,
u32 iomode)
{
struct inode *ino = lo->inode;

set_bit(lo_fail_bit(iomode), &lo->state);
spin_lock(&ino->i_lock);
put_layout_hdr_locked(lo);
spin_unlock(&ino->i_lock);
return NULL;
}

static struct pnfs_layout_hdr *
alloc_init_layout_hdr(struct inode *ino)
{
struct pnfs_layout_hdr *lo;

lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
if (!lo)
return NULL;
lo->refcount = 1;
lo->inode = ino;
return lo;
}

static struct pnfs_layout_hdr *
pnfs_find_alloc_layout(struct inode *ino)
{
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);

assert_spin_locked(&ino->i_lock);
if (nfsi->layout)
return nfsi->layout;

spin_unlock(&ino->i_lock);
new = alloc_init_layout_hdr(ino);
spin_lock(&ino->i_lock);

if (likely(nfsi->layout == NULL)) /* Won the race? */
nfsi->layout = new;
else
kfree(new);
return nfsi->layout;
}

/* STUB - LAYOUTGET never succeeds, so cache is empty */
static struct pnfs_layout_segment *
pnfs_has_layout(struct pnfs_layout_hdr *lo, u32 iomode)
{
return NULL;
}

/*
* 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,
enum pnfs_iomode iomode)
{
struct nfs_inode *nfsi = NFS_I(ino);
struct pnfs_layout_hdr *lo;
struct pnfs_layout_segment *lseg = NULL;

if (!pnfs_enabled_sb(NFS_SERVER(ino)))
return NULL;
spin_lock(&ino->i_lock);
lo = pnfs_find_alloc_layout(ino);
if (lo == NULL) {
dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
goto out_unlock;
}

/* Check to see if the layout for the given range already exists */
lseg = pnfs_has_layout(lo, iomode);
if (lseg) {
dprintk("%s: Using cached lseg %p for iomode %d)\n",
__func__, lseg, iomode);
goto out_unlock;
}

/* if LAYOUTGET already failed once we don't try again */
if (test_bit(lo_fail_bit(iomode), &nfsi->layout->state))
goto out_unlock;

get_layout_hdr_locked(lo);
spin_unlock(&ino->i_lock);

lseg = send_layoutget(lo, ctx, iomode);
out:
dprintk("%s end, state 0x%lx lseg %p\n", __func__,
nfsi->layout->state, lseg);
return lseg;
out_unlock:
spin_unlock(&ino->i_lock);
goto out;
}
39 changes: 39 additions & 0 deletions trunk/fs/nfs/pnfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@

#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"

enum {
NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
};

/* Per-layout driver specific registration structure */
struct pnfs_layoutdriver_type {
struct list_head pnfs_tblid;
Expand All @@ -44,14 +49,48 @@ struct pnfs_layoutdriver_type {
int (*uninitialize_mountpoint) (struct nfs_server *);
};

struct pnfs_layout_hdr {
unsigned long refcount;
unsigned long state;
struct inode *inode;
};

extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);

struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
enum pnfs_iomode access_type);
void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
void unset_pnfs_layoutdriver(struct nfs_server *);
void pnfs_destroy_layout(struct nfs_inode *);


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

/* Return true if a layout driver is being used for this mountpoint */
static inline int pnfs_enabled_sb(struct nfs_server *nfss)
{
return nfss->pnfs_curr_ld != NULL;
}

#else /* CONFIG_NFS_V4_1 */

static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
{
}

static inline struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
enum pnfs_iomode access_type)
{
return NULL;
}

static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
{
}
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/nfs/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
#include "pnfs.h"

#define NFSDBG_FACILITY NFSDBG_PAGECACHE

Expand Down Expand Up @@ -120,6 +121,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
pnfs_update_layout(inode, ctx, IOMODE_READ);
new = nfs_create_request(ctx, inode, page, 0, len);
if (IS_ERR(new)) {
unlock_page(page);
Expand Down Expand Up @@ -624,6 +626,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
if (ret == 0)
goto read_complete; /* all pages were read */

pnfs_update_layout(inode, desc.ctx, IOMODE_READ);
if (rsize < PAGE_CACHE_SIZE)
nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
else
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ struct nfs_inode {
struct nfs_delegation *delegation;
fmode_t delegation_state;
struct rw_semaphore rwsem;

/* pNFS layout information */
struct pnfs_layout_hdr *layout;
#endif /* CONFIG_NFS_V4*/
#ifdef CONFIG_NFS_FSCACHE
struct fscache_cookie *fscache;
Expand Down

0 comments on commit 43df462

Please sign in to comment.