aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/serialP.h
Commit message (Expand)AuthorAge
* Don't include linux/config.h from anywhere else in include/David Woodhouse2006-04-26
* [SERIAL] Convert parport_serial to use new 8250_pci interfacesRussell King2005-07-27
* [PATCH] Serial: Remove linux/version.hOlaf Hering2005-07-16
* Linux-2.6.12-rc2v2.6.12-rc2Linus Torvalds2005-04-16
0400 sysv: add ->sync_fs' href='/cgit/cgit.cgi/litmus-rt.git/commit/fs/sysv/inode.c?h=v2015.1&id=ad43ffdeea0a7bd3e6036c4aeec2e6699aef8ac7'>ad43ffdeea0a
1da177e4c3f4



ebc1ac164560
1da177e4c3f4












ad43ffdeea0a
ebc1ac164560
ad43ffdeea0a









1da177e4c3f4




bbd6851a3213
1da177e4c3f4



bbd6851a3213
1da177e4c3f4






8c85e125124a


1da177e4c3f4













726c33422318
1da177e4c3f4
726c33422318
1da177e4c3f4
1c5b45411f93
1da177e4c3f4







1c5b45411f93

1da177e4c3f4












































c5ef1c42c51b
1da177e4c3f4



















21acaf8e8da0
1da177e4c3f4
21acaf8e8da0


1da177e4c3f4



b8e1343f6746
1da177e4c3f4
1da177e4c3f4



b8e1343f6746

1da177e4c3f4


b8e1343f6746

1da177e4c3f4
b8e1343f6746






1da177e4c3f4

















ba52de123d45
1da177e4c3f4











b8e1343f6746

1da177e4c3f4

b8e1343f6746

1da177e4c3f4

05459ca81ac3
1da177e4c3f4






05459ca81ac3
1da177e4c3f4




05459ca81ac3
1da177e4c3f4



05459ca81ac3
1da177e4c3f4

















05459ca81ac3







1da177e4c3f4
1da177e4c3f4


05459ca81ac3
1da177e4c3f4
05459ca81ac3
1da177e4c3f4



fef266580e5c
1da177e4c3f4

1da177e4c3f4
1da177e4c3f4

e18b890bb088
1da177e4c3f4




e94b1766097d
1da177e4c3f4









51cc50685a42
1da177e4c3f4


a35afb830f8d
1da177e4c3f4

ee9b6d61a2a4
1da177e4c3f4

1da177e4c3f4



ad43ffdeea0a
1da177e4c3f4







4b6a9316fab5
20c2df83d25c
1da177e4c3f4








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362






















                                                                              




                              
                        


                          
                                                         



                                                     
                       












                                                                                
 
                         









                                                    




                                                                       
                       



                                    
                         






                                                  


                                     













                                                          
                                                                  
 
                                              
                                               
                                                     







                                                                  

                                             












































                                                                     
                                                                      



















                                                                     
                        
                                                                          


                                                                               



                                                               
                                                                 
 



                                                

                            


                                                                          

                                      
         






                                        

















                                                                           
                            











                                                                                

                                

          

                             

 
                                                   






                                                
                    




                                                                          
                            



                                                        
                            

















                                                                                







                                                                          
                   


                 
                                        
 
                                          



                                                  
                                                

                             
                               

 
                                            




                                                             
                                                             









                                                          
                              


                                                                 
                                        

 
                                           

                                             



                                            
                                       







                                                                 
                                                             
                                   








                                              
/*
 *  linux/fs/sysv/inode.c
 *
 *  minix/inode.c
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  xenix/inode.c
 *  Copyright (C) 1992  Doug Evans
 *
 *  coh/inode.c
 *  Copyright (C) 1993  Pascal Haible, Bruno Haible
 *
 *  sysv/inode.c
 *  Copyright (C) 1993  Paul B. Monday
 *
 *  sysv/inode.c
 *  Copyright (C) 1993  Bruno Haible
 *  Copyright (C) 1997, 1998  Krzysztof G. Baranowski
 *
 *  This file contains code for allocating/freeing inodes and for read/writing
 *  the superblock.
 */

#include <linux/highuid.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
#include <linux/namei.h>
#include <asm/byteorder.h>
#include "sysv.h"

static int sysv_sync_fs(struct super_block *sb, int wait)
{
	struct sysv_sb_info *sbi = SYSV_SB(sb);
	unsigned long time = get_seconds(), old_time;

	lock_super(sb);

	/*
	 * If we are going to write out the super block,
	 * then attach current time stamp.
	 * But if the filesystem was marked clean, keep it clean.
	 */
	old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
	if (sbi->s_type == FSTYPE_SYSV4) {
		if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
			*sbi->s_sb_state = cpu_to_fs32(sbi, 0x7c269d38 - time);
		*sbi->s_sb_time = cpu_to_fs32(sbi, time);
		mark_buffer_dirty(sbi->s_bh2);
	}

	unlock_super(sb);

	return 0;
}

