2 * Copyright (C) 2011+ Evgeniy Polyakov <zbr@ioremap.net>
9 static int pohmelfs_setattr(struct dentry
*dentry
, struct iattr
*iattr
)
11 struct inode
*inode
= dentry
->d_inode
;
14 err
= inode_change_ok(inode
, iattr
);
18 if (iattr
->ia_valid
& ATTR_SIZE
&& iattr
->ia_size
!= inode
->i_size
) {
19 truncate_setsize(inode
, iattr
->ia_size
);
21 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
22 if (inode_needs_sync(inode
)) {
23 sync_inode_metadata(inode
, 1);
26 setattr_copy(inode
, iattr
);
27 mark_inode_dirty(inode
);
29 pr_info("pohmelfs_setattr: ino: %lu, size: %llu, mtime: %lu.%lu\n",
30 inode
->i_ino
, inode
->i_size
, inode
->i_mtime
.tv_sec
, inode
->i_mtime
.tv_nsec
);
35 static int pohmelfs_send_prepare_commit(struct pohmelfs_inode
*pi
, size_t len
, loff_t pos
, int prepare
)
37 struct pohmelfs_io
*io
;
40 io
= kmem_cache_zalloc(pohmelfs_io_cache
, GFP_NOIO
);
48 io
->cmd
= DNET_CMD_WRITE
;
51 io
->cflags
= DNET_FLAGS_NEED_ACK
;
52 io
->aflags
= DNET_ATTR_NOCSUM
;
54 io
->ioflags
= DNET_IO_FLAGS_PREPARE
;
56 io
->ioflags
= DNET_IO_FLAGS_COMMIT
;
57 io
->ioflags
|= DNET_IO_FLAGS_PLAIN_WRITE
;
59 err
= pohmelfs_send_io(io
);
61 kmem_cache_free(pohmelfs_io_cache
, io
);
66 static int pohmelfs_write_init(struct pohmelfs_trans
*t
)
68 struct pohmelfs_wait
*wait
= t
->priv
;
70 pohmelfs_wait_get(wait
);
74 static void pohmelfs_write_destroy(struct pohmelfs_trans
*t
)
76 struct pohmelfs_wait
*wait
= t
->priv
;
79 pohmelfs_wait_put(wait
);
82 static int pohmelfs_write_complete(struct pohmelfs_trans
*t
, struct pohmelfs_state
*recv
)
84 struct pohmelfs_wait
*wait
= t
->priv
;
85 struct pohmelfs_inode
*pi
= pohmelfs_inode(t
->inode
);
86 struct dnet_cmd
*cmd
= &recv
->cmd
;
87 unsigned long long trans
= cmd
->trans
& ~DNET_TRANS_REPLY
;
89 pr_info("pohmelfs: %s: write complete: %llu, flags: %x, status: %d\n",
90 pohmelfs_dump_id(pi
->id
.id
), trans
, cmd
->flags
, cmd
->status
);
92 if (cmd
->flags
& DNET_FLAGS_MORE
)
95 wait
->condition
= cmd
->status
;
102 static int pohmelfs_send_write_metadata(struct pohmelfs_inode
*pi
, struct pohmelfs_io
*pio
, struct pohmelfs_wait
*wait
)
104 struct pohmelfs_sb
*psb
= pohmelfs_sb(pi
->vfs_inode
.i_sb
);
105 struct timespec ts
= CURRENT_TIME
;
106 struct dnet_meta_update
*mu
;
111 size
= sizeof(struct dnet_meta
) * 5 +
112 sizeof(struct dnet_meta_check_status
) +
113 sizeof(struct dnet_meta_update
) +
114 sizeof(struct dnet_meta_checksum
) +
116 psb
->group_num
* sizeof(int);
118 data
= kzalloc(size
, GFP_NOIO
);
125 m
->type
= DNET_META_GROUPS
;
126 m
->size
= psb
->group_num
* sizeof(int);
127 memcpy(m
->data
, psb
->groups
, m
->size
);
128 dnet_convert_meta(m
);
130 m
= (struct dnet_meta
*)(m
->data
+ le32_to_cpu(m
->size
));
131 m
->type
= DNET_META_NAMESPACE
;
132 m
->size
= psb
->fsid_len
;
133 memcpy(m
->data
, psb
->fsid
, psb
->fsid_len
);
134 dnet_convert_meta(m
);
136 m
= (struct dnet_meta
*)(m
->data
+ le32_to_cpu(m
->size
));
137 m
->type
= DNET_META_CHECKSUM
;
138 m
->size
= sizeof(struct dnet_meta_checksum
);
139 /* do not fill, it will be updated on server */
140 dnet_convert_meta(m
);
142 m
= (struct dnet_meta
*)(m
->data
+ le32_to_cpu(m
->size
));
143 m
->type
= DNET_META_UPDATE
;
144 m
->size
= sizeof(struct dnet_meta_update
);
145 mu
= (struct dnet_meta_update
*)m
->data
;
146 mu
->tm
.tsec
= ts
.tv_sec
;
147 mu
->tm
.tnsec
= ts
.tv_nsec
;
148 dnet_convert_meta_update(mu
);
149 dnet_convert_meta(m
);
151 m
= (struct dnet_meta
*)(m
->data
+ le32_to_cpu(m
->size
));
152 m
->type
= DNET_META_CHECK_STATUS
;
153 m
->size
= sizeof(struct dnet_meta_check_status
);
154 /* do not fill, it will be updated on server */
155 dnet_convert_meta(m
);
157 memset(pio
, 0, sizeof(struct pohmelfs_io
));
161 pio
->cmd
= DNET_CMD_WRITE
;
162 pio
->ioflags
= DNET_IO_FLAGS_OVERWRITE
| DNET_IO_FLAGS_META
;
163 pio
->cflags
= DNET_FLAGS_NEED_ACK
;
165 pio
->cb
.init
= pohmelfs_write_init
;
166 pio
->cb
.destroy
= pohmelfs_write_destroy
;
167 pio
->cb
.complete
= pohmelfs_write_complete
;
172 err
= pohmelfs_send_io(pio
);
182 static ssize_t
pohmelfs_write(struct file
*filp
, const char __user
*buf
, size_t len
, loff_t
*ppos
)
185 struct inode
*inode
= filp
->f_mapping
->host
;
186 struct pohmelfs_sb
*psb
= pohmelfs_sb(inode
->i_sb
);
187 struct pohmelfs_inode
*pi
= pohmelfs_inode(inode
);
188 struct pohmelfs_io
*pio
;
189 loff_t offset
= *ppos
;
190 struct pohmelfs_wait
*wait
;
194 err
= pohmelfs_send_prepare_commit(pi
, len
, offset
, 1);
198 err
= do_sync_write(filp
, buf
, len
, ppos
);
199 pohmelfs_send_prepare_commit(pi
, 0, 0, 0);
202 err
= do_sync_write(filp
, buf
, len
, ppos
);
203 pr_info("pohmelfs_write: %s: ino: %lu size: %llu, notime: %d, mtime: %lu.%lu\n",
204 pohmelfs_dump_id(pi
->id
.id
),
205 inode
->i_ino
, inode
->i_size
, IS_NOCMTIME(inode
),
206 inode
->i_mtime
.tv_sec
, inode
->i_mtime
.tv_nsec
);
211 wait
= pohmelfs_wait_alloc(pi
);
217 pio
= kmem_cache_zalloc(pohmelfs_io_cache
, GFP_NOIO
);
225 pio
->cmd
= DNET_CMD_WRITE
;
226 pio
->offset
= offset
;
228 pio
->cflags
= DNET_FLAGS_NEED_ACK
;
229 pio
->aflags
= DNET_ATTR_NOCSUM
;
230 pio
->ioflags
= DNET_IO_FLAGS_OVERWRITE
;
231 //pio->ioflags |= DNET_IO_FLAGS_PLAIN_WRITE;
232 pio
->cb
.init
= pohmelfs_write_init
;
233 pio
->cb
.destroy
= pohmelfs_write_destroy
;
234 pio
->cb
.complete
= pohmelfs_write_complete
;
235 pio
->mapping
= filp
->f_mapping
;
238 err
= pohmelfs_send_io(pio
);
242 err
= pohmelfs_send_write_metadata(pi
, pio
, wait
);
246 inode
->i_sb
->s_op
->write_inode(inode
, NULL
);
248 ret
= wait_event_interruptible_timeout(wait
->wq
,
249 wait
->condition
!= 0 && atomic_read(&wait
->refcnt
.refcount
) == 1,
250 msecs_to_jiffies(psb
->write_wait_timeout
));
258 if (wait
->condition
< 0) {
259 err
= wait
->condition
;
266 kmem_cache_free(pohmelfs_io_cache
, pio
);
268 pohmelfs_wait_put(wait
);
274 const struct file_operations pohmelfs_file_ops
= {
275 .open
= generic_file_open
,
277 .llseek
= generic_file_llseek
,
279 .read
= do_sync_read
,
280 .aio_read
= generic_file_aio_read
,
282 .mmap
= generic_file_mmap
,
284 .splice_read
= generic_file_splice_read
,
285 .splice_write
= generic_file_splice_write
,
287 .write
= pohmelfs_write
,
288 .aio_write
= generic_file_aio_write
,
291 const struct inode_operations pohmelfs_file_inode_operations
= {
292 .setattr
= pohmelfs_setattr
,