2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/backing-dev.h>
19 #include <linux/fsnotify.h>
20 #include <linux/slab.h>
21 #include <linux/mempool.h>
25 static int pohmelfs_send_lock_trans(struct pohmelfs_inode
*pi
,
26 u64 id
, u64 start
, u32 size
, int type
)
28 struct inode
*inode
= &pi
->vfs_inode
;
29 struct pohmelfs_sb
*psb
= POHMELFS_SB(inode
->i_sb
);
30 struct netfs_trans
*t
;
31 struct netfs_cmd
*cmd
;
35 int isize
= (type
& POHMELFS_LOCK_GRAB
) ? 0 : sizeof(struct netfs_inode_info
);
37 err
= pohmelfs_path_length(pi
);
44 t
= netfs_trans_alloc(psb
, path_len
+ sizeof(struct netfs_lock
) + isize
,
45 NETFS_TRANS_SINGLE_DST
, 0);
49 cmd
= netfs_trans_current(t
);
52 err
= pohmelfs_construct_path_string(pi
, data
, path_len
);
64 cmd
->cmd
= NETFS_LOCK
;
67 cmd
->size
= sizeof(struct netfs_lock
) + path_len
+ isize
;
71 netfs_convert_cmd(cmd
);
72 netfs_convert_lock(l
);
75 struct netfs_inode_info
*info
= (struct netfs_inode_info
*)(l
+ 1);
77 info
->mode
= inode
->i_mode
;
78 info
->nlink
= inode
->i_nlink
;
79 info
->uid
= inode
->i_uid
;
80 info
->gid
= inode
->i_gid
;
81 info
->blocks
= inode
->i_blocks
;
82 info
->rdev
= inode
->i_rdev
;
83 info
->size
= inode
->i_size
;
84 info
->version
= inode
->i_version
;
86 netfs_convert_inode_info(info
);
89 netfs_trans_update(cmd
, t
, path_len
+ sizeof(struct netfs_lock
) + isize
);
91 return netfs_trans_finish(t
, psb
);
96 printk("%s: err: %d.\n", __func__
, err
);
100 int pohmelfs_data_lock(struct pohmelfs_inode
*pi
, u64 start
, u32 size
, int type
)
102 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
103 struct pohmelfs_mcache
*m
;
106 struct inode
*inode
= &pi
->vfs_inode
;
108 dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
109 "type: %d, locked as: %d, owned: %d.\n",
110 __func__
, &pi
->vfs_inode
, pi
->ino
,
111 start
, size
, type
, pi
->lock_type
,
112 !!test_bit(NETFS_INODE_OWNED
, &pi
->state
));
114 if (!pohmelfs_need_lock(pi
, type
))
117 m
= pohmelfs_mcache_alloc(psb
, start
, size
, NULL
);
121 err
= pohmelfs_send_lock_trans(pi
, m
->gen
, start
, size
,
122 type
| POHMELFS_LOCK_GRAB
);
126 err
= wait_for_completion_timeout(&m
->complete
, psb
->mcache_timeout
);
133 printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
134 __func__
, &pi
->vfs_inode
, pi
->ino
, m
->gen
, start
, size
, err
);
137 if (err
&& (err
!= -ENOENT
))
141 netfs_convert_inode_info(&m
->info
);
143 iattr
.ia_valid
= ATTR_MODE
| ATTR_UID
| ATTR_GID
| ATTR_SIZE
| ATTR_ATIME
;
144 iattr
.ia_mode
= m
->info
.mode
;
145 iattr
.ia_uid
= m
->info
.uid
;
146 iattr
.ia_gid
= m
->info
.gid
;
147 iattr
.ia_size
= m
->info
.size
;
148 iattr
.ia_atime
= CURRENT_TIME
;
150 dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
151 __func__
, &pi
->vfs_inode
, pi
->ino
, m
->gen
, start
, inode
->i_size
, m
->info
.size
);
153 err
= pohmelfs_setattr_raw(inode
, &iattr
);
155 struct dentry
*dentry
= d_find_alias(inode
);
157 fsnotify_change(dentry
, iattr
.ia_valid
);
163 pi
->lock_type
= type
;
164 set_bit(NETFS_INODE_OWNED
, &pi
->state
);
166 pohmelfs_mcache_put(psb
, m
);
171 pohmelfs_mcache_put(psb
, m
);
175 int pohmelfs_data_unlock(struct pohmelfs_inode
*pi
, u64 start
, u32 size
, int type
)
177 dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
178 __func__
, &pi
->vfs_inode
, pi
->ino
, start
, size
, type
);
180 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &pi
->state
);
181 clear_bit(NETFS_INODE_OWNED
, &pi
->state
);
182 return pohmelfs_send_lock_trans(pi
, pi
->ino
, start
, size
, type
);