static void sysv_write_super(struct super_block *sb)
{
	if (!(sb->s_flags & MS_RDONLY))
		sysv_sync_fs(sb, 1);
	else
		sb->s_dirt = 0;
}

static int sysv_remount(struct super_block *sb, int *flags, char *data)
{
	struct sysv_sb_info *sbi = SYSV_SB(sb);
	lock_super(sb);
	if (sbi->s_forced_ro)
		*flags |= MS_RDONLY;
	if (!(*flags & MS_RDONLY))
		sb->s_dirt = 1;
	unlock_super(sb);
	return 0;
}

static void sysv_put_super(struct super_block *sb)
{
	struct sysv_sb_info *sbi = SYSV_SB(sb);

	if (sb->s_dirt)
		sysv_write_super(sb);

	if (!(sb->s_flags & MS_RDONLY)) {
		/* XXX ext2 also updates the state here */
		mark_buffer_dirty(sbi->s_bh1);
		if (sbi->s_bh1 != sbi->s_bh2)
			mark_buffer_dirty(sbi->s_bh2);
	}

	brelse(sbi->s_bh1);
	if (sbi->s_bh1 != sbi->s_bh2)
		brelse(sbi->s_bh2);

	kfree(sbi);
}

static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	struct super_block *sb = dentry->d_sb;
	struct sysv_sb_info *sbi = SYSV_SB(sb);
	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);

	buf->f_type = sb->s_magic;
	buf->f_bsize = sb->s_blocksize;
	buf->f_blocks = sbi->s_ndatazones;
	buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb);
	buf->f_files = sbi->s_ninodes;
	buf->f_ffree = sysv_count_free_inodes(sb);
	buf->f_namelen = SYSV_NAMELEN;
	buf->f_fsid.val[0] = (u32)id;
	buf->f_fsid.val[1] = (u32)(id >> 32);
	return 0;
}

/* 
 * NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32
 */
static inline void read3byte(struct sysv_sb_info *sbi,
	unsigned char * from, unsigned char * to)
{
	if (sbi->s_bytesex == BYTESEX_PDP) {
		to[0] = from[0];
		to[1] = 0;
		to[2] = from[1];
		to[3] = from[2];
	} else if (sbi->s_bytesex == BYTESEX_LE) {
		to[0] = from[0];
		to[1] = from[1];
		to[2] = from[2];
		to[3] = 0;
	} else {
		to[0] = 0;
		to[1] = from[0];
		to[2] = from[1];
		to[3] = from[2];
	}
}

static inline void write3byte(struct sysv_sb_info *sbi,
	unsigned char * from, unsigned char * to)
{
	if (sbi->s_bytesex == BYTESEX_PDP) {
		to[0] = from[0];
		to[1] = from[2];
		to[2] = from[3];
	} else if (sbi->s_bytesex == BYTESEX_LE) {
		to[0] = from[0];
		to[1] = from[1];
		to[2] = from[2];
	} else {
		to[0] = from[1];
		to[1] = from[2];
		to[2] = from[3];
	}
}

static const struct inode_operations sysv_symlink_inode_operations = {
	.readlink	= generic_readlink,
	.follow_link	= page_follow_link_light,
	.put_link	= page_put_link,
	.getattr	= sysv_getattr,
};

void sysv_set_inode(struct inode *inode, dev_t rdev)
{
	if (S_ISREG(inode->i_mode)) {
		inode->i_op = &sysv_file_inode_operations;
		inode->i_fop = &sysv_file_operations;
		inode->i_mapping->a_ops = &sysv_aops;
	} else if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &sysv_dir_inode_operations;
		inode->i_fop = &sysv_dir_operations;
		inode->i_mapping->a_ops = &sysv_aops;
	} else if (S_ISLNK(inode->i_mode)) {
		if (inode->i_blocks) {
			inode->i_op = &sysv_symlink_inode_operations;
			inode->i_mapping->a_ops = &sysv_aops;
		} else {
			inode->i_op = &sysv_fast_symlink_inode_operations;
			nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size,
				sizeof(SYSV_I(inode)->i_data) - 1);
		}
	} else
		init_special_inode(inode, inode->i_mode, rdev);
}

struct inode *sysv_iget(struct super_block *sb, unsigned int ino)
{
	struct sysv_sb_info * sbi = SYSV_SB(sb);
	struct buffer_head * bh;
	struct sysv_inode * raw_inode;
	struct sysv_inode_info * si;
	struct inode *inode;
	unsigned int block;

