Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
* 'for-linus' of git://linux-nfs.org/~bfields/linux:
  nfsd: don't allow setting ctime over v4
  Update to NFS/RDMA documentation
  locks: don't call ->copy_lock methods on return of conflicting locks
  lockd: unlock lockd locks held for a certain filesystem
  lockd: unlock lockd locks associated with a given server ip
  leases: remove unneeded variable from fcntl_setlease().
  leases: move lock allocation earlier in generic_setlease()
  leases: when unlocking, skip locking-related steps
  leases: fix a return-value mixup
  • Loading branch information
Linus Torvalds committed Apr 25, 2008
2 parents 9f4def9 + e36cd4a commit cf2ec15
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 48 deletions.
14 changes: 9 additions & 5 deletions Documentation/filesystems/nfs-rdma.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
################################################################################

Author: NetApp and Open Grid Computing
Date: February 25, 2008
Date: April 15, 2008

Table of Contents
~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -197,12 +197,16 @@ NFS/RDMA Setup
- On the server system, configure the /etc/exports file and
start the NFS/RDMA server.

Exports entries with the following format have been tested:
Exports entries with the following formats have been tested:

/vol0 10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash)
/vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
/vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)

Here the first IP address is the client's Ethernet address and the second
IP address is the clients IPoIB address.
The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
cleint's iWARP address(es) for an RNIC.

NOTE: The "insecure" option must be used because the NFS/RDMA client does not
use a reserved port.

Each time a machine boots:

Expand Down
2 changes: 1 addition & 1 deletion fs/lockd/svclock.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
block->b_flags |= B_TIMED_OUT;
if (conf) {
if (block->b_fl)
locks_copy_lock(block->b_fl, conf);
__locks_copy_lock(block->b_fl, conf);
}
}

Expand Down
69 changes: 61 additions & 8 deletions fs/lockd/svcsubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <linux/lockd/lockd.h>
#include <linux/lockd/share.h>
#include <linux/lockd/sm_inter.h>
#include <linux/module.h>
#include <linux/mount.h>

#define NLMDBG_FACILITY NLMDBG_SVCSUBS

Expand Down Expand Up @@ -194,6 +196,12 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
return 0;
}

static int
nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2)
{
return 1;
}

/*
* Inspect a single file
*/
Expand Down Expand Up @@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file)
* Loop over all files in the file table.
*/
static int
nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
nlm_traverse_files(void *data, nlm_host_match_fn_t match,
int (*is_failover_file)(void *data, struct nlm_file *file))
{
struct hlist_node *pos, *next;
struct nlm_file *file;
Expand All @@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
mutex_lock(&nlm_file_mutex);
for (i = 0; i < FILE_NRHASH; i++) {
hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
if (is_failover_file && !is_failover_file(data, file))
continue;
file->f_count++;
mutex_unlock(&nlm_file_mutex);

/* Traverse locks, blocks and shares of this file
* and update file->f_locks count */
if (nlm_inspect_file(host, file, match))
if (nlm_inspect_file(data, file, match))
ret = 1;

mutex_lock(&nlm_file_mutex);
Expand Down Expand Up @@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file)
* Used by nlmsvc_invalidate_all
*/
static int
nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy)
nlmsvc_mark_host(void *data, struct nlm_host *dummy)
{
struct nlm_host *host = data;

host->h_inuse = 1;
return 0;
}

static int
nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other)
nlmsvc_same_host(void *data, struct nlm_host *other)
{
struct nlm_host *host = data;

return host == other;
}

static int
nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
nlmsvc_is_client(void *data, struct nlm_host *dummy)
{
struct nlm_host *host = data;

if (host->h_server) {
/* we are destroying locks even though the client
* hasn't asked us too, so don't unmonitor the
Expand All @@ -337,7 +354,7 @@ void
nlmsvc_mark_resources(void)
{
dprintk("lockd: nlmsvc_mark_resources\n");
nlm_traverse_files(NULL, nlmsvc_mark_host);
nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
}

/*
Expand All @@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host)
{
dprintk("lockd: nlmsvc_free_host_resources\n");

if (nlm_traverse_files(host, nlmsvc_same_host)) {
if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) {
printk(KERN_WARNING
"lockd: couldn't remove all locks held by %s\n",
host->h_name);
Expand All @@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void)
* turn, which is about as inefficient as it gets.
* Now we just do it once in nlm_traverse_files.
*/
nlm_traverse_files(NULL, nlmsvc_is_client);
nlm_traverse_files(NULL, nlmsvc_is_client, NULL);
}

static int
nlmsvc_match_sb(void *datap, struct nlm_file *file)
{
struct super_block *sb = datap;

return sb == file->f_file->f_path.mnt->mnt_sb;
}

int
nlmsvc_unlock_all_by_sb(struct super_block *sb)
{
int ret;

ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb);
return ret ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);

static int
nlmsvc_match_ip(void *datap, struct nlm_host *host)
{
__be32 *server_addr = datap;

return host->h_saddr.sin_addr.s_addr == *server_addr;
}

