Skip to content

Commit

Permalink
Mark additional functions as PF_FSTRANS
Browse files Browse the repository at this point in the history
Prevent deadlocks by disabling direct reclaim during all NFS, xattr,
ctldir, and super function calls.  This is related to 40d06e3.

Signed-off-by: Brian Behlendorf <[email protected]>
Signed-off-by: Tim Chase <[email protected]>
Issue openzfs#3225
  • Loading branch information
behlendorf committed Apr 17, 2015
1 parent b467db4 commit 7fad629
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
20 changes: 16 additions & 4 deletions module/zfs/zpl_ctldir.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,17 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
#endif

{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
struct inode *ip = NULL;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
error = -zfsctl_snapdir_lookup(dip, dname(dentry), &ip,
0, cr, NULL, NULL);
ASSERT3S(error, <=, 0);
spl_fstrans_unmark(cookie);
crfree(cr);

if (error && error != -ENOENT)
Expand All @@ -250,21 +253,23 @@ static int
zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
{
zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
fstrans_cookie_t cookie;
char snapname[MAXNAMELEN];
boolean_t case_conflict;
uint64_t id, cookie;
uint64_t id, pos;
int error = 0;

ZFS_ENTER(zsb);
cookie = spl_fstrans_mark();

if (!dir_emit_dots(filp, ctx))
goto out;

cookie = ctx->pos;
pos = ctx->pos;
while (error == 0) {
dsl_pool_config_enter(dmu_objset_pool(zsb->z_os), FTAG);
error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN,
snapname, &id, &cookie, &case_conflict);
snapname, &id, &pos, &case_conflict);
dsl_pool_config_exit(dmu_objset_pool(zsb->z_os), FTAG);
if (error)
goto out;
Expand All @@ -273,9 +278,10 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
ZFSCTL_INO_SHARES - id, DT_DIR))
goto out;

ctx->pos = cookie;
ctx->pos = pos;
}
out:
spl_fstrans_unmark(cookie);
ZFS_EXIT(zsb);

if (error == -ENOENT)
Expand Down Expand Up @@ -414,14 +420,17 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
unsigned int flags)
#endif
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
struct inode *ip = NULL;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
error = -zfsctl_shares_lookup(dip, dname(dentry), &ip,
0, cr, NULL, NULL);
ASSERT3S(error, <=, 0);
spl_fstrans_unmark(cookie);
crfree(cr);

if (error) {
Expand All @@ -437,12 +446,14 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
static int
zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
znode_t *dzp;
int error = 0;

ZFS_ENTER(zsb);
cookie = spl_fstrans_mark();

if (zsb->z_shares_dir == 0) {
dir_emit_dots(filp, ctx);
Expand All @@ -459,6 +470,7 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)

iput(ZTOI(dzp));
out:
spl_fstrans_unmark(cookie);
ZFS_EXIT(zsb);
ASSERT3S(error, <=, 0);

Expand Down
12 changes: 12 additions & 0 deletions module/zfs/zpl_export.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
{
struct inode *ip = dentry->d_inode;
#endif /* HAVE_ENCODE_FH_WITH_INODE */
fstrans_cookie_t cookie;
fid_t *fid = (fid_t *)fh;
int len_bytes, rc;

Expand All @@ -48,12 +49,14 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
return (255);

fid->fid_len = len_bytes - offsetof(fid_t, fid_data);
cookie = spl_fstrans_mark();

if (zfsctl_is_node(ip))
rc = zfsctl_fid(ip, fid);
else
rc = zfs_fid(ip, fid);

spl_fstrans_unmark(cookie);
len_bytes = offsetof(fid_t, fid_data) + fid->fid_len;
*max_len = roundup(len_bytes, sizeof (__u32)) / sizeof (__u32);

Expand Down Expand Up @@ -84,6 +87,7 @@ zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
int fh_len, int fh_type)
{
fid_t *fid = (fid_t *)fh;
fstrans_cookie_t cookie;
struct inode *ip;
int len_bytes, rc;

Expand All @@ -94,7 +98,9 @@ zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
len_bytes < offsetof(fid_t, fid_data) + fid->fid_len)
return (ERR_PTR(-EINVAL));

cookie = spl_fstrans_mark();
rc = zfs_vget(sb, &ip, fid);
spl_fstrans_unmark(cookie);

if (rc != 0)
return (ERR_PTR(-rc));
Expand All @@ -108,11 +114,14 @@ static struct dentry *
zpl_get_parent(struct dentry *child)
{
cred_t *cr = CRED();
fstrans_cookie_t cookie;
struct inode *ip;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

Expand All @@ -127,10 +136,13 @@ static int
zpl_commit_metadata(struct inode *inode)
{
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_fsync(inode, 0, cr);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

Expand Down
16 changes: 16 additions & 0 deletions module/zfs/zpl_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,26 @@ zpl_inode_delete(struct inode *ip)
static void
zpl_put_super(struct super_block *sb)
{
fstrans_cookie_t cookie;
int error;

cookie = spl_fstrans_mark();
error = -zfs_umount(sb);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);
}

static int
zpl_sync_fs(struct super_block *sb, int wait)
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
int error;

crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_sync(sb, wait, cr);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

Expand All @@ -159,9 +165,12 @@ zpl_sync_fs(struct super_block *sb, int wait)
static int
zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
{
fstrans_cookie_t cookie;
int error;

cookie = spl_fstrans_mark();
error = -zfs_statvfs(dentry, statp);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);

return (error);
Expand All @@ -170,8 +179,12 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
static int
zpl_remount_fs(struct super_block *sb, int *flags, char *data)
{
fstrans_cookie_t cookie;
int error;

cookie = spl_fstrans_mark();
error = -zfs_remount(sb, flags, data);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);

return (error);
Expand Down Expand Up @@ -242,9 +255,12 @@ zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
static int
zpl_fill_super(struct super_block *sb, void *data, int silent)
{
fstrans_cookie_t cookie;
int error;

cookie = spl_fstrans_mark();
error = -zfs_domount(sb, data, silent);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);

return (error);
Expand Down
9 changes: 9 additions & 0 deletions module/zfs/zpl_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,11 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
zfs_sb_t *zsb = ZTOZSB(zp);
xattr_filldir_t xf = { buffer_size, 0, buffer, dentry->d_inode };
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error = 0;

crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&zp->z_xattr_lock, RW_READER);

if (zsb->z_use_sa && zp->z_is_sa) {
Expand All @@ -228,6 +230,7 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
out:

rw_exit(&zp->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);

return (error);
Expand Down Expand Up @@ -337,12 +340,15 @@ zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size)
{
znode_t *zp = ITOZ(ip);
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&zp->z_xattr_lock, RW_READER);
error = __zpl_xattr_get(ip, name, value, size, cr);
rw_exit(&zp->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);

return (error);
Expand Down Expand Up @@ -482,9 +488,11 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
znode_t *zp = ITOZ(ip);
zfs_sb_t *zsb = ZTOZSB(zp);
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;

crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&ITOZ(ip)->z_xattr_lock, RW_WRITER);

/*
Expand Down Expand Up @@ -522,6 +530,7 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
error = zpl_xattr_set_dir(ip, name, value, size, flags, cr);
out:
rw_exit(&ITOZ(ip)->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

Expand Down

0 comments on commit 7fad629

Please sign in to comment.