	if (!ino || ino > sbi->s_ninodes) {
		printk("Bad inode number on dev %s: %d is out of range\n",
		       sb->s_id, ino);
		return ERR_PTR(-EIO);
	}

	inode = iget_locked(sb, ino);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

	raw_inode = sysv_raw_inode(sb, ino, &bh);
	if (!raw_inode) {
		printk("Major problem: unable to read inode from dev %s\n",
		       inode->i_sb->s_id);
		goto bad_inode;
	}
	/* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
	inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode);
	inode->i_uid = (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid);
	inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid);
	inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink);
	inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
	inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime);
	inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime);
	inode->i_ctime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_ctime);
	inode->i_ctime.tv_nsec = 0;
	inode->i_atime.tv_nsec = 0;
	inode->i_mtime.tv_nsec = 0;
	inode->i_blocks = 0;

	si = SYSV_I(inode);
	for (block = 0; block < 10+1+1+1; block++)
		read3byte(sbi, &raw_inode->i_data[3*block],
				(u8 *)&si->i_data[block]);
	brelse(bh);
	si->i_dir_start_lookup = 0;
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		sysv_set_inode(inode,
			       old_decode_dev(fs32_to_cpu(sbi, si->i_data[0])));
	else
		sysv_set_inode(inode, 0);
	unlock_new_inode(inode);
	return inode;

bad_inode:
	iget_failed(inode);
	return ERR_PTR(-EIO);
}

int sysv_write_inode(struct inode *inode, int wait)
{
	struct super_block * sb = inode->i_sb;
	struct sysv_sb_info * sbi = SYSV_SB(sb);
	struct buffer_head * bh;
	struct sysv_inode * raw_inode;
	struct sysv_inode_info * si;
	unsigned int ino, block;
	int err = 0;

	ino = inode->i_ino;
	if (!ino || ino > sbi->s_ninodes) {
		printk("Bad inode number on dev %s: %d is out of range\n",
		       inode->i_sb->s_id, ino);
		return -EIO;
	}
	raw_inode = sysv_raw_inode(sb, ino, &bh);
	if (!raw_inode) {
		printk("unable to read i-node block\n");
		return -EIO;
	}

	raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode);
	raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid));
	raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid));
	raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink);
	raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size);
	raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime.tv_sec);
	raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime.tv_sec);
	raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime.tv_sec);

	si = SYSV_I(inode);
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		si->i_data[0] = cpu_to_fs32(sbi, old_encode_dev(inode->i_rdev));
	for (block = 0; block < 10+1+1+1; block++)
		write3byte(sbi, (u8 *)&si->i_data[block],
			&raw_inode->i_data[3*block]);
	mark_buffer_dirty(bh);
	if (wait) {
                sync_dirty_buffer(bh);
                if (buffer_req(bh) && !buffer_uptodate(bh)) {
                        printk ("IO error syncing sysv inode [%s:%08x]\n",
                                sb->s_id, ino);
                        err = -EIO;
                }
        }
	brelse(bh);
	return 0;
}

int sysv_sync_inode(struct inode *inode)
{
	return sysv_write_inode(inode, 1);
}

static void sysv_delete_inode(struct inode *inode)
{
	truncate_inode_pages(&inode->i_data, 0);
	inode->i_size = 0;
	sysv_truncate(inode);
	sysv_free_inode(inode);
}

static struct kmem_cache *sysv_inode_cachep;

static struct inode *sysv_alloc_inode(struct super_block *sb)
{
	struct sysv_inode_info *si;

	si = kmem_cache_alloc(sysv_inode_cachep, GFP_KERNEL);
	if (!si)
		return NULL;
	return &si->vfs_inode;
}

static void sysv_destroy_inode(struct inode *inode)
{
	kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
}

static void init_once(void *p)
{
	struct sysv_inode_info *si = (struct sysv_inode_info *)p;

	inode_init_once(&si->vfs_inode);
}

const struct super_operations sysv_sops = {
	.alloc_inode	= sysv_alloc_inode,
	.destroy_inode	= sysv_destroy_inode,
	.write_inode	= sysv_write_inode,
	.delete_inode	= sysv_delete_inode,
	.put_super	= sysv_put_super,
	.write_super	= sysv_write_super,
	.sync_fs	= sysv_sync_fs,
	.remount_fs	= sysv_remount,
	.statfs		= sysv_statfs,
};

int __init sysv_init_icache(void)
{
	sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
			sizeof(struct sysv_inode_info), 0,
			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
			init_once);
	if (!sysv_inode_cachep)
		return -ENOMEM;
	return 0;
}

void sysv_destroy_icache(void)
{
	kmem_cache_destroy(sysv_inode_cachep);
}