int
nlmsvc_unlock_all_by_ip(__be32 server_addr)
{
int ret;
ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
return ret ? -EIO : 0;

}
EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
32 changes: 17 additions & 15 deletions fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
/*
* Initialize a new lock from an existing file_lock structure.
*/
static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
{
new->fl_owner = fl->fl_owner;
new->fl_pid = fl->fl_pid;
Expand Down Expand Up @@ -833,7 +833,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
if (!posix_locks_conflict(request, fl))
continue;
if (conflock)
locks_copy_lock(conflock, fl);
__locks_copy_lock(conflock, fl);
error = -EAGAIN;
if (!(request->fl_flags & FL_SLEEP))
goto out;
Expand Down Expand Up @@ -1367,18 +1367,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)

lease = *flp;

error = -EAGAIN;
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
goto out;
if ((arg == F_WRLCK)
&& ((atomic_read(&dentry->d_count) > 1)
|| (atomic_read(&inode->i_count) > 1)))
goto out;
if (arg != F_UNLCK) {
error = -ENOMEM;
new_fl = locks_alloc_lock();
if (new_fl == NULL)
goto out;

error = -ENOMEM;
new_fl = locks_alloc_lock();
if (new_fl == NULL)
goto out;
error = -EAGAIN;
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
goto out;
if ((arg == F_WRLCK)
&& ((atomic_read(&dentry->d_count) > 1)
|| (atomic_read(&inode->i_count) > 1)))
goto out;
}

/*
* At this point, we know that if there is an exclusive
Expand All @@ -1404,6 +1406,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
rdlease_count++;
}

error = -EAGAIN;
if ((arg == F_RDLCK && (wrlease_count > 0)) ||
(arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
goto out;
Expand Down Expand Up @@ -1490,8 +1493,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
{
struct file_lock fl, *flp = &fl;
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct inode *inode = filp->f_path.dentry->d_inode;
int error;

locks_init_lock(&fl);
Expand Down
3 changes: 0 additions & 3 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2712,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* Note: locks.c uses the BKL to protect the inode's lock list.
*/

/* XXX?: Just to divert the locks_release_private at the start of
* locks_copy_lock: */
locks_init_lock(&conflock);
err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
switch (-err) {
case 0: /* success! */
Expand Down
14 changes: 0 additions & 14 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
goto xdr_error;
}
}
if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
/* We require the high 32 bits of 'seconds' to be 0, and we ignore
all 32 bits of 'nseconds'. */
READ_BUF(12);
len += 12;
READ32(dummy32);
if (dummy32)
return nfserr_inval;
READ32(iattr->ia_ctime.tv_sec);
READ32(iattr->ia_ctime.tv_nsec);
if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
return nfserr_inval;
iattr->ia_valid |= ATTR_CTIME;
}
if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
READ_BUF(4);
len += 4;
Expand Down
65 changes: 65 additions & 0 deletions fs/nfsd/nfsctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/inet.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/ctype.h>
Expand All @@ -35,6 +36,7 @@
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
#include <linux/lockd/lockd.h>

#include <asm/uaccess.h>
#include <net/ipv6.h>
Expand All @@ -53,6 +55,8 @@ enum {
NFSD_Getfs,
NFSD_List,
NFSD_Fh,
NFSD_FO_UnlockIP,
NFSD_FO_UnlockFS,
NFSD_Threads,
NFSD_Pool_Threads,
NFSD_Versions,
Expand Down Expand Up @@ -89,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
#endif

static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);

static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Svc] = write_svc,
[NFSD_Add] = write_add,
Expand All @@ -98,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Getfd] = write_getfd,
[NFSD_Getfs] = write_getfs,
[NFSD_Fh] = write_filehandle,
[NFSD_FO_UnlockIP] = failover_unlock_ip,
[NFSD_FO_UnlockFS] = failover_unlock_fs,
[NFSD_Threads] = write_threads,
[NFSD_Pool_Threads] = write_pool_threads,
[NFSD_Versions] = write_versions,
Expand Down Expand Up @@ -298,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
return err;
}

static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
{
__be32 server_ip;
char *fo_path, c;
int b1, b2, b3, b4;

/* sanity check */
if (size == 0)
return -EINVAL;

if (buf[size-1] != '\n')
return -EINVAL;

fo_path = buf;
if (qword_get(&buf, fo_path, size) < 0)
return -EINVAL;

/* get ipv4 address */
if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
return -EINVAL;
server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);

return nlmsvc_unlock_all_by_ip(server_ip);
}

static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
{
struct nameidata nd;
char *fo_path;
int error;

/* sanity check */
if (size == 0)
return -EINVAL;

if (buf[size-1] != '\n')
return -EINVAL;

fo_path = buf;
if (qword_get(&buf, fo_path, size) < 0)
return -EINVAL;

error = path_lookup(fo_path, 0, &nd);
if (error)
return error;

error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);

path_put(&nd.path);
return error;
}

static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
{
/* request is:
Expand Down Expand Up @@ -700,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_FO_UnlockIP] = {"unlock_ip",
&transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_FO_UnlockFS] = {"unlock_filesystem",
&transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
Expand Down
1 change: 1 addition & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
extern void locks_copy_lock(struct file_lock *, struct file_lock *);
extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
extern void posix_test_lock(struct file *, struct file_lock *);
Expand Down
Loading

0 comments on commit cf2ec15

Please sign in to